diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7889b52afa141d9ec38c739b7bff350fc88997fa..baf875fd0fb798920a4e76c0456daf0179f70399 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -44,15 +44,27 @@ variables: - cargo --version - sccache -s only: - - tags - master - /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 - schedules - web - /^[0-9]+$/ # PRs + retry: + max: 2 + when: + - runner_system_failure + - unknown_failure + - api_failure tags: - linux-docker +.build-only: &build-only + only: + - master + - /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 + - web + + #### stage: test @@ -95,7 +107,7 @@ cargo-check-benches: stage: test <<: *docker-env script: - - BUILD_DUMMY_WASM_BINARY=1 time cargo check --benches --all + - BUILD_DUMMY_WASM_BINARY=1 time cargo +nightly check --benches --all - sccache -s @@ -121,7 +133,7 @@ test-linux-stable: &test-linux variables: - $DEPLOY_TAG script: - - time cargo test --all --release --verbose --locked | + - WASM_BUILD_NO_COLOR=1 time cargo test --all --release --verbose --locked | tee output.log - sccache -s after_script: @@ -145,19 +157,26 @@ test-srml-staking: &test-srml-staking except: variables: - $DEPLOY_TAG - only: - changes: - - .gitlab-ci.yml - - srml/staking/* script: - cd srml/staking/ - - time cargo test --release --verbose --no-default-features --features std + - WASM_BUILD_NO_COLOR=1 time cargo test --release --verbose --no-default-features --features std - sccache -s - - - - +test-wasmtime: &test-wasmtime + stage: test + <<: *docker-env + variables: + # Enable debug assertions since we are running optimized builds for testing + # but still want to have debug assertions. + RUSTFLAGS: -Cdebug-assertions=y + RUST_BACKTRACE: 1 + except: + variables: + - $DEPLOY_TAG + script: + - cd core/executor + - WASM_BUILD_NO_COLOR=1 time cargo test --release --verbose --features wasmtime + - sccache -s test-linux-stable-int: <<: *test-linux @@ -169,7 +188,7 @@ test-linux-stable-int: script: - echo "___Logs will be partly shown at the end in case of failure.___" - echo "___Full log will be saved to the job artifacts only in case of failure.___" - - RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace + - WASM_BUILD_NO_COLOR=1 RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace time cargo test -p node-cli --release --verbose --locked -- --ignored --test-threads=1 &> ${CI_COMMIT_SHORT_SHA}_int_failure.log - sccache -s @@ -198,28 +217,38 @@ check-web-wasm: - time cargo web build -p substrate-consensus-aura - time cargo web build -p substrate-consensus-babe - time cargo web build -p substrate-consensus-common - - time cargo web build -p substrate-keyring - - time cargo web build -p substrate-keystore - - time cargo web build -p substrate-executor - - time cargo web build -p substrate-network - - time cargo web build -p substrate-offchain - - time cargo web build -p substrate-panic-handler - - time cargo web build -p substrate-peerset - - time cargo web build -p substrate-primitives - # TODO: we can't use cargo web until https://github.com/paritytech/jsonrpc/pull/436 is deployed - - time cargo build -p substrate-rpc-servers --target wasm32-unknown-unknown - - time cargo web build -p substrate-serializer - - time cargo web build -p substrate-state-db - - time cargo web build -p substrate-state-machine - time cargo web build -p substrate-telemetry - - time cargo web build -p substrate-trie + # Note: the command below is a bit weird because several Cargo issues prevent us from compiling the node in a more straight-forward way. + - time cargo build --manifest-path=node/cli/Cargo.toml --no-default-features --features "browser" --target=wasm32-unknown-unknown + - sccache -s + +node-exits: + stage: test + <<: *docker-env + except: + - /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 + script: + - ./ci/check_for_exit.sh + + +test-full-crypto-feature: &test-full-crypto-feature + stage: test + <<: *docker-env + variables: + # Enable debug assertions since we are running optimized builds for testing + # but still want to have debug assertions. + RUSTFLAGS: -Cdebug-assertions=y + RUST_BACKTRACE: 1 + except: + variables: + - $DEPLOY_TAG + script: + - cd core/primitives/ + - time cargo +nightly build --verbose --no-default-features --features full_crypto + - cd ../application-crypto + - time cargo +nightly build --verbose --no-default-features --features full_crypto - sccache -s -.build-only: &build-only - only: - - master - - tags - - web #### stage: build @@ -232,7 +261,7 @@ build-linux-substrate: variables: - $DEPLOY_TAG script: - - time cargo build --release --verbose + - WASM_BUILD_NO_COLOR=1 time cargo build --release --verbose - mkdir -p ./artifacts/substrate/ - mv ./target/release/substrate ./artifacts/substrate/. - echo -n "Substrate version = " @@ -285,7 +314,7 @@ build-rust-doc-release: <<: *build-only script: - rm -f ./crate-docs/index.html # use it as an indicator if the job succeeds - - BUILD_DUMMY_WASM_BINARY=1 time cargo +nightly doc --release --all --verbose + - BUILD_DUMMY_WASM_BINARY=1 RUSTDOCFLAGS="--html-in-header $(pwd)/rustdoc-header.html" time cargo +nightly doc --release --all --verbose - cp -R ./target/doc ./crate-docs - echo "" > ./crate-docs/index.html - sccache -s @@ -309,6 +338,22 @@ check_warnings: fi allow_failure: true +check_polkadot: + stage: build + <<: *docker-env + allow_failure: true + dependencies: + - test-linux-stable + script: + - git clone --depth 1 https://github.com/paritytech/polkadot.git + - COMMIT_HASH=$(git rev-parse HEAD) + - cd polkadot + - git grep -l "polkadot-master" | grep toml | xargs sed -i "s/branch.*=.*\"polkadot-master\"/rev = \"$COMMIT_HASH\"/" + - cargo update -p sr-io --precise $COMMIT_HASH + - time cargo check + - cd .. + - sccache -s + #### stage: publish .publish-docker-release: &publish-docker-release @@ -336,7 +381,7 @@ check_warnings: - docker push $CONTAINER_IMAGE:$VERSION - docker push $CONTAINER_IMAGE:latest -publish-docker-substrate: +publish-docker-substrate: stage: publish <<: *publish-docker-release # collect VERSION artifact here to pass it on to kubernetes @@ -526,6 +571,8 @@ deploy-ue1-tag: name: parity-prod-ue1 .validator-deploy: &validator-deploy + # script will fail if there is no artifacts/substrate/VERSION + <<: *build-only stage: flaming-fir dependencies: - build-linux-substrate diff --git a/CODEOWNERS b/CODEOWNERS index 2106b2a59e1b3eaea8c407c2267a964b0ccc4c06..866f16522316bcfa0d89aaf1ea1762982a36bc9c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,11 @@ -# Lists some code owners +# Lists some code owners. +# +# A codeowner just oversees some part of the codebase. If an owned file is changed then the +# corresponding codeowner receives a review request. An approval of the codeowner is +# not required for merging a PR though. +# +# **This is pretty much an experiment at the moment**. Feel free to remove yourself at any time if +# you do not want to receive review requests any longer. # # For details about syntax, see: # https://help.github.com/en/articles/about-code-owners @@ -8,8 +15,54 @@ # can be everywhere. # - Multiple owners are supported. # - Either handle (e.g, @pepyakin) or email can be used. Keep in mind, that handles might work better because they -# are more recognizable on GitHub, you can use them for mentioning unlike an email. +# are more recognizable on GitHub, you can use them for mentioning unlike an email. # - The latest matching rule, if multiple, takes precedence. -/srml/contracts/ @pepyakin +# Wasm execution and the wasm side of Substrate Runtime Interface /core/executor/ @pepyakin +/core/sr-io/without_std.rs @pepyakin +/core/sr-std/without_std.rs @pepyakin + +# Sandboxing capability of Substrate Runtime +/core/sr-sandbox/ @pepyakin +/core/primitives/src/sandbox.rs @pepyakin + +# Transaction pool +/core/transaction-pool/ @tomusdrw + +# Offchain +/core/offchain/ @tomusdrw +/sr-io/src/offchain/ @tomusdrw + +# Everything that has RPC in it +/core/rpc/ @tomusdrw +/node/rpc/ @tomusdrw +/node/rpc-client/ @tomusdrw +/core/rpc-servers/ @tomusdrw + +# GRANDPA, BABE, consensus stuff +/srml/babe/ @andresilva @DemiMarie-parity +/srml/grandpa/ @andresilva @DemiMarie-parity +/core/finality-grandpa/ @andresilva @DemiMarie-parity +/core/consensus/babe/ @andresilva @DemiMarie-parity +/core/consensus/slots/ @andresilva @DemiMarie-parity + +# Contracts +/srml/contracts/ @pepyakin @thiolliere @jimpo +/srml/contracts/src/wasm/runtime.rs @Robbepop + +# Inflation points +/srml/staking/src/inflation.rs @thiolliere + +# NPoS and Governance +/srml/staking/ @kianenigma +/srml/election/ @kianenigma + +# End to end testing of substrate node +/node/executor/ @kianenigma + +# Transaction weight stuff +/core/sr-primitives/weights.rs @kianenigma + +# Support crates +/srml/support/ @thiolliere @kianenigma diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc index b797e72e82b542fa06724a0d0eceaa7a92b6e779..817e1d7489f3968c2a851e78b1728949776b544d 100644 --- a/CONTRIBUTING.adoc +++ b/CONTRIBUTING.adoc @@ -26,6 +26,7 @@ Merging pull requests once CI is successful: - it is an urgent fix with no large change to logic, then it may be merged after a non-author contributor has approved the review once CI is complete. . Once a PR is ready for review please add the https://github.com/paritytech/substrate/pulls?q=is%3Apr+is%3Aopen+label%3AA0-pleasereview[`pleasereview`] label. Generally PRs should sit with this label for 48 hours in order to garner feedback. It may be merged before if all relevant parties had a look at it. +. If the first review is not an approval, swap `A0-pleasereview` to any label `[A3, A7]` to indicate that the PR has received some feedback, but needs further work. For example. https://github.com/paritytech/substrate/labels/A3-inprogress[`A3-inprogress`] is a general indicator that the PR is work in progress and https://github.com/paritytech/substrate/labels/A4-gotissues[`A4-gotissues`] means that it has significant problems that need fixing. Once the work is done, change the label back to `A0-pleasereview`. You might end up swapping a few times back and forth to climb up the A label group. Once a PR is https://github.com/paritytech/substrate/labels/A8-looksgood[`A8-looksgood`], it is ready to merge. . PRs that break the external API must be tagged with https://github.com/paritytech/substrate/labels/B2-breaksapi[`breaksapi`], when it changes the SRML or consensus of running system with https://github.com/paritytech/substrate/labels/B3-breaksconsensus[`breaksconsensus`] . No PR should be merged until all reviews' comments are addressed. @@ -45,6 +46,21 @@ When reviewing a pull request, the end-goal is to suggest useful changes to the . There exists a somewhat cleaner/better/faster way of accomplishing the same feature/fix. . It does not fit well with some other contributors' longer-term vision for the project. +=== Updating Polkadot as well + +If your PR changes the external APIs or interfaces used by Polkadot, **a corresponding PR on Polkadot must** be submitted as well. If you tagged the PR with `breaksapi` or `breaksconsensus` this is most certainly the case, in all other cases check for it by running step 1. + +To update a corresponding Polkadot PR: + +0. Pull lastet Polkadot master (or clone it, if you haven't yet). +1. Replace `polkadot-master` in all `Cargo.toml` with the name of the PR-branch - e.g. by running `find . -name "Cargo.toml" -exec sed -i "s/polkadot-master/PR_BRANCH/g" {}` (and to your repo, if the branch is not on mainline); Commit this change. +2. Make the changes required to pass the build again. +3. Submit all this as a PR against the Polkadot Repo, link that new PR in the existing substrate PR for reference +4. Wait for reviews on both +5. Once both PRs have been green lit, merge the Substrate PR into master and sync the changes onto the `polkadot-master` on mainline (push it). Now revert that first commit in your Polkadot PR, reverting the name back to `polkadot-master`, push and wait for the CI to confirm all is fine. Then merge the Polkadot PR. + +As there might be multiple pending PRs that might conflict with one another, a) you should not merge the substrate PR until the Polkadot PR has also been reviewed and b) both should be merged pretty quickly after another to not block others. + == Helping out We use https://github.com/paritytech/substrate/labels[labels] to manage PRs and issues and communicate state of a PR. Please familiarize yourself with them. Furthermore we are organizing issues in https://github.com/paritytech/substrate/milestones[milestones]. Best way to get started is to a pick a ticket from the current milestone tagged https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ2-easy[`easy`] or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ3-medium[`medium`] and get going or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AX1-mentor[`mentor`] and get in contact with the mentor offering their support on that larger task. diff --git a/Cargo.lock b/Cargo.lock index a22ab0491af7100d76e4f021a91badffb926df7d..0af6e36e351e663a61d67be0699ce9d410168319 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "adler32" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -13,7 +13,7 @@ dependencies = [ "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -23,7 +23,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -32,37 +32,40 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ahash" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "aio-limited" -version = "0.1.0" +name = "ansi_term" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ansi_term" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -88,27 +91,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arrayvec" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "asn1_der" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "asn1_der_derive" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -121,24 +129,24 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.33" +version = "0.3.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -146,8 +154,8 @@ name = "backtrace-sys" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -161,7 +169,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -173,12 +181,13 @@ dependencies = [ ] [[package]] -name = "bigint" -version = "4.4.1" +name = "bincode" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -186,25 +195,25 @@ name = "bindgen" version = "0.47.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -212,11 +221,6 @@ name = "bitmask" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bitvec" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitvec" version = "0.14.0" @@ -224,13 +228,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blake2" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -238,17 +242,18 @@ name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "block-buffer" -version = "0.2.0" +name = "blake2b_simd" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -280,18 +285,18 @@ dependencies = [ [[package]] name = "bs58" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bstr" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -304,7 +309,7 @@ dependencies = [ [[package]] name = "bumpalo" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -312,11 +317,6 @@ name = "byte-slice-cast" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "byte-tools" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byte-tools" version = "0.3.1" @@ -338,8 +338,8 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -347,7 +347,7 @@ name = "c2-chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -358,14 +358,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo_metadata" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -375,10 +374,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.38" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -391,25 +391,27 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chain-spec-builder" version = "2.0.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "node-cli 2.0.0", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-keystore 2.0.0", "substrate-primitives 2.0.0", - "substrate-service 2.0.0", ] [[package]] name = "chrono" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -421,21 +423,21 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.32.0" +version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -445,7 +447,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -453,20 +455,56 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.40" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "console_log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "const-random" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "const-random-macro" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "constant_time_eq" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -475,7 +513,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -483,12 +521,95 @@ name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cranelift-bforest" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-bforest 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-shared 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen-shared 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-entity" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-frontend" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-native" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-wasm" +version = "0.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -498,21 +619,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -528,19 +673,19 @@ dependencies = [ ] [[package]] -name = "crossbeam-channel" -version = "0.3.9" +name = "criterion-plot" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-deque" -version = "0.6.3" +name = "crossbeam-channel" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -558,10 +703,10 @@ name = "crossbeam-epoch" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -579,29 +724,15 @@ name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crunchy" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "crypto-mac" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crypto-mac" version = "0.7.0" @@ -616,11 +747,11 @@ name = "csv" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -633,11 +764,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -646,7 +777,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -655,7 +786,7 @@ version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -669,14 +800,14 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "1.2.1" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -684,28 +815,17 @@ name = "data-encoding" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "derive_more" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "derive_more" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -715,18 +835,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "digest" -version = "0.6.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "digest" -version = "0.8.1" +name = "directories" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -745,19 +877,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ed25519-dalek" -version = "1.0.0-pre.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "either" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -774,15 +918,27 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "environmental" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -790,97 +946,190 @@ name = "erased-serde" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "error-chain" -version = "0.12.1" +name = "errno" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "exit-future" -version = "0.1.4" +name = "errno-dragonfly" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "failure" -version = "0.1.5" +name = "error-chain" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "failure_derive" -version = "0.1.5" +name = "evm" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-gasometer 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "fake-simd" -version = "0.1.2" +name = "evm-core" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "fdlimit" -version = "0.1.1" +name = "evm-gasometer" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "finality-grandpa" -version = "0.9.0" +name = "evm-runtime" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "fixed-hash" -version = "0.4.0" +name = "exit-future" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "flate2" -version = "1.0.9" +name = "faerie" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fdlimit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "file-per-thread-logger" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "finality-grandpa" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hashmap_core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fixed-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fixedbitset" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "flate2" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -905,7 +1154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "fork-tree" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -913,10 +1162,10 @@ name = "fs-swap" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -924,8 +1173,8 @@ name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -938,7 +1187,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -949,21 +1198,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-channel-preview" -version = "0.3.0-alpha.17" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-core-preview" -version = "0.3.0-alpha.17" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -971,66 +1220,63 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-executor-preview" -version = "0.3.0-alpha.17" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-io-preview" -version = "0.3.0-alpha.17" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-preview" -version = "0.3.0-alpha.17" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-sink-preview" -version = "0.3.0-alpha.17" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "futures-timer" -version = "0.2.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "futures-util-preview" -version = "0.3.0-alpha.17" +version = "0.3.0-alpha.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1041,21 +1287,12 @@ name = "gcc" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "generic-array" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1065,7 +1302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1075,16 +1312,30 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.6" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gimli" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1102,11 +1353,21 @@ name = "globset" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "goblin" +version = "0.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1117,10 +1378,10 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1128,12 +1389,12 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hash256-std-hasher" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1148,9 +1409,18 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hashmap_core" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1158,7 +1428,7 @@ name = "heapsize" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1175,30 +1445,25 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "hex-literal" -version = "0.2.0" +name = "hex" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hex-literal-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "hex-literal-impl" -version = "0.2.0" +name = "hex-literal" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "hmac" -version = "0.4.2" +name = "hex-literal-impl" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1212,17 +1477,17 @@ dependencies = [ [[package]] name = "hmac-drbg" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "http" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1236,8 +1501,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1248,7 +1513,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "humantime" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1274,19 +1539,19 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.33" +version = "0.12.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1294,13 +1559,25 @@ dependencies = [ "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper-tls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.1.5" @@ -1311,34 +1588,53 @@ dependencies = [ "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "impl-codec" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "impl-serde" -version = "0.1.1" +name = "impl-rlp" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "impl-serde" -version = "0.2.0" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "indexmap" -version = "1.0.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1353,16 +1649,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ipnet" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1370,7 +1665,7 @@ name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1378,114 +1673,124 @@ name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "jobserver" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "js-sys" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-client-transports" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.22.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-core" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-core-client" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-client-transports 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-client-transports 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-derive" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-http-server" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-server-utils 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-pubsub" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-server-utils" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ws-server" -version = "12.1.0" +version = "14.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "jsonrpc-core 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-server-utils 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-server-utils 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1495,11 +1800,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "keccak-hasher" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1539,10 +1844,10 @@ dependencies = [ "fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1553,11 +1858,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "lazycell" @@ -1566,7 +1868,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1574,127 +1876,126 @@ name = "libloading" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core-derive 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-deflate 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-dns 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-floodsub 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-kad 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mdns 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mplex 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-noise 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-plaintext 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ratelimit 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-secio 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-tcp 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-uds 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-wasm-ext 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-websocket 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-yamux 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-deflate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-dns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-floodsub 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-kad 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mdns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mplex 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-noise 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-plaintext 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-secio 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-tcp 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-uds 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-wasm-ext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-websocket 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-yamux 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-core" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "asn1_der 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "multistream-select 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-core-derive" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-deflate" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-dns" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-floodsub" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1702,258 +2003,249 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-kad" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-mdns" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-mplex" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-noise" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "snow 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-ping" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-plaintext" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-ratelimit" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-secio" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-swarm" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-tcp" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnet 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnet 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-uds" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-wasm-ext" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-websocket" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "soketto 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.10.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libp2p-yamux" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "yamux 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1964,22 +2256,23 @@ version = "5.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libsecp256k1" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1987,9 +2280,9 @@ name = "libz-sys" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2036,15 +2329,15 @@ name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2055,13 +2348,21 @@ dependencies = [ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mach" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "malloc_size_of_derive" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2075,7 +2376,7 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2088,11 +2389,11 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2103,13 +2404,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "merlin" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2121,44 +2422,24 @@ dependencies = [ ] [[package]] -name = "miniz-sys" -version = "0.1.12" +name = "miniz_oxide" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "miniz_oxide" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz_oxide_c_api" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio" -version = "0.6.19" +name = "mio" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2171,7 +2452,7 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2181,8 +2462,8 @@ name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2198,17 +2479,21 @@ dependencies = [ ] [[package]] -name = "multistream-select" +name = "multimap" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "multistream-select" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2224,13 +2509,13 @@ name = "native-tls" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2241,9 +2526,9 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2251,10 +2536,10 @@ name = "nix" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2262,16 +2547,27 @@ dependencies = [ name = "node-cli" version = "2.0.0" dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", + "libp2p 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "node-executor 2.0.0", "node-primitives 2.0.0", + "node-rpc 2.0.0", "node-runtime 2.0.0", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "srml-balances 2.0.0", @@ -2282,10 +2578,14 @@ dependencies = [ "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", - "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "srml-transaction-payment 2.0.0", + "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-basic-authorship 2.0.0", + "substrate-build-script-utils 2.0.0", + "substrate-chain-spec 2.0.0", "substrate-cli 2.0.0", "substrate-client 2.0.0", + "substrate-client-db 2.0.0", "substrate-consensus-babe 2.0.0", "substrate-consensus-babe-primitives 2.0.0", "substrate-consensus-common 2.0.0", @@ -2295,7 +2595,9 @@ dependencies = [ "substrate-keyring 2.0.0", "substrate-keystore 2.0.0", "substrate-network 2.0.0", + "substrate-offchain 2.0.0", "substrate-primitives 2.0.0", + "substrate-rpc 2.0.0", "substrate-service 2.0.0", "substrate-service-test 2.0.0", "substrate-telemetry 2.0.0", @@ -2303,15 +2605,20 @@ dependencies = [ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "transaction-factory 0.0.1", + "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-executor" version = "2.0.0" dependencies = [ + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", "node-runtime 2.0.0", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "node-testing 2.0.0", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "srml-balances 2.0.0", @@ -2319,43 +2626,54 @@ dependencies = [ "srml-grandpa 2.0.0", "srml-indices 2.0.0", "srml-session 2.0.0", - "srml-staking 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", + "srml-transaction-payment 2.0.0", "srml-treasury 2.0.0", "substrate-executor 2.0.0", - "substrate-keyring 2.0.0", "substrate-primitives 2.0.0", "substrate-state-machine 2.0.0", "substrate-test-client 2.0.0", "substrate-trie 2.0.0", - "trie-root 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-primitives" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", - "sr-std 2.0.0", "substrate-primitives 2.0.0", "substrate-serializer 2.0.0", ] +[[package]] +name = "node-rpc" +version = "2.0.0" +dependencies = [ + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "node-primitives 2.0.0", + "node-runtime 2.0.0", + "sr-primitives 2.0.0", + "srml-contracts-rpc 2.0.0", + "srml-system-rpc 2.0.0", + "srml-transaction-payment-rpc 2.0.0", + "substrate-client 2.0.0", + "substrate-transaction-pool 2.0.0", +] + [[package]] name = "node-rpc-client" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core-client 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", "substrate-rpc 2.0.0", ] @@ -2366,11 +2684,13 @@ version = "2.0.0" dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", "sr-std 2.0.0", "sr-version 2.0.0", "srml-authorship 0.1.0", @@ -2378,29 +2698,37 @@ dependencies = [ "srml-balances 2.0.0", "srml-collective 2.0.0", "srml-contracts 2.0.0", + "srml-contracts-rpc-runtime-api 2.0.0", "srml-democracy 2.0.0", - "srml-elections 2.0.0", + "srml-elections-phragmen 2.0.0", "srml-executive 2.0.0", "srml-finality-tracker 2.0.0", "srml-grandpa 2.0.0", "srml-im-online 0.1.0", "srml-indices 2.0.0", "srml-membership 2.0.0", + "srml-nicks 2.0.0", + "srml-offences 1.0.0", + "srml-randomness-collective-flip 2.0.0", "srml-session 2.0.0", "srml-staking 2.0.0", + "srml-staking-reward-curve 2.0.0", "srml-sudo 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", + "srml-system-rpc-runtime-api 2.0.0", "srml-timestamp 2.0.0", + "srml-transaction-payment 2.0.0", + "srml-transaction-payment-rpc-runtime-api 2.0.0", "srml-treasury 2.0.0", + "srml-utility 2.0.0", "substrate-client 2.0.0", "substrate-consensus-babe-primitives 2.0.0", - "substrate-consensus-common-primitives 2.0.0", "substrate-keyring 2.0.0", "substrate-offchain-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-session 2.0.0", - "substrate-wasm-builder-runner 1.0.2", + "substrate-wasm-builder-runner 1.0.4", ] [[package]] @@ -2408,20 +2736,23 @@ name = "node-template" version = "2.0.0" dependencies = [ "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "node-template-runtime 2.0.0", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", + "sr-primitives 2.0.0", "substrate-basic-authorship 2.0.0", + "substrate-build-script-utils 2.0.0", "substrate-cli 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura 2.0.0", "substrate-consensus-aura-primitives 2.0.0", "substrate-executor 2.0.0", + "substrate-finality-grandpa 2.0.0", "substrate-finality-grandpa-primitives 2.0.0", "substrate-inherents 2.0.0", "substrate-network 2.0.0", @@ -2429,7 +2760,7 @@ dependencies = [ "substrate-service 2.0.0", "substrate-transaction-pool 2.0.0", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2437,9 +2768,9 @@ dependencies = [ name = "node-template-runtime" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -2447,27 +2778,59 @@ dependencies = [ "srml-aura 2.0.0", "srml-balances 2.0.0", "srml-executive 2.0.0", + "srml-grandpa 2.0.0", "srml-indices 2.0.0", + "srml-randomness-collective-flip 2.0.0", "srml-sudo 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", + "srml-transaction-payment 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", "substrate-offchain-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-session 2.0.0", - "substrate-wasm-builder-runner 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-wasm-builder-runner 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "node-testing" +version = "2.0.0" +dependencies = [ + "node-executor 2.0.0", + "node-primitives 2.0.0", + "node-runtime 2.0.0", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "srml-balances 2.0.0", + "srml-contracts 2.0.0", + "srml-grandpa 2.0.0", + "srml-indices 2.0.0", + "srml-session 2.0.0", + "srml-staking 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "srml-timestamp 2.0.0", + "srml-transaction-payment 2.0.0", + "srml-treasury 2.0.0", + "substrate-client 2.0.0", + "substrate-executor 2.0.0", + "substrate-keyring 2.0.0", + "substrate-primitives 2.0.0", + "substrate-test-client 2.0.0", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nodrop" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "nohash-hasher" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2481,9 +2844,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2493,7 +2857,7 @@ name = "num-integer" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2502,8 +2866,8 @@ name = "num-rational" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2513,7 +2877,7 @@ name = "num-traits" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2521,7 +2885,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2541,22 +2905,27 @@ dependencies = [ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "once_cell" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "opaque-debug" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.24" +version = "0.10.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2566,13 +2935,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.48" +version = "0.9.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2581,15 +2950,7 @@ name = "output_vt100" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "owning_ref" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2605,69 +2966,58 @@ name = "parity-bytes" version = "0.1.0" source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" -[[package]] -name = "parity-codec" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitvec 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parity-multiaddr" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-multihash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-scale-codec" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec-derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "vecarray 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-scale-codec-derive" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2680,27 +3030,23 @@ name = "parity-util-mem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-wasm" -version = "0.31.3" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "parking_lot" -version = "0.5.5" +name = "parity-wasm" +version = "0.40.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "parking_lot" @@ -2740,27 +3086,16 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot_core" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2768,11 +3103,11 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2780,14 +3115,14 @@ name = "parking_lot_core" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2795,33 +3130,33 @@ name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "paste" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "paste-impl" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2833,6 +3168,11 @@ dependencies = [ "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pdqselect" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "peeking_take_while" version = "0.1.2" @@ -2843,6 +3183,19 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "petgraph" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pin-utils" version = "0.1.0-alpha.4" @@ -2850,7 +3203,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pkg-config" -version = "0.3.15" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2864,20 +3222,21 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "primitive-types" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2885,17 +3244,27 @@ name = "proc-macro-crate" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-error" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-hack" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2906,19 +3275,75 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "prost" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "prost-build" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "prost-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "prost-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "protobuf" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pwasm-utils" -version = "0.6.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2933,13 +3358,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quickcheck" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2950,12 +3375,20 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2965,10 +3398,10 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2978,9 +3411,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2988,28 +3421,28 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3018,7 +3451,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3028,7 +3461,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3036,20 +3469,20 @@ name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand_core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3065,7 +3498,7 @@ name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3081,9 +3514,9 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3093,10 +3526,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3104,8 +3547,8 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3125,25 +3568,43 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_xoshiro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rayon" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3160,6 +3621,17 @@ name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "redox_users" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ref_thread_local" version = "0.0.0" @@ -3167,14 +3639,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3187,10 +3658,18 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.10" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "region" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3198,7 +3677,7 @@ name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3207,46 +3686,64 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ring" -version = "0.14.6" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rocksdb" -version = "0.11.0" +name = "rlp" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "librocksdb-sys 5.18.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rocksdb" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "librocksdb-sys 5.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rpassword" -version = "3.0.2" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rust-argon2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3264,15 +3761,24 @@ dependencies = [ [[package]] name = "rustls" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustversion" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3281,13 +3787,13 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ryu" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3300,7 +3806,7 @@ dependencies = [ [[package]] name = "safemem" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3313,26 +3819,27 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "schnorrkel" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curve25519-dalek 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3345,13 +3852,32 @@ name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scroll" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scroll_derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sct" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3361,7 +3887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3387,7 +3913,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3402,30 +3928,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.97" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.97" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3436,7 +3962,7 @@ dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3444,18 +3970,6 @@ name = "sha1" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "sha2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "sha2" version = "0.8.0" @@ -3464,7 +3978,7 @@ dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3476,7 +3990,7 @@ dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3517,10 +4031,10 @@ name = "slog-json" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3530,7 +4044,7 @@ version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3541,7 +4055,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3551,33 +4065,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "snow" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "soketto" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3592,7 +4101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "spin" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3600,11 +4109,12 @@ name = "sr-api-macros" version = "2.0.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-version 2.0.0", "substrate-client 2.0.0", @@ -3612,21 +4122,36 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-state-machine 2.0.0", "substrate-test-runtime-client 2.0.0", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", - "trybuild 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sr-arithmetic" +version = "2.0.0" +dependencies = [ + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-debug-derive 2.0.0", ] [[package]] name = "sr-io" version = "2.0.0" dependencies = [ - "environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", - "substrate-offchain 2.0.0", + "substrate-externalities 2.0.0", "substrate-primitives 2.0.0", "substrate-state-machine 2.0.0", "substrate-trie 2.0.0", @@ -3637,18 +4162,18 @@ dependencies = [ name = "sr-primitives" version = "2.0.0" dependencies = [ - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-arithmetic 2.0.0", "sr-io 2.0.0", "sr-std 2.0.0", "substrate-application-crypto 2.0.0", + "substrate-offchain 2.0.0", "substrate-primitives 2.0.0", ] @@ -3657,12 +4182,21 @@ name = "sr-sandbox" version = "2.0.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", "substrate-primitives 2.0.0", - "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sr-staking-primitives" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "sr-std 2.0.0", ] [[package]] @@ -3676,9 +4210,9 @@ dependencies = [ name = "sr-version" version = "2.0.0" dependencies = [ - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", ] @@ -3687,8 +4221,8 @@ dependencies = [ name = "srml-assets" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3701,15 +4235,14 @@ dependencies = [ name = "srml-aura" version = "2.0.0" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", "srml-session 2.0.0", - "srml-staking 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", @@ -3719,11 +4252,30 @@ dependencies = [ "substrate-primitives 2.0.0", ] +[[package]] +name = "srml-authority-discovery" +version = "0.1.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", + "sr-std 2.0.0", + "srml-session 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "substrate-application-crypto 2.0.0", + "substrate-consensus-babe-primitives 2.0.0", + "substrate-primitives 2.0.0", +] + [[package]] name = "srml-authorship" version = "0.1.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3737,36 +4289,39 @@ dependencies = [ name = "srml-babe" version = "2.0.0" dependencies = [ - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", "sr-std 2.0.0", + "sr-version 2.0.0", "srml-session 2.0.0", - "srml-staking 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", "substrate-consensus-babe-primitives 2.0.0", "substrate-inherents 2.0.0", "substrate-primitives 2.0.0", + "substrate-test-runtime 2.0.0", ] [[package]] name = "srml-balances" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", + "srml-transaction-payment 2.0.0", "substrate-keyring 2.0.0", "substrate-primitives 2.0.0", ] @@ -3775,10 +4330,10 @@ dependencies = [ name = "srml-collective" version = "2.0.0" dependencies = [ - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3794,31 +4349,59 @@ version = "2.0.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-sandbox 2.0.0", "sr-std 2.0.0", "srml-balances 2.0.0", + "srml-randomness-collective-flip 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", "substrate-primitives 2.0.0", - "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "srml-contracts-rpc" +version = "2.0.0" +dependencies = [ + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "srml-contracts-rpc-runtime-api 2.0.0", + "substrate-client 2.0.0", + "substrate-primitives 2.0.0", + "substrate-rpc-primitives 2.0.0", +] + +[[package]] +name = "srml-contracts-rpc-runtime-api" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "substrate-client 2.0.0", ] [[package]] name = "srml-democracy" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3832,16 +4415,53 @@ dependencies = [ name = "srml-elections" version = "2.0.0" dependencies = [ - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "srml-balances 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-elections-phragmen" +version = "2.0.0" +dependencies = [ + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "srml-balances 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "substrate-phragmen 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-evm" +version = "2.0.0" +dependencies = [ + "evm 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", "srml-balances 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", + "srml-timestamp 2.0.0", "substrate-primitives 2.0.0", ] @@ -3849,10 +4469,11 @@ dependencies = [ name = "srml-example" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", + "sr-std 2.0.0", "srml-balances 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", @@ -3863,9 +4484,9 @@ dependencies = [ name = "srml-executive" version = "2.0.0" dependencies = [ - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3873,6 +4494,7 @@ dependencies = [ "srml-indices 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", + "srml-transaction-payment 2.0.0", "substrate-primitives 2.0.0", ] @@ -3880,8 +4502,9 @@ dependencies = [ name = "srml-finality-tracker" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3895,8 +4518,8 @@ dependencies = [ name = "srml-generic-asset" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3909,10 +4532,11 @@ dependencies = [ name = "srml-grandpa" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", "sr-std 2.0.0", "srml-finality-tracker 2.0.0", "srml-session 2.0.0", @@ -3926,15 +4550,18 @@ dependencies = [ name = "srml-im-online" version = "0.1.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", "sr-std 2.0.0", + "srml-authorship 0.1.0", "srml-session 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "substrate-application-crypto 2.0.0", + "substrate-offchain 2.0.0", "substrate-primitives 2.0.0", ] @@ -3942,10 +4569,10 @@ dependencies = [ name = "srml-indices" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3959,8 +4586,8 @@ dependencies = [ name = "srml-membership" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -3973,9 +4600,69 @@ dependencies = [ name = "srml-metadata" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-nicks" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "srml-balances 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-offences" +version = "1.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", + "sr-std 2.0.0", + "srml-balances 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-randomness-collective-flip" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-scored-pool" +version = "1.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", "sr-std 2.0.0", + "srml-balances 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", "substrate-primitives 2.0.0", ] @@ -3983,12 +4670,14 @@ dependencies = [ name = "srml-session" version = "2.0.0" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", "sr-std 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", @@ -4002,34 +4691,46 @@ dependencies = [ name = "srml-staking" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", + "sr-staking-primitives 2.0.0", "sr-std 2.0.0", "srml-authorship 0.1.0", "srml-balances 2.0.0", "srml-session 2.0.0", + "srml-staking-reward-curve 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", "substrate-keyring 2.0.0", + "substrate-phragmen 2.0.0", "substrate-primitives 2.0.0", ] +[[package]] +name = "srml-staking-reward-curve" +version = "2.0.0" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "srml-sudo" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", "srml-support 2.0.0", - "srml-support-procedural 2.0.0", "srml-system 2.0.0", "substrate-primitives 2.0.0", ] @@ -4039,11 +4740,13 @@ name = "srml-support" version = "2.0.0" dependencies = [ "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4058,11 +4761,11 @@ dependencies = [ name = "srml-support-procedural" version = "2.0.0" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 2.0.0", "srml-support-procedural-tools 2.0.0", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4070,33 +4773,34 @@ name = "srml-support-procedural-tools" version = "2.0.0" dependencies = [ "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 2.0.0", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-procedural-tools-derive" version = "2.0.0" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "srml-support-test" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", + "sr-primitives 2.0.0", "srml-support 2.0.0", "substrate-inherents 2.0.0", "substrate-primitives 2.0.0", - "trybuild 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4104,22 +4808,53 @@ name = "srml-system" version = "2.0.0" dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", + "sr-version 2.0.0", "srml-support 2.0.0", "substrate-primitives 2.0.0", ] +[[package]] +name = "srml-system-rpc" +version = "2.0.0" +dependencies = [ + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "srml-system-rpc-runtime-api 2.0.0", + "substrate-client 2.0.0", + "substrate-primitives 2.0.0", + "substrate-test-runtime-client 2.0.0", + "substrate-transaction-pool 2.0.0", +] + +[[package]] +name = "srml-system-rpc-runtime-api" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-client 2.0.0", +] + [[package]] name = "srml-timestamp" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4129,12 +4864,69 @@ dependencies = [ "substrate-primitives 2.0.0", ] +[[package]] +name = "srml-transaction-payment" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "srml-balances 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "srml-transaction-payment-rpc-runtime-api 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-transaction-payment-rpc" +version = "2.0.0" +dependencies = [ + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "srml-transaction-payment-rpc-runtime-api 2.0.0", + "substrate-client 2.0.0", + "substrate-primitives 2.0.0", + "substrate-rpc-primitives 2.0.0", +] + +[[package]] +name = "srml-transaction-payment-rpc-runtime-api" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "substrate-client 2.0.0", +] + [[package]] name = "srml-treasury" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "srml-balances 2.0.0", + "srml-support 2.0.0", + "srml-system 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "srml-utility" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4154,14 +4946,9 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "static_slice" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "stream-cipher" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4175,29 +4962,38 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "string-interner" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "strsim" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.18" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.18" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4213,59 +5009,84 @@ dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "subkey" version = "2.0.0" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", "node-runtime 2.0.0", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "srml-balances 2.0.0", "srml-system 2.0.0", + "srml-transaction-payment 2.0.0", "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 2.0.0", "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "substrate" +name = "substrate-application-crypto" version = "2.0.0" dependencies = [ - "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "node-cli 2.0.0", - "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "substrate-primitives 2.0.0", + "substrate-test-runtime-client 2.0.0", ] [[package]] -name = "substrate-application-crypto" +name = "substrate-authority-discovery" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prost-build 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", - "sr-std 2.0.0", + "substrate-authority-discovery-primitives 2.0.0", + "substrate-client 2.0.0", + "substrate-network 2.0.0", + "substrate-peerset 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", ] +[[package]] +name = "substrate-authority-discovery-primitives" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "substrate-client 2.0.0", +] + [[package]] name = "substrate-basic-authorship" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-consensus-common 2.0.0", @@ -4283,33 +5104,62 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-build-script-utils" +version = "2.0.0" + +[[package]] +name = "substrate-chain-spec" +version = "2.0.0" +dependencies = [ + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "substrate-chain-spec-derive 2.0.0", + "substrate-network 2.0.0", + "substrate-primitives 2.0.0", + "substrate-telemetry 2.0.0", +] + +[[package]] +name = "substrate-chain-spec-derive" +version = "2.0.0" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-cli" version = "2.0.0" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rpassword 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", - "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-client 2.0.0", + "substrate-header-metadata 2.0.0", "substrate-keyring 2.0.0", "substrate-network 2.0.0", "substrate-panic-handler 2.0.0", @@ -4326,48 +5176,54 @@ dependencies = [ name = "substrate-client" version = "2.0.0" dependencies = [ - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", "sr-version 2.0.0", + "substrate-client-db 2.0.0", "substrate-consensus-common 2.0.0", "substrate-executor 2.0.0", + "substrate-header-metadata 2.0.0", "substrate-inherents 2.0.0", "substrate-keyring 2.0.0", + "substrate-panic-handler 2.0.0", "substrate-primitives 2.0.0", "substrate-state-machine 2.0.0", "substrate-telemetry 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-trie 2.0.0", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-client-db" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-executor 2.0.0", + "substrate-header-metadata 2.0.0", "substrate-keyring 2.0.0", "substrate-primitives 2.0.0", "substrate-state-db 2.0.0", @@ -4380,12 +5236,13 @@ dependencies = [ name = "substrate-consensus-aura" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", @@ -4414,7 +5271,7 @@ dependencies = [ name = "substrate-consensus-aura-primitives" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-application-crypto 2.0.0", @@ -4425,20 +5282,22 @@ dependencies = [ name = "substrate-consensus-babe" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fork-tree 2.0.0", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-version 2.0.0", @@ -4451,6 +5310,7 @@ dependencies = [ "substrate-consensus-slots 2.0.0", "substrate-consensus-uncles 2.0.0", "substrate-executor 2.0.0", + "substrate-header-metadata 2.0.0", "substrate-inherents 2.0.0", "substrate-keyring 2.0.0", "substrate-keystore 2.0.0", @@ -4467,8 +5327,8 @@ dependencies = [ name = "substrate-consensus-babe-primitives" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-application-crypto 2.0.0", @@ -4480,12 +5340,12 @@ dependencies = [ name = "substrate-consensus-common" version = "2.0.0" dependencies = [ - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4496,24 +5356,42 @@ dependencies = [ ] [[package]] -name = "substrate-consensus-common-primitives" +name = "substrate-consensus-pow" +version = "2.0.0" +dependencies = [ + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", + "srml-timestamp 2.0.0", + "substrate-client 2.0.0", + "substrate-consensus-common 2.0.0", + "substrate-consensus-pow-primitives 2.0.0", + "substrate-inherents 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "substrate-consensus-pow-primitives" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-client 2.0.0", + "substrate-primitives 2.0.0", ] [[package]] name = "substrate-consensus-rhd" version = "2.0.0" dependencies = [ - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rhododendron 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", @@ -4533,16 +5411,17 @@ dependencies = [ name = "substrate-consensus-slots" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-consensus-common 2.0.0", "substrate-inherents 2.0.0", "substrate-primitives 2.0.0", + "substrate-telemetry 2.0.0", "substrate-test-runtime-client 2.0.0", ] @@ -4550,7 +5429,7 @@ dependencies = [ name = "substrate-consensus-uncles" version = "2.0.0" dependencies = [ - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "srml-authorship 0.1.0", "substrate-client 2.0.0", @@ -4559,23 +5438,37 @@ dependencies = [ "substrate-primitives 2.0.0", ] +[[package]] +name = "substrate-debug-derive" +version = "2.0.0" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "substrate-executor" version = "2.0.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-version 2.0.0", "substrate-client 2.0.0", + "substrate-externalities 2.0.0", "substrate-offchain 2.0.0", "substrate-panic-handler 2.0.0", "substrate-primitives 2.0.0", @@ -4583,37 +5476,53 @@ dependencies = [ "substrate-serializer 2.0.0", "substrate-state-machine 2.0.0", "substrate-trie 2.0.0", + "substrate-wasm-interface 2.0.0", + "test-case 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-environ 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", + "wasmtime-jit 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", + "wasmtime-runtime 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", +] + +[[package]] +name = "substrate-externalities" +version = "2.0.0" +dependencies = [ + "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-primitives-storage 2.0.0", ] [[package]] name = "substrate-finality-grandpa" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "finality-grandpa 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "fork-tree 2.0.0", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "srml-finality-tracker 2.0.0", "substrate-client 2.0.0", "substrate-consensus-babe-primitives 2.0.0", "substrate-consensus-common 2.0.0", "substrate-finality-grandpa-primitives 2.0.0", + "substrate-header-metadata 2.0.0", "substrate-inherents 2.0.0", "substrate-keyring 2.0.0", "substrate-keystore 2.0.0", "substrate-network 2.0.0", "substrate-primitives 2.0.0", - "substrate-service 2.0.0", + "substrate-state-machine 2.0.0", "substrate-telemetry 2.0.0", "substrate-test-runtime-client 2.0.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4626,19 +5535,28 @@ dependencies = [ name = "substrate-finality-grandpa-primitives" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-application-crypto 2.0.0", "substrate-client 2.0.0", ] +[[package]] +name = "substrate-header-metadata" +version = "2.0.0" +dependencies = [ + "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", +] + [[package]] name = "substrate-inherents" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -4648,7 +5566,7 @@ dependencies = [ name = "substrate-keyring" version = "2.0.0" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4662,11 +5580,11 @@ dependencies = [ "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-application-crypto 2.0.0", "substrate-primitives 2.0.0", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4674,29 +5592,29 @@ dependencies = [ name = "substrate-network" version = "2.0.0" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fork-tree 2.0.0", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quickcheck 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "slog_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4704,6 +5622,7 @@ dependencies = [ "substrate-client 2.0.0", "substrate-consensus-babe-primitives 2.0.0", "substrate-consensus-common 2.0.0", + "substrate-header-metadata 2.0.0", "substrate-keyring 2.0.0", "substrate-peerset 2.0.0", "substrate-primitives 2.0.0", @@ -4713,20 +5632,28 @@ dependencies = [ "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-offchain" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-client-db 2.0.0", @@ -4736,6 +5663,8 @@ dependencies = [ "substrate-primitives 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", + "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4750,21 +5679,33 @@ dependencies = [ name = "substrate-panic-handler" version = "2.0.0" dependencies = [ - "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-peerset" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-phragmen" +version = "2.0.0" +dependencies = [ + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-primitives 2.0.0", + "sr-std 2.0.0", + "srml-support 2.0.0", ] [[package]] @@ -4775,31 +5716,47 @@ dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-debug-derive 2.0.0", + "substrate-externalities 2.0.0", + "substrate-primitives-storage 2.0.0", "substrate-serializer 2.0.0", "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "twox-hash 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-primitives-storage" +version = "2.0.0" +dependencies = [ + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-debug-derive 2.0.0", ] [[package]] @@ -4807,19 +5764,16 @@ name = "substrate-rpc" version = "2.0.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core-client 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-derive 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-version 2.0.0", @@ -4828,6 +5782,8 @@ dependencies = [ "substrate-keystore 2.0.0", "substrate-network 2.0.0", "substrate-primitives 2.0.0", + "substrate-rpc-api 2.0.0", + "substrate-rpc-primitives 2.0.0", "substrate-session 2.0.0", "substrate-state-machine 2.0.0", "substrate-test-runtime-client 2.0.0", @@ -4835,17 +5791,47 @@ dependencies = [ "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "substrate-rpc-api" +version = "2.0.0" +dependencies = [ + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-version 2.0.0", + "substrate-primitives 2.0.0", + "substrate-rpc-primitives 2.0.0", + "substrate-transaction-graph 2.0.0", +] + +[[package]] +name = "substrate-rpc-primitives" +version = "2.0.0" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-primitives 2.0.0", +] + [[package]] name = "substrate-rpc-servers" version = "2.0.0" dependencies = [ - "jsonrpc-http-server 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-ws-server 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-pubsub 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-ws-server 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", - "substrate-rpc 2.0.0", ] [[package]] @@ -4853,42 +5839,44 @@ name = "substrate-runtime-test" version = "2.0.0" dependencies = [ "sr-io 2.0.0", + "sr-primitives 2.0.0", "sr-sandbox 2.0.0", "sr-std 2.0.0", "substrate-primitives 2.0.0", - "substrate-wasm-builder-runner 1.0.2", + "substrate-wasm-builder-runner 1.0.4", ] [[package]] name = "substrate-serializer" version = "2.0.0" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-service" version = "2.0.0" dependencies = [ - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "node-executor 2.0.0", "node-primitives 2.0.0", "node-runtime 2.0.0", - "parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "substrate-application-crypto 2.0.0", + "substrate-chain-spec 2.0.0", "substrate-client 2.0.0", "substrate-client-db 2.0.0", "substrate-consensus-babe-primitives 2.0.0", @@ -4900,13 +5888,15 @@ dependencies = [ "substrate-network 2.0.0", "substrate-offchain 2.0.0", "substrate-primitives 2.0.0", + "substrate-rpc 2.0.0", "substrate-rpc-servers 2.0.0", "substrate-session 2.0.0", "substrate-telemetry 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-transaction-pool 2.0.0", - "sysinfo 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sysinfo 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4915,10 +5905,11 @@ dependencies = [ name = "substrate-service-test" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-consensus-common 2.0.0", @@ -4943,9 +5934,9 @@ dependencies = [ name = "substrate-state-db" version = "2.0.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 2.0.0", ] @@ -4954,17 +5945,19 @@ dependencies = [ name = "substrate-state-machine" version = "2.0.0" dependencies = [ - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-externalities 2.0.0", "substrate-panic-handler 2.0.0", "substrate-primitives 2.0.0", "substrate-trie 2.0.0", - "trie-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4972,14 +5965,14 @@ name = "substrate-telemetry" version = "2.0.0" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)", "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4992,9 +5985,9 @@ dependencies = [ name = "substrate-test-client" version = "2.0.0" dependencies = [ - "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", "substrate-client-db 2.0.0", @@ -5009,11 +6002,11 @@ dependencies = [ name = "substrate-test-runtime" version = "2.0.0" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", @@ -5022,6 +6015,7 @@ dependencies = [ "srml-executive 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", + "srml-system-rpc-runtime-api 2.0.0", "srml-timestamp 2.0.0", "substrate-application-crypto 2.0.0", "substrate-client 2.0.0", @@ -5036,15 +6030,15 @@ dependencies = [ "substrate-state-machine 2.0.0", "substrate-test-runtime-client 2.0.0", "substrate-trie 2.0.0", - "substrate-wasm-builder-runner 1.0.2", - "trie-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-wasm-builder-runner 1.0.4", + "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-test-runtime-client" version = "2.0.0" dependencies = [ - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-test-client 2.0.0", @@ -5056,13 +6050,14 @@ name = "substrate-transaction-graph" version = "2.0.0" dependencies = [ "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-primitives 2.0.0", "substrate-test-runtime 2.0.0", @@ -5072,10 +6067,10 @@ dependencies = [ name = "substrate-transaction-pool" version = "2.0.0" dependencies = [ - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-client 2.0.0", @@ -5090,40 +6085,49 @@ name = "substrate-trie" version = "2.0.0" dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", "substrate-primitives 2.0.0", - "trie-bench 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-standardmap 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-bench 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-wasm-builder" -version = "1.0.4" +version = "1.0.8" dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "build-helper 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-gc-api 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "substrate-wasm-builder-runner" -version = "1.0.2" +version = "1.0.4" [[package]] name = "substrate-wasm-builder-runner" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "substrate-wasm-interface" +version = "2.0.0" +dependencies = [ + "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "subtle" version = "1.0.0" @@ -5131,12 +6135,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "subtle" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.42" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5144,6 +6148,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.10.2" @@ -5151,20 +6165,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synstructure" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sysinfo" -version = "0.9.0" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5172,6 +6197,16 @@ name = "take_mut" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "target-lexicon" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "target_info" version = "0.1.0" @@ -5191,12 +6226,12 @@ name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5204,15 +6239,27 @@ name = "termcolor" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "test-case" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "textwrap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5220,7 +6267,15 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "threadpool" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5228,9 +6283,9 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5238,7 +6293,7 @@ name = "tiny-bip39" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5260,19 +6315,8 @@ name = "tinytemplate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tk-listen" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5281,7 +6325,7 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5289,12 +6333,12 @@ dependencies = [ "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5304,8 +6348,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5314,7 +6358,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5323,7 +6367,7 @@ name = "tokio-current-thread" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5332,9 +6376,9 @@ name = "tokio-dns-unofficial" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5344,7 +6388,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5352,9 +6396,9 @@ name = "tokio-fs" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5363,48 +6407,48 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-rustls" -version = "0.10.0-alpha.4" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5413,25 +6457,25 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5442,7 +6486,7 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5452,23 +6496,23 @@ name = "tokio-tls" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-udp" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5477,23 +6521,23 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5505,8 +6549,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "transaction-factory" version = "0.0.1" dependencies = [ - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "substrate-cli 2.0.0", "substrate-client 2.0.0", @@ -5517,46 +6561,46 @@ dependencies = [ [[package]] name = "trie-bench" -version = "0.16.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-standardmap 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-db" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-root" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "trie-standardmap" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hasher 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5566,15 +6610,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "trybuild" -version = "1.0.9" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5584,15 +6628,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "twox-hash" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5602,17 +6646,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "typenum" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ucd-util" -version = "0.1.5" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5630,7 +6669,7 @@ dependencies = [ [[package]] name = "unicase" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5659,7 +6698,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -5667,9 +6706,14 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unsigned-varint" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5678,7 +6722,7 @@ dependencies = [ [[package]] name = "untrusted" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -5692,9 +6736,14 @@ dependencies = [ ] [[package]] -name = "utf8-ranges" -version = "1.0.3" +name = "url" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "vcpkg" @@ -5706,24 +6755,14 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "vecarray" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-codec 4.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "vergen" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5731,6 +6770,11 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -5738,22 +6782,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wabt" -version = "0.7.4" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wabt-sys" -version = "0.5.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5763,7 +6807,7 @@ version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -5772,166 +6816,271 @@ name = "want" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "wasm-bindgen" -version = "0.2.48" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wasm-bindgen-macro 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.48" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bumpalo 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-futures" -version = "0.3.25" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.48" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.48" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.48" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-bindgen-webidl" -version = "0.2.48" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wasm-gc-api" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasm-timer" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmi" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmi-validation" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmparser" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmtime-debug" +version = "0.2.0" +source = "git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6#71dd73d672deb325664e3c9cd4ee7acebed5fb95" +dependencies = [ + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "faerie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-environ 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", +] + +[[package]] +name = "wasmtime-environ" +version = "0.2.0" +source = "git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6#71dd73d672deb325664e3c9cd4ee7acebed5fb95" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd 0.4.28+zstd.1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-jit" +version = "0.2.0" +source = "git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6#71dd73d672deb325664e3c9cd4ee7acebed5fb95" +dependencies = [ + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-debug 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", + "wasmtime-environ 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", + "wasmtime-runtime 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", +] + +[[package]] +name = "wasmtime-runtime" +version = "0.2.0" +source = "git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6#71dd73d672deb325664e3c9cd4ee7acebed5fb95" +dependencies = [ + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime-environ 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "web-sys" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-webidl 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-webidl 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webpki" -version = "0.19.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webpki-roots" -version = "0.16.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "websocket" -version = "0.22.4" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5951,8 +7100,8 @@ name = "which" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5962,7 +7111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -5984,7 +7133,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5994,28 +7143,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wincolor" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ws" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -6033,7 +7182,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -6053,9 +7202,9 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "nohash-hasher 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6065,126 +7214,172 @@ dependencies = [ [[package]] name = "zeroize" -version = "0.9.2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "zeroize" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "zeroize" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "zstd" +version = "0.4.28+zstd.1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "zeroize_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd-safe 1.4.13+zstd.1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "zeroize_derive" -version = "0.9.0" +name = "zstd-safe" +version = "1.4.13+zstd.1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd-sys 1.4.13+zstd.1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zstd-sys" +version = "1.4.13+zstd.1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" +"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" "checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" "checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" -"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" -"checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" +"checksum ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "b35dfc96a657c1842b4eb73180b65e37152d4b94d0eb5cb51708aee7826950b4" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" -"checksum asn1_der 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bea40e881533b1fe23afca9cd1c1ca022219a10fce604099ecfc96bfa26eaf1a" -"checksum asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7f92edafad155aff997fa5b727c6429b91e996b5a5d62a2b0adbae1306b5fe" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +"checksum asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638" +"checksum asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" "checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" -"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" +"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" "checksum bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df683a55b54b41d5ea8ebfaebb5aa7e6b84e3f3006a78f010dadc9ca88469260" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" "checksum bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead" -"checksum bitvec 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b67491e1cc6f37da6c4415cd743cb8d2e2c65388acc91ca3094a054cbf3cbd0c" "checksum bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9633b74910e1870f50f5af189b08487195cdb83c0e27a71d6f64d5e09dd0538b" -"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" +"checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" +"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" -"checksum bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a692f1c740e7e821ca71a22cf99b9b2322dfa94d10f71443befb1797b3946a" +"checksum bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" "checksum build-helper 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdce191bf3fa4995ce948c8c83b4640a1745457a149e73c6db75b4ffe36aad5f" -"checksum bumpalo 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2cd43d82f27d68911e6ee11ee791fb248f138f5d69424dc02e098d4f152b0b05" +"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" "checksum byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbcbf18128ec71d8d4a0d054461ec59fff5b75b7d10a4c9b7c7cb1a379c3e77" -"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" -"checksum cargo_metadata 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e904f164f39cae0c3a4f2713eb97a47ba64676a071e99a69ddfef4994694d2c" +"checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" +"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" "checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cmake 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "2ca4386c8954b76a8415b63959337d940d724b336cabd3afe189c2b51a7e1ff0" -"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" +"checksum console_error_panic_hook 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +"checksum console_log 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e7871d2947441b0fdd8e2bd1ce2a2f75304f896582c0d572162d48290683c48" +"checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" +"checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum cranelift-bforest 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "18c97588946d3e5fe11f8e34ebf8cc65fd3fda50f3ffa2e80c98b2748058f00f" +"checksum cranelift-codegen 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3255935da50302bcb0f7109f2fef27f44b46f1c797dfa7db971379261023adcd" +"checksum cranelift-codegen-meta 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd57265ef5e6ff253c378b6261ed8c2e6cb1b15e91624540dbd09b1e5a40e9ca" +"checksum cranelift-codegen-shared 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c093398d21f9493ab29445191362592ef621f497e56a8efb15bdf80471978b7a" +"checksum cranelift-entity 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e915fa58d2a75e3c4b768b7e4760282889915c3fcd9ccb2ad2b3ebec99654a78" +"checksum cranelift-frontend 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46963952cda267bd0177b3f036e50038cd56e7b4c5b09a455b02df727e0f2a16" +"checksum cranelift-native 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7ba8a2d69ddd4729199a321bc2f4020e1969a088b468ed6a29dc7a69350be76e" +"checksum cranelift-wasm 0.46.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5a802357a6a016bf4c1dcdc6d73a650640eb3b613cc098a1a044a6c3731ca264" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394" +"checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" "checksum criterion-plot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76f9212ddf2f4a9eb2d401635190600656a1f88a932ef53d06e7fa4c7e02fb8e" +"checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" -"checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" +"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" "checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" "checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f" "checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" -"checksum curve25519-dalek 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5d4b820e8711c211745880150f5fac78ab07d6e3851d8ce9f5a02cedc199174c" +"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" "checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" -"checksum derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839" "checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" +"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" "checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" -"checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" -"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" +"checksum ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d07e8b8a8386c3b89a7a4b329fdfa4cb545de2545e9e2ebbc3dd3929253e426" +"checksum ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "845aaacc16f01178f33349e7c992ecd0cee095aa5e577f0f4dee35971bd36455" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" -"checksum environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c7464757b80de8930c91c9afe77ddce501826bf9d134a87db2c67d9dc177e2c" +"checksum env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39ecdb7dd54465526f0a56d666e3b2dd5f3a218665a030b6e4ad9e70fa95d8fa" +"checksum environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34f8467a0284de039e6bd0e25c14519538462ba5beb548bb1f03e645097837a8" "checksum erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3beee4bc16478a1b26f2e80ad819a52d24745e292f521a63c16eea5f74b7eb60" +"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" +"checksum evm 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1138816a9b7f9a9d1fcabb1b8a7afed2687d035692baf297bd3fea122acdc96f" +"checksum evm-core 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bcde5af3d542874ddeb53de0919302d57586ea04b3f76f54d865f8a6cdc70ae" +"checksum evm-gasometer 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b82bc9f275cb59d2bcc05d85c98736ddfaba003a7ef7b73893fa7c1c1fab29dc" +"checksum evm-runtime 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbc89d29618c3722c17ba78ddf432d40ace8ee27e3f8b28b52a85921112e4b" "checksum exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d8013f441e38e31c670e7f34ec8f1d5d3a2bd9d303c1ff83976ca886005e8f48" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum faerie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "875d78b92b2a4d9e1e2c7eeccfa30a327d2ee6434db3beb8fd6fd92f41898bc4" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" +"checksum file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8505b75b31ef7285168dd237c4a7db3c1f3e0927e7d314e670bc98e854272fe9" "checksum finality-grandpa 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9681c1f75941ea47584573dd2bc10558b2067d460612945887e00744e43393be" -"checksum fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "516877b7b9a1cc2d0293cbce23cd6203f0edbfd4090e6ca4489fecb5aa73050e" -"checksum flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "550934ad4808d5d39365e5d61727309bf18b3b02c6c56b729cb92e7dd84bc3d8" +"checksum fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6357b15872f8126e4ea7cf79d579473f132ccd2de239494ad1bf4aa892faea68" +"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" +"checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -6193,98 +7388,103 @@ dependencies = [ "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" -"checksum futures-channel-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "21c71ed547606de08e9ae744bb3c6d80f5627527ef31ecf2a7210d0e67bc8fae" -"checksum futures-core-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4b141ccf9b7601ef987f36f1c0d9522f76df3bba1cf2e63bfacccc044c4558f5" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" +"checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-executor-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "87ba260fe51080ba37f063ad5b0732c4ff1f737ea18dcb67833d282cdc2c6f14" -"checksum futures-io-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "082e402605fcb8b1ae1e5ba7d7fdfd3e31ef510e2a8367dd92927bb41ae41b3a" -"checksum futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "bf25f91c8a9a1f64c451e91b43ba269ed359b9f52d35ed4b3ce3f9c842435867" -"checksum futures-sink-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4309a25a1069a1f3c10647b227b9afe6722b67a030d3f00a9cbdc171fc038de4" -"checksum futures-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb4a32e84935678650944c6ebd0d912db46405d37bf94f1a058435c5080abcb1" -"checksum futures-util-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)" = "af8198c48b222f02326940ce2b3aa9e6e91a32886eeaad7ca3b8e4c70daa3f4e" +"checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" +"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" +"checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" +"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" +"checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" +"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" "checksum get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" "checksum get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" -"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "162d18ae5f2e3b90a993d202f1ba17a5633c2484426f8bcae201f86194bacd00" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +"checksum goblin 0.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "e3fa261d919c1ae9d1e4533c4a2f99e10938603c4208d56c05bec7a872b661b0" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -"checksum hash-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32c87fec93c4a2d264483ef843ac1930ae7c7999d97d73721305a5188b4c23a4" -"checksum hash256-std-hasher 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16293646125e09e5bc216d9f73fa81ab31c4f97007d56c036bbf15a58e970540" +"checksum hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" +"checksum hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" -"checksum hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8e04cb7a5051270ef3fa79f8c7604d581ecfa73d520e74f554e45541c4b5881a" +"checksum hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" +"checksum hashmap_core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6852e5a86250521973b0c1d39677166d8a9c0047c908d7e04f1aa04177973c" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3da68162fdd2147e66682e78e729bd77f93b4c99656db058c5782d8c6b6225a" -"checksum hex-literal-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06095d08c7c05760f11a071b3e1d4c5b723761c01bd8d7201c30a9536668a612" -"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" +"checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" +"checksum hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0" +"checksum hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d4c5c844e2fee0bf673d54c2c177f1713b3d2af2ff6e666b49cb7572e6cf42d" "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" -"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" +"checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" +"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -"checksum hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb44cbce9d8ee4fb36e4c0ad7b794ac44ebaad924b9c8291a63215bb44c2c8f" +"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum impl-codec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "78c441b3d2b5e24b407161e76d482b7bbd29b5da357707839ac40d95152f031f" -"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" -"checksum impl-serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d26be4b97d738552ea423f76c4f681012ff06c3fa36fa968656b3679f60b4a1" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +"checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" +"checksum impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" +"checksum impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" +"checksum impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" +"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum ipnet 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e61c2da0d0f700c77d2d313dbf4f93e41d235fa12c6681fee06621036df4c2af" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum ipnet 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc15ac2e0886d62ba078989ef6920ab23997ab0b04ca5687f1a9a7484296a48" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "da3ea71161651a4cd97d999b2da139109c537b15ab33abc8ae4ead38deac8a03" -"checksum jsonrpc-client-transports 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6be24a8de4ced80f6fd8b6ace54aa610823a7642976a0e8e00e3bb2f4d8c33f0" -"checksum jsonrpc-core 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0216cf4c95fb373d89c63572672097b8aa74cfcdd77054accbf545d840be5bd7" -"checksum jsonrpc-core-client 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1603b6cc05060de7794c2962edd705e1ad2698bd2b0d2ddd4489f8c85df122b7" -"checksum jsonrpc-derive 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8afff172177878850d133ccdcd93cad794e85d7779ab334998d669ef80e13180" -"checksum jsonrpc-http-server 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a24e140242e0d2e9a694cf8db513a2bd739d24c392e0ad15e0d6d7ee8851e3a2" -"checksum jsonrpc-pubsub 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c45f7cdb1bb28a3bfb3a0a5184bf99669c9ffe8cf8d7b8a582f2a52bf9944a" -"checksum jsonrpc-server-utils 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7aac8e0029d19582b68c9fd498d18bdcf0846612c968acc93b6e5ae67eea4e0" -"checksum jsonrpc-ws-server 12.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "698fee4fcaf09a5927b7e39dd8a8136a102b343cebacaa351fc4def01a050a5b" +"checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" +"checksum js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc9a97d7cec30128fd8b28a7c1f9df1c001ceb9b441e2b755e24130a6b43c79" +"checksum jsonrpc-client-transports 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d389a085cb2184604dff060390cadb8cba1f063c7fd0ad710272c163c88b9f20" +"checksum jsonrpc-core 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "34651edf3417637cc45e70ed0182ecfa9ced0b7e8131805fccf7400d989845ca" +"checksum jsonrpc-core-client 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbaec1d57271ff952f24ca79d37d716cfd749c855b058d9aa5f053a6b8ae4ef" +"checksum jsonrpc-derive 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d5c31575cc70a8b21542599028472c80a9248394aeea4d8918a045a0ab08a3" +"checksum jsonrpc-http-server 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aa54c4c2d88cb5e04b251a5031ba0f2ee8c6ef30970e31228955b89a80c3b611" +"checksum jsonrpc-pubsub 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ee1b8da0b9219a231c4b7cbc7110bfdb457cbcd8d90a6224d0b3cab8aae8443" +"checksum jsonrpc-server-utils 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "87bc3c0a9a282211b2ec14abb3e977de33016bbec495332e9f7be858de7c5117" +"checksum jsonrpc-ws-server 14.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af36a129cef77a9db8028ac7552d927e1bb7b6928cd96b23dd25cc38bff974ab" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" -"checksum keccak-hasher 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bf18164fd7ce989041f8fc4a1ae72a8bd1bec3575f2aeaf1d4968fc053aabef" +"checksum keccak-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3468207deea1359a0e921591ae9b4c928733d94eb9d6a2eeda994cfd59f42cf8" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" -"checksum libp2p 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18b3404dae1e3110caaae14b2d59bf7254b1e988ed7ed38da59c005bed711e7d" -"checksum libp2p-core 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efa1b75b0b388c0f33bc2e2f5d385885f9ed77f622802895b68ac8397aaef2de" -"checksum libp2p-core-derive 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "954fe45edba727b76196abff0d3894116c32a07e4f8173a8f26caf3484add4c0" -"checksum libp2p-deflate 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56b77964eaf8ba7019df8de2a02f2241ee240011d6de69f4991baf174ad42d2e" -"checksum libp2p-dns 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c2625c6acd4073403f1107e4e038efa02ba5de54de0d08567a2cc338560d63f" -"checksum libp2p-floodsub 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d14e6c61c6e69f291261c8ec001b85a2c6426f2074183a40c337c29ed7939bd1" -"checksum libp2p-identify 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34ba4b8d4e27f4848a6b121604d98818a8527f4269948ba77dfe49f0f1c3dc8f" -"checksum libp2p-kad 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "93384ee24fe137bf3afa8263b8d9e63c6bd6c92aad7cc50949fdba2b90db93a4" -"checksum libp2p-mdns 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd24b59da234647e15c34054158b6853a505301d5888719593e6fcd7841c39d9" -"checksum libp2p-mplex 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b101952e8dfdc5c902f1063cd8bfbb80e735857a16d387033ae8180df578009" -"checksum libp2p-noise 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1dd3313a8216b92e3ae5a24034d6fc35bf9671e9f4ad4b2ce445291852508b77" -"checksum libp2p-ping 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c803a4d21c97e14eb8b5019cc32242e296f1d1835de8664e5464d7dc31f068d" -"checksum libp2p-plaintext 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fbac75c9683aa5997887420007ea2cf47ab9b68584b4edfa2b20598c9d509273" -"checksum libp2p-ratelimit 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7abef2e38e9d4bb5036724d325dd0518007e32d73d5171334d4d5355995bb4d8" -"checksum libp2p-secio 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33c208e7c74c15c72e7092503d6772ed5b2add2155e08234ae10169769e3135c" -"checksum libp2p-swarm 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8788a19e54240ba632ec0913bb951e7fd744f4e6151b2dc1a8b44d80b2947830" -"checksum libp2p-tcp 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "180543c45126c4eec42f35594e169a8d7c891253bc127297ca7781c05ad8bce6" -"checksum libp2p-uds 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffaf9dfc24beaf7ad5be01a6eabe67842cd02575da68a08ebe11b5a8821fc4a9" -"checksum libp2p-wasm-ext 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35307568a484cce18eae7516201ecbbfc3fb7e17c7f235d407690aee6adaa046" -"checksum libp2p-websocket 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e6c6d86998e66848f16b65e89896d94fa3825e218d2fc44cbc6b84e8ef97bb9" -"checksum libp2p-yamux 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c03b89d025c7b01c966348e4d618b1ec4b95f3c09749ca9f2b2c98240aabfe6" +"checksum libp2p 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9aa3d728b96c06763b2e919b4c99a334d698303c49489671b5ffe3a4b0fd4c9c" +"checksum libp2p-core 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07759706a4cb4a90903c67d92cb9575acd8df90f583dfdc46d57afdeaead4c82" +"checksum libp2p-core-derive 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eeb2704ac14c60f31967e351ed928b848526a5fc6db4104520020665012826f" +"checksum libp2p-deflate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2b0bf5d37692ac90e2bffa436bec26c0b0def6c0cab7ea85ff67a353d58aaa" +"checksum libp2p-dns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3175fb0fc9016c95c8517a297bbdb5fb6bfbd5665bacd2eb23495d1cbdeb033" +"checksum libp2p-floodsub 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92c11b95281e8cb87eb83c204b3ca4988fa665ed9351199b5bcc323056f49816" +"checksum libp2p-identify 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4eba6103329e9a1a2aa940671efe5600c758a295e61172139d7a900166da0017" +"checksum libp2p-kad 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84ceb0faa267b96560ef883dc5bc6dddd9de1662e35a4070208623b391deefca" +"checksum libp2p-mdns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab1eec2958fc74883ed8ecb0c38324941a44195a58fea87fcfc2bd17da34d1fa" +"checksum libp2p-mplex 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2fe584816d993dc0f893396521a3c93191d78a6f28a892b150baa714a12c3e5" +"checksum libp2p-noise 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a30ec2640262a7ad6b1a8b28f6cd8281e620a6802f700adf9ff26e61487c333a" +"checksum libp2p-ping 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4e1682cdae649394d2793758ded2bfd4d9d440f807e3b4d9f70981f377aa28a" +"checksum libp2p-plaintext 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4fe82189f5c20e8f0a11deaa04d492703c501cefd2428ad68f4f64aefab76f" +"checksum libp2p-secio 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee09e259ceb7633a52fd17f187bedf94e3545b1746487beedbd3a0a07d99817" +"checksum libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd55bc9f5f9eac2bb1ff24ca3c8a655810a566ac38c7a6ee1f30aced5a62905b" +"checksum libp2p-tcp 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "234a7093d05651ab5630db926a4a42ca8978a65bab8c27c2ce2b66b200c76989" +"checksum libp2p-uds 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e2fe0648967da3e56e4a55055c857c8c48326b66be0047d0e04c8ca60d34630" +"checksum libp2p-wasm-ext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7b8f2bd81fb356e81352d4513856bc21215ecf91502aa1f55b6449642a9acf" +"checksum libp2p-websocket 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d74d4fc229ad7e8d1a973178786bdcd5dadbdd7b9822c4477c8687df6f82f66" +"checksum libp2p-yamux 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1913eb7dd6eb5515957b6f1770296f6921968db87bc9b985f0e974b6657e1003" "checksum librocksdb-sys 5.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19778314deaa7048f2ea7d07b8aa12e1c227acebe975a37eeab6d2f8c74e41b" -"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" +"checksum libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63cc09b49bf0cc55885982347b174ad89855e97a12284d2c9dcc6da2e20c28f5" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7c91c4c7bbeb4f2f7c4e5be11e6a05bd6830bc37249c47ce1ad86ad453ff9c" @@ -6292,140 +7492,158 @@ dependencies = [ "checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" "checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum memory-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a688133a81c915553c1dd9c3e859949f43a854cb8f8773e690e849b53b1f89f0" +"checksum memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef49315991403ba5fa225a70399df5e115f57b274cb0b1b4bcd6e734fa5bd783" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum merlin 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "66448a173ad394ef5ebf734efa724f3644dcffda083b1e89979da4461ddac079" +"checksum merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "de2d16d3b15fec5943d1144f861f61f279d165fdd60998ca262913b9bf1c8adb" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum miniz-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" -"checksum miniz_oxide 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c061edee74a88eb35d876ce88b94d77a0448a201de111c244b70d047f5820516" -"checksum miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6c675792957b0d19933816c4e1d56663c341dd9bfa31cb2140ff2267c1d8ecf4" +"checksum miniz_oxide 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "304f66c19be2afa56530fa7c39796192eef38618da8d19df725ad7c6d6b2aaae" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multistream-select 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f989d40aab0ed0d83c1cdb4856b5790e980b96548d1a921f280e985eb049f38d" +"checksum multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151" +"checksum multistream-select 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1242e4ecf2060b35fb58002988e4720fbb3a2cbd4c136d369c420fa028f69efe" "checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d138afcce92d219ccb6eb53d9b1e8a96ac0d633cfd3c53cd9856d96d1741bb8" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +"checksum nohash-hasher 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e657a6ec97f9a3ba46f6f7034ea6db9fcd5b71d25ef1074b7bc03da49be0e8e" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" -"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" +"checksum once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d584f08c2d717d5c23a6414fc2822b71c651560713e54fa7eace675f758a355e" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)" = "b5ba300217253bcc5dc68bed23d782affa45000193866e025329aa8a7a9f05b8" +"checksum openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)" = "ba24190c8f0805d3bd2ce028f439fe5af1d55882bbe6261bed1dbc93b50dd6b1" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum parity-codec 4.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2900f06356edf90de66a2922db622b36178dca71e85625eae58d0d9cc6cff2ac" -"checksum parity-multiaddr 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "045b3c7af871285146300da35b1932bb6e4639b66c7c98e85d06a32cbc4e8fa7" -"checksum parity-multihash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df3a17dc27848fd99e4f87eb0f8c9baba6ede0a6d555400c850ca45254ef4ce3" -"checksum parity-scale-codec 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "00fd14ff806ad82cea9a8f909bb116443d92efda7c9acd4502690af64741ad81" -"checksum parity-scale-codec-derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a81f3cd93ed368a8e41c4e79538e99ca6e8f536096de23e3a0bc3e782093ce28" +"checksum parity-multiaddr 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7dbc379f41150dedda75cbbdb5b9beb2bf786a07e56c2c99ec89aeaaa894662c" +"checksum parity-multihash 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "340ed03f939e02e4cb71a5a127b5507ba4dab506e41a05f8f467e28d8ce529f4" +"checksum parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "001fbbb956d8593f321c7a784f64d16b2c99b2657823976eea729006ad2c3668" +"checksum parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42af752f59119656fa3cb31e8852ed24e895b968c0bdb41847da7f0cea6d155f" "checksum parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" "checksum parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2005637ccf93dbb60c85081ccaaf3f945f573da48dcc79f27f9646caa3ec1dc" -"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" +"checksum parity-wasm 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16ad52817c4d343339b3bc2e26861bd21478eda0b7509acf83505727000512ac" +"checksum parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e39faaa292a687ea15120b1ac31899b13586446521df6c149e46f1584671e0f" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" -"checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" +"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" +"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" +"checksum pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" -"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" +"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum primitive-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e44400d651ca5276415dc8e00541c5c9d03844f1f0a87ad28f0a8fadcb2300bc" +"checksum primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97b5a08dda18910f056e5c2060c034e77cab18e0bd7d895e44f03207af4c71d5" "checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -"checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" +"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +"checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum protobuf 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8aefcec9f142b524d98fc81d07827743be89dd6586a1ba6ab21fa66a500b3fa5" -"checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96d14b1c185652833d24aaad41c5832b0be5616a590227c1fbff57c616754b23" +"checksum prost-build 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb788126ea840817128183f8f603dce02cb7aea25c2a0b764359d8e20010702e" +"checksum prost-derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e7dc378b94ac374644181a2247cebf59a6ec1c88b49ac77f3a94b86b79d0e11" +"checksum prost-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1de482a366941c8d56d19b650fac09ca08508f2a696119ee7513ad590c8bac6f" +"checksum protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40361836defdd5871ff7e84096c6f6444af7fc157f8ef1789f54f147687caa20" +"checksum pwasm-utils 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d473123ba135028544926f7aa6f34058d8bc6f120c4fcd3777f84af724280b3" "checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quickcheck 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9c35d9c36a562f37eca96e79f66d5fd56eefbc22560dacc4a864cabd2d277456" +"checksum quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5ca504a2fdaa08d3517f442fbbba91ac24d1ec4c51ea68688a038765e3b2662" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929" -"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" -"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" +"checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" +"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" +"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" +"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" "checksum ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6" -"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" -"checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "448e868c6e4cfddfa49b6a72c95906c04e8547465e9536575b95c70a4044f856" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum rhododendron 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36542aafc2429a4c010fafa079a20dee953b663cb2427f51d86cf1d436846b4d" -"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" +"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac" +"checksum rlp 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8376a3f725ebb53f69263bbebb42196361fdfd551212409c8a721239aab4f09f" "checksum rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1651697fefd273bfb4fd69466cc2a9d20de557a0213b97233b22b5e95924b5e" -"checksum rpassword 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34fa7bcae7fca3c8471e8417088bbc3ad9af8066b0ecf4f3c0d98a0d772716e" -"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" +"checksum rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f072d931f11a96546efd97642e1e75e807345aced86b947f9239102f262d0fcd" +"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f271e3552cd835fa28c541c34a7e8fdd8cdff09d77fe4eb8f6c42e87a11b096e" +"checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" +"checksum rustversion 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48f91977f4ef3be5358c15d131d3f663f6b4d7a112555bf3bf52ad23b6659e5" "checksum rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9cbe61c20455d3015b2bb7be39e1872310283b8e5a52f5b242b0ac7581fe78" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19d2271fa48eaf61e53cc88b4ad9adcbafa2d512c531e7fadb6dc11a4d3656c5" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" +"checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" -"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" -"checksum schnorrkel 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "77e8d6a92f49a53f21b71c090a5559bf45c469071ebe556aebaf2dca3abc5cb5" +"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" +"checksum schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f5adf8fbd58e1b1b52699dc8bed2630faecb6d8c7bee77d009d6bbe4af569b9" +"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" +"checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" +"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" -"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72" -"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f" -"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" "checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" @@ -6436,39 +7654,43 @@ dependencies = [ "checksum slog-scope 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1d3ec6214d46e57a7ec87c1972bbca66c59172a0cfffa5233c54726afb946bf" "checksum slog_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eff3b513cf2e0d1a60e1aba152dc72bedc5b05585722bb3cebd7bcb1e31b98f" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5a64f02fd208ef15bd2d1a65861df4707e416151e1272d02c8faafad1c138100" -"checksum soketto 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db2383e992ba8ba8205cd1169cac2efdf325d3a0da465dc35f63a2074598347e" +"checksum snow 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91eecae35b461ed26bda7a76bea2cc5bda2bf4b8dd06761879f19e6fdd50c2dd" +"checksum soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bceb1a3a15232d013d9a3b7cac9e5ce8e2313f348f01d4bc1097e5e53aa07095" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" -"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" -"checksum stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8861bc80f649f5b4c9bd38b696ae9af74499d479dbfb327f0607de6b326a36bc" +"checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" -"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" +"checksum string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd710eadff449a1531351b0e43eb81ea404336fa2f56c777427ab0e32a4cf183" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f66a4c0ddf7aee4677995697366de0749b0139057342eccbb609b12d0affc" +"checksum structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fe0c13e476b4e21ff7f5c4ace3818b6d7bdc16897c31c73862471bc1663acae" "checksum strum 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1c33039533f051704951680f1adfd468fd37ac46816ded0d9ee068e60f05f" "checksum strum_macros 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47cd23f5c7dee395a00fa20135e2ec0fffcdfa151c56182966d7a3261343432e" "checksum substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" -"checksum substrate-wasm-builder-runner 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f52ecbff6cc3d6e5c6401828e15937b680f459d6803ce238f01fe615bc40d071" +"checksum substrate-wasm-builder-runner 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bd48273fe9d7f92c1f7d6c1c537bb01c8068f925b47ad2cd8367e11dc32f8550" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01dca13cf6c3b179864ab3292bd794e757618d35a7766b7c46050c614ba00829" -"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" +"checksum subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab3af2eb31c42e8f0ccf43548232556c42737e01a96db6e1777b0be108e79799" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum sysinfo 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3e2cab189e59f72710e3dd5e1e0d5be0f6c5c999c326f2fdcdf3bf4483ec9fd" +"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" +"checksum sysinfo 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bd3b813d94552a8033c650691645f8dd5a63d614dddd62428a95d3931ef7b6" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" +"checksum target-lexicon 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7975cb2c6f37d77b190bc5004a2bb015971464756fde9514651a525ada2a741a" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum test-case 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a605baa797821796a751f4a959e1206079b24a4b7e1ed302b7d785d81a9276c9" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" "checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" "checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" -"checksum tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5462b0f968c0457efe38fcd2df7e487096b992419e4f5337b06775a614bbda4b" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" @@ -6477,78 +7699,89 @@ dependencies = [ "checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-rustls 0.10.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e5cebc3ca33110e460c4d2e7c5e863b159fadcbf125449d896720695b2af709" -"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" +"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" +"checksum tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1df2fa53ac211c136832f530ccb081af9af891af22d685a9493e232c7a359bc2" +"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" +"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" +"checksum toml 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04dffffeac90885436d23c692517bb5b8b3f8863e4afc15023628d067d667b7" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum trie-bench 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1861db0e69cc3d650083ca1e70e6f5aeb871491409abc0efaf321dff48df24a" -"checksum trie-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b65d609ae631d808c6c1cc23a622733d5a0b66a7d67e9f5cd5171562a1f4cb5" -"checksum trie-root 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b0eaa64e50d686c89e6d4817ed33cb18cfa249e9071b7918b18ecfacc7867" -"checksum trie-standardmap 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64fda153c00484d640bc91334624be22ead0e5baca917d9fd53ff29bdebcf9b2" +"checksum trie-bench 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3073600c543ed001319d7e092c46dfd8c245af1a218ec5c75eb01582660a2b3e" +"checksum trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b62d27e8aa1c07414549ac872480ac82380bab39e730242ab08d82d7cc098a" +"checksum trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b779f7c1c8fe9276365d9d5be5c4b5adeacf545117bb3f64c974305789c5c0b" +"checksum trie-standardmap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3161ba520ab28cd8e6b68e1126f1009f6e335339d1a73b978139011703264c8" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum trybuild 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f2e8e773ac21d176ee05243456b9f1a942cd1a586dab188ced05b8e8d58dc635" +"checksum trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e6851bf8351876984fbab8a2391de6378947b898410d8714edd12164d2137127" "checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" -"checksum twox-hash 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7834480552ffc48e1930ceddd701f47d2234319d80b7bcbbe2fe7202933c101" +"checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" -"checksum uint 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5375d2c574f89adad4108ad525c93e39669853a602560bf5ed4ca9943b10799" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" +"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c64cdf40b4a9645534a943668681bcb219faf51874d4b65d2e0abda1b10a2ab" -"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f0023a96687fe169081e8adce3f65e3874426b7886e9234d490af2dc077959" +"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" +"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" "checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum vecarray 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d68a73b7d7d950c6558b6009e9fba229fb67562bda9fd02198f614f4ecf83f" "checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "74e463a508e390cc7447e70f640fbf44ad52e1bd095314ace1fdf99516d32add" -"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c" +"checksum wabt 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5c5c1286c6e578416982609f47594265f9d489f9b836157d403ad605a46693" +"checksum wabt-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af5d153dc96aad7dc13ab90835b892c69867948112d95299e522d370c4e13a08" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "4de97fa1806bb1a99904216f6ac5e0c050dc4f8c676dc98775047c38e5c01b55" -"checksum wasm-bindgen-backend 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "5d82c170ef9f5b2c63ad4460dfcee93f3ec04a9a36a4cc20bc973c39e59ab8e3" -"checksum wasm-bindgen-futures 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "73c25810ee684c909488c214f55abcbc560beb62146d352b9588519e73c2fed9" -"checksum wasm-bindgen-macro 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f07d50f74bf7a738304f6b8157f4a581e1512cd9e9cdb5baad8c31bbe8ffd81d" -"checksum wasm-bindgen-macro-support 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "95cf8fe77e45ba5f91bc8f3da0c3aa5d464b3d8ed85d84f4d4c7cc106436b1d7" -"checksum wasm-bindgen-shared 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "d9c2d4d4756b2e46d3a5422e06277d02e4d3e1d62d138b76a4c681e925743623" -"checksum wasm-bindgen-webidl 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "24e47859b4eba3d3b9a5c2c299f9d6f8d0b613671315f6f0c5c7f835e524b36a" -"checksum wasm-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6101df9a5987df809216bdda7289f52b58128e6b6a6546e9ee3e6b632b4921" -"checksum wasmi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48437c526d40a6a593c50c5367dac825b8d6a04411013e866eca66123fb56faa" -"checksum wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab380192444b3e8522ae79c0a1976e42a82920916ccdfbce3def89f456ea33f3" -"checksum web-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "86d515d2f713d3a6ab198031d2181b7540f8e319e4637ec2d4a41a208335ef29" -"checksum webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7e1cd7900a3a6b65a3e8780c51a3e6b59c0e2c55c6dc69578c288d69f7d082" -"checksum webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c10fa4212003ba19a564f25cd8ab572c6791f99a03cc219c13ed35ccab00de0e" -"checksum websocket 0.22.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0adcd2a64c5746c9702b354a1b992802b0c363df1dfa324a74cb7aebe10e0cbf" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum wasm-bindgen 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "cd34c5ba0d228317ce388e87724633c57edca3e7531feb4e25e35aaa07a656af" +"checksum wasm-bindgen-backend 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "927196b315c23eed2748442ba675a4c54a1a079d90d9bdc5ad16ce31cf90b15b" +"checksum wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c" +"checksum wasm-bindgen-macro 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "92c2442bf04d89792816650820c3fb407af8da987a9f10028d5317f5b04c2b4a" +"checksum wasm-bindgen-macro-support 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "9c075d27b7991c68ca0f77fe628c3513e64f8c477d422b859e03f28751b46fc5" +"checksum wasm-bindgen-shared 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "83d61fe986a7af038dd8b5ec660e5849cbd9f38e7492b9404cc48b2b4df731d1" +"checksum wasm-bindgen-webidl 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "9b979afb0535fe4749906a674082db1211de8aef466331d43232f63accb7c07c" +"checksum wasm-gc-api 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c32691b6c7e6c14e7f8fd55361a9088b507aa49620fcd06c09b3a1082186b9" +"checksum wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aa3e01d234bb71760e685cfafa5e2c96f8ad877c161a721646356651069e26ac" +"checksum wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f31d26deb2d9a37e6cfed420edce3ed604eab49735ba89035e13c98f9a528313" +"checksum wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc0356e3df56e639fc7f7d8a99741915531e27ed735d911ed83d7e1339c8188" +"checksum wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5083b449454f7de0b15f131eee17de54b5a71dcb9adcf11df2b2f78fad0cd82" +"checksum wasmtime-debug 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)" = "" +"checksum wasmtime-environ 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)" = "" +"checksum wasmtime-jit 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)" = "" +"checksum wasmtime-runtime 0.2.0 (git+https://github.com/CraneStation/wasmtime.git?rev=71dd73d6)" = "" +"checksum web-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)" = "c84440699cd02ca23bed6f045ffb1497bc18a3c2628bd13e2093186faaaacf6b" +"checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4" +"checksum webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" +"checksum websocket 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b255b190f412e45000c35be7fe9b48b39a2ac5eb90d093d421694e5dae8b335c" "checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum ws 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec91ea61b83ce033c43c06c52ddc7532f465c0153281610d44c58b74083aee1a" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" +"checksum ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6f5bb86663ff4d1639408410f50bf6050367a8525d644d49a6894cd618a631" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee1585dc1484373cbc1cee7aafda26634665cf449436fd6e24bfd1fad230538" "checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" "checksum yamux 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01bd67889938c48f0049fc60a77341039e6c3eaf16cb7693e6ead7c0ba701295" -"checksum zeroize 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4177936c03b5a349c1b8e4509c46add268e66bc66fe92663729fa0570fe4f213" -"checksum zeroize_derive 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afd1469e4bbca3b96606d26ba6e9bd6d3aed3b1299c82b92ec94377d22d78dbc" +"checksum zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4090487fa66630f7b166fba2bbb525e247a5449f41c468cc1d98f8ae6ac03120" +"checksum zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" +"checksum zeroize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdc979d9b5ead18184c357c4d8a3f81b579aae264e32507223032e64715462d3" +"checksum zstd 0.4.28+zstd.1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4e716acaad66f2daf2526f37a1321674a8814c0b37a366ebe6c97a699f85ddc" +"checksum zstd-safe 1.4.13+zstd.1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bfe4d3b26a0790201848865663e8ffabf091e126e548bc9710ccfa95621ece48" +"checksum zstd-sys 1.4.13+zstd.1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fadc8ebe858f056ab82dffb9d93850b841603bdf663db7cf5e3dbd7f34cc55b2" diff --git a/Cargo.toml b/Cargo.toml index be6c89c2b7b1002b39511cc7423d57ea89578027..bdc0d8737518c8a8c8445dbf2b2e09dd47c48d74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,36 +1,23 @@ -[[bin]] -name = "substrate" -path = "node/src/main.rs" - -[package] -name = "substrate" -version = "2.0.0" -authors = ["Parity Technologies "] -build = "build.rs" -edition = "2018" - -[dependencies] -cli = { package = "node-cli", path = "node/cli" } -futures = "0.1" -ctrlc = { version = "3.0", features = ["termination"] } - -[build-dependencies] -vergen = "3" - [workspace] members = [ + "core/authority-discovery", "core/application-crypto", + "core/chain-spec", + "core/chain-spec/derive", "core/cli", "core/client", "core/client/db", + "core/client/header-metadata", "core/consensus/aura", "core/consensus/babe", "core/consensus/common", "core/consensus/rhd", "core/consensus/slots", "core/consensus/uncles", + "core/consensus/pow", "core/executor", "core/executor/runtime-test", + "core/externalities", "core/finality-grandpa", "core/finality-grandpa/primitives", "core/inherents", @@ -40,14 +27,17 @@ members = [ "core/panic-handler", "core/primitives", "core/rpc", + "core/rpc/primitives", "core/rpc-servers", "core/serializer", "core/service", "core/service/test", "core/session", "core/sr-api-macros", + "core/sr-arithmetic", "core/sr-io", "core/sr-primitives", + "core/sr-staking-primitives", "core/sr-sandbox", "core/sr-std", "core/sr-version", @@ -62,6 +52,7 @@ members = [ "core/utils/fork-tree", "core/utils/wasm-builder", "core/utils/wasm-builder-runner", + "core/wasm-interface", "srml/support", "srml/support/procedural", "srml/support/procedural/tools", @@ -72,40 +63,50 @@ members = [ "srml/aura", "srml/balances", "srml/contracts", + "srml/contracts/rpc", "srml/collective", "srml/democracy", "srml/elections", + "srml/elections-phragmen", "srml/example", "srml/executive", "srml/finality-tracker", "srml/generic-asset", "srml/grandpa", "srml/im-online", + "srml/authority-discovery", "srml/indices", "srml/membership", "srml/metadata", + "srml/nicks", + "srml/offences", + "srml/randomness-collective-flip", + "srml/scored-pool", "srml/session", "srml/staking", + "srml/staking/reward-curve", "srml/sudo", "srml/system", + "srml/system/rpc", "srml/timestamp", "srml/treasury", + "srml/transaction-payment", + "srml/transaction-payment/rpc", + "srml/utility", + "srml/evm", "node/cli", "node/executor", "node/primitives", - "node/runtime", + "node/rpc", "node/rpc-client", + "node/runtime", + "node/testing", "node-template", "subkey", "test-utils/chain-spec-builder", ] -[badges] -travis-ci = { repository = "paritytech/substrate", branch = "master" } -maintenance = { status = "actively-developed" } -is-it-maintained-issue-resolution = { repository = "paritytech/substrate" } -is-it-maintained-open-issues = { repository = "paritytech/substrate" } - [profile.release] # Substrate runtime requires unwinding. panic = "unwind" + diff --git a/Dockerfile b/Dockerfile index 0271db8d1461d7a8c58fb52f9f6306e5ca833e2e..7cba85c544afc2c8cc1ff56401b2172a01d30364 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,20 +5,21 @@ FROM phusion/baseimage:0.10.2 as builder LABEL maintainer="chevdor@gmail.com" LABEL description="This is the build stage for Substrate. Here we create the binary." +ENV DEBIAN_FRONTEND=noninteractive + ARG PROFILE=release WORKDIR /substrate COPY . /substrate RUN apt-get update && \ - apt-get dist-upgrade -y && \ + apt-get dist-upgrade -y -o Dpkg::Options::="--force-confold" && \ apt-get install -y cmake pkg-config libssl-dev git clang RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \ export PATH="$PATH:$HOME/.cargo/bin" && \ rustup toolchain install nightly && \ rustup target add wasm32-unknown-unknown --toolchain nightly && \ - cargo install --git https://github.com/alexcrichton/wasm-gc && \ rustup default nightly && \ rustup default stable && \ cargo build "--$PROFILE" diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 9b368f3f04d4c60d5f7bdfcf83eaa323340ab181..9755fa0e40ff9bcef1003d0933b174cc1adee06b 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -15,6 +15,7 @@ Before you submitting, please check that: - Any panickers have a proof or removed. - [ ] You bumped the runtime version if there are breaking changes in the **runtime**. - [ ] You updated any rustdocs which may have changed +- [ ] Has the PR altered the external API or interfaces used by Polkadot? Do you have the corresponding Polkadot PR ready? After you've read this notice feel free to remove it. Thank you! diff --git a/README.adoc b/README.adoc index aaab6df3cc2f2cafcb730b1001e85bd4375a5e42..5caa3f932b23e0e38cd7171d73463e59446cc927 100644 --- a/README.adoc +++ b/README.adoc @@ -20,13 +20,13 @@ See also https://www.parity.io/what-is-substrate/. Substrate is still an early stage project, and while it has already been used as the basis of major projects like Polkadot, using it is still a significant undertaking. In particular, you should have a good knowledge of blockchain concepts and basic cryptography. Terminology like header, block, client, hash, transaction and signature should be familiar. At present you will need a working knowledge of Rust to be able to do anything interesting (though eventually, we aim for this not to be the case). -Substrate is designed to be used in one of three ways: +Substrate is designed for use in one of three ways: -1. Trivial: By running the Substrate binary `substrate` and configuring it with a genesis block that includes the current demonstration runtime. In this case, you just build Substrate, configure a JSON file and launch your own blockchain. This affords you the least amount of customisability, primarily allowing you to change the genesis parameters of the various included runtime modules such as balances, staking, block-period, fees and governance. +**1. Trivial**: By running the Substrate binary `substrate` and configuring it with a genesis block that includes the current demonstration runtime. In this case, you just build Substrate, configure a JSON file, and launch your own blockchain. This affords you the least amount of customizability, primarily allowing you to change the genesis parameters of the various included runtime modules such as balances, staking, block-period, fees, and governance. -2. Modular: By hacking together modules from the Substrate Runtime Module Library into a new runtime and possibly altering or reconfiguring the Substrate client's block authoring logic. This affords you a very large amount of freedom over your own blockchain's logic, letting you change datatypes, add or remove modules and, crucially, add your own modules. Much can be changed without touching the block-authoring logic (since it is generic). If this is the case, then the existing Substrate binary can be used for block authoring and syncing. If the block authoring logic needs to be tweaked, then a new altered block-authoring binary must be built as a separate project and used by validators. This is how the Polkadot relay chain is built and should suffice for almost all circumstances in the near to mid-term. +**2. Modular**: By hacking together modules from the Substrate Runtime Module Library (SRML) into a new runtime and possibly altering or reconfiguring the Substrate client's block authoring logic. This affords you a very large amount of freedom over your blockchain's logic, letting you change datatypes, add or remove modules, and crucially, add your own modules. Much can be changed without touching the block authoring logic (since it is generic). If this is the case, then the existing Substrate binary can be used for block authoring and syncing. If the block authoring logic needs to be tweaked, then a new, altered block authoring binary must be built as a separate project and used by validators. This is how the Polkadot relay chain is built and should suffice for almost all circumstances in the near to mid-term. -3. Generic: The entire Substrate Runtime Module Library can be ignored and the entire runtime designed and implemented from scratch. If desired, this can be done in a language other than Rust, providing it can target WebAssembly. If the runtime can be made to be compatible with the existing client's block authoring logic, then you can simply construct a new genesis block from your Wasm blob and launch your chain with the existing Rust-based Substrate client. If not, then you'll need to alter the client's block authoring logic accordingly. This is probably a useless option for most projects right now, but provides complete flexibility allowing for a long-term far-reaching upgrade path for the Substrate paradigm. +**3. Generic**: The entire SRML can be ignored and the entire runtime designed and implemented from scratch. If desired, this can be done in a language other than Rust, provided it can target WebAssembly. If the runtime can be made compatible with the existing client's block authoring logic, then you can simply construct a new genesis block from your Wasm blob and launch your chain with the existing Rust-based Substrate client. If not, then you'll need to alter the client's block authoring logic accordingly. This is probably a useless option for most projects right now, but provides complete flexibility allowing for a long-term, far-reaching upgrade path for the Substrate paradigm. === The Basics of Substrate @@ -133,7 +133,7 @@ First let's get a template chainspec that you can edit. We'll use the "staging" substrate build-spec --chain=staging > ~/chainspec.json ---- -Now, edit `~/chainspec.json` in your editor. There are a lot of individual fields for each module, and one very large one which contains the Webassembly code blob for this chain. The easiest field to edit is the block `period`. Change it to 10 (seconds): +Now, edit `~/chainspec.json` in your editor. There are a lot of individual fields for each module, and one very large one which contains the WebAssembly code blob for this chain. The easiest field to edit is the block `period`. Change it to 10 (seconds): [source, json] ---- @@ -160,7 +160,7 @@ It won't do much until you start producing blocks though, so to do that you'll n [source, shell] ---- -substrate --chain ~/mychain.json --validator --key ... +substrate --chain ~/mychain.json --validator ---- You can distribute `mychain.json` so that everyone can synchronize and (depending on your authorities list) validate on your chain. @@ -184,7 +184,6 @@ curl https://sh.rustup.rs -sSf | sh rustup update nightly rustup target add wasm32-unknown-unknown --toolchain nightly rustup update stable -cargo install --git https://github.com/alexcrichton/wasm-gc ---- You will also need to install the following packages: @@ -193,6 +192,11 @@ You will also need to install the following packages: [source, shell] sudo apt install cmake pkg-config libssl-dev git clang libclang-dev +- Linux on ARM: +`rust-lld` is required for linking wasm, but is missing on non Tier 1 platforms. +So, use this https://github.com/Plume-org/Plume/blob/master/script/wasm-deps.sh[script] +to build `lld` and create the symlink `/usr/bin/rust-lld` to the build binary. + - Mac: [source, shell] brew install cmake pkg-config openssl git llvm @@ -226,13 +230,9 @@ If you are trying to set up Substrate on Windows, you should do the following: rustup update stable rustup target add wasm32-unknown-unknown --toolchain nightly -4. Next, you install wasm-gc, which is used to slim down Wasm files: - - cargo install --git https://github.com/alexcrichton/wasm-gc --force +4. Then, you need to install LLVM: https://releases.llvm.org/download.html -5. Then, you need to install LLVM: https://releases.llvm.org/download.html - -6. Next, you need to install OpenSSL, which we will do with `vcpkg`: +5. Next, you need to install OpenSSL, which we will do with `vcpkg`: mkdir \Tools cd \Tools @@ -241,14 +241,14 @@ If you are trying to set up Substrate on Windows, you should do the following: .\bootstrap-vcpkg.bat .\vcpkg.exe install openssl:x64-windows-static -7. After, you need to add OpenSSL to your System Variables: +6. After, you need to add OpenSSL to your System Variables. Note that in order for the following commands to work, you need to use Windows Powershell: $env:OPENSSL_DIR = 'C:\Tools\vcpkg\installed\x64-windows-static' $env:OPENSSL_STATIC = 'Yes' [System.Environment]::SetEnvironmentVariable('OPENSSL_DIR', $env:OPENSSL_DIR, [System.EnvironmentVariableTarget]::User) [System.Environment]::SetEnvironmentVariable('OPENSSL_STATIC', $env:OPENSSL_STATIC, [System.EnvironmentVariableTarget]::User) -8. Finally, you need to install `cmake`: https://cmake.org/download/ +7. Finally, you need to install `cmake`: https://cmake.org/download/ ==== Shared Steps @@ -277,13 +277,13 @@ Or just run the tests of a specific package (i.e. `cargo test -p srml-assets`) You can start a development chain with: [source, shell] -cargo run \-- --dev +cargo run --release -- --dev -Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run \-- --dev`. +Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run --release \-- --dev`. -If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain specification that have been endowed with a testnet DOTs. We'll give each node a name and expose them so they are listed on link:https://telemetry.polkadot.io/#/Local%20Testnet[Telemetry] . You'll need two terminals windows open. +If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain specification that have been endowed with a testnet DOTs. We'll give each node a name and expose them so they are listed on link:https://telemetry.polkadot.io/#/Local%20Testnet[Telemetry]. You'll need two terminal windows open. -We'll start Alice's substrate node first on default TCP port 30333 with her chain database stored locally at `/tmp/alice`. The Bootnode ID of her node is `QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR`, which is generated from the `--node-key` value that we specify below: +We'll start Alice's Substrate node first on default TCP port 30333 with her chain database stored locally at `/tmp/alice`. The Bootnode ID of her node is `QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR`, which is generated from the `--node-key` value that we specify below: [source, shell] cargo run --release \-- \ @@ -294,7 +294,7 @@ cargo run --release \-- \ --telemetry-url ws://telemetry.polkadot.io:1024 \ --validator -In the second terminal, we'll run the following to start Bob's substrate node on a different TCP port of 30334, and with his chain database stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect his node to Alice's Bootnode ID on TCP port 30333: +In the second terminal, we'll run the following to start Bob's Substrate node on a different TCP port of 30334, and with his chain database stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect his node to Alice's Bootnode ID on TCP port 30333: [source, shell] cargo run --release \-- \ @@ -321,6 +321,10 @@ we support multiple environment variables: * `TRIGGER_WASM_BUILD` - Can be set to trigger a WASM build. On subsequent calls the value of the variable needs to change. As WASM builder instructs `cargo` to watch for file changes this environment variable should only be required in certain circumstances. +* `WASM_TARGET_DIRECTORY` - Will copy any build WASM binary to the given directory. The path needs + to be absolute. +* `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. +* `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will @@ -333,13 +337,13 @@ Flaming Fir is the new testnet for Substrate master (2.0) to test the latest dev Since Flaming Fir is targeting the master branch we make absolutely no guarantees of stability and/or persistence of the network. We might reset the chain at any time if it is necessary to deploy new changes. Currently, the validators are running with a client built from `d013bd900`, if you build from this commit you should be able to successfully sync, later commits may not work as new breaking changes may be introduced in master. -Latest known working version: `d013bd900` +Latest known working version: `a2a0eb5398d6223e531455b4c155ef053a4a3a2b` [source, shell] ---- git clone https://github.com/paritytech/substrate.git cd substrate -git checkout -b flaming-fir d013bd900 +git checkout -b flaming-fir a2a0eb5398d6223e531455b4c155ef053a4a3a2b ---- You can run the tests if you like: @@ -378,12 +382,45 @@ git checkout -b v1.0 origin/v1.0 You can then follow the same steps for building and running as described above in <>. +== Key management + +Keys in Substrate are stored in the keystore in the file system. To store keys into this keystore, +you need to use one of the two provided RPC calls. If your keys are encrypted or should be encrypted +by the keystore, you need to provide the key using one of the cli arguments `--password`, +`--password-interactive` or `--password-filename`. + +=== Recommended RPC call + +For most users who want to run a validator node, the `author_rotateKeys` RPC call is sufficient. +The RPC call will generate `N` Session keys for you and return their public keys. `N` is the number +of session keys configured in the runtime. The output of the RPC call can be used as input for the +`session::set_keys` transaction. + +``` +curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_rotateKeys", "id":1 }' localhost:9933 +``` + +=== Advanced RPC call + +If the Session keys need to match a fixed seed, they can be set individually key by key. The RPC call +expects the key seed and the key type. The key types supported by default in Substrate are listed +https://github.com/paritytech/substrate/blob/master/core/primitives/src/crypto.rs#L767[here], but the +user can declare any key type. + +``` +curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "method":"author_insertKey", "params":["KEY_TYPE", "SEED", "PUBLIC"],"id":1 }' localhost:9933 +``` + +`KEY_TYPE` - needs to be replaced with the 4-character key type identifier. +`SEED` - is the seed of the key. +`PUBLIC` - public key for the given key. + == Documentation === Viewing documentation for Substrate packages You can generate documentation for a Substrate Rust package and have it automatically open in your web browser using https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo[rustdoc with Cargo], -(of the The Rustdoc Book), by running the the following command: +(of the The Rustdoc Book), by running the following command: ``` cargo doc --package --open diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000000000000000000000000000000000..b850e5462e2a8368c1e58a417eb9cef229b49537 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,101 @@ +# Security Policy + +Parity Technologies is committed to resolving security vulnerabilities in our software quickly and carefully. We take the necessary steps to minimize risk, provide timely information, and deliver vulnerability fixes and mitigations required to address security issues. + +## Reporting a Vulnerability + +Security vulnerabilities in Parity software should be reported by email to security@parity.io. If you think your report might be eligible for the Parity Bug Bounty Program, your email should be send to bugbounty@parity.io. + +Your report should include the following: + +- your name +- description of the vulnerability +- attack scenario (if any) +- components +- reproduction +- other details + +Try to include as much information in your report as you can, including a description of the vulnerability, its potential impact, and steps for reproducing it. Be sure to use a descriptive subject line. + +You'll receive a response to your email within two business days indicating the next steps in handling your report. We encourage finders to use encrypted communication channels to protect the confidentiality of vulnerability reports. You can encrypt your report using our public key. This key is [on MIT's key server](https://pgp.mit.edu/pks/lookup?op=get&search=0x5D0F03018D07DE73) server and reproduced below. + +After the initial reply to your report, our team will endeavor to keep you informed of the progress being made towards a fix. These updates will be sent at least every five business days. + +Thank you for taking the time to responsibly disclose any vulnerabilities you find. + +## Responsible Investigation and Reporting + +Responsible investigation and reporting includes, but isn't limited to, the following: + +- Don't violate the privacy of other users, destroy data, etc. +- Don’t defraud or harm Parity Technologies Ltd or its users during your research; you should make a good faith effort to not interrupt or degrade our services. +- Don't target our physical security measures, or attempt to use social engineering, spam, distributed denial of service (DDOS) attacks, etc. +- Initially report the bug only to us and not to anyone else. +- Give us a reasonable amount of time to fix the bug before disclosing it to anyone else, and give us adequate written warning before disclosing it to anyone else. +- In general, please investigate and report bugs in a way that makes a reasonable, good faith effort not to be disruptive or harmful to us or our users. Otherwise your actions might be interpreted as an attack rather than an effort to be helpful. + +## Bug Bounty Program + +Our Bug Bounty Program allows us to recognise and reward members of the Parity community for helping us find and address significant bugs, in accordance with the terms of the Parity Bug Bounty Program. A detailed description on eligibility, rewards, legal information and terms & conditions for contributors can be found on [our website](https://paritytech.io/bug-bounty.html). + + + + + + +## Plaintext PGP Key + +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBF0vHwQBEADKui4qAo4bzdzRhMm+uhUpYGf8jjjmET3zJ8kKQIpp6JTsV+HJ +6m1We0QYeMRXoOYH1xVHBf2zNCuHS0nSQdUCQA7SHWsPB05STa2hvlR7fSdQnCCp +gnLOJWXvvedlRDIAhvqI6cwLdUlXgVSKEwrwmrpiBhh4NxI3qX+LyIa+Ovkchu2S +d/YCnE4GqojSGRfJYiGwe2N+sF7OfaoKhQuTrtdDExHrMU4cWnTXW2wyxTr4xkj9 +jS2WeLVZWflvkDHT8JD9N6jNxBVEF/Qvjk83zI0kCOzkhek8x+YUgfLq3/rHOYbX +3pW21ccHYPacHjHWvKE+xRebjeEhJ4KxKHfCVjQcxybwDBqDka1AniZt4CQ7UORf +MU/ue2oSZ9nNg0uMdb/0AbQPZ04OlMcYPAPWzFL08nVPox9wT9uqlL6JtcOeC90h +oOeDmfgwmjMmdwWTRgt9qQjcbgXzVvuAzIGbzj1X3MdLspWdHs/d2+US4nji1TkN +oYIW7vE+xkd3aB+NZunIlm9Rwd/0mSgDg+DaNa5KceOLhq0/qKgcXC/RRU29I8II +tusRoR/oesGJGYTjh4k6PJkG+nvDPsoQrwYT44bhnniS1xYkxWYXF99JFI7LgMdD +e1SgKeIDVpvm873k82E6arp5655Wod1XOjaXBggCwFp84eKcEZEN+1qEWwARAQAB +tClQYXJpdHkgU2VjdXJpdHkgVGVhbSA8c2VjdXJpdHlAcGFyaXR5LmlvPokCVAQT +AQoAPhYhBJ1LK264+XFW0ZZpqf8IEtSRuWeYBQJdLx8EAhsDBQkDwmcABQsJCAcC +BhUKCQgLAgQWAgMBAh4BAheAAAoJEP8IEtSRuWeYL84QAI6NwnwS561DWYYRAd4y +ocGPr3CnwFSt1GjkSkRy3B+tMhzexBg1y7EbLRUefIrO4LwOlywtRk8tTRGgEI4i +5xRLHbOkeolfgCFSpOj5d8cMKCt5HEIv18hsv6dkrzlSYA5NLX/GRBEh3F/0sGny +vCXapfxa1cx72sU7631JBK7t2Tf+MfwxdfyFZ9TI9WdtP5AfVjgTkIVkEDFcZPTc +n3CYXqTYFIBCNUD8LP4iTi3xUt7pTGJQQoFT8l15nJCgzRYQ+tXpoTRlf+/LtXmw +6iidPV87E06jHdK9666rBouIabAtx7i0/4kwo+bSZ8DiSKRUaehiHGd212HSEmdF +jxquWE4pEzoUowYznhSIfR+WWIqRBHxEYarP4m98Hi+VXZ7Fw1ytzO8+BAKnLXnj +2W2+T9qJks5gqVEoaWNnqpvya6JA11QZvZ0w7Om2carDc2ILNm2Xx9J0mRUye8P0 +KxcgqJuKNGFtugebQAsXagkxOKsdKna1PlDlxEfTf6AgI3ST8qSiMAwaaIMB/REF +VKUapGoslQX4tOCjibI2pzEgE//D8NAaSVu2A9+BUcFERdZRxsI7fydIXNeZ2R46 +N2qfW+DP3YR/14QgdRxDItEavUoE1vByRXwIufKAkVemOZzIoFXKFsDeXwqTVW5i +6CXu6OddZ3QHDiT9TEbRny4QuQINBF0vKCwBEACnP5J7LEGbpxNBrPvGdxZUo0YA +U8RgeKDRPxJTvMo27V1IPZGaKRCRq8LBfg/eHhqZhQ7SLJBjBljd8kuT5dHDBTRe +jE1UIOhmnlSlrEJjAmpVO08irlGpq1o+8mGcvkBsR0poCVjeNeSnwYfRnR+c3GK5 +Er6/JRqfN4mJvnEC9/Pbm6C7ql6YLKxC3yqzF97JL5brbbuozrW7nixY/yAI8619 +VlBIMP7PAUbGcnSQyuV5b/Wr2Sgr6NJclnNSLjh2U9/Du6w/0tDGlMBts8HjRnWJ +BXbkTdQKCTaqgK68kTKSiN1/x+lynxHC2AavMpH/08Kopg2ZCzJowMKIgcB+4Z/I +DJKZWHWKumhaZMGXcWgzgcByog9IpamuROEZFJNEUAFf7YIncEckPSif4looiOdS +VurKZGvYXXaGSsZbGgHxI5CWu7ZxMdLBLvtOcCYmRQrG+g/h+PGU5BT0bNAfNTkm +V3/n1B/TWbpWRmB3AwT2emQivXHkaubGI0VivhaO43AuI9JWoqiMqFtxbuTeoxwD +xlu2Dzcp0v+AR4T5cIG9D5/+yiPc25aIY7cIKxuNFHIDL4td5fwSGC7vU6998PIG +2Y48TGBnw7zpEfDfMayqAeBjX0YU6PTNsvS5O6bP3j4ojTOUYD7Z8QdCvgISDID3 +WMGAdmSwmCRvsQ/OJwARAQABiQI8BBgBCgAmFiEEnUsrbrj5cVbRlmmp/wgS1JG5 +Z5gFAl0vKCwCGwwFCQB2pwAACgkQ/wgS1JG5Z5hdbw//ZqR+JcWm59NUIHjauETJ +sYDYhcAfa3txTacRn5uPz/TQiTd7wZ82+G8Et0ZnpEHy6eWyBqHpG0hiPhFBzxjY +nhjHl8jJeyo2mQIVJhzkL58BHBZk8WM2TlaU7VxZ6TYOmP2y3qf6FD6mCcrQ4Fml +E9f0lyVUoI/5Zs9oF0izRk8vkwaY3UvLM7XEY6nM8GnFG8kaiZMYmx26Zo7Uz31G +7EGGZFsrVDXfNhSJyz79Gyn+Lx9jOTdoR0sH/THYIIosE83awMGE6jKeuDYTbVWu ++ZtHQef+pRteki3wvNLJK+kC1y3BtHqDJS9Lqx0s8SCiVozlC+fZfC9hCtU7bXJK +0UJZ4qjSvj6whzfaNgOZAqJpmwgOnd8W/3YJk1DwUeX98FcU38MR23SOkx2EDdDE +77Kdu62vTs/tLmOTuyKBvYPaHaYulYjQTxurG+o8vhHtaL87ARvuq+83dj+nO5z3 +5O9vkcVJYWjOEnJe7ZvCTxeLJehpCmHIbyUuDx5P24MWVbyXOxIlxNxTqlub5GlW +rQF6Qsa/0k9TRk7Htbct6fAA0/VahJS0g096MrTH8AxBXDNE8lIoNeGikVlaxK9Z +S+aannlWYIJymZ4FygIPPaRlzhAoXBuJd8OaR5giC7dS1xquxKOiQEXTGsLeGFaI +BZYiIhW7GG4ozvKDqyNm4eg= +=yKcB +-----END PGP PUBLIC KEY BLOCK----- +``` diff --git a/ci/check_for_exit.sh b/ci/check_for_exit.sh new file mode 100755 index 0000000000000000000000000000000000000000..c5a54eb83b80051e1a4186626ecb73146899ff74 --- /dev/null +++ b/ci/check_for_exit.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# Script that checks that a node exits after `SIGINT` was send. + +set -e + +cargo build --release +./target/release/substrate --dev & +PID=$! + +# Let the chain running for 60 seconds +sleep 60 + +# Send `SIGINT` and give the process 30 seconds to end +kill -INT $PID +timeout 30 tail --pid=$PID -f /dev/null diff --git a/core/application-crypto/Cargo.toml b/core/application-crypto/Cargo.toml index 6d39b12653fa51e5237dc57045948ca7519ed751..663ca79d77045963c2d9dbed420688046e9b367a 100644 --- a/core/application-crypto/Cargo.toml +++ b/core/application-crypto/Cargo.toml @@ -8,9 +8,9 @@ description = "Provides facilities for generating application specific crypto wr [dependencies] primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } rstd = { package = "sr-std", path = "../sr-std", default-features = false } -rio = { package = "sr-io", path = "../sr-io", default-features = false } +runtime-io = { package = "sr-io", path = "../sr-io", default-features = false } [dev-dependencies] test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } @@ -18,4 +18,11 @@ sr-primitives = { path = "../sr-primitives" } [features] default = [ "std" ] -std = [ "primitives/std", "codec/std", "serde", "rstd/std", "rio/std" ] +std = [ "full_crypto", "primitives/std", "codec/std", "serde", "rstd/std", "runtime-io/std" ] + +# This feature enables all crypto primitives for `no_std` builds like microcontrollers +# or Intel SGX. +# For the regular wasm runtime builds this should not be used. +full_crypto = [ + "primitives/full_crypto" +] \ No newline at end of file diff --git a/core/application-crypto/src/ed25519.rs b/core/application-crypto/src/ed25519.rs index 6c5458492b6b8654201cfeeb7c268b2609e35834..bd785acadba46d53e0ab53f45265102ab26efe9c 100644 --- a/core/application-crypto/src/ed25519.rs +++ b/core/application-crypto/src/ed25519.rs @@ -21,39 +21,43 @@ use crate::{RuntimePublic, KeyTypeId}; pub use primitives::ed25519::*; mod app { - use crate::key_types::ED25519; + use primitives::testing::ED25519; crate::app_crypto!(super, ED25519); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } } pub use app::Public as AppPublic; pub use app::Signature as AppSignature; -#[cfg(feature="std")] +#[cfg(feature = "full_crypto")] pub use app::Pair as AppPair; impl RuntimePublic for Public { type Signature = Signature; fn all(key_type: KeyTypeId) -> crate::Vec { - rio::ed25519_public_keys(key_type) + runtime_io::ed25519_public_keys(key_type) } fn generate_pair(key_type: KeyTypeId, seed: Option<&str>) -> Self { - rio::ed25519_generate(key_type, seed) + runtime_io::ed25519_generate(key_type, seed) } fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { - rio::ed25519_sign(key_type, self, msg) + runtime_io::ed25519_sign(key_type, self, msg.as_ref()) } fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { - rio::ed25519_verify(&signature, msg.as_ref(), self) + runtime_io::ed25519_verify(&signature, msg.as_ref(), self) } } #[cfg(test)] mod tests { use sr_primitives::{generic::BlockId, traits::ProvideRuntimeApi}; - use primitives::{testing::KeyStore, crypto::Pair, traits::BareCryptoStore as _}; + use primitives::{testing::{KeyStore, ED25519}, crypto::Pair}; use test_client::{ TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, runtime::{TestAPI, app_crypto::ed25519::{AppPair, AppPublic}}, @@ -67,7 +71,7 @@ mod tests { .test_ed25519_crypto(&BlockId::Number(0)) .expect("Tests `ed25519` crypto."); - let key_pair = keystore.read().ed25519_key_pair(crate::key_types::ED25519, &public.as_ref()) + let key_pair = keystore.read().ed25519_key_pair(ED25519, &public.as_ref()) .expect("There should be at a `ed25519` key in the keystore for the given public key."); assert!(AppPair::verify(&signature, "ed25519", &AppPublic::from(key_pair.public()))); diff --git a/core/application-crypto/src/lib.rs b/core/application-crypto/src/lib.rs index d9bff822eedee4ecc9e99f4e0c4d9393ec6c7577..66214ce444437c8048f66b2291048f9867b41b01 100644 --- a/core/application-crypto/src/lib.rs +++ b/core/application-crypto/src/lib.rs @@ -21,9 +21,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #[doc(hidden)] -pub use primitives::{self, crypto::{CryptoType, Public, Derive, IsWrappedBy, Wraps}}; +pub use primitives::{self, crypto::{CryptoType, Public, Derive, IsWrappedBy, Wraps}, RuntimeDebug}; #[doc(hidden)] -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub use primitives::crypto::{SecretStringError, DeriveJunction, Ss58Codec, Pair}; pub use primitives::{crypto::{KeyTypeId, key_types}}; @@ -50,17 +50,43 @@ pub use traits::*; /// // of value `b"fuba"`. /// app_crypto!(ed25519, KeyTypeId(*b"_uba")); /// ``` +#[cfg(feature = "full_crypto")] +#[macro_export] +macro_rules! app_crypto { + ($module:ident, $key_type:expr) => { + $crate::app_crypto_public_full_crypto!($module::Public, $key_type); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type); + $crate::app_crypto_signature_full_crypto!($module::Signature, $key_type); + $crate::app_crypto_signature_common!($module::Signature, $key_type); + $crate::app_crypto_pair!($module::Pair, $key_type); + }; +} + +/// Declares Public, Pair, Signature types which are functionally equivalent to `$pair`, but are new +/// Application-specific types whose identifier is `$key_type`. +/// +/// ```rust +///# use substrate_application_crypto::{app_crypto, wrap, ed25519, KeyTypeId}; +/// // Declare a new set of crypto types using Ed25519 logic that identifies as `KeyTypeId` +/// // of value `b"fuba"`. +/// app_crypto!(ed25519, KeyTypeId(*b"_uba")); +/// ``` +#[cfg(not(feature = "full_crypto"))] #[macro_export] macro_rules! app_crypto { ($module:ident, $key_type:expr) => { - #[cfg(feature="std")] - $crate::app_crypto!($module::Pair, $module::Public, $module::Signature, $key_type); - #[cfg(not(feature="std"))] - $crate::app_crypto!($module::Public, $module::Signature, $key_type); + $crate::app_crypto_public_not_full_crypto!($module::Public, $key_type); + $crate::app_crypto_public_common!($module::Public, $module::Signature, $key_type); + $crate::app_crypto_signature_not_full_crypto!($module::Signature, $key_type); + $crate::app_crypto_signature_common!($module::Signature, $key_type); }; - ($pair:ty, $public:ty, $sig:ty, $key_type:expr) => { - $crate::app_crypto!($public, $sig, $key_type); +} +/// Declares Pair type which is functionally equivalent to `$pair`, but is new +/// Application-specific type whose identifier is `$key_type`. +#[macro_export] +macro_rules! app_crypto_pair { + ($pair:ty, $key_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $pair crypto; this has no specific App. #[derive(Clone)] @@ -71,16 +97,18 @@ macro_rules! app_crypto { type Pair = Pair; } - #[cfg(feature = "std")] impl $crate::Pair for Pair { type Public = Public; type Seed = <$pair as $crate::Pair>::Seed; type Signature = Signature; type DeriveError = <$pair as $crate::Pair>::DeriveError; + + #[cfg(feature = "std")] fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed) { let r = <$pair>::generate_with_phrase(password); (Self(r.0), r.1, r.2) } + #[cfg(feature = "std")] fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Self, Self::Seed), $crate::SecretStringError> { @@ -88,22 +116,13 @@ macro_rules! app_crypto { } fn derive< Iter: Iterator - >(&self, path: Iter) -> Result { - self.0.derive(path).map(Self) + >(&self, path: Iter, seed: Option) -> Result<(Self, Option), Self::DeriveError> { + self.0.derive(path, seed).map(|x| (Self(x.0), x.1)) } fn from_seed(seed: &Self::Seed) -> Self { Self(<$pair>::from_seed(seed)) } fn from_seed_slice(seed: &[u8]) -> Result { <$pair>::from_seed_slice(seed).map(Self) } - fn from_standard_components< - I: Iterator - >( - seed: &str, - password: Option<&str>, - path: I, - ) -> Result { - <$pair>::from_standard_components::(seed, password, path).map(Self) - } fn sign(&self, msg: &[u8]) -> Self::Signature { Signature(self.0.sign(msg)) } @@ -124,6 +143,7 @@ macro_rules! app_crypto { fn public(&self) -> Self::Public { Public(self.0.public()) } fn to_raw_vec(&self) -> Vec { self.0.to_raw_vec() } } + impl $crate::AppKey for Pair { type UntypedGeneric = $pair; type Public = Public; @@ -131,21 +151,81 @@ macro_rules! app_crypto { type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; } + impl $crate::AppPair for Pair { type Generic = $pair; } }; - ($public:ty, $sig:ty, $key_type:expr) => { +} + +/// Declares Public type which is functionally equivalent to `$public`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used together with `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_public_full_crypto { + ($public:ty, $key_type:expr) => { + $crate::wrap!{ + /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. + #[derive( + Clone, Default, Eq, PartialEq, Ord, PartialOrd, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + #[derive(Hash)] + pub struct Public($public); + } + + impl $crate::CryptoType for Public { + type Pair = Pair; + } + + impl $crate::AppKey for Public { + type UntypedGeneric = $public; + type Public = Public; + type Pair = Pair; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; + } + } +} + +/// Declares Public type which is functionally equivalent to `$public`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used without `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_public_not_full_crypto { + ($public:ty, $key_type:expr) => { $crate::wrap!{ /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. #[derive( - Clone, Default, Eq, PartialEq, Ord, PartialOrd, $crate::codec::Encode, + Clone, Default, Eq, PartialEq, Ord, PartialOrd, + $crate::codec::Encode, $crate::codec::Decode, + $crate::RuntimeDebug, )] - #[cfg_attr(feature = "std", derive(Debug, Hash))] pub struct Public($public); } + impl $crate::CryptoType for Public {} + + impl $crate::AppKey for Public { + type UntypedGeneric = $public; + type Public = Public; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; + } + } +} + +/// Declares Public type which is functionally equivalent to `$public`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// For full functionality, app_crypto_public_(not)_full_crypto! must be called too. +#[macro_export] +macro_rules! app_crypto_public_common { + ($public:ty, $sig:ty, $key_type:expr) => { impl $crate::Derive for Public { #[cfg(feature = "std")] fn derive>(&self, @@ -190,29 +270,16 @@ macro_rules! app_crypto { fn as_mut(&mut self) -> &mut [u8] { self.0.as_mut() } } - impl $crate::CryptoType for Public { - #[cfg(feature="std")] - type Pair = Pair; - } - impl $crate::Public for Public { fn from_slice(x: &[u8]) -> Self { Self(<$public>::from_slice(x)) } } - impl $crate::AppKey for Public { - type UntypedGeneric = $public; - type Public = Public; - #[cfg(feature="std")] - type Pair = Pair; - type Signature = Signature; - const ID: $crate::KeyTypeId = $key_type; - } - impl $crate::AppPublic for Public { type Generic = $public; } impl $crate::RuntimeAppPublic for Public where $public: $crate::RuntimePublic { + const ID: $crate::KeyTypeId = $key_type; type Signature = Signature; fn all() -> $crate::Vec { @@ -235,37 +302,84 @@ macro_rules! app_crypto { <$public as $crate::RuntimePublic>::verify(self.as_ref(), msg, &signature.as_ref()) } } + } +} +/// Declares Signature type which is functionally equivalent to `$sig`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used together with `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_signature_full_crypto { + ($sig:ty, $key_type:expr) => { $crate::wrap! { /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. - #[derive(Clone, Default, Eq, PartialEq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug, Hash))] + #[derive(Clone, Default, Eq, PartialEq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + #[derive(Hash)] pub struct Signature($sig); } - impl $crate::Deref for Signature { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { self.0.as_ref() } + impl $crate::CryptoType for Signature { + type Pair = Pair; } - impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { self.0.as_ref() } + impl $crate::AppKey for Signature { + type UntypedGeneric = $sig; + type Public = Public; + type Pair = Pair; + type Signature = Signature; + const ID: $crate::KeyTypeId = $key_type; } + } +} - impl $crate::CryptoType for Signature { - #[cfg(feature="std")] - type Pair = Pair; +/// Declares Signature type which is functionally equivalent to `$sig`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// can only be used without `full_crypto` feature +/// For full functionality, app_crypto_public_common! must be called too. +#[macro_export] +macro_rules! app_crypto_signature_not_full_crypto { + ($sig:ty, $key_type:expr) => { + $crate::wrap! { + /// A generic `AppPublic` wrapper type over $public crypto; this has no specific App. + #[derive(Clone, Default, Eq, PartialEq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + pub struct Signature($sig); } + + impl $crate::CryptoType for Signature {} impl $crate::AppKey for Signature { type UntypedGeneric = $sig; type Public = Public; - #[cfg(feature="std")] - type Pair = Pair; type Signature = Signature; const ID: $crate::KeyTypeId = $key_type; } + } +} + +/// Declares Signature type which is functionally equivalent to `$sig`, but is new +/// Application-specific type whose identifier is `$key_type`. +/// For full functionality, app_crypto_public_(not)_full_crypto! must be called too. +#[macro_export] +macro_rules! app_crypto_signature_common { + ($sig:ty, $key_type:expr) => { + impl $crate::Deref for Signature { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { self.0.as_ref() } + } + + impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { self.0.as_ref() } + } impl $crate::AppSignature for Signature { type Generic = $sig; diff --git a/core/application-crypto/src/sr25519.rs b/core/application-crypto/src/sr25519.rs index af112dc70ee7e6b1c669dae7c5edd6e65dfa59e3..f6c2388a9bbdf148abdcf3498c46fdb38b63e790 100644 --- a/core/application-crypto/src/sr25519.rs +++ b/core/application-crypto/src/sr25519.rs @@ -21,39 +21,43 @@ use crate::{RuntimePublic, KeyTypeId}; pub use primitives::sr25519::*; mod app { - use crate::key_types::SR25519; + use primitives::testing::SR25519; crate::app_crypto!(super, SR25519); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } } pub use app::Public as AppPublic; pub use app::Signature as AppSignature; -#[cfg(feature="std")] +#[cfg(feature = "full_crypto")] pub use app::Pair as AppPair; impl RuntimePublic for Public { type Signature = Signature; fn all(key_type: KeyTypeId) -> crate::Vec { - rio::sr25519_public_keys(key_type) + runtime_io::sr25519_public_keys(key_type) } fn generate_pair(key_type: KeyTypeId, seed: Option<&str>) -> Self { - rio::sr25519_generate(key_type, seed) + runtime_io::sr25519_generate(key_type, seed) } fn sign>(&self, key_type: KeyTypeId, msg: &M) -> Option { - rio::sr25519_sign(key_type, self, msg) + runtime_io::sr25519_sign(key_type, self, msg.as_ref()) } fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { - rio::sr25519_verify(&signature, msg.as_ref(), self) + runtime_io::sr25519_verify(&signature, msg.as_ref(), self) } } #[cfg(test)] mod tests { use sr_primitives::{generic::BlockId, traits::ProvideRuntimeApi}; - use primitives::{testing::KeyStore, crypto::Pair, traits::BareCryptoStore as _}; + use primitives::{testing::{KeyStore, SR25519}, crypto::Pair}; use test_client::{ TestClientBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt, runtime::{TestAPI, app_crypto::sr25519::{AppPair, AppPublic}}, @@ -67,7 +71,7 @@ mod tests { .test_sr25519_crypto(&BlockId::Number(0)) .expect("Tests `sr25519` crypto."); - let key_pair = keystore.read().sr25519_key_pair(crate::key_types::SR25519, public.as_ref()) + let key_pair = keystore.read().sr25519_key_pair(SR25519, public.as_ref()) .expect("There should be at a `sr25519` key in the keystore for the given public key."); assert!(AppPair::verify(&signature, "sr25519", &AppPublic::from(key_pair.public()))); diff --git a/core/application-crypto/src/traits.rs b/core/application-crypto/src/traits.rs index d7f1eafe35407d94e6a27ef476e26e67763029bf..28073be1cebca9b9f9f9d54e64c37b30064a605f 100644 --- a/core/application-crypto/src/traits.rs +++ b/core/application-crypto/src/traits.rs @@ -14,10 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use primitives::crypto::{KeyTypeId, CryptoType, IsWrappedBy, Public}; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] use primitives::crypto::Pair; +use codec::Codec; +use primitives::crypto::{KeyTypeId, CryptoType, IsWrappedBy, Public}; +use rstd::fmt::Debug; + /// An application-specific key. pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { /// The corresponding type as a generic crypto type. @@ -27,7 +30,7 @@ pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { type Public: AppPublic; /// The corresponding key pair type in this application scheme. - #[cfg(feature="std")] + #[cfg(feature = "full_crypto")] type Pair: AppPair; /// The corresponding signature type in this application scheme. @@ -37,42 +40,50 @@ pub trait AppKey: 'static + Send + Sync + Sized + CryptoType + Clone { const ID: KeyTypeId; } -/// Type which implements Debug and Hash in std, not when no-std (std variant). +/// Type which implements Hash in std, not when no-std (std variant). #[cfg(feature = "std")] -pub trait MaybeDebugHash: std::fmt::Debug + std::hash::Hash {} +pub trait MaybeHash: rstd::hash::Hash {} #[cfg(feature = "std")] -impl MaybeDebugHash for T {} +impl MaybeHash for T {} + +/// Type which implements Hash in std, not when no-std (no-std variant). +#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))] +pub trait MaybeHash {} +#[cfg(all(not(feature = "std"), not(feature = "full_crypto")))] +impl MaybeHash for T {} -/// Type which implements Debug and Hash in std, not when no-std (no-std variant). -#[cfg(not(feature = "std"))] -pub trait MaybeDebugHash {} -#[cfg(not(feature = "std"))] -impl MaybeDebugHash for T {} +/// Type which implements Debug and Hash in std, not when no-std (no-std variant with crypto). +#[cfg(all(not(feature = "std"), feature = "full_crypto"))] +pub trait MaybeDebugHash: rstd::hash::Hash {} +#[cfg(all(not(feature = "std"), feature = "full_crypto"))] +impl MaybeDebugHash for T {} /// A application's public key. -pub trait AppPublic: AppKey + Public + Ord + PartialOrd + Eq + PartialEq + MaybeDebugHash + codec::Codec { +pub trait AppPublic: + AppKey + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec +{ /// The wrapped type which is just a plain instance of `Public`. type Generic: - IsWrappedBy + Public + Ord + PartialOrd + Eq + PartialEq + MaybeDebugHash + codec::Codec; + IsWrappedBy + Public + Ord + PartialOrd + Eq + PartialEq + Debug + MaybeHash + codec::Codec; } /// A application's key pair. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub trait AppPair: AppKey + Pair::Public> { /// The wrapped type which is just a plain instance of `Pair`. type Generic: IsWrappedBy + Pair::Public as AppPublic>::Generic>; } /// A application's signature. -pub trait AppSignature: AppKey + Eq + PartialEq + MaybeDebugHash { +pub trait AppSignature: AppKey + Eq + PartialEq + Debug + MaybeHash { /// The wrapped type which is just a plain instance of `Signature`. - type Generic: IsWrappedBy + Eq + PartialEq + MaybeDebugHash; + type Generic: IsWrappedBy + Eq + PartialEq + Debug + MaybeHash; } /// A runtime interface for a public key. pub trait RuntimePublic: Sized { /// The signature that will be generated when signing with the corresponding private key. - type Signature; + type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; /// Returns all public keys for the given key type in the keystore. fn all(key_type: KeyTypeId) -> crate::Vec; @@ -95,9 +106,12 @@ pub trait RuntimePublic: Sized { } /// A runtime interface for an application's public key. -pub trait RuntimeAppPublic: Sized { +pub trait RuntimeAppPublic: Sized { + /// An identifier for this application-specific key type. + const ID: KeyTypeId; + /// The signature that will be generated when signing with the corresponding private key. - type Signature; + type Signature: Codec + Debug + MaybeHash + Eq + PartialEq + Clone; /// Returns all public keys for this application in the keystore. fn all() -> crate::Vec; @@ -118,3 +132,9 @@ pub trait RuntimeAppPublic: Sized { /// Verify that the given signature matches the given message using this public key. fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool; } + +/// Something that bound to a fixed `RuntimeAppPublic`. +pub trait BoundToRuntimeAppPublic { + /// The `RuntimeAppPublic` this type is bound to. + type Public: RuntimeAppPublic; +} diff --git a/core/authority-discovery/Cargo.toml b/core/authority-discovery/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..823977668a0e5803531d1d70fec6cbf33b7fb603 --- /dev/null +++ b/core/authority-discovery/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "substrate-authority-discovery" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[build-dependencies] +prost-build = "0.5.0" + +[dependencies] +authority-discovery-primitives = { package = "substrate-authority-discovery-primitives", path = "./primitives" } +bytes = "0.4.12" +client = { package = "substrate-client", path = "../../core/client" } +codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" } +derive_more = "0.15.0" +futures-preview = "0.3.0-alpha.19" +libp2p = { version = "0.13.0", default-features = false, features = ["secp256k1", "libp2p-websocket"] } +log = "0.4.8" +network = { package = "substrate-network", path = "../../core/network" } +primitives = { package = "substrate-primitives", path = "../primitives" } +prost = "0.5.0" +serde_json = "1.0.41" +sr-primitives = { path = "../../core/sr-primitives" } +futures-timer = "0.4" + +[dev-dependencies] +parking_lot = "0.9.0" +peerset = { package = "substrate-peerset", path = "../../core/peerset" } +test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } diff --git a/core/authority-discovery/build.rs b/core/authority-discovery/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..ed632575f3ba86d0d02e1edc013d15ada1d934cc --- /dev/null +++ b/core/authority-discovery/build.rs @@ -0,0 +1,3 @@ +fn main() { + prost_build::compile_protos(&["src/schema/dht.proto"], &["src/schema"]).unwrap(); +} diff --git a/core/authority-discovery/primitives/Cargo.toml b/core/authority-discovery/primitives/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..8e9e465a299f6c6577a8a235ff50dd59e0e1868c --- /dev/null +++ b/core/authority-discovery/primitives/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "substrate-authority-discovery-primitives" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Authority discovery primitives" +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" } +client = { package = "substrate-client", path = "../../client", default-features = false } +sr-primitives = { path = "../../sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../sr-std", default-features = false } + +[features] +default = ["std"] +std = [ + "rstd/std", + "client/std", + "codec/std", + "sr-primitives/std" +] diff --git a/core/authority-discovery/primitives/src/lib.rs b/core/authority-discovery/primitives/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7c56dc6ca4ca6b26c97be661b36370a174a3916a --- /dev/null +++ b/core/authority-discovery/primitives/src/lib.rs @@ -0,0 +1,50 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime Api to help discover authorities. + +#![cfg_attr(not(feature = "std"), no_std)] + +use client::decl_runtime_apis; +use rstd::vec::Vec; +use sr_primitives::RuntimeDebug; + +#[derive(codec::Encode, codec::Decode, Eq, PartialEq, Clone, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Hash))] +pub struct Signature(pub Vec); +#[derive(codec::Encode, codec::Decode, Eq, PartialEq, Clone, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Hash))] +pub struct AuthorityId(pub Vec); + +decl_runtime_apis! { + /// The authority discovery api. + /// + /// This api is used by the `core/authority-discovery` module to retrieve our + /// own authority identifier, to retrieve identifiers of the current authority + /// set, as well as sign and verify Kademlia Dht external address payloads + /// from and to other authorities. + pub trait AuthorityDiscoveryApi { + /// Retrieve authority identifiers of the current authority set. + fn authorities() -> Vec; + + /// Sign the given payload with the private key corresponding to the given authority id. + fn sign(payload: &Vec) -> Option<(Signature, AuthorityId)>; + + /// Verify the given signature for the given payload with the given + /// authority identifier. + fn verify(payload: &Vec, signature: &Signature, authority_id: &AuthorityId) -> bool; + } +} diff --git a/core/authority-discovery/src/error.rs b/core/authority-discovery/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..dca50cc0beb9eeaf8094bbfb2c35d612500497b0 --- /dev/null +++ b/core/authority-discovery/src/error.rs @@ -0,0 +1,45 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Authority discovery errors. + +/// AuthorityDiscovery Result. +pub type Result = std::result::Result; + +/// Error type for the authority discovery module. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// Failed to verify a dht payload with the given signature. + VerifyingDhtPayload, + /// Failed to hash the authority id to be used as a dht key. + HashingAuthorityId(libp2p::core::multiaddr::multihash::EncodeError), + /// Failed calling into the Substrate runtime. + CallingRuntime(client::error::Error), + /// Failed signing the dht payload via the Substrate runtime. + SigningDhtPayload, + /// From the Dht we only get the hashed authority id. In order to retrieve the actual authority id and to ensure it + /// is actually an authority, we match the hash against the hash of the authority id of all other authorities. This + /// error is the result of the above failing. + MatchingHashedAuthorityIdWithAuthorityId, + /// Failed to set the authority discovery peerset priority group in the peerset module. + SettingPeersetPriorityGroup(String), + /// Failed to encode a dht payload. + Encoding(prost::EncodeError), + /// Failed to decode a dht payload. + Decoding(prost::DecodeError), + /// Failed to parse a libp2p multi address. + ParsingMultiaddress(libp2p::core::multiaddr::Error), +} diff --git a/core/authority-discovery/src/lib.rs b/core/authority-discovery/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..35237e251c895997baa7825e7a98b0d265954a8e --- /dev/null +++ b/core/authority-discovery/src/lib.rs @@ -0,0 +1,687 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#![warn(missing_docs)] + +//! Substrate authority discovery. +//! +//! This crate enables Substrate authorities to directly connect to other authorities. [`AuthorityDiscovery`] implements +//! the Future trait. By polling [`AuthorityDiscovery`] an authority: +//! +//! +//! 1. **Makes itself discoverable** +//! +//! 1. Retrieves its external addresses. +//! +//! 2. Adds its network peer id to the addresses. +//! +//! 3. Signs the above. +//! +//! 4. Puts the signature and the addresses on the libp2p Kademlia DHT. +//! +//! +//! 2. **Discovers other authorities** +//! +//! 1. Retrieves the current set of authorities. +//! +//! 2. Starts DHT queries for the ids of the authorities. +//! +//! 3. Validates the signatures of the retrieved key value pairs. +//! +//! 4. Adds the retrieved external addresses as priority nodes to the peerset. +use std::collections::{HashMap, HashSet}; +use std::convert::TryInto; +use std::iter::FromIterator; +use std::marker::PhantomData; +use std::pin::Pin; +use std::sync::Arc; +use std::time::Duration; + +use futures::channel::mpsc::Receiver; +use futures::stream::StreamExt; +use futures::task::{Context, Poll}; +use futures::Future; +use futures_timer::Interval; + +use authority_discovery_primitives::{AuthorityDiscoveryApi, AuthorityId, Signature}; +use client::blockchain::HeaderBackend; +use error::{Error, Result}; +use log::{debug, error, log_enabled, warn}; +use network::specialization::NetworkSpecialization; +use network::{DhtEvent, ExHashT}; +use prost::Message; +use sr_primitives::generic::BlockId; +use sr_primitives::traits::{Block as BlockT, ProvideRuntimeApi}; + +mod error; +/// Dht payload schemas generated from Protobuf definitions via Prost crate in build.rs. +mod schema { + include!(concat!(env!("OUT_DIR"), "/authority_discovery.rs")); +} + +/// An `AuthorityDiscovery` makes a given authority discoverable and discovers other authorities. +pub struct AuthorityDiscovery +where + Block: BlockT + 'static, + Network: NetworkProvider, + Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, + ::Api: AuthorityDiscoveryApi, +{ + client: Arc, + + network: Arc, + /// Channel we receive Dht events on. + dht_event_rx: Receiver, + + /// Interval to be proactive, publishing own addresses. + publish_interval: Interval, + /// Interval on which to query for addresses of other authorities. + query_interval: Interval, + + /// The network peerset interface for priority groups lets us only set an entire group, but we retrieve the + /// addresses of other authorities one by one from the network. To use the peerset interface we need to cache the + /// addresses and always overwrite the entire peerset priority group. To ensure this map doesn't grow indefinitely + /// `purge_old_authorities_from_cache` function is called each time we add a new entry. + address_cache: HashMap>, + + phantom: PhantomData, +} + +impl AuthorityDiscovery +where + Block: BlockT + Unpin + 'static, + Network: NetworkProvider, + Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, + ::Api: AuthorityDiscoveryApi, + Self: Future, +{ + /// Return a new authority discovery. + pub fn new( + client: Arc, + network: Arc, + dht_event_rx: Receiver, + ) -> Self { + // Kademlia's default time-to-live for Dht records is 36h, republishing records every 24h. Given that a node + // could restart at any point in time, one can not depend on the republishing process, thus publishing own + // external addresses should happen on an interval < 36h. + let publish_interval = Interval::new(Duration::from_secs(12 * 60 * 60)); + + // External addresses of other authorities can change at any given point in time. The interval on which to query + // for external addresses of other authorities is a trade off between efficiency and performance. + let query_interval = Interval::new(Duration::from_secs(10 * 60)); + + let address_cache = HashMap::new(); + + AuthorityDiscovery { + client, + network, + dht_event_rx, + publish_interval, + query_interval, + address_cache, + phantom: PhantomData, + } + } + + fn publish_own_ext_addresses(&mut self) -> Result<()> { + let id = BlockId::hash(self.client.info().best_hash); + + let addresses = self + .network + .external_addresses() + .into_iter() + .map(|a| { + a.with(libp2p::core::multiaddr::Protocol::P2p( + self.network.local_peer_id().into(), + )) + }) + .map(|a| a.to_vec()) + .collect(); + + let mut serialized_addresses = vec![]; + schema::AuthorityAddresses { addresses } + .encode(&mut serialized_addresses) + .map_err(Error::Encoding)?; + + let (signature, authority_id) = self + .client + .runtime_api() + .sign(&id, &serialized_addresses) + .map_err(Error::CallingRuntime)? + .ok_or(Error::SigningDhtPayload)?; + + let mut signed_addresses = vec![]; + schema::SignedAuthorityAddresses { + addresses: serialized_addresses, + signature: signature.0, + } + .encode(&mut signed_addresses) + .map_err(Error::Encoding)?; + + self.network.put_value( + hash_authority_id(authority_id.0.as_ref())?, + signed_addresses, + ); + + Ok(()) + } + + fn request_addresses_of_others(&mut self) -> Result<()> { + let id = BlockId::hash(self.client.info().best_hash); + + let authorities = self + .client + .runtime_api() + .authorities(&id) + .map_err(Error::CallingRuntime)?; + + for authority_id in authorities.iter() { + self.network + .get_value(&hash_authority_id(authority_id.0.as_ref())?); + } + + Ok(()) + } + + fn handle_dht_events(&mut self, cx: &mut Context) -> Result<()> { + while let Poll::Ready(Some(event)) = self.dht_event_rx.poll_next_unpin(cx) { + match event { + DhtEvent::ValueFound(v) => { + if log_enabled!(log::Level::Debug) { + let hashes = v.iter().map(|(hash, _value)| hash.clone()); + debug!(target: "sub-authority-discovery", "Value for hash '{:?}' found on Dht.", hashes); + } + + self.handle_dht_value_found_event(v)?; + } + DhtEvent::ValueNotFound(hash) => warn!( + target: "sub-authority-discovery", + "Value for hash '{:?}' not found on Dht.", hash + ), + DhtEvent::ValuePut(hash) => debug!( + target: "sub-authority-discovery", + "Successfully put hash '{:?}' on Dht.", hash), + DhtEvent::ValuePutFailed(hash) => warn!( + target: "sub-authority-discovery", + "Failed to put hash '{:?}' on Dht.", hash + ), + } + } + + Ok(()) + } + + fn handle_dht_value_found_event( + &mut self, + values: Vec<(libp2p::kad::record::Key, Vec)>, + ) -> Result<()> { + debug!(target: "sub-authority-discovery", "Got Dht value from network."); + + let id = BlockId::hash(self.client.info().best_hash); + + // From the Dht we only get the hashed authority id. In order to retrieve the actual authority id and to ensure + // it is actually an authority, we match the hash against the hash of the authority id of all other authorities. + let authorities = self.client.runtime_api().authorities(&id)?; + self.purge_old_authorities_from_cache(&authorities); + + let authorities = authorities + .into_iter() + .map(|a| hash_authority_id(a.0.as_ref()).map(|h| (h, a))) + .collect::>>()?; + + for (key, value) in values.iter() { + // Check if the event origins from an authority in the current authority set. + let authority_id: &AuthorityId = authorities + .get(key) + .ok_or(Error::MatchingHashedAuthorityIdWithAuthorityId)?; + + let schema::SignedAuthorityAddresses { + signature, + addresses, + } = schema::SignedAuthorityAddresses::decode(value).map_err(Error::Decoding)?; + let signature = Signature(signature); + + let is_verified = self + .client + .runtime_api() + .verify(&id, &addresses, &signature, &authority_id.clone()) + .map_err(Error::CallingRuntime)?; + + if !is_verified { + return Err(Error::VerifyingDhtPayload); + } + + let addresses: Vec = schema::AuthorityAddresses::decode(addresses) + .map(|a| a.addresses) + .map_err(Error::Decoding)? + .into_iter() + .map(|a| a.try_into()) + .collect::>() + .map_err(Error::ParsingMultiaddress)?; + + self.address_cache.insert(authority_id.clone(), addresses); + } + + // Let's update the peerset priority group with the all the addresses we have in our cache. + + let addresses = HashSet::from_iter( + self.address_cache + .iter() + .map(|(_peer_id, addresses)| addresses.clone()) + .flatten(), + ); + + debug!(target: "sub-authority-discovery", "Applying priority group {:#?} to peerset.", addresses); + self.network + .set_priority_group("authorities".to_string(), addresses) + .map_err(Error::SettingPeersetPriorityGroup)?; + + Ok(()) + } + + fn purge_old_authorities_from_cache(&mut self, current_authorities: &Vec) { + self.address_cache + .retain(|peer_id, _addresses| current_authorities.contains(peer_id)) + } +} + +impl Future for AuthorityDiscovery +where + Block: BlockT + Unpin + 'static, + Network: NetworkProvider, + Client: ProvideRuntimeApi + Send + Sync + 'static + HeaderBackend, + ::Api: AuthorityDiscoveryApi, +{ + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let mut inner = || -> Result<()> { + // Process incoming events before triggering new ones. + self.handle_dht_events(cx)?; + + if let Poll::Ready(_) = self.publish_interval.poll_next_unpin(cx) { + // Make sure to call interval.poll until it returns Async::NotReady once. Otherwise, in case one of the + // function calls within this block do a `return`, we don't call `interval.poll` again and thereby the + // underlying Tokio task is never registered with Tokio's Reactor to be woken up on the next interval + // tick. + while let Poll::Ready(_) = self.publish_interval.poll_next_unpin(cx) {} + + self.publish_own_ext_addresses()?; + } + + if let Poll::Ready(_) = self.query_interval.poll_next_unpin(cx) { + // Make sure to call interval.poll until it returns Async::NotReady once. Otherwise, in case one of the + // function calls within this block do a `return`, we don't call `interval.poll` again and thereby the + // underlying Tokio task is never registered with Tokio's Reactor to be woken up on the next interval + // tick. + while let Poll::Ready(_) = self.query_interval.poll_next_unpin(cx) {} + + self.request_addresses_of_others()?; + } + + Ok(()) + }; + + match inner() { + Ok(()) => {} + Err(e) => error!(target: "sub-authority-discovery", "Poll failure: {:?}", e), + }; + + // Make sure to always return NotReady as this is a long running task with the same lifetime as the node itself. + Poll::Pending + } +} + +/// NetworkProvider provides AuthorityDiscovery with all necessary hooks into the underlying Substrate networking. Using +/// this trait abstraction instead of NetworkService directly is necessary to unit test AuthorityDiscovery. +pub trait NetworkProvider { + /// Returns the local external addresses. + fn external_addresses(&self) -> Vec; + + /// Returns the network identity of the node. + fn local_peer_id(&self) -> libp2p::PeerId; + + /// Modify a peerset priority group. + fn set_priority_group( + &self, + group_id: String, + peers: HashSet, + ) -> std::result::Result<(), String>; + + /// Start putting a value in the Dht. + fn put_value(&self, key: libp2p::kad::record::Key, value: Vec); + + /// Start getting a value from the Dht. + fn get_value(&self, key: &libp2p::kad::record::Key); +} + +impl NetworkProvider for network::NetworkService +where + B: BlockT + 'static, + S: NetworkSpecialization, + H: ExHashT, +{ + fn external_addresses(&self) -> Vec { + self.external_addresses() + } + fn local_peer_id(&self) -> libp2p::PeerId { + self.local_peer_id() + } + fn set_priority_group( + &self, + group_id: String, + peers: HashSet, + ) -> std::result::Result<(), String> { + self.set_priority_group(group_id, peers) + } + fn put_value(&self, key: libp2p::kad::record::Key, value: Vec) { + self.put_value(key, value) + } + fn get_value(&self, key: &libp2p::kad::record::Key) { + self.get_value(key) + } +} + +fn hash_authority_id(id: &[u8]) -> Result { + libp2p::multihash::encode(libp2p::multihash::Hash::SHA2256, id) + .map(|k| libp2p::kad::record::Key::new(&k)) + .map_err(Error::HashingAuthorityId) +} + +#[cfg(test)] +mod tests { + use super::*; + use client::runtime_api::{ApiExt, Core, RuntimeVersion, StorageProof}; + use futures::channel::mpsc::channel; + use futures::executor::block_on; + use futures::future::poll_fn; + use primitives::{ExecutionContext, NativeOrEncoded}; + use sr_primitives::traits::Zero; + use sr_primitives::traits::{ApiRef, Block as BlockT, NumberFor, ProvideRuntimeApi}; + use std::sync::{Arc, Mutex}; + use test_client::runtime::Block; + + #[derive(Clone)] + struct TestApi {} + + impl ProvideRuntimeApi for TestApi { + type Api = RuntimeApi; + + fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { + RuntimeApi {}.into() + } + } + + /// Blockchain database header backend. Does not perform any validation. + impl HeaderBackend for TestApi { + fn header( + &self, + _id: BlockId, + ) -> std::result::Result, client::error::Error> { + Ok(None) + } + + fn info(&self) -> client::blockchain::Info { + client::blockchain::Info { + best_hash: Default::default(), + best_number: Zero::zero(), + finalized_hash: Default::default(), + finalized_number: Zero::zero(), + genesis_hash: Default::default(), + } + } + + fn status( + &self, + _id: BlockId, + ) -> std::result::Result { + Ok(client::blockchain::BlockStatus::Unknown) + } + + fn number( + &self, + _hash: Block::Hash, + ) -> std::result::Result>, client::error::Error> { + Ok(None) + } + + fn hash( + &self, + _number: NumberFor, + ) -> std::result::Result, client::error::Error> { + Ok(None) + } + } + + struct RuntimeApi {} + + impl Core for RuntimeApi { + fn Core_version_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> std::result::Result, client::error::Error> { + unimplemented!("Not required for testing!") + } + + fn Core_execute_block_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<(Block)>, + _: Vec, + ) -> std::result::Result, client::error::Error> { + unimplemented!("Not required for testing!") + } + + fn Core_initialize_block_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<&::Header>, + _: Vec, + ) -> std::result::Result, client::error::Error> { + unimplemented!("Not required for testing!") + } + } + + impl ApiExt for RuntimeApi { + fn map_api_result std::result::Result, R, E>( + &self, + _: F, + ) -> std::result::Result { + unimplemented!("Not required for testing!") + } + + fn runtime_version_at( + &self, + _: &BlockId, + ) -> std::result::Result { + unimplemented!("Not required for testing!") + } + + fn record_proof(&mut self) { + unimplemented!("Not required for testing!") + } + + fn extract_proof(&mut self) -> Option { + unimplemented!("Not required for testing!") + } + } + + impl AuthorityDiscoveryApi for RuntimeApi { + fn AuthorityDiscoveryApi_authorities_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> std::result::Result>, client::error::Error> { + return Ok(NativeOrEncoded::Native(vec![ + AuthorityId("test-authority-id-1".as_bytes().to_vec()), + AuthorityId("test-authority-id-2".as_bytes().to_vec()), + ])); + } + fn AuthorityDiscoveryApi_sign_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<&std::vec::Vec>, + _: Vec, + ) -> std::result::Result< + NativeOrEncoded>, + client::error::Error, + > { + return Ok(NativeOrEncoded::Native(Some(( + Signature("test-signature-1".as_bytes().to_vec()), + AuthorityId("test-authority-id-1".as_bytes().to_vec()), + )))); + } + fn AuthorityDiscoveryApi_verify_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + args: Option<(&Vec, &Signature, &AuthorityId)>, + _: Vec, + ) -> std::result::Result, client::error::Error> { + if *args.unwrap().1 == Signature("test-signature-1".as_bytes().to_vec()) { + return Ok(NativeOrEncoded::Native(true)); + } + return Ok(NativeOrEncoded::Native(false)); + } + } + + #[derive(Default)] + struct TestNetwork { + // Whenever functions on `TestNetwork` are called, the function arguments are added to the vectors below. + pub put_value_call: Arc)>>>, + pub get_value_call: Arc>>, + pub set_priority_group_call: Arc)>>>, + } + + impl NetworkProvider for TestNetwork { + fn external_addresses(&self) -> Vec { + vec![] + } + fn local_peer_id(&self) -> libp2p::PeerId { + libp2p::PeerId::random() + } + fn set_priority_group( + &self, + group_id: String, + peers: HashSet, + ) -> std::result::Result<(), String> { + self.set_priority_group_call + .lock() + .unwrap() + .push((group_id, peers)); + Ok(()) + } + fn put_value(&self, key: libp2p::kad::record::Key, value: Vec) { + self.put_value_call.lock().unwrap().push((key, value)); + } + fn get_value(&self, key: &libp2p::kad::record::Key) { + self.get_value_call.lock().unwrap().push(key.clone()); + } + } + + #[test] + fn publish_own_ext_addresses_puts_record_on_dht() { + let (_dht_event_tx, dht_event_rx) = channel(1000); + let test_api = Arc::new(TestApi {}); + let network: Arc = Arc::new(Default::default()); + + let mut authority_discovery = + AuthorityDiscovery::new(test_api, network.clone(), dht_event_rx); + + authority_discovery.publish_own_ext_addresses().unwrap(); + + // Expect authority discovery to put a new record onto the dht. + assert_eq!(network.put_value_call.lock().unwrap().len(), 1); + } + + #[test] + fn request_addresses_of_others_triggers_dht_get_query() { + let (_dht_event_tx, dht_event_rx) = channel(1000); + let test_api = Arc::new(TestApi {}); + let network: Arc = Arc::new(Default::default()); + + let mut authority_discovery = + AuthorityDiscovery::new(test_api, network.clone(), dht_event_rx); + + authority_discovery.request_addresses_of_others().unwrap(); + + // Expect authority discovery to request new records from the dht. + assert_eq!(network.get_value_call.lock().unwrap().len(), 2); + } + + #[test] + fn handle_dht_events_with_value_found_should_call_set_priority_group() { + // Create authority discovery. + + let (mut dht_event_tx, dht_event_rx) = channel(1000); + let test_api = Arc::new(TestApi {}); + let network: Arc = Arc::new(Default::default()); + + let mut authority_discovery = + AuthorityDiscovery::new(test_api, network.clone(), dht_event_rx); + + // Create sample dht event. + + let authority_id_1 = hash_authority_id("test-authority-id-1".as_bytes()).unwrap(); + let address_1: libp2p::Multiaddr = "/ip6/2001:db8::".parse().unwrap(); + + let mut serialized_addresses = vec![]; + schema::AuthorityAddresses { + addresses: vec![address_1.to_vec()], + } + .encode(&mut serialized_addresses) + .unwrap(); + + let mut signed_addresses = vec![]; + schema::SignedAuthorityAddresses { + addresses: serialized_addresses, + signature: "test-signature-1".as_bytes().to_vec(), + } + .encode(&mut signed_addresses) + .unwrap(); + + let dht_event = network::DhtEvent::ValueFound(vec![(authority_id_1, signed_addresses)]); + dht_event_tx.try_send(dht_event).unwrap(); + + // Make authority discovery handle the event. + let f = |cx: &mut Context<'_>| -> Poll<()> { + authority_discovery.handle_dht_events(cx).unwrap(); + + // Expect authority discovery to set the priority set. + assert_eq!(network.set_priority_group_call.lock().unwrap().len(), 1); + + assert_eq!( + network.set_priority_group_call.lock().unwrap()[0], + ( + "authorities".to_string(), + HashSet::from_iter(vec![address_1.clone()].into_iter()) + ) + ); + + Poll::Ready(()) + }; + + let _ = block_on(poll_fn(f)); + } +} diff --git a/core/authority-discovery/src/schema/dht.proto b/core/authority-discovery/src/schema/dht.proto new file mode 100644 index 0000000000000000000000000000000000000000..9dbe9d559f4b121b33f048245b0e10873da30817 --- /dev/null +++ b/core/authority-discovery/src/schema/dht.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package authority_discovery; + +// First we need to serialize the addresses in order to be able to sign them. +message AuthorityAddresses { + repeated bytes addresses = 1; +} + +// Then we need to serialize addresses and signature to send them over the wire. +message SignedAuthorityAddresses { + bytes addresses = 1; + bytes signature = 2; +} diff --git a/core/basic-authorship/Cargo.toml b/core/basic-authorship/Cargo.toml index 003eb79349266471802a298ed3b2d477a6451fcc..0a98c151d6eaf90dab9dbde6fc8d5b2512befca2 100644 --- a/core/basic-authorship/Cargo.toml +++ b/core/basic-authorship/Cargo.toml @@ -5,8 +5,8 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -log = "0.4" -futures-preview = "=0.3.0-alpha.17" +log = "0.4.8" +futures-preview = "0.3.0-alpha.19" codec = { package = "parity-scale-codec", version = "1.0.0" } sr-primitives = { path = "../../core/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index 2030f2be5a2f92c858447bd73d2ac85fb4d6a488..7f8b343f6512c6720fe3b0f98135c464bd2426c1 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -30,9 +30,10 @@ use inherents::InherentData; use log::{error, info, debug, trace}; use primitives::{H256, Blake2Hasher, ExecutionContext}; use sr_primitives::{ - traits::{Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, DigestFor, BlakeTwo256}, + traits::{ + Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, DigestFor, BlakeTwo256 + }, generic::BlockId, - ApplyError, }; use transaction_pool::txpool::{self, Pool as TransactionPool}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; @@ -170,7 +171,7 @@ impl Proposer, A> wh Ok(()) => { debug!("[{:?}] Pushed to the block.", pending.hash); } - Err(error::Error::ApplyExtrinsicFailed(ApplyError::FullBlock)) => { + Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausted_resources() => { if is_first { debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash); unqueue_invalid.push(pending.hash.clone()); @@ -178,7 +179,7 @@ impl Proposer, A> wh skipped += 1; debug!( "Block seems full, but will try {} more transactions before quitting.", - MAX_SKIPPED_TRANSACTIONS - skipped + MAX_SKIPPED_TRANSACTIONS - skipped, ); } else { debug!("Block is full, proceed with proposing."); @@ -246,10 +247,12 @@ mod tests { fn should_cease_building_block_when_deadline_is_reached() { // given let client = Arc::new(test_client::new()); - let chain_api = transaction_pool::ChainApi::new(client.clone()); + let chain_api = transaction_pool::FullChainApi::new(client.clone()); let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); - txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)]).unwrap(); + futures::executor::block_on( + txpool.submit_at(&BlockId::number(0), vec![extrinsic(0), extrinsic(1)], false) + ).unwrap(); let mut proposer_factory = ProposerFactory { client: client.clone(), diff --git a/core/basic-authorship/src/lib.rs b/core/basic-authorship/src/lib.rs index 71c9e2792248fa260980c87400bb6130e1a898fe..7961e4fe9e9dfe7b8e4ccf41fb448335fd286173 100644 --- a/core/basic-authorship/src/lib.rs +++ b/core/basic-authorship/src/lib.rs @@ -26,7 +26,7 @@ //! # use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; //! # use transaction_pool::txpool::{self, Pool as TransactionPool}; //! # let client = Arc::new(test_client::new()); -//! # let chain_api = transaction_pool::ChainApi::new(client.clone()); +//! # let chain_api = transaction_pool::FullChainApi::new(client.clone()); //! # let txpool = Arc::new(TransactionPool::new(Default::default(), chain_api)); //! // The first step is to create a `ProposerFactory`. //! let mut proposer_factory = ProposerFactory { diff --git a/core/chain-spec/Cargo.toml b/core/chain-spec/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..1ab78a18dd13c690eb939f92cfb3b65dd35fd701 --- /dev/null +++ b/core/chain-spec/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "substrate-chain-spec" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +substrate-chain-spec-derive = { path = "./derive" } +impl-trait-for-tuples = "0.1.3" +network = { package = "substrate-network", path = "../../core/network" } +primitives = { package = "substrate-primitives", path = "../primitives" } +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" +sr-primitives = { path = "../../core/sr-primitives" } +tel = { package = "substrate-telemetry", path = "../../core/telemetry" } + +[dev-dependencies] diff --git a/core/chain-spec/derive/Cargo.toml b/core/chain-spec/derive/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..9fb8eabc608444dbbb4a52684e35d8ee1a28ffa4 --- /dev/null +++ b/core/chain-spec/derive/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "substrate-chain-spec-derive" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +proc-macro-crate = "0.1.4" +proc-macro2 = "1.0.6" +quote = "1.0.2" +syn = "1.0.7" + +[dev-dependencies] diff --git a/core/chain-spec/derive/src/impls.rs b/core/chain-spec/derive/src/impls.rs new file mode 100644 index 0000000000000000000000000000000000000000..cdc27aef0b9c698aac9742056814f76a49091d5f --- /dev/null +++ b/core/chain-spec/derive/src/impls.rs @@ -0,0 +1,190 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{DeriveInput, Ident, Error}; +use proc_macro_crate::crate_name; + +const CRATE_NAME: &str = "substrate-chain-spec"; +const ATTRIBUTE_NAME: &str = "forks"; + +/// Implements `Extension's` `Group` accessor. +/// +/// The struct that derives this implementation will be usable within the `ChainSpec` file. +/// The derive implements a by-type accessor method. +pub fn extension_derive(ast: &DeriveInput) -> proc_macro::TokenStream { + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, fields| { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let forks = fields.named.iter().find_map(|f| { + if f.attrs.iter().any(|attr| attr.path.is_ident(ATTRIBUTE_NAME)) { + let typ = &f.ty; + Some(quote! { #typ }) + } else { + None + } + }).unwrap_or_else(|| quote! { #crate_name::NoExtension }); + + quote! { + impl #impl_generics #crate_name::Extension for #name #ty_generics #where_clause { + type Forks = #forks; + + fn get(&self) -> Option<&T> { + use std::any::{Any, TypeId}; + + match TypeId::of::() { + #( x if x == TypeId::of::<#field_types>() => Any::downcast_ref(&self.#field_names) ),*, + _ => None, + } + } + } + } + }) +} + + +/// Implements required traits and creates `Fork` structs for `ChainSpec` custom parameter group. +pub fn group_derive(ast: &DeriveInput) -> proc_macro::TokenStream { + derive(ast, |crate_name, name, generics: &syn::Generics, field_names, field_types, _fields| { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let fork_name = Ident::new(&format!("{}Fork", name), Span::call_site()); + + let fork_fields = generate_fork_fields(&crate_name, &field_names, &field_types); + let to_fork = generate_base_to_fork(&fork_name, &field_names); + let combine_with = generate_combine_with(&field_names); + let to_base = generate_fork_to_base(name, &field_names); + + quote! { + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + pub struct #fork_name #ty_generics #where_clause { + #fork_fields + } + + impl #impl_generics #crate_name::Group for #name #ty_generics #where_clause { + type Fork = #fork_name #ty_generics; + + fn to_fork(self) -> Self::Fork { + use #crate_name::Group; + #to_fork + } + } + + impl #impl_generics #crate_name::Fork for #fork_name #ty_generics #where_clause { + type Base = #name #ty_generics; + + fn combine_with(&mut self, other: Self) { + use #crate_name::Fork; + #combine_with + } + + fn to_base(self) -> Option { + use #crate_name::Fork; + #to_base + } + } + } + }) +} + +pub fn derive( + ast: &DeriveInput, + derive: impl Fn( + &Ident, &Ident, &syn::Generics, Vec<&Ident>, Vec<&syn::Type>, &syn::FieldsNamed, + ) -> TokenStream, +) -> proc_macro::TokenStream { + let err = || { + let err = Error::new( + Span::call_site(), + "ChainSpecGroup is only avaible for structs with named fields." + ).to_compile_error(); + quote!( #err ).into() + }; + + let data = match &ast.data { + syn::Data::Struct(ref data) => data, + _ => return err(), + }; + + let fields = match &data.fields { + syn::Fields::Named(ref named) => named, + _ => return err(), + }; + + const PROOF: &str = "CARGO_PKG_NAME always defined when compiling; qed"; + let name = &ast.ident; + let crate_name = match crate_name(CRATE_NAME) { + Ok(chain_spec_name) => chain_spec_name, + Err(e) => if std::env::var("CARGO_PKG_NAME").expect(PROOF) == CRATE_NAME { + // we return the name of the crate here instead of `crate` to support doc tests. + CRATE_NAME.replace("-", "_") + } else { + let err = Error::new(Span::call_site(), &e).to_compile_error(); + return quote!( #err ).into() + }, + }; + let crate_name = Ident::new(&crate_name, Span::call_site()); + let field_names = fields.named.iter().flat_map(|x| x.ident.as_ref()).collect::>(); + let field_types = fields.named.iter().map(|x| &x.ty).collect::>(); + + derive(&crate_name, name, &ast.generics, field_names, field_types, fields).into() +} + +fn generate_fork_fields( + crate_name: &Ident, + names: &[&Ident], + types: &[&syn::Type], +) -> TokenStream { + let crate_name = std::iter::repeat(crate_name); + quote! { + #( pub #names: Option<<#types as #crate_name::Group>::Fork>, )* + } +} + +fn generate_base_to_fork( + fork_name: &Ident, + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + #fork_name { + #( #names: Some(self.#names2.to_fork()), )* + } + } +} + +fn generate_combine_with( + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + #( self.#names.combine_with(other.#names2); )* + } +} + +fn generate_fork_to_base( + fork: &Ident, + names: &[&Ident], +) -> TokenStream { + let names2 = names.to_vec(); + + quote!{ + Some(#fork { + #( #names: self.#names2?.to_base()?, )* + }) + } +} diff --git a/core/chain-spec/derive/src/lib.rs b/core/chain-spec/derive/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..bcd50c102178553243be1ea88fcaefd595fdfa3a --- /dev/null +++ b/core/chain-spec/derive/src/lib.rs @@ -0,0 +1,39 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Macros to derive chain spec extension traits implementation. + +extern crate proc_macro; + +mod impls; + +use proc_macro::TokenStream; + +#[proc_macro_derive(ChainSpecGroup)] +pub fn group_derive(input: TokenStream) -> TokenStream { + match syn::parse(input) { + Ok(ast) => impls::group_derive(&ast), + Err(e) => e.to_compile_error().into(), + } +} + +#[proc_macro_derive(ChainSpecExtension, attributes(forks))] +pub fn extensions_derive(input: TokenStream) -> TokenStream { + match syn::parse(input) { + Ok(ast) => impls::extension_derive(&ast), + Err(e) => e.to_compile_error().into(), + } +} diff --git a/core/chain-spec/res/chain_spec.json b/core/chain-spec/res/chain_spec.json new file mode 100644 index 0000000000000000000000000000000000000000..673f35d5079194ba9b1bfc0c960e3007cde2d79f --- /dev/null +++ b/core/chain-spec/res/chain_spec.json @@ -0,0 +1,31 @@ +{ + "name": "Flaming Fir", + "id": "flaming-fir", + "properties": { + "tokenDecimals": 15, + "tokenSymbol": "FIR" + }, + "bootNodes": [ + "/ip4/35.246.224.91/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.224.91/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.210.11/tcp/30333/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.246.210.11/tcp/30334/ws/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.198.110.45/tcp/30333/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.110.45/tcp/30334/ws/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.114.154/tcp/30333/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6", + "/ip4/35.198.114.154/tcp/30334/ws/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6" + ], + "telemetryEndpoints": [ + ["wss://telemetry.polkadot.io/submit/", 0] + ], + "protocolId": "fir", + "consensusEngine": null, + "genesis": { + "raw": [ + { + "0xb2029f8665aac509629f2d28cea790a3": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106" + }, + {} + ] + } +} diff --git a/core/chain-spec/res/chain_spec2.json b/core/chain-spec/res/chain_spec2.json new file mode 100644 index 0000000000000000000000000000000000000000..950a7fc82749431771376591ec3428374b27fe75 --- /dev/null +++ b/core/chain-spec/res/chain_spec2.json @@ -0,0 +1,32 @@ +{ + "name": "Flaming Fir", + "id": "flaming-fir", + "properties": { + "tokenDecimals": 15, + "tokenSymbol": "FIR" + }, + "bootNodes": [ + "/ip4/35.246.224.91/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.224.91/tcp/30334/ws/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV", + "/ip4/35.246.210.11/tcp/30333/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.246.210.11/tcp/30334/ws/p2p/QmWv9Ww7znzgLFyCzf21SR6tUKXrmHCZH9KhebeH4gyE9f", + "/ip4/35.198.110.45/tcp/30333/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.110.45/tcp/30334/ws/p2p/QmTtcYKJho9vFmqtMA548QBSmLbmwAkBSiEKK3kWKfb6bJ", + "/ip4/35.198.114.154/tcp/30333/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6", + "/ip4/35.198.114.154/tcp/30334/ws/p2p/QmQJmDorK9c8KjMF5PdWiH2WGUXyzJtgTeJ55S5gggdju6" + ], + "telemetryEndpoints": [ + ["wss://telemetry.polkadot.io/submit/", 0] + ], + "protocolId": "fir", + "consensusEngine": null, + "myProperty": "Test Extension", + "genesis": { + "raw": [ + { + "0xb2029f8665aac509629f2d28cea790a3": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106" + }, + {} + ] + } +} diff --git a/core/service/src/chain_spec.rs b/core/chain-spec/src/chain_spec.rs similarity index 60% rename from core/service/src/chain_spec.rs rename to core/chain-spec/src/chain_spec.rs index 8d84b4880cc3e65fcd0f48f8537d025173b487fa..0f69654b9e8f6cf217e1d54c8dbf8d0fb0ef03b3 100644 --- a/core/service/src/chain_spec.rs +++ b/core/chain-spec/src/chain_spec.rs @@ -20,18 +20,19 @@ use std::borrow::Cow; use std::collections::HashMap; use std::fs::File; use std::path::PathBuf; +use std::rc::Rc; use serde::{Serialize, Deserialize}; use primitives::storage::{StorageKey, StorageData}; use sr_primitives::{BuildStorage, StorageOverlay, ChildrenStorageOverlay}; use serde_json as json; -use crate::components::RuntimeGenesis; +use crate::RuntimeGenesis; use network::Multiaddr; use tel::TelemetryEndpoints; enum GenesisSource { File(PathBuf), Binary(Cow<'static, [u8]>), - Factory(fn() -> G), + Factory(Rc G>), } impl Clone for GenesisSource { @@ -39,7 +40,7 @@ impl Clone for GenesisSource { match *self { GenesisSource::File(ref path) => GenesisSource::File(path.clone()), GenesisSource::Binary(ref d) => GenesisSource::Binary(d.clone()), - GenesisSource::Factory(f) => GenesisSource::Factory(f), + GenesisSource::Factory(ref f) => GenesisSource::Factory(f.clone()), } } } @@ -53,14 +54,15 @@ impl GenesisSource { match self { GenesisSource::File(path) => { - let file = File::open(path).map_err(|e| format!("Error opening spec file: {}", e))?; - let genesis: GenesisContainer = - json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; + let file = File::open(path) + .map_err(|e| format!("Error opening spec file: {}", e))?; + let genesis: GenesisContainer = json::from_reader(file) + .map_err(|e| format!("Error parsing spec file: {}", e))?; Ok(genesis.genesis) }, GenesisSource::Binary(buf) => { - let genesis: GenesisContainer = - json::from_reader(buf.as_ref()).map_err(|e| format!("Error parsing embedded file: {}", e))?; + let genesis: GenesisContainer = json::from_reader(buf.as_ref()) + .map_err(|e| format!("Error parsing embedded file: {}", e))?; Ok(genesis.genesis) }, GenesisSource::Factory(f) => Ok(Genesis::Runtime(f())), @@ -68,8 +70,8 @@ impl GenesisSource { } } -impl<'a, G: RuntimeGenesis> BuildStorage for &'a ChainSpec { - fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { +impl<'a, G: RuntimeGenesis, E> BuildStorage for &'a ChainSpec { + fn build_storage(&self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { match self.genesis.resolve()? { Genesis::Runtime(gc) => gc.build_storage(), Genesis::Raw(map, children_map) => Ok(( @@ -81,7 +83,11 @@ impl<'a, G: RuntimeGenesis> BuildStorage for &'a ChainSpec { )), } } - fn assimilate_storage(self, _: &mut (StorageOverlay, ChildrenStorageOverlay)) -> Result<(), String> { + + fn assimilate_storage( + &self, + _: &mut (StorageOverlay, ChildrenStorageOverlay) + ) -> Result<(), String> { Err("`assimilate_storage` not implemented for `ChainSpec`.".into()) } } @@ -97,28 +103,39 @@ enum Genesis { ), } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] -struct ChainSpecFile { +#[serde(deny_unknown_fields)] +struct ChainSpecFile { pub name: String, pub id: String, pub boot_nodes: Vec, pub telemetry_endpoints: Option, pub protocol_id: Option, - pub consensus_engine: Option, pub properties: Option, + #[serde(flatten)] + pub extensions: E, + // Never used, left only for backward compatibility. + consensus_engine: (), + #[serde(skip_serializing)] + genesis: serde::de::IgnoredAny, } /// Arbitrary properties defined in chain spec as a JSON object pub type Properties = json::map::Map; +/// A type denoting empty extensions. +/// +/// We use `Option` here since `()` is not flattenable by serde. +pub type NoExtension = Option<()>; + /// A configuration of a chain. Can be used to build a genesis block. -pub struct ChainSpec { - spec: ChainSpecFile, +pub struct ChainSpec { + spec: ChainSpecFile, genesis: GenesisSource, } -impl Clone for ChainSpec { +impl Clone for ChainSpec { fn clone(&self) -> Self { ChainSpec { spec: self.spec.clone(), @@ -127,7 +144,7 @@ impl Clone for ChainSpec { } } -impl ChainSpec { +impl ChainSpec { /// A list of bootnode addresses. pub fn boot_nodes(&self) -> &[String] { &self.spec.boot_nodes @@ -153,14 +170,10 @@ impl ChainSpec { self.spec.protocol_id.as_ref().map(String::as_str) } - /// Name of the consensus engine. - pub fn consensus_engine(&self) -> Option<&str> { - self.spec.consensus_engine.as_ref().map(String::as_str) - } - /// Additional loosly-typed properties of the chain. + /// + /// Returns an empty JSON object if 'properties' not defined in config pub fn properties(&self) -> Properties { - // Return an empty JSON object if 'properties' not defined in config self.spec.properties.as_ref().unwrap_or(&json::map::Map::new()).clone() } @@ -169,61 +182,73 @@ impl ChainSpec { self.spec.boot_nodes.push(addr.to_string()) } - /// Parse json content into a `ChainSpec` - pub fn from_json_bytes(json: impl Into>) -> Result { - let json = json.into(); - let spec = json::from_slice(json.as_ref()).map_err(|e| format!("Error parsing spec file: {}", e))?; - Ok(ChainSpec { - spec, - genesis: GenesisSource::Binary(json), - }) - } - - /// Parse json file into a `ChainSpec` - pub fn from_json_file(path: PathBuf) -> Result { - let file = File::open(&path).map_err(|e| format!("Error opening spec file: {}", e))?; - let spec = json::from_reader(file).map_err(|e| format!("Error parsing spec file: {}", e))?; - Ok(ChainSpec { - spec, - genesis: GenesisSource::File(path), - }) + /// Returns a reference to defined chain spec extensions. + pub fn extensions(&self) -> &E { + &self.spec.extensions } /// Create hardcoded spec. - pub fn from_genesis( + pub fn from_genesis G + 'static>( name: &str, id: &str, - constructor: fn() -> G, + constructor: F, boot_nodes: Vec, telemetry_endpoints: Option, protocol_id: Option<&str>, - consensus_engine: Option<&str>, properties: Option, - ) -> Self - { + extensions: E, + ) -> Self { let spec = ChainSpecFile { name: name.to_owned(), id: id.to_owned(), boot_nodes: boot_nodes, telemetry_endpoints, protocol_id: protocol_id.map(str::to_owned), - consensus_engine: consensus_engine.map(str::to_owned), properties, + extensions, + consensus_engine: (), + genesis: Default::default(), }; + ChainSpec { spec, - genesis: GenesisSource::Factory(constructor), + genesis: GenesisSource::Factory(Rc::new(constructor)), } } } -impl ChainSpec { +impl ChainSpec { + /// Parse json content into a `ChainSpec` + pub fn from_json_bytes(json: impl Into>) -> Result { + let json = json.into(); + let spec = json::from_slice(json.as_ref()) + .map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + spec, + genesis: GenesisSource::Binary(json), + }) + } + + /// Parse json file into a `ChainSpec` + pub fn from_json_file(path: PathBuf) -> Result { + let file = File::open(&path) + .map_err(|e| format!("Error opening spec file: {}", e))?; + let spec = json::from_reader(file) + .map_err(|e| format!("Error parsing spec file: {}", e))?; + Ok(ChainSpec { + spec, + genesis: GenesisSource::File(path), + }) + } +} + +impl ChainSpec { /// Dump to json string. pub fn to_json(self, raw: bool) -> Result { #[derive(Serialize, Deserialize)] - struct Container { + struct Container { #[serde(flatten)] - spec: ChainSpecFile, + spec: ChainSpecFile, genesis: Genesis, }; @@ -250,6 +275,58 @@ impl ChainSpec { spec: self.spec, genesis, }; - json::to_string_pretty(&spec).map_err(|e| format!("Error generating spec json: {}", e)) + json::to_string_pretty(&spec) + .map_err(|e| format!("Error generating spec json: {}", e)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug, Serialize, Deserialize)] + struct Genesis(HashMap); + + impl BuildStorage for Genesis { + fn assimilate_storage( + &self, + storage: &mut (StorageOverlay, ChildrenStorageOverlay), + ) -> Result<(), String> { + storage.0.extend( + self.0.iter().map(|(a, b)| (a.clone().into_bytes(), b.clone().into_bytes())) + ); + Ok(()) + } + } + + type TestSpec = ChainSpec; + + #[test] + fn should_deserailize_example_chain_spec() { + let spec1 = TestSpec::from_json_bytes(Cow::Owned( + include_bytes!("../res/chain_spec.json").to_vec() + )).unwrap(); + let spec2 = TestSpec::from_json_file( + PathBuf::from("./res/chain_spec.json") + ).unwrap(); + + assert_eq!(spec1.to_json(false), spec2.to_json(false)); + } + + #[derive(Debug, Serialize, Deserialize)] + #[serde(rename_all = "camelCase")] + struct Extension1 { + my_property: String, + } + + type TestSpec2 = ChainSpec; + + #[test] + fn should_deserialize_chain_spec_with_extensions() { + let spec = TestSpec2::from_json_bytes(Cow::Owned( + include_bytes!("../res/chain_spec2.json").to_vec() + )).unwrap(); + + assert_eq!(spec.extensions().my_property, "Test Extension"); } } diff --git a/core/chain-spec/src/extension.rs b/core/chain-spec/src/extension.rs new file mode 100644 index 0000000000000000000000000000000000000000..e5110a77d5a2301fadcdea8943e01aeb501c1ed4 --- /dev/null +++ b/core/chain-spec/src/extension.rs @@ -0,0 +1,363 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Chain Spec extensions helpers. + +use std::fmt::Debug; +use std::collections::BTreeMap; + +use serde::{Serialize, Deserialize, de::DeserializeOwned}; + +/// A `ChainSpec` extension. +/// +/// This trait is implemented automatically by `ChainSpecGroup` macro. +pub trait Group: Clone + Sized { + /// An associated type containing fork definition. + type Fork: Fork; + + /// Convert to fork type. + fn to_fork(self) -> Self::Fork; +} + +/// A `ChainSpec` extension fork definition. +/// +/// Basically should look the same as `Group`, but +/// all parameters are optional. This allows changing +/// only one parameter as part of the fork. +/// The forks can be combined (summed up) to specify +/// a complete set of parameters +pub trait Fork: Serialize + DeserializeOwned + Clone + Sized { + /// A base `Group` type. + type Base: Group; + + /// Combine with another struct. + /// + /// All parameters set in `other` should override the + /// ones in the current struct. + fn combine_with(&mut self, other: Self); + + /// Attempt to convert to the base type if all parameters are set. + fn to_base(self) -> Option; +} + +macro_rules! impl_trivial { + () => {}; + ($A : ty) => { + impl_trivial!($A ,); + }; + ($A : ty , $( $B : ty ),*) => { + impl_trivial!($( $B ),*); + + impl Group for $A { + type Fork = $A; + + fn to_fork(self) -> Self::Fork { + self + } + } + + impl Fork for $A { + type Base = $A; + + fn combine_with(&mut self, other: Self) { + *self = other; + } + + fn to_base(self) -> Option { + Some(self) + } + } + } +} + +impl_trivial!((), u8, u16, u32, u64, usize, String, Vec); + +impl Group for Option { + type Fork = Option; + + fn to_fork(self) -> Self::Fork { + self.map(|a| a.to_fork()) + } +} + +impl Fork for Option { + type Base = Option; + + fn combine_with(&mut self, other: Self) { + *self = match (self.take(), other) { + (Some(mut a), Some(b)) => { + a.combine_with(b); + Some(a) + }, + (a, b) => a.or(b), + }; + } + + fn to_base(self) -> Option { + self.map(|x| x.to_base()) + } +} + +/// A collection of `ChainSpec` extensions. +/// +/// This type can be passed around and allows the core +/// modules to request a strongly-typed, but optional configuration. +pub trait Extension: Serialize + DeserializeOwned + Clone { + type Forks: IsForks; + + /// Get an extension of specific type. + fn get(&self) -> Option<&T>; + + /// Get forkable extensions of specific type. + fn forks(&self) -> Option> where + BlockNumber: Ord + Clone + 'static, + T: Group + 'static, + ::Extension: Extension, + <::Extension as Group>::Fork: Extension, + { + self.get::::Extension>>()? + .for_type() + } +} + +impl Extension for crate::NoExtension { + type Forks = Self; + + fn get(&self) -> Option<&T> { None } +} + +pub trait IsForks { + type BlockNumber: Ord + 'static; + type Extension: Group + 'static; +} + +impl IsForks for Option<()> { + type BlockNumber = u64; + type Extension = Self; +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct Forks { + forks: BTreeMap, + #[serde(flatten)] + base: T, +} + +impl Default for Forks { + fn default() -> Self { + Self { + base: Default::default(), + forks: Default::default(), + } + } +} + +impl Forks where + T::Fork: Debug, +{ + /// Create new fork definition given the base and the forks. + pub fn new(base: T, forks: BTreeMap) -> Self { + Self { base, forks } + } + + /// Return a set of parameters for `Group` including all forks up to `block` (inclusive). + pub fn at_block(&self, block: B) -> T { + let mut start = self.base.clone().to_fork(); + + for (_, fork) in self.forks.range(..=block) { + start.combine_with(fork.clone()); + } + + start + .to_base() + .expect("We start from the `base` object, so it's always fully initialized; qed") + } +} + +impl IsForks for Forks where + B: Ord + 'static, + T: Group + 'static, +{ + type BlockNumber = B; + type Extension = T; +} + +impl Forks where + T::Fork: Extension, +{ + /// Get forks definition for a subset of this extension. + /// + /// Returns the `Forks` struct, but limited to a particular type + /// within the extension. + pub fn for_type(&self) -> Option> where + X: Group + 'static, + { + let base = self.base.get::()?.clone(); + let forks = self.forks.iter().filter_map(|(k, v)| { + Some((k.clone(), v.get::>()?.clone()?)) + }).collect(); + + Some(Forks { + base, + forks, + }) + } +} + +impl Extension for Forks where + B: Serialize + DeserializeOwned + Ord + Clone + 'static, + E: Extension + Group + 'static, +{ + type Forks = Self; + + fn get(&self) -> Option<&T> { + use std::any::{TypeId, Any}; + + match TypeId::of::() { + x if x == TypeId::of::() => Any::downcast_ref(&self.base), + _ => self.base.get(), + } + } + + fn forks(&self) -> Option> where + BlockNumber: Ord + Clone + 'static, + T: Group + 'static, + ::Extension: Extension, + <::Extension as Group>::Fork: Extension, + { + use std::any::{TypeId, Any}; + + if TypeId::of::() == TypeId::of::() { + Any::downcast_ref(&self.for_type::()?).cloned() + } else { + self.get::::Extension>>()? + .for_type() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use substrate_chain_spec_derive::{ChainSpecGroup, ChainSpecExtension}; + // Make the proc macro work for tests and doc tests. + use crate as substrate_chain_spec; + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] + #[serde(deny_unknown_fields)] + pub struct Extension1 { + pub test: u64, + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup)] + #[serde(deny_unknown_fields)] + pub struct Extension2 { + pub test: u8, + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] + #[serde(deny_unknown_fields)] + pub struct Extensions { + pub ext1: Extension1, + pub ext2: Extension2, + } + + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecExtension)] + #[serde(deny_unknown_fields)] + pub struct Ext2 { + #[serde(flatten)] + ext1: Extension1, + #[forks] + forkable: Forks, + } + + #[test] + fn forks_should_work_correctly() { + use super::Extension as _ ; + + let ext: Ext2 = serde_json::from_str(r#" +{ + "test": 11, + "forkable": { + "ext1": { + "test": 15 + }, + "ext2": { + "test": 123 + }, + "forks": { + "1": { + "ext1": { "test": 5 } + }, + "2": { + "ext2": { "test": 5 } + }, + "5": { + "ext2": { "test": 1 } + } + } + } +} + "#).unwrap(); + + assert_eq!(ext.get::(), Some(&Extension1 { + test: 11 + })); + + // get forks definition + let forks = ext.get::>().unwrap(); + assert_eq!(forks.at_block(0), Extensions { + ext1: Extension1 { test: 15 }, + ext2: Extension2 { test: 123 }, + }); + assert_eq!(forks.at_block(1), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 123 }, + }); + assert_eq!(forks.at_block(2), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 5 }, + }); + assert_eq!(forks.at_block(4), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 5 }, + }); + assert_eq!(forks.at_block(5), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 1 }, + }); + assert_eq!(forks.at_block(10), Extensions { + ext1: Extension1 { test: 5 }, + ext2: Extension2 { test: 1 }, + }); + assert!(forks.at_block(10).get::().is_some()); + + // filter forks for `Extension2` + let ext2 = forks.for_type::().unwrap(); + assert_eq!(ext2.at_block(0), Extension2 { test: 123 }); + assert_eq!(ext2.at_block(2), Extension2 { test: 5 }); + assert_eq!(ext2.at_block(10), Extension2 { test: 1 }); + + // make sure that it can return forks correctly + let ext2_2 = forks.forks::().unwrap(); + assert_eq!(ext2, ext2_2); + + // also ext should be able to return forks correctly: + let ext2_3 = ext.forks::().unwrap(); + assert_eq!(ext2_2, ext2_3); + } +} diff --git a/core/chain-spec/src/lib.rs b/core/chain-spec/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..8c35c22d9b2b34959d8dbf05226fffb9e971011f --- /dev/null +++ b/core/chain-spec/src/lib.rs @@ -0,0 +1,123 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate chain configurations. +//! +//! This crate contains structs and utilities to declare +//! a runtime-specific configuration file (a.k.a chain spec). +//! +//! Basic chain spec type containing all required parameters is +//! [`ChainSpec`](./struct.ChainSpec.html). It can be extended with +//! additional options that contain configuration specific to your chain. +//! Usually the extension is going to be an amalgamate of types exposed +//! by Substrate core modules. To allow the core modules to retrieve +//! their configuration from your extension you should use `ChainSpecExtension` +//! macro exposed by this crate. +//! +//! ```rust +//! use std::collections::HashMap; +//! use serde::{Serialize, Deserialize}; +//! use substrate_chain_spec::{ChainSpec, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] +//! pub struct MyExtension { +//! pub known_blocks: HashMap, +//! } +//! +//! pub type MyChainSpec = ChainSpec; +//! ``` +//! +//! Some parameters may require different values depending on the +//! current blockchain height (a.k.a. forks). You can use `ChainSpecGroup` +//! macro and provided [`Forks`](./struct.Forks.html) structure to put +//! such parameters to your chain spec. +//! This will allow to override a single parameter starting at specific +//! block number. +//! +//! ```rust +//! use serde::{Serialize, Deserialize}; +//! use substrate_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct ClientParams { +//! max_block_size: usize, +//! max_extrinsic_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct PoolParams { +//! max_transaction_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +//! pub struct Extension { +//! pub client: ClientParams, +//! pub pool: PoolParams, +//! } +//! +//! pub type BlockNumber = u64; +//! +//! /// A chain spec supporting forkable `ClientParams`. +//! pub type MyChainSpec1 = ChainSpec>; +//! +//! /// A chain spec supporting forkable `Extension`. +//! pub type MyChainSpec2 = ChainSpec>; +//! ``` +//! +//! It's also possible to have a set of parameters that is allowed to change +//! with block numbers (i.e. is forkable), and another set that is not subject to changes. +//! This is also possible by declaring an extension that contains `Forks` within it. +//! +//! +//! ```rust +//! use serde::{Serialize, Deserialize}; +//! use substrate_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension}; +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct ClientParams { +//! max_block_size: usize, +//! max_extrinsic_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)] +//! pub struct PoolParams { +//! max_transaction_size: usize, +//! } +//! +//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)] +//! pub struct Extension { +//! pub client: ClientParams, +//! #[forks] +//! pub pool: Forks, +//! } +//! +//! pub type MyChainSpec = ChainSpec; +//! ``` + + +mod chain_spec; +mod extension; + +pub use chain_spec::{ChainSpec, Properties, NoExtension}; +pub use extension::{Group, Fork, Forks, Extension}; +pub use substrate_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; + +use serde::{Serialize, de::DeserializeOwned}; +use sr_primitives::BuildStorage; + +/// A set of traits for the runtime genesis config. +pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} +impl RuntimeGenesis for T {} diff --git a/core/cli/Cargo.toml b/core/cli/Cargo.toml index a5af7362268f94d413795cb85106fdabdf40739a..9fb528e66cf567c3827805e43b35b552e57c9f49 100644 --- a/core/cli/Cargo.toml +++ b/core/cli/Cargo.toml @@ -6,34 +6,40 @@ description = "Substrate CLI interface." edition = "2018" [dependencies] -clap = "~2.32" -derive_more = "0.14.0" -env_logger = "0.6" -log = "0.4" -atty = "0.2" -regex = "1" -time = "0.1" -ansi_term = "0.11" -lazy_static = "1.3" -app_dirs = "1.2" -tokio = "0.1.7" -futures = "0.1.17" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.17", features = ["compat"] } -fdlimit = "0.1" -exit-future = "0.1" -serde_json = "1.0" +clap = "2.33.0" +derive_more = "0.15.0" +env_logger = "0.7.0" +log = "0.4.8" +atty = "0.2.13" +regex = "1.3.1" +time = "0.1.42" +ansi_term = "0.12.1" +lazy_static = "1.4.0" +app_dirs = "1.2.1" +tokio = "0.1.22" +futures = "0.1.29" +futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19", features = ["compat"] } +fdlimit = "0.1.1" +exit-future = "0.1.4" +serde_json = "1.0.41" panic-handler = { package = "substrate-panic-handler", path = "../../core/panic-handler" } client = { package = "substrate-client", path = "../../core/client" } +header-metadata = { package = "substrate-header-metadata", path = "../../core/client/header-metadata" } network = { package = "substrate-network", path = "../../core/network" } sr-primitives = { path = "../../core/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } -service = { package = "substrate-service", path = "../../core/service" } +service = { package = "substrate-service", path = "../../core/service", default-features = false } state-machine = { package = "substrate-state-machine", path = "../../core/state-machine" } substrate-telemetry = { path = "../../core/telemetry" } keyring = { package = "substrate-keyring", path = "../keyring" } names = "0.11.0" -structopt = "0.2" -rpassword = "3.0" +structopt = "0.3.3" +rpassword = "4.0.1" [dev-dependencies] -tempdir = "0.3" +tempdir = "0.3.7" + +[features] +wasmtime = [ + "service/wasmtime", +] diff --git a/core/cli/src/execution_strategy.rs b/core/cli/src/execution_strategy.rs index bd3030906ec09fdea7d3707d0387926055cce96f..93236227e5d640983c58139f316afc81f003ab30 100644 --- a/core/cli/src/execution_strategy.rs +++ b/core/cli/src/execution_strategy.rs @@ -16,7 +16,7 @@ #![allow(missing_docs)] -use structopt::clap::{arg_enum, _clap_count_exprs}; +use structopt::clap::arg_enum; arg_enum! { /// How to execute blocks diff --git a/core/cli/src/informant.rs b/core/cli/src/informant.rs index b5a2f03d795461a75e2ad0f02084875fed395bcb..f7c23ba47918a42363c960ec1a3d4bef0f97accf 100644 --- a/core/cli/src/informant.rs +++ b/core/cli/src/informant.rs @@ -16,36 +16,29 @@ //! Console informant. Prints sync progress and block events. Runs on the calling thread. -use client::{backend::Backend, BlockchainEvents}; +use client::BlockchainEvents; use futures::{Future, Stream}; use futures03::{StreamExt as _, TryStreamExt as _}; use log::{info, warn}; -use sr_primitives::{generic::BlockId, traits::Header}; -use service::{Service, Components}; -use tokio::runtime::TaskExecutor; +use sr_primitives::traits::Header; +use service::AbstractService; +use std::time::Duration; mod display; -/// Spawn informant on the event loop -#[deprecated(note = "Please use informant::build instead, and then create the task manually")] -pub fn start(service: &Service, exit: ::exit_future::Exit, handle: TaskExecutor) where - C: Components, -{ - handle.spawn(exit.until(build(service)).map(|_| ())); -} - /// Creates an informant in the form of a `Future` that must be polled regularly. -pub fn build(service: &Service) -> impl Future -where C: Components { +pub fn build(service: &impl AbstractService) -> impl Future { let client = service.client(); let mut display = display::InformantDisplay::new(); - let display_notifications = service.network_status().for_each(move |(net_status, _)| { - let info = client.info(); - display.display(&info, net_status); - Ok(()) - }); + let display_notifications = service + .network_status(Duration::from_millis(5000)) + .for_each(move |(net_status, _)| { + let info = client.info(); + display.display(&info, net_status); + Ok(()) + }); let client = service.client(); let mut last_best = { @@ -57,19 +50,18 @@ where C: Components { // detect and log reorganizations. if let Some((ref last_num, ref last_hash)) = last_best { if n.header.parent_hash() != last_hash && n.is_new_best { - let tree_route = ::client::blockchain::tree_route( - #[allow(deprecated)] - client.backend().blockchain(), - BlockId::Hash(last_hash.clone()), - BlockId::Hash(n.hash), + let maybe_ancestor = header_metadata::lowest_common_ancestor( + &*client, + last_hash.clone(), + n.hash, ); - match tree_route { - Ok(ref t) if !t.retracted().is_empty() => info!( + match maybe_ancestor { + Ok(ref ancestor) if ancestor.hash != *last_hash => info!( "Reorg from #{},{} to #{},{}, common ancestor #{},{}", last_num, last_hash, n.header.number(), n.hash, - t.common_block().number, t.common_block().hash, + ancestor.number, ancestor.hash, ), Ok(_) => {}, Err(e) => warn!("Error computing tree route: {}", e), diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs index ef5290413166d6a247d53f7ecf9c39f4b798b7ff..e445addf5ddd762b8d8ba34309f08b89ca1f72b6 100644 --- a/core/cli/src/lib.rs +++ b/core/cli/src/lib.rs @@ -28,13 +28,16 @@ pub mod informant; use client::ExecutionStrategies; use service::{ - config::Configuration, - ServiceFactory, FactoryFullConfiguration, RuntimeGenesis, - FactoryGenesis, PruningMode, ChainSpec, + config::{Configuration, DatabaseConfig}, + ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert, + RuntimeGenesis, ChainSpecExtension, PruningMode, ChainSpec, }; use network::{ - self, multiaddr::Protocol, - config::{NetworkConfiguration, TransportConfig, NonReservedPeerMode, NodeKeyConfig, build_multiaddr}, + self, + multiaddr::Protocol, + config::{ + NetworkConfiguration, TransportConfig, NonReservedPeerMode, NodeKeyConfig, build_multiaddr + }, }; use primitives::H256; @@ -62,22 +65,25 @@ use lazy_static::lazy_static; use futures::Future; use substrate_telemetry::TelemetryEndpoints; +/// default sub directory to store network config +const DEFAULT_NETWORK_CONFIG_PATH : &'static str = "network"; +/// default sub directory to store database +const DEFAULT_DB_CONFIG_PATH : &'static str = "db"; +/// default sub directory for the key store +const DEFAULT_KEYSTORE_CONFIG_PATH : &'static str = "keystore"; + /// The maximum number of characters for a node name. const NODE_NAME_MAX_LENGTH: usize = 32; -/// The file name of the node's Secp256k1 secret key inside the chain-specific -/// network config directory, if neither `--node-key` nor `--node-key-file` -/// is specified in combination with `--node-key-type=secp256k1`. -const NODE_KEY_SECP256K1_FILE: &str = "secret"; - /// The file name of the node's Ed25519 secret key inside the chain-specific /// network config directory, if neither `--node-key` nor `--node-key-file` /// is specified in combination with `--node-key-type=ed25519`. const NODE_KEY_ED25519_FILE: &str = "secret_ed25519"; /// Executable version. Used to pass version information from the root crate. +#[derive(Clone)] pub struct VersionInfo { - /// Implemtation name. + /// Implementaiton name. pub name: &'static str, /// Implementation version. pub version: &'static str, @@ -121,8 +127,10 @@ fn generate_node_name() -> String { result } -fn load_spec(cli: &SharedParams, factory: F) -> error::Result> - where G: RuntimeGenesis, F: FnOnce(&str) -> Result>, String>, +fn load_spec(cli: &SharedParams, factory: F) -> error::Result> where + G: RuntimeGenesis, + E: ChainSpecExtension, + F: FnOnce(&str) -> Result>, String>, { let chain_key = get_chain_key(cli); let spec = match factory(&chain_key)? { @@ -191,13 +199,13 @@ where I: IntoIterator, ::Item: Into + Clone, { - panic_handler::set(version.support_url); - let full_version = service::config::full_version_from_strs( version.version, version.commit ); + panic_handler::set(version.support_url, &full_version); + let matches = CoreParams::::clap() .name(version.executable_name) .author(version.author) @@ -235,6 +243,17 @@ where } } +/// Returns a string displaying the node role, special casing the sentry mode +/// (returning `SENTRY`), since the node technically has an `AUTHORITY` role but +/// doesn't participate. +pub fn display_role(config: &Configuration) -> String { + if config.sentry_mode { + "SENTRY".to_string() + } else { + format!("{:?}", config.roles) + } +} + /// Output of calling `parse_and_prepare`. #[must_use] pub enum ParseAndPrepare<'a, CC, RP> { @@ -263,20 +282,25 @@ pub struct ParseAndPrepareRun<'a, RP> { impl<'a, RP> ParseAndPrepareRun<'a, RP> { /// Runs the command and runs the main client. - pub fn run( + pub fn run( self, spec_factory: S, - exit: E, + exit: Exit, run_service: RS, ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, + where + S: FnOnce(&str) -> Result>, String>, + E: Into, RP: StructOpt + Clone, C: Default, G: RuntimeGenesis, - E: IntoExit, - RS: FnOnce(E, RunCmd, RP, Configuration) -> Result<(), String> + CE: ChainSpecExtension, + Exit: IntoExit, + RS: FnOnce(Exit, RunCmd, RP, Configuration) -> Result<(), E> { - let config = create_run_node_config(self.params.left.clone(), spec_factory, self.impl_name, self.version)?; + let config = create_run_node_config( + self.params.left.clone(), spec_factory, self.impl_name, self.version, + )?; run_service(exit, self.params.left, self.params.right, config).map_err(Into::into) } @@ -290,17 +314,36 @@ pub struct ParseAndPrepareBuildSpec<'a> { impl<'a> ParseAndPrepareBuildSpec<'a> { /// Runs the command and build the chain specs. - pub fn run( + pub fn run( self, spec_factory: S - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - G: RuntimeGenesis + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, { info!("Building chain spec"); let raw_output = self.params.raw; let mut spec = load_spec(&self.params.shared_params, spec_factory)?; - with_default_boot_node(&mut spec, self.params, self.version)?; + + if spec.boot_nodes().is_empty() && !self.params.disable_default_bootnode { + let base_path = base_path(&self.params.shared_params, self.version); + let cfg = service::Configuration::::default_with_spec_and_base_path(spec.clone(), Some(base_path)); + let node_key = node_key_config( + self.params.node_key_params, + &Some(cfg.in_chain_config_dir(DEFAULT_NETWORK_CONFIG_PATH).expect("We provided a base_path")) + )?; + let keys = node_key.into_keypair()?; + let peer_id = keys.public().into_peer_id(); + let addr = build_multiaddr![ + Ip4([127, 0, 0, 1]), + Tcp(30333u16), + P2p(peer_id) + ]; + spec.add_boot_node(addr) + } + let json = service::chain_ops::build_spec(spec, raw_output)?; print!("{}", json); @@ -317,18 +360,25 @@ pub struct ParseAndPrepareExport<'a> { impl<'a> ParseAndPrepareExport<'a> { /// Runs the command and exports from the chain. - pub fn run( + pub fn run_with_builder( self, + builder: F, spec_factory: S, - exit: E, + exit: Exit, ) -> error::Result<()> - where S: FnOnce(&str) -> Result>>, String>, - F: ServiceFactory, - E: IntoExit + where S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, + B: ServiceBuilderExport, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + Exit: IntoExit { let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; - info!("DB path: {}", config.database_path.display()); + if let DatabaseConfig::Path { ref path, .. } = &config.database { + info!("DB path: {}", path.display()); + } let from = self.params.from.unwrap_or(1); let to = self.params.to; let json = self.params.json; @@ -338,9 +388,8 @@ impl<'a> ParseAndPrepareExport<'a> { None => Box::new(stdout()), }; - service::chain_ops::export_blocks::( - config, exit.into_exit(), file, from.into(), to.map(Into::into), json - ).map_err(Into::into) + builder(config)?.export_blocks(exit.into_exit(), file, from.into(), to.map(Into::into), json)?; + Ok(()) } } @@ -352,16 +401,22 @@ pub struct ParseAndPrepareImport<'a> { impl<'a> ParseAndPrepareImport<'a> { /// Runs the command and imports to the chain. - pub fn run( + pub fn run_with_builder( self, + builder: F, spec_factory: S, - exit: E, + exit: Exit, ) -> error::Result<()> - where S: FnOnce(&str) -> Result>>, String>, - F: ServiceFactory, - E: IntoExit + where S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, + B: ServiceBuilderImport, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + Exit: IntoExit { let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; + config.wasm_method = self.params.wasm_method.into(); config.execution_strategies = ExecutionStrategies { importing: self.params.execution.into(), other: self.params.execution.into(), @@ -377,7 +432,7 @@ impl<'a> ParseAndPrepareImport<'a> { }, }; - let fut = service::chain_ops::import_blocks::(config, exit.into_exit(), file)?; + let fut = builder(config)?.import_blocks(exit.into_exit(), file)?; tokio::run(fut); Ok(()) } @@ -391,18 +446,27 @@ pub struct ParseAndPreparePurge<'a> { impl<'a> ParseAndPreparePurge<'a> { /// Runs the command and purges the chain. - pub fn run( + pub fn run( self, spec_factory: S - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>, String>, - G: RuntimeGenesis + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + G: RuntimeGenesis, + E: ChainSpecExtension, { - let config = create_config_with_db_path::<(), _, _>(spec_factory, &self.params.shared_params, self.version)?; - let db_path = config.database_path; + let config = create_config_with_db_path::<(), _, _, _>( + spec_factory, &self.params.shared_params, self.version + )?; + let db_path = match config.database { + DatabaseConfig::Path { path, .. } => path, + _ => { + eprintln!("Cannot purge custom database implementation"); + return Ok(()); + } + }; if !self.params.yes { - print!("Are you sure to remove {:?}? (y/n)", &db_path); + print!("Are you sure to remove {:?}? [y/N]: ", &db_path); stdout().flush().expect("failed to flush stdout"); let mut input = String::new(); @@ -424,7 +488,7 @@ impl<'a> ParseAndPreparePurge<'a> { Ok(()) }, Result::Err(ref err) if err.kind() == ErrorKind::NotFound => { - println!("{:?} did not exist.", &db_path); + eprintln!("{:?} did not exist.", &db_path); Ok(()) }, Result::Err(err) => Result::Err(err.into()) @@ -440,67 +504,27 @@ pub struct ParseAndPrepareRevert<'a> { impl<'a> ParseAndPrepareRevert<'a> { /// Runs the command and reverts the chain. - pub fn run( + pub fn run_with_builder( self, + builder: F, spec_factory: S - ) -> error::Result<()> - where S: FnOnce(&str) -> Result>>, String>, - F: ServiceFactory { - let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?; + ) -> error::Result<()> where + S: FnOnce(&str) -> Result>, String>, + F: FnOnce(Configuration) -> Result, + B: ServiceBuilderRevert, + C: Default, + G: RuntimeGenesis, + E: ChainSpecExtension, + { + let config = create_config_with_db_path( + spec_factory, &self.params.shared_params, self.version + )?; let blocks = self.params.num; - Ok(service::chain_ops::revert_chain::(config, blocks.into())?) + builder(config)?.revert_chain(blocks.into())?; + Ok(()) } } -/// Parse command line interface arguments and executes the desired command. -/// -/// # Return value -/// -/// A result that indicates if any error occurred. -/// If no error occurred and a custom subcommand was found, the subcommand is returned. -/// The user needs to handle this subcommand on its own. -/// -/// # Remarks -/// -/// `CC` is a custom subcommand. This needs to be an `enum`! If no custom subcommand is required, -/// `NoCustom` can be used as type here. -/// `RP` are custom parameters for the run command. This needs to be a `struct`! The custom -/// parameters are visible to the user as if they were normal run command parameters. If no custom -/// parameters are required, `NoCustom` can be used as type here. -#[deprecated( - note = "Use parse_and_prepare instead; see the source code of parse_and_execute for how to transition" -)] -pub fn parse_and_execute<'a, F, CC, RP, S, RS, E, I, T>( - spec_factory: S, - version: &VersionInfo, - impl_name: &'static str, - args: I, - exit: E, - run_service: RS, -) -> error::Result> -where - F: ServiceFactory, - S: FnOnce(&str) -> Result>>, String>, - CC: StructOpt + Clone + GetLogFilter, - RP: StructOpt + Clone + AugmentClap, - E: IntoExit, - RS: FnOnce(E, RunCmd, RP, FactoryFullConfiguration) -> Result<(), String>, - I: IntoIterator, - T: Into + Clone, -{ - match parse_and_prepare::(version, impl_name, args) { - ParseAndPrepare::Run(cmd) => cmd.run(spec_factory, exit, run_service), - ParseAndPrepare::BuildSpec(cmd) => cmd.run(spec_factory), - ParseAndPrepare::ExportBlocks(cmd) => cmd.run::(spec_factory, exit), - ParseAndPrepare::ImportBlocks(cmd) => cmd.run::(spec_factory, exit), - ParseAndPrepare::PurgeChain(cmd) => cmd.run(spec_factory), - ParseAndPrepare::RevertChain(cmd) => cmd.run::(spec_factory), - ParseAndPrepare::CustomCommand(cmd) => return Ok(Some(cmd)) - }?; - - Ok(None) -} - /// Create a `NodeKeyConfig` from the given `NodeKeyParams` in the context /// of an optional network config storage directory. fn node_key_config

(params: NodeKeyParams, net_config_dir: &Option

) @@ -509,14 +533,6 @@ where P: AsRef { match params.node_key_type { - NodeKeyType::Secp256k1 => - params.node_key.as_ref().map(parse_secp256k1_secret).unwrap_or_else(|| - Ok(params.node_key_file - .or_else(|| net_config_file(net_config_dir, NODE_KEY_SECP256K1_FILE)) - .map(network::config::Secret::File) - .unwrap_or(network::config::Secret::New))) - .map(NodeKeyConfig::Secp256k1), - NodeKeyType::Ed25519 => params.node_key.as_ref().map(parse_ed25519_secret).unwrap_or_else(|| Ok(params.node_key_file @@ -539,14 +555,6 @@ fn invalid_node_key(e: impl std::fmt::Display) -> error::Error { error::Error::Input(format!("Invalid node key: {}", e)) } -/// Parse a Secp256k1 secret key from a hex string into a `network::Secret`. -fn parse_secp256k1_secret(hex: &String) -> error::Result { - H256::from_str(hex).map_err(invalid_node_key).and_then(|bytes| - network::config::identity::secp256k1::SecretKey::from_bytes(bytes) - .map(network::config::Secret::Input) - .map_err(invalid_node_key)) -} - /// Parse a Ed25519 secret key from a hex string into a `network::Secret`. fn parse_ed25519_secret(hex: &String) -> error::Result { H256::from_str(&hex).map_err(invalid_node_key).and_then(|bytes| @@ -556,8 +564,8 @@ fn parse_ed25519_secret(hex: &String) -> error::Result( - options: &mut Configuration, +fn fill_transaction_pool_configuration( + options: &mut Configuration, params: TransactionPoolParams, ) -> error::Result<()> { // ready queue @@ -575,19 +583,17 @@ fn fill_transaction_pool_configuration( /// Fill the given `NetworkConfiguration` by looking at the cli parameters. fn fill_network_configuration( cli: NetworkConfigurationParams, - base_path: &Path, - chain_spec_id: &str, + config_path: PathBuf, config: &mut NetworkConfiguration, client_id: String, is_dev: bool, ) -> error::Result<()> { config.boot_nodes.extend(cli.bootnodes.into_iter()); - config.config_path = Some( - network_path(&base_path, chain_spec_id).to_string_lossy().into() - ); + config.config_path = Some(config_path.to_string_lossy().into()); config.net_config_path = config.config_path.clone(); config.reserved_nodes.extend(cli.reserved_nodes.into_iter()); - if !config.reserved_nodes.is_empty() { + + if cli.reserved_only { config.non_reserved_mode = NonReservedPeerMode::Deny; } @@ -631,8 +637,8 @@ fn input_keystore_password() -> Result { } /// Fill the password field of the given config instance. -fn fill_config_keystore_password( - config: &mut service::Configuration, +fn fill_config_keystore_password( + config: &mut service::Configuration, cli: &RunCmd, ) -> Result<(), String> { config.keystore_password = if cli.password_interactive { @@ -648,16 +654,18 @@ fn fill_config_keystore_password( Ok(()) } -fn create_run_node_config( - cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo -) -> error::Result> +fn create_run_node_config( + cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo, +) -> error::Result> where C: Default, G: RuntimeGenesis, - S: FnOnce(&str) -> Result>, String>, + E: ChainSpecExtension, + S: FnOnce(&str) -> Result>, String>, { let spec = load_spec(&cli.shared_params, spec_factory)?; - let mut config = service::Configuration::default_with_spec(spec.clone()); + let base_path = base_path(&cli.shared_params, &version); + let mut config = service::Configuration::default_with_spec_and_base_path(spec.clone(), Some(base_path)); fill_config_keystore_password(&mut config, &cli)?; @@ -681,34 +689,53 @@ where )? } - let base_path = base_path(&cli.shared_params, version); - - config.keystore_path = cli.keystore_path.unwrap_or_else( - || keystore_path(&base_path, config.chain_spec.id()) - ); + config.keystore_path = cli.keystore_path.or_else(|| config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH)); - config.database_path = db_path(&base_path, config.chain_spec.id()); - config.database_cache_size = cli.database_cache_size; - config.state_cache_size = cli.state_cache_size; - config.pruning = match cli.pruning { - Some(ref s) if s == "archive" => PruningMode::ArchiveAll, - None => PruningMode::default(), - Some(s) => PruningMode::keep_blocks( - s.parse().map_err(|_| error::Error::Input("Invalid pruning mode specified".to_string()))? - ), + config.database = DatabaseConfig::Path { + path: config.in_chain_config_dir(DEFAULT_DB_CONFIG_PATH).expect("We provided a base_path."), + cache_size: cli.database_cache_size, }; + config.state_cache_size = cli.state_cache_size; let is_dev = cli.shared_params.dev; + let is_authority = cli.validator || cli.sentry || is_dev || cli.keyring.account.is_some(); let role = if cli.light { service::Roles::LIGHT - } else if cli.validator || is_dev || cli.keyring.account.is_some() { + } else if is_authority { service::Roles::AUTHORITY } else { service::Roles::FULL }; + // set sentry mode (i.e. act as an authority but **never** actively participate) + config.sentry_mode = cli.sentry; + + // by default we disable pruning if the node is an authority (i.e. + // `ArchiveAll`), otherwise we keep state for the last 256 blocks. if the + // node is an authority and pruning is enabled explicitly, then we error + // unless `unsafe_pruning` is set. + config.pruning = match cli.pruning { + Some(ref s) if s == "archive" => PruningMode::ArchiveAll, + None if role == service::Roles::AUTHORITY => PruningMode::ArchiveAll, + None => PruningMode::default(), + Some(s) => { + if role == service::Roles::AUTHORITY && !cli.unsafe_pruning { + return Err(error::Error::Input( + "Validators should run with state pruning disabled (i.e. archive). \ + You can ignore this check with `--unsafe-pruning`.".to_string() + )); + } + + PruningMode::keep_blocks(s.parse() + .map_err(|_| error::Error::Input("Invalid pruning mode specified".to_string()))? + ) + }, + }; + + config.wasm_method = cli.wasm_method.into(); + let exec = cli.execution_strategies; let exec_all_or = |strat: params::ExecutionStrategy| exec.execution.unwrap_or(strat).into(); config.execution_strategies = ExecutionStrategies { @@ -732,8 +759,7 @@ where let client_id = config.client_id(); fill_network_configuration( cli.network_config, - &base_path, - spec.id(), + config.in_chain_config_dir(DEFAULT_NETWORK_CONFIG_PATH).expect("We provided a basepath"), &mut config.network, client_id, is_dev, @@ -784,52 +810,24 @@ where Ok(config) } -// -// IANA unassigned port ranges that we could use: -// 6717-6766 Unassigned -// 8504-8553 Unassigned -// 9556-9591 Unassigned -// 9803-9874 Unassigned -// 9926-9949 Unassigned - -fn with_default_boot_node( - spec: &mut ChainSpec, - cli: BuildSpecCmd, - version: &VersionInfo, -) -> error::Result<()> -where - G: RuntimeGenesis -{ - if spec.boot_nodes().is_empty() { - let base_path = base_path(&cli.shared_params, version); - let storage_path = network_path(&base_path, spec.id()); - let node_key = node_key_config(cli.node_key_params, &Some(storage_path))?; - let keys = node_key.into_keypair()?; - let peer_id = keys.public().into_peer_id(); - let addr = build_multiaddr![ - Ip4([127, 0, 0, 1]), - Tcp(30333u16), - P2p(peer_id) - ]; - spec.add_boot_node(addr) - } - Ok(()) -} - /// Creates a configuration including the database path. -pub fn create_config_with_db_path( +pub fn create_config_with_db_path( spec_factory: S, cli: &SharedParams, version: &VersionInfo, -) -> error::Result> +) -> error::Result> where C: Default, G: RuntimeGenesis, - S: FnOnce(&str) -> Result>, String>, + E: ChainSpecExtension, + S: FnOnce(&str) -> Result>, String>, { let spec = load_spec(cli, spec_factory)?; let base_path = base_path(cli, version); - let mut config = service::Configuration::default_with_spec(spec.clone()); - config.database_path = db_path(&base_path, spec.id()); + let mut config = service::Configuration::default_with_spec_and_base_path(spec.clone(), Some(base_path)); + config.database = DatabaseConfig::Path { + path: config.in_chain_config_dir(DEFAULT_DB_CONFIG_PATH).expect("We provided a base_path."), + cache_size: None, + }; Ok(config) } @@ -853,30 +851,6 @@ fn parse_address( Ok(address) } -fn keystore_path(base_path: &Path, chain_id: &str) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("chains"); - path.push(chain_id); - path.push("keystore"); - path -} - -fn db_path(base_path: &Path, chain_id: &str) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("chains"); - path.push(chain_id); - path.push("db"); - path -} - -fn network_path(base_path: &Path, chain_id: &str) -> PathBuf { - let mut path = base_path.to_owned(); - path.push("chains"); - path.push(chain_id); - path.push("network"); - path -} - fn init_logger(pattern: &str) { use ansi_term::Colour; @@ -884,6 +858,7 @@ fn init_logger(pattern: &str) { // Disable info logging by default for some modules: builder.filter(Some("ws"), log::LevelFilter::Off); builder.filter(Some("hyper"), log::LevelFilter::Warn); + builder.filter(Some("cranelift_wasm"), log::LevelFilter::Warn); // Enable info for others. builder.filter(None, log::LevelFilter::Info); @@ -930,7 +905,9 @@ fn init_logger(pattern: &str) { writeln!(buf, "{}", output) }); - builder.init(); + if builder.try_init().is_err() { + info!("Not registering Substrate logger, as there is already a global logger registered!"); + } } fn kill_color(s: &str) -> String { @@ -944,7 +921,7 @@ fn kill_color(s: &str) -> String { mod tests { use super::*; use tempdir::TempDir; - use network::config::identity::{secp256k1, ed25519}; + use network::config::identity::ed25519; #[test] fn tests_node_name_good() { @@ -967,7 +944,6 @@ mod tests { NodeKeyType::variants().into_iter().try_for_each(|t| { let node_key_type = NodeKeyType::from_str(t).unwrap(); let sk = match node_key_type { - NodeKeyType::Secp256k1 => secp256k1::SecretKey::generate().to_bytes().to_vec(), NodeKeyType::Ed25519 => ed25519::SecretKey::generate().as_ref().to_vec() }; let params = NodeKeyParams { @@ -976,9 +952,6 @@ mod tests { node_key_file: None }; node_key_config(params, &net_config_dir).and_then(|c| match c { - NodeKeyConfig::Secp256k1(network::config::Secret::Input(ref ski)) - if node_key_type == NodeKeyType::Secp256k1 && - &sk[..] == ski.to_bytes() => Ok(()), NodeKeyConfig::Ed25519(network::config::Secret::Input(ref ski)) if node_key_type == NodeKeyType::Ed25519 && &sk[..] == ski.as_ref() => Ok(()), @@ -1004,8 +977,6 @@ mod tests { node_key_file: Some(file.clone()) }; node_key_config(params, &net_config_dir).and_then(|c| match c { - NodeKeyConfig::Secp256k1(network::config::Secret::File(ref f)) - if node_key_type == NodeKeyType::Secp256k1 && f == &file => Ok(()), NodeKeyConfig::Ed25519(network::config::Secret::File(ref f)) if node_key_type == NodeKeyType::Ed25519 && f == &file => Ok(()), _ => Err(error::Error::Input("Unexpected node key config".into())) @@ -1038,8 +1009,6 @@ mod tests { let typ = params.node_key_type; node_key_config::(params, &None) .and_then(|c| match c { - NodeKeyConfig::Secp256k1(network::config::Secret::New) - if typ == NodeKeyType::Secp256k1 => Ok(()), NodeKeyConfig::Ed25519(network::config::Secret::New) if typ == NodeKeyType::Ed25519 => Ok(()), _ => Err(error::Error::Input("Unexpected node key config".into())) @@ -1053,9 +1022,6 @@ mod tests { let typ = params.node_key_type; node_key_config(params, &Some(net_config_dir.clone())) .and_then(move |c| match c { - NodeKeyConfig::Secp256k1(network::config::Secret::File(ref f)) - if typ == NodeKeyType::Secp256k1 && - f == &dir.join(NODE_KEY_SECP256K1_FILE) => Ok(()), NodeKeyConfig::Ed25519(network::config::Secret::File(ref f)) if typ == NodeKeyType::Ed25519 && f == &dir.join(NODE_KEY_ED25519_FILE) => Ok(()), diff --git a/core/cli/src/params.rs b/core/cli/src/params.rs index b17fc114c4f07fbeaa8b30fbe372f7bb13fad287..d0a235241667c827a025904f940f08b7555bba1b 100644 --- a/core/cli/src/params.rs +++ b/core/cli/src/params.rs @@ -17,8 +17,7 @@ use crate::traits::{AugmentClap, GetLogFilter}; use std::path::PathBuf; -use structopt::{StructOpt, clap::{arg_enum, _clap_count_exprs, App, AppSettings, SubCommand, Arg}}; -use client; +use structopt::{StructOpt, clap::{arg_enum, App, AppSettings, SubCommand, Arg}}; pub use crate::execution_strategy::ExecutionStrategy; @@ -44,6 +43,43 @@ impl Into for ExecutionStrategy { } } +arg_enum! { + /// How to execute Wasm runtime code + #[allow(missing_docs)] + #[derive(Debug, Clone)] + pub enum WasmExecutionMethod { + // Uses an interpreter. + Interpreted, + // Uses a compiled runtime. + Compiled, + } +} + +impl WasmExecutionMethod { + /// Returns list of variants that are not disabled by feature flags. + fn enabled_variants() -> Vec<&'static str> { + Self::variants() + .iter() + .cloned() + .filter(|&name| cfg!(feature = "wasmtime") || name != "Compiled") + .collect() + } +} + +impl Into for WasmExecutionMethod { + fn into(self) -> service::config::WasmExecutionMethod { + match self { + WasmExecutionMethod::Interpreted => service::config::WasmExecutionMethod::Interpreted, + #[cfg(feature = "wasmtime")] + WasmExecutionMethod::Compiled => service::config::WasmExecutionMethod::Compiled, + #[cfg(not(feature = "wasmtime"))] + WasmExecutionMethod::Compiled => panic!( + "Substrate must be compiled with \"wasmtime\" feature for compiled Wasm execution" + ), + } + } +} + arg_enum! { /// Whether off-chain workers are enabled. #[allow(missing_docs)] @@ -58,11 +94,11 @@ arg_enum! { /// Shared parameters used by all `CoreParams`. #[derive(Debug, StructOpt, Clone)] pub struct SharedParams { - /// Specify the chain specification (one of dev, local or staging) + /// Specify the chain specification (one of dev, local or staging). #[structopt(long = "chain", value_name = "CHAIN_SPEC")] pub chain: Option, - /// Specify the development chain + /// Specify the development chain. #[structopt(long = "dev")] pub dev: bool, @@ -70,7 +106,7 @@ pub struct SharedParams { #[structopt(long = "base-path", short = "d", value_name = "PATH", parse(from_os_str))] pub base_path: Option, - /// Sets a custom logging filter + /// Sets a custom logging filter. #[structopt(short = "l", long = "log", value_name = "LOG_PATTERN")] pub log: Option, } @@ -84,32 +120,43 @@ impl GetLogFilter for SharedParams { /// Parameters used to create the network configuration. #[derive(Debug, StructOpt, Clone)] pub struct NetworkConfigurationParams { - /// Specify a list of bootnodes + /// Specify a list of bootnodes. #[structopt(long = "bootnodes", value_name = "URL")] pub bootnodes: Vec, - /// Specify a list of reserved node addresses + /// Specify a list of reserved node addresses. #[structopt(long = "reserved-nodes", value_name = "URL")] pub reserved_nodes: Vec, - /// Listen on this multiaddress + /// Whether to only allow connections to/from reserved nodes. + /// + /// If you are a validator your node might still connect to other validator + /// nodes regardless of whether they are defined as reserved nodes. + #[structopt(long = "reserved-only")] + pub reserved_only: bool, + + /// Listen on this multiaddress. #[structopt(long = "listen-addr", value_name = "LISTEN_ADDR")] pub listen_addr: Vec, - /// Specify p2p protocol TCP port. Only used if --listen-addr is not specified. + /// Specify p2p protocol TCP port. + /// + /// Only used if --listen-addr is not specified. #[structopt(long = "port", value_name = "PORT")] pub port: Option, - /// Specify the number of outgoing connections we're trying to maintain + /// Specify the number of outgoing connections we're trying to maintain. #[structopt(long = "out-peers", value_name = "OUT_PEERS", default_value = "25")] pub out_peers: u32, - /// Specify the maximum number of incoming connections we're accepting + /// Specify the maximum number of incoming connections we're accepting. #[structopt(long = "in-peers", value_name = "IN_PEERS", default_value = "25")] pub in_peers: u32, - /// By default, the network will use mDNS to discover other nodes on the local network. This - /// disables it. Automatically implied when using --dev. + /// Disable mDNS discovery. + /// + /// By default, the network will use mDNS to discover other nodes on the + /// local network. This disables it. Automatically implied when using --dev. #[structopt(long = "no-mdns")] pub no_mdns: bool, @@ -119,9 +166,9 @@ pub struct NetworkConfigurationParams { } arg_enum! { + #[allow(missing_docs)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum NodeKeyType { - Secp256k1, Ed25519 } } @@ -135,10 +182,6 @@ pub struct NodeKeyParams { /// The value is a string that is parsed according to the choice of /// `--node-key-type` as follows: /// - /// `secp256k1`: - /// The value is parsed as a hex-encoded Secp256k1 32 bytes secret key, - /// i.e. 64 hex characters. - /// /// `ed25519`: /// The value is parsed as a hex-encoded Ed25519 32 bytes secret key, /// i.e. 64 hex characters. @@ -169,18 +212,12 @@ pub struct NodeKeyParams { /// /// The node's secret key determines the corresponding public key and hence the /// node's peer ID in the context of libp2p. - /// - /// NOTE: The current default key type is `secp256k1` for a transition period only - /// but will eventually change to `ed25519` in a future release. To continue using - /// `secp256k1` keys, use `--node-key-type=secp256k1`. #[structopt( long = "node-key-type", value_name = "TYPE", - raw( - possible_values = "&NodeKeyType::variants()", - case_insensitive = "true", - default_value = r#""Ed25519""# - ) + possible_values = &NodeKeyType::variants(), + case_insensitive = true, + default_value = "Ed25519" )] pub node_key_type: NodeKeyType, @@ -189,9 +226,6 @@ pub struct NodeKeyParams { /// The contents of the file are parsed according to the choice of `--node-key-type` /// as follows: /// - /// `secp256k1`: - /// The file must contain an unencoded 32 bytes Secp256k1 secret key. - /// /// `ed25519`: /// The file must contain an unencoded 32 bytes Ed25519 secret key. /// @@ -208,7 +242,7 @@ pub struct TransactionPoolParams { #[structopt(long = "pool-limit", value_name = "COUNT", default_value = "512")] pub pool_limit: usize, /// Maximum number of kilobytes of all transactions stored in the pool. - #[structopt(long = "pool-kbytes", value_name = "COUNT", default_value="10240")] + #[structopt(long = "pool-kbytes", value_name = "COUNT", default_value = "10240")] pub pool_kbytes: usize, } @@ -219,11 +253,9 @@ pub struct ExecutionStrategies { #[structopt( long = "execution-syncing", value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""NativeElseWasm""# - ) + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "NativeElseWasm" )] pub execution_syncing: ExecutionStrategy, @@ -231,11 +263,9 @@ pub struct ExecutionStrategies { #[structopt( long = "execution-import-block", value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""NativeElseWasm""# - ) + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "NativeElseWasm" )] pub execution_import_block: ExecutionStrategy, @@ -243,11 +273,9 @@ pub struct ExecutionStrategies { #[structopt( long = "execution-block-construction", value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""Wasm""# - ) + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "Wasm" )] pub execution_block_construction: ExecutionStrategy, @@ -255,11 +283,9 @@ pub struct ExecutionStrategies { #[structopt( long = "execution-offchain-worker", value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""Native""# - ) + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "Native" )] pub execution_offchain_worker: ExecutionStrategy, @@ -267,11 +293,9 @@ pub struct ExecutionStrategies { #[structopt( long = "execution-other", value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""Native""# - ) + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "Native" )] pub execution_other: ExecutionStrategy, @@ -279,17 +303,15 @@ pub struct ExecutionStrategies { #[structopt( long = "execution", value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - conflicts_with_all = "&[ - \"execution_other\", - \"execution_offchain_worker\", - \"execution_block_construction\", - \"execution_import_block\", - \"execution_syncing\", - ]" - ) + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + conflicts_with_all = &[ + "execution-other", + "execution-offchain-worker", + "execution-block-construction", + "execution-import-block", + "execution-syncing", + ] )] pub execution: Option, } @@ -297,39 +319,65 @@ pub struct ExecutionStrategies { /// The `run` command used to run a node. #[derive(Debug, StructOpt, Clone)] pub struct RunCmd { - /// Enable validator mode - #[structopt(long = "validator")] + /// Enable validator mode. + /// + /// The node will be started with the authority role and actively + /// participate in any consensus task that it can (e.g. depending on + /// availability of local keys). + #[structopt( + long = "validator", + conflicts_with_all = &[ "sentry" ] + )] pub validator: bool, - /// Disable GRANDPA voter when running in validator mode, otherwise disables the GRANDPA observer + /// Enable sentry mode. + /// + /// The node will be started with the authority role and participate in + /// consensus tasks as an "observer", it will never actively participate + /// regardless of whether it could (e.g. keys are available locally). This + /// mode is useful as a secure proxy for validators (which would run + /// detached from the network), since we want this node to participate in + /// the full consensus protocols in order to have all needed consensus data + /// available to relay to private nodes. + #[structopt( + long = "sentry", + conflicts_with_all = &[ "validator" ] + )] + pub sentry: bool, + + /// Disable GRANDPA voter when running in validator mode, otherwise disables the GRANDPA observer. #[structopt(long = "no-grandpa")] pub no_grandpa: bool, - /// Experimental: Run in light client mode + /// Experimental: Run in light client mode. #[structopt(long = "light")] pub light: bool, - /// Limit the memory the database cache can use + /// Limit the memory the database cache can use. #[structopt(long = "db-cache", value_name = "MiB")] pub database_cache_size: Option, - /// Specify the state cache size + /// Specify the state cache size. #[structopt(long = "state-cache-size", value_name = "Bytes", default_value = "67108864")] pub state_cache_size: usize, - /// Listen to all RPC interfaces (default is local) + /// Listen to all RPC interfaces. + /// + /// Default is local. #[structopt(long = "rpc-external")] pub rpc_external: bool, - /// Listen to all Websocket interfaces (default is local) + /// Listen to all Websocket interfaces. + /// + /// Default is local. #[structopt(long = "ws-external")] pub ws_external: bool, - /// Specify HTTP RPC server TCP port + /// Specify HTTP RPC server TCP port. #[structopt(long = "rpc-port", value_name = "PORT")] pub rpc_port: Option, - /// Specify WebSockets RPC server TCP port + /// Specify WebSockets RPC server TCP port. #[structopt(long = "ws-port", value_name = "PORT")] pub ws_port: Option, @@ -338,44 +386,74 @@ pub struct RunCmd { pub ws_max_connections: Option, /// Specify browser Origins allowed to access the HTTP & WS RPC servers. - /// It's a comma-separated list of origins (protocol://domain or special `null` value). - /// Value of `all` will disable origin validation. - /// Default is to allow localhost, https://polkadot.js.org and https://substrate-ui.parity.io origins. - /// When running in --dev mode the default is to allow all origins. - #[structopt(long = "rpc-cors", value_name = "ORIGINS", parse(try_from_str = "parse_cors"))] + /// + /// A comma-separated list of origins (protocol://domain or special `null` + /// value). Value of `all` will disable origin validation. Default is to + /// allow localhost, https://polkadot.js.org and + /// https://substrate-ui.parity.io origins. When running in --dev mode the + /// default is to allow all origins. + #[structopt(long = "rpc-cors", value_name = "ORIGINS", parse(try_from_str = parse_cors))] pub rpc_cors: Option, - /// Specify the pruning mode, a number of blocks to keep or 'archive'. Default is 256. + /// Specify the state pruning mode, a number of blocks to keep or 'archive'. + /// + /// Default is to keep all block states if the node is running as a + /// validator (i.e. 'archive'), otherwise state is only kept for the last + /// 256 blocks. #[structopt(long = "pruning", value_name = "PRUNING_MODE")] pub pruning: Option, - /// The human-readable name for this node, as reported to the telemetry server, if enabled + /// Force start with unsafe pruning settings. + /// + /// When running as a validator it is highly recommended to disable state + /// pruning (i.e. 'archive') which is the default. The node will refuse to + /// start as a validator if pruning is enabled unless this option is set. + #[structopt(long = "unsafe-pruning")] + pub unsafe_pruning: bool, + + /// The human-readable name for this node. + /// + /// The node name will be reported to the telemetry server, if enabled. #[structopt(long = "name", value_name = "NAME")] pub name: Option, - /// Disable connecting to the Substrate telemetry server (telemetry is on by default on global chains). + /// Disable connecting to the Substrate telemetry server. + /// + /// Telemetry is on by default on global chains. #[structopt(long = "no-telemetry")] pub no_telemetry: bool, - /// The URL of the telemetry server to connect to. This flag can be passed multiple times - /// as a mean to specify multiple telemetry endpoints. Verbosity levels range from 0-9, with - /// 0 denoting the least verbosity. If no verbosity level is specified the default is 0. - #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = "parse_telemetry_endpoints"))] + /// The URL of the telemetry server to connect to. + /// + /// This flag can be passed multiple times as a mean to specify multiple + /// telemetry endpoints. Verbosity levels range from 0-9, with 0 denoting + /// the least verbosity. If no verbosity level is specified the default is + /// 0. + #[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = parse_telemetry_endpoints))] pub telemetry_endpoints: Vec<(String, u8)>, - /// Should execute offchain workers on every block. By default it's only enabled for nodes that are authoring new - /// blocks. + /// Should execute offchain workers on every block. + /// + /// By default it's only enabled for nodes that are authoring new blocks. #[structopt( long = "offchain-worker", value_name = "ENABLED", - raw( - possible_values = "&OffchainWorkerEnabled::variants()", - case_insensitive = "true", - default_value = r#""WhenValidating""# - ) + possible_values = &OffchainWorkerEnabled::variants(), + case_insensitive = true, + default_value = "WhenValidating" )] pub offchain_worker: OffchainWorkerEnabled, + /// Method for executing Wasm runtime code. + #[structopt( + long = "wasm-execution", + value_name = "METHOD", + possible_values = &WasmExecutionMethod::enabled_variants(), + case_insensitive = true, + default_value = "Interpreted" + )] + pub wasm_method: WasmExecutionMethod, + #[allow(missing_docs)] #[structopt(flatten)] pub execution_strategies: ExecutionStrategies, @@ -407,14 +485,14 @@ pub struct RunCmd { /// Use interactive shell for entering the password used by the keystore. #[structopt( long = "password-interactive", - raw(conflicts_with_all = "&[ \"password\", \"password_filename\" ]") + conflicts_with_all = &[ "password", "password-filename" ] )] pub password_interactive: bool, /// Password used by the keystore. #[structopt( long = "password", - raw(conflicts_with_all = "&[ \"password_interactive\", \"password_filename\" ]") + conflicts_with_all = &[ "password-interactive", "password-filename" ] )] pub password: Option, @@ -423,7 +501,7 @@ pub struct RunCmd { long = "password-filename", value_name = "PATH", parse(from_os_str), - raw(conflicts_with_all = "&[ \"password_interactive\", \"password\" ]") + conflicts_with_all = &[ "password-interactive", "password" ] )] pub password_filename: Option } @@ -440,7 +518,11 @@ lazy_static::lazy_static! { /// The Cli values for all test accounts. static ref TEST_ACCOUNTS_CLI_VALUES: Vec = { keyring::Sr25519Keyring::iter().map(|a| { - let help = format!("Shortcut for `--key //{} --name {}`.", a, a); + let help = format!( + "Shortcut for `--name {} --validator` with session keys for `{}` added to keystore.", + a, + a, + ); let conflicts_with = keyring::Sr25519Keyring::iter() .filter(|b| a != *b) .map(|b| b.to_string().to_lowercase()) @@ -561,6 +643,13 @@ pub struct BuildSpecCmd { #[structopt(long = "raw")] pub raw: bool, + /// Disable adding the default bootnode to the specification. + /// + /// By default the `/ip4/127.0.0.1/tcp/30333/p2p/NODE_PEER_ID` bootnode is added to the + /// specification when no bootnode exists. + #[structopt(long = "disable-default-bootnode")] + pub disable_default_bootnode: bool, + #[allow(missing_docs)] #[structopt(flatten)] pub shared_params: SharedParams, @@ -579,11 +668,15 @@ pub struct ExportBlocksCmd { #[structopt(parse(from_os_str))] pub output: Option, - /// Specify starting block number. 1 by default. + /// Specify starting block number. + /// + /// Default is 1. #[structopt(long = "from", value_name = "BLOCK")] pub from: Option, - /// Specify last block number. Best block by default. + /// Specify last block number. + /// + /// Default is best block. #[structopt(long = "to", value_name = "BLOCK")] pub to: Option, @@ -605,7 +698,9 @@ pub struct ImportBlocksCmd { #[structopt(parse(from_os_str))] pub input: Option, - /// The default number of 64KB pages to ever allocate for Wasm execution. Don't alter this unless you know what you're doing. + /// The default number of 64KB pages to ever allocate for Wasm execution. + /// + /// Don't alter this unless you know what you're doing. #[structopt(long = "default-heap-pages", value_name = "COUNT")] pub default_heap_pages: Option, @@ -613,15 +708,23 @@ pub struct ImportBlocksCmd { #[structopt(flatten)] pub shared_params: SharedParams, + /// Method for executing Wasm runtime code. + #[structopt( + long = "wasm-execution", + value_name = "METHOD", + possible_values = &WasmExecutionMethod::variants(), + case_insensitive = true, + default_value = "Interpreted" + )] + pub wasm_method: WasmExecutionMethod, + /// The means of execution used when calling into the runtime while importing blocks. #[structopt( long = "execution", value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategy::variants()", - case_insensitive = "true", - default_value = r#""NativeElseWasm""# - ) + possible_values = &ExecutionStrategy::variants(), + case_insensitive = true, + default_value = "NativeElseWasm" )] pub execution: ExecutionStrategy, } @@ -696,11 +799,13 @@ impl StructOpt for CoreParams where ) ).subcommand( BuildSpecCmd::augment_clap(SubCommand::with_name("build-spec")) - .about("Build a spec.json file, outputing to stdout.") + .about("Build a spec.json file, outputting to stdout.") ) .subcommand( ExportBlocksCmd::augment_clap(SubCommand::with_name("export-blocks")) - .about("Export blocks to a file.") + .about("Export blocks to a file. This file can only be re-imported \ + if it is in binary format (not JSON!)." + ) ) .subcommand( ImportBlocksCmd::augment_clap(SubCommand::with_name("import-blocks")) @@ -749,7 +854,7 @@ impl GetLogFilter for CoreParams where CC: GetLogFilter { /// A special commandline parameter that expands to nothing. /// Should be used as custom subcommand/run arguments if no custom values are required. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct NoCustom {} impl StructOpt for NoCustom { diff --git a/core/client/Cargo.toml b/core/client/Cargo.toml index d917427a509f1cb3ba54038e2625db6ffa138d8a..761b2a9da21b0076bb45d2ff1f5a7cadbd5d7b53 100644 --- a/core/client/Cargo.toml +++ b/core/client/Cargo.toml @@ -5,19 +5,20 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -derive_more = { version = "0.14.0", optional = true } -fnv = { version = "1.0", optional = true } -log = { version = "0.4", optional = true } +derive_more = { version = "0.15.0", optional = true } +fnv = { version = "1.0.6", optional = true } +log = { version = "0.4.8", optional = true } parking_lot = { version = "0.9.0", optional = true } -hex = { package = "hex-literal", version = "0.2", optional = true } -futures-preview = { version = "=0.3.0-alpha.17", optional = true } +hex-literal = { version = "0.2.1", optional = true } +futures = { version = "0.1.29", optional = true } +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"], optional = true } consensus = { package = "substrate-consensus-common", path = "../consensus/common", optional = true } executor = { package = "substrate-executor", path = "../executor", optional = true } state-machine = { package = "substrate-state-machine", path = "../state-machine", optional = true } keyring = { package = "substrate-keyring", path = "../keyring", optional = true } trie = { package = "substrate-trie", path = "../trie", optional = true } substrate-telemetry = { path = "../telemetry", optional = true } -hash-db = { version = "0.15.0", default-features = false } +hash-db = { version = "0.15.2", default-features = false } kvdb = { git = "https://github.com/paritytech/parity-common", optional = true, rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } @@ -26,11 +27,15 @@ runtime-version = { package = "sr-version", path = "../sr-version", default-feat rstd = { package = "sr-std", path = "../sr-std", default-features = false } inherents = { package = "substrate-inherents", path = "../inherents", default-features = false } sr-api-macros = { path = "../sr-api-macros" } +header-metadata = { package = "substrate-header-metadata", path = "header-metadata", optional = true } [dev-dependencies] -env_logger = "0.6" +env_logger = "0.7.0" +tempfile = "3.1.0" +client-db = { package = "substrate-client-db", path = "./db", features = ["kvdb-rocksdb"] } test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } +panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } [features] default = ["std"] @@ -42,13 +47,15 @@ std = [ "sr-primitives/std", "runtime-version/std", "hash-db/std", + "header-metadata", "consensus", "parking_lot", "derive_more", "fnv", "log", - "hex", - "futures-preview", + "hex-literal", + "futures", + "futures03", "executor", "state-machine", "keyring", diff --git a/core/client/db/Cargo.toml b/core/client/db/Cargo.toml index 35440f10b0fd64ccbec3ec3501dcedb6a1135b34..161c78bcf0bc5e689ac9fa550a220be50534f44c 100644 --- a/core/client/db/Cargo.toml +++ b/core/client/db/Cargo.toml @@ -6,13 +6,13 @@ edition = "2018" [dependencies] parking_lot = "0.9.0" -log = "0.4" +log = "0.4.8" kvdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } # FIXME replace with release as soon as our rocksdb changes are released upstream https://github.com/paritytech/parity-common/issues/88 kvdb-rocksdb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d", optional = true } kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } -linked-hash-map = "0.5" -hash-db = { version = "0.15.0" } +linked-hash-map = "0.5.2" +hash-db = "0.15.2" primitives = { package = "substrate-primitives", path = "../../primitives" } sr-primitives = { path = "../../sr-primitives" } client = { package = "substrate-client", path = "../../client" } @@ -21,11 +21,12 @@ codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive executor = { package = "substrate-executor", path = "../../executor" } state_db = { package = "substrate-state-db", path = "../../state-db" } trie = { package = "substrate-trie", path = "../../trie" } +header_metadata = { package = "substrate-header-metadata", path = "../header-metadata" } [dev-dependencies] substrate-keyring = { path = "../../keyring" } test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } -env_logger = { version = "0.6" } +env_logger = "0.7.0" [features] default = [] diff --git a/core/client/db/src/cache/list_cache.rs b/core/client/db/src/cache/list_cache.rs index 10942d926f2289f2e8a44da3e8388c497afc3aaf..3e65c80b9925fb000a95c8bcde7ba5259f6bd420 100644 --- a/core/client/db/src/cache/list_cache.rs +++ b/core/client/db/src/cache/list_cache.rs @@ -87,7 +87,8 @@ pub enum CommitOperation { /// - new entry is finalized AND/OR /// - some forks are destroyed BlockFinalized(ComplexBlockId, Option>, BTreeSet), - /// When best block is reverted - contains the forks that have to be updated. + /// When best block is reverted - contains the forks that have to be updated + /// (they're either destroyed, or their best entry is updated to earlier block). BlockReverted(BTreeMap>>), } @@ -147,7 +148,7 @@ impl> Lis /// Get value valid at block. pub fn value_at_block( &self, - at: ComplexBlockId, + at: &ComplexBlockId, ) -> ClientResult, Option>, T)>> { let head = if at.number <= self.best_finalized_block.number { // if the block is older than the best known finalized block @@ -353,29 +354,38 @@ impl> Lis Ok(Some(operation)) } - /// When previously inserted block is finalized. + /// When block is reverted. pub fn on_block_revert>( &self, tx: &mut Tx, - block: NumberFor, + reverted_block: &ComplexBlockId, ) -> ClientResult> { // can't revert finalized blocks - debug_assert!(self.best_finalized_block.number < block); + debug_assert!(self.best_finalized_block.number < reverted_block.number); // iterate all unfinalized forks and truncate/destroy if required let mut updated = BTreeMap::new(); for (index, fork) in self.unfinalized.iter().enumerate() { - if fork.head.valid_from.number >= block { - let updated_fork = fork.truncate( - &self.storage, - tx, - block, - self.best_finalized_block.number, - )?; - updated.insert(index, updated_fork); + // we only need to truncate fork if its head is ancestor of truncated block + if fork.head.valid_from.number < reverted_block.number { + continue; + } + + // we only need to truncate fork if its head is connected to truncated block + if !chain::is_connected_to_block(&self.storage, reverted_block, &fork.head.valid_from)? { + continue; } + + let updated_fork = fork.truncate( + &self.storage, + tx, + reverted_block.number, + self.best_finalized_block.number, + )?; + updated.insert(index, updated_fork); } + // schedule commit operation and update meta let operation = CommitOperation::BlockReverted(updated); tx.update_meta(self.best_finalized_entry.as_ref(), &self.unfinalized, &operation); @@ -384,6 +394,7 @@ impl> Lis /// When transaction is committed. pub fn on_transaction_commit(&mut self, ops: Vec>) { +println!("=== on_transaction_commit: {:?}", ops); for op in ops { match op { CommitOperation::AppendNewBlock(index, best_block) => { @@ -412,8 +423,8 @@ impl> Lis if let Some(finalizing_entry) = finalizing_entry { self.best_finalized_entry = Some(finalizing_entry); } - for fork_index in forks.into_iter().rev() { - self.unfinalized.remove(fork_index); + for fork_index in forks.iter().rev() { + self.unfinalized.remove(*fork_index); } }, CommitOperation::BlockReverted(forks) => { @@ -613,7 +624,7 @@ impl Fork { &self, storage: &S, tx: &mut Tx, - truncating_block: NumberFor, + reverting_block: NumberFor, best_finalized_block: NumberFor, ) -> ClientResult>> { let mut current = self.head.valid_from.clone(); @@ -621,13 +632,13 @@ impl Fork { // read pointer to previous entry let entry = storage.require_entry(¤t)?; - // truncation stops when we have reached the ancestor of truncated block - if current.number < truncating_block { + // truncation stops when we have reached the ancestor of truncated block + if current.number < reverting_block { // if we have reached finalized block => destroy fork if chain::is_finalized_block(storage, ¤t, best_finalized_block)? { return Ok(None); } - + // else fork needs to be updated return Ok(Some(Fork { best_block: None, @@ -830,7 +841,7 @@ pub mod tests { // --- 50 --- // ----------> [100] assert_eq!(ListCache::<_, u64, _>::new(DummyStorage::new(), PruningStrategy::ByDepth(1024), test_id(100)) - .unwrap().value_at_block(test_id(50)).unwrap(), None); + .unwrap().value_at_block(&test_id(50)).unwrap(), None); // when block is earlier than best finalized block AND it is finalized AND value is some // [30] ---- 50 ---> [100] assert_eq!(ListCache::new( @@ -840,7 +851,7 @@ pub mod tests { .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }) .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), PruningStrategy::ByDepth(1024), test_id(100) - ).unwrap().value_at_block(test_id(50)).unwrap(), Some((test_id(30), Some(test_id(100)), 30))); + ).unwrap().value_at_block(&test_id(50)).unwrap(), Some((test_id(30), Some(test_id(100)), 30))); // when block is the best finalized block AND value is some // ---> [100] assert_eq!(ListCache::new( @@ -850,7 +861,7 @@ pub mod tests { .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }) .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), PruningStrategy::ByDepth(1024), test_id(100) - ).unwrap().value_at_block(test_id(100)).unwrap(), Some((test_id(100), None, 100))); + ).unwrap().value_at_block(&test_id(100)).unwrap(), Some((test_id(100), None, 100))); // when block is parallel to the best finalized block // ---- 100 // ---> [100] @@ -861,7 +872,7 @@ pub mod tests { .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }) .with_entry(test_id(30), StorageEntry { prev_valid_from: None, value: 30 }), PruningStrategy::ByDepth(1024), test_id(100) - ).unwrap().value_at_block(ComplexBlockId::new(H256::from_low_u64_be(2), 100)).unwrap(), None); + ).unwrap().value_at_block(&ComplexBlockId::new(H256::from_low_u64_be(2), 100)).unwrap(), None); // when block is later than last finalized block AND there are no forks AND finalized value is Some // ---> [100] --- 200 @@ -871,7 +882,7 @@ pub mod tests { .with_id(50, H256::from_low_u64_be(50)) .with_entry(test_id(100), StorageEntry { prev_valid_from: Some(test_id(30)), value: 100 }), PruningStrategy::ByDepth(1024), test_id(100) - ).unwrap().value_at_block(test_id(200)).unwrap(), Some((test_id(100), None, 100))); + ).unwrap().value_at_block(&test_id(200)).unwrap(), Some((test_id(100), None, 100))); // when block is later than last finalized block AND there are no matching forks // AND block is connected to finalized block AND finalized value is Some @@ -887,7 +898,7 @@ pub mod tests { .with_header(test_header(4)) .with_header(fork_header(0, 2, 3)), PruningStrategy::ByDepth(1024), test_id(2) - ).unwrap().value_at_block(fork_id(0, 2, 3)).unwrap(), Some((correct_id(2), None, 2))); + ).unwrap().value_at_block(&fork_id(0, 2, 3)).unwrap(), Some((correct_id(2), None, 2))); // when block is later than last finalized block AND there are no matching forks // AND block is not connected to finalized block // --- 2 --- 3 @@ -904,7 +915,7 @@ pub mod tests { .with_header(fork_header(0, 1, 3)) .with_header(fork_header(0, 1, 2)), PruningStrategy::ByDepth(1024), test_id(2) - ).unwrap().value_at_block(fork_id(0, 1, 3)).unwrap(), None); + ).unwrap().value_at_block(&fork_id(0, 1, 3)).unwrap(), None); // when block is later than last finalized block AND it appends to unfinalized fork from the end // AND unfinalized value is Some @@ -917,7 +928,7 @@ pub mod tests { .with_header(test_header(4)) .with_header(test_header(5)), PruningStrategy::ByDepth(1024), test_id(2) - ).unwrap().value_at_block(correct_id(5)).unwrap(), Some((correct_id(4), None, 4))); + ).unwrap().value_at_block(&correct_id(5)).unwrap(), Some((correct_id(4), None, 4))); // when block is later than last finalized block AND it does not fits unfinalized fork // AND it is connected to the finalized block AND finalized value is Some // ---> [2] ----------> [4] @@ -932,7 +943,7 @@ pub mod tests { .with_header(test_header(4)) .with_header(fork_header(0, 2, 3)), PruningStrategy::ByDepth(1024), test_id(2) - ).unwrap().value_at_block(fork_id(0, 2, 3)).unwrap(), Some((correct_id(2), None, 2))); + ).unwrap().value_at_block(&fork_id(0, 2, 3)).unwrap(), Some((correct_id(2), None, 2))); } #[test] @@ -1552,32 +1563,53 @@ pub mod tests { #[test] fn revert_block_works() { + // 1 -> (2) -> 3 -> 4 -> 5 + // \ + // -> 5'' + // \ + // -> (3') -> 4' -> 5' let mut cache = ListCache::new( DummyStorage::new() - .with_meta(Some(test_id(10)), vec![test_id(15), fork_id(1, 11, 17)]) - .with_id(10, test_id(10).hash) - .with_entry(test_id(10), StorageEntry { prev_valid_from: None, value: 10 }) - .with_entry(test_id(15), StorageEntry { prev_valid_from: Some(test_id(10)), value: 15 }) - .with_entry(fork_id(1, 11,13), StorageEntry { prev_valid_from: Some(test_id(10)), value: 13 }) - .with_entry(fork_id(1, 11,17), StorageEntry { prev_valid_from: Some(fork_id(1, 11, 13)), value: 17 }), - PruningStrategy::NeverPrune, test_id(10) + .with_meta(Some(correct_id(1)), vec![correct_id(5), fork_id(1, 2, 5), fork_id(2, 4, 5)]) + .with_id(1, correct_id(1).hash) + .with_entry(correct_id(1), StorageEntry { prev_valid_from: None, value: 1 }) + .with_entry(correct_id(3), StorageEntry { prev_valid_from: Some(correct_id(1)), value: 3 }) + .with_entry(correct_id(4), StorageEntry { prev_valid_from: Some(correct_id(3)), value: 4 }) + .with_entry(correct_id(5), StorageEntry { prev_valid_from: Some(correct_id(4)), value: 5 }) + .with_entry(fork_id(1, 2, 4), StorageEntry { prev_valid_from: Some(correct_id(1)), value: 14 }) + .with_entry(fork_id(1, 2, 5), StorageEntry { prev_valid_from: Some(fork_id(1, 2, 4)), value: 15 }) + .with_entry(fork_id(2, 4, 5), StorageEntry { prev_valid_from: Some(correct_id(4)), value: 25 }) + .with_header(test_header(1)) + .with_header(test_header(2)) + .with_header(test_header(3)) + .with_header(test_header(4)) + .with_header(test_header(5)) + .with_header(fork_header(1, 2, 3)) + .with_header(fork_header(1, 2, 4)) + .with_header(fork_header(1, 2, 5)) + .with_header(fork_header(2, 4, 5)), + PruningStrategy::ByDepth(1024), correct_id(1) ).unwrap(); - let op = cache.on_block_revert(&mut DummyTransaction::new(), 17).unwrap(); + // when 5 is reverted: entry 5 is truncated + let op = cache.on_block_revert(&mut DummyTransaction::new(), &correct_id(5)).unwrap(); assert_eq!(op, CommitOperation::BlockReverted(vec![ - (1, Some(Fork { best_block: None, head: Entry { valid_from: fork_id(1, 11, 13), value: 13 } })), + (0, Some(Fork { best_block: None, head: Entry { valid_from: correct_id(4), value: 4 } })), ].into_iter().collect())); cache.on_transaction_commit(vec![op]); - let op = cache.on_block_revert(&mut DummyTransaction::new(), 14).unwrap(); + // when 3 is reverted: entries 4+5' are truncated + let op = cache.on_block_revert(&mut DummyTransaction::new(), &correct_id(3)).unwrap(); assert_eq!(op, CommitOperation::BlockReverted(vec![ (0, None), + (2, None), ].into_iter().collect())); cache.on_transaction_commit(vec![op]); - let op = cache.on_block_revert(&mut DummyTransaction::new(), 11).unwrap(); + // when 2 is reverted: entries 4'+5' are truncated + let op = cache.on_block_revert(&mut DummyTransaction::new(), &correct_id(2)).unwrap(); assert_eq!(op, CommitOperation::BlockReverted(vec![ - (0, None), // it is actually 1, because 0 has been destroyed already + (0, None), ].into_iter().collect())); cache.on_transaction_commit(vec![op]); } diff --git a/core/client/db/src/cache/mod.rs b/core/client/db/src/cache/mod.rs index 04d90a34ac5d984b805df93e1f37b06867f6df37..5529c008961de76580058db296557c54056ffb9d 100644 --- a/core/client/db/src/cache/mod.rs +++ b/core/client/db/src/cache/mod.rs @@ -21,8 +21,7 @@ use parking_lot::RwLock; use kvdb::{KeyValueDB, DBTransaction}; -use client::blockchain::{well_known_cache_keys, Cache as BlockchainCache}; -use client::well_known_cache_keys::Id as CacheKeyId; +use client::blockchain::{well_known_cache_keys::{self, Id as CacheKeyId}, Cache as BlockchainCache}; use client::error::Result as ClientResult; use codec::{Encode, Decode}; use sr_primitives::generic::BlockId; @@ -241,7 +240,7 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { // prepare list of caches that are not update // (we might still need to do some cache maintenance in this case) let missed_caches = self.cache.cache_at.keys() - .filter(|cache| !data_at.contains_key(cache.clone())) + .filter(|cache| !data_at.contains_key(*cache)) .cloned() .collect::>(); @@ -307,7 +306,7 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { /// When block is reverted. pub fn on_block_revert( mut self, - block: NumberFor, + reverted_block: &ComplexBlockId, ) -> ClientResult { for (name, cache) in self.cache.cache_at.iter() { let mut cache_ops = self.cache_at_ops.remove(name).unwrap_or_default(); @@ -316,7 +315,7 @@ impl<'a, Block: BlockT> DbCacheTransaction<'a, Block> { cache.storage(), &mut self.tx ), - block, + reverted_block, )?; cache_ops.push(op); @@ -355,42 +354,52 @@ impl BlockchainCache for DbCacheSync { key: &CacheKeyId, at: &BlockId, ) -> Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)> { - let id = { - let cache = self.0.read(); - let storage = cache.cache_at.get(key)?.storage(); - let db = storage.db(); - let columns = storage.columns(); - match *at { - BlockId::Hash(hash) => { - let header = utils::read_header::( - &**db, - columns.key_lookup, - columns.header, - BlockId::Hash(hash.clone())).ok()??; - ComplexBlockId::new(hash, *header.number()) - }, - BlockId::Number(number) => { - let hash = utils::read_header::( - &**db, - columns.key_lookup, - columns.header, - BlockId::Number(number.clone())).ok()??.hash(); - ComplexBlockId::new(hash, number) - }, - } + let mut cache = self.0.write(); + let storage = cache.get_cache(*key).ok()?.storage(); + let db = storage.db(); + let columns = storage.columns(); + let at = match *at { + BlockId::Hash(hash) => { + let header = utils::read_header::( + &**db, + columns.key_lookup, + columns.header, + BlockId::Hash(hash.clone())).ok()??; + ComplexBlockId::new(hash, *header.number()) + }, + BlockId::Number(number) => { + let hash = utils::read_header::( + &**db, + columns.key_lookup, + columns.header, + BlockId::Number(number.clone())).ok()??.hash(); + ComplexBlockId::new(hash, number) + }, }; - self.0.read().cache_at.get(key)? - .value_at_block(id) + cache.cache_at + .get(key)? + .value_at_block(&at) .map(|block_and_value| block_and_value.map(|(begin_block, end_block, value)| - ((begin_block.number, begin_block.hash), end_block.map(|end_block| (end_block.number, end_block.hash)), value))) + ( + (begin_block.number, begin_block.hash), + end_block.map(|end_block| (end_block.number, end_block.hash)), + value, + ))) .ok()? } } /// Get pruning strategy for given cache. fn cache_pruning_strategy>(cache: CacheKeyId) -> PruningStrategy { + // the cache is mostly used to store data from consensus engines + // this kind of data is only required for non-finalized blocks + // => by default we prune finalized cached entries + match cache { + // we need to keep changes tries configurations forever (or at least until changes tries, + // that were built using this configuration, are pruned) to make it possible to refer + // to old changes tries well_known_cache_keys::CHANGES_TRIE_CONFIG => PruningStrategy::NeverPrune, _ => PruningStrategy::ByDepth(PRUNE_DEPTH.into()), } diff --git a/core/client/db/src/changes_tries_storage.rs b/core/client/db/src/changes_tries_storage.rs index 78e7bea870b7a2fdde73dd2a62c7ab82da172a1a..ffb946fed7353e4791fd73b64cdc0d215dcaf9f5 100644 --- a/core/client/db/src/changes_tries_storage.rs +++ b/core/client/db/src/changes_tries_storage.rs @@ -16,7 +16,7 @@ //! DB-backed changes tries storage. -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use hash_db::Prefix; use kvdb::{KeyValueDB, DBTransaction}; @@ -31,7 +31,7 @@ use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, NumberFor, One, Zero, CheckedSub, }; use sr_primitives::generic::{BlockId, DigestItem, ChangesTrieSignal}; -use state_machine::DBValue; +use state_machine::{DBValue, ChangesTrieBuildCache, ChangesTrieCacheAction}; use crate::utils::{self, Meta, meta_keys, db_err}; use crate::cache::{ DbCacheSync, DbCache, DbCacheTransactionOps, @@ -85,6 +85,7 @@ pub struct DbChangesTrieStorage { tries_meta: RwLock>, min_blocks_to_keep: Option, cache: DbCacheSync, + build_cache: RwLock>>, } /// Persistent struct that contains all the changes tries metadata. @@ -136,6 +137,7 @@ impl> DbChangesTrieStorage { genesis_hash, ComplexBlockId::new(finalized_hash, finalized_number), ))), + build_cache: RwLock::new(ChangesTrieBuildCache::new()), tries_meta: RwLock::new(tries_meta), }) } @@ -242,7 +244,7 @@ impl> DbChangesTrieStorage { pub fn revert( &self, tx: &mut DBTransaction, - block: NumberFor, + block: &ComplexBlockId, ) -> ClientResult> { Ok(self.cache.0.write().transaction(tx) .on_block_revert(block)? @@ -259,6 +261,11 @@ impl> DbChangesTrieStorage { } } + /// Commit changes into changes trie build cache. + pub fn commit_build_cache(&self, cache_update: ChangesTrieCacheAction>) { + self.build_cache.write().perform(cache_update); + } + /// Prune obsolete changes tries. fn prune( &self, @@ -327,6 +334,11 @@ impl> DbChangesTrieStorage { config, } }, + _ if config_for_new_block => { + self.configuration_at(&BlockId::Hash(*new_header.expect( + "config_for_new_block is only true when new_header is passed; qed" + ).parent_hash()))? + }, _ => self.configuration_at(&BlockId::Hash(next_digest_range_start_hash))?, }; if let Some(config) = next_config.config { @@ -451,6 +463,14 @@ where self } + fn with_cached_changed_keys( + &self, + root: &H256, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool { + self.build_cache.read().with_changed_keys(root, functor) + } + fn get(&self, key: &H256, _prefix: Prefix) -> Result, String> { self.db.get(self.changes_tries_column, &key[..]) .map_err(|err| format!("{}", err)) @@ -520,7 +540,7 @@ mod tests { let header = Header { number, parent_hash, - state_root: BlakeTwo256::trie_root::<_, &[u8], &[u8]>(Vec::new()), + state_root: BlakeTwo256::trie_root(Vec::new()), digest, extrinsics_root: Default::default(), }; @@ -534,7 +554,7 @@ mod tests { let mut op = backend.begin_operation().unwrap(); backend.begin_state_operation(&mut op, block_id).unwrap(); op.set_block_data(header, None, None, NewBlockState::Best).unwrap(); - op.update_changes_trie(changes_trie_update).unwrap(); + op.update_changes_trie((changes_trie_update, ChangesTrieCacheAction::Clear)).unwrap(); backend.commit_operation(op).unwrap(); header_hash @@ -950,7 +970,7 @@ mod tests { ); // after truncating block2_1 && block2_2 - there are still two unfinalized forks (cache impl specifics), - // though they're pointing to the same block + // the 1st one points to the block #3 because it isn't truncated backend.revert(1).unwrap(); assert_eq!( backend.changes_tries_storage.cache.0.write() @@ -960,18 +980,7 @@ mod tests { .iter() .map(|fork| fork.head().valid_from.number) .collect::>(), - vec![2, 2], - ); - assert_eq!( - backend.changes_tries_storage.cache.0.write() - .get_cache(well_known_cache_keys::CHANGES_TRIE_CONFIG) - .unwrap() - .unfinalized() - .iter() - .map(|fork| fork.head().valid_from.number) - .collect::<::std::collections::HashSet<_>>() - .len(), - 1, + vec![3, 2], ); // after truncating block2 - there are no unfinalized forks diff --git a/core/client/db/src/lib.rs b/core/client/db/src/lib.rs index f601e4b0868ab6d5c590db2fc9afd8b70128fa1b..47fac249a348e1b5fde71db666811b5f32b6e8e2 100644 --- a/core/client/db/src/lib.rs +++ b/core/client/db/src/lib.rs @@ -40,31 +40,35 @@ use std::io; use std::collections::HashMap; use client::backend::NewBlockState; -use client::blockchain::HeaderBackend; -use client::ExecutionStrategies; +use client::blockchain::{well_known_cache_keys, HeaderBackend}; +use client::{ForkBlocks, ExecutionStrategies}; use client::backend::{StorageCollection, ChildStorageCollection, PrunableStateChangesTrieStorage}; +use client::error::{Result as ClientResult, Error as ClientError}; use codec::{Decode, Encode}; use hash_db::{Hasher, Prefix}; use kvdb::{KeyValueDB, DBTransaction}; use trie::{MemoryDB, PrefixedMemoryDB, prefixed_key}; use parking_lot::{Mutex, RwLock}; -use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration}; +use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, traits::CodeExecutor}; use primitives::storage::well_known_keys; use sr_primitives::{ generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay, - BuildStorage + BuildStorage, }; use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion }; -use state_machine::backend::Backend as StateBackend; use executor::RuntimeInfo; -use state_machine::{CodeExecutor, DBValue}; -use crate::utils::{Meta, db_err, meta_keys, read_db, block_id_to_lookup_key, read_meta}; +use state_machine::{ + DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, + backend::Backend as StateBackend, +}; +use crate::utils::{Meta, db_err, meta_keys, read_db, read_meta}; use crate::changes_tries_storage::{DbChangesTrieStorage, DbChangesTrieStorageTransaction}; use client::leaves::{LeafSet, FinalizationDisplaced}; -use client::{children, well_known_cache_keys}; +use client::children; use state_db::StateDb; +use header_metadata::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache}; use crate::storage_cache::{CachingState, SharedCache, new_shared_cache}; use log::{trace, debug, warn}; pub use state_db::PruningMode; @@ -81,6 +85,9 @@ const DEFAULT_CHILD_RATIO: (usize, usize) = (1, 10); /// DB-backed patricia trie state, transaction type is an overlay of changes to commit. pub type DbState = state_machine::TrieBackend>, Blake2Hasher>; +/// Re-export the KVDB trait so that one can pass an implementation of it. +pub use kvdb; + /// A reference tracking state. /// /// It makes sure that the hash we are using stays pinned in storage @@ -109,6 +116,12 @@ impl Drop for RefTrackingState { } } +impl std::fmt::Debug for RefTrackingState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Block {:?}", self.parent_hash) + } +} + impl StateBackend for RefTrackingState { type Error = >::Error; type Transaction = >::Transaction; @@ -138,6 +151,10 @@ impl StateBackend for RefTrackingState { self.state.for_keys_with_prefix(prefix, f) } + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.state.for_key_values_with_prefix(prefix, f) + } + fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { self.state.for_keys_in_child_storage(storage_key, f) } @@ -179,16 +196,28 @@ impl StateBackend for RefTrackingState { /// Database settings. pub struct DatabaseSettings { - /// Cache size in bytes. If `None` default is used. - pub cache_size: Option, /// State cache size. pub state_cache_size: usize, /// Ratio of cache size dedicated to child tries. pub state_cache_child_ratio: Option<(usize, usize)>, - /// Path to the database. - pub path: PathBuf, /// Pruning mode. pub pruning: PruningMode, + /// Where to find the database. + pub source: DatabaseSettingsSrc, +} + +/// Where to find the database.. +pub enum DatabaseSettingsSrc { + /// Load a database from a given path. Recommended for most uses. + Path { + /// Path to the database. + path: PathBuf, + /// Cache size in bytes. If `None` default is used. + cache_size: Option, + }, + + /// Use a custom already-open database. + Custom(Arc), } /// Create an instance of db-backed client. @@ -196,20 +225,31 @@ pub fn new_client( settings: DatabaseSettings, executor: E, genesis_storage: S, + fork_blocks: ForkBlocks, execution_strategies: ExecutionStrategies, keystore: Option, -) -> Result< - client::Client, - client::LocalCallExecutor, E>, Block, RA>, client::error::Error +) -> Result<( + client::Client< + Backend, + client::LocalCallExecutor, E>, + Block, + RA, + >, + Arc>, + ), + client::error::Error, > where Block: BlockT, - E: CodeExecutor + RuntimeInfo, + E: CodeExecutor + RuntimeInfo, S: BuildStorage, { let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); let executor = client::LocalCallExecutor::new(backend.clone(), executor, keystore); - Ok(client::Client::new(backend, executor, genesis_storage, execution_strategies)?) + Ok(( + client::Client::new(backend.clone(), executor, genesis_storage, fork_blocks, execution_strategies)?, + backend, + )) } pub(crate) mod columns { @@ -251,16 +291,18 @@ pub struct BlockchainDb { db: Arc, meta: Arc, Block::Hash>>>, leaves: RwLock>>, + header_metadata_cache: HeaderMetadataCache, } impl BlockchainDb { - fn new(db: Arc) -> Result { + fn new(db: Arc) -> ClientResult { let meta = read_meta::(&*db, columns::META, columns::HEADER)?; let leaves = LeafSet::read_from_db(&*db, columns::META, meta_keys::LEAF_PREFIX)?; Ok(BlockchainDb { db, leaves: RwLock::new(leaves), meta: Arc::new(RwLock::new(meta)), + header_metadata_cache: HeaderMetadataCache::default(), }) } @@ -290,7 +332,7 @@ impl BlockchainDb { } impl client::blockchain::HeaderBackend for BlockchainDb { - fn header(&self, id: BlockId) -> Result, client::error::Error> { + fn header(&self, id: BlockId) -> ClientResult> { utils::read_header(&*self.db, columns::KEY_LOOKUP, columns::HEADER, id) } @@ -305,7 +347,7 @@ impl client::blockchain::HeaderBackend for BlockchainDb) -> Result { + fn status(&self, id: BlockId) -> ClientResult { let exists = match id { BlockId::Hash(_) => read_db( &*self.db, @@ -321,16 +363,11 @@ impl client::blockchain::HeaderBackend for BlockchainDb Result>, client::error::Error> { - if let Some(lookup_key) = block_id_to_lookup_key::(&*self.db, columns::KEY_LOOKUP, BlockId::Hash(hash))? { - let number = utils::lookup_key_to_number(&lookup_key)?; - Ok(Some(number)) - } else { - Ok(None) - } + fn number(&self, hash: Block::Hash) -> ClientResult>> { + Ok(self.header_metadata(hash).ok().map(|header_metadata| header_metadata.number)) } - fn hash(&self, number: NumberFor) -> Result, client::error::Error> { + fn hash(&self, number: NumberFor) -> ClientResult> { self.header(BlockId::Number(number)).and_then(|maybe_header| match maybe_header { Some(header) => Ok(Some(header.hash().clone())), None => Ok(None), @@ -339,7 +376,7 @@ impl client::blockchain::HeaderBackend for BlockchainDb client::blockchain::Backend for BlockchainDb { - fn body(&self, id: BlockId) -> Result>, client::error::Error> { + fn body(&self, id: BlockId) -> ClientResult>> { match read_db(&*self.db, columns::KEY_LOOKUP, columns::BODY, id)? { Some(body) => match Decode::decode(&mut &body[..]) { Ok(body) => Ok(Some(body)), @@ -351,7 +388,7 @@ impl client::blockchain::Backend for BlockchainDb { } } - fn justification(&self, id: BlockId) -> Result, client::error::Error> { + fn justification(&self, id: BlockId) -> ClientResult> { match read_db(&*self.db, columns::KEY_LOOKUP, columns::JUSTIFICATION, id)? { Some(justification) => match Decode::decode(&mut &justification[..]) { Ok(justification) => Ok(Some(justification)), @@ -363,7 +400,7 @@ impl client::blockchain::Backend for BlockchainDb { } } - fn last_finalized(&self) -> Result { + fn last_finalized(&self) -> ClientResult { Ok(self.meta.read().finalized_hash.clone()) } @@ -371,11 +408,11 @@ impl client::blockchain::Backend for BlockchainDb { None } - fn leaves(&self) -> Result, client::error::Error> { + fn leaves(&self) -> ClientResult> { Ok(self.leaves.read().hashes()) } - fn children(&self, parent_hash: Block::Hash) -> Result, client::error::Error> { + fn children(&self, parent_hash: Block::Hash) -> ClientResult> { children::read_children(&*self.db, columns::META, meta_keys::CHILDREN_PREFIX, parent_hash) } } @@ -386,6 +423,31 @@ impl client::blockchain::ProvideCache for BlockchainDb HeaderMetadata for BlockchainDb { + type Error = client::error::Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.header_metadata_cache.header_metadata(hash).or_else(|_| { + self.header(BlockId::hash(hash))?.map(|header| { + let header_metadata = CachedHeaderMetadata::from(&header); + self.header_metadata_cache.insert_header_metadata( + header_metadata.hash, + header_metadata.clone(), + ); + header_metadata + }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) + }) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.header_metadata_cache.insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.header_metadata_cache.remove_header_metadata(hash); + } +} + /// Database transaction pub struct BlockImportOperation { old_state: CachingState, Block>, @@ -393,6 +455,7 @@ pub struct BlockImportOperation { storage_updates: StorageCollection, child_storage_updates: ChildStorageCollection, changes_trie_updates: MemoryDB, + changes_trie_cache_update: Option>>, changes_trie_config_update: Option>, pending_block: Option>, aux_ops: Vec<(Vec, Option>)>, @@ -412,12 +475,11 @@ impl BlockImportOperation { } impl client::backend::BlockImportOperation -for BlockImportOperation -where Block: BlockT, + for BlockImportOperation where Block: BlockT, { type State = CachingState, Block>; - fn state(&self) -> Result, client::error::Error> { + fn state(&self) -> ClientResult> { Ok(Some(&self.old_state)) } @@ -427,7 +489,7 @@ where Block: BlockT, body: Option>, justification: Option, leaf_state: NewBlockState, - ) -> Result<(), client::error::Error> { + ) -> ClientResult<()> { assert!(self.pending_block.is_none(), "Only one block per operation is allowed"); if let Some(changes_trie_config_update) = changes_tries_storage::extract_new_configuration(&header) { self.changes_trie_config_update = Some(changes_trie_config_update.clone()); @@ -445,7 +507,7 @@ where Block: BlockT, // Currently cache isn't implemented on full nodes. } - fn update_db_storage(&mut self, update: PrefixedMemoryDB) -> Result<(), client::error::Error> { + fn update_db_storage(&mut self, update: PrefixedMemoryDB) -> ClientResult<()> { self.db_updates = update; Ok(()) } @@ -454,7 +516,7 @@ where Block: BlockT, &mut self, top: StorageOverlay, children: ChildrenStorageOverlay - ) -> Result { + ) -> ClientResult { if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { return Err(client::error::Error::GenesisInvalid.into()); @@ -490,12 +552,16 @@ where Block: BlockT, Ok(root) } - fn update_changes_trie(&mut self, update: MemoryDB) -> Result<(), client::error::Error> { - self.changes_trie_updates = update; + fn update_changes_trie( + &mut self, + update: ChangesTrieTransaction>, + ) -> ClientResult<()> { + self.changes_trie_updates = update.0; + self.changes_trie_cache_update = Some(update.1); Ok(()) } - fn insert_aux(&mut self, ops: I) -> Result<(), client::error::Error> + fn insert_aux(&mut self, ops: I) -> ClientResult<()> where I: IntoIterator, Option>)> { self.aux_ops.append(&mut ops.into_iter().collect()); @@ -506,18 +572,18 @@ where Block: BlockT, &mut self, update: StorageCollection, child_update: ChildStorageCollection, - ) -> Result<(), client::error::Error> { + ) -> ClientResult<()> { self.storage_updates = update; self.child_storage_updates = child_update; Ok(()) } - fn mark_finalized(&mut self, block: BlockId, justification: Option) -> Result<(), client::error::Error> { + fn mark_finalized(&mut self, block: BlockId, justification: Option) -> ClientResult<()> { self.finalized_blocks.push((block, justification)); Ok(()) } - fn mark_head(&mut self, block: BlockId) -> Result<(), client::error::Error> { + fn mark_head(&mut self, block: BlockId) -> ClientResult<()> { assert!(self.set_head.is_none(), "Only one set head per operation is allowed"); self.set_head = Some(block); Ok(()) @@ -579,18 +645,8 @@ impl> Backend { /// Create a new instance of database backend. /// /// The pruning window is how old a block must be before the state is pruned. - pub fn new(config: DatabaseSettings, canonicalization_delay: u64) -> client::error::Result { - Self::new_inner(config, canonicalization_delay) - } - - fn new_inner(config: DatabaseSettings, canonicalization_delay: u64) -> Result { - #[cfg(feature = "kvdb-rocksdb")] + pub fn new(config: DatabaseSettings, canonicalization_delay: u64) -> ClientResult { let db = crate::utils::open_database(&config, columns::META, "full")?; - #[cfg(not(feature = "kvdb-rocksdb"))] - let db = { - log::warn!("Running without the RocksDB feature. The database will NOT be saved."); - Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)) - }; Self::from_kvdb(db as Arc<_>, canonicalization_delay, &config) } @@ -598,32 +654,21 @@ impl> Backend { #[cfg(any(test, feature = "test-helpers"))] pub fn new_test(keep_blocks: u32, canonicalization_delay: u64) -> Self { let db = Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); - Self::new_test_db(keep_blocks, canonicalization_delay, db as Arc<_>) - } - - /// Creates a client backend with test settings. - #[cfg(any(test, feature = "test-helpers"))] - pub fn new_test_db(keep_blocks: u32, canonicalization_delay: u64, db: Arc) -> Self { - let db_setting = DatabaseSettings { - cache_size: None, state_cache_size: 16777216, state_cache_child_ratio: Some((50, 100)), - path: Default::default(), pruning: PruningMode::keep_blocks(keep_blocks), + source: DatabaseSettingsSrc::Custom(db), }; - Self::from_kvdb( - db, - canonicalization_delay, - &db_setting, - ).expect("failed to create test-db") + + Self::new(db_setting, canonicalization_delay).expect("failed to create test-db") } fn from_kvdb( db: Arc, canonicalization_delay: u64, config: &DatabaseSettings - ) -> Result { + ) -> ClientResult { let is_archive_pruning = config.pruning.is_archive(); let blockchain = BlockchainDb::new(db.clone())?; let meta = blockchain.meta.clone(); @@ -714,7 +759,12 @@ impl> Backend { /// In the case where the new best block is a block to be imported, `route_to` /// should be the parent of `best_to`. In the case where we set an existing block /// to be best, `route_to` should equal to `best_to`. - fn set_head_with_transaction(&self, transaction: &mut DBTransaction, route_to: Block::Hash, best_to: (NumberFor, Block::Hash)) -> Result<(Vec, Vec), client::error::Error> { + fn set_head_with_transaction( + &self, + transaction: &mut DBTransaction, + route_to: Block::Hash, + best_to: (NumberFor, Block::Hash), + ) -> ClientResult<(Vec, Vec)> { let mut enacted = Vec::default(); let mut retracted = Vec::default(); @@ -722,10 +772,10 @@ impl> Backend { // cannot find tree route with empty DB. if meta.best_hash != Default::default() { - let tree_route = ::client::blockchain::tree_route( + let tree_route = header_metadata::tree_route( &self.blockchain, - BlockId::Hash(meta.best_hash), - BlockId::Hash(route_to), + meta.best_hash, + route_to, )?; // uncanonicalize: check safety violations and ensure the numbers no longer @@ -776,7 +826,7 @@ impl> Backend { &self, header: &Block::Header, last_finalized: Option, - ) -> Result<(), client::error::Error> { + ) -> ClientResult<()> { let last_finalized = last_finalized.unwrap_or_else(|| self.blockchain.meta.read().finalized_hash); if *header.parent_hash() != last_finalized { return Err(::client::error::Error::NonSequentialFinalization( @@ -795,7 +845,7 @@ impl> Backend { justification: Option, changes_trie_cache_ops: &mut Option>, finalization_displaced: &mut Option>>, - ) -> Result<(Block::Hash, ::Number, bool, bool), client::error::Error> { + ) -> ClientResult<(Block::Hash, ::Number, bool, bool)> { // TODO: ensure best chain contains this block. let number = *header.number(); self.ensure_sequential_finalization(header, last_finalized)?; @@ -825,7 +875,7 @@ impl> Backend { hash: Block::Hash, number: NumberFor, ) - -> Result<(), client::error::Error> + -> ClientResult<()> { let number_u64 = number.saturated_into::(); if number_u64 > self.canonicalization_delay { @@ -853,33 +903,31 @@ impl> Backend { } fn try_commit_operation(&self, mut operation: BlockImportOperation) - -> Result<(), client::error::Error> + -> ClientResult<()> { let mut transaction = DBTransaction::new(); let mut finalization_displaced_leaves = None; operation.apply_aux(&mut transaction); - let mut meta_updates = Vec::new(); + let mut meta_updates = Vec::with_capacity(operation.finalized_blocks.len()); let mut last_finalized_hash = self.blockchain.meta.read().finalized_hash; let mut changes_trie_cache_ops = None; - if !operation.finalized_blocks.is_empty() { - for (block, justification) in operation.finalized_blocks { - let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; - let block_header = self.blockchain.expect_header(BlockId::Hash(block_hash))?; + for (block, justification) in operation.finalized_blocks { + let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; + let block_header = self.blockchain.expect_header(BlockId::Hash(block_hash))?; - meta_updates.push(self.finalize_block_with_transaction( - &mut transaction, - &block_hash, - &block_header, - Some(last_finalized_hash), - justification, - &mut changes_trie_cache_ops, - &mut finalization_displaced_leaves, - )?); - last_finalized_hash = block_hash; - } + meta_updates.push(self.finalize_block_with_transaction( + &mut transaction, + &block_hash, + &block_header, + Some(last_finalized_hash), + justification, + &mut changes_trie_cache_ops, + &mut finalization_displaced_leaves, + )?); + last_finalized_hash = block_hash; } let imported = if let Some(pending_block) = operation.pending_block { @@ -903,6 +951,12 @@ impl> Backend { hash, )?; + let header_metadata = CachedHeaderMetadata::from(&pending_block.header); + self.blockchain.insert_header_metadata( + header_metadata.hash, + header_metadata, + ); + transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode()); if let Some(body) = pending_block.body { transaction.put(columns::BODY, &lookup_key, &body.encode()); @@ -1014,6 +1068,10 @@ impl> Backend { let write_result = self.storage.db.write(transaction).map_err(db_err); + if let Some(changes_trie_cache_update) = operation.changes_trie_cache_update { + self.changes_tries_storage.commit_build_cache(changes_trie_cache_update); + } + if let Some(( number, hash, @@ -1074,7 +1132,7 @@ impl> Backend { f_hash: Block::Hash, changes_trie_cache_ops: &mut Option>, displaced: &mut Option>>, - ) -> Result<(), client::error::Error> where + ) -> ClientResult<()> where Block: BlockT, { let f_num = f_header.number().clone(); @@ -1132,7 +1190,7 @@ impl client::backend::AuxStore for Backend where Block: BlockT, D: IntoIterator, - >(&self, insert: I, delete: D) -> client::error::Result<()> { + >(&self, insert: I, delete: D) -> ClientResult<()> { let mut transaction = DBTransaction::new(); for (k, v) in insert { transaction.put(columns::AUX, k, v); @@ -1144,7 +1202,7 @@ impl client::backend::AuxStore for Backend where Block: BlockT Result>, client::error::Error> { + fn get_aux(&self, key: &[u8]) -> ClientResult>> { Ok(self.storage.db.get(columns::AUX, key).map(|r| r.map(|v| v.to_vec())).map_err(db_err)?) } } @@ -1155,7 +1213,7 @@ impl client::backend::Backend for Backend whe type State = CachingState, Block>; type OffchainStorage = offchain::LocalStorage; - fn begin_operation(&self) -> Result { + fn begin_operation(&self) -> ClientResult { let old_state = self.state_at(BlockId::Hash(Default::default()))?; Ok(BlockImportOperation { pending_block: None, @@ -1165,19 +1223,24 @@ impl client::backend::Backend for Backend whe child_storage_updates: Default::default(), changes_trie_config_update: None, changes_trie_updates: MemoryDB::default(), + changes_trie_cache_update: None, aux_ops: Vec::new(), finalized_blocks: Vec::new(), set_head: None, }) } - fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId) -> Result<(), client::error::Error> { + fn begin_state_operation( + &self, + operation: &mut Self::BlockImportOperation, + block: BlockId, + ) -> ClientResult<()> { operation.old_state = self.state_at(block)?; Ok(()) } fn commit_operation(&self, operation: Self::BlockImportOperation) - -> Result<(), client::error::Error> + -> ClientResult<()> { match self.try_commit_operation(operation) { Ok(_) => { @@ -1192,7 +1255,7 @@ impl client::backend::Backend for Backend whe } fn finalize_block(&self, block: BlockId, justification: Option) - -> Result<(), client::error::Error> + -> ClientResult<()> { let mut transaction = DBTransaction::new(); let hash = self.blockchain.expect_block_hash_from_id(&block)?; @@ -1235,7 +1298,7 @@ impl client::backend::Backend for Backend whe Some(self.offchain_storage.clone()) } - fn revert(&self, n: NumberFor) -> Result, client::error::Error> { + fn revert(&self, n: NumberFor) -> ClientResult> { let mut best = self.blockchain.info().best_number; let finalized = self.blockchain.info().finalized_number; let revertible = best - finalized; @@ -1259,7 +1322,13 @@ impl client::backend::Backend for Backend whe || client::error::Error::UnknownBlock( format!("Error reverting to {}. Block hash not found.", best)))?; let key = utils::number_and_hash_to_lookup_key(best.clone(), &hash)?; - let changes_trie_cache_ops = self.changes_tries_storage.revert(&mut transaction, removed_number)?; + let changes_trie_cache_ops = self.changes_tries_storage.revert( + &mut transaction, + &cache::ComplexBlockId::new( + removed.hash(), + removed_number, + ), + )?; transaction.put(columns::META, meta_keys::BEST_BLOCK, &key); transaction.delete(columns::KEY_LOOKUP, removed.hash().as_ref()); children::remove_children(&mut transaction, columns::META, meta_keys::CHILDREN_PREFIX, hash); @@ -1283,7 +1352,7 @@ impl client::backend::Backend for Backend whe Some(used) } - fn state_at(&self, block: BlockId) -> Result { + fn state_at(&self, block: BlockId) -> ClientResult { use client::blockchain::HeaderBackend as BcHeaderBackend; // special case for genesis initialization @@ -1319,7 +1388,7 @@ impl client::backend::Backend for Backend whe !self.storage.state_db.is_pruned(hash, number.saturated_into::()) } - fn destroy_state(&self, state: Self::State) -> Result<(), client::error::Error> { + fn destroy_state(&self, state: Self::State) -> ClientResult<()> { if let Some(hash) = state.cache.parent_hash.clone() { let is_best = || self.blockchain.meta.read().best_hash == hash; state.release().sync_cache(&[], &[], vec![], vec![], None, None, is_best); @@ -1346,7 +1415,8 @@ pub(crate) mod tests { use sr_primitives::generic::DigestItem; use sr_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; use sr_primitives::traits::{Hash, BlakeTwo256}; - use state_machine::{TrieMut, TrieDBMut}; + use state_machine::{TrieMut, TrieDBMut, ChangesTrieRootsStorage, ChangesTrieStorage}; + use header_metadata::{lowest_common_ancestor, tree_route}; use test_client; pub type Block = RawBlock>; @@ -1386,7 +1456,7 @@ pub(crate) mod tests { let header = Header { number, parent_hash, - state_root: BlakeTwo256::trie_root::<_, &[u8], &[u8]>(Vec::new()), + state_root: BlakeTwo256::trie_root(Vec::new()), digest, extrinsics_root, }; @@ -1400,7 +1470,7 @@ pub(crate) mod tests { let mut op = backend.begin_operation().unwrap(); backend.begin_state_operation(&mut op, block_id).unwrap(); op.set_block_data(header, None, None, NewBlockState::Best).unwrap(); - op.update_changes_trie(changes_trie_update).unwrap(); + op.update_changes_trie((changes_trie_update, ChangesTrieCacheAction::Clear)).unwrap(); backend.commit_operation(op).unwrap(); header_hash @@ -1448,7 +1518,12 @@ pub(crate) mod tests { db.storage.db.clone() }; - let backend = Backend::::new_test_db(1, 0, backing); + let backend = Backend::::new(DatabaseSettings { + state_cache_size: 16777216, + state_cache_child_ratio: Some((50, 100)), + pruning: PruningMode::keep_blocks(1), + source: DatabaseSettingsSrc::Custom(backing), + }, 0).unwrap(); assert_eq!(backend.blockchain().info().best_number, 9); for i in 0..10 { assert!(backend.blockchain().hash(i).unwrap().is_some()) @@ -1701,6 +1776,7 @@ pub(crate) mod tests { #[test] fn tree_route_works() { let backend = Backend::::new_test(1000, 100); + let blockchain = backend.blockchain(); let block0 = insert_header(&backend, 0, Default::default(), None, Default::default()); // fork from genesis: 3 prong. @@ -1713,11 +1789,7 @@ pub(crate) mod tests { let b2 = insert_header(&backend, 2, b1, None, Default::default()); { - let tree_route = ::client::blockchain::tree_route( - backend.blockchain(), - BlockId::Hash(a3), - BlockId::Hash(b2) - ).unwrap(); + let tree_route = tree_route(blockchain, a3, b2).unwrap(); assert_eq!(tree_route.common_block().hash, block0); assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2, a1]); @@ -1725,11 +1797,7 @@ pub(crate) mod tests { } { - let tree_route = ::client::blockchain::tree_route( - backend.blockchain(), - BlockId::Hash(a1), - BlockId::Hash(a3), - ).unwrap(); + let tree_route = tree_route(blockchain, a1, a3).unwrap(); assert_eq!(tree_route.common_block().hash, a1); assert!(tree_route.retracted().is_empty()); @@ -1737,11 +1805,7 @@ pub(crate) mod tests { } { - let tree_route = ::client::blockchain::tree_route( - backend.blockchain(), - BlockId::Hash(a3), - BlockId::Hash(a1), - ).unwrap(); + let tree_route = tree_route(blockchain, a3, a1).unwrap(); assert_eq!(tree_route.common_block().hash, a1); assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2]); @@ -1749,11 +1813,7 @@ pub(crate) mod tests { } { - let tree_route = ::client::blockchain::tree_route( - backend.blockchain(), - BlockId::Hash(a2), - BlockId::Hash(a2), - ).unwrap(); + let tree_route = tree_route(blockchain, a2, a2).unwrap(); assert_eq!(tree_route.common_block().hash, a2); assert!(tree_route.retracted().is_empty()); @@ -1764,16 +1824,13 @@ pub(crate) mod tests { #[test] fn tree_route_child() { let backend = Backend::::new_test(1000, 100); + let blockchain = backend.blockchain(); let block0 = insert_header(&backend, 0, Default::default(), None, Default::default()); let block1 = insert_header(&backend, 1, block0, None, Default::default()); { - let tree_route = ::client::blockchain::tree_route( - backend.blockchain(), - BlockId::Hash(block0), - BlockId::Hash(block1), - ).unwrap(); + let tree_route = tree_route(blockchain, block0, block1).unwrap(); assert_eq!(tree_route.common_block().hash, block0); assert!(tree_route.retracted().is_empty()); @@ -1781,6 +1838,98 @@ pub(crate) mod tests { } } + #[test] + fn lowest_common_ancestor_works() { + let backend = Backend::::new_test(1000, 100); + let blockchain = backend.blockchain(); + let block0 = insert_header(&backend, 0, Default::default(), None, Default::default()); + + // fork from genesis: 3 prong. + let a1 = insert_header(&backend, 1, block0, None, Default::default()); + let a2 = insert_header(&backend, 2, a1, None, Default::default()); + let a3 = insert_header(&backend, 3, a2, None, Default::default()); + + // fork from genesis: 2 prong. + let b1 = insert_header(&backend, 1, block0, None, H256::from([1; 32])); + let b2 = insert_header(&backend, 2, b1, None, Default::default()); + + { + let lca = lowest_common_ancestor(blockchain, a3, b2).unwrap(); + + assert_eq!(lca.hash, block0); + assert_eq!(lca.number, 0); + } + + { + let lca = lowest_common_ancestor(blockchain, a1, a3).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(blockchain, a3, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(blockchain, a2, a3).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + + { + let lca = lowest_common_ancestor(blockchain, a2, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(blockchain, a2, a2).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + } + + #[test] + fn test_tree_route_regression() { + // NOTE: this is a test for a regression introduced in #3665, the result + // of tree_route would be erroneously computed, since it was taking into + // account the `ancestor` in `CachedHeaderMetadata` for the comparison. + // in this test we simulate the same behavior with the side-effect + // triggering the issue being eviction of a previously fetched record + // from the cache, therefore this test is dependent on the LRU cache + // size for header metadata, which is currently set to 5000 elements. + let backend = Backend::::new_test(10000, 10000); + let blockchain = backend.blockchain(); + + let genesis = insert_header(&backend, 0, Default::default(), None, Default::default()); + + let block100 = (1..=100).fold(genesis, |parent, n| { + insert_header(&backend, n, parent, None, Default::default()) + }); + + let block7000 = (101..=7000).fold(block100, |parent, n| { + insert_header(&backend, n, parent, None, Default::default()) + }); + + // This will cause the ancestor of `block100` to be set to `genesis` as a side-effect. + lowest_common_ancestor(blockchain, genesis, block100).unwrap(); + + // While traversing the tree we will have to do 6900 calls to + // `header_metadata`, which will make sure we will exhaust our cache + // which only takes 5000 elements. In particular, the `CachedHeaderMetadata` struct for + // block #100 will be evicted and will get a new value (with ancestor set to its parent). + let tree_route = tree_route(blockchain, block100, block7000).unwrap(); + + assert!(tree_route.retracted().is_empty()); + } + #[test] fn test_leaves_with_complex_block_tree() { let backend: Arc> = Arc::new(Backend::new_test(20, 20)); diff --git a/core/client/db/src/light.rs b/core/client/db/src/light.rs index 415f9e811906c99dc6c26ee6ac5c6cec93b6364b..e0adc7e59c647404e2882e0423639a6311003d6e 100644 --- a/core/client/db/src/light.rs +++ b/core/client/db/src/light.rs @@ -23,15 +23,19 @@ use parking_lot::RwLock; use kvdb::{KeyValueDB, DBTransaction}; use client::backend::{AuxStore, NewBlockState}; -use client::blockchain::{BlockStatus, Cache as BlockchainCache, - HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo}; -use client::{cht, well_known_cache_keys}; +use client::blockchain::{ + BlockStatus, Cache as BlockchainCache, + HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo, + well_known_cache_keys, +}; +use client::cht; use client::error::{Error as ClientError, Result as ClientResult}; use client::light::blockchain::Storage as LightBlockchainStorage; use codec::{Decode, Encode}; use primitives::Blake2Hasher; use sr_primitives::generic::{DigestItem, BlockId}; use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor}; +use header_metadata::{CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache}; use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType}; use crate::utils::{self, meta_keys, Meta, db_err, read_db, block_id_to_lookup_key, read_meta}; use crate::DatabaseSettings; @@ -57,6 +61,7 @@ pub struct LightStorage { db: Arc, meta: RwLock, Block::Hash>>, cache: Arc>, + header_metadata_cache: HeaderMetadataCache, } impl LightStorage @@ -65,22 +70,10 @@ impl LightStorage { /// Create new storage with given settings. pub fn new(config: DatabaseSettings) -> ClientResult { - Self::new_inner(config) - } - - #[cfg(feature = "kvdb-rocksdb")] - fn new_inner(config: DatabaseSettings) -> ClientResult { let db = crate::utils::open_database(&config, columns::META, "light")?; Self::from_kvdb(db as Arc<_>) } - #[cfg(not(feature = "kvdb-rocksdb"))] - fn new_inner(_config: DatabaseSettings) -> ClientResult { - log::warn!("Running without the RocksDB feature. The database will NOT be saved."); - let db = Arc::new(kvdb_memorydb::create(crate::utils::NUM_COLUMNS)); - Self::from_kvdb(db as Arc<_>) - } - /// Create new memory-backed `LightStorage` for tests. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test() -> Self { @@ -106,6 +99,7 @@ impl LightStorage db, meta: RwLock::new(meta), cache: Arc::new(DbCacheSync(RwLock::new(cache))), + header_metadata_cache: HeaderMetadataCache::default(), }) } @@ -189,6 +183,31 @@ impl BlockchainHeaderBackend for LightStorage } } +impl HeaderMetadata for LightStorage { + type Error = ClientError; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.header_metadata_cache.header_metadata(hash).or_else(|_| { + self.header(BlockId::hash(hash))?.map(|header| { + let header_metadata = CachedHeaderMetadata::from(&header); + self.header_metadata_cache.insert_header_metadata( + header_metadata.hash, + header_metadata.clone(), + ); + header_metadata + }).ok_or(ClientError::UnknownBlock(format!("header not found in db: {}", hash))) + }) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.header_metadata_cache.insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.header_metadata_cache.remove_header_metadata(hash); + } +} + impl LightStorage { // Get block changes trie root, if available. fn changes_trie_root(&self, block: BlockId) -> ClientResult> { @@ -205,17 +224,18 @@ impl LightStorage { /// In the case where the new best block is a block to be imported, `route_to` /// should be the parent of `best_to`. In the case where we set an existing block /// to be best, `route_to` should equal to `best_to`. - fn set_head_with_transaction(&self, transaction: &mut DBTransaction, route_to: Block::Hash, best_to: (NumberFor, Block::Hash)) -> Result<(), client::error::Error> { + fn set_head_with_transaction( + &self, + transaction: &mut DBTransaction, + route_to: Block::Hash, + best_to: (NumberFor, Block::Hash), + ) -> ClientResult<()> { let lookup_key = utils::number_and_hash_to_lookup_key(best_to.0, &best_to.1)?; // handle reorg. let meta = self.meta.read(); if meta.best_hash != Default::default() { - let tree_route = ::client::blockchain::tree_route( - self, - BlockId::Hash(meta.best_hash), - BlockId::Hash(route_to), - )?; + let tree_route = header_metadata::tree_route(self, meta.best_hash, route_to)?; // update block number to hash lookup entries. for retracted in tree_route.retracted() { @@ -415,6 +435,12 @@ impl LightBlockchainStorage for LightStorage )?; transaction.put(columns::HEADER, &lookup_key, &header.encode()); + let header_metadata = CachedHeaderMetadata::from(&header); + self.header_metadata_cache.insert_header_metadata( + header.hash().clone(), + header_metadata, + ); + let is_genesis = number.is_zero(); if is_genesis { self.cache.0.write().set_genesis_hash(hash); @@ -547,6 +573,7 @@ pub(crate) mod tests { use primitives::ChangesTrieConfiguration; use sr_primitives::generic::{BlockId, DigestItem, ChangesTrieSignal}; use sr_primitives::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper}; + use header_metadata::{lowest_common_ancestor, tree_route}; use super::*; type Block = RawBlock>; @@ -791,11 +818,7 @@ pub(crate) mod tests { let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); { - let tree_route = ::client::blockchain::tree_route( - &db, - BlockId::Hash(a3), - BlockId::Hash(b2) - ).unwrap(); + let tree_route = tree_route(&db, a3, b2).unwrap(); assert_eq!(tree_route.common_block().hash, block0); assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2, a1]); @@ -803,11 +826,7 @@ pub(crate) mod tests { } { - let tree_route = ::client::blockchain::tree_route( - &db, - BlockId::Hash(a1), - BlockId::Hash(a3), - ).unwrap(); + let tree_route = tree_route(&db, a1, a3).unwrap(); assert_eq!(tree_route.common_block().hash, a1); assert!(tree_route.retracted().is_empty()); @@ -815,11 +834,7 @@ pub(crate) mod tests { } { - let tree_route = ::client::blockchain::tree_route( - &db, - BlockId::Hash(a3), - BlockId::Hash(a1), - ).unwrap(); + let tree_route = tree_route(&db, a3, a1).unwrap(); assert_eq!(tree_route.common_block().hash, a1); assert_eq!(tree_route.retracted().iter().map(|r| r.hash).collect::>(), vec![a3, a2]); @@ -827,11 +842,7 @@ pub(crate) mod tests { } { - let tree_route = ::client::blockchain::tree_route( - &db, - BlockId::Hash(a2), - BlockId::Hash(a2), - ).unwrap(); + let tree_route = tree_route(&db, a2, a2).unwrap(); assert_eq!(tree_route.common_block().hash, a2); assert!(tree_route.retracted().is_empty()); @@ -839,6 +850,63 @@ pub(crate) mod tests { } } + #[test] + fn lowest_common_ancestor_works() { + let db = LightStorage::new_test(); + let block0 = insert_block(&db, HashMap::new(), || default_header(&Default::default(), 0)); + + // fork from genesis: 3 prong. + let a1 = insert_block(&db, HashMap::new(), || default_header(&block0, 1)); + let a2 = insert_block(&db, HashMap::new(), || default_header(&a1, 2)); + let a3 = insert_block(&db, HashMap::new(), || default_header(&a2, 3)); + + // fork from genesis: 2 prong. + let b1 = insert_block(&db, HashMap::new(), || header_with_extrinsics_root(&block0, 1, Hash::from([1; 32]))); + let b2 = insert_block(&db, HashMap::new(), || default_header(&b1, 2)); + + { + let lca = lowest_common_ancestor(&db, a3, b2).unwrap(); + + assert_eq!(lca.hash, block0); + assert_eq!(lca.number, 0); + } + + { + let lca = lowest_common_ancestor(&db, a1, a3).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(&db, a3, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(&db, a2, a3).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + + { + let lca = lowest_common_ancestor(&db, a2, a1).unwrap(); + + assert_eq!(lca.hash, a1); + assert_eq!(lca.number, 1); + } + + { + let lca = lowest_common_ancestor(&db, a2, a2).unwrap(); + + assert_eq!(lca.hash, a2); + assert_eq!(lca.number, 2); + } + } + #[test] fn authorities_are_cached() { let db = LightStorage::new_test(); @@ -1042,27 +1110,41 @@ pub(crate) mod tests { #[test] fn cache_can_be_initialized_after_genesis_inserted() { - let db = LightStorage::::new_test(); + let (genesis_hash, storage) = { + let db = LightStorage::::new_test(); + + // before cache is initialized => None + assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); + + // insert genesis block (no value for cache is provided) + let mut genesis_hash = None; + insert_block(&db, HashMap::new(), || { + let header = default_header(&Default::default(), 0); + genesis_hash = Some(header.hash()); + header + }); - // before cache is initialized => None - assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); + // after genesis is inserted => None + assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); - // insert genesis block (no value for cache is provided) - let mut genesis_hash = None; - insert_block(&db, HashMap::new(), || { - let header = default_header(&Default::default(), 0); - genesis_hash = Some(header.hash()); - header - }); + // initialize cache + db.cache().initialize(b"test", vec![42]).unwrap(); - // after genesis is inserted => None - assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), None); + // after genesis is inserted + cache is initialized => Some + assert_eq!( + db.cache().get_at(b"test", &BlockId::Number(0)), + Some(((0, genesis_hash.unwrap()), None, vec![42])), + ); - // initialize cache - db.cache().initialize(b"test", vec![42]).unwrap(); + (genesis_hash, db.db) + }; - // after genesis is inserted + cache is initialized => Some - assert_eq!(db.cache().get_at(b"test", &BlockId::Number(0)), Some(((0, genesis_hash.unwrap()), None, vec![42]))); + // restart && check that after restart value is read from the cache + let db = LightStorage::::from_kvdb(storage as Arc<_>).expect("failed to create test-db"); + assert_eq!( + db.cache().get_at(b"test", &BlockId::Number(0)), + Some(((0, genesis_hash.unwrap()), None, vec![42])), + ); } #[test] diff --git a/core/client/db/src/storage_cache.rs b/core/client/db/src/storage_cache.rs index 8b3e81212ed0a1d7c8bced455ccb054f3a411bd7..8c81e44ba6bf22800e52a7bfa25904e25782cef9 100644 --- a/core/client/db/src/storage_cache.rs +++ b/core/client/db/src/storage_cache.rs @@ -22,6 +22,7 @@ use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard}; use linked_hash_map::{LinkedHashMap, Entry}; use hash_db::Hasher; use sr_primitives::traits::{Block as BlockT, Header}; +use primitives::hexdisplay::HexDisplay; use state_machine::{backend::Backend as StateBackend, TrieBackend}; use log::trace; use super::{StorageCollection, ChildStorageCollection}; @@ -168,7 +169,7 @@ impl Cache { trace!("Reverting enacted block {:?}", block); m.is_canon = true; for a in &m.storage { - trace!("Reverting enacted key {:?}", a); + trace!("Reverting enacted key {:?}", HexDisplay::from(a)); self.lru_storage.remove(a); } for a in &m.child_storage { @@ -188,7 +189,7 @@ impl Cache { trace!("Retracting block {:?}", block); m.is_canon = false; for a in &m.storage { - trace!("Retracted key {:?}", a); + trace!("Retracted key {:?}", HexDisplay::from(a)); self.lru_storage.remove(a); } for a in &m.child_storage { @@ -285,6 +286,12 @@ pub struct CachingState, B: BlockT> { pub cache: CacheChanges } +impl, B: BlockT> std::fmt::Debug for CachingState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Block {:?}", self.cache.parent_hash) + } +} + impl CacheChanges { /// Propagate local cache into the shared cache and synchronize /// the shared cache with the best block state. @@ -410,21 +417,16 @@ impl, B: BlockT> CachingState { key: Option<&[u8]>, child_key: Option<&ChildStorageKey>, parent_hash: &Option, - modifications: - &VecDeque> + modifications: &VecDeque> ) -> bool { let mut parent = match *parent_hash { None => { - trace!("Cache lookup skipped for {:?}: no parent hash", key); + trace!("Cache lookup skipped for {:?}: no parent hash", key.as_ref().map(HexDisplay::from)); return false; } Some(ref parent) => parent, }; - if modifications.is_empty() { - trace!("Cache lookup allowed for {:?}", key); - return true; - } // Ignore all storage modified in later blocks // Modifications contains block ordered by the number // We search for our parent in that list first and then for @@ -439,7 +441,7 @@ impl, B: BlockT> CachingState { } if let Some(key) = key { if m.storage.contains(key) { - trace!("Cache lookup skipped for {:?}: modified in a later block", key); + trace!("Cache lookup skipped for {:?}: modified in a later block", HexDisplay::from(&key)); return false; } } @@ -450,7 +452,7 @@ impl, B: BlockT> CachingState { } } } - trace!("Cache lookup skipped for {:?}: parent hash is unknown", key); + trace!("Cache lookup skipped for {:?}: parent hash is unknown", key.as_ref().map(HexDisplay::from)); false } @@ -469,17 +471,17 @@ impl, B: BlockT> StateBackend for CachingState< let local_cache = self.cache.local_cache.upgradable_read(); // Note that local cache makes that lru is not refreshed if let Some(entry) = local_cache.storage.get(key).cloned() { - trace!("Found in local cache: {:?}", key); + trace!("Found in local cache: {:?}", HexDisplay::from(&key)); return Ok(entry) } let mut cache = self.cache.shared_cache.lock(); if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) { if let Some(entry) = cache.lru_storage.get(key).map(|a| a.clone()) { - trace!("Found in shared cache: {:?}", key); + trace!("Found in shared cache: {:?}", HexDisplay::from(&key)); return Ok(entry) } } - trace!("Cache miss: {:?}", key); + trace!("Cache miss: {:?}", HexDisplay::from(&key)); let value = self.state.storage(key)?; RwLockUpgradableReadGuard::upgrade(local_cache).storage.insert(key.to_vec(), value.clone()); Ok(value) @@ -488,17 +490,17 @@ impl, B: BlockT> StateBackend for CachingState< fn storage_hash(&self, key: &[u8]) -> Result, Self::Error> { let local_cache = self.cache.local_cache.upgradable_read(); if let Some(entry) = local_cache.hashes.get(key).cloned() { - trace!("Found hash in local cache: {:?}", key); + trace!("Found hash in local cache: {:?}", HexDisplay::from(&key)); return Ok(entry) } let mut cache = self.cache.shared_cache.lock(); if Self::is_allowed(Some(key), None, &self.cache.parent_hash, &cache.modifications) { if let Some(entry) = cache.lru_hashes.get(key).map(|a| a.0.clone()) { - trace!("Found hash in shared cache: {:?}", key); + trace!("Found hash in shared cache: {:?}", HexDisplay::from(&key)); return Ok(entry) } } - trace!("Cache hash miss: {:?}", key); + trace!("Cache hash miss: {:?}", HexDisplay::from(&key)); let hash = self.state.storage_hash(key)?; RwLockUpgradableReadGuard::upgrade(local_cache).hashes.insert(key.to_vec(), hash.clone()); Ok(hash) @@ -536,6 +538,10 @@ impl, B: BlockT> StateBackend for CachingState< self.state.for_keys_with_prefix(prefix, f) } + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.state.for_key_values_with_prefix(prefix, f) + } + fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { self.state.for_keys_in_child_storage(storage_key, f) } @@ -718,4 +724,44 @@ mod tests { // 32 key, 2 byte size assert_eq!(shared.lock().used_storage_cache_size(), 34 /* bytes */); } + + #[test] + fn fix_storage_mismatch_issue() { + let _ = ::env_logger::try_init(); + let root_parent = H256::random(); + + let key = H256::random()[..].to_vec(); + + let h0 = H256::random(); + let h1 = H256::random(); + + let shared = new_shared_cache::(256*1024, (0, 1)); + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(root_parent.clone())); + s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![2]))], vec![], Some(h0.clone()), Some(0), || true); + + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h0.clone())); + s.cache.sync_cache(&[], &[], vec![(key.clone(), Some(vec![3]))], vec![], Some(h1.clone()), Some(1), || true); + + let mut s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1.clone())); + assert_eq!(s.storage(&key).unwrap(), Some(vec![3])); + + // Restart (or unknown block?), clear caches. + { + let mut cache = s.cache.shared_cache.lock(); + let cache = &mut *cache; + cache.lru_storage.clear(); + cache.lru_hashes.clear(); + cache.lru_child_storage.clear(); + cache.modifications.clear(); + } + + // New value is written because of cache miss. + s.cache.local_cache.write().storage.insert(key.clone(), Some(vec![42])); + + // New value is propagated. + s.cache.sync_cache(&[], &[], vec![], vec![], None, None, || true); + + let s = CachingState::new(InMemory::::default(), shared.clone(), Some(h1.clone())); + assert_eq!(s.storage(&key).unwrap(), None); + } } diff --git a/core/client/db/src/utils.rs b/core/client/db/src/utils.rs index 3d8a4defd5778e0d42884ef530adc4d2eaadc450..aeaa61a6f9fd7ec7e84448765425e040dfc08f42 100644 --- a/core/client/db/src/utils.rs +++ b/core/client/db/src/utils.rs @@ -17,7 +17,6 @@ //! Db-based backend utility structures and functions, used by both //! full and light storages. -#[cfg(feature = "kvdb-rocksdb")] use std::sync::Arc; use std::{io, convert::TryInto}; @@ -34,8 +33,7 @@ use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, Zero, UniqueSaturatedFrom, UniqueSaturatedInto, }; -#[cfg(feature = "kvdb-rocksdb")] -use crate::DatabaseSettings; +use crate::{DatabaseSettings, DatabaseSettingsSrc}; /// Number of columns in the db. Must be the same for both full && light dbs. /// Otherwise RocksDb will fail to open database && check its type. @@ -208,16 +206,26 @@ pub fn db_err(err: io::Error) -> client::error::Error { } /// Open RocksDB database. -#[cfg(feature = "kvdb-rocksdb")] pub fn open_database( config: &DatabaseSettings, col_meta: Option, db_type: &str ) -> client::error::Result> { - let mut db_config = DatabaseConfig::with_columns(Some(NUM_COLUMNS)); - db_config.memory_budget = config.cache_size; - let path = config.path.to_str().ok_or_else(|| client::error::Error::Backend("Invalid database path".into()))?; - let db = Database::open(&db_config, &path).map_err(db_err)?; + let db: Arc = match &config.source { + #[cfg(feature = "kvdb-rocksdb")] + DatabaseSettingsSrc::Path { path, cache_size } => { + let mut db_config = DatabaseConfig::with_columns(Some(NUM_COLUMNS)); + db_config.memory_budget = *cache_size; + let path = path.to_str().ok_or_else(|| client::error::Error::Backend("Invalid database path".into()))?; + Arc::new(Database::open(&db_config, &path).map_err(db_err)?) + }, + #[cfg(not(feature = "kvdb-rocksdb"))] + DatabaseSettingsSrc::Path { .. } => { + let msg = "Try to open RocksDB database with RocksDB disabled".into(); + return Err(client::error::Error::Backend(msg)); + }, + DatabaseSettingsSrc::Custom(db) => db.clone(), + }; // check database type match db.get(col_meta, meta_keys::TYPE).map_err(db_err)? { @@ -234,7 +242,7 @@ pub fn open_database( }, } - Ok(Arc::new(db)) + Ok(db) } /// Read database column entry for the given block. diff --git a/core/client/header-metadata/Cargo.toml b/core/client/header-metadata/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..43fcebb25bf96647aae8faa8e949c973cea89784 --- /dev/null +++ b/core/client/header-metadata/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "substrate-header-metadata" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +lru-cache = { version = "0.1.2" } +parking_lot = { version = "0.9.0" } +sr-primitives = { path = "../../sr-primitives" } diff --git a/core/client/header-metadata/src/lib.rs b/core/client/header-metadata/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..a8c3886020e271daac7fafb9a75cbe4cd4e2548b --- /dev/null +++ b/core/client/header-metadata/src/lib.rs @@ -0,0 +1,281 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implements tree backend, cached header metadata and algorithms +//! to compute routes efficiently over the tree of headers. + +use sr_primitives::traits::{Block as BlockT, NumberFor, Header}; +use parking_lot::RwLock; +use lru_cache::LruCache; + +/// Set to the expected max difference between `best` and `finalized` blocks at sync. +const LRU_CACHE_SIZE: usize = 5_000; + +/// Get lowest common ancestor between two blocks in the tree. +/// +/// This implementation is efficient because our trees have very few and +/// small branches, and because of our current query pattern: +/// lca(best, final), lca(best + 1, final), lca(best + 2, final), etc. +/// The first call is O(h) but the others are O(1). +pub fn lowest_common_ancestor>( + backend: &T, + id_one: Block::Hash, + id_two: Block::Hash, +) -> Result, T::Error> { + let mut header_one = backend.header_metadata(id_one)?; + let mut header_two = backend.header_metadata(id_two)?; + + let mut orig_header_one = header_one.clone(); + let mut orig_header_two = header_two.clone(); + + // We move through ancestor links as much as possible, since ancestor >= parent. + + while header_one.number > header_two.number { + let ancestor_one = backend.header_metadata(header_one.ancestor)?; + + if ancestor_one.number >= header_two.number { + header_one = ancestor_one; + } else { + break + } + } + + while header_one.number < header_two.number { + let ancestor_two = backend.header_metadata(header_two.ancestor)?; + + if ancestor_two.number >= header_one.number { + header_two = ancestor_two; + } else { + break + } + } + + // Then we move the remaining path using parent links. + + while header_one.hash != header_two.hash { + if header_one.number > header_two.number { + header_one = backend.header_metadata(header_one.parent)?; + } else { + header_two = backend.header_metadata(header_two.parent)?; + } + } + + // Update cached ancestor links. + + if orig_header_one.number > header_one.number { + orig_header_one.ancestor = header_one.hash; + backend.insert_header_metadata(orig_header_one.hash, orig_header_one); + } + + if orig_header_two.number > header_one.number { + orig_header_two.ancestor = header_one.hash; + backend.insert_header_metadata(orig_header_two.hash, orig_header_two); + } + + Ok(HashAndNumber { + hash: header_one.hash, + number: header_one.number, + }) +} + +/// Compute a tree-route between two blocks. See tree-route docs for more details. +pub fn tree_route>( + backend: &T, + from: Block::Hash, + to: Block::Hash, +) -> Result, T::Error> { + let mut from = backend.header_metadata(from)?; + let mut to = backend.header_metadata(to)?; + + let mut from_branch = Vec::new(); + let mut to_branch = Vec::new(); + + while to.number > from.number { + to_branch.push(HashAndNumber { + number: to.number, + hash: to.hash, + }); + + to = backend.header_metadata(to.parent)?; + } + + while from.number > to.number { + from_branch.push(HashAndNumber { + number: from.number, + hash: from.hash, + }); + from = backend.header_metadata(from.parent)?; + } + + // numbers are equal now. walk backwards until the block is the same + + while to.hash != from.hash { + to_branch.push(HashAndNumber { + number: to.number, + hash: to.hash, + }); + to = backend.header_metadata(to.parent)?; + + from_branch.push(HashAndNumber { + number: from.number, + hash: from.hash, + }); + from = backend.header_metadata(from.parent)?; + } + + // add the pivot block. and append the reversed to-branch (note that it's reverse order originals) + let pivot = from_branch.len(); + from_branch.push(HashAndNumber { + number: to.number, + hash: to.hash, + }); + from_branch.extend(to_branch.into_iter().rev()); + + Ok(TreeRoute { + route: from_branch, + pivot, + }) +} + +/// Hash and number of a block. +#[derive(Debug)] +pub struct HashAndNumber { + /// The number of the block. + pub number: NumberFor, + /// The hash of the block. + pub hash: Block::Hash, +} + +/// A tree-route from one block to another in the chain. +/// +/// All blocks prior to the pivot in the deque is the reverse-order unique ancestry +/// of the first block, the block at the pivot index is the common ancestor, +/// and all blocks after the pivot is the ancestry of the second block, in +/// order. +/// +/// The ancestry sets will include the given blocks, and thus the tree-route is +/// never empty. +/// +/// ```text +/// Tree route from R1 to E2. Retracted is [R1, R2, R3], Common is C, enacted [E1, E2] +/// <- R3 <- R2 <- R1 +/// / +/// C +/// \-> E1 -> E2 +/// ``` +/// +/// ```text +/// Tree route from C to E2. Retracted empty. Common is C, enacted [E1, E2] +/// C -> E1 -> E2 +/// ``` +#[derive(Debug)] +pub struct TreeRoute { + route: Vec>, + pivot: usize, +} + +impl TreeRoute { + /// Get a slice of all retracted blocks in reverse order (towards common ancestor) + pub fn retracted(&self) -> &[HashAndNumber] { + &self.route[..self.pivot] + } + + /// Get the common ancestor block. This might be one of the two blocks of the + /// route. + pub fn common_block(&self) -> &HashAndNumber { + self.route.get(self.pivot).expect("tree-routes are computed between blocks; \ + which are included in the route; \ + thus it is never empty; qed") + } + + /// Get a slice of enacted blocks (descendents of the common ancestor) + pub fn enacted(&self) -> &[HashAndNumber] { + &self.route[self.pivot + 1 ..] + } +} + +/// Handles header metadata: hash, number, parent hash, etc. +pub trait HeaderMetadata { + /// Error used in case the header metadata is not found. + type Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error>; + fn insert_header_metadata(&self, hash: Block::Hash, header_metadata: CachedHeaderMetadata); + fn remove_header_metadata(&self, hash: Block::Hash); +} + +/// Caches header metadata in an in-memory LRU cache. +pub struct HeaderMetadataCache { + cache: RwLock>>, +} + +impl HeaderMetadataCache { + /// Creates a new LRU header metadata cache with `capacity`. + pub fn new(capacity: usize) -> Self { + HeaderMetadataCache { + cache: RwLock::new(LruCache::new(capacity)), + } + } +} + +impl Default for HeaderMetadataCache { + fn default() -> Self { + HeaderMetadataCache { + cache: RwLock::new(LruCache::new(LRU_CACHE_SIZE)), + } + } +} + +impl HeaderMetadata for HeaderMetadataCache { + type Error = String; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.cache.write().get_mut(&hash).cloned() + .ok_or("header metadata not found in cache".to_owned()) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.cache.write().insert(hash, metadata); + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.cache.write().remove(&hash); + } +} + +/// Cached header metadata. Used to efficiently traverse the tree. +#[derive(Debug, Clone)] +pub struct CachedHeaderMetadata { + /// Hash of the header. + pub hash: Block::Hash, + /// Block number. + pub number: NumberFor, + /// Hash of parent header. + pub parent: Block::Hash, + /// Hash of an ancestor header. Used to jump through the tree. + ancestor: Block::Hash, +} + +impl From<&Block::Header> for CachedHeaderMetadata { + fn from(header: &Block::Header) -> Self { + CachedHeaderMetadata { + hash: header.hash().clone(), + number: header.number().clone(), + parent: header.parent_hash().clone(), + ancestor: header.parent_hash().clone(), + } + } +} diff --git a/core/client/src/backend.rs b/core/client/src/backend.rs index 2a3c4a3b2731f2fdb8794f9bf246369023ab1e2a..155af14bb729d70877430eb88c109bd53af8a7a4 100644 --- a/core/client/src/backend.rs +++ b/core/client/src/backend.rs @@ -16,16 +16,18 @@ //! Substrate Client data backend +use std::sync::Arc; use std::collections::HashMap; use crate::error; +use crate::light::blockchain::RemoteBlockchain; use primitives::ChangesTrieConfiguration; use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; use sr_primitives::traits::{Block as BlockT, NumberFor}; use state_machine::backend::Backend as StateBackend; -use state_machine::{ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieState}; +use state_machine::{ChangesTrieStorage as StateChangesTrieStorage, ChangesTrieState, ChangesTrieTransaction}; use crate::blockchain::well_known_cache_keys; +use consensus::BlockOrigin; use hash_db::Hasher; -use trie::MemoryDB; use parking_lot::Mutex; /// In memory array of storage values. @@ -34,6 +36,26 @@ pub type StorageCollection = Vec<(Vec, Option>)>; /// In memory arrays of storage values for multiple child tries. pub type ChildStorageCollection = Vec<(Vec, StorageCollection)>; +pub(crate) struct ImportSummary { + pub(crate) hash: Block::Hash, + pub(crate) origin: BlockOrigin, + pub(crate) header: Block::Header, + pub(crate) is_new_best: bool, + pub(crate) storage_changes: Option<(StorageCollection, ChildStorageCollection)>, + pub(crate) retracted: Vec, +} + +/// Import operation wrapper +pub struct ClientImportOperation< + Block: BlockT, + H: Hasher, + B: Backend, +> { + pub(crate) op: B::BlockImportOperation, + pub(crate) notify_imported: Option>, + pub(crate) notify_finalized: Vec, +} + /// State of a new block. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum NewBlockState { @@ -63,7 +85,9 @@ impl NewBlockState { } } -/// Block insertion operation. Keeps hold if the inserted block state and data. +/// Block insertion operation. +/// +/// Keeps hold if the inserted block state and data. pub trait BlockImportOperation where Block: BlockT, H: Hasher, @@ -71,8 +95,11 @@ pub trait BlockImportOperation where /// Associated state backend type. type State: StateBackend; - /// Returns pending state. Returns None for backends with locally-unavailable state data. + /// Returns pending state. + /// + /// Returns None for backends with locally-unavailable state data. fn state(&self) -> error::Result>; + /// Append block data to the transaction. fn set_block_data( &mut self, @@ -84,30 +111,82 @@ pub trait BlockImportOperation where /// Update cached data. fn update_cache(&mut self, cache: HashMap>); + /// Inject storage data into the database. fn update_db_storage(&mut self, update: >::Transaction) -> error::Result<()>; + /// Inject storage data into the database replacing any existing data. fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result; + /// Set storage changes. fn update_storage( &mut self, update: StorageCollection, child_update: ChildStorageCollection, ) -> error::Result<()>; + /// Inject changes trie data into the database. - fn update_changes_trie(&mut self, update: MemoryDB) -> error::Result<()>; - /// Insert auxiliary keys. Values are `None` if should be deleted. + fn update_changes_trie(&mut self, update: ChangesTrieTransaction>) -> error::Result<()>; + + /// Insert auxiliary keys. + /// + /// Values are `None` if should be deleted. fn insert_aux(&mut self, ops: I) -> error::Result<()> where I: IntoIterator, Option>)>; + /// Mark a block as finalized. fn mark_finalized(&mut self, id: BlockId, justification: Option) -> error::Result<()>; /// Mark a block as new head. If both block import and set head are specified, set head overrides block import's best block rule. fn mark_head(&mut self, id: BlockId) -> error::Result<()>; } +/// Finalize Facilities +pub trait Finalizer, B: Backend> { + /// Mark all blocks up to given as finalized in operation. + /// + /// If `justification` is provided it is stored with the given finalized + /// block (any other finalized blocks are left unjustified). + /// + /// If the block being finalized is on a different fork from the current + /// best block the finalized block is set as best, this might be slightly + /// inaccurate (i.e. outdated). Usages that require determining an accurate + /// best block should use `SelectChain` instead of the client. + fn apply_finality( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + justification: Option, + notify: bool, + ) -> error::Result<()>; + + + /// Finalize a block. + /// + /// This will implicitly finalize all blocks up to it and + /// fire finality notifications. + /// + /// If the block being finalized is on a different fork from the current + /// best block, the finalized block is set as best. This might be slightly + /// inaccurate (i.e. outdated). Usages that require determining an accurate + /// best block should use `SelectChain` instead of the client. + /// + /// Pass a flag to indicate whether finality notifications should be propagated. + /// This is usually tied to some synchronization state, where we don't send notifications + /// while performing major synchronization work. + fn finalize_block( + &self, + id: BlockId, + justification: Option, + notify: bool, + ) -> error::Result<()>; + +} + /// Provides access to an auxiliary database. pub trait AuxStore { - /// Insert auxiliary data into key-value store. Deletions occur after insertions. + /// Insert auxiliary data into key-value store. + /// + /// Deletions occur after insertions. fn insert_aux< 'a, 'b: 'a, @@ -115,11 +194,14 @@ pub trait AuxStore { I: IntoIterator, D: IntoIterator, >(&self, insert: I, delete: D) -> error::Result<()>; + /// Query auxiliary data from key-value store. fn get_aux(&self, key: &[u8]) -> error::Result>>; } -/// Client backend. Manages the data layer. +/// Client backend. +/// +/// Manages the data layer. /// /// Note on state pruning: while an object from `state_at` is alive, the state /// should not be pruned. The backend should internally reference-count @@ -141,35 +223,49 @@ pub trait Backend: AuxStore + Send + Sync where type OffchainStorage: OffchainStorage; /// Begin a new block insertion transaction with given parent block id. + /// /// When constructing the genesis, this is called with all-zero hash. fn begin_operation(&self) -> error::Result; + /// Note an operation to contain state transition. fn begin_state_operation(&self, operation: &mut Self::BlockImportOperation, block: BlockId) -> error::Result<()>; + /// Commit block insertion. fn commit_operation(&self, transaction: Self::BlockImportOperation) -> error::Result<()>; - /// Finalize block with given Id. This should only be called if the parent of the given - /// block has been finalized. + + /// Finalize block with given Id. + /// + /// This should only be called if the parent of the given block has been finalized. fn finalize_block(&self, block: BlockId, justification: Option) -> error::Result<()>; + /// Returns reference to blockchain backend. fn blockchain(&self) -> &Self::Blockchain; + /// Returns the used state cache, if existent. fn used_state_cache_size(&self) -> Option; + /// Returns reference to changes trie storage. fn changes_trie_storage(&self) -> Option<&dyn PrunableStateChangesTrieStorage>; + /// Returns a handle to offchain storage. fn offchain_storage(&self) -> Option; + /// Returns true if state for given block is available. fn have_state_at(&self, hash: &Block::Hash, _number: NumberFor) -> bool { self.state_at(BlockId::Hash(hash.clone())).is_ok() } + /// Returns state backend with post-state of given block. fn state_at(&self, block: BlockId) -> error::Result; + /// Destroy state and save any useful data, such as cache. fn destroy_state(&self, _state: Self::State) -> error::Result<()> { Ok(()) } - /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were - /// successfully reverted. + + /// Attempts to revert the chain by `n` blocks. + /// + /// Returns the number of blocks that were successfully reverted. fn revert(&self, n: NumberFor) -> error::Result>; /// Insert auxiliary data into key-value store. @@ -189,6 +285,7 @@ pub trait Backend: AuxStore + Send + Sync where } /// Gain access to the import lock around this backend. + /// /// _Note_ Backend isn't expected to acquire the lock by itself ever. Rather /// the using components should acquire and hold the lock whenever they do /// something that the import of a block would interfere with, e.g. importing @@ -256,6 +353,12 @@ where { /// Returns true if the state for given block is available locally. fn is_local_state_available(&self, block: &BlockId) -> bool; + + /// Returns reference to blockchain backend. + /// + /// Returned backend either resolves blockchain data + /// locally, or prepares request to fetch that data from remote node. + fn remote_blockchain(&self) -> Arc>; } /// Return changes tries state at given block. diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 22aac577e3342f0495877ac1f080ac9c20979122..f5cd6a9f660b0925bc2984529d2d60c519cfba3f 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -17,12 +17,12 @@ use super::api::BlockBuilder as BlockBuilderApi; use std::vec::Vec; use codec::Encode; -use sr_primitives::ApplyOutcome; use sr_primitives::generic::BlockId; use sr_primitives::traits::{ Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef, DigestFor, }; use primitives::{H256, ExecutionContext}; +use state_machine::StorageProof; use crate::blockchain::HeaderBackend; use crate::runtime_api::{Core, ApiExt}; use crate::error; @@ -104,7 +104,7 @@ where ExecutionContext::BlockConstruction, xt.clone() )? { - Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail) => { + Ok(_) => { extrinsics.push(xt); Ok(()) } @@ -129,7 +129,7 @@ where debug_assert_eq!( self.header.extrinsics_root().clone(), HashFor::::ordered_trie_root( - self.extrinsics.iter().map(Encode::encode) + self.extrinsics.iter().map(Encode::encode).collect(), ), ); @@ -141,7 +141,7 @@ where /// /// The proof will be `Some(_)`, if proof recording was enabled while creating /// the block builder. - pub fn bake_and_extract_proof(mut self) -> error::Result<(Block, Option>>)> { + pub fn bake_and_extract_proof(mut self) -> error::Result<(Block, Option)> { self.bake_impl()?; let proof = self.api.extract_proof(); diff --git a/core/client/src/blockchain.rs b/core/client/src/blockchain.rs index 7ae94659cb1bcb2c92afa763b2220a6b9d83211d..73b7c138d020e62238750b72fe8bf202e42ec109 100644 --- a/core/client/src/blockchain.rs +++ b/core/client/src/blockchain.rs @@ -21,6 +21,10 @@ use std::sync::Arc; use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use sr_primitives::generic::BlockId; use sr_primitives::Justification; +use log::warn; +use parking_lot::Mutex; + +use header_metadata::HeaderMetadata; use crate::error::{Error, Result}; @@ -72,7 +76,7 @@ pub trait HeaderBackend: Send + Sync { } /// Blockchain database backend. Does not perform any validation. -pub trait Backend: HeaderBackend { +pub trait Backend: HeaderBackend + HeaderMetadata { /// Get block body. Returns `None` if block is not found. fn body(&self, id: BlockId) -> Result::Extrinsic>>>; /// Get block justification. Returns `None` if justification does not exist. @@ -89,6 +93,123 @@ pub trait Backend: HeaderBackend { /// Return hashes of all blocks that are children of the block with `parent_hash`. fn children(&self, parent_hash: Block::Hash) -> Result>; + + /// Get the most recent block hash of the best (longest) chains + /// that contain block with the given `target_hash`. + /// + /// The search space is always limited to blocks which are in the finalized + /// chain or descendents of it. + /// + /// If `maybe_max_block_number` is `Some(max_block_number)` + /// the search is limited to block `numbers <= max_block_number`. + /// in other words as if there were no blocks greater `max_block_number`. + /// Returns `Ok(None)` if `target_hash` is not found in search space. + /// TODO: document time complexity of this, see [#1444](https://github.com/paritytech/substrate/issues/1444) + fn best_containing( + &self, + target_hash: Block::Hash, + maybe_max_number: Option>, + import_lock: &Mutex<()>, + ) -> Result> { + let target_header = { + match self.header(BlockId::Hash(target_hash))? { + Some(x) => x, + // target not in blockchain + None => { return Ok(None); }, + } + }; + + if let Some(max_number) = maybe_max_number { + // target outside search range + if target_header.number() > &max_number { + return Ok(None); + } + } + + let leaves = { + // ensure no blocks are imported during this code block. + // an import could trigger a reorg which could change the canonical chain. + // we depend on the canonical chain staying the same during this code block. + let _import_guard = import_lock.lock(); + + let info = self.info(); + + // this can be `None` if the best chain is shorter than the target header. + let maybe_canon_hash = self.hash(*target_header.number())?; + + if maybe_canon_hash.as_ref() == Some(&target_hash) { + // if a `max_number` is given we try to fetch the block at the + // given depth, if it doesn't exist or `max_number` is not + // provided, we continue to search from all leaves below. + if let Some(max_number) = maybe_max_number { + if let Some(header) = self.hash(max_number)? { + return Ok(Some(header)); + } + } + } else if info.finalized_number >= *target_header.number() { + // header is on a dead fork. + return Ok(None); + } + + self.leaves()? + }; + + // for each chain. longest chain first. shortest last + for leaf_hash in leaves { + // start at the leaf + let mut current_hash = leaf_hash; + + // if search is not restricted then the leaf is the best + let mut best_hash = leaf_hash; + + // go backwards entering the search space + // waiting until we are <= max_number + if let Some(max_number) = maybe_max_number { + loop { + let current_header = self.header(BlockId::Hash(current_hash.clone()))? + .ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?; + + if current_header.number() <= &max_number { + best_hash = current_header.hash(); + break; + } + + current_hash = *current_header.parent_hash(); + } + } + + // go backwards through the chain (via parent links) + loop { + // until we find target + if current_hash == target_hash { + return Ok(Some(best_hash)); + } + + let current_header = self.header(BlockId::Hash(current_hash.clone()))? + .ok_or_else(|| Error::from(format!("failed to get header for hash {}", current_hash)))?; + + // stop search in this chain once we go below the target's block number + if current_header.number() < target_header.number() { + break; + } + + current_hash = *current_header.parent_hash(); + } + } + + // header may be on a dead fork -- the only leaves that are considered are + // those which can still be finalized. + // + // FIXME #1558 only issue this warning when not on a dead fork + warn!( + "Block {:?} exists in chain but not found when following all \ + leaves backwards. Number limit = {:?}", + target_hash, + maybe_max_number, + ); + + Ok(None) + } } /// Provides access to the optional cache. @@ -104,13 +225,14 @@ pub trait Cache: Send + Sync { /// The operation should be performed once before anything else is inserted in the cache. /// Otherwise cache may end up in inconsistent state. fn initialize(&self, key: &well_known_cache_keys::Id, value_at_genesis: Vec) -> Result<()>; - /// For given key and block, returns cached value actual at this block AND block where this value - /// has been originally set. - fn get_at(&self, key: &well_known_cache_keys::Id, block: &BlockId) -> Option<( - (NumberFor, Block::Hash), - Option<(NumberFor, Block::Hash)>, - Vec, - )>; + /// Returns cached value by the given key. + /// + /// Returned tuple is the range where value has been active and the value itself. + fn get_at( + &self, + key: &well_known_cache_keys::Id, + block: &BlockId, + ) -> Option<((NumberFor, Block::Hash), Option<(NumberFor, Block::Hash)>, Vec)>; } /// Blockchain info @@ -137,132 +259,6 @@ pub enum BlockStatus { Unknown, } -/// An entry in a tree route. -#[derive(Debug)] -pub struct RouteEntry { - /// The number of the block. - pub number: ::Number, - /// The hash of the block. - pub hash: Block::Hash, -} - -/// A tree-route from one block to another in the chain. -/// -/// All blocks prior to the pivot in the deque is the reverse-order unique ancestry -/// of the first block, the block at the pivot index is the common ancestor, -/// and all blocks after the pivot is the ancestry of the second block, in -/// order. -/// -/// The ancestry sets will include the given blocks, and thus the tree-route is -/// never empty. -/// -/// ```text -/// Tree route from R1 to E2. Retracted is [R1, R2, R3], Common is C, enacted [E1, E2] -/// <- R3 <- R2 <- R1 -/// / -/// C -/// \-> E1 -> E2 -/// ``` -/// -/// ```text -/// Tree route from C to E2. Retracted empty. Common is C, enacted [E1, E2] -/// C -> E1 -> E2 -/// ``` -#[derive(Debug)] -pub struct TreeRoute { - route: Vec>, - pivot: usize, -} - -impl TreeRoute { - /// Get a slice of all retracted blocks in reverse order (towards common ancestor) - pub fn retracted(&self) -> &[RouteEntry] { - &self.route[..self.pivot] - } - - /// Get the common ancestor block. This might be one of the two blocks of the - /// route. - pub fn common_block(&self) -> &RouteEntry { - self.route.get(self.pivot).expect("tree-routes are computed between blocks; \ - which are included in the route; \ - thus it is never empty; qed") - } - - /// Get a slice of enacted blocks (descendents of the common ancestor) - pub fn enacted(&self) -> &[RouteEntry] { - &self.route[self.pivot + 1 ..] - } -} - -/// Compute a tree-route between two blocks. See tree-route docs for more details. -pub fn tree_route>( - backend: &Backend, - from: BlockId, - to: BlockId, -) -> Result> { - use sr_primitives::traits::Header; - - let load_header = |id: BlockId| { - match backend.header(id) { - Ok(Some(hdr)) => Ok(hdr), - Ok(None) => Err(Error::UnknownBlock(format!("Unknown block {:?}", id))), - Err(e) => Err(e), - } - }; - - let mut from = load_header(from)?; - let mut to = load_header(to)?; - - let mut from_branch = Vec::new(); - let mut to_branch = Vec::new(); - - while to.number() > from.number() { - to_branch.push(RouteEntry { - number: to.number().clone(), - hash: to.hash(), - }); - - to = load_header(BlockId::Hash(*to.parent_hash()))?; - } - - while from.number() > to.number() { - from_branch.push(RouteEntry { - number: from.number().clone(), - hash: from.hash(), - }); - from = load_header(BlockId::Hash(*from.parent_hash()))?; - } - - // numbers are equal now. walk backwards until the block is the same - - while to != from { - to_branch.push(RouteEntry { - number: to.number().clone(), - hash: to.hash(), - }); - to = load_header(BlockId::Hash(*to.parent_hash()))?; - - from_branch.push(RouteEntry { - number: from.number().clone(), - hash: from.hash(), - }); - from = load_header(BlockId::Hash(*from.parent_hash()))?; - } - - // add the pivot block. and append the reversed to-branch (note that it's reverse order originalls) - let pivot = from_branch.len(); - from_branch.push(RouteEntry { - number: to.number().clone(), - hash: to.hash(), - }); - from_branch.extend(to_branch.into_iter().rev()); - - Ok(TreeRoute { - route: from_branch, - pivot, - }) -} - /// A list of all well known keys in the blockchain cache. pub mod well_known_cache_keys { /// The type representing cache keys. diff --git a/core/client/src/call_executor.rs b/core/client/src/call_executor.rs index 6ad9715cac502ff0dea377508a38d42a0f6cd6ca..153800f2fdf0b43d4d6111ec2edb6302cc9354bc 100644 --- a/core/client/src/call_executor.rs +++ b/core/client/src/call_executor.rs @@ -17,16 +17,18 @@ use std::{sync::Arc, cmp::Ord, panic::UnwindSafe, result, cell::RefCell, rc::Rc}; use codec::{Encode, Decode}; use sr_primitives::{ - generic::BlockId, traits::Block as BlockT, + generic::BlockId, traits::Block as BlockT, traits::NumberFor, }; use state_machine::{ - self, OverlayedChanges, Ext, CodeExecutor, ExecutionManager, - ExecutionStrategy, NeverOffchainExt, backend::Backend as _, + self, OverlayedChanges, Ext, ExecutionManager, StateMachine, ExecutionStrategy, + backend::Backend as _, ChangesTrieTransaction, StorageProof, }; use executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; use hash_db::Hasher; -use trie::MemoryDB; -use primitives::{offchain, H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue}; +use primitives::{ + offchain::OffchainExt, H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue, + traits::{CodeExecutor, KeystoreExt}, +}; use crate::runtime_api::{ProofRecorder, InitializeBlock}; use crate::backend; @@ -45,15 +47,13 @@ where /// Execute a call to a contract on top of state in a block of given hash. /// /// No changes are made. - fn call< - O: offchain::Externalities, - >( + fn call( &self, id: &BlockId, method: &str, call_data: &[u8], strategy: ExecutionStrategy, - side_effects_handler: Option<&mut O>, + side_effects_handler: Option, ) -> Result, error::Error>; /// Execute a contextual call on top of state in a block of a given hash. @@ -63,14 +63,13 @@ where /// of the execution context. fn contextual_call< 'a, - O: offchain::Externalities, IB: Fn() -> error::Result<()>, EM: Fn( Result, Self::Error>, Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, initialize_block_fn: IB, @@ -81,7 +80,7 @@ where initialize_block: InitializeBlock<'a, B>, execution_manager: ExecutionManager, native_call: Option, - side_effects_handler: Option<&mut O>, + side_effects_handler: Option, proof_recorder: &Option>>>, enable_keystore: bool, ) -> error::Result> where ExecutionManager: Clone; @@ -95,14 +94,13 @@ where /// /// No changes are made. fn call_at_state< - O: offchain::Externalities, S: state_machine::Backend, F: FnOnce( Result, Self::Error>, - Result, Self::Error> + Result, Self::Error>, ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >(&self, state: &S, state_block: &BlockId, @@ -111,8 +109,15 @@ where call_data: &[u8], manager: ExecutionManager, native_call: Option, - side_effects_handler: Option<&mut O>, - ) -> Result<(NativeOrEncoded, (S::Transaction, H::Out), Option>), error::Error>; + side_effects_handler: Option, + ) -> Result< + ( + NativeOrEncoded, + (S::Transaction, H::Out), + Option>> + ), + error::Error, + >; /// Execute a call to a contract on top of given state, gathering execution proof. /// @@ -123,7 +128,7 @@ where overlay: &mut OverlayedChanges, method: &str, call_data: &[u8] - ) -> Result<(Vec, Vec>), error::Error> { + ) -> Result<(Vec, StorageProof), error::Error> { let trie_state = state.as_trie_backend() .ok_or_else(|| Box::new(state_machine::ExecutionError::UnableToGenerateProof) @@ -141,7 +146,7 @@ where overlay: &mut OverlayedChanges, method: &str, call_data: &[u8] - ) -> Result<(Vec, Vec>), error::Error>; + ) -> Result<(Vec, StorageProof), error::Error>; /// Get runtime version if supported. fn native_runtime_version(&self) -> Option<&NativeVersion>; @@ -183,22 +188,22 @@ impl Clone for LocalCallExecutor where E: Clone { impl CallExecutor for LocalCallExecutor where B: backend::Backend, - E: CodeExecutor + RuntimeInfo, + E: CodeExecutor + RuntimeInfo, Block: BlockT, { type Error = E::Error; - fn call( + fn call( &self, id: &BlockId, method: &str, call_data: &[u8], strategy: ExecutionStrategy, - side_effects_handler: Option<&mut O>, + side_effects_handler: Option, ) -> error::Result> { let mut changes = OverlayedChanges::default(); let state = self.backend.state_at(*id)?; - let return_data = state_machine::new( + let return_data = StateMachine::new( &state, backend::changes_tries_state_at_block(id, self.backend.changes_trie_storage())?, side_effects_handler, @@ -206,7 +211,7 @@ where &self.executor, method, call_data, - self.keystore.clone(), + self.keystore.clone().map(KeystoreExt), ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( strategy.get_manager(), false, @@ -219,14 +224,13 @@ where fn contextual_call< 'a, - O: offchain::Externalities, IB: Fn() -> error::Result<()>, EM: Fn( Result, Self::Error>, Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, initialize_block_fn: IB, @@ -237,7 +241,7 @@ where initialize_block: InitializeBlock<'a, Block>, execution_manager: ExecutionManager, native_call: Option, - side_effects_handler: Option<&mut O>, + side_effects_handler: Option, recorder: &Option>>>, enable_keystore: bool, ) -> Result, error::Error> where ExecutionManager: Clone { @@ -251,7 +255,7 @@ where } let keystore = if enable_keystore { - self.keystore.clone() + self.keystore.clone().map(KeystoreExt) } else { None }; @@ -272,7 +276,7 @@ where recorder.clone() ); - state_machine::new( + StateMachine::new( &backend, changes_trie_state, side_effects_handler, @@ -290,7 +294,7 @@ where .map(|(result, _, _)| result) .map_err(Into::into) } - None => state_machine::new( + None => StateMachine::new( &state, changes_trie_state, side_effects_handler, @@ -319,7 +323,6 @@ where &mut overlay, &state, changes_trie_state.as_ref(), - NeverOffchainExt::new(), None, ); let version = self.executor.runtime_version(&mut ext); @@ -328,14 +331,13 @@ where } fn call_at_state< - O: offchain::Externalities, S: state_machine::Backend, F: FnOnce( Result, Self::Error>, - Result, Self::Error> + Result, Self::Error>, ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >(&self, state: &S, state_block: &BlockId, @@ -344,17 +346,17 @@ where call_data: &[u8], manager: ExecutionManager, native_call: Option, - side_effects_handler: Option<&mut O>, + side_effects_handler: Option, ) -> error::Result<( NativeOrEncoded, (S::Transaction, ::Out), - Option>, + Option>>, )> { let changes_trie_state = backend::changes_tries_state_at_block::( state_block, self.backend.changes_trie_storage(), )?; - state_machine::new( + StateMachine::new( state, changes_trie_state, side_effects_handler, @@ -362,7 +364,7 @@ where &self.executor, method, call_data, - self.keystore.clone(), + self.keystore.clone().map(KeystoreExt), ).execute_using_consensus_failure_handler( manager, true, @@ -382,14 +384,14 @@ where overlay: &mut OverlayedChanges, method: &str, call_data: &[u8] - ) -> Result<(Vec, Vec>), error::Error> { - state_machine::prove_execution_on_trie_backend( + ) -> Result<(Vec, StorageProof), error::Error> { + state_machine::prove_execution_on_trie_backend::<_, _, NumberFor, _>( trie_state, overlay, &self.executor, method, call_data, - self.keystore.clone(), + self.keystore.clone().map(KeystoreExt), ) .map_err(Into::into) } diff --git a/core/client/src/cht.rs b/core/client/src/cht.rs index 37462851a96781957a40dcd7599b2c9e312766ff..aff875032d3570bec3329630d6f0df7f3e1a7292 100644 --- a/core/client/src/cht.rs +++ b/core/client/src/cht.rs @@ -23,8 +23,6 @@ //! root has. A correct proof implies that the claimed block is identical to the one //! we discarded. -use std::collections::HashSet; - use hash_db; use codec::Encode; use trie; @@ -32,7 +30,7 @@ use trie; use primitives::{H256, convert_hash}; use sr_primitives::traits::{Header as HeaderT, SimpleArithmetic, Zero, One}; use state_machine::backend::InMemory as InMemoryState; -use state_machine::{MemoryDB, TrieBackend, Backend as StateBackend, +use state_machine::{MemoryDB, TrieBackend, Backend as StateBackend, StorageProof, prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend}; use crate::error::{Error as ClientError, Result as ClientResult}; @@ -90,7 +88,7 @@ pub fn build_proof( cht_num: Header::Number, blocks: BlocksI, hashes: HashesI -) -> ClientResult>> +) -> ClientResult where Header: HeaderT, Hasher: hash_db::Hasher, @@ -105,15 +103,10 @@ pub fn build_proof( let mut storage = InMemoryState::::default().update(transaction); let trie_storage = storage.as_trie_backend() .expect("InMemoryState::as_trie_backend always returns Some; qed"); - let mut total_proof = HashSet::new(); - for block in blocks.into_iter() { - debug_assert_eq!(block_to_cht_number(cht_size, block), Some(cht_num)); - - let (value, proof) = prove_read_on_trie_backend(trie_storage, &encode_cht_key(block))?; - assert!(value.is_some(), "we have just built trie that includes the value for block"); - total_proof.extend(proof); - } - Ok(total_proof.into_iter().collect()) + prove_read_on_trie_backend( + trie_storage, + blocks.into_iter().map(|number| encode_cht_key(number)), + ).map_err(ClientError::Execution) } /// Check CHT-based header proof. @@ -121,16 +114,28 @@ pub fn check_proof( local_root: Header::Hash, local_number: Header::Number, remote_hash: Header::Hash, - remote_proof: Vec> + remote_proof: StorageProof, ) -> ClientResult<()> where Header: HeaderT, Hasher: hash_db::Hasher, Hasher::Out: Ord, { - do_check_proof::(local_root, local_number, remote_hash, move |local_root, local_cht_key| - read_proof_check::(local_root, remote_proof, - local_cht_key).map_err(|e| ClientError::from(e))) + do_check_proof::( + local_root, + local_number, + remote_hash, + move |local_root, local_cht_key| + read_proof_check::( + local_root, + remote_proof, + ::std::iter::once(local_cht_key), + ) + .map(|mut map| map + .remove(local_cht_key) + .expect("checked proof of local_cht_key; qed")) + .map_err(|e| ClientError::from(e)), + ) } /// Check CHT-based header proof on pre-created proving backend. @@ -145,9 +150,16 @@ pub fn check_proof_on_proving_backend( Hasher: hash_db::Hasher, Hasher::Out: Ord, { - do_check_proof::(local_root, local_number, remote_hash, |_, local_cht_key| - read_proof_check_on_proving_backend::( - proving_backend, local_cht_key).map_err(|e| ClientError::from(e))) + do_check_proof::( + local_root, + local_number, + remote_hash, + |_, local_cht_key| + read_proof_check_on_proving_backend::( + proving_backend, + local_cht_key, + ).map_err(|e| ClientError::from(e)), + ) } /// Check CHT-based header proof using passed checker function. diff --git a/core/client/src/client.rs b/core/client/src/client.rs index aaab7af720187c4787c0f1b2646ecdf302d4f5e5..70703db7223b1dfbc0df992c83870721e9e57413 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -21,14 +21,14 @@ use std::{ panic::UnwindSafe, result, cell::RefCell, rc::Rc, }; use log::{info, trace, warn}; -use futures::channel::mpsc; +use futures03::channel::mpsc; use parking_lot::{Mutex, RwLock}; use codec::{Encode, Decode}; use hash_db::{Hasher, Prefix}; use primitives::{ - Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, - NeverNativeValue, ExecutionContext, - storage::{StorageKey, StorageData, well_known_keys}, NativeOrEncoded + Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue, ExecutionContext, + NativeOrEncoded, storage::{StorageKey, StorageData, well_known_keys}, + offchain::{OffchainExt, self}, traits::CodeExecutor, }; use substrate_telemetry::{telemetry, SUBSTRATE_INFO}; use sr_primitives::{ @@ -40,18 +40,18 @@ use sr_primitives::{ }, }; use state_machine::{ - DBValue, Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId, - ChangesTrieConfigurationRange, ExecutionStrategy, ExecutionManager, - prove_read, prove_child_read, - ChangesTrieRootsStorage, ChangesTrieStorage, - key_changes, key_changes_proof, OverlayedChanges, NeverOffchainExt, + DBValue, Backend as StateBackend, ChangesTrieAnchorBlockId, ExecutionStrategy, ExecutionManager, + prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage, + ChangesTrieTransaction, ChangesTrieConfigurationRange, key_changes, key_changes_proof, + OverlayedChanges, BackendTrustLevel, StorageProof, merge_storage_proofs, }; use executor::{RuntimeVersion, RuntimeInfo}; use consensus::{ - Error as ConsensusError, BlockImportParams, + Error as ConsensusError, BlockStatus, BlockImportParams, BlockCheckParams, ImportResult, BlockOrigin, ForkChoiceStrategy, SelectChain, self, }; +use header_metadata::{HeaderMetadata, CachedHeaderMetadata}; use crate::{ runtime_api::{ @@ -60,7 +60,7 @@ use crate::{ }, backend::{ self, BlockImportOperation, PrunableStateChangesTrieStorage, - StorageCollection, ChildStorageCollection + ClientImportOperation, Finalizer, ImportSummary, }, blockchain::{ self, Info as ChainInfo, Backend as ChainBackend, @@ -86,7 +86,12 @@ type StorageUpdate = < >::BlockImportOperation as BlockImportOperation >::State as state_machine::Backend>::Transaction; -type ChangesUpdate = trie::MemoryDB; +type ChangesUpdate = ChangesTrieTransaction>; + +/// Expected hashes of blocks at given heights. +/// +/// This may be used as chain spec extension to filter out known, unwanted forks. +pub type ForkBlocks = Option, ::Hash>>; /// Execution strategies settings. #[derive(Debug, Clone)] @@ -124,25 +129,11 @@ pub struct Client where Block: BlockT { finality_notification_sinks: Mutex>>>, // holds the block hash currently being imported. TODO: replace this with block queue importing_block: RwLock>, + fork_blocks: ForkBlocks, execution_strategies: ExecutionStrategies, _phantom: PhantomData, } -/// Client import operation, a wrapper for the backend. -pub struct ClientImportOperation, B: backend::Backend> { - op: B::BlockImportOperation, - notify_imported: Option<( - Block::Hash, - BlockOrigin, - Block::Header, - bool, - Option<( - StorageCollection, - ChildStorageCollection, - )>)>, - notify_finalized: Vec, -} - /// A source of blockchain events. pub trait BlockchainEvents { /// Get block import event stream. Not guaranteed to be fired for every @@ -183,21 +174,8 @@ pub trait ProvideUncles { pub struct ClientInfo { /// Best block hash. pub chain: ChainInfo, -} - -/// Block status. -#[derive(Debug, PartialEq, Eq)] -pub enum BlockStatus { - /// Added to the import queue. - Queued, - /// Already in the blockchain and the state is available. - InChainWithState, - /// In the blockchain, but the state is not available. - InChainPruned, - /// Block or parent is known to be bad. - KnownBad, - /// Not in the queue or the blockchain. - Unknown, + /// State Cache Size currently used by the backend + pub used_state_cache_size: Option, } /// Summary of an imported block @@ -211,6 +189,8 @@ pub struct BlockImportNotification { pub header: Block::Header, /// Is this the new best block. pub is_new_best: bool, + /// List of retracted blocks ordered by block number. + pub retracted: Vec, } /// Summary of a finalized block. @@ -268,7 +248,7 @@ pub fn new_in_mem( Block, RA >> where - E: CodeExecutor + RuntimeInfo, + E: CodeExecutor + RuntimeInfo, S: BuildStorage, Block: BlockT, { @@ -284,13 +264,13 @@ pub fn new_with_backend( keystore: Option, ) -> error::Result, Block, RA>> where - E: CodeExecutor + RuntimeInfo, + E: CodeExecutor + RuntimeInfo, S: BuildStorage, Block: BlockT, B: backend::LocalBackend { let call_executor = LocalCallExecutor::new(backend.clone(), executor, keystore); - Client::new(backend, call_executor, build_genesis_storage, Default::default()) + Client::new(backend, call_executor, build_genesis_storage, Default::default(), Default::default()) } /// Figure out the block type for a given type (for now, just a `Client`). @@ -317,6 +297,7 @@ impl Client where backend: Arc, executor: E, build_genesis_storage: S, + fork_blocks: ForkBlocks, execution_strategies: ExecutionStrategies ) -> error::Result { if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() { @@ -345,6 +326,7 @@ impl Client where import_notification_sinks: Default::default(), finality_notification_sinks: Default::default(), importing_block: Default::default(), + fork_blocks, execution_strategies, _phantom: Default::default(), }) @@ -360,15 +342,6 @@ impl Client where self.backend.state_at(*block) } - /// Expose backend reference. To be used in tests only - #[doc(hidden)] - #[deprecated(note="Rather than relying on `client` to provide this, access \ - to the backend should be handled at setup only - see #1134. This function \ - will be removed once that is in place.")] - pub fn backend(&self) -> &Arc { - &self.backend - } - /// Given a `BlockId` and a key prefix, return the matching child storage keys in that block. pub fn storage_keys(&self, id: &BlockId, key_prefix: &StorageKey) -> error::Result> { let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect(); @@ -448,24 +421,28 @@ impl Client where } /// Reads storage value at a given block + key, returning read proof. - pub fn read_proof(&self, id: &BlockId, key: &[u8]) -> error::Result>> { + pub fn read_proof(&self, id: &BlockId, keys: I) -> error::Result where + I: IntoIterator, + I::Item: AsRef<[u8]>, + { self.state_at(id) - .and_then(|state| prove_read(state, key) - .map(|(_, proof)| proof) + .and_then(|state| prove_read(state, keys) .map_err(Into::into)) } /// Reads child storage value at a given block + storage_key + key, returning /// read proof. - pub fn read_child_proof( + pub fn read_child_proof( &self, id: &BlockId, storage_key: &[u8], - key: &[u8] - ) -> error::Result>> { + keys: I, + ) -> error::Result where + I: IntoIterator, + I::Item: AsRef<[u8]>, + { self.state_at(id) - .and_then(|state| prove_child_read(state, storage_key, key) - .map(|(_, proof)| proof) + .and_then(|state| prove_child_read(state, storage_key, keys) .map_err(Into::into)) } @@ -477,14 +454,14 @@ impl Client where id: &BlockId, method: &str, call_data: &[u8] - ) -> error::Result<(Vec, Vec>)> { + ) -> error::Result<(Vec, StorageProof)> { let state = self.state_at(id)?; let header = self.prepare_environment_block(id)?; prove_execution(state, header, &self.executor, method, call_data) } /// Reads given header and generates CHT-based header proof. - pub fn header_proof(&self, id: &BlockId) -> error::Result<(Block::Header, Vec>)> { + pub fn header_proof(&self, id: &BlockId) -> error::Result<(Block::Header, StorageProof)> { self.header_proof_with_cht_size(id, cht::size()) } @@ -500,7 +477,7 @@ impl Client where &self, id: &BlockId, cht_size: NumberFor, - ) -> error::Result<(Block::Header, Vec>)> { + ) -> error::Result<(Block::Header, StorageProof)> { let proof_error = || error::Error::Backend(format!("Failed to generate header proof for {:?}", id)); let header = self.backend.blockchain().expect_header(*id)?; let block_num = *header.number(); @@ -558,6 +535,7 @@ impl Client where &self, first: NumberFor, last: BlockId, + storage_key: Option<&StorageKey>, key: &StorageKey ) -> error::Result, u32)>> { let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?; @@ -588,6 +566,7 @@ impl Client where range_first, &range_anchor, best_number, + storage_key.as_ref().map(|x| &x.0[..]), &key.0) .and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::>()) .map_err(|err| error::Error::ChangesTrieAccessFailed(err))?; @@ -609,13 +588,15 @@ impl Client where last: Block::Hash, min: Block::Hash, max: Block::Hash, - key: &StorageKey + storage_key: Option<&StorageKey>, + key: &StorageKey, ) -> error::Result> { self.key_changes_proof_with_cht_size( first, last, min, max, + storage_key, key, cht::size(), ) @@ -628,6 +609,7 @@ impl Client where last: Block::Hash, min: Block::Hash, max: Block::Hash, + storage_key: Option<&StorageKey>, key: &StorageKey, cht_size: NumberFor, ) -> error::Result> { @@ -661,10 +643,18 @@ impl Client where } impl<'a, Block: BlockT> ChangesTrieStorage> for AccessedRootsRecorder<'a, Block> { - fn as_roots_storage(&self) -> &ChangesTrieRootsStorage> { + fn as_roots_storage(&self) -> &dyn state_machine::ChangesTrieRootsStorage> { self } + fn with_cached_changed_keys( + &self, + root: &H256, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool { + self.storage.with_cached_changed_keys(root, functor) + } + fn get(&self, key: &H256, prefix: Prefix) -> Result, String> { self.storage.get(key, prefix) } @@ -705,7 +695,8 @@ impl Client where number: last_number, }, max_number, - &key.0 + storage_key.as_ref().map(|x| &x.0[..]), + &key.0, ) .map_err(|err| error::Error::from(error::Error::ChangesTrieAccessFailed(err)))?; proof.extend(proof_range); @@ -729,18 +720,18 @@ impl Client where &self, cht_size: NumberFor, blocks: I - ) -> error::Result>> { + ) -> error::Result { // most probably we have touched several changes tries that are parts of the single CHT // => GroupBy changes tries by CHT number and then gather proof for the whole group at once - let mut proof = HashSet::new(); + let mut proofs = Vec::new(); cht::for_each_cht_group::(cht_size, blocks, |_, cht_num, cht_blocks| { let cht_proof = self.changes_trie_roots_proof_at_cht(cht_size, cht_num, cht_blocks)?; - proof.extend(cht_proof); + proofs.push(cht_proof); Ok(()) }, ())?; - Ok(proof.into_iter().collect()) + Ok(merge_storage_proofs(proofs)) } /// Generates CHT-based proof for roots of changes tries at given blocks (that are part of single CHT). @@ -749,7 +740,7 @@ impl Client where cht_size: NumberFor, cht_num: NumberFor, blocks: Vec> - ) -> error::Result>> { + ) -> error::Result { let cht_start = cht::start_number(cht_size, cht_num); let mut current_num = cht_start; let cht_range = ::std::iter::from_fn(|| { @@ -772,7 +763,7 @@ impl Client where first: NumberFor, last: Block::Hash, ) -> error::Result<( - &PrunableStateChangesTrieStorage, + &dyn PrunableStateChangesTrieStorage, Vec<(NumberFor, Option<(NumberFor, Block::Hash)>, ChangesTrieConfiguration)>, )> { let storage = match self.backend.changes_trie_storage() { @@ -877,28 +868,9 @@ impl Client where result } - /// Set a block as best block. - pub fn set_head( - &self, - id: BlockId - ) -> error::Result<()> { - self.lock_import_and_run(|operation| { - self.apply_head(operation, id) - }) - } - - /// Set a block as best block, and apply it to an operation. - pub fn apply_head( - &self, - operation: &mut ClientImportOperation, - id: BlockId, - ) -> error::Result<()> { - operation.op.mark_head(id) - } - /// Apply a checked and validated block to an operation. If a justification is provided /// then `finalized` *must* be true. - pub fn apply_block( + fn apply_block( &self, operation: &mut ClientImportOperation, import_block: BlockImportParams, @@ -954,11 +926,15 @@ impl Client where fork_choice, ); - telemetry!(SUBSTRATE_INFO; "block.import"; - "height" => height, - "best" => ?hash, - "origin" => ?origin - ); + if let Ok(ImportResult::Imported(ref aux)) = result { + if aux.is_new_best { + telemetry!(SUBSTRATE_INFO; "block.import"; + "height" => height, + "best" => ?hash, + "origin" => ?origin + ); + } + } result } @@ -984,10 +960,13 @@ impl Client where blockchain::BlockStatus::Unknown => {}, } - let (last_best, last_best_number) = { - let info = self.backend.blockchain().info(); - (info.best_hash, info.best_number) - }; + let info = self.backend.blockchain().info(); + + // the block is lower than our last finalized block so it must revert + // finality, refusing import. + if *import_headers.post().number() <= info.finalized_number { + return Err(error::Error::NotInFinalizedChain); + } // this is a fairly arbitrary choice of where to draw the line on making notifications, // but the general goal is to only make notifications when we are already fully synced @@ -1002,17 +981,24 @@ impl Client where // ensure parent block is finalized to maintain invariant that // finality is called sequentially. if finalized { - self.apply_finality_with_block_hash(operation, parent_hash, None, last_best, make_notifications)?; + self.apply_finality_with_block_hash(operation, parent_hash, None, info.best_hash, make_notifications)?; } // FIXME #1232: correct path logic for when to execute this function - let (storage_update,changes_update,storage_changes) = - self.block_execution(&operation.op, &import_headers, origin, hash, parent_hash, body.clone())?; + let (storage_update, changes_update, storage_changes) = self.block_execution( + &operation.op, + &import_headers, + origin, + hash, + parent_hash, + body.clone(), + )?; let is_new_best = finalized || match fork_choice { - ForkChoiceStrategy::LongestChain => import_headers.post().number() > &last_best_number, + ForkChoiceStrategy::LongestChain => import_headers.post().number() > &info.best_number, ForkChoiceStrategy::Custom(v) => v, }; + let leaf_state = if finalized { crate::backend::NewBlockState::Final } else if is_new_best { @@ -1021,6 +1007,17 @@ impl Client where crate::backend::NewBlockState::Normal }; + let retracted = if is_new_best { + let route_from_best = header_metadata::tree_route( + self.backend.blockchain(), + info.best_hash, + parent_hash, + )?; + route_from_best.retracted().iter().rev().map(|e| e.hash.clone()).collect() + } else { + Vec::default() + }; + trace!("Imported {}, (#{}), best={}, origin={:?}", hash, import_headers.post().number(), is_new_best, origin); operation.op.set_block_data( @@ -1048,10 +1045,17 @@ impl Client where operation.notify_finalized.push(hash); } - operation.notify_imported = Some((hash, origin, import_headers.into_post(), is_new_best, storage_changes)); + operation.notify_imported = Some(ImportSummary { + hash, + origin, + header: import_headers.into_post(), + is_new_best, + storage_changes, + retracted, + }) } - Ok(ImportResult::imported()) + Ok(ImportResult::imported(is_new_best)) } fn block_execution( @@ -1064,7 +1068,7 @@ impl Client where body: Option>, ) -> error::Result<( Option>, - Option>, + Option>>, Option<( Vec<(Vec, Option>)>, Vec<(Vec, Vec<(Vec, Option>)>)> @@ -1079,7 +1083,7 @@ impl Client where let get_execution_manager = |execution_strategy: ExecutionStrategy| { match execution_strategy { ExecutionStrategy::NativeElseWasm => ExecutionManager::NativeElseWasm, - ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, + ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted), ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| { let header = import_headers.post(); @@ -1096,19 +1100,28 @@ impl Client where }), } }; - let (_, storage_update, changes_update) = self.executor.call_at_state::<_, _, _, NeverNativeValue, fn() -> _>( - transaction_state, - &BlockId::Hash(parent_hash), - &mut overlay, - "Core_execute_block", - &::new(import_headers.pre().clone(), body.unwrap_or_default()).encode(), - match origin { - BlockOrigin::NetworkInitialSync => get_execution_manager(self.execution_strategies().syncing), - _ => get_execution_manager(self.execution_strategies().importing), - }, - None, - NeverOffchainExt::new(), - )?; + + let encoded_block = ::encode_from( + import_headers.pre(), + &body.unwrap_or_default() + ); + + let (_, storage_update, changes_update) = self.executor + .call_at_state::<_, _, NeverNativeValue, fn() -> _>( + transaction_state, + &BlockId::Hash(parent_hash), + &mut overlay, + "Core_execute_block", + &encoded_block, + match origin { + BlockOrigin::NetworkInitialSync => get_execution_manager( + self.execution_strategies().syncing, + ), + _ => get_execution_manager(self.execution_strategies().importing), + }, + None, + None, + )?; overlay.commit_prospective(); @@ -1140,11 +1153,7 @@ impl Client where return Ok(()); } - let route_from_finalized = crate::blockchain::tree_route( - self.backend.blockchain(), - BlockId::Hash(last_finalized), - BlockId::Hash(block), - )?; + let route_from_finalized = header_metadata::tree_route(self.backend.blockchain(), last_finalized, block)?; if let Some(retracted) = route_from_finalized.retracted().get(0) { warn!("Safety violation: attempted to revert finalized block {:?} which is not in the \ @@ -1153,17 +1162,13 @@ impl Client where return Err(error::Error::NotInFinalizedChain); } - let route_from_best = crate::blockchain::tree_route( - self.backend.blockchain(), - BlockId::Hash(best_block), - BlockId::Hash(block), - )?; + let route_from_best = header_metadata::tree_route(self.backend.blockchain(), best_block, block)?; // if the block is not a direct ancestor of the current best chain, // then some other block is the common ancestor. if route_from_best.common_block().hash != block { // NOTE: we're setting the finalized block as best block, this might - // be slightly innacurate since we might have a "better" block + // be slightly inaccurate since we might have a "better" block // further along this chain, but since best chain selection logic is // pluggable we cannot make a better choice here. usages that need // an accurate "best" block need to go through `SelectChain` @@ -1220,35 +1225,23 @@ impl Client where Ok(()) } - fn notify_imported( - &self, - notify_import: ( - Block::Hash, BlockOrigin, - Block::Header, - bool, - Option<( - Vec<(Vec, Option>)>, - Vec<(Vec, Vec<(Vec, Option>)>)>, - ) - >), - ) -> error::Result<()> { - let (hash, origin, header, is_new_best, storage_changes) = notify_import; - - if let Some(storage_changes) = storage_changes { + fn notify_imported(&self, notify_import: ImportSummary) -> error::Result<()> { + if let Some(storage_changes) = notify_import.storage_changes { // TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes? self.storage_notifications.lock() .trigger( - &hash, + ¬ify_import.hash, storage_changes.0.into_iter(), storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())), ); } let notification = BlockImportNotification:: { - hash, - origin, - header, - is_new_best, + hash: notify_import.hash, + origin: notify_import.origin, + header: notify_import.header, + is_new_best: notify_import.is_new_best, + retracted: notify_import.retracted, }; self.import_notification_sinks.lock() @@ -1257,68 +1250,6 @@ impl Client where Ok(()) } - /// Apply auxiliary data insertion into an operation. - pub fn apply_aux< - 'a, - 'b: 'a, - 'c: 'a, - I: IntoIterator, - D: IntoIterator, - >( - &self, - operation: &mut ClientImportOperation, - insert: I, - delete: D - ) -> error::Result<()> { - operation.op.insert_aux( - insert.into_iter() - .map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) - .chain(delete.into_iter().map(|k| (k.to_vec(), None))) - ) - } - - /// Mark all blocks up to given as finalized in operation. If a - /// justification is provided it is stored with the given finalized - /// block (any other finalized blocks are left unjustified). - /// - /// If the block being finalized is on a different fork from the current - /// best block the finalized block is set as best, this might be slightly - /// innacurate (i.e. outdated), usages that require determining an accurate - /// best block should use `SelectChain` instead of the client. - pub fn apply_finality( - &self, - operation: &mut ClientImportOperation, - id: BlockId, - justification: Option, - notify: bool, - ) -> error::Result<()> { - let last_best = self.backend.blockchain().info().best_hash; - let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; - self.apply_finality_with_block_hash(operation, to_finalize_hash, justification, last_best, notify) - } - - /// Finalize a block. This will implicitly finalize all blocks up to it and - /// fire finality notifications. - /// - /// If the block being finalized is on a different fork from the current - /// best block the finalized block is set as best, this might be slightly - /// innacurate (i.e. outdated), usages that require determining an accurate - /// best block should use `SelectChain` instead of the client. - /// - /// Pass a flag to indicate whether finality notifications should be propagated. - /// This is usually tied to some synchronization state, where we don't send notifications - /// while performing major synchronization work. - pub fn finalize_block(&self, id: BlockId, justification: Option, notify: bool) -> error::Result<()> { - self.lock_import_and_run(|operation| { - let last_best = self.backend.blockchain().info().best_hash; - let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; - self.apply_finality_with_block_hash(operation, to_finalize_hash, justification, last_best, notify) - }).map_err(|e| { - warn!("Block finalization error:\n{:?}", e); - e - }) - } - /// Attempts to revert the chain by `n` blocks. Returns the number of blocks that were /// successfully reverted. pub fn revert(&self, n: NumberFor) -> error::Result> { @@ -1330,6 +1261,7 @@ impl Client where let info = self.backend.blockchain().info(); ClientInfo { chain: info, + used_state_cache_size: self.backend.used_state_cache_size(), } } @@ -1388,7 +1320,7 @@ impl Client where let load_header = |id: Block::Hash| -> error::Result { match self.backend.blockchain().header(BlockId::Hash(id))? { Some(hdr) => Ok(hdr), - None => Err(Error::UnknownBlock(format!("Unknown block {:?}", id))), + None => Err(Error::UnknownBlock(format!("{:?}", id))), } }; @@ -1427,6 +1359,26 @@ impl Client where } } +impl HeaderMetadata for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + type Error = error::Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.backend.blockchain().header_metadata(hash) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.backend.blockchain().insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.backend.blockchain().remove_header_metadata(hash) + } +} + impl ProvideUncles for Client where B: backend::Backend, E: CallExecutor, @@ -1468,6 +1420,33 @@ impl ChainHeaderBackend for Client wher } } +impl ChainHeaderBackend for &Client where + B: backend::Backend, + E: CallExecutor + Send + Sync, + Block: BlockT, + RA: Send + Sync, +{ + fn header(&self, id: BlockId) -> error::Result> { + (**self).backend.blockchain().header(id) + } + + fn info(&self) -> blockchain::Info { + (**self).backend.blockchain().info() + } + + fn status(&self, id: BlockId) -> error::Result { + (**self).status(id) + } + + fn number(&self, hash: Block::Hash) -> error::Result::Header as HeaderT>::Number>> { + (**self).number(hash) + } + + fn hash(&self, number: NumberFor) -> error::Result> { + (**self).hash(number) + } +} + impl ProvideCache for Client where B: backend::Backend, Block: BlockT, @@ -1498,7 +1477,7 @@ impl CallRuntimeAt for Client where fn call_api_at< 'a, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, C: CoreApi, >( &self, @@ -1512,8 +1491,6 @@ impl CallRuntimeAt for Client where context: ExecutionContext, recorder: &Option>>>, ) -> error::Result> { - let enable_keystore = context.enable_keystore(); - let manager = match context { ExecutionContext::BlockConstruction => self.execution_strategies.block_construction.get_manager(), @@ -1521,18 +1498,20 @@ impl CallRuntimeAt for Client where self.execution_strategies.syncing.get_manager(), ExecutionContext::Importing => self.execution_strategies.importing.get_manager(), - ExecutionContext::OffchainWorker(_) => + ExecutionContext::OffchainCall(Some((_, capabilities))) if capabilities.has_all() => self.execution_strategies.offchain_worker.get_manager(), - ExecutionContext::Other => + ExecutionContext::OffchainCall(_) => self.execution_strategies.other.get_manager(), }; - let mut offchain_extensions = match context { - ExecutionContext::OffchainWorker(ext) => Some(ext), - _ => None, + let capabilities = context.capabilities(); + let offchain_extensions = if let ExecutionContext::OffchainCall(Some(ext)) = context { + Some(OffchainExt::new(offchain::LimitedExternalities::new(capabilities, ext.0))) + } else { + None }; - self.executor.contextual_call::<_, _, fn(_,_) -> _,_,_>( + self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( || core_api.initialize_block(at, &self.prepare_environment_block(at)?), at, function, @@ -1541,9 +1520,9 @@ impl CallRuntimeAt for Client where initialize_block, manager, native_call, - offchain_extensions.as_mut(), + offchain_extensions, recorder, - enable_keystore, + capabilities.has(offchain::Capability::Keystore), ) } @@ -1552,6 +1531,9 @@ impl CallRuntimeAt for Client where } } +/// NOTE: only use this implementation when you are sure there are NO consensus-level BlockImport +/// objects. Otherwise, importing blocks directly into the client would be bypassing +/// important verification work. impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client where B: backend::Backend, E: CallExecutor + Clone + Send + Sync, @@ -1561,6 +1543,13 @@ impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client, @@ -1577,9 +1566,22 @@ impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client, ) -> Result { + let BlockCheckParams { hash, number, parent_hash } = block; + + if let Some(h) = self.fork_blocks.as_ref().and_then(|x| x.get(&number)) { + if &hash != h { + trace!( + "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}", + hash, + h, + number + ); + return Ok(ImportResult::KnownBad); + } + } + match self.block_status(&BlockId::Hash(parent_hash)) .map_err(|e| ConsensusError::ClientImport(e.to_string()))? { @@ -1596,7 +1598,8 @@ impl<'a, B, E, Block, RA> consensus::BlockImport for &'a Client return Ok(ImportResult::KnownBad), } - Ok(ImportResult::imported()) + + Ok(ImportResult::imported(false)) } } @@ -1617,10 +1620,53 @@ impl consensus::BlockImport for Client fn check_block( &mut self, - hash: Block::Hash, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - (&*self).check_block(hash, parent_hash) + (&*self).check_block(block) + } +} + +impl Finalizer for Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn apply_finality( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + justification: Option, + notify: bool, + ) -> error::Result<()> { + let last_best = self.backend.blockchain().info().best_hash; + let to_finalize_hash = self.backend.blockchain().expect_block_hash_from_id(&id)?; + self.apply_finality_with_block_hash(operation, to_finalize_hash, justification, last_best, notify) + } + + fn finalize_block(&self, id: BlockId, justification: Option, notify: bool) -> error::Result<()> { + self.lock_import_and_run(|operation| { + self.apply_finality(operation, id, justification, notify) + }) + } +} + +impl Finalizer for &Client where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + fn apply_finality( + &self, + operation: &mut ClientImportOperation, + id: BlockId, + justification: Option, + notify: bool, + ) -> error::Result<()> { + (**self).apply_finality(operation, id, justification, notify) + } + + fn finalize_block(&self, id: BlockId, justification: Option, notify: bool) -> error::Result<()> { + (**self).finalize_block(id, justification, notify) } } @@ -1684,129 +1730,14 @@ where fn best_block_header(&self) -> error::Result<::Header> { let info = self.backend.blockchain().info(); - let best_hash = self.best_containing(info.best_hash, None)? + let import_lock = self.backend.get_import_lock(); + let best_hash = self.backend.blockchain().best_containing(info.best_hash, None, import_lock)? .unwrap_or(info.best_hash); Ok(self.backend.blockchain().header(BlockId::Hash(best_hash))? .expect("given block hash was fetched from block in db; qed")) } - /// Get the most recent block hash of the best (longest) chains - /// that contain block with the given `target_hash`. - /// - /// The search space is always limited to blocks which are in the finalized - /// chain or descendents of it. - /// - /// If `maybe_max_block_number` is `Some(max_block_number)` - /// the search is limited to block `numbers <= max_block_number`. - /// in other words as if there were no blocks greater `max_block_number`. - /// Returns `Ok(None)` if `target_hash` is not found in search space. - /// TODO: document time complexity of this, see [#1444](https://github.com/paritytech/substrate/issues/1444) - fn best_containing( - &self, - target_hash: Block::Hash, - maybe_max_number: Option> - ) -> error::Result> { - let target_header = { - match self.backend.blockchain().header(BlockId::Hash(target_hash))? { - Some(x) => x, - // target not in blockchain - None => { return Ok(None); }, - } - }; - - if let Some(max_number) = maybe_max_number { - // target outside search range - if target_header.number() > &max_number { - return Ok(None); - } - } - - let leaves = { - // ensure no blocks are imported during this code block. - // an import could trigger a reorg which could change the canonical chain. - // we depend on the canonical chain staying the same during this code block. - let _import_lock = self.backend.get_import_lock().lock(); - - let info = self.backend.blockchain().info(); - - let canon_hash = self.backend.blockchain().hash(*target_header.number())? - .ok_or_else(|| error::Error::from(format!("failed to get hash for block number {}", target_header.number())))?; - - if canon_hash == target_hash { - // if a `max_number` is given we try to fetch the block at the - // given depth, if it doesn't exist or `max_number` is not - // provided, we continue to search from all leaves below. - if let Some(max_number) = maybe_max_number { - if let Some(header) = self.backend.blockchain().hash(max_number)? { - return Ok(Some(header)); - } - } - } else if info.finalized_number >= *target_header.number() { - // header is on a dead fork. - return Ok(None); - } - - self.backend.blockchain().leaves()? - }; - - // for each chain. longest chain first. shortest last - for leaf_hash in leaves { - // start at the leaf - let mut current_hash = leaf_hash; - - // if search is not restricted then the leaf is the best - let mut best_hash = leaf_hash; - - // go backwards entering the search space - // waiting until we are <= max_number - if let Some(max_number) = maybe_max_number { - loop { - let current_header = self.backend.blockchain().header(BlockId::Hash(current_hash.clone()))? - .ok_or_else(|| error::Error::from(format!("failed to get header for hash {}", current_hash)))?; - - if current_header.number() <= &max_number { - best_hash = current_header.hash(); - break; - } - - current_hash = *current_header.parent_hash(); - } - } - - // go backwards through the chain (via parent links) - loop { - // until we find target - if current_hash == target_hash { - return Ok(Some(best_hash)); - } - - let current_header = self.backend.blockchain().header(BlockId::Hash(current_hash.clone()))? - .ok_or_else(|| error::Error::from(format!("failed to get header for hash {}", current_hash)))?; - - // stop search in this chain once we go below the target's block number - if current_header.number() < target_header.number() { - break; - } - - current_hash = *current_header.parent_hash(); - } - } - - // header may be on a dead fork -- the only leaves that are considered are - // those which can still be finalized. - // - // FIXME #1558 only issue this warning when not on a dead fork - warn!( - "Block {:?} exists in chain but not found when following all \ - leaves backwards. Number limit = {:?}", - target_hash, - maybe_max_number, - ); - - Ok(None) - } - fn leaves(&self) -> Result::Hash>, error::Error> { self.backend.blockchain().leaves() } @@ -1835,7 +1766,8 @@ where target_hash: Block::Hash, maybe_max_number: Option> ) -> Result, ConsensusError> { - LongestChain::best_containing(self, target_hash, maybe_max_number) + let import_lock = self.backend.get_import_lock(); + self.backend.blockchain().best_containing(target_hash, maybe_max_number, import_lock) .map_err(|e| ConsensusError::ChainLookup(e.to_string()).into()) } } @@ -1870,7 +1802,7 @@ impl backend::AuxStore for Client // layer, one can always use atomic operations to make sure // import is only locked once. self.lock_import_and_run(|operation| { - self.apply_aux(operation, insert, delete) + apply_aux(operation, insert, delete) }) } /// Query auxiliary data from key-value store. @@ -1879,11 +1811,55 @@ impl backend::AuxStore for Client } } + +impl backend::AuxStore for &Client + where + B: backend::Backend, + E: CallExecutor, + Block: BlockT, +{ + + fn insert_aux< + 'a, + 'b: 'a, + 'c: 'a, + I: IntoIterator, + D: IntoIterator, + >(&self, insert: I, delete: D) -> error::Result<()> { + (**self).insert_aux(insert, delete) + } + + fn get_aux(&self, key: &[u8]) -> error::Result>> { + (**self).get_aux(key) + } +} + +/// Helper function to apply auxiliary data insertion into an operation. +pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, H, D, I>( + operation: &mut ClientImportOperation, + insert: I, + delete: D +) -> error::Result<()> +where + Block: BlockT, + H: Hasher, + B: backend::Backend, + I: IntoIterator, + D: IntoIterator, +{ + operation.op.insert_aux( + insert.into_iter() + .map(|(k, v)| (k.to_vec(), Some(v.to_vec()))) + .chain(delete.into_iter().map(|k| (k.to_vec(), None))) + ) +} + /// Utility methods for the client. pub mod utils { use super::*; - use crate::{backend::Backend, blockchain, error}; + use crate::error; use primitives::H256; + use std::borrow::Borrow; /// Returns a function for checking block ancestry, the returned function will /// return `true` if the given hash (second parameter) is a descendent of the @@ -1891,16 +1867,17 @@ pub mod utils { /// represent the current block `hash` and its `parent hash`, if given the /// function that's returned will assume that `hash` isn't part of the local DB /// yet, and all searches in the DB will instead reference the parent. - pub fn is_descendent_of<'a, B, E, Block: BlockT, RA>( - client: &'a Client, - current: Option<(&'a H256, &'a H256)>, + pub fn is_descendent_of<'a, Block: BlockT, T, H: Borrow + 'a>( + client: &'a T, + current: Option<(H, H)>, ) -> impl Fn(&H256, &H256) -> Result + 'a - where B: Backend, - E: CallExecutor + Send + Sync, + where T: ChainHeaderBackend + HeaderMetadata, { move |base, hash| { if base == hash { return Ok(false); } + let current = current.as_ref().map(|(c, p)| (c.borrow(), p.borrow())); + let mut hash = hash; if let Some((current_hash, current_parent_hash)) = current { if base == current_hash { return Ok(false); } @@ -1913,18 +1890,23 @@ pub mod utils { } } - let tree_route = blockchain::tree_route( - #[allow(deprecated)] - client.backend().blockchain(), - BlockId::Hash(*hash), - BlockId::Hash(*base), - )?; + let ancestor = header_metadata::lowest_common_ancestor(client, *hash, *base)?; - Ok(tree_route.common_block().hash == *base) + Ok(ancestor.hash == *base) } } } +impl consensus::block_validation::Chain for Client + where BE: backend::Backend, + E: CallExecutor, + B: BlockT +{ + fn block_status(&self, id: &BlockId) -> Result> { + Client::block_status(self, id).map_err(|e| Box::new(e) as Box<_>) + } +} + #[cfg(test)] pub(crate) mod tests { use std::collections::HashMap; @@ -1934,7 +1916,7 @@ pub(crate) mod tests { use consensus::{BlockOrigin, SelectChain}; use test_client::{ prelude::*, - client::backend::Backend as TestBackend, + client_db::{Backend, DatabaseSettings, DatabaseSettingsSrc, PruningMode}, runtime::{self, Block, Transfer, RuntimeApi, TestAPI}, }; @@ -2584,7 +2566,12 @@ pub(crate) mod tests { for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() { let end = client.block_hash(end).unwrap().unwrap(); - let actual_result = client.key_changes(begin, BlockId::Hash(end), &StorageKey(key)).unwrap(); + let actual_result = client.key_changes( + begin, + BlockId::Hash(end), + None, + &StorageKey(key), + ).unwrap(); match actual_result == expected_result { true => (), false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}", @@ -2595,8 +2582,6 @@ pub(crate) mod tests { #[test] fn import_with_justification() { - use test_client::blockchain::Backend; - let client = test_client::new(); // G -> A1 @@ -2612,33 +2597,29 @@ pub(crate) mod tests { let a3 = client.new_block_at(&BlockId::Hash(a2.hash()), Default::default()).unwrap().bake().unwrap(); client.import_justified(BlockOrigin::Own, a3.clone(), justification.clone()).unwrap(); - #[allow(deprecated)] - let blockchain = client.backend().blockchain(); - assert_eq!( - blockchain.last_finalized().unwrap(), + client.info().chain.finalized_hash, a3.hash(), ); assert_eq!( - blockchain.justification(BlockId::Hash(a3.hash())).unwrap(), + client.justification(&BlockId::Hash(a3.hash())).unwrap(), Some(justification), ); assert_eq!( - blockchain.justification(BlockId::Hash(a1.hash())).unwrap(), + client.justification(&BlockId::Hash(a1.hash())).unwrap(), None, ); assert_eq!( - blockchain.justification(BlockId::Hash(a2.hash())).unwrap(), + client.justification(&BlockId::Hash(a2.hash())).unwrap(), None, ); } #[test] fn importing_diverged_finalized_block_should_trigger_reorg() { - use test_client::blockchain::HeaderBackend; let client = test_client::new(); @@ -2662,12 +2643,9 @@ pub(crate) mod tests { // create but don't import B1 just yet let b1 = b1.bake().unwrap(); - #[allow(deprecated)] - let blockchain = client.backend().blockchain(); - // A2 is the current best since it's the longest chain assert_eq!( - blockchain.info().best_hash, + client.info().chain.best_hash, a2.hash(), ); @@ -2676,19 +2654,18 @@ pub(crate) mod tests { client.import_justified(BlockOrigin::Own, b1.clone(), justification).unwrap(); assert_eq!( - blockchain.info().best_hash, + client.info().chain.best_hash, b1.hash(), ); assert_eq!( - blockchain.info().finalized_hash, + client.info().chain.finalized_hash, b1.hash(), ); } #[test] fn finalizing_diverged_block_should_trigger_reorg() { - use test_client::blockchain::HeaderBackend; let (client, select_chain) = TestClientBuilder::new().build_with_longest_chain(); @@ -2715,29 +2692,26 @@ pub(crate) mod tests { let b2 = client.new_block_at(&BlockId::Hash(b1.hash()), Default::default()).unwrap().bake().unwrap(); client.import(BlockOrigin::Own, b2.clone()).unwrap(); - #[allow(deprecated)] - let blockchain = client.backend().blockchain(); - // A2 is the current best since it's the longest chain assert_eq!( - blockchain.info().best_hash, + client.info().chain.best_hash, a2.hash(), ); // we finalize block B1 which is on a different branch from current best // which should trigger a re-org. - client.finalize_block(BlockId::Hash(b1.hash()), None, false).unwrap(); + client.finalize_block(BlockId::Hash(b1.hash()), None).unwrap(); // B1 should now be the latest finalized assert_eq!( - blockchain.info().finalized_hash, + client.info().chain.finalized_hash, b1.hash(), ); // and B1 should be the new best block (`finalize_block` as no way of // knowing about B2) assert_eq!( - blockchain.info().best_hash, + client.info().chain.best_hash, b1.hash(), ); @@ -2756,7 +2730,7 @@ pub(crate) mod tests { client.import(BlockOrigin::Own, b3.clone()).unwrap(); assert_eq!( - blockchain.info().best_hash, + client.info().chain.best_hash, b3.hash(), ); } @@ -2819,41 +2793,96 @@ pub(crate) mod tests { } #[test] - fn state_reverted_on_set_head() { + fn doesnt_import_blocks_that_revert_finality() { let _ = env_logger::try_init(); - let client = test_client::new(); + let tmp = tempfile::tempdir().unwrap(); + + // we need to run with archive pruning to avoid pruning non-canonical + // states + let backend = Arc::new(Backend::new( + DatabaseSettings { + state_cache_size: 1 << 20, + state_cache_child_ratio: None, + pruning: PruningMode::ArchiveAll, + source: DatabaseSettingsSrc::Path { + path: tmp.path().into(), + cache_size: None, + } + }, + u64::max_value(), + ).unwrap()); - let current_balance = || - client.runtime_api().balance_of( - &BlockId::number(client.info().chain.best_number), AccountKeyring::Alice.into() - ).unwrap(); + let client = TestClientBuilder::with_backend(backend).build(); - // G -> A1 + // -> C1 + // / + // G -> A1 -> A2 // \ - // -> B1 - let mut a1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - a1.push_transfer(Transfer { - from: AccountKeyring::Alice.into(), - to: AccountKeyring::Bob.into(), - amount: 10, - nonce: 0, - }).unwrap(); - let a1 = a1.bake().unwrap(); + // -> B1 -> B2 -> B3 + + let a1 = client.new_block_at(&BlockId::Number(0), Default::default()) + .unwrap().bake().unwrap(); client.import(BlockOrigin::Own, a1.clone()).unwrap(); + let a2 = client.new_block_at(&BlockId::Hash(a1.hash()), Default::default()) + .unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, a2.clone()).unwrap(); + let mut b1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); + + // needed to make sure B1 gets a different hash from A1 b1.push_transfer(Transfer { from: AccountKeyring::Alice.into(), to: AccountKeyring::Ferdie.into(), - amount: 50, + amount: 1, nonce: 0, }).unwrap(); let b1 = b1.bake().unwrap(); client.import(BlockOrigin::Own, b1.clone()).unwrap(); - assert_eq!(990, current_balance()); - // Set B1 as new best - client.set_head(BlockId::hash(b1.hash())).unwrap(); - assert_eq!(950, current_balance()); + + let b2 = client.new_block_at(&BlockId::Hash(b1.hash()), Default::default()) + .unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, b2.clone()).unwrap(); + + // we will finalize A2 which should make it impossible to import a new + // B3 at the same height but that doesnt't include it + client.finalize_block(BlockId::Hash(a2.hash()), None).unwrap(); + + let b3 = client.new_block_at(&BlockId::Hash(b2.hash()), Default::default()) + .unwrap().bake().unwrap(); + + let import_err = client.import(BlockOrigin::Own, b3).err().unwrap(); + let expected_err = ConsensusError::ClientImport( + error::Error::NotInFinalizedChain.to_string() + ); + + assert_eq!( + import_err.to_string(), + expected_err.to_string(), + ); + + // adding a C1 block which is lower than the last finalized should also + // fail (with a cheaper check that doesn't require checking ancestry). + let mut c1 = client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); + + // needed to make sure C1 gets a different hash from A1 and B1 + c1.push_transfer(Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), + amount: 2, + nonce: 0, + }).unwrap(); + let c1 = c1.bake().unwrap(); + + let import_err = client.import(BlockOrigin::Own, c1).err().unwrap(); + let expected_err = ConsensusError::ClientImport( + error::Error::NotInFinalizedChain.to_string() + ); + + assert_eq!( + import_err.to_string(), + expected_err.to_string(), + ); } #[test] @@ -2940,7 +2969,7 @@ pub(crate) mod tests { // now check that configuration cache works assert_eq!( - client.key_changes(1, BlockId::Number(31), &StorageKey(vec![42])).unwrap(), + client.key_changes(1, BlockId::Number(31), None, &StorageKey(vec![42])).unwrap(), vec![(30, 0), (27, 0), (25, 0), (24, 0), (11, 0)] ); } diff --git a/core/client/src/error.rs b/core/client/src/error.rs index 01bf08b53f913bc5fdf9d724166c82a9fb3f7371..9baebcc9d79dd13fbb3a6be636285d3ce3b2c49b 100644 --- a/core/client/src/error.rs +++ b/core/client/src/error.rs @@ -134,9 +134,7 @@ impl Error { } /// Chain a state error. - pub fn from_state(e: Box) -> Self { + pub fn from_state(e: Box) -> Self { Error::Execution(e) } } - -impl state_machine::Error for Error {} diff --git a/core/client/src/genesis.rs b/core/client/src/genesis.rs index f3e550dbea3628546a3a719b4513f632936d94dc..3da5bb4dcc931d9cf1a9e5036b68f296f8ef0cfd 100644 --- a/core/client/src/genesis.rs +++ b/core/client/src/genesis.rs @@ -24,7 +24,10 @@ pub fn construct_genesis_block< > ( state_root: Block::Hash ) -> Block { - let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root(::std::iter::empty::<(&[u8], &[u8])>()); + let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + Vec::new(), + ); + Block::new( <::Header as HeaderT>::new( Zero::zero(), @@ -41,25 +44,24 @@ pub fn construct_genesis_block< mod tests { use codec::{Encode, Decode, Joiner}; use executor::native_executor_instance; - use state_machine::{self, OverlayedChanges, ExecutionStrategy}; + use state_machine::{self, StateMachine, OverlayedChanges, ExecutionStrategy}; use state_machine::backend::InMemory; use test_client::{ runtime::genesismap::{GenesisConfig, insert_genesis_block}, runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest}, AccountKeyring, Sr25519Keyring, }; - use primitives::Blake2Hasher; - use hex::*; + use primitives::{Blake2Hasher, map}; + use hex_literal::*; native_executor_instance!( Executor, test_client::runtime::api::dispatch, - test_client::runtime::native_version, - test_client::runtime::WASM_BINARY + test_client::runtime::native_version ); fn executor() -> executor::NativeExecutor { - executor::NativeExecutor::new(None) + executor::NativeExecutor::new(executor::WasmExecutionMethod::Interpreted, None) } fn construct_block( @@ -86,10 +88,10 @@ mod tests { let hash = header.hash(); let mut overlay = OverlayedChanges::default(); - state_machine::new( + StateMachine::new( backend, state_machine::disabled_changes_trie_state::<_, u64>(), - state_machine::NeverOffchainExt::new(), + None, &mut overlay, &executor(), "Core_initialize_block", @@ -100,10 +102,10 @@ mod tests { ).unwrap(); for tx in transactions.iter() { - state_machine::new( + StateMachine::new( backend, state_machine::disabled_changes_trie_state::<_, u64>(), - state_machine::NeverOffchainExt::new(), + None, &mut overlay, &executor(), "BlockBuilder_apply_extrinsic", @@ -114,10 +116,10 @@ mod tests { ).unwrap(); } - let (ret_data, _, _) = state_machine::new( + let (ret_data, _, _) = StateMachine::new( backend, state_machine::disabled_changes_trie_state::<_, u64>(), - state_machine::NeverOffchainExt::new(), + None, &mut overlay, &executor(), "BlockBuilder_finalize_block", @@ -153,6 +155,8 @@ mod tests { vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], 1000, None, + map![], + map![], ).genesis_map(); let genesis_hash = insert_genesis_block(&mut storage); @@ -160,10 +164,10 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = state_machine::new( + let _ = StateMachine::new( &backend, state_machine::disabled_changes_trie_state::<_, u64>(), - state_machine::NeverOffchainExt::new(), + None, &mut overlay, &executor(), "Core_execute_block", @@ -181,6 +185,8 @@ mod tests { vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], 1000, None, + map![], + map![], ).genesis_map(); let genesis_hash = insert_genesis_block(&mut storage); @@ -188,10 +194,10 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = state_machine::new( + let _ = StateMachine::new( &backend, state_machine::disabled_changes_trie_state::<_, u64>(), - state_machine::NeverOffchainExt::new(), + None, &mut overlay, &executor(), "Core_execute_block", @@ -209,6 +215,8 @@ mod tests { vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], 68, None, + map![], + map![], ).genesis_map(); let genesis_hash = insert_genesis_block(&mut storage); @@ -216,10 +224,10 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let r = state_machine::new( + let r = StateMachine::new( &backend, state_machine::disabled_changes_trie_state::<_, u64>(), - state_machine::NeverOffchainExt::new(), + None, &mut overlay, &executor(), "Core_execute_block", diff --git a/core/client/src/in_mem.rs b/core/client/src/in_mem.rs index c199af366b98ea97a30eb17837234b3763ab8d9d..1ab222aa61ab2009d90926b148c0379d07f58ca7 100644 --- a/core/client/src/in_mem.rs +++ b/core/client/src/in_mem.rs @@ -23,16 +23,21 @@ use primitives::storage::well_known_keys; use sr_primitives::generic::BlockId; use sr_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor}; use sr_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay}; -use state_machine::backend::{Backend as StateBackend, InMemory}; +use state_machine::{ + backend::{Backend as StateBackend, InMemory}, + ChangesTrieTransaction, +}; use hash_db::Hasher; -use trie::MemoryDB; +use header_metadata::{CachedHeaderMetadata, HeaderMetadata}; use crate::error; use crate::backend::{self, NewBlockState, StorageCollection, ChildStorageCollection}; use crate::light; use crate::leaves::LeafSet; -use crate::blockchain::{self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId}; +use crate::blockchain::{ + self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId +}; struct PendingBlock { block: StoredBlock, @@ -221,11 +226,7 @@ impl Blockchain { if &best_hash == header.parent_hash() { None } else { - let route = crate::blockchain::tree_route( - self, - BlockId::Hash(best_hash), - BlockId::Hash(*header.parent_hash()), - )?; + let route = header_metadata::tree_route(self, best_hash, *header.parent_hash())?; Some(route) } }; @@ -320,6 +321,21 @@ impl HeaderBackend for Blockchain { } } +impl HeaderMetadata for Blockchain { + type Error = error::Error; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header)) + .ok_or(error::Error::UnknownBlock(format!("header not found: {}", hash))) + } + + fn insert_header_metadata(&self, _hash: Block::Hash, _metadata: CachedHeaderMetadata) { + // No need to implement. + } + fn remove_header_metadata(&self, _hash: Block::Hash) { + // No need to implement. + } +} impl blockchain::Backend for Blockchain { fn body(&self, id: BlockId) -> error::Result::Extrinsic>>> { @@ -440,7 +456,6 @@ pub struct BlockImportOperation { pending_cache: HashMap>, old_state: InMemory, new_state: Option>, - changes_trie_update: Option>, aux: Vec<(Vec, Option>)>, finalized_blocks: Vec<(BlockId, Option)>, set_head: Option>, @@ -483,11 +498,6 @@ where Ok(()) } - fn update_changes_trie(&mut self, update: MemoryDB) -> error::Result<()> { - self.changes_trie_update = Some(update); - Ok(()) - } - fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> error::Result { check_genesis_storage(&top, &children)?; @@ -504,6 +514,13 @@ where Ok(root) } + fn update_changes_trie( + &mut self, + _update: ChangesTrieTransaction>, + ) -> error::Result<()> { + Ok(()) + } + fn insert_aux(&mut self, ops: I) -> error::Result<()> where I: IntoIterator, Option>)> { @@ -601,7 +618,6 @@ where pending_cache: Default::default(), old_state, new_state: None, - changes_trie_update: None, aux: Default::default(), finalized_blocks: Default::default(), set_head: None, @@ -703,6 +719,10 @@ where .map(|num| num.is_zero()) .unwrap_or(false) } + + fn remote_blockchain(&self) -> Arc> { + unimplemented!() + } } /// Check that genesis storage is valid. diff --git a/core/client/src/lib.rs b/core/client/src/lib.rs index 1ea39976e479630cfa753849d59081cb5dc3f0c6..57147eb18b181e51803e30955b039d8dfb74aeac 100644 --- a/core/client/src/lib.rs +++ b/core/client/src/lib.rs @@ -49,7 +49,7 @@ //! use substrate_client::{Client, in_mem::Backend, LocalCallExecutor}; //! use primitives::Blake2Hasher; //! use sr_primitives::{StorageOverlay, ChildrenStorageOverlay}; -//! use executor::NativeExecutor; +//! use executor::{NativeExecutor, WasmExecutionMethod}; //! //! // In this example, we're using the `Block` and `RuntimeApi` types from the //! // `substrate-test-runtime-client` crate. These types are automatically generated when @@ -62,12 +62,13 @@ //! backend.clone(), //! LocalCallExecutor::new( //! backend.clone(), -//! NativeExecutor::::new(None), +//! NativeExecutor::::new(WasmExecutionMethod::Interpreted, None), //! None, //! ), //! // This parameter provides the storage for the chain genesis. //! <(StorageOverlay, ChildrenStorageOverlay)>::default(), -//! Default::default() +//! Default::default(), +//! Default::default(), //! ); //! ``` //! @@ -113,18 +114,17 @@ pub use crate::call_executor::{CallExecutor, LocalCallExecutor}; pub use crate::client::{ new_with_backend, new_in_mem, - BlockBody, BlockStatus, ImportNotifications, FinalityNotifications, BlockchainEvents, + BlockBody, ImportNotifications, FinalityNotifications, BlockchainEvents, BlockImportNotification, Client, ClientInfo, ExecutionStrategies, FinalityNotification, - LongestChain, BlockOf, ProvideUncles, - utils, + LongestChain, BlockOf, ProvideUncles, ForkBlocks, + utils, apply_aux, }; #[cfg(feature = "std")] pub use crate::notifications::{StorageEventStream, StorageChangeSet}; #[cfg(feature = "std")] -pub use state_machine::{ExecutionStrategy, NeverOffchainExt}; +pub use state_machine::{ExecutionStrategy, StorageProof}; #[cfg(feature = "std")] pub use crate::leaves::LeafSet; - #[cfg(feature = "std")] pub use crate::blockchain::well_known_cache_keys; diff --git a/core/client/src/light/backend.rs b/core/client/src/light/backend.rs index d269b7d11399c174524081a1518d14f74c293e14..e1db5cec9cdd0995419a4f4c74da82bb9efb2a82 100644 --- a/core/client/src/light/backend.rs +++ b/core/client/src/light/backend.rs @@ -18,13 +18,13 @@ //! Everything else is requested from full nodes on demand. use std::collections::HashMap; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use parking_lot::{RwLock, Mutex}; use codec::{Decode, Encode}; use primitives::{ChangesTrieConfiguration, storage::well_known_keys}; use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; -use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState}; +use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState, ChangesTrieTransaction}; use sr_primitives::traits::{Block as BlockT, NumberFor, Zero, Header}; use crate::in_mem::check_genesis_storage; use crate::backend::{ @@ -34,21 +34,20 @@ use crate::backend::{ use crate::blockchain::{HeaderBackend as BlockchainHeaderBackend, well_known_cache_keys}; use crate::error::{Error as ClientError, Result as ClientResult}; use crate::light::blockchain::{Blockchain, Storage as BlockchainStorage}; -use crate::light::fetcher::{Fetcher, RemoteReadRequest}; use hash_db::Hasher; use trie::MemoryDB; const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always succeeds; qed"; /// Light client backend. -pub struct Backend { - blockchain: Arc>, +pub struct Backend { + blockchain: Arc>, genesis_state: RwLock>>, import_lock: Mutex<()>, } /// Light block (header and justification) import operation. -pub struct ImportOperation { +pub struct ImportOperation { header: Option, cache: HashMap>, leaf_state: NewBlockState, @@ -57,28 +56,21 @@ pub struct ImportOperation { set_head: Option>, storage_update: Option>, changes_trie_config_update: Option>, - _phantom: ::std::marker::PhantomData<(S, F)>, + _phantom: ::std::marker::PhantomData<(S)>, } -/// On-demand state. -pub struct OnDemandState { - fetcher: Weak, - blockchain: Weak>, - block: Block::Hash, - cached_header: RwLock>, -} - -/// On-demand or in-memory genesis state. -pub enum OnDemandOrGenesisState { - /// On-demand state - storage values are fetched from remote nodes. - OnDemand(OnDemandState), +/// Either in-memory genesis state, or locally-unavailable state. +pub enum GenesisOrUnavailableState { /// Genesis state - storage values are stored in-memory. Genesis(InMemoryState), + /// We know that state exists, but all calls will fail with error, because it + /// isn't locally available. + Unavailable, } -impl Backend { +impl Backend { /// Create new light backend. - pub fn new(blockchain: Arc>) -> Self { + pub fn new(blockchain: Arc>) -> Self { Self { blockchain, genesis_state: RwLock::new(None), @@ -87,12 +79,12 @@ impl Backend { } /// Get shared blockchain reference. - pub fn blockchain(&self) -> &Arc> { + pub fn blockchain(&self) -> &Arc> { &self.blockchain } } -impl AuxStore for Backend { +impl AuxStore for Backend { fn insert_aux< 'a, 'b: 'a, @@ -108,16 +100,15 @@ impl AuxStore for Backend { } } -impl ClientBackend for Backend where +impl ClientBackend for Backend where Block: BlockT, S: BlockchainStorage, - F: Fetcher, H: Hasher, H::Out: Ord, { - type BlockImportOperation = ImportOperation; - type Blockchain = Blockchain; - type State = OnDemandOrGenesisState; + type BlockImportOperation = ImportOperation; + type Blockchain = Blockchain; + type State = GenesisOrUnavailableState; type OffchainStorage = crate::in_mem::OffchainStorage; fn begin_operation(&self) -> ClientResult { @@ -188,7 +179,7 @@ impl ClientBackend for Backend where self.blockchain.storage().finalize_header(block) } - fn blockchain(&self) -> &Blockchain { + fn blockchain(&self) -> &Blockchain { &self.blockchain } @@ -196,7 +187,7 @@ impl ClientBackend for Backend where None } - fn changes_trie_storage(&self) -> Option<&PrunableStateChangesTrieStorage> { + fn changes_trie_storage(&self) -> Option<&dyn PrunableStateChangesTrieStorage> { None } @@ -210,22 +201,17 @@ impl ClientBackend for Backend where // special case for genesis block if block_number.is_zero() { if let Some(genesis_state) = self.genesis_state.read().clone() { - return Ok(OnDemandOrGenesisState::Genesis(genesis_state)); + return Ok(GenesisOrUnavailableState::Genesis(genesis_state)); } } - // else create on-demand state - let block_hash = self.blockchain.expect_block_hash_from_id(&block)?; - Ok(OnDemandOrGenesisState::OnDemand(OnDemandState { - fetcher: self.blockchain.fetcher(), - blockchain: Arc::downgrade(&self.blockchain), - block: block_hash, - cached_header: RwLock::new(None), - })) + // else return unavailable state. We do not return error here, because error + // would mean that we do not know this state at all. But we know that it exists + Ok(GenesisOrUnavailableState::Unavailable) } fn revert(&self, _n: NumberFor) -> ClientResult> { - Err(ClientError::NotAvailableOnLightClient.into()) + Err(ClientError::NotAvailableOnLightClient) } fn get_import_lock(&self) -> &Mutex<()> { @@ -233,11 +219,10 @@ impl ClientBackend for Backend where } } -impl RemoteBackend for Backend +impl RemoteBackend for Backend where Block: BlockT, - S: BlockchainStorage, - F: Fetcher, + S: BlockchainStorage + 'static, H: Hasher, H::Out: Ord, { @@ -247,17 +232,20 @@ where .map(|num| num.is_zero()) .unwrap_or(false) } + + fn remote_blockchain(&self) -> Arc> { + self.blockchain.clone() + } } -impl BlockImportOperation for ImportOperation +impl BlockImportOperation for ImportOperation where Block: BlockT, - F: Fetcher, S: BlockchainStorage, H: Hasher, H::Out: Ord, { - type State = OnDemandOrGenesisState; + type State = GenesisOrUnavailableState; fn state(&self) -> ClientResult> { // None means 'locally-stateless' backend @@ -285,7 +273,7 @@ where Ok(()) } - fn update_changes_trie(&mut self, _update: MemoryDB) -> ClientResult<()> { + fn update_changes_trie(&mut self, _update: ChangesTrieTransaction>) -> ClientResult<()> { // we're not storing anything locally => ignore changes Ok(()) } @@ -349,95 +337,18 @@ where } } -impl StateBackend for OnDemandState -where - Block: BlockT, - S: BlockchainStorage, - F: Fetcher, - H: Hasher, -{ - type Error = ClientError; - type Transaction = (); - type TrieBackendStorage = MemoryDB; - - fn storage(&self, key: &[u8]) -> ClientResult>> { - let mut header = self.cached_header.read().clone(); - if header.is_none() { - let cached_header = self.blockchain.upgrade() - .ok_or_else(|| ClientError::UnknownBlock(format!("{}", self.block))) - .and_then(|blockchain| blockchain.expect_header(BlockId::Hash(self.block)))?; - header = Some(cached_header.clone()); - *self.cached_header.write() = Some(cached_header); +impl std::fmt::Debug for GenesisOrUnavailableState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => state.fmt(f), + GenesisOrUnavailableState::Unavailable => write!(f, "Unavailable"), } - - futures::executor::block_on( - self.fetcher.upgrade().ok_or(ClientError::NotAvailableOnLightClient)? - .remote_read(RemoteReadRequest { - block: self.block, - header: header.expect("if block above guarantees that header is_some(); qed"), - key: key.to_vec(), - retry_count: None, - }) - ) - } - - fn child_storage(&self, _storage_key: &[u8], _key: &[u8]) -> ClientResult>> { - Err(ClientError::NotAvailableOnLightClient.into()) - } - - fn for_keys_with_prefix(&self, _prefix: &[u8], _action: A) { - // whole state is not available on light node - } - - fn for_keys_in_child_storage(&self, _storage_key: &[u8], _action: A) { - // whole state is not available on light node - } - - fn for_child_keys_with_prefix( - &self, - _storage_key: &[u8], - _prefix: &[u8], - _action: A, - ) { - // whole state is not available on light node - } - - fn storage_root(&self, _delta: I) -> (H::Out, Self::Transaction) - where - I: IntoIterator, Option>)> - { - (H::Out::default(), ()) - } - - fn child_storage_root(&self, _key: &[u8], _delta: I) -> (Vec, bool, Self::Transaction) - where - I: IntoIterator, Option>)> - { - (H::Out::default().as_ref().to_vec(), true, ()) - } - - fn pairs(&self) -> Vec<(Vec, Vec)> { - // whole state is not available on light node - Vec::new() - } - - fn keys(&self, _prefix: &[u8]) -> Vec> { - // whole state is not available on light node - Vec::new() - } - - fn as_trie_backend(&mut self) -> Option<&TrieBackend> { - None } } -impl StateBackend for OnDemandOrGenesisState -where - Block: BlockT, - F: Fetcher, - S: BlockchainStorage, - H: Hasher, - H::Out: Ord, +impl StateBackend for GenesisOrUnavailableState + where + H::Out: Ord, { type Error = ClientError; type Transaction = (); @@ -445,35 +356,39 @@ where fn storage(&self, key: &[u8]) -> ClientResult>> { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::storage(state, key), - OnDemandOrGenesisState::Genesis(ref state) => + GenesisOrUnavailableState::Genesis(ref state) => Ok(state.storage(key).expect(IN_MEMORY_EXPECT_PROOF)), + GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), } } fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> ClientResult>> { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::child_storage(state, storage_key, key), - OnDemandOrGenesisState::Genesis(ref state) => + GenesisOrUnavailableState::Genesis(ref state) => Ok(state.child_storage(storage_key, key).expect(IN_MEMORY_EXPECT_PROOF)), + GenesisOrUnavailableState::Unavailable => Err(ClientError::NotAvailableOnLightClient), } } fn for_keys_with_prefix(&self, prefix: &[u8], action: A) { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::for_keys_with_prefix(state, prefix, action), - OnDemandOrGenesisState::Genesis(ref state) => state.for_keys_with_prefix(prefix, action), + GenesisOrUnavailableState::Genesis(ref state) => state.for_keys_with_prefix(prefix, action), + GenesisOrUnavailableState::Unavailable => (), } } + fn for_key_values_with_prefix(&self, prefix: &[u8], action: A) { + match *self { + GenesisOrUnavailableState::Genesis(ref state) => state.for_key_values_with_prefix(prefix, action), + GenesisOrUnavailableState::Unavailable => (), + } + } + + fn for_keys_in_child_storage(&self, storage_key: &[u8], action: A) { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::for_keys_in_child_storage(state, storage_key, action), - OnDemandOrGenesisState::Genesis(ref state) => state.for_keys_in_child_storage(storage_key, action), + GenesisOrUnavailableState::Genesis(ref state) => state.for_keys_in_child_storage(storage_key, action), + GenesisOrUnavailableState::Unavailable => (), } } @@ -484,10 +399,9 @@ where action: A, ) { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::for_child_keys_with_prefix(state, storage_key, prefix, action), - OnDemandOrGenesisState::Genesis(ref state) => + GenesisOrUnavailableState::Genesis(ref state) => state.for_child_keys_with_prefix(storage_key, prefix, action), + GenesisOrUnavailableState::Unavailable => (), } } @@ -496,12 +410,9 @@ where I: IntoIterator, Option>)> { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::storage_root(state, delta), - OnDemandOrGenesisState::Genesis(ref state) => { - let (root, _) = state.storage_root(delta); - (root, ()) - }, + GenesisOrUnavailableState::Genesis(ref state) => + (state.storage_root(delta).0, ()), + GenesisOrUnavailableState::Unavailable => (H::Out::default(), ()), } } @@ -510,35 +421,32 @@ where I: IntoIterator, Option>)> { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::child_storage_root(state, key, delta), - OnDemandOrGenesisState::Genesis(ref state) => { + GenesisOrUnavailableState::Genesis(ref state) => { let (root, is_equal, _) = state.child_storage_root(key, delta); (root, is_equal, ()) }, + GenesisOrUnavailableState::Unavailable => (H::Out::default().as_ref().to_vec(), true, ()), } } fn pairs(&self) -> Vec<(Vec, Vec)> { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::pairs(state), - OnDemandOrGenesisState::Genesis(ref state) => state.pairs(), + GenesisOrUnavailableState::Genesis(ref state) => state.pairs(), + GenesisOrUnavailableState::Unavailable => Vec::new(), } } fn keys(&self, prefix: &[u8]) -> Vec> { match *self { - OnDemandOrGenesisState::OnDemand(ref state) => - StateBackend::::keys(state, prefix), - OnDemandOrGenesisState::Genesis(ref state) => state.keys(prefix), + GenesisOrUnavailableState::Genesis(ref state) => state.keys(prefix), + GenesisOrUnavailableState::Unavailable => Vec::new(), } } fn as_trie_backend(&mut self) -> Option<&TrieBackend> { match self { - OnDemandOrGenesisState::OnDemand(ref mut state) => state.as_trie_backend(), - OnDemandOrGenesisState::Genesis(ref mut state) => state.as_trie_backend(), + GenesisOrUnavailableState::Genesis(ref mut state) => state.as_trie_backend(), + GenesisOrUnavailableState::Unavailable => None, } } } @@ -556,24 +464,24 @@ mod tests { let def = Default::default(); let header0 = test_client::runtime::Header::new(0, def, def, def, Default::default()); - let backend: Backend<_, _, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + let backend: Backend<_, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); let mut op = backend.begin_operation().unwrap(); op.set_block_data(header0, None, None, NewBlockState::Final).unwrap(); op.reset_storage(Default::default(), Default::default()).unwrap(); backend.commit_operation(op).unwrap(); match backend.state_at(BlockId::Number(0)).unwrap() { - OnDemandOrGenesisState::Genesis(_) => (), + GenesisOrUnavailableState::Genesis(_) => (), _ => panic!("unexpected state"), } } #[test] - fn remote_state_is_created_when_genesis_state_is_inavailable() { - let backend: Backend<_, _, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); + fn unavailable_state_is_created_when_genesis_state_is_unavailable() { + let backend: Backend<_, Blake2Hasher> = Backend::new(Arc::new(DummyBlockchain::new(DummyStorage::new()))); match backend.state_at(BlockId::Number(0)).unwrap() { - OnDemandOrGenesisState::OnDemand(_) => (), + GenesisOrUnavailableState::Unavailable => (), _ => panic!("unexpected state"), } } diff --git a/core/client/src/light/blockchain.rs b/core/client/src/light/blockchain.rs index c0d9810ab432b55dafc0e49a49b9d8a08a70a0d5..510d6f5ae3a0a55b5a0dc6ad186e4b3ef05a1135 100644 --- a/core/client/src/light/blockchain.rs +++ b/core/client/src/light/blockchain.rs @@ -17,12 +17,14 @@ //! Light client blockchain backend. Only stores headers and justifications of recent //! blocks. CHT roots are stored for headers of ancient blocks. -use std::{sync::{Weak, Arc}, collections::HashMap}; -use parking_lot::Mutex; +use std::future::Future; +use std::{sync::Arc, collections::HashMap}; use sr_primitives::{Justification, generic::BlockId}; use sr_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; +use header_metadata::{HeaderMetadata, CachedHeaderMetadata}; + use crate::backend::{AuxStore, NewBlockState}; use crate::blockchain::{ Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache, @@ -31,10 +33,10 @@ use crate::blockchain::{ }; use crate::cht; use crate::error::{Error as ClientError, Result as ClientResult}; -use crate::light::fetcher::{Fetcher, RemoteBodyRequest, RemoteHeaderRequest}; +use crate::light::fetcher::{Fetcher, RemoteHeaderRequest}; /// Light client blockchain storage. -pub trait Storage: AuxStore + BlockchainHeaderBackend { +pub trait Storage: AuxStore + BlockchainHeaderBackend + HeaderMetadata { /// Store new header. Should refuse to revert any finalized blocks. fn import_header( @@ -72,65 +74,52 @@ pub trait Storage: AuxStore + BlockchainHeaderBackend { fn cache(&self) -> Option>>; } +/// Remote header. +#[derive(Debug)] +pub enum LocalOrRemote { + /// When data is available locally, it is returned. + Local(Data), + /// When data is unavailable locally, the request to fetch it from remote node is returned. + Remote(Request), + /// When data is unknown. + Unknown, +} + +/// Futures-based blockchain backend that either resolves blockchain data +/// locally, or fetches required data from remote node. +pub trait RemoteBlockchain: Send + Sync { + /// Get block header. + fn header(&self, id: BlockId) -> ClientResult, + >>; +} + /// Light client blockchain. -pub struct Blockchain { - fetcher: Mutex>, +pub struct Blockchain { storage: S, } -impl Blockchain { +impl Blockchain { /// Create new light blockchain backed with given storage. pub fn new(storage: S) -> Self { Self { - fetcher: Mutex::new(Default::default()), storage, } } - /// Sets fetcher reference. - pub fn set_fetcher(&self, fetcher: Weak) { - *self.fetcher.lock() = fetcher; - } - - /// Get fetcher weak reference. - pub fn fetcher(&self) -> Weak { - self.fetcher.lock().clone() - } - /// Get storage reference. pub fn storage(&self) -> &S { &self.storage } } -impl BlockchainHeaderBackend for Blockchain where Block: BlockT, S: Storage, F: Fetcher { +impl BlockchainHeaderBackend for Blockchain where Block: BlockT, S: Storage { fn header(&self, id: BlockId) -> ClientResult> { - match self.storage.header(id)? { - Some(header) => Ok(Some(header)), - None => { - let number = match id { - BlockId::Hash(hash) => match self.storage.number(hash)? { - Some(number) => number, - None => return Ok(None), - }, - BlockId::Number(number) => number, - }; - - // if the header is from future or genesis (we never prune genesis) => return - if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown { - return Ok(None); - } - - futures::executor::block_on( - self.fetcher().upgrade() - .ok_or(ClientError::NotAvailableOnLightClient)? - .remote_header(RemoteHeaderRequest { - cht_root: self.storage.header_cht_root(cht::size(), number)?, - block: number, - retry_count: None, - }) - ).map(Some) - } + match RemoteBlockchain::header(self, id)? { + LocalOrRemote::Local(header) => Ok(Some(header)), + LocalOrRemote::Remote(_) => Err(ClientError::NotAvailableOnLightClient), + LocalOrRemote::Unknown => Ok(None), } } @@ -151,24 +140,29 @@ impl BlockchainHeaderBackend for Blockchain where Bloc } } -impl BlockchainBackend for Blockchain where Block: BlockT, S: Storage, F: Fetcher { - fn body(&self, id: BlockId) -> ClientResult>> { - let header = match self.header(id)? { - Some(header) => header, - None => return Ok(None), - }; +impl HeaderMetadata for Blockchain where Block: BlockT, S: Storage { + type Error = ClientError; + + fn header_metadata(&self, hash: Block::Hash) -> Result, Self::Error> { + self.storage.header_metadata(hash) + } + + fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata) { + self.storage.insert_header_metadata(hash, metadata) + } + + fn remove_header_metadata(&self, hash: Block::Hash) { + self.storage.remove_header_metadata(hash) + } +} - futures::executor::block_on( - self.fetcher().upgrade().ok_or(ClientError::NotAvailableOnLightClient)? - .remote_body(RemoteBodyRequest { - header, - retry_count: None, - }) - ).map(Some) +impl BlockchainBackend for Blockchain where Block: BlockT, S: Storage { + fn body(&self, _id: BlockId) -> ClientResult>> { + Err(ClientError::NotAvailableOnLightClient) } fn justification(&self, _id: BlockId) -> ClientResult> { - Ok(None) + Err(ClientError::NotAvailableOnLightClient) } fn last_finalized(&self) -> ClientResult { @@ -180,29 +174,84 @@ impl BlockchainBackend for Blockchain where Block: Blo } fn leaves(&self) -> ClientResult> { - unimplemented!() + Err(ClientError::NotAvailableOnLightClient) } fn children(&self, _parent_hash: Block::Hash) -> ClientResult> { - unimplemented!() + Err(ClientError::NotAvailableOnLightClient) } } -impl, F, Block: BlockT> ProvideCache for Blockchain { +impl, Block: BlockT> ProvideCache for Blockchain { fn cache(&self) -> Option>> { self.storage.cache() } } +impl RemoteBlockchain for Blockchain + where + S: Storage, +{ + fn header(&self, id: BlockId) -> ClientResult, + >> { + // first, try to read header from local storage + if let Some(local_header) = self.storage.header(id)? { + return Ok(LocalOrRemote::Local(local_header)); + } + + // we need to know block number to check if it's a part of CHT + let number = match id { + BlockId::Hash(hash) => match self.storage.number(hash)? { + Some(number) => number, + None => return Ok(LocalOrRemote::Unknown), + }, + BlockId::Number(number) => number, + }; + + // if the header is genesis (never pruned), non-canonical, or from future => return + if number.is_zero() || self.storage.status(BlockId::Number(number))? == BlockStatus::Unknown { + return Ok(LocalOrRemote::Unknown); + } + + Ok(LocalOrRemote::Remote(RemoteHeaderRequest { + cht_root: self.storage.header_cht_root(cht::size(), number)?, + block: number, + retry_count: None, + })) + } +} + +/// Returns future that resolves header either locally, or remotely. +pub fn future_header>( + blockchain: &dyn RemoteBlockchain, + fetcher: &F, + id: BlockId, +) -> impl Future, ClientError>> { + use futures03::future::{ready, Either, FutureExt}; + + match blockchain.header(id) { + Ok(LocalOrRemote::Remote(request)) => Either::Left( + fetcher + .remote_header(request) + .then(|header| ready(header.map(Some))) + ), + Ok(LocalOrRemote::Unknown) => Either::Right(ready(Ok(None))), + Ok(LocalOrRemote::Local(local_header)) => Either::Right(ready(Ok(Some(local_header)))), + Err(err) => Either::Right(ready(Err(err))), + } +} + #[cfg(test)] pub mod tests { use std::collections::HashMap; + use parking_lot::Mutex; use test_client::runtime::{Hash, Block, Header}; use crate::blockchain::Info; - use crate::light::fetcher::tests::OkCallFetcher; use super::*; - pub type DummyBlockchain = Blockchain; + pub type DummyBlockchain = Blockchain; pub struct DummyStorage { pub changes_tries_cht_roots: HashMap, @@ -248,6 +297,17 @@ pub mod tests { } } + impl HeaderMetadata for DummyStorage { + type Error = ClientError; + + fn header_metadata(&self, hash: Hash) -> Result, Self::Error> { + self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header)) + .ok_or(ClientError::UnknownBlock("header not found".to_owned())) + } + fn insert_header_metadata(&self, _hash: Hash, _metadata: CachedHeaderMetadata) {} + fn remove_header_metadata(&self, _hash: Hash) {} + } + impl AuxStore for DummyStorage { fn insert_aux< 'a, diff --git a/core/client/src/light/call_executor.rs b/core/client/src/light/call_executor.rs index eba232bc3edec644897b867ddecf21adf201a7d7..ba6afd654bb26f6221664d97783adca336926fef 100644 --- a/core/client/src/light/call_executor.rs +++ b/core/client/src/light/call_executor.rs @@ -14,264 +14,88 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Light client call executor. Executes methods on remote full nodes, fetching -//! execution proof and checking it locally. +//! Methods that light client could use to execute runtime calls. -use std::{ - collections::HashSet, sync::Arc, panic::UnwindSafe, result, - marker::PhantomData, cell::RefCell, rc::Rc, -}; +use std::{sync::Arc, panic::UnwindSafe, result, cell::RefCell, rc::Rc}; use codec::{Encode, Decode}; -use primitives::{offchain, H256, Blake2Hasher, convert_hash, NativeOrEncoded}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{One, Block as BlockT, Header as HeaderT}; +use primitives::{ + offchain::OffchainExt, H256, Blake2Hasher, convert_hash, NativeOrEncoded, + traits::CodeExecutor, +}; +use sr_primitives::{ + generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, NumberFor}, +}; use state_machine::{ - self, Backend as StateBackend, CodeExecutor, OverlayedChanges, - ExecutionStrategy, create_proof_check_backend, - execution_proof_check_on_trie_backend, ExecutionManager, NeverOffchainExt + self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend, + execution_proof_check_on_trie_backend, ExecutionManager, ChangesTrieTransaction, StorageProof, + merge_storage_proofs, }; use hash_db::Hasher; use crate::runtime_api::{ProofRecorder, InitializeBlock}; use crate::backend::RemoteBackend; -use crate::blockchain::Backend as ChainBackend; use crate::call_executor::CallExecutor; use crate::error::{Error as ClientError, Result as ClientResult}; -use crate::light::fetcher::{Fetcher, RemoteCallRequest}; +use crate::light::fetcher::RemoteCallRequest; use executor::{RuntimeVersion, NativeVersion}; -use trie::MemoryDB; -/// Call executor that executes methods on remote node, querying execution proof -/// and checking proof by re-executing locally. -pub struct RemoteCallExecutor { - blockchain: Arc, - fetcher: Arc, -} - -/// Remote or local call executor. +/// Call executor that is able to execute calls only on genesis state. /// -/// Calls are executed locally if state is available locally. Otherwise, calls -/// are redirected to remote call executor. -pub struct RemoteOrLocalCallExecutor, B, R, L> { +/// Trying to execute call on non-genesis state leads to error. +pub struct GenesisCallExecutor { backend: Arc, - remote: R, local: L, - _block: PhantomData, } -impl Clone for RemoteCallExecutor { - fn clone(&self) -> Self { - RemoteCallExecutor { - blockchain: self.blockchain.clone(), - fetcher: self.fetcher.clone(), - } +impl GenesisCallExecutor { + /// Create new genesis call executor. + pub fn new(backend: Arc, local: L) -> Self { + Self { backend, local } } } -impl RemoteCallExecutor { - /// Creates new instance of remote call executor. - pub fn new(blockchain: Arc, fetcher: Arc) -> Self { - RemoteCallExecutor { blockchain, fetcher } - } -} - -impl CallExecutor for RemoteCallExecutor -where - Block: BlockT, - B: ChainBackend, - F: Fetcher, - Block::Hash: Ord, -{ - type Error = ClientError; - - fn call< - O: offchain::Externalities, - >( - &self, - id: &BlockId, - method: &str, - call_data: &[u8], - _strategy: ExecutionStrategy, - _side_effects_handler: Option<&mut O>, - ) -> ClientResult> - { - let block_hash = self.blockchain.expect_block_hash_from_id(id)?; - let block_header = self.blockchain.expect_header(id.clone())?; - - futures::executor::block_on(self.fetcher.remote_call(RemoteCallRequest { - block: block_hash, - header: block_header, - method: method.into(), - call_data: call_data.to_vec(), - retry_count: None, - })) - } - - fn contextual_call< - 'a, - O: offchain::Externalities, - IB: Fn() -> ClientResult<()>, - EM: Fn( - Result, Self::Error>, - Result, Self::Error> - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC, - >( - &self, - _initialize_block_fn: IB, - at: &BlockId, - method: &str, - call_data: &[u8], - changes: &RefCell, - initialize_block: InitializeBlock<'a, Block>, - execution_manager: ExecutionManager, - _native_call: Option, - side_effects_handler: Option<&mut O>, - _recorder: &Option>>>, - _enable_keystore: bool, - ) -> ClientResult> where ExecutionManager: Clone { - let block_initialized = match initialize_block { - InitializeBlock::Do(ref init_block) => { - init_block.borrow().is_some() - }, - InitializeBlock::Skip => false, - }; - - // it is only possible to execute contextual call if changes are empty - if !changes.borrow().is_empty() || block_initialized { - return Err(ClientError::NotAvailableOnLightClient.into()); - } - - self.call( - at, - method, - call_data, - (&execution_manager).into(), - side_effects_handler, - ).map(NativeOrEncoded::Encoded) - } - - fn runtime_version(&self, id: &BlockId) -> ClientResult { - let call_result = self.call( - id, - "Core_version", - &[], - ExecutionStrategy::NativeElseWasm, - NeverOffchainExt::new() - )?; - RuntimeVersion::decode(&mut call_result.as_slice()) - .map_err(|_| ClientError::VersionInvalid.into()) - } - - fn call_at_state< - O: offchain::Externalities, - S: StateBackend, - FF: FnOnce( - Result, Self::Error>, - Result, Self::Error> - ) -> Result, Self::Error>, - R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result, - >(&self, - _state: &S, - _state_block: &BlockId, - _changes: &mut OverlayedChanges, - _method: &str, - _call_data: &[u8], - _m: ExecutionManager, - _native_call: Option, - _side_effects_handler: Option<&mut O>, - ) -> ClientResult<( - NativeOrEncoded, - (S::Transaction, ::Out), - Option>, - )> { - Err(ClientError::NotAvailableOnLightClient.into()) - } - - fn prove_at_trie_state>( - &self, - _state: &state_machine::TrieBackend, - _changes: &mut OverlayedChanges, - _method: &str, - _call_data: &[u8] - ) -> ClientResult<(Vec, Vec>)> { - Err(ClientError::NotAvailableOnLightClient.into()) - } - - fn native_runtime_version(&self) -> Option<&NativeVersion> { - None - } -} - -impl Clone for RemoteOrLocalCallExecutor - where - Block: BlockT, - B: RemoteBackend, - R: CallExecutor + Clone, - L: CallExecutor + Clone, -{ +impl Clone for GenesisCallExecutor { fn clone(&self) -> Self { - RemoteOrLocalCallExecutor { + GenesisCallExecutor { backend: self.backend.clone(), - remote: self.remote.clone(), local: self.local.clone(), - _block: Default::default(), } } } -impl RemoteOrLocalCallExecutor - where - Block: BlockT, - B: RemoteBackend, - Remote: CallExecutor, - Local: CallExecutor, -{ - /// Creates new instance of remote/local call executor. - pub fn new(backend: Arc, remote: Remote, local: Local) -> Self { - RemoteOrLocalCallExecutor { backend, remote, local, _block: Default::default(), } - } -} - -impl CallExecutor for - RemoteOrLocalCallExecutor +impl CallExecutor for + GenesisCallExecutor where Block: BlockT, B: RemoteBackend, - Remote: CallExecutor, Local: CallExecutor, { type Error = ClientError; - fn call< - O: offchain::Externalities, - >( + fn call( &self, id: &BlockId, method: &str, call_data: &[u8], strategy: ExecutionStrategy, - side_effects_handler: Option<&mut O>, + side_effects_handler: Option, ) -> ClientResult> { match self.backend.is_local_state_available(id) { true => self.local.call(id, method, call_data, strategy, side_effects_handler), - false => self.remote.call(id, method, call_data, strategy, side_effects_handler), + false => Err(ClientError::NotAvailableOnLightClient), } } fn contextual_call< 'a, - O: offchain::Externalities, IB: Fn() -> ClientResult<()>, EM: Fn( Result, Self::Error>, Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, initialize_block_fn: IB, @@ -282,7 +106,7 @@ impl CallExecutor for initialize_block: InitializeBlock<'a, Block>, _manager: ExecutionManager, native_call: Option, - side_effects_handler: Option<&mut O>, + side_effects_handler: Option, recorder: &Option>>>, enable_keystore: bool, ) -> ClientResult> where ExecutionManager: Clone { @@ -291,7 +115,6 @@ impl CallExecutor for match self.backend.is_local_state_available(at) { true => CallExecutor::contextual_call::< - _, _, fn( Result, Local::Error>, @@ -313,95 +136,50 @@ impl CallExecutor for recorder, enable_keystore, ).map_err(|e| ClientError::Execution(Box::new(e.to_string()))), - false => CallExecutor::contextual_call::< - _, - _, - fn( - Result, Remote::Error>, - Result, Remote::Error>, - ) -> Result, Remote::Error>, - _, - NC - >( - &self.remote, - initialize_block_fn, - at, - method, - call_data, - changes, - initialize_block, - ExecutionManager::NativeWhenPossible, - native_call, - side_effects_handler, - recorder, - enable_keystore, - ).map_err(|e| ClientError::Execution(Box::new(e.to_string()))), + false => Err(ClientError::NotAvailableOnLightClient), } } fn runtime_version(&self, id: &BlockId) -> ClientResult { match self.backend.is_local_state_available(id) { true => self.local.runtime_version(id), - false => self.remote.runtime_version(id), + false => Err(ClientError::NotAvailableOnLightClient), } } fn call_at_state< - O: offchain::Externalities, S: StateBackend, FF: FnOnce( Result, Self::Error>, Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >(&self, - state: &S, - state_block: &BlockId, - changes: &mut OverlayedChanges, - method: &str, - call_data: &[u8], + _state: &S, + _state_block: &BlockId, + _changes: &mut OverlayedChanges, + _method: &str, + _call_data: &[u8], _manager: ExecutionManager, - native_call: Option, - side_effects_handler: Option<&mut O>, + _native_call: Option, + _side_effects_handler: Option, ) -> ClientResult<( NativeOrEncoded, (S::Transaction, ::Out), - Option>, + Option>>, )> { - // there's no actual way/need to specify native/wasm execution strategy on light node - // => we can safely ignore passed values - - CallExecutor::call_at_state::< - _, - _, - fn( - Result, Remote::Error>, - Result, Remote::Error>, - ) -> Result, Remote::Error>, - _, - NC - >( - &self.remote, - state, - state_block, - changes, - method, - call_data, - ExecutionManager::NativeWhenPossible, - native_call, - side_effects_handler, - ).map_err(|e| ClientError::Execution(Box::new(e.to_string()))) + Err(ClientError::NotAvailableOnLightClient) } fn prove_at_trie_state>( &self, - state: &state_machine::TrieBackend, - changes: &mut OverlayedChanges, - method: &str, - call_data: &[u8] - ) -> ClientResult<(Vec, Vec>)> { - self.remote.prove_at_trie_state(state, changes, method, call_data) + _state: &state_machine::TrieBackend, + _changes: &mut OverlayedChanges, + _method: &str, + _call_data: &[u8] + ) -> ClientResult<(Vec, StorageProof)> { + Err(ClientError::NotAvailableOnLightClient) } fn native_runtime_version(&self) -> Option<&NativeVersion> { @@ -419,7 +197,7 @@ pub fn prove_execution( executor: &E, method: &str, call_data: &[u8], -) -> ClientResult<(Vec, Vec>)> +) -> ClientResult<(Vec, StorageProof)> where Block: BlockT, S: StateBackend, @@ -439,11 +217,7 @@ pub fn prove_execution( // execute method + record execution proof let (result, exec_proof) = executor.prove_at_trie_state(&trie_state, &mut changes, method, call_data)?; - let total_proof = init_proof.into_iter() - .chain(exec_proof.into_iter()) - .collect::>() - .into_iter() - .collect(); + let total_proof = merge_storage_proofs(vec![init_proof, exec_proof]); Ok((result, total_proof)) } @@ -455,13 +229,37 @@ pub fn prove_execution( pub fn check_execution_proof( executor: &E, request: &RemoteCallRequest

, - remote_proof: Vec> + remote_proof: StorageProof, +) -> ClientResult> + where + Header: HeaderT, + E: CodeExecutor, + H: Hasher, +{ + check_execution_proof_with_make_header::( + executor, + request, + remote_proof, + |header|
::new( + *header.number() + One::one(), + Default::default(), + Default::default(), + header.hash(), + Default::default(), + ), + ) +} + +fn check_execution_proof_with_make_header Header>( + executor: &E, + request: &RemoteCallRequest
, + remote_proof: StorageProof, + make_next_header: MakeNextHeader, ) -> ClientResult> where Header: HeaderT, - E: CodeExecutor, - H: Hasher, - H::Out: Ord + 'static, + E: CodeExecutor, + H: Hasher, { let local_state_root = request.header.state_root(); let root: H::Out = convert_hash(&local_state_root); @@ -469,51 +267,135 @@ pub fn check_execution_proof( // prepare execution environment + check preparation proof let mut changes = OverlayedChanges::default(); let trie_backend = create_proof_check_backend(root, remote_proof)?; - let next_block =
::new( - *request.header.number() + One::one(), - Default::default(), - Default::default(), - request.header.hash(), - request.header.digest().clone(), - ); - execution_proof_check_on_trie_backend::( + let next_header = make_next_header(&request.header); + execution_proof_check_on_trie_backend::( &trie_backend, &mut changes, executor, "Core_initialize_block", - &next_block.encode(), + &next_header.encode(), None, )?; // execute method - let local_result = execution_proof_check_on_trie_backend::( + execution_proof_check_on_trie_backend::( &trie_backend, &mut changes, executor, &request.method, &request.call_data, None, - )?; - - Ok(local_result) + ).map_err(Into::into) } #[cfg(test)] mod tests { + use super::*; use consensus::BlockOrigin; - use test_client::{self, runtime::Header, ClientExt, TestClient}; - use executor::NativeExecutor; + use test_client::{self, runtime::{Header, Digest, Block}, ClientExt, TestClient}; + use executor::{NativeExecutor, WasmExecutionMethod}; + use primitives::Blake2Hasher; use crate::backend::{Backend, NewBlockState}; use crate::in_mem::Backend as InMemBackend; - use crate::light::fetcher::tests::OkCallFetcher; - use super::*; + + struct DummyCallExecutor; + + impl CallExecutor for DummyCallExecutor { + type Error = ClientError; + + fn call( + &self, + _id: &BlockId, + _method: &str, + _call_data: &[u8], + _strategy: ExecutionStrategy, + _side_effects_handler: Option, + ) -> Result, ClientError> { + Ok(vec![42]) + } + + fn contextual_call< + 'a, + IB: Fn() -> ClientResult<()>, + EM: Fn( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >( + &self, + _initialize_block_fn: IB, + _at: &BlockId, + _method: &str, + _call_data: &[u8], + _changes: &RefCell, + _initialize_block: InitializeBlock<'a, Block>, + _execution_manager: ExecutionManager, + _native_call: Option, + _side_effects_handler: Option, + _proof_recorder: &Option>>>, + _enable_keystore: bool, + ) -> ClientResult> where ExecutionManager: Clone { + unreachable!() + } + + fn runtime_version(&self, _id: &BlockId) -> Result { + unreachable!() + } + + fn call_at_state< + S: state_machine::Backend, + F: FnOnce( + Result, Self::Error>, + Result, Self::Error> + ) -> Result, Self::Error>, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, + >(&self, + _state: &S, + _state_block: &BlockId, + _overlay: &mut OverlayedChanges, + _method: &str, + _call_data: &[u8], + _manager: ExecutionManager, + _native_call: Option, + _side_effects_handler: Option, + ) -> Result< + ( + NativeOrEncoded, + (S::Transaction, H256), + Option>>, + ), + ClientError, + > { + unreachable!() + } + + fn prove_at_trie_state>( + &self, + _trie_state: &state_machine::TrieBackend, + _overlay: &mut OverlayedChanges, + _method: &str, + _call_data: &[u8] + ) -> Result<(Vec, StorageProof), ClientError> { + unreachable!() + } + + fn native_runtime_version(&self) -> Option<&NativeVersion> { + unreachable!() + } + } + + fn local_executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + } #[test] fn execution_proof_is_generated_and_checked() { fn execute(remote_client: &TestClient, at: u64, method: &'static str) -> (Vec, Vec) { let remote_block_id = BlockId::Number(at); - let remote_root = remote_client.state_at(&remote_block_id) - .unwrap().storage_root(::std::iter::empty()).0; + let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); // 'fetch' execution proof from remote node let (remote_result, remote_execution_proof) = remote_client.execution_proof( @@ -523,30 +405,65 @@ mod tests { ).unwrap(); // check remote execution proof locally - let local_executor = NativeExecutor::::new(None); - let local_result = check_execution_proof(&local_executor, &RemoteCallRequest { - block: test_client::runtime::Hash::default(), - header: test_client::runtime::Header { - state_root: remote_root.into(), - parent_hash: Default::default(), - number: at, - extrinsics_root: Default::default(), - digest: Default::default(), + let local_result = check_execution_proof::<_, _, Blake2Hasher>( + &local_executor(), + &RemoteCallRequest { + block: test_client::runtime::Hash::default(), + header: remote_header, + method: method.into(), + call_data: vec![], + retry_count: None, }, - method: method.into(), - call_data: vec![], - retry_count: None, - }, remote_execution_proof).unwrap(); + remote_execution_proof, + ).unwrap(); (remote_result, local_result) } + fn execute_with_proof_failure(remote_client: &TestClient, at: u64, method: &'static str) { + let remote_block_id = BlockId::Number(at); + let remote_header = remote_client.header(&remote_block_id).unwrap().unwrap(); + + // 'fetch' execution proof from remote node + let (_, remote_execution_proof) = remote_client.execution_proof( + &remote_block_id, + method, + &[] + ).unwrap(); + + // check remote execution proof locally + let execution_result = check_execution_proof_with_make_header::<_, _, Blake2Hasher, _>( + &local_executor(), + &RemoteCallRequest { + block: test_client::runtime::Hash::default(), + header: remote_header, + method: method.into(), + call_data: vec![], + retry_count: None, + }, + remote_execution_proof, + |header|
::new( + at + 1, + Default::default(), + Default::default(), + header.hash(), + header.digest().clone(), // this makes next header wrong + ), + ); + match execution_result { + Err(crate::error::Error::Execution(_)) => (), + _ => panic!("Unexpected execution result: {:?}", execution_result), + } + } + // prepare remote client let remote_client = test_client::new(); - for _ in 1..3 { + for i in 1u32..3u32 { + let mut digest = Digest::default(); + digest.push(sr_primitives::generic::DigestItem::Other::(i.to_le_bytes().to_vec())); remote_client.import_justified( BlockOrigin::Own, - remote_client.new_block(Default::default()).unwrap().bake().unwrap(), + remote_client.new_block(digest).unwrap().bake().unwrap(), Default::default(), ).unwrap(); } @@ -555,20 +472,29 @@ mod tests { let (remote, local) = execute(&remote_client, 0, "Core_version"); assert_eq!(remote, local); + let (remote, local) = execute(&remote_client, 2, "Core_version"); + assert_eq!(remote, local); + // check method that requires environment let (_, block) = execute(&remote_client, 0, "BlockBuilder_finalize_block"); let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); assert_eq!(local_block.number, 1); - // check method that requires environment let (_, block) = execute(&remote_client, 2, "BlockBuilder_finalize_block"); let local_block: Header = Decode::decode(&mut &block[..]).unwrap(); assert_eq!(local_block.number, 3); + + // check that proof check doesn't panic even if proof is incorrect AND no panic handler is set + execute_with_proof_failure(&remote_client, 2, "Core_version"); + + // check that proof check doesn't panic even if proof is incorrect AND panic handler is set + panic_handler::set("TEST", "1.2.3"); + execute_with_proof_failure(&remote_client, 2, "Core_version"); } #[test] - fn code_is_executed_locally_or_remotely() { - let backend = Arc::new(InMemBackend::new()); + fn code_is_executed_at_genesis_only() { + let backend = Arc::new(InMemBackend::::new()); let def = H256::default(); let header0 = test_client::runtime::Header::new(0, def, def, def, Default::default()); let hash0 = header0.hash(); @@ -577,28 +503,29 @@ mod tests { backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap(); backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap(); - let local_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![1]))); - let remote_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![2]))); - let remote_or_local = RemoteOrLocalCallExecutor::new(backend, remote_executor, local_executor); + let genesis_executor = GenesisCallExecutor::new(backend, DummyCallExecutor); assert_eq!( - remote_or_local.call( + genesis_executor.call( &BlockId::Number(0), "test_method", &[], ExecutionStrategy::NativeElseWasm, - NeverOffchainExt::new(), + None, ).unwrap(), - vec![1], + vec![42], ); - assert_eq!( - remote_or_local.call( - &BlockId::Number(1), - "test_method", - &[], - ExecutionStrategy::NativeElseWasm, - NeverOffchainExt::new(), - ).unwrap(), - vec![2], + + let call_on_unavailable = genesis_executor.call( + &BlockId::Number(1), + "test_method", + &[], + ExecutionStrategy::NativeElseWasm, + None, ); + + match call_on_unavailable { + Err(ClientError::NotAvailableOnLightClient) => (), + _ => unreachable!("unexpected result: {:?}", call_on_unavailable), + } } } diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs index 57c8114d17ba01e1cd72f96b8953d2d8402c8c8a..1dc1101c1a0d867bd813b90f9059eb48ba79b22a 100644 --- a/core/client/src/light/fetcher.rs +++ b/core/client/src/light/fetcher.rs @@ -17,22 +17,23 @@ //! Light client data fetcher. Fetches requested data from remote full nodes. use std::sync::Arc; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::marker::PhantomData; use std::future::Future; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use codec::{Decode, Encode}; -use primitives::{ChangesTrieConfiguration, convert_hash}; +use primitives::{ChangesTrieConfiguration, convert_hash, traits::CodeExecutor, H256}; use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor, SimpleArithmetic, CheckedConversion, }; -use state_machine::{CodeExecutor, ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, - ChangesTrieConfigurationRange, TrieBackend, InMemoryChangesTrieStorage, - read_proof_check, key_changes_proof_check_with_db, +use state_machine::{ + ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, + InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db, create_proof_check_backend_storage, read_child_proof_check, }; +pub use state_machine::StorageProof; use crate::cht; use crate::error::{Error as ClientError, Result as ClientResult}; @@ -73,7 +74,7 @@ pub struct RemoteReadRequest { /// Header of block at which read is performed. pub header: Header, /// Storage key to read. - pub key: Vec, + pub keys: Vec>, /// Number of times to retry request. None means that default RETRY_COUNT is used. pub retry_count: Option, } @@ -88,7 +89,7 @@ pub struct RemoteReadChildRequest { /// Storage key for child. pub storage_key: Vec, /// Child storage key to read. - pub key: Vec, + pub keys: Vec>, /// Number of times to retry request. None means that default RETRY_COUNT is used. pub retry_count: Option, } @@ -109,6 +110,8 @@ pub struct RemoteChangesRequest { /// Known changes trie roots for the range of blocks [tries_roots.0..max_block]. /// Proofs for roots of ascendants of tries_roots.0 are provided by the remote node. pub tries_roots: (Header::Number, Header::Hash, Vec), + /// Optional Child Storage key to read. + pub storage_key: Option>, /// Storage key to read. pub key: Vec, /// Number of times to retry request. None means that default RETRY_COUNT is used. @@ -127,7 +130,7 @@ pub struct ChangesProof { pub roots: BTreeMap, /// The proofs for all changes tries roots that have been touched AND are /// missing from the requester' node. It is a map of CHT number => proof. - pub roots_proof: Vec>, + pub roots_proof: StorageProof, } /// Remote block body request @@ -143,15 +146,15 @@ pub struct RemoteBodyRequest { /// is correct (see FetchedDataChecker) and return already checked data. pub trait Fetcher: Send + Sync { /// Remote header future. - type RemoteHeaderResult: Future>; + type RemoteHeaderResult: Future> + Send + 'static; /// Remote storage read future. - type RemoteReadResult: Future>, ClientError>>; + type RemoteReadResult: Future, Option>>, ClientError>> + Send + 'static; /// Remote call result future. - type RemoteCallResult: Future, ClientError>>; + type RemoteCallResult: Future, ClientError>> + Send + 'static; /// Remote changes result future. - type RemoteChangesResult: Future, u32)>, ClientError>>; + type RemoteChangesResult: Future, u32)>, ClientError>> + Send + 'static; /// Remote block body result future. - type RemoteBodyResult: Future, ClientError>>; + type RemoteBodyResult: Future, ClientError>> + Send + 'static; /// Fetch remote header. fn remote_header(&self, request: RemoteHeaderRequest) -> Self::RemoteHeaderResult; @@ -184,25 +187,25 @@ pub trait FetchChecker: Send + Sync { &self, request: &RemoteHeaderRequest, header: Option, - remote_proof: Vec> + remote_proof: StorageProof, ) -> ClientResult; /// Check remote storage read proof. fn check_read_proof( &self, request: &RemoteReadRequest, - remote_proof: Vec> - ) -> ClientResult>>; + remote_proof: StorageProof, + ) -> ClientResult, Option>>>; /// Check remote storage read proof. fn check_read_child_proof( &self, request: &RemoteReadChildRequest, - remote_proof: Vec> - ) -> ClientResult>>; + remote_proof: StorageProof, + ) -> ClientResult, Option>>>; /// Check remote method execution proof. fn check_execution_proof( &self, request: &RemoteCallRequest, - remote_proof: Vec> + remote_proof: StorageProof, ) -> ClientResult>; /// Check remote changes query proof. fn check_changes_proof( @@ -219,15 +222,15 @@ pub trait FetchChecker: Send + Sync { } /// Remote data checker. -pub struct LightDataChecker, F> { - blockchain: Arc>, +pub struct LightDataChecker> { + blockchain: Arc>, executor: E, _hasher: PhantomData<(B, H)>, } -impl, F> LightDataChecker { +impl> LightDataChecker { /// Create new light data checker. - pub fn new(blockchain: Arc>, executor: E) -> Self { + pub fn new(blockchain: Arc>, executor: E) -> Self { Self { blockchain, executor, _hasher: PhantomData } @@ -307,6 +310,7 @@ impl, F> LightDataChecker, F> LightDataChecker, remote_roots: &BTreeMap, B::Hash>, - remote_roots_proof: Vec>, + remote_roots_proof: StorageProof, ) -> ClientResult<()> where H: Hasher, @@ -369,20 +373,18 @@ impl, F> LightDataChecker FetchChecker for LightDataChecker +impl FetchChecker for LightDataChecker where Block: BlockT, - E: CodeExecutor, - H: Hasher, - H::Out: Ord + 'static, + E: CodeExecutor, + H: Hasher, S: BlockchainStorage, - F: Send + Sync, { fn check_header_proof( &self, request: &RemoteHeaderRequest, remote_header: Option, - remote_proof: Vec> + remote_proof: StorageProof, ) -> ClientResult { let remote_header = remote_header.ok_or_else(|| ClientError::from(ClientError::InvalidCHTProof))?; @@ -398,29 +400,32 @@ impl FetchChecker for LightDataChecker, - remote_proof: Vec> - ) -> ClientResult>> { - read_proof_check::(convert_hash(request.header.state_root()), remote_proof, &request.key) - .map_err(Into::into) + remote_proof: StorageProof, + ) -> ClientResult, Option>>> { + read_proof_check::( + convert_hash(request.header.state_root()), + remote_proof, + request.keys.iter(), + ).map_err(Into::into) } fn check_read_child_proof( &self, request: &RemoteReadChildRequest, - remote_proof: Vec> - ) -> ClientResult>> { - read_child_proof_check::( + remote_proof: StorageProof, + ) -> ClientResult, Option>>> { + read_child_proof_check::( convert_hash(request.header.state_root()), remote_proof, &request.storage_key, - &request.key) - .map_err(Into::into) + request.keys.iter(), + ).map_err(Into::into) } fn check_execution_proof( &self, request: &RemoteCallRequest, - remote_proof: Vec> + remote_proof: StorageProof, ) -> ClientResult> { check_execution_proof::<_, _, H>(&self.executor, request, remote_proof) } @@ -439,7 +444,9 @@ impl FetchChecker for LightDataChecker ) -> ClientResult> { // TODO: #2621 - let extrinsics_root = HashFor::::ordered_trie_root(body.iter().map(Encode::encode)); + let extrinsics_root = HashFor::::ordered_trie_root( + body.iter().map(Encode::encode).collect(), + ); if *request.header.extrinsics_root() == extrinsics_root { Ok(body) } else { @@ -461,7 +468,7 @@ struct RootsStorage<'a, Number: SimpleArithmetic, Hash: 'a> { impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number, Hash> where H: Hasher, - Number: ::std::fmt::Display + Clone + SimpleArithmetic + Encode + Decode + Send + Sync + 'static, + Number: ::std::fmt::Display + ::std::hash::Hash + Clone + SimpleArithmetic + Encode + Decode + Send + Sync + 'static, Hash: 'a + Send + Sync + Clone + AsRef<[u8]>, { fn build_anchor( @@ -497,11 +504,11 @@ impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a #[cfg(test)] pub mod tests { - use futures::future::Ready; + use futures03::future::Ready; use parking_lot::Mutex; use codec::Decode; use crate::client::tests::prepare_client_with_key_changes; - use executor::{self, NativeExecutor}; + use executor::{NativeExecutor, WasmExecutionMethod}; use crate::error::Error as ClientError; use test_client::{ self, ClientExt, blockchain::HeaderBackend, AccountKeyring, @@ -525,12 +532,12 @@ pub mod tests { where E: std::convert::From<&'static str>, { - futures::future::ready(Err("Not implemented on test node".into())) + futures03::future::ready(Err("Not implemented on test node".into())) } impl Fetcher for OkCallFetcher { type RemoteHeaderResult = Ready>; - type RemoteReadResult = Ready>, ClientError>>; + type RemoteReadResult = Ready, Option>>, ClientError>>; type RemoteCallResult = Ready, ClientError>>; type RemoteChangesResult = Ready, u32)>, ClientError>>; type RemoteBodyResult = Ready, ClientError>>; @@ -548,7 +555,7 @@ pub mod tests { } fn remote_call(&self, _request: RemoteCallRequest
) -> Self::RemoteCallResult { - futures::future::ready(Ok((*self.lock()).clone())) + futures03::future::ready(Ok((*self.lock()).clone())) } fn remote_changes(&self, _request: RemoteChangesRequest
) -> Self::RemoteChangesResult { @@ -561,26 +568,33 @@ pub mod tests { } type TestChecker = LightDataChecker< - executor::NativeExecutor, + NativeExecutor, Blake2Hasher, Block, DummyStorage, - OkCallFetcher, >; - fn prepare_for_read_proof_check() -> (TestChecker, Header, Vec>, u32) { + fn local_executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + } + + fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) { // prepare remote client let remote_client = test_client::new(); let remote_block_id = BlockId::Number(0); let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); - remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap().storage_root(::std::iter::empty()).0.into(); + remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap() + .storage_root(::std::iter::empty()).0.into(); // 'fetch' read proof from remote node let heap_pages = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec())) .unwrap() .and_then(|v| Decode::decode(&mut &v.0[..]).ok()).unwrap(); - let remote_read_proof = remote_client.read_proof(&remote_block_id, well_known_keys::HEAP_PAGES).unwrap(); + let remote_read_proof = remote_client.read_proof( + &remote_block_id, + &[well_known_keys::HEAP_PAGES], + ).unwrap(); // check remote read proof locally let local_storage = InMemoryBlockchain::::new(); @@ -591,12 +605,56 @@ pub mod tests { None, crate::backend::NewBlockState::Final, ).unwrap(); - let local_executor = NativeExecutor::::new(None); - let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor); + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor() + ); (local_checker, remote_block_header, remote_read_proof, heap_pages) } - fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, Vec>) { + fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, Vec) { + use test_client::DefaultTestClientBuilderExt; + use test_client::TestClientBuilderExt; + // prepare remote client + let remote_client = test_client::TestClientBuilder::new() + .add_extra_child_storage(b":child_storage:default:child1".to_vec(), b"key1".to_vec(), b"value1".to_vec()) + .build(); + let remote_block_id = BlockId::Number(0); + let remote_block_hash = remote_client.block_hash(0).unwrap().unwrap(); + let mut remote_block_header = remote_client.header(&remote_block_id).unwrap().unwrap(); + remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap() + .storage_root(::std::iter::empty()).0.into(); + + // 'fetch' child read proof from remote node + let child_value = remote_client.child_storage( + &remote_block_id, + &StorageKey(b":child_storage:default:child1".to_vec()), + &StorageKey(b"key1".to_vec()), + ).unwrap().unwrap().0; + assert_eq!(b"value1"[..], child_value[..]); + let remote_read_proof = remote_client.read_child_proof( + &remote_block_id, + b":child_storage:default:child1", + &[b"key1"], + ).unwrap(); + + // check locally + let local_storage = InMemoryBlockchain::::new(); + local_storage.insert( + remote_block_hash, + remote_block_header.clone(), + None, + None, + crate::backend::NewBlockState::Final, + ).unwrap(); + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); + (local_checker, remote_block_header, remote_read_proof, child_value) + } + + fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, StorageProof) { // prepare remote client let remote_client = test_client::new(); let mut local_headers_hashes = Vec::new(); @@ -617,8 +675,10 @@ pub mod tests { if insert_cht { local_storage.insert_cht_root(1, local_cht_root); } - let local_executor = NativeExecutor::::new(None); - let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor); + let local_checker = LightDataChecker::new( + Arc::new(DummyBlockchain::new(DummyStorage::new())), + local_executor(), + ); (local_checker, local_cht_root, remote_block_header, remote_header_proof) } @@ -637,9 +697,29 @@ pub mod tests { assert_eq!((&local_checker as &dyn FetchChecker).check_read_proof(&RemoteReadRequest::
{ block: remote_block_header.hash(), header: remote_block_header, - key: well_known_keys::HEAP_PAGES.to_vec(), + keys: vec![well_known_keys::HEAP_PAGES.to_vec()], retry_count: None, - }, remote_read_proof).unwrap().unwrap()[0], heap_pages as u8); + }, remote_read_proof).unwrap().remove(well_known_keys::HEAP_PAGES).unwrap().unwrap()[0], heap_pages as u8); + } + + #[test] + fn storage_child_read_proof_is_generated_and_checked() { + let ( + local_checker, + remote_block_header, + remote_read_proof, + result, + ) = prepare_for_read_child_proof_check(); + assert_eq!((&local_checker as &dyn FetchChecker).check_read_child_proof( + &RemoteReadChildRequest::
{ + block: remote_block_header.hash(), + header: remote_block_header, + storage_key: b":child_storage:default:child1".to_vec(), + keys: vec![b"key1".to_vec()], + retry_count: None, + }, + remote_read_proof + ).unwrap().remove(b"key1".as_ref()).unwrap().unwrap(), result); } #[test] @@ -679,7 +759,7 @@ pub mod tests { let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - NativeExecutor::::new(None) + local_executor(), ); let local_checker = &local_checker as &dyn FetchChecker; let max = remote_client.info().chain.best_number; @@ -692,7 +772,7 @@ pub mod tests { // 'fetch' changes proof from remote node let key = StorageKey(key); let remote_proof = remote_client.key_changes_proof( - begin_hash, end_hash, begin_hash, max_hash, &key + begin_hash, end_hash, begin_hash, max_hash, None, &key ).unwrap(); // check proof on local client @@ -705,6 +785,7 @@ pub mod tests { max_block: (max, max_hash), tries_roots: (begin, begin_hash, local_roots_range), key: key.0, + storage_key: None, retry_count: None, }; let local_result = local_checker.check_changes_proof(&request, ChangesProof { @@ -739,7 +820,7 @@ pub mod tests { let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); let remote_proof = remote_client.key_changes_proof_with_cht_size( - b1, b4, b3, b4, &dave, 4 + b1, b4, b3, b4, None, &dave, 4 ).unwrap(); // prepare local checker, having a root of changes trie CHT#0 @@ -748,7 +829,7 @@ pub mod tests { local_storage.changes_tries_cht_roots.insert(0, local_cht_root); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), - NativeExecutor::::new(None) + local_executor(), ); // check proof on local client @@ -759,6 +840,7 @@ pub mod tests { last_block: (4, b4), max_block: (4, b4), tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]), + storage_key: None, key: dave.0, retry_count: None, }; @@ -777,7 +859,7 @@ pub mod tests { let (remote_client, local_roots, test_cases) = prepare_client_with_key_changes(); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - NativeExecutor::::new(None) + local_executor(), ); let local_checker = &local_checker as &dyn FetchChecker; let max = remote_client.info().chain.best_number; @@ -790,7 +872,7 @@ pub mod tests { // 'fetch' changes proof from remote node let key = StorageKey(key); let remote_proof = remote_client.key_changes_proof( - begin_hash, end_hash, begin_hash, max_hash, &key).unwrap(); + begin_hash, end_hash, begin_hash, max_hash, None, &key).unwrap(); let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec(); let config = ChangesTrieConfiguration::new(4, 2); @@ -800,6 +882,7 @@ pub mod tests { last_block: (end, end_hash), max_block: (max, max_hash), tries_roots: (begin, begin_hash, local_roots_range.clone()), + storage_key: None, key: key.0, retry_count: None, }; @@ -825,13 +908,13 @@ pub mod tests { max_block: remote_proof.max_block, proof: remote_proof.proof.clone(), roots: vec![(begin - 1, Default::default())].into_iter().collect(), - roots_proof: vec![], + roots_proof: StorageProof::empty(), }).is_err()); assert!(local_checker.check_changes_proof(&request, ChangesProof { max_block: remote_proof.max_block, proof: remote_proof.proof.clone(), roots: vec![(end + 1, Default::default())].into_iter().collect(), - roots_proof: vec![], + roots_proof: StorageProof::empty(), }).is_err()); } @@ -853,13 +936,13 @@ pub mod tests { let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap(); let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap(); let remote_proof = remote_client.key_changes_proof_with_cht_size( - b1, b4, b3, b4, &dave, 4 + b1, b4, b3, b4, None, &dave, 4 ).unwrap(); // fails when changes trie CHT is missing from the local db let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - NativeExecutor::::new(None) + local_executor(), ); assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, remote_proof.roots_proof.clone()).is_err()); @@ -869,9 +952,12 @@ pub mod tests { local_storage.changes_tries_cht_roots.insert(0, local_cht_root); let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), - NativeExecutor::::new(None) + local_executor(), + ); + let result = local_checker.check_changes_tries_proof( + 4, &remote_proof.roots, StorageProof::empty() ); - assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, vec![]).is_err()); + assert!(result.is_err()); } #[test] @@ -883,7 +969,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - NativeExecutor::::new(None) + local_executor(), ); let body_request = RemoteBodyRequest { @@ -906,7 +992,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - NativeExecutor::::new(None) + local_executor(), ); let body_request = RemoteBodyRequest { diff --git a/core/client/src/light/mod.rs b/core/client/src/light/mod.rs index 89d3c60ddc3727f7fb67ef8b1c332b92ed12d4b3..d06a9ae9dd93c09b4bb7e7322ea6d478ff916f53 100644 --- a/core/client/src/light/mod.rs +++ b/core/client/src/light/mod.rs @@ -24,67 +24,59 @@ pub mod fetcher; use std::sync::Arc; use executor::RuntimeInfo; -use primitives::{H256, Blake2Hasher}; +use primitives::{H256, Blake2Hasher, traits::CodeExecutor}; use sr_primitives::BuildStorage; use sr_primitives::traits::Block as BlockT; -use state_machine::CodeExecutor; use crate::call_executor::LocalCallExecutor; use crate::client::Client; use crate::error::Result as ClientResult; use crate::light::backend::Backend; use crate::light::blockchain::{Blockchain, Storage as BlockchainStorage}; -use crate::light::call_executor::{RemoteCallExecutor, RemoteOrLocalCallExecutor}; -use crate::light::fetcher::{Fetcher, LightDataChecker}; +use crate::light::call_executor::GenesisCallExecutor; +use crate::light::fetcher::LightDataChecker; /// Create an instance of light client blockchain backend. -pub fn new_light_blockchain, F>(storage: S) -> Arc> { +pub fn new_light_blockchain>(storage: S) -> Arc> { Arc::new(Blockchain::new(storage)) } /// Create an instance of light client backend. -pub fn new_light_backend(blockchain: Arc>, fetcher: Arc) -> Arc> +pub fn new_light_backend(blockchain: Arc>) -> Arc> where B: BlockT, S: BlockchainStorage, - F: Fetcher, { - blockchain.set_fetcher(Arc::downgrade(&fetcher)); Arc::new(Backend::new(blockchain)) } /// Create an instance of light client. -pub fn new_light( - backend: Arc>, - fetcher: Arc, +pub fn new_light( + backend: Arc>, genesis_storage: GS, code_executor: E, -) -> ClientResult, RemoteOrLocalCallExecutor< - B, - Backend, - RemoteCallExecutor, F>, - LocalCallExecutor, E> +) -> ClientResult, GenesisCallExecutor< + Backend, + LocalCallExecutor, E> >, B, RA>> where B: BlockT, - S: BlockchainStorage, - F: Fetcher, + S: BlockchainStorage + 'static, GS: BuildStorage, - E: CodeExecutor + RuntimeInfo, + E: CodeExecutor + RuntimeInfo, { - let remote_executor = RemoteCallExecutor::new(backend.blockchain().clone(), fetcher); let local_executor = LocalCallExecutor::new(backend.clone(), code_executor, None); - let executor = RemoteOrLocalCallExecutor::new(backend.clone(), remote_executor, local_executor); - Client::new(backend, executor, genesis_storage, Default::default()) + let executor = GenesisCallExecutor::new(backend.clone(), local_executor); + Client::new(backend, executor, genesis_storage, Default::default(), Default::default()) } /// Create an instance of fetch data checker. -pub fn new_fetch_checker, F>( - blockchain: Arc>, +pub fn new_fetch_checker>( + blockchain: Arc>, executor: E, -) -> LightDataChecker +) -> LightDataChecker where - E: CodeExecutor, + E: CodeExecutor, { LightDataChecker::new(blockchain, executor) } diff --git a/core/client/src/notifications.rs b/core/client/src/notifications.rs index 0ddc4c72cdb5530aba3570a2586a3132a353df24..37f90dcc0ba64a0bb10a5a4b31cc70a988582edc 100644 --- a/core/client/src/notifications.rs +++ b/core/client/src/notifications.rs @@ -22,7 +22,7 @@ use std::{ }; use fnv::{FnvHashSet, FnvHashMap}; -use futures::channel::mpsc; +use futures03::channel::mpsc; use primitives::storage::{StorageKey, StorageData}; use sr_primitives::traits::Block as BlockT; @@ -347,7 +347,7 @@ mod tests { // given let mut notifications = StorageNotifications::::default(); let child_filter = [(StorageKey(vec![4]), None)]; - let mut recv = futures::executor::block_on_stream( + let mut recv = futures03::executor::block_on_stream( notifications.listen(None, Some(&child_filter[..])) ); @@ -382,13 +382,13 @@ mod tests { // given let mut notifications = StorageNotifications::::default(); let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; - let mut recv1 = futures::executor::block_on_stream( + let mut recv1 = futures03::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![1])]), None) ); - let mut recv2 = futures::executor::block_on_stream( + let mut recv2 = futures03::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![2])]), None) ); - let mut recv3 = futures::executor::block_on_stream( + let mut recv3 = futures03::executor::block_on_stream( notifications.listen(Some(&[]), Some(&child_filter)) ); @@ -429,16 +429,16 @@ mod tests { let mut notifications = StorageNotifications::::default(); { let child_filter = [(StorageKey(vec![4]), Some(vec![StorageKey(vec![5])]))]; - let _recv1 = futures::executor::block_on_stream( + let _recv1 = futures03::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![1])]), None) ); - let _recv2 = futures::executor::block_on_stream( + let _recv2 = futures03::executor::block_on_stream( notifications.listen(Some(&[StorageKey(vec![2])]), None) ); - let _recv3 = futures::executor::block_on_stream( + let _recv3 = futures03::executor::block_on_stream( notifications.listen(None, None) ); - let _recv4 = futures::executor::block_on_stream( + let _recv4 = futures03::executor::block_on_stream( notifications.listen(None, Some(&child_filter)) ); assert_eq!(notifications.listeners.len(), 2); @@ -465,7 +465,7 @@ mod tests { // given let mut recv = { let mut notifications = StorageNotifications::::default(); - let recv = futures::executor::block_on_stream(notifications.listen(None, None)); + let recv = futures03::executor::block_on_stream(notifications.listen(None, None)); // when let changeset = vec![]; diff --git a/core/client/src/runtime_api.rs b/core/client/src/runtime_api.rs index ed5c9fad48dc3dc4968cd7a154d2d442445a36de..0fa0545daef2ffa49f85a2ba8ccb45b6d95d9e47 100644 --- a/core/client/src/runtime_api.rs +++ b/core/client/src/runtime_api.rs @@ -18,11 +18,14 @@ #[doc(hidden)] #[cfg(feature = "std")] -pub use state_machine::OverlayedChanges; +pub use state_machine::{OverlayedChanges, StorageProof}; #[doc(hidden)] #[cfg(feature = "std")] pub use primitives::NativeOrEncoded; #[doc(hidden)] +#[cfg(not(feature = "std"))] +pub use primitives::to_substrate_wasm_fn_return_value; +#[doc(hidden)] pub use sr_primitives::{ traits::{ Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, @@ -103,7 +106,7 @@ pub trait ApiExt { /// Extract the recorded proof. /// This stops the proof recording. - fn extract_proof(&mut self) -> Option>>; + fn extract_proof(&mut self) -> Option; } /// Before calling any runtime api function, the runtime need to be initialized @@ -136,7 +139,7 @@ pub trait CallRuntimeAt { fn call_api_at< 'a, R: Encode + Decode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, C: Core, >( &self, diff --git a/core/consensus/aura/Cargo.toml b/core/consensus/aura/Cargo.toml index d6ce48841b8592514dffce78ee340202a175f3e9..a09d51095018e57b5700c94a83baad1f6b5592ce 100644 --- a/core/consensus/aura/Cargo.toml +++ b/core/consensus/aura/Cargo.toml @@ -21,11 +21,12 @@ substrate-telemetry = { path = "../../telemetry" } keystore = { package = "substrate-keystore", path = "../../keystore" } consensus_common = { package = "substrate-consensus-common", path = "../common" } sr-primitives = { path = "../../sr-primitives" } -futures-preview = { version = "=0.3.0-alpha.17", features = ["compat"] } +futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } futures01 = { package = "futures", version = "0.1" } -futures-timer = "0.2.1" +futures-timer = "0.4.0" parking_lot = "0.9.0" -log = "0.4" +log = "0.4.8" +derive_more = "0.15.0" [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../keyring" } @@ -33,6 +34,6 @@ substrate-executor = { path = "../../executor" } network = { package = "substrate-network", path = "../../network", features = ["test-helpers"]} service = { package = "substrate-service", path = "../../service" } test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } -tokio = "0.1.7" -env_logger = "0.6" -tempfile = "3.1" +tokio = "0.1.22" +env_logger = "0.7.0" +tempfile = "3.1.0" diff --git a/core/consensus/aura/primitives/Cargo.toml b/core/consensus/aura/primitives/Cargo.toml index ac2c2c791b2b1920f656a3f90bba926afbbaa1fd..7fd3f3d05d9bfc43ba1d0d8ea2d073b1417ba013 100644 --- a/core/consensus/aura/primitives/Cargo.toml +++ b/core/consensus/aura/primitives/Cargo.toml @@ -10,7 +10,7 @@ codec = { package = "parity-scale-codec", version = "1.0.0", default-features = substrate-client = { path = "../../../client", default-features = false } app-crypto = { package = "substrate-application-crypto", path = "../../../application-crypto", default-features = false } rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } -sr-primitives = { path = "../../../sr-primitives", default-features = false } +sr-primitives = { path = "../../../sr-primitives", default-features = false } [features] default = ["std"] diff --git a/core/consensus/aura/primitives/src/lib.rs b/core/consensus/aura/primitives/src/lib.rs index 070eb6c6a91a44d0c93e66d7317616a1a3ea4366..e4620fcdbfdd44e6c3873db6eb80e318075fa051 100644 --- a/core/consensus/aura/primitives/src/lib.rs +++ b/core/consensus/aura/primitives/src/lib.rs @@ -23,45 +23,45 @@ use substrate_client::decl_runtime_apis; use rstd::vec::Vec; use sr_primitives::ConsensusEngineId; -mod app_sr25519 { - use app_crypto::{app_crypto, key_types::AURA, sr25519}; - app_crypto!(sr25519, AURA); -} - pub mod sr25519 { + mod app_sr25519 { + use app_crypto::{app_crypto, key_types::AURA, sr25519}; + app_crypto!(sr25519, AURA); + } + /// An Aura authority keypair using S/R 25519 as its crypto. #[cfg(feature = "std")] - pub type AuthorityPair = super::app_sr25519::Pair; + pub type AuthorityPair = app_sr25519::Pair; /// An Aura authority signature using S/R 25519 as its crypto. - pub type AuthoritySignature = super::app_sr25519::Signature; + pub type AuthoritySignature = app_sr25519::Signature; /// An Aura authority identifier using S/R 25519 as its crypto. - pub type AuthorityId = super::app_sr25519::Public; -} - -mod app_ed25519 { - use app_crypto::{app_crypto, key_types::AURA, ed25519}; - app_crypto!(ed25519, AURA); + pub type AuthorityId = app_sr25519::Public; } pub mod ed25519 { + mod app_ed25519 { + use app_crypto::{app_crypto, key_types::AURA, ed25519}; + app_crypto!(ed25519, AURA); + } + /// An Aura authority keypair using Ed25519 as its crypto. #[cfg(feature = "std")] - pub type AuthorityPair = super::app_ed25519::Pair; + pub type AuthorityPair = app_ed25519::Pair; /// An Aura authority signature using Ed25519 as its crypto. - pub type AuthoritySignature = super::app_ed25519::Signature; + pub type AuthoritySignature = app_ed25519::Signature; /// An Aura authority identifier using Ed25519 as its crypto. - pub type AuthorityId = super::app_ed25519::Public; + pub type AuthorityId = app_ed25519::Public; } /// The `ConsensusEngineId` of AuRa. pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a']; /// The index of an authority. -pub type AuthorityIndex = u64; +pub type AuthorityIndex = u32; /// An consensus log item for Aura. #[derive(Decode, Encode)] diff --git a/core/consensus/aura/src/lib.rs b/core/consensus/aura/src/lib.rs index f9bd8267ba85f262e430e0eb8e231719c9767baf..eb2d1dba20f1b7750d9f7780f71b63ad4c6c98e7 100644 --- a/core/consensus/aura/src/lib.rs +++ b/core/consensus/aura/src/lib.rs @@ -44,25 +44,24 @@ use client::{ well_known_cache_keys::{self, Id as CacheKeyId}, }; -use sr_primitives::{generic::{self, BlockId, OpaqueDigestItemId}, Justification}; +use sr_primitives::{generic::{BlockId, OpaqueDigestItemId}, Justification}; use sr_primitives::traits::{Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member}; use primitives::crypto::Pair; -use inherents::{InherentDataProviders, InherentData}; +use inherents::{InherentDataProviders, InherentData, RuntimeString}; -use futures::{prelude::*, future}; +use futures::prelude::*; use parking_lot::Mutex; -use futures_timer::Delay; -use log::{error, warn, debug, info, trace}; +use log::{debug, info, trace}; use srml_aura::{ InherentType as AuraInherent, AuraInherentData, timestamp::{TimestampInherentData, InherentType as TimestampInherent, InherentError as TIError} }; -use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; +use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_INFO}; use slots::{CheckedHeader, SlotData, SlotWorker, SlotInfo, SlotCompatible}; -use slots::{SignedDuration, check_equivocation}; +use slots::check_equivocation; use keystore::KeyStorePtr; @@ -140,19 +139,19 @@ pub fn start_aura( sync_oracle: SO, inherent_data_providers: InherentDataProviders, force_authoring: bool, - keystore: Option, + keystore: KeyStorePtr, ) -> Result, consensus_common::Error> where B: BlockT, C: ProvideRuntimeApi + BlockOf + ProvideCache + AuxStore + Send + Sync, C::Api: AuraApi>, SC: SelectChain, + E: Environment + Send + Sync + 'static, E::Proposer: Proposer, - >::Create: Unpin + Send + 'static, - P: Pair + Send + Sync + 'static, + >::Create: Unpin + Send, + P: Pair + Send + Sync, P::Public: Hash + Member + Encode + Decode, P::Signature: Hash + Member + Encode + Decode, H: Header, - E: Environment, I: BlockImport + Send + Sync + 'static, Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, SO: SyncOracle + Send + Sync + Clone, @@ -184,149 +183,82 @@ struct AuraWorker { client: Arc, block_import: Arc>, env: E, - keystore: Option, + keystore: KeyStorePtr, sync_oracle: SO, force_authoring: bool, _key_type: PhantomData

, } -impl SlotWorker for AuraWorker where +impl slots::SimpleSlotWorker for AuraWorker where B: BlockT, C: ProvideRuntimeApi + BlockOf + ProvideCache + Sync, C::Api: AuraApi>, E: Environment, E::Proposer: Proposer, - >::Create: Unpin + Send + 'static, + >::Create: Unpin + Send, H: Header, I: BlockImport + Send + Sync + 'static, - P: Pair + Send + Sync + 'static, + P: Pair + Send + Sync, P::Public: Member + Encode + Decode + Hash, P::Signature: Member + Encode + Decode + Hash + Debug, SO: SyncOracle + Send + Clone, Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, { - type OnSlot = Pin> + Send>>; - - fn on_slot( - &mut self, - chain_head: B::Header, - slot_info: SlotInfo, - ) -> Self::OnSlot { - let client = self.client.clone(); - let block_import = self.block_import.clone(); - - let (timestamp, slot_num, slot_duration) = - (slot_info.timestamp, slot_info.number, slot_info.duration); - - let authorities = match authorities(client.as_ref(), &BlockId::Hash(chain_head.hash())) { - Ok(authorities) => authorities, - Err(e) => { - warn!("Unable to fetch authorities at block {:?}: {:?}", chain_head.hash(), e); - - telemetry!( - CONSENSUS_WARN; "aura.unable_fetching_authorities"; - "slot" => ?chain_head.hash(), - "err" => ?e, - ); - return Box::pin(future::ready(Ok(()))); - } - }; - - if !self.force_authoring && self.sync_oracle.is_offline() && authorities.len() > 1 { - debug!(target: "aura", "Skipping proposal slot. Waiting for the network."); - telemetry!( - CONSENSUS_DEBUG; - "aura.skipping_proposal_slot"; - "authorities_len" => authorities.len(), - ); - return Box::pin(future::ready(Ok(()))); - } - let maybe_author = slot_author::

(slot_num, &authorities); - let maybe_pair = maybe_author.and_then(|p| - self.keystore.as_ref().and_then(|k| - k.read().key_pair_by_type::

(&p, app_crypto::key_types::AURA).ok() - ) - ); - let proposal_work = match maybe_pair { - None => return Box::pin(future::ready(Ok(()))), - Some(pair) => { - debug!( - target: "aura", "Starting authorship at slot {}; timestamp = {}", - slot_num, - timestamp, - ); - telemetry!(CONSENSUS_DEBUG; "aura.starting_authorship"; - "slot_num" => slot_num, - "timestamp" => timestamp, - ); + type EpochData = Vec>; + type Claim = P; + type SyncOracle = SO; + type Proposer = E::Proposer; + type BlockImport = I; + + fn logging_target(&self) -> &'static str { + "aura" + } - // we are the slot author. make a block and sign it. - let mut proposer = match self.env.init(&chain_head) { - Ok(p) => p, - Err(e) => { - warn!("Unable to author block in slot {:?}: {:?}", slot_num, e); - telemetry!(CONSENSUS_WARN; "aura.unable_authoring_block"; - "slot" => slot_num, "err" => ?e - ); - return Box::pin(future::ready(Ok(()))) - } - }; + fn block_import(&self) -> Arc> { + self.block_import.clone() + } - let remaining_duration = slot_info.remaining_duration(); - // deadline our production to approx. the end of the - // slot - futures::future::select( - proposer.propose( - slot_info.inherent_data, - generic::Digest { - logs: vec![ - as CompatibleDigestItem

>::aura_pre_digest(slot_num), - ], - }, - remaining_duration, - ).map_err(|e| consensus_common::Error::ClientImport(format!("{:?}", e)).into()), - Delay::new(remaining_duration) - .map_err(|err| consensus_common::Error::FaultyTimer(err).into()) - ).map(|v| match v { - futures::future::Either::Left((v, _)) => v.map(|v| (v, pair)), - futures::future::Either::Right((Ok(_), _)) => - Err(consensus_common::Error::ClientImport("Timeout in the AuRa proposer".into())), - futures::future::Either::Right((Err(err), _)) => Err(err), - }) - } - }; + fn epoch_data(&self, header: &B::Header, _slot_number: u64) -> Result { + authorities(self.client.as_ref(), &BlockId::Hash(header.hash())) + } - Box::pin(proposal_work.map_ok(move |(b, pair)| { - // minor hack since we don't have access to the timestamp - // that is actually set by the proposer. - let slot_after_building = SignedDuration::default().slot_now(slot_duration); - if slot_after_building != slot_num { - info!("Discarding proposal for slot {}; block production took too long", slot_num); - telemetry!(CONSENSUS_INFO; "aura.discarding_proposal_took_too_long"; - "slot" => slot_num, - ); - return - } + fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize { + epoch_data.len() + } - let (header, body) = b.deconstruct(); - let pre_digest: Result = find_pre_digest::(&header); - if let Err(e) = pre_digest { - error!(target: "aura", "FATAL ERROR: Invalid pre-digest: {}!", e); - return - } else { - trace!(target: "aura", "Got correct number of seals. Good!") - }; + fn claim_slot( + &self, + _header: &B::Header, + slot_number: u64, + epoch_data: &Self::EpochData, + ) -> Option { + let expected_author = slot_author::

(slot_number, epoch_data); + + expected_author.and_then(|p| { + self.keystore.read() + .key_pair_by_type::

(&p, app_crypto::key_types::AURA).ok() + }) + } - let header_num = header.number().clone(); - let parent_hash = header.parent_hash().clone(); + fn pre_digest_data(&self, slot_number: u64, _claim: &Self::Claim) -> Vec> { + vec![ + as CompatibleDigestItem

>::aura_pre_digest(slot_number), + ] + } + fn block_import_params(&self) -> Box, + Self::Claim, + ) -> consensus_common::BlockImportParams + Send> { + Box::new(|header, header_hash, body, pair| { // sign the pre-sealed hash of the block and then // add it to a digest item. - let header_hash = header.hash(); let signature = pair.sign(header_hash.as_ref()); let signature_digest_item = as CompatibleDigestItem

>::aura_seal(signature); - let import_block: BlockImportParams = BlockImportParams { + BlockImportParams { origin: BlockOrigin::Own, header, justification: None, @@ -335,40 +267,74 @@ impl SlotWorker for AuraWorker w finalized: false, auxiliary: Vec::new(), fork_choice: ForkChoiceStrategy::LongestChain, - }; + } + }) + } - info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", - header_num, - import_block.post_header().hash(), - header_hash - ); - telemetry!(CONSENSUS_INFO; "aura.pre_sealed_block"; - "header_num" => ?header_num, - "hash_now" => ?import_block.post_header().hash(), - "hash_previously" => ?header_hash, - ); + fn force_authoring(&self) -> bool { + self.force_authoring + } - if let Err(e) = block_import.lock().import_block(import_block, Default::default()) { - warn!(target: "aura", "Error with block built on {:?}: {:?}", parent_hash, e); + fn sync_oracle(&mut self) -> &mut Self::SyncOracle { + &mut self.sync_oracle + } - telemetry!(CONSENSUS_WARN; "aura.err_with_block_built_on"; - "hash" => ?parent_hash, "err" => ?e, - ); - } - })) + fn proposer(&mut self, block: &B::Header) -> Result { + self.env.init(block).map_err(|e| { + consensus_common::Error::ClientImport(format!("{:?}", e)).into() + }) } } -macro_rules! aura_err { - ($($i: expr),+) => { - { - debug!(target: "aura", $( $i ),+); - format!($( $i ),+) - } - }; +impl SlotWorker for AuraWorker where + B: BlockT, + C: ProvideRuntimeApi + BlockOf + ProvideCache + Sync + Send, + C::Api: AuraApi>, + E: Environment + Send + Sync, + E::Proposer: Proposer, + >::Create: Unpin + Send + 'static, + H: Header, + I: BlockImport + Send + Sync + 'static, + P: Pair + Send + Sync, + P::Public: Member + Encode + Decode + Hash, + P::Signature: Member + Encode + Decode + Hash + Debug, + SO: SyncOracle + Send + Sync + Clone, + Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, +{ + type OnSlot = Pin> + Send>>; + + fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot { + >::on_slot(self, chain_head, slot_info) + } +} + +fn aura_err(error: Error) -> Error { + debug!(target: "aura", "{}", error); + error } -fn find_pre_digest(header: &B::Header) -> Result +#[derive(derive_more::Display)] +enum Error { + #[display(fmt = "Multiple Aura pre-runtime headers")] + MultipleHeaders, + #[display(fmt = "No Aura pre-runtime digest found")] + NoDigestFound, + #[display(fmt = "Header {:?} is unsealed", _0)] + HeaderUnsealed(B::Hash), + #[display(fmt = "Header {:?} has a bad seal", _0)] + HeaderBadSeal(B::Hash), + #[display(fmt = "Slot Author not found")] + SlotAuthorNotFound, + #[display(fmt = "Bad signature on {:?}", _0)] + BadSignature(B::Hash), + #[display(fmt = "Rejecting block too far in future")] + TooFarInFuture, + Client(client::error::Error), + DataProvider(String), + Runtime(RuntimeString) +} + +fn find_pre_digest(header: &B::Header) -> Result> where DigestItemFor: CompatibleDigestItem

, P::Signature: Decode, P::Public: Encode + Decode + PartialEq + Clone, @@ -377,21 +343,20 @@ fn find_pre_digest(header: &B::Header) -> Result Err(aura_err!("Multiple AuRa pre-runtime headers, rejecting!"))?, + (Some(_), true) => Err(aura_err(Error::MultipleHeaders))?, (None, _) => trace!(target: "aura", "Ignoring digest not meant for us"), (s, false) => pre_digest = s, } } - pre_digest.ok_or_else(|| aura_err!("No AuRa pre-runtime digest found")) + pre_digest.ok_or_else(|| aura_err(Error::NoDigestFound)) } - /// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned. /// if it's successful, returns the pre-header and the digest item containing the seal. /// /// This digest item will always return `Some` when used with `as_aura_seal`. // -// FIXME #1018 needs misbehavior types. The `transaction_pool` parameter will be +// FIXME #1018 needs misbehavior types. The `transaction_pool` parameter will be // used to submit such misbehavior reports. fn check_header( client: &C, @@ -400,7 +365,7 @@ fn check_header( hash: B::Hash, authorities: &[AuthorityId

], _transaction_pool: Option<&T>, -) -> Result)>, String> where +) -> Result)>, Error> where DigestItemFor: CompatibleDigestItem

, P::Signature: Decode, C: client::backend::AuxStore, @@ -409,11 +374,11 @@ fn check_header( { let seal = match header.digest_mut().pop() { Some(x) => x, - None => return Err(format!("Header {:?} is unsealed", hash)), + None => return Err(Error::HeaderUnsealed(hash)), }; let sig = seal.as_aura_seal().ok_or_else(|| { - aura_err!("Header {:?} has a bad seal", hash) + aura_err(Error::HeaderBadSeal(hash)) })?; let slot_num = find_pre_digest::(&header)?; @@ -425,7 +390,7 @@ fn check_header( // check the signature is valid under the expected authority and // chain state. let expected_author = match slot_author::

(slot_num, &authorities) { - None => return Err("Slot Author not found".to_string()), + None => return Err(Error::SlotAuthorNotFound), Some(author) => author, }; @@ -438,7 +403,7 @@ fn check_header( slot_num, &header, expected_author, - ).map_err(|e| e.to_string())? { + ).map_err(Error::Client)? { info!( "Slot author is equivocating at slot {} with headers {:?} and {:?}", slot_num, @@ -449,7 +414,7 @@ fn check_header( Ok(CheckedHeader::Checked(header, (slot_num, seal))) } else { - Err(format!("Bad signature on {:?}", hash)) + Err(Error::BadSignature(hash)) } } } @@ -471,7 +436,7 @@ impl AuraVerifier block_id: BlockId, inherent_data: InherentData, timestamp_now: u64, - ) -> Result<(), String> + ) -> Result<(), Error> where C: ProvideRuntimeApi, C::Api: BlockBuilderApi { const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; @@ -480,7 +445,7 @@ impl AuraVerifier &block_id, block, inherent_data, - ).map_err(|e| format!("{:?}", e))?; + ).map_err(Error::Client)?; if !inherent_res.ok() { inherent_res @@ -490,7 +455,7 @@ impl AuraVerifier // halt import until timestamp is valid. // reject when too far ahead. if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { - return Err("Rejecting block too far in future".into()); + return Err(Error::TooFarInFuture); } let diff = timestamp.saturating_sub(timestamp_now); @@ -505,8 +470,10 @@ impl AuraVerifier thread::sleep(Duration::from_secs(diff)); Ok(()) }, - Some(TIError::Other(e)) => Err(e.into()), - None => Err(self.inherent_data_providers.error_to_string(&i, &e)), + Some(TIError::Other(e)) => Err(Error::Runtime(e)), + None => Err(Error::DataProvider( + self.inherent_data_providers.error_to_string(&i, &e) + )), }) } else { Ok(()) @@ -549,7 +516,7 @@ impl Verifier for AuraVerifier where hash, &authorities[..], self.transaction_pool.as_ref().map(|x| &**x), - )?; + ).map_err(|e| e.to_string())?; match checked_header { CheckedHeader::Checked(pre_header, (slot_num, seal)) => { // if the body is passed through, we need to use the runtime @@ -570,7 +537,7 @@ impl Verifier for AuraVerifier where BlockId::Hash(parent_hash), inherent_data, timestamp_now, - )?; + ).map_err(|e| e.to_string())?; } let (_, inner_body) = block.deconstruct(); @@ -594,7 +561,7 @@ impl Verifier for AuraVerifier where _ => None, }); - let import_block = BlockImportParams { + let block_import_params = BlockImportParams { origin, header: pre_header, post_digests: vec![seal], @@ -605,7 +572,7 @@ impl Verifier for AuraVerifier where fork_choice: ForkChoiceStrategy::LongestChain, }; - Ok((import_block, maybe_keys)) + Ok((block_import_params, maybe_keys)) } CheckedHeader::Deferred(a, b) => { debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); @@ -733,7 +700,7 @@ mod tests { use parking_lot::Mutex; use tokio::runtime::current_thread; use keyring::sr25519::Keyring; - use client::{LongestChain, BlockchainEvents}; + use client::BlockchainEvents; use test_client; use aura_primitives::sr25519::AuthorityPair; @@ -793,11 +760,11 @@ mod tests { } } - fn make_verifier(&self, client: PeersClient, _cfg: &ProtocolConfig) + fn make_verifier(&self, client: PeersClient, _cfg: &ProtocolConfig, _peer_data: &()) -> Self::Verifier { match client { - PeersClient::Full(client) => { + PeersClient::Full(client, _) => { let slot_duration = SlotDuration::get_or_compute(&*client) .expect("slot duration available"); let inherent_data_providers = InherentDataProviders::new(); @@ -814,7 +781,7 @@ mod tests { phantom: Default::default(), } }, - PeersClient::Light(_) => unreachable!("No (yet) tests for light client + Aura"), + PeersClient::Light(_, _) => unreachable!("No (yet) tests for light client + Aura"), } } @@ -849,6 +816,10 @@ mod tests { let mut runtime = current_thread::Runtime::new().unwrap(); let mut keystore_paths = Vec::new(); for (peer_id, key) in peers { + let mut net = net.lock(); + let peer = net.peer(*peer_id); + let client = peer.client().as_full().expect("full clients are created").clone(); + let select_chain = peer.select_chain().expect("full client has a select chain"); let keystore_path = tempfile::tempdir().expect("Creates keystore path"); let keystore = keystore::Store::open(keystore_path.path(), None).expect("Creates keystore."); @@ -856,11 +827,6 @@ mod tests { .expect("Creates authority key"); keystore_paths.push(keystore_path); - let client = net.lock().peer(*peer_id).client().as_full().expect("full clients are created").clone(); - #[allow(deprecated)] - let select_chain = LongestChain::new( - client.backend().clone(), - ); let environ = DummyFactory(client.clone()); import_notifications.push( client.import_notification_stream() @@ -885,7 +851,7 @@ mod tests { DummyOracle, inherent_data_providers, false, - Some(keystore), + keystore, ).expect("Starts aura"); runtime.spawn(aura); diff --git a/core/consensus/babe/Cargo.toml b/core/consensus/babe/Cargo.toml index 9490887ba34bced36527613052f78164da18c1bb..30b7c1f8d6b1cec1d34a17cd48fb1550e52de676 100644 --- a/core/consensus/babe/Cargo.toml +++ b/core/consensus/babe/Cargo.toml @@ -10,9 +10,9 @@ codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive babe_primitives = { package = "substrate-consensus-babe-primitives", path = "primitives" } primitives = { package = "substrate-primitives", path = "../../primitives" } app-crypto = { package = "substrate-application-crypto", path = "../../application-crypto" } -num-bigint = "0.2" -num-rational = "0.2" -num-traits = "0.2" +num-bigint = "0.2.3" +num-rational = "0.2.2" +num-traits = "0.2.8" runtime-support = { package = "srml-support", path = "../../../srml/support" } runtime-version = { package = "sr-version", path = "../../sr-version" } runtime-io = { package = "sr-io", path = "../../sr-io" } @@ -21,19 +21,22 @@ substrate-telemetry = { path = "../../telemetry" } keystore = { package = "substrate-keystore", path = "../../keystore" } srml-babe = { path = "../../../srml/babe" } client = { package = "substrate-client", path = "../../client" } +header-metadata = { package = "substrate-header-metadata", path = "../../client/header-metadata" } consensus-common = { package = "substrate-consensus-common", path = "../common" } uncles = { package = "substrate-consensus-uncles", path = "../uncles" } slots = { package = "substrate-consensus-slots", path = "../slots" } sr-primitives = { path = "../../sr-primitives" } fork-tree = { path = "../../utils/fork-tree" } -futures-preview = { version = "=0.3.0-alpha.17", features = ["compat"] } +futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } futures01 = { package = "futures", version = "0.1" } -futures-timer = "0.2.1" +futures-timer = "0.4.0" parking_lot = "0.9.0" -log = "0.4.6" -schnorrkel = { version = "0.8.4", features = ["preaudit_deprecated"] } -rand = "0.6.5" -merlin = "1.0.3" +log = "0.4.8" +schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"] } +rand = "0.7.2" +merlin = "1.2.1" +pdqselect = "0.1.0" +derive_more = "0.15.0" [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../keyring" } @@ -41,9 +44,9 @@ substrate-executor = { path = "../../executor" } network = { package = "substrate-network", path = "../../network", features = ["test-helpers"]} service = { package = "substrate-service", path = "../../service" } test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } -tokio = "0.1.18" -env_logger = "0.6.1" -tempfile = "3.1" +tokio = "0.1.22" +env_logger = "0.7.0" +tempfile = "3.1.0" [features] test-helpers = [] diff --git a/core/consensus/babe/primitives/Cargo.toml b/core/consensus/babe/primitives/Cargo.toml index 5f7fbe4fd812944ad992fd73b26b08e5bc35f49e..79e817d08102825456f5822199caa33de4deab75 100644 --- a/core/consensus/babe/primitives/Cargo.toml +++ b/core/consensus/babe/primitives/Cargo.toml @@ -11,7 +11,7 @@ rstd = { package = "sr-std", path = "../../../sr-std", default-features = false sr-primitives = { path = "../../../sr-primitives", default-features = false } app-crypto = { package = "substrate-application-crypto", path = "../../../application-crypto", default-features = false } slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true } -schnorrkel = { version = "0.8.4", features = ["preaudit_deprecated"], optional = true } +schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"], optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } [features] diff --git a/core/consensus/babe/primitives/src/digest.rs b/core/consensus/babe/primitives/src/digest.rs index 3b6e3221bd8a87ab5aa1fe399c4ba5e8edb44e5e..95dd247810782396499596ffaa3a1d4d74c2ce65 100644 --- a/core/consensus/babe/primitives/src/digest.rs +++ b/core/consensus/babe/primitives/src/digest.rs @@ -17,12 +17,10 @@ //! Private implementation details of BABE digests. #[cfg(feature = "std")] -use super::AuthoritySignature; -#[cfg(feature = "std")] -use super::{BABE_ENGINE_ID, Epoch}; +use super::{BABE_ENGINE_ID, AuthoritySignature}; #[cfg(not(feature = "std"))] use super::{VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH}; -use super::SlotNumber; +use super::{AuthorityId, AuthorityIndex, SlotNumber, BabeAuthorityWeight}; #[cfg(feature = "std")] use sr_primitives::{DigestItem, generic::OpaqueDigestItemId}; #[cfg(feature = "std")] @@ -35,47 +33,135 @@ use schnorrkel::{ SignatureError, errors::MultiSignatureStage, vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH} }; +use rstd::vec::Vec; + -/// A BABE pre-digest +/// A BABE pre-runtime digest. This contains all data required to validate a +/// block and for the BABE runtime module. Slots can be assigned to a primary +/// (VRF based) and to a secondary (slot number based). #[cfg(feature = "std")] #[derive(Clone, Debug)] -pub struct BabePreDigest { - /// VRF output - pub vrf_output: VRFOutput, - /// VRF proof - pub vrf_proof: VRFProof, - /// Authority index - pub authority_index: super::AuthorityIndex, - /// Slot number - pub slot_number: SlotNumber, +pub enum BabePreDigest { + /// A primary VRF-based slot assignment. + Primary { + /// VRF output + vrf_output: VRFOutput, + /// VRF proof + vrf_proof: VRFProof, + /// Authority index + authority_index: super::AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + }, + /// A secondary deterministic slot assignment. + Secondary { + /// Authority index + authority_index: super::AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + }, +} + +#[cfg(feature = "std")] +impl BabePreDigest { + /// Returns the slot number of the pre digest. + pub fn authority_index(&self) -> AuthorityIndex { + match self { + BabePreDigest::Primary { authority_index, .. } => *authority_index, + BabePreDigest::Secondary { authority_index, .. } => *authority_index, + } + } + + /// Returns the slot number of the pre digest. + pub fn slot_number(&self) -> SlotNumber { + match self { + BabePreDigest::Primary { slot_number, .. } => *slot_number, + BabePreDigest::Secondary { slot_number, .. } => *slot_number, + } + } + + /// Returns the weight _added_ by this digest, not the cumulative weight + /// of the chain. + pub fn added_weight(&self) -> crate::BabeBlockWeight { + match self { + BabePreDigest::Primary { .. } => 1, + BabePreDigest::Secondary { .. } => 0, + } + } } /// The prefix used by BABE for its VRF keys. -pub const BABE_VRF_PREFIX: &'static [u8] = b"substrate-babe-vrf"; +pub const BABE_VRF_PREFIX: &[u8] = b"substrate-babe-vrf"; /// A raw version of `BabePreDigest`, usable on `no_std`. #[derive(Copy, Clone, Encode, Decode)] -pub struct RawBabePreDigest { - /// Slot number - pub slot_number: SlotNumber, - /// Authority index - pub authority_index: super::AuthorityIndex, - /// VRF output - pub vrf_output: [u8; VRF_OUTPUT_LENGTH], - /// VRF proof - pub vrf_proof: [u8; VRF_PROOF_LENGTH], +pub enum RawBabePreDigest { + /// A primary VRF-based slot assignment. + #[codec(index = "1")] + Primary { + /// Authority index + authority_index: AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + /// VRF output + vrf_output: [u8; VRF_OUTPUT_LENGTH], + /// VRF proof + vrf_proof: [u8; VRF_PROOF_LENGTH], + }, + /// A secondary deterministic slot assignment. + #[codec(index = "2")] + Secondary { + /// Authority index + /// + /// This is not strictly-speaking necessary, since the secondary slots + /// are assigned based on slot number and epoch randomness. But including + /// it makes things easier for higher-level users of the chain data to + /// be aware of the author of a secondary-slot block. + authority_index: AuthorityIndex, + /// Slot number + slot_number: SlotNumber, + }, +} + +impl RawBabePreDigest { + /// Returns the slot number of the pre digest. + pub fn slot_number(&self) -> SlotNumber { + match self { + RawBabePreDigest::Primary { slot_number, .. } => *slot_number, + RawBabePreDigest::Secondary { slot_number, .. } => *slot_number, + } + } } #[cfg(feature = "std")] impl Encode for BabePreDigest { fn encode(&self) -> Vec { - let tmp = RawBabePreDigest { - vrf_output: *self.vrf_output.as_bytes(), - vrf_proof: self.vrf_proof.to_bytes(), - authority_index: self.authority_index, - slot_number: self.slot_number, + let raw = match self { + BabePreDigest::Primary { + vrf_output, + vrf_proof, + authority_index, + slot_number, + } => { + RawBabePreDigest::Primary { + vrf_output: *vrf_output.as_bytes(), + vrf_proof: vrf_proof.to_bytes(), + authority_index: *authority_index, + slot_number: *slot_number, + } + }, + BabePreDigest::Secondary { + authority_index, + slot_number, + } => { + RawBabePreDigest::Secondary { + authority_index: *authority_index, + slot_number: *slot_number, + } + }, }; - codec::Encode::encode(&tmp) + + codec::Encode::encode(&raw) } } @@ -85,22 +171,39 @@ impl codec::EncodeLike for BabePreDigest {} #[cfg(feature = "std")] impl Decode for BabePreDigest { fn decode(i: &mut R) -> Result { - let RawBabePreDigest { vrf_output, vrf_proof, authority_index, slot_number } = Decode::decode(i)?; - - // Verify (at compile time) that the sizes in babe_primitives are correct - let _: [u8; super::VRF_OUTPUT_LENGTH] = vrf_output; - let _: [u8; super::VRF_PROOF_LENGTH] = vrf_proof; - Ok(BabePreDigest { - vrf_proof: VRFProof::from_bytes(&vrf_proof) - .map_err(convert_error)?, - vrf_output: VRFOutput::from_bytes(&vrf_output) - .map_err(convert_error)?, - authority_index, - slot_number, - }) + let pre_digest = match Decode::decode(i)? { + RawBabePreDigest::Primary { vrf_output, vrf_proof, authority_index, slot_number } => { + // Verify (at compile time) that the sizes in babe_primitives are correct + let _: [u8; super::VRF_OUTPUT_LENGTH] = vrf_output; + let _: [u8; super::VRF_PROOF_LENGTH] = vrf_proof; + + BabePreDigest::Primary { + vrf_proof: VRFProof::from_bytes(&vrf_proof).map_err(convert_error)?, + vrf_output: VRFOutput::from_bytes(&vrf_output).map_err(convert_error)?, + authority_index, + slot_number, + } + }, + RawBabePreDigest::Secondary { authority_index, slot_number } => { + BabePreDigest::Secondary { authority_index, slot_number } + }, + }; + + Ok(pre_digest) } } +/// Information about the next epoch. This is broadcast in the first block +/// of the epoch. +#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] +pub struct NextEpochDescriptor { + /// The authorities. + pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + + /// The value of randomness to use for the slot-assignment. + pub randomness: [u8; VRF_OUTPUT_LENGTH], +} + /// A digest item which is usable with BABE consensus. #[cfg(feature = "std")] pub trait CompatibleDigestItem: Sized { @@ -117,7 +220,7 @@ pub trait CompatibleDigestItem: Sized { fn as_babe_seal(&self) -> Option; /// If this item is a BABE epoch, return it. - fn as_babe_epoch(&self) -> Option; + fn as_next_epoch_descriptor(&self) -> Option; } #[cfg(feature = "std")] @@ -140,8 +243,12 @@ impl CompatibleDigestItem for DigestItem where self.try_to(OpaqueDigestItemId::Seal(&BABE_ENGINE_ID)) } - fn as_babe_epoch(&self) -> Option { + fn as_next_epoch_descriptor(&self) -> Option { self.try_to(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)) + .and_then(|x: super::ConsensusLog| match x { + super::ConsensusLog::NextEpochData(n) => Some(n), + _ => None, + }) } } diff --git a/core/consensus/babe/primitives/src/lib.rs b/core/consensus/babe/primitives/src/lib.rs index f4da908080c8b524112827ba935fde7d1c8f1ac5..c464e797d8d5868439504e725aac90b379433e69 100644 --- a/core/consensus/babe/primitives/src/lib.rs +++ b/core/consensus/babe/primitives/src/lib.rs @@ -23,12 +23,12 @@ mod digest; use codec::{Encode, Decode}; use rstd::vec::Vec; -use sr_primitives::ConsensusEngineId; +use sr_primitives::{ConsensusEngineId, RuntimeDebug}; use substrate_client::decl_runtime_apis; #[cfg(feature = "std")] pub use digest::{BabePreDigest, CompatibleDigestItem}; -pub use digest::{BABE_VRF_PREFIX, RawBabePreDigest}; +pub use digest::{BABE_VRF_PREFIX, RawBabePreDigest, NextEpochDescriptor}; mod app { use app_crypto::{app_crypto, key_types::BABE, sr25519}; @@ -59,6 +59,11 @@ pub const VRF_PROOF_LENGTH: usize = 64; /// The length of the public key pub const PUBLIC_KEY_LENGTH: usize = 32; +/// How many blocks to wait before running the median algorithm for relative time +/// This will not vary from chain to chain as it is not dependent on slot duration +/// or epoch length. +pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by w3f-research. + /// The index of an authority. pub type AuthorityIndex = u32; @@ -68,40 +73,60 @@ pub type SlotNumber = u64; /// The weight of an authority. // NOTE: we use a unique name for the weight to avoid conflicts with other // `Weight` types, since the metadata isn't able to disambiguate. -pub type BabeWeight = u64; +pub type BabeAuthorityWeight = u64; + +/// The weight of a BABE block. +pub type BabeBlockWeight = u32; /// BABE epoch information -#[derive(Decode, Encode, Default, PartialEq, Eq, Clone)] -#[cfg_attr(any(feature = "std", test), derive(Debug))] +#[derive(Decode, Encode, Default, PartialEq, Eq, Clone, RuntimeDebug)] pub struct Epoch { /// The epoch index pub epoch_index: u64, /// The starting slot of the epoch, - pub start_slot: u64, + pub start_slot: SlotNumber, /// The duration of this epoch pub duration: SlotNumber, /// The authorities and their weights - pub authorities: Vec<(AuthorityId, BabeWeight)>, + pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, /// Randomness for this epoch pub randomness: [u8; VRF_OUTPUT_LENGTH], } +impl Epoch { + /// "increment" the epoch, with given descriptor for the next. + pub fn increment(&self, descriptor: NextEpochDescriptor) -> Epoch { + Epoch { + epoch_index: self.epoch_index + 1, + start_slot: self.start_slot + self.duration, + duration: self.duration, + authorities: descriptor.authorities, + randomness: descriptor.randomness, + } + } + + /// Produce the "end slot" of the epoch. This is NOT inclusive to the epoch, + // i.e. the slots covered by the epoch are `self.start_slot .. self.end_slot()`. + pub fn end_slot(&self) -> SlotNumber { + self.start_slot + self.duration + } +} + /// An consensus log item for BABE. #[derive(Decode, Encode, Clone, PartialEq, Eq)] pub enum ConsensusLog { - /// The epoch has changed. This provides information about the - /// epoch _after_ next: what slot number it will start at, who are the authorities (and their weights) - /// and the next epoch randomness. The information for the _next_ epoch should already - /// be available. + /// The epoch has changed. This provides information about the _next_ + /// epoch - information about the _current_ epoch (i.e. the one we've just + /// entered) should already be available earlier in the chain. #[codec(index = "1")] - NextEpochData(Epoch), + NextEpochData(NextEpochDescriptor), /// Disable the authority with given index. #[codec(index = "2")] OnDisabled(AuthorityIndex), } /// Configuration data used by the BABE consensus engine. -#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] pub struct BabeConfiguration { /// The slot duration in milliseconds for BABE. Currently, only /// the value provided by this type at genesis will be used. @@ -109,35 +134,35 @@ pub struct BabeConfiguration { /// Dynamic slot duration may be supported in the future. pub slot_duration: u64, + /// The duration of epochs in slots. + pub epoch_length: SlotNumber, + /// A constant value that is used in the threshold calculation formula. - /// Expressed as a fraction where the first member of the tuple is the - /// numerator and the second is the denominator. The fraction should + /// Expressed as a rational where the first member of the tuple is the + /// numerator and the second is the denominator. The rational should /// represent a value between 0 and 1. /// In the threshold formula calculation, `1 - c` represents the probability /// of a slot being empty. pub c: (u64, u64), - /// The minimum number of blocks that must be received before running the - /// median algorithm to compute the offset between the on-chain time and the - /// local time. Currently, only the value provided by this type at genesis - /// will be used, but this is subject to change. - /// - /// Blocks less than `self.median_required_blocks` must be generated by an - /// *initial validator* ― that is, a node that was a validator at genesis. - pub median_required_blocks: u64, + /// The authorities for the genesis epoch. + pub genesis_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + + /// The randomness for the genesis epoch. + pub randomness: [u8; VRF_OUTPUT_LENGTH], + + /// Whether this chain should run with secondary slots, which are assigned + /// in round-robin manner. + pub secondary_slots: bool, } #[cfg(feature = "std")] impl slots::SlotData for BabeConfiguration { - /// Return the slot duration in milliseconds for BABE. Currently, only - /// the value provided by this type at genesis will be used. - /// - /// Dynamic slot duration may be supported in the future. fn slot_duration(&self) -> u64 { self.slot_duration } - const SLOT_KEY: &'static [u8] = b"babe_bootstrap_data"; + const SLOT_KEY: &'static [u8] = b"babe_configuration"; } decl_runtime_apis! { @@ -147,9 +172,6 @@ decl_runtime_apis! { /// only the value provided by this type at genesis will be used. /// /// Dynamic configuration may be supported in the future. - fn startup_data() -> BabeConfiguration; - - /// Get the current epoch data for Babe. - fn epoch() -> Epoch; + fn configuration() -> BabeConfiguration; } } diff --git a/core/consensus/babe/src/authorship.rs b/core/consensus/babe/src/authorship.rs new file mode 100644 index 0000000000000000000000000000000000000000..93405ff7776e62c739a07212594ffac540fa1eea --- /dev/null +++ b/core/consensus/babe/src/authorship.rs @@ -0,0 +1,214 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! BABE authority selection and slot claiming. + +use merlin::Transcript; +use babe_primitives::{AuthorityId, BabeAuthorityWeight, BABE_ENGINE_ID, BABE_VRF_PREFIX}; +use babe_primitives::{Epoch, SlotNumber, AuthorityPair, BabePreDigest, BabeConfiguration}; +use primitives::{U256, blake2_256}; +use codec::Encode; +use schnorrkel::vrf::VRFInOut; +use primitives::Pair; +use keystore::KeyStorePtr; + +/// Calculates the primary selection threshold for a given authority, taking +/// into account `c` (`1 - c` represents the probability of a slot being empty). +pub(super) fn calculate_primary_threshold( + c: (u64, u64), + authorities: &[(AuthorityId, BabeAuthorityWeight)], + authority_index: usize, +) -> u128 { + use num_bigint::BigUint; + use num_rational::BigRational; + use num_traits::{cast::ToPrimitive, identities::One}; + + let c = c.0 as f64 / c.1 as f64; + + let theta = + authorities[authority_index].1 as f64 / + authorities.iter().map(|(_, weight)| weight).sum::() as f64; + + let calc = || { + let p = BigRational::from_float(1f64 - (1f64 - c).powf(theta))?; + let numer = p.numer().to_biguint()?; + let denom = p.denom().to_biguint()?; + ((BigUint::one() << 128) * numer / denom).to_u128() + }; + + calc().unwrap_or(u128::max_value()) +} + +/// Returns true if the given VRF output is lower than the given threshold, +/// false otherwise. +pub(super) fn check_primary_threshold(inout: &VRFInOut, threshold: u128) -> bool { + u128::from_le_bytes(inout.make_bytes::<[u8; 16]>(BABE_VRF_PREFIX)) < threshold +} + +/// Get the expected secondary author for the given slot and with given +/// authorities. This should always assign the slot to some authority unless the +/// authorities list is empty. +pub(super) fn secondary_slot_author( + slot_number: u64, + authorities: &[(AuthorityId, BabeAuthorityWeight)], + randomness: [u8; 32], +) -> Option<&AuthorityId> { + if authorities.is_empty() { + return None; + } + + let rand = U256::from((randomness, slot_number).using_encoded(blake2_256)); + + let authorities_len = U256::from(authorities.len()); + let idx = rand % authorities_len; + + let expected_author = authorities.get(idx.as_u32() as usize) + .expect("authorities not empty; index constrained to list length; \ + this is a valid index; qed"); + + Some(&expected_author.0) +} + +#[allow(deprecated)] +pub(super) fn make_transcript( + randomness: &[u8], + slot_number: u64, + epoch: u64, +) -> Transcript { + let mut transcript = Transcript::new(&BABE_ENGINE_ID); + transcript.commit_bytes(b"slot number", &slot_number.to_le_bytes()); + transcript.commit_bytes(b"current epoch", &epoch.to_le_bytes()); + transcript.commit_bytes(b"chain randomness", randomness); + transcript +} + + +/// Claim a secondary slot if it is our turn to propose, returning the +/// pre-digest to use when authoring the block, or `None` if it is not our turn +/// to propose. +fn claim_secondary_slot( + slot_number: SlotNumber, + authorities: &[(AuthorityId, BabeAuthorityWeight)], + keystore: &KeyStorePtr, + randomness: [u8; 32], +) -> Option<(BabePreDigest, AuthorityPair)> { + if authorities.is_empty() { + return None; + } + + let expected_author = super::authorship::secondary_slot_author( + slot_number, + authorities, + randomness, + )?; + + let keystore = keystore.read(); + + for (pair, authority_index) in authorities.iter() + .enumerate() + .flat_map(|(i, a)| { + keystore.key_pair::(&a.0).ok().map(|kp| (kp, i)) + }) + { + if pair.public() == *expected_author { + let pre_digest = BabePreDigest::Secondary { + slot_number, + authority_index: authority_index as u32, + }; + + return Some((pre_digest, pair)); + } + } + + None +} + +/// Tries to claim the given slot number. This method starts by trying to claim +/// a primary VRF based slot. If we are not able to claim it, then if we have +/// secondary slots enabled for the given epoch, we will fallback to trying to +/// claim a secondary slot. +pub(super) fn claim_slot( + slot_number: SlotNumber, + epoch: &Epoch, + config: &BabeConfiguration, + keystore: &KeyStorePtr, +) -> Option<(BabePreDigest, AuthorityPair)> { + claim_primary_slot(slot_number, epoch, config.c, keystore) + .or_else(|| { + if config.secondary_slots { + claim_secondary_slot( + slot_number, + &epoch.authorities, + keystore, + epoch.randomness, + ) + } else { + None + } + }) +} + +fn get_keypair(q: &AuthorityPair) -> &schnorrkel::Keypair { + use primitives::crypto::IsWrappedBy; + primitives::sr25519::Pair::from_ref(q).as_ref() +} + +/// Claim a primary slot if it is our turn. Returns `None` if it is not our turn. +/// This hashes the slot number, epoch, genesis hash, and chain randomness into +/// the VRF. If the VRF produces a value less than `threshold`, it is our turn, +/// so it returns `Some(_)`. Otherwise, it returns `None`. +fn claim_primary_slot( + slot_number: SlotNumber, + epoch: &Epoch, + c: (u64, u64), + keystore: &KeyStorePtr, +) -> Option<(BabePreDigest, AuthorityPair)> { + let Epoch { authorities, randomness, epoch_index, .. } = epoch; + let keystore = keystore.read(); + + for (pair, authority_index) in authorities.iter() + .enumerate() + .flat_map(|(i, a)| { + keystore.key_pair::(&a.0).ok().map(|kp| (kp, i)) + }) + { + let transcript = super::authorship::make_transcript(randomness, slot_number, *epoch_index); + + // Compute the threshold we will use. + // + // We already checked that authorities contains `key.public()`, so it can't + // be empty. Therefore, this division in `calculate_threshold` is safe. + let threshold = super::authorship::calculate_primary_threshold(c, authorities, authority_index); + + let pre_digest = get_keypair(&pair) + .vrf_sign_after_check(transcript, |inout| super::authorship::check_primary_threshold(inout, threshold)) + .map(|s| { + BabePreDigest::Primary { + slot_number, + vrf_output: s.0.to_output(), + vrf_proof: s.1, + authority_index: authority_index as u32, + } + }); + + // early exit on first successful claim + if let Some(pre_digest) = pre_digest { + return Some((pre_digest, pair)); + } + } + + None +} diff --git a/core/consensus/babe/src/aux_schema.rs b/core/consensus/babe/src/aux_schema.rs index ac90b4ce52dc4357ab64f62e044ecde5004321c3..6290d5cf316434bede137c5badfb0d9822ea1e0b 100644 --- a/core/consensus/babe/src/aux_schema.rs +++ b/core/consensus/babe/src/aux_schema.rs @@ -22,18 +22,23 @@ use codec::{Decode, Encode}; use client::backend::AuxStore; use client::error::{Result as ClientResult, Error as ClientError}; use sr_primitives::traits::Block as BlockT; +use babe_primitives::BabeBlockWeight; -use super::{EpochChanges, SharedEpochChanges}; +use super::{epoch_changes::EpochChangesFor, SharedEpochChanges}; const BABE_EPOCH_CHANGES: &[u8] = b"babe_epoch_changes"; +fn block_weight_key(block_hash: H) -> Vec { + (b"block_weight", block_hash).encode() +} + fn load_decode(backend: &B, key: &[u8]) -> ClientResult> where B: AuxStore, T: Decode, { let corrupt = |e: codec::Error| { - ClientError::Backend(format!("BABE DB is corrupted. Decode error: {}", e.what())).into() + ClientError::Backend(format!("BABE DB is corrupted. Decode error: {}", e.what())) }; match backend.get_aux(key)? { None => Ok(None), @@ -45,7 +50,7 @@ fn load_decode(backend: &B, key: &[u8]) -> ClientResult> pub(crate) fn load_epoch_changes( backend: &B, ) -> ClientResult> { - let epoch_changes = load_decode::<_, EpochChanges>(backend, BABE_EPOCH_CHANGES)? + let epoch_changes = load_decode::<_, EpochChangesFor>(backend, BABE_EPOCH_CHANGES)? .map(Into::into) .unwrap_or_else(|| { info!(target: "babe", @@ -59,7 +64,7 @@ pub(crate) fn load_epoch_changes( /// Update the epoch changes on disk after a change. pub(crate) fn write_epoch_changes( - epoch_changes: &EpochChanges, + epoch_changes: &EpochChangesFor, write_aux: F, ) -> R where F: FnOnce(&[(&'static [u8], &[u8])]) -> R, @@ -69,3 +74,28 @@ pub(crate) fn write_epoch_changes( &[(BABE_EPOCH_CHANGES, encoded_epoch_changes.as_slice())], ) } + +/// Write the cumulative chain-weight of a block ot aux storage. +pub(crate) fn write_block_weight( + block_hash: H, + block_weight: &BabeBlockWeight, + write_aux: F, +) -> R where + F: FnOnce(&[(Vec, &[u8])]) -> R, +{ + + let key = block_weight_key(block_hash); + block_weight.using_encoded(|s| + write_aux( + &[(key, s)], + ) + ) +} + +/// Load the cumulative chain-weight associated with a block. +pub(crate) fn load_block_weight( + backend: &B, + block_hash: H, +) -> ClientResult> { + load_decode(backend, block_weight_key(block_hash).as_slice()) +} diff --git a/core/consensus/babe/src/epoch_changes.rs b/core/consensus/babe/src/epoch_changes.rs new file mode 100644 index 0000000000000000000000000000000000000000..09a14d286426d966c145f160a52816eca05427eb --- /dev/null +++ b/core/consensus/babe/src/epoch_changes.rs @@ -0,0 +1,656 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Handling epoch changes in BABE. +//! +//! This exposes the `SharedEpochChanges`, which is a wrapper around a +//! persistent DAG superimposed over the forks of the blockchain. + +use std::sync::Arc; +use babe_primitives::{Epoch, SlotNumber, NextEpochDescriptor}; +use fork_tree::ForkTree; +use parking_lot::{Mutex, MutexGuard}; +use sr_primitives::traits::{Block as BlockT, NumberFor, One, Zero}; +use codec::{Encode, Decode}; +use client::error::Error as ClientError; +use client::utils as client_utils; +use client::blockchain::HeaderBackend; +use header_metadata::HeaderMetadata; +use primitives::H256; +use std::ops::Add; + +/// A builder for `is_descendent_of` functions. +pub trait IsDescendentOfBuilder { + /// The error returned by the function. + type Error: std::error::Error; + /// A function that can tell you if the second parameter is a descendent of + /// the first. + type IsDescendentOf: Fn(&Hash, &Hash) -> Result; + + /// Build an `is_descendent_of` function. + /// + /// The `current` parameter can be `Some` with the details a fresh block whose + /// details aren't yet stored, but its parent is. + /// + /// The format of `current` when `Some` is `(current, current_parent)`. + fn build_is_descendent_of(&self, current: Option<(Hash, Hash)>) + -> Self::IsDescendentOf; +} + +/// Produce a descendent query object given the client. +pub(crate) fn descendent_query(client: &H) -> HeaderBackendDescendentBuilder<&H, Block> { + HeaderBackendDescendentBuilder(client, std::marker::PhantomData) +} + +/// Wrapper to get around unconstrained type errors when implementing +/// `IsDescendentOfBuilder` for header backends. +pub(crate) struct HeaderBackendDescendentBuilder(H, std::marker::PhantomData); + +// TODO: relying on Hash = H256 is awful. +// https://github.com/paritytech/substrate/issues/3624 +impl<'a, H, Block> IsDescendentOfBuilder + for HeaderBackendDescendentBuilder<&'a H, Block> where + H: HeaderBackend + HeaderMetadata, + Block: BlockT, +{ + type Error = ClientError; + type IsDescendentOf = Box Result + 'a>; + + fn build_is_descendent_of(&self, current: Option<(H256, H256)>) + -> Self::IsDescendentOf + { + Box::new(client_utils::is_descendent_of(self.0, current)) + } +} + +/// An unimported genesis epoch. +pub struct UnimportedGenesis(Epoch); + +/// The viable epoch under which a block can be verified. +/// +/// If this is the first non-genesis block in the chain, then it will +/// hold an `UnimportedGenesis` epoch. +pub enum ViableEpoch { + Genesis(UnimportedGenesis), + Regular(Epoch), +} + +impl From for ViableEpoch { + fn from(epoch: Epoch) -> ViableEpoch { + ViableEpoch::Regular(epoch) + } +} + +impl AsRef for ViableEpoch { + fn as_ref(&self) -> &Epoch { + match *self { + ViableEpoch::Genesis(UnimportedGenesis(ref e)) => e, + ViableEpoch::Regular(ref e) => e, + } + } +} + +impl ViableEpoch { + /// Extract the underlying epoch, disregarding the fact that a genesis + /// epoch may be unimported. + pub fn into_inner(self) -> Epoch { + match self { + ViableEpoch::Genesis(UnimportedGenesis(e)) => e, + ViableEpoch::Regular(e) => e, + } + } + + /// Increment the epoch, yielding an `IncrementedEpoch` to be imported + /// into the fork-tree. + pub fn increment(&self, next_descriptor: NextEpochDescriptor) -> IncrementedEpoch { + let next = self.as_ref().increment(next_descriptor); + let to_persist = match *self { + ViableEpoch::Genesis(UnimportedGenesis(ref epoch_0)) => + PersistedEpoch::Genesis(epoch_0.clone(), next), + ViableEpoch::Regular(_) => PersistedEpoch::Regular(next), + }; + + IncrementedEpoch(to_persist) + } +} + +/// The datatype encoded on disk. +// This really shouldn't be public, but the encode/decode derives force it to be. +#[derive(Clone, Encode, Decode)] +pub enum PersistedEpoch { + // epoch_0, epoch_1, + Genesis(Epoch, Epoch), + // epoch_n + Regular(Epoch), +} + +/// A fresh, incremented epoch to import into the underlying fork-tree. +/// +/// Create this with `ViableEpoch::increment`. +#[must_use = "Freshly-incremented epoch must be imported with `EpochChanges::import`"] +pub struct IncrementedEpoch(PersistedEpoch); + +impl AsRef for IncrementedEpoch { + fn as_ref(&self) -> &Epoch { + match self.0 { + PersistedEpoch::Genesis(_, ref epoch_1) => epoch_1, + PersistedEpoch::Regular(ref epoch_n) => epoch_n, + } + } +} + +/// Tree of all epoch changes across all *seen* forks. Data stored in tree is +/// the hash and block number of the block signaling the epoch change, and the +/// epoch that was signalled at that block. +/// +/// BABE special-cases the first epoch, epoch_0, by saying that it starts at +/// slot number of the first block in the chain. When bootstrapping a chain, +/// there can be multiple competing block #1s, so we have to ensure that the overlayed +/// DAG doesn't get confused. +/// +/// The first block of every epoch should be producing a descriptor for the next +/// epoch - this is checked in higher-level code. So the first block of epoch_0 contains +/// a descriptor for epoch_1. We special-case these and bundle them together in the +/// same DAG entry, pinned to a specific block #1. +/// +/// Further epochs (epoch_2, ..., epoch_n) each get their own entry. +#[derive(Clone, Encode, Decode)] +pub struct EpochChanges { + inner: ForkTree, +} + +// create a fake header hash which hasn't been included in the chain. +fn fake_head_hash + AsMut<[u8]> + Clone>(parent_hash: &H) -> H { + let mut h = parent_hash.clone(); + // dirty trick: flip the first bit of the parent hash to create a hash + // which has not been in the chain before (assuming a strong hash function). + h.as_mut()[0] ^= 0b10000000; + h +} + +impl EpochChanges where + Hash: PartialEq + AsRef<[u8]> + AsMut<[u8]> + Copy, + Number: Ord + One + Zero + Add + Copy, +{ + /// Create a new epoch-change tracker. + fn new() -> Self { + EpochChanges { inner: ForkTree::new() } + } + + /// Prune out finalized epochs, except for the ancestor of the finalized + /// block. The given slot should be the slot number at which the finalized + /// block was authored. + pub fn prune_finalized>( + &mut self, + descendent_of_builder: D, + hash: &Hash, + number: Number, + slot: SlotNumber, + ) -> Result<(), fork_tree::Error> { + let is_descendent_of = descendent_of_builder + .build_is_descendent_of(None); + + let predicate = |epoch: &PersistedEpoch| match *epoch { + PersistedEpoch::Genesis(_, ref epoch_1) => + slot >= epoch_1.end_slot(), + PersistedEpoch::Regular(ref epoch_n) => + slot >= epoch_n.end_slot(), + }; + + // prune any epochs which could not be _live_ as of the children of the + // finalized block, i.e. re-root the fork tree to the oldest ancestor of + // (hash, number) where epoch.end_slot() >= finalized_slot + self.inner.prune( + hash, + &number, + &is_descendent_of, + &predicate, + )?; + + Ok(()) + } + + /// Finds the epoch for a child of the given block, assuming the given slot number. + /// + /// If the returned epoch is an `UnimportedGenesis` epoch, it should be imported into the + /// tree. + pub fn epoch_for_child_of, G>( + &self, + descendent_of_builder: D, + parent_hash: &Hash, + parent_number: Number, + slot_number: SlotNumber, + make_genesis: G, + ) -> Result, fork_tree::Error> + where G: FnOnce(SlotNumber) -> Epoch + { + // find_node_where will give you the node in the fork-tree which is an ancestor + // of the `parent_hash` by default. if the last epoch was signalled at the parent_hash, + // then it won't be returned. we need to create a new fake chain head hash which + // "descends" from our parent-hash. + let fake_head_hash = fake_head_hash(parent_hash); + + let is_descendent_of = descendent_of_builder + .build_is_descendent_of(Some((fake_head_hash, *parent_hash))); + + if parent_number == Zero::zero() { + // need to insert the genesis epoch. + let genesis_epoch = make_genesis(slot_number); + return Ok(Some(ViableEpoch::Genesis(UnimportedGenesis(genesis_epoch)))); + } + + // We want to find the deepest node in the tree which is an ancestor + // of our block and where the start slot of the epoch was before the + // slot of our block. The genesis special-case doesn't need to look + // at epoch_1 -- all we're doing here is figuring out which node + // we need. + let predicate = |epoch: &PersistedEpoch| match *epoch { + PersistedEpoch::Genesis(ref epoch_0, _) => + epoch_0.start_slot <= slot_number, + PersistedEpoch::Regular(ref epoch_n) => + epoch_n.start_slot <= slot_number, + }; + + self.inner.find_node_where( + &fake_head_hash, + &(parent_number + One::one()), + &is_descendent_of, + &predicate, + ) + .map(|n| n.map(|node| ViableEpoch::Regular(match node.data { + // Ok, we found our node. + // and here we figure out which of the internal epochs + // of a genesis node to use based on their start slot. + PersistedEpoch::Genesis(ref epoch_0, ref epoch_1) => + if epoch_1.start_slot <= slot_number { + epoch_1.clone() + } else { + epoch_0.clone() + }, + PersistedEpoch::Regular(ref epoch_n) => epoch_n.clone(), + }))) + } + + /// Import a new epoch-change, signalled at the given block. + /// + /// This assumes that the given block is prospective (i.e. has not been + /// imported yet), but its parent has. This is why the parent hash needs + /// to be provided. + pub fn import>( + &mut self, + descendent_of_builder: D, + hash: Hash, + number: Number, + parent_hash: Hash, + epoch: IncrementedEpoch, + ) -> Result<(), fork_tree::Error> { + let is_descendent_of = descendent_of_builder + .build_is_descendent_of(Some((hash, parent_hash))); + + let res = self.inner.import( + hash, + number, + epoch.0, + &is_descendent_of, + ); + + match res { + Ok(_) | Err(fork_tree::Error::Duplicate) => Ok(()), + Err(e) => Err(e), + } + } + + /// Return the inner fork tree, useful for testing purposes. + #[cfg(test)] + pub fn tree(&self) -> &ForkTree { + &self.inner + } +} + +/// Type alias to produce the epoch-changes tree from a block type. +pub type EpochChangesFor = EpochChanges<::Hash, NumberFor>; + +/// A shared epoch changes tree. +#[derive(Clone)] +pub struct SharedEpochChanges { + inner: Arc>>, +} + +impl SharedEpochChanges { + /// Create a new instance of the `SharedEpochChanges`. + pub fn new() -> Self { + SharedEpochChanges { + inner: Arc::new(Mutex::new(EpochChanges::<_, _>::new())) + } + } + + /// Lock the shared epoch changes, + pub fn lock(&self) -> MutexGuard> { + self.inner.lock() + } +} + +impl From> for SharedEpochChanges { + fn from(epoch_changes: EpochChangesFor) -> Self { + SharedEpochChanges { + inner: Arc::new(Mutex::new(epoch_changes)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug, PartialEq)] + pub struct TestError; + + impl std::fmt::Display for TestError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "TestError") + } + } + + impl std::error::Error for TestError {} + + impl<'a, F: 'a , H: 'a + PartialEq + std::fmt::Debug> IsDescendentOfBuilder for &'a F + where F: Fn(&H, &H) -> Result + { + type Error = TestError; + type IsDescendentOf = Box Result + 'a>; + + fn build_is_descendent_of(&self, current: Option<(H, H)>) + -> Self::IsDescendentOf + { + let f = *self; + Box::new(move |base, head| { + let mut head = head; + + if let Some((ref c_head, ref c_parent)) = current { + if head == c_head { + if base == c_parent { + return Ok(true); + } else { + head = c_parent; + } + } + } + + f(base, head) + }) + } + } + + type Hash = [u8; 1]; + + #[test] + fn genesis_epoch_is_created_but_not_imported() { + // + // A - B + // \ + // — C + // + let is_descendent_of = |base: &Hash, block: &Hash| -> Result { + match (base, *block) { + (b"A", b) => Ok(b == *b"B" || b == *b"C" || b == *b"D"), + (b"B", b) | (b"C", b) => Ok(b == *b"D"), + (b"0", _) => Ok(true), + _ => Ok(false), + } + }; + + let make_genesis = |slot| Epoch { + epoch_index: 0, + start_slot: slot, + duration: 100, + authorities: Vec::new(), + randomness: [0; 32], + }; + + let epoch_changes = EpochChanges::new(); + let genesis_epoch = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"0", + 0, + 10101, + &make_genesis, + ).unwrap().unwrap(); + + match genesis_epoch { + ViableEpoch::Genesis(_) => {}, + _ => panic!("should be unimported genesis"), + }; + assert_eq!(genesis_epoch.as_ref(), &make_genesis(10101)); + + let genesis_epoch_2 = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"0", + 0, + 10102, + &make_genesis, + ).unwrap().unwrap(); + + match genesis_epoch_2 { + ViableEpoch::Genesis(_) => {}, + _ => panic!("should be unimported genesis"), + }; + assert_eq!(genesis_epoch_2.as_ref(), &make_genesis(10102)); + } + + #[test] + fn epoch_changes_between_blocks() { + // + // A - B + // \ + // — C + // + let is_descendent_of = |base: &Hash, block: &Hash| -> Result { + match (base, *block) { + (b"A", b) => Ok(b == *b"B" || b == *b"C" || b == *b"D"), + (b"B", b) | (b"C", b) => Ok(b == *b"D"), + (b"0", _) => Ok(true), + _ => Ok(false), + } + }; + + let make_genesis = |slot| Epoch { + epoch_index: 0, + start_slot: slot, + duration: 100, + authorities: Vec::new(), + randomness: [0; 32], + }; + + let mut epoch_changes = EpochChanges::new(); + let genesis_epoch = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"0", + 0, + 100, + &make_genesis, + ).unwrap().unwrap(); + + assert_eq!(genesis_epoch.as_ref(), &make_genesis(100)); + + let import_epoch_1 = genesis_epoch.increment(NextEpochDescriptor { + authorities: Vec::new(), + randomness: [1; 32], + }); + let epoch_1 = import_epoch_1.as_ref().clone(); + + epoch_changes.import( + &is_descendent_of, + *b"A", + 1, + *b"0", + import_epoch_1, + ).unwrap(); + let genesis_epoch = genesis_epoch.into_inner(); + + assert!(is_descendent_of(b"0", b"A").unwrap()); + + let end_slot = genesis_epoch.end_slot(); + assert_eq!(end_slot, epoch_1.start_slot); + + { + // x is still within the genesis epoch. + let x = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"A", + 1, + end_slot - 1, + &make_genesis, + ).unwrap().unwrap().into_inner(); + + assert_eq!(x, genesis_epoch); + } + + { + // x is now at the next epoch, because the block is now at the + // start slot of epoch 1. + let x = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"A", + 1, + end_slot, + &make_genesis, + ).unwrap().unwrap().into_inner(); + + assert_eq!(x, epoch_1); + } + + { + // x is now at the next epoch, because the block is now after + // start slot of epoch 1. + let x = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"A", + 1, + epoch_1.end_slot() - 1, + &make_genesis, + ).unwrap().unwrap().into_inner(); + + assert_eq!(x, epoch_1); + } + } + + #[test] + fn two_block_ones_dont_conflict() { + // X - Y + // / + // 0 - A - B + // + let is_descendent_of = |base: &Hash, block: &Hash| -> Result { + match (base, *block) { + (b"A", b) => Ok(b == *b"B"), + (b"X", b) => Ok(b == *b"Y"), + (b"0", _) => Ok(true), + _ => Ok(false), + } + }; + + let duration = 100; + + let make_genesis = |slot| Epoch { + epoch_index: 0, + start_slot: slot, + duration, + authorities: Vec::new(), + randomness: [0; 32], + }; + + let mut epoch_changes = EpochChanges::new(); + let next_descriptor = NextEpochDescriptor { + authorities: Vec::new(), + randomness: [0; 32], + }; + + // insert genesis epoch for A + { + let genesis_epoch_a = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"0", + 0, + 100, + &make_genesis, + ).unwrap().unwrap(); + + epoch_changes.import( + &is_descendent_of, + *b"A", + 1, + *b"0", + genesis_epoch_a.increment(next_descriptor.clone()), + ).unwrap(); + + } + + // insert genesis epoch for X + { + let genesis_epoch_x = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"0", + 0, + 1000, + &make_genesis, + ).unwrap().unwrap(); + + epoch_changes.import( + &is_descendent_of, + *b"X", + 1, + *b"0", + genesis_epoch_x.increment(next_descriptor.clone()), + ).unwrap(); + } + + // now check that the genesis epochs for our respective block 1s + // respect the chain structure. + { + let epoch_for_a_child = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"A", + 1, + 101, + &make_genesis, + ).unwrap().unwrap(); + + assert_eq!(epoch_for_a_child.into_inner(), make_genesis(100)); + + let epoch_for_x_child = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"X", + 1, + 1001, + &make_genesis, + ).unwrap().unwrap(); + + assert_eq!(epoch_for_x_child.into_inner(), make_genesis(1000)); + + let epoch_for_x_child_before_genesis = epoch_changes.epoch_for_child_of( + &is_descendent_of, + b"X", + 1, + 101, + &make_genesis, + ).unwrap(); + + // even though there is a genesis epoch at that slot, it's not in + // this chain. + assert!(epoch_for_x_child_before_genesis.is_none()); + } + } +} diff --git a/core/consensus/babe/src/lib.rs b/core/consensus/babe/src/lib.rs index ae142a27bf170e87ea14bf1ad44c382a64c75d60..766b9a3125340bf77ee2dae631cbaed42dc7142f 100644 --- a/core/consensus/babe/src/lib.rs +++ b/core/consensus/babe/src/lib.rs @@ -14,46 +14,74 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! # BABE consensus +//! # BABE (Blind Assignment for Blockchain Extension) //! -//! BABE (Blind Assignment for Blockchain Extension) consensus in Substrate. +//! BABE is a slot-based block production mechanism which uses a VRF PRNG to +//! randomly perform the slot allocation. On every slot, all the authorities +//! generate a new random number with the VRF function and if it is lower than a +//! given threshold (which is proportional to their weight/stake) they have a +//! right to produce a block. The proof of the VRF function execution will be +//! used by other peer to validate the legitimacy of the slot claim. +//! +//! The engine is also responsible for collecting entropy on-chain which will be +//! used to seed the given VRF PRNG. An epoch is a contiguous number of slots +//! under which we will be using the same authority set. During an epoch all VRF +//! outputs produced as a result of block production will be collected on an +//! on-chain randomness pool. Epoch changes are announced one epoch in advance, +//! i.e. when ending epoch N, we announce the parameters (randomness, +//! authorities, etc.) for epoch N+2. +//! +//! Since the slot assignment is randomized, it is possible that a slot is +//! assigned to multiple validators in which case we will have a temporary fork, +//! or that a slot is assigned to no validator in which case no block is +//! produced. Which means that block times are not deterministic. +//! +//! The protocol has a parameter `c` [0, 1] for which `1 - c` is the probability +//! of a slot being empty. The choice of this parameter affects the security of +//! the protocol relating to maximum tolerable network delays. +//! +//! In addition to the VRF-based slot assignment described above, which we will +//! call primary slots, the engine also supports a deterministic secondary slot +//! assignment. Primary slots take precedence over secondary slots, when +//! authoring the node starts by trying to claim a primary slot and falls back +//! to a secondary slot claim attempt. The secondary slot assignment is done +//! by picking the authority at index: +//! +//! `blake2_256(epoch_randomness ++ slot_number) % authorities_len`. +//! +//! The fork choice rule is weight-based, where weight equals the number of +//! primary blocks in the chain. We will pick the heaviest chain (more primary +//! blocks) and will go with the longest one in case of a tie. +//! +//! An in-depth description and analysis of the protocol can be found here: +//! -#![forbid(unsafe_code, missing_docs)] +#![forbid(unsafe_code)] +#![warn(missing_docs)] pub use babe_primitives::*; pub use consensus_common::SyncOracle; -use std::{collections::HashMap, sync::Arc, u64, fmt::{Debug, Display}, pin::Pin, time::{Instant, Duration}}; +use std::{collections::HashMap, sync::Arc, u64, pin::Pin, time::{Instant, Duration}}; use babe_primitives; use consensus_common::ImportResult; use consensus_common::import_queue::{ BoxJustificationImport, BoxFinalityProofImport, }; -use sr_primitives::{generic, generic::{BlockId, OpaqueDigestItemId}, Justification}; +use sr_primitives::{generic::{BlockId, OpaqueDigestItemId}, Justification, RuntimeString}; use sr_primitives::traits::{ - Block as BlockT, Header, DigestItemFor, NumberFor, ProvideRuntimeApi, - SimpleBitOps, Zero, + Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, + Zero, }; use keystore::KeyStorePtr; -use runtime_support::serde::{Serialize, Deserialize}; -use codec::{Decode, Encode}; -use parking_lot::{Mutex, MutexGuard}; -use primitives::{Blake2Hasher, H256, Pair, Public}; -use merlin::Transcript; +use parking_lot::Mutex; +use primitives::{Blake2Hasher, H256, Pair}; use inherents::{InherentDataProviders, InherentData}; use substrate_telemetry::{ telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, - CONSENSUS_WARN, - CONSENSUS_INFO, -}; -use schnorrkel::{ - keys::Keypair, - vrf::{ - VRFProof, VRFProofBatchable, VRFInOut, - }, }; use consensus_common::{ - self, BlockImport, Environment, Proposer, + self, BlockImport, Environment, Proposer, BlockCheckParams, ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError, }; use srml_babe::{ @@ -65,40 +93,120 @@ use consensus_common::import_queue::{Verifier, BasicQueue}; use client::{ block_builder::api::BlockBuilder as BlockBuilderApi, blockchain::{self, HeaderBackend, ProvideCache}, BlockchainEvents, CallExecutor, Client, - runtime_api::ApiExt, error::Result as ClientResult, backend::{AuxStore, Backend}, + error::Result as ClientResult, error::Error as ClientError, backend::{AuxStore, Backend}, ProvideUncles, - utils::is_descendent_of, well_known_cache_keys::{self, Id as CacheKeyId}, }; -use fork_tree::ForkTree; use slots::{CheckedHeader, check_equivocation}; -use futures::{prelude::*, future}; -use futures01::Stream as _; -use futures_timer::Delay; -use log::{error, warn, debug, info, trace}; - -use slots::{SlotWorker, SlotData, SlotInfo, SlotCompatible, SignedDuration}; +use futures::prelude::*; +use log::{warn, debug, info, trace}; +use slots::{SlotWorker, SlotData, SlotInfo, SlotCompatible}; +use epoch_changes::descendent_query; +use header_metadata::HeaderMetadata; +use schnorrkel::SignatureError; mod aux_schema; +mod verification; +mod epoch_changes; +mod authorship; #[cfg(test)] mod tests; -pub use babe_primitives::{AuthorityId, AuthorityPair, AuthoritySignature}; +pub use babe_primitives::{ + AuthorityId, AuthorityPair, AuthoritySignature, Epoch, NextEpochDescriptor, +}; +pub use epoch_changes::{EpochChanges, EpochChangesFor, SharedEpochChanges}; + + +#[derive(derive_more::Display, Debug)] +enum Error { + #[display(fmt = "Multiple BABE pre-runtime digests, rejecting!")] + MultiplePreRuntimeDigests, + #[display(fmt = "No BABE pre-runtime digest found")] + NoPreRuntimeDigest, + #[display(fmt = "Multiple BABE epoch change digests, rejecting!")] + MultipleEpochChangeDigests, + #[display(fmt = "Could not extract timestamp and slot: {:?}", _0)] + Extraction(consensus_common::Error), + #[display(fmt = "Could not fetch epoch at {:?}", _0)] + FetchEpoch(B::Hash), + #[display(fmt = "Header {:?} rejected: too far in the future", _0)] + TooFarInFuture(B::Hash), + #[display(fmt = "Parent ({}) of {} unavailable. Cannot import", _0, _1)] + ParentUnavailable(B::Hash, B::Hash), + #[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)] + SlotNumberMustIncrease(u64, u64), + #[display(fmt = "Header {:?} has a bad seal", _0)] + HeaderBadSeal(B::Hash), + #[display(fmt = "Header {:?} is unsealed", _0)] + HeaderUnsealed(B::Hash), + #[display(fmt = "Slot author not found")] + SlotAuthorNotFound, + #[display(fmt = "Secondary slot assignments are disabled for the current epoch.")] + SecondarySlotAssignmentsDisabled, + #[display(fmt = "Bad signature on {:?}", _0)] + BadSignature(B::Hash), + #[display(fmt = "Invalid author: Expected secondary author: {:?}, got: {:?}.", _0, _1)] + InvalidAuthor(AuthorityId, AuthorityId), + #[display(fmt = "No secondary author expected.")] + NoSecondaryAuthorExpected, + #[display(fmt = "VRF verification of block by author {:?} failed: threshold {} exceeded", _0, _1)] + VRFVerificationOfBlockFailed(AuthorityId, u128), + #[display(fmt = "VRF verification failed: {:?}", _0)] + VRFVerificationFailed(SignatureError), + #[display(fmt = "Could not fetch parent header: {:?}", _0)] + FetchParentHeader(client::error::Error), + #[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)] + ExpectedEpochChange(B::Hash, u64), + #[display(fmt = "Could not look up epoch: {:?}", _0)] + CouldNotLookUpEpoch(Box>), + #[display(fmt = "Block {} is not valid under any epoch.", _0)] + BlockNotValid(B::Hash), + #[display(fmt = "Unexpected epoch change")] + UnexpectedEpochChange, + #[display(fmt = "Parent block of {} has no associated weight", _0)] + ParentBlockNoAssociatedWeight(B::Hash), + #[display(fmt = "Checking inherents failed: {}", _0)] + CheckInherents(String), + Client(client::error::Error), + Runtime(RuntimeString), + ForkTree(Box>), +} + +impl std::convert::From> for String { + fn from(error: Error) -> String { + error.to_string() + } +} + +fn babe_err(error: Error) -> Error { + debug!(target: "babe", "{}", error); + error +} + +macro_rules! babe_info { + ($($i: expr),+) => { + { + info!(target: "babe", $($i),+); + format!($($i),+) + } + }; +} /// A slot duration. Create with `get_or_compute`. // FIXME: Once Rust has higher-kinded types, the duplication between this // and `super::babe::Config` can be eliminated. // https://github.com/paritytech/substrate/issues/2434 +#[derive(Clone)] pub struct Config(slots::SlotDuration); impl Config { /// Either fetch the slot duration from disk or compute it from the genesis /// state. - pub fn get_or_compute(client: &C) -> ClientResult - where + pub fn get_or_compute(client: &C) -> ClientResult where C: AuxStore + ProvideRuntimeApi, C::Api: BabeApi, { trace!(target: "babe", "Getting slot duration"); - match slots::SlotDuration::get_or_compute(client, |a, b| a.startup_data(b)).map(Self) { + match slots::SlotDuration::get_or_compute(client, |a, b| a.configuration(b)).map(Self) { Ok(s) => Ok(s), Err(s) => { warn!(target: "babe", "Failed to get slot duration"); @@ -107,37 +215,29 @@ impl Config { } } - /// Get the slot duration in milliseconds. - pub fn get(&self) -> u64 { - self.0.slot_duration - } - - /// Retrieve the threshold calculation constant `c`. - pub fn c(&self) -> (u64, u64) { - self.0.c + /// Create the genesis epoch (epoch #0). This is defined to start at the slot of + /// the first block, so that has to be provided. + pub fn genesis_epoch(&self, slot_number: SlotNumber) -> Epoch { + Epoch { + epoch_index: 0, + start_slot: slot_number, + duration: self.epoch_length, + authorities: self.genesis_authorities.clone(), + randomness: self.randomness.clone(), + } } } -impl SlotCompatible for BabeLink { - fn extract_timestamp_and_slot( - &self, - data: &InherentData, - ) -> Result<(TimestampInherent, u64, std::time::Duration), consensus_common::Error> { - trace!(target: "babe", "extract timestamp"); - data.timestamp_inherent_data() - .and_then(|t| data.babe_inherent_data().map(|a| (t, a))) - .map_err(Into::into) - .map_err(consensus_common::Error::InherentData) - .map(|(x, y)| (x, y, self.0.lock().0.take().unwrap_or_default())) +impl std::ops::Deref for Config { + type Target = BabeConfiguration; + + fn deref(&self) -> &BabeConfiguration { + &*self.0 } } /// Parameters for BABE. -pub struct BabeParams { - /// The configuration for BABE. Includes the slot duration, threshold, and - /// other parameters. - pub config: Config, - +pub struct BabeParams { /// The keystore that manages the keys of the node. pub keystore: KeyStorePtr, @@ -147,12 +247,14 @@ pub struct BabeParams { /// The SelectChain Strategy pub select_chain: SC, - /// A block importer - pub block_import: I, - - /// The environment + /// The environment we are producing blocks for. pub env: E, + /// The underlying block-import object to supply our produced blocks to. + /// This must be a `BabeBlockImport` or a wrapper of it, otherwise + /// critical consensus logic will be omitted. + pub block_import: I, + /// A sync oracle pub sync_oracle: SO, @@ -163,282 +265,237 @@ pub struct BabeParams { pub force_authoring: bool, /// The source of timestamps for relative slots - pub time_source: BabeLink, + pub babe_link: BabeLink, } /// Start the babe worker. The returned future should be run in a tokio runtime. -pub fn start_babe(BabeParams { - config, - client, +pub fn start_babe(BabeParams { keystore, + client, select_chain, - block_import, env, + block_import, sync_oracle, inherent_data_providers, force_authoring, - time_source, -}: BabeParams) -> Result< + babe_link, +}: BabeParams) -> Result< impl futures01::Future, consensus_common::Error, > where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache + ProvideUncles + Send + Sync + 'static, + B: BlockT, + C: ProvideRuntimeApi + ProvideCache + ProvideUncles + BlockchainEvents + + HeaderBackend + HeaderMetadata + Send + Sync + 'static, C::Api: BabeApi, SC: SelectChain + 'static, + E: Environment + Send + Sync, E::Proposer: Proposer, >::Create: Unpin + Send + 'static, - H: Header, - E: Environment, - I: BlockImport + Send + Sync + 'static, + I: BlockImport + Send + Sync + 'static, Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, SO: SyncOracle + Send + Sync + Clone, { + let config = babe_link.config; let worker = BabeWorker { client: client.clone(), block_import: Arc::new(Mutex::new(block_import)), env, sync_oracle: sync_oracle.clone(), force_authoring, - c: config.c(), keystore, + epoch_changes: babe_link.epoch_changes.clone(), + config: config.clone(), }; - register_babe_inherent_data_provider(&inherent_data_providers, config.0.slot_duration())?; + + register_babe_inherent_data_provider(&inherent_data_providers, config.slot_duration())?; uncles::register_uncles_inherent_data_provider( client.clone(), select_chain.clone(), &inherent_data_providers, )?; - Ok(slots::start_slot_worker( + + babe_info!("Starting BABE Authorship worker"); + let slot_worker = slots::start_slot_worker( config.0, select_chain, worker, sync_oracle, inherent_data_providers, - time_source, - ).map(|()| Ok::<(), ()>(())).compat()) + babe_link.time_source, + ); + + Ok(slot_worker.map(|_| Ok::<(), ()>(())).compat()) } -struct BabeWorker { +struct BabeWorker { client: Arc, block_import: Arc>, env: E, sync_oracle: SO, force_authoring: bool, - c: (u64, u64), keystore: KeyStorePtr, + epoch_changes: SharedEpochChanges, + config: Config, } -impl SlotWorker for BabeWorker where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache, +impl slots::SimpleSlotWorker for BabeWorker where + B: BlockT, + C: ProvideRuntimeApi + ProvideCache + HeaderBackend + HeaderMetadata, C::Api: BabeApi, E: Environment, E::Proposer: Proposer, >::Create: Unpin + Send + 'static, - Hash: Debug + Eq + Copy + SimpleBitOps + Encode + Decode + Serialize + - for<'de> Deserialize<'de> + Debug + Default + AsRef<[u8]> + AsMut<[u8]> + - std::hash::Hash + Display + Send + Sync + 'static, - H: Header, I: BlockImport + Send + Sync + 'static, SO: SyncOracle + Send + Clone, Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, { - type OnSlot = Pin> + Send>>; - - fn on_slot( - &mut self, - chain_head: B::Header, - slot_info: SlotInfo, - ) -> Self::OnSlot { - let ref client = self.client; - let block_import = self.block_import.clone(); - - let (timestamp, slot_number, slot_duration) = - (slot_info.timestamp, slot_info.number, slot_info.duration); - - let epoch = match epoch(client.as_ref(), &BlockId::Hash(chain_head.hash())) { - Ok(authorities) => authorities, - Err(e) => { - error!( - target: "babe", - "Unable to fetch authorities at block {:?}: {:?}", - chain_head.hash(), - e - ); - telemetry!(CONSENSUS_WARN; "babe.unable_fetching_authorities"; - "slot" => ?chain_head.hash(), "err" => ?e - ); - return Box::pin(future::ready(Ok(()))); - } - }; + type EpochData = Epoch; + type Claim = (BabePreDigest, AuthorityPair); + type SyncOracle = SO; + type Proposer = E::Proposer; + type BlockImport = I; + + fn logging_target(&self) -> &'static str { + "babe" + } - let Epoch { ref authorities, .. } = epoch; + fn block_import(&self) -> Arc> { + self.block_import.clone() + } - if authorities.is_empty() { - error!(target: "babe", "No authorities at block {:?}", chain_head.hash()); - } + fn epoch_data(&self, parent: &B::Header, slot_number: u64) -> Result { + self.epoch_changes.lock().epoch_for_child_of( + descendent_query(&*self.client), + &parent.hash(), + parent.number().clone(), + slot_number, + |slot| self.config.genesis_epoch(slot) + ) + .map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))? + .map(|e| e.into_inner()) + .ok_or(consensus_common::Error::InvalidAuthoritiesSet) + } - if !self.force_authoring && self.sync_oracle.is_offline() && authorities.len() > 1 { - debug!(target: "babe", "Skipping proposal slot. Waiting for the network."); - telemetry!(CONSENSUS_DEBUG; "babe.skipping_proposal_slot"; - "authorities_len" => authorities.len() - ); - return Box::pin(future::ready(Ok(()))); - } + fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize { + epoch_data.authorities.len() + } - let proposal_work = if let Some(claim) = claim_slot( - slot_info.number, - epoch, - self.c, + fn claim_slot( + &self, + _parent_header: &B::Header, + slot_number: SlotNumber, + epoch_data: &Epoch, + ) -> Option { + debug!(target: "babe", "Attempting to claim slot {}", slot_number); + let s = authorship::claim_slot( + slot_number, + epoch_data, + &*self.config, &self.keystore, - ) { - let ((inout, vrf_proof, _batchable_proof), authority_index, key) = claim; - - debug!( - target: "babe", "Starting authorship at slot {}; timestamp = {}", - slot_number, - timestamp, - ); - telemetry!(CONSENSUS_DEBUG; "babe.starting_authorship"; - "slot_number" => slot_number, "timestamp" => timestamp - ); - - // we are the slot author. make a block and sign it. - let mut proposer = match self.env.init(&chain_head) { - Ok(p) => p, - Err(e) => { - warn!(target: "babe", - "Unable to author block in slot {:?}: {:?}", - slot_number, - e, - ); - telemetry!(CONSENSUS_WARN; "babe.unable_authoring_block"; - "slot" => slot_number, "err" => ?e - ); - return Box::pin(future::ready(Ok(()))) - } - }; - - let inherent_digest = BabePreDigest { - vrf_proof, - vrf_output: inout.to_output(), - authority_index: authority_index as u32, - slot_number, - }; + ); - // deadline our production to approx. the end of the slot - let remaining_duration = slot_info.remaining_duration(); - futures::future::select( - proposer.propose( - slot_info.inherent_data, - generic::Digest { - logs: vec![ - generic::DigestItem::babe_pre_digest(inherent_digest.clone()), - ], - }, - remaining_duration, - ).map_err(|e| consensus_common::Error::ClientImport(format!("{:?}", e)).into()), - Delay::new(remaining_duration) - .map_err(|err| consensus_common::Error::FaultyTimer(err).into()) - ).map(|v| match v { - futures::future::Either::Left((v, _)) => v.map(|v| (v, key)), - futures::future::Either::Right((Ok(_), _)) => - Err(consensus_common::Error::ClientImport("Timeout in the BaBe proposer".into())), - futures::future::Either::Right((Err(err), _)) => Err(err), - }) - } else { - return Box::pin(future::ready(Ok(()))); - }; + if let Some(_) = s { + debug!(target: "babe", "Claimed slot {}", slot_number); + } - Box::pin(proposal_work.map_ok(move |(b, key)| { - // minor hack since we don't have access to the timestamp - // that is actually set by the proposer. - let slot_after_building = SignedDuration::default().slot_now(slot_duration); - if slot_after_building != slot_number { - info!( - target: "babe", - "Discarding proposal for slot {}; block production took too long", - slot_number - ); - telemetry!(CONSENSUS_INFO; "babe.discarding_proposal_took_too_long"; - "slot" => slot_number - ); - return; - } + s + } - let (header, body) = b.deconstruct(); - let header_num = header.number().clone(); - let parent_hash = header.parent_hash().clone(); + fn pre_digest_data(&self, _slot_number: u64, claim: &Self::Claim) -> Vec> { + vec![ + as CompatibleDigestItem>::babe_pre_digest(claim.0.clone()), + ] + } + fn block_import_params(&self) -> Box, + Self::Claim, + ) -> consensus_common::BlockImportParams + Send> { + Box::new(|header, header_hash, body, (_, pair)| { // sign the pre-sealed hash of the block and then // add it to a digest item. - let header_hash = header.hash(); - let signature = key.sign(header_hash.as_ref()); - let signature_digest_item = DigestItemFor::::babe_seal(signature); + let signature = pair.sign(header_hash.as_ref()); + let signature_digest_item = as CompatibleDigestItem>::babe_seal(signature); - let import_block = BlockImportParams:: { + BlockImportParams { origin: BlockOrigin::Own, header, justification: None, post_digests: vec![signature_digest_item], body: Some(body), finalized: false, - auxiliary: Vec::new(), + auxiliary: Vec::new(), // block-weight is written in block import. + // TODO: block-import handles fork choice and this shouldn't even have the + // option to specify one. + // https://github.com/paritytech/substrate/issues/3623 fork_choice: ForkChoiceStrategy::LongestChain, - }; + } + }) + } - info!(target: "babe", - "Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", - header_num, - import_block.post_header().hash(), - header_hash, - ); + fn force_authoring(&self) -> bool { + self.force_authoring + } - telemetry!(CONSENSUS_INFO; "babe.pre_sealed_block"; - "header_num" => ?header_num, - "hash_now" => ?import_block.post_header().hash(), - "hash_previously" => ?header_hash, - ); + fn sync_oracle(&mut self) -> &mut Self::SyncOracle { + &mut self.sync_oracle + } - if let Err(e) = block_import.lock().import_block(import_block, Default::default()) { - warn!(target: "babe", "Error with block built on {:?}: {:?}", - parent_hash, e); - telemetry!(CONSENSUS_WARN; "babe.err_with_block_built_on"; - "hash" => ?parent_hash, "err" => ?e - ); - } - })) + fn proposer(&mut self, block: &B::Header) -> Result { + self.env.init(block).map_err(|e| { + consensus_common::Error::ClientImport(format!("{:?}", e)) + }) } } -macro_rules! babe_err { - ($($i: expr),+) => { - { debug!(target: "babe", $($i),+) - ; format!($($i),+) - } - }; +impl SlotWorker for BabeWorker where + B: BlockT, + C: ProvideRuntimeApi + ProvideCache + HeaderBackend + HeaderMetadata + Send + Sync, + C::Api: BabeApi, + E: Environment + Send + Sync, + E::Proposer: Proposer, + >::Create: Unpin + Send + 'static, + I: BlockImport + Send + Sync + 'static, + SO: SyncOracle + Send + Sync + Clone, + Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, +{ + type OnSlot = Pin> + Send>>; + + fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot { + >::on_slot(self, chain_head, slot_info) + } } /// Extract the BABE pre digest from the given header. Pre-runtime digests are /// mandatory, the function will return `Err` if none is found. -fn find_pre_digest(header: &B::Header) -> Result - where DigestItemFor: CompatibleDigestItem, +fn find_pre_digest(header: &B::Header) -> Result> { + // genesis block doesn't contain a pre digest so let's generate a + // dummy one to not break any invariants in the rest of the code + if header.number().is_zero() { + return Ok(BabePreDigest::Secondary { + slot_number: 0, + authority_index: 0, + }); + } + let mut pre_digest: Option<_> = None; for log in header.digest().logs() { trace!(target: "babe", "Checking log {:?}, looking for pre runtime digest", log); match (log.as_babe_pre_digest(), pre_digest.is_some()) { - (Some(_), true) => Err(babe_err!("Multiple BABE pre-runtime digests, rejecting!"))?, + (Some(_), true) => return Err(babe_err(Error::MultiplePreRuntimeDigests)), (None, _) => trace!(target: "babe", "Ignoring digest not meant for us"), (s, false) => pre_digest = s, } } - pre_digest.ok_or_else(|| babe_err!("No BABE pre-runtime digest found")) + pre_digest.ok_or_else(|| babe_err(Error::NoPreRuntimeDigest)) } /// Extract the BABE epoch change digest from the given header, if it exists. -fn find_next_epoch_digest(header: &B::Header) -> Result, String> +fn find_next_epoch_digest(header: &B::Header) + -> Result, Error> where DigestItemFor: CompatibleDigestItem, { let mut epoch_digest: Option<_> = None; @@ -446,7 +503,7 @@ fn find_next_epoch_digest(header: &B::Header) -> Result trace!(target: "babe", "Checking log {:?}, looking for epoch change digest.", log); let log = log.try_to::(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID)); match (log, epoch_digest.is_some()) { - (Some(ConsensusLog::NextEpochData(_)), true) => Err(babe_err!("Multiple BABE epoch change digests, rejecting!"))?, + (Some(ConsensusLog::NextEpochData(_)), true) => return Err(babe_err(Error::MultipleEpochChangeDigests)), (Some(ConsensusLog::NextEpochData(epoch)), false) => epoch_digest = Some(epoch), _ => trace!(target: "babe", "Ignoring digest not meant for us"), } @@ -455,130 +512,61 @@ fn find_next_epoch_digest(header: &B::Header) -> Result Ok(epoch_digest) } -/// Check a header has been signed by the right key. If the slot is too far in -/// the future, an error will be returned. If successful, returns the pre-header -/// and the digest item containing the seal. -/// -/// The seal must be the last digest. Otherwise, the whole header is considered -/// unsigned. This is required for security and must not be changed. -/// -/// This digest item will always return `Some` when used with `as_babe_pre_digest`. -// FIXME #1018 needs misbehavior types. The `transaction_pool` parameter will be -// used to submit such misbehavior reports. -fn check_header( - client: &C, - slot_now: u64, - mut header: B::Header, - hash: B::Hash, - authorities: &[(AuthorityId, BabeWeight)], - randomness: [u8; 32], - epoch_index: u64, - c: (u64, u64), - _transaction_pool: Option<&T>, -) -> Result, DigestItemFor)>, String> where - DigestItemFor: CompatibleDigestItem, - T: Send + Sync + 'static, -{ - trace!(target: "babe", "Checking header"); - let seal = match header.digest_mut().pop() { - Some(x) => x, - None => return Err(babe_err!("Header {:?} is unsealed", hash)), - }; - - let sig = seal.as_babe_seal().ok_or_else(|| { - babe_err!("Header {:?} has a bad seal", hash) - })?; - - let pre_digest = find_pre_digest::(&header)?; - - let BabePreDigest { slot_number, authority_index, ref vrf_proof, ref vrf_output } = pre_digest; - if slot_number > slot_now { - header.digest_mut().push(seal); - Ok(CheckedHeader::Deferred(header, slot_number)) - } else if authority_index > authorities.len() as u32 { - Err(babe_err!("Slot author not found")) - } else { - let (pre_hash, author) = (header.hash(), &authorities[authority_index as usize].0); - - if AuthorityPair::verify(&sig, pre_hash, &author) { - let (inout, _batchable_proof) = { - let transcript = make_transcript( - &randomness, - slot_number, - epoch_index, - ); - - schnorrkel::PublicKey::from_bytes(author.as_slice()).and_then(|p| { - p.vrf_verify(transcript, vrf_output, vrf_proof) - }).map_err(|s| { - babe_err!("VRF verification failed: {:?}", s) - })? - }; +#[derive(Default, Clone)] +struct TimeSource(Arc, Vec<(Instant, u64)>)>>); - let threshold = calculate_threshold(c, authorities, authority_index as usize); - if !check(&inout, threshold) { - return Err(babe_err!("VRF verification of block by author {:?} failed: \ - threshold {} exceeded", author, threshold)); - } - - if let Some(equivocation_proof) = check_equivocation( - client, - slot_now, - slot_number, - &header, - author, - ).map_err(|e| e.to_string())? { - info!( - "Slot author {:?} is equivocating at slot {} with headers {:?} and {:?}", - author, - slot_number, - equivocation_proof.fst_header().hash(), - equivocation_proof.snd_header().hash(), - ); - } - - let pre_digest = CompatibleDigestItem::babe_pre_digest(pre_digest); - Ok(CheckedHeader::Checked(header, (pre_digest, seal))) - } else { - Err(babe_err!("Bad signature on {:?}", hash)) - } +impl SlotCompatible for TimeSource { + fn extract_timestamp_and_slot( + &self, + data: &InherentData, + ) -> Result<(TimestampInherent, u64, std::time::Duration), consensus_common::Error> { + trace!(target: "babe", "extract timestamp"); + data.timestamp_inherent_data() + .and_then(|t| data.babe_inherent_data().map(|a| (t, a))) + .map_err(Into::into) + .map_err(consensus_common::Error::InherentData) + .map(|(x, y)| (x, y, self.0.lock().0.take().unwrap_or_default())) } } /// State that must be shared between the import queue and the authoring logic. -#[derive(Default, Clone, Debug)] -pub struct BabeLink(Arc, Vec<(Instant, u64)>)>>); - +#[derive(Clone)] +pub struct BabeLink { + time_source: TimeSource, + epoch_changes: SharedEpochChanges, + config: Config, +} /// A verifier for Babe blocks. -pub struct BabeVerifier { - api: Arc, +pub struct BabeVerifier { + client: Arc>, + api: Arc, inherent_data_providers: inherents::InherentDataProviders, config: Config, - time_source: BabeLink, - transaction_pool: Option>, + epoch_changes: SharedEpochChanges, + time_source: TimeSource, } -impl BabeVerifier { - fn check_inherents( +impl BabeVerifier { + fn check_inherents( &self, - block: B, - block_id: BlockId, + block: Block, + block_id: BlockId, inherent_data: InherentData, - ) -> Result<(), String> - where C: ProvideRuntimeApi, C::Api: BlockBuilderApi + ) -> Result<(), Error> + where PRA: ProvideRuntimeApi, PRA::Api: BlockBuilderApi { let inherent_res = self.api.runtime_api().check_inherents( &block_id, block, inherent_data, - ).map_err(|e| format!("{:?}", e))?; + ).map_err(Error::Client)?; if !inherent_res.ok() { inherent_res .into_errors() .try_for_each(|(i, e)| { - Err(self.inherent_data_providers.error_to_string(&i, &e)) + Err(Error::CheckInherents(self.inherent_data_providers.error_to_string(&i, &e))) }) } else { Ok(()) @@ -598,7 +586,7 @@ fn median_algorithm( if num_timestamps as u64 >= median_required_blocks && median_required_blocks > 0 { let mut new_list: Vec<_> = time_source.1.iter().map(|&(t, sl)| { let offset: u128 = u128::from(slot_duration) - .checked_mul(1_000_000u128) // self.config.get() returns *milliseconds* + .checked_mul(1_000_000u128) // self.config.slot_duration returns milliseconds .and_then(|x| { x.checked_mul(u128::from(slot_number).saturating_sub(u128::from(sl))) }) @@ -611,8 +599,8 @@ fn median_algorithm( t + Duration::new(secs, nanos) }).collect(); - // FIXME #2926: use a selection algorithm instead of a full sorting algorithm. - new_list.sort_unstable(); + // Use a partial sort to move the median timestamp to the middle of the list + pdqselect::select(&mut new_list, num_timestamps / 2); let &median = new_list .get(num_timestamps / 2) @@ -629,18 +617,21 @@ fn median_algorithm( } } -impl Verifier for BabeVerifier where - C: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache, - C::Api: BlockBuilderApi + BabeApi, - T: Send + Sync + 'static, +impl Verifier for BabeVerifier where + Block: BlockT, + B: Backend + 'static, + E: CallExecutor + 'static + Clone + Send + Sync, + RA: Send + Sync, + PRA: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache, + PRA::Api: BlockBuilderApi + BabeApi, { fn verify( &mut self, origin: BlockOrigin, - header: B::Header, + header: Block::Header, justification: Option, - mut body: Option>, - ) -> Result<(BlockImportParams, Option)>>), String> { + mut body: Option>, + ) -> Result<(BlockImportParams, Option)>>), String> { trace!( target: "babe", "Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}", @@ -654,42 +645,74 @@ impl Verifier for BabeVerifier where let mut inherent_data = self .inherent_data_providers .create_inherent_data() - .map_err(String::from)?; + .map_err( Error::::Runtime)?; let (_, slot_now, _) = self.time_source.extract_timestamp_and_slot(&inherent_data) - .map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?; + .map_err(Error::::Extraction)?; let hash = header.hash(); let parent_hash = *header.parent_hash(); - let Epoch { authorities, randomness, epoch_index, .. } = - epoch(self.api.as_ref(), &BlockId::Hash(parent_hash)) - .map_err(|e| format!("Could not fetch epoch at {:?}: {:?}", parent_hash, e))?; - // We add one to allow for some small drift. + let parent_header_metadata = self.client.header_metadata(parent_hash) + .map_err(Error::::FetchParentHeader)?; + + let pre_digest = find_pre_digest::(&header)?; + let epoch = { + let epoch_changes = self.epoch_changes.lock(); + epoch_changes.epoch_for_child_of( + descendent_query(&*self.client), + &parent_hash, + parent_header_metadata.number, + pre_digest.slot_number(), + |slot| self.config.genesis_epoch(slot), + ) + .map_err(|e| Error::::ForkTree(Box::new(e)))? + .ok_or_else(|| Error::::FetchEpoch(parent_hash))? + }; + + // We add one to the current slot to allow for some small drift. // FIXME #1019 in the future, alter this queue to allow deferring of headers - let checked_header = check_header::( - &self.api, - slot_now + 1, - header, - hash, - &authorities, - randomness, - epoch_index, - self.config.c(), - self.transaction_pool.as_ref().map(|x| &**x), - )?; - - match checked_header { - CheckedHeader::Checked(pre_header, (pre_digest, seal)) => { - let BabePreDigest { slot_number, .. } = pre_digest.as_babe_pre_digest() + let v_params = verification::VerificationParams { + header: header.clone(), + pre_digest: Some(pre_digest.clone()), + slot_now: slot_now + 1, + epoch: epoch.as_ref(), + config: &self.config, + }; + + match verification::check_header::(v_params)? { + CheckedHeader::Checked(pre_header, verified_info) => { + let babe_pre_digest = verified_info.pre_digest.as_babe_pre_digest() .expect("check_header always returns a pre-digest digest item; qed"); + let slot_number = babe_pre_digest.slot_number(); + + let author = verified_info.author; + + // the header is valid but let's check if there was something else already + // proposed at the same slot by the given author + if let Some(equivocation_proof) = check_equivocation( + &*self.api, + slot_now, + babe_pre_digest.slot_number(), + &header, + &author, + ).map_err(|e| e.to_string())? { + info!( + "Slot author {:?} is equivocating at slot {} with headers {:?} and {:?}", + author, + babe_pre_digest.slot_number(), + equivocation_proof.fst_header().hash(), + equivocation_proof.snd_header().hash(), + ); + } + // if the body is passed through, we need to use the runtime // to check that the internally-set timestamp in the inherents // actually matches the slot set in the seal. if let Some(inner_body) = body.take() { inherent_data.babe_replace_inherent_data(slot_number); - let block = B::new(pre_header.clone(), inner_body); + let block = Block::new(pre_header.clone(), inner_body); self.check_inherents( block.clone(), @@ -707,57 +730,33 @@ impl Verifier for BabeVerifier where "babe.checked_and_importing"; "pre_header" => ?pre_header); - let import_block = BlockImportParams { + let block_import_params = BlockImportParams { origin, header: pre_header, - post_digests: vec![seal], + post_digests: vec![verified_info.seal], body, finalized: false, justification, auxiliary: Vec::new(), + // TODO: block-import handles fork choice and this shouldn't even have the + // option to specify one. + // https://github.com/paritytech/substrate/issues/3623 fork_choice: ForkChoiceStrategy::LongestChain, }; - Ok((import_block, Default::default())) + Ok((block_import_params, Default::default())) } CheckedHeader::Deferred(a, b) => { debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); telemetry!(CONSENSUS_DEBUG; "babe.header_too_far_in_future"; "hash" => ?hash, "a" => ?a, "b" => ?b ); - Err(format!("Header {:?} rejected: too far in the future", hash)) + Err(Error::::TooFarInFuture(hash).into()) } } } } -/// Extract current epoch data from cache and fallback to querying the runtime -/// if the cache isn't populated. -fn epoch(client: &C, at: &BlockId) -> Result where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache, - C::Api: BabeApi, -{ - client - .cache() - .and_then(|cache| cache.get_at(&well_known_cache_keys::EPOCH, at) - .and_then(|(_, _, v)| Decode::decode(&mut &v[..]).ok())) - .or_else(|| { - if client.runtime_api().has_api::>(at).unwrap_or(false) { - let s = BabeApi::epoch(&*client.runtime_api(), at).ok()?; - if s.authorities.is_empty() { - error!("No authorities!"); - None - } else { - Some(s) - } - } else { - error!("bad api!"); - None - } - }).ok_or(consensus_common::Error::InvalidAuthoritiesSet) -} - /// The BABE import queue type. pub type BabeImportQueue = BasicQueue; @@ -777,149 +776,6 @@ fn register_babe_inherent_data_provider( } } -fn get_keypair(q: &AuthorityPair) -> &Keypair { - use primitives::crypto::IsWrappedBy; - primitives::sr25519::Pair::from_ref(q).as_ref() -} - -#[allow(deprecated)] -fn make_transcript( - randomness: &[u8], - slot_number: u64, - epoch: u64, -) -> Transcript { - let mut transcript = Transcript::new(&BABE_ENGINE_ID); - transcript.commit_bytes(b"slot number", &slot_number.to_le_bytes()); - transcript.commit_bytes(b"current epoch", &epoch.to_le_bytes()); - transcript.commit_bytes(b"chain randomness", randomness); - transcript -} - -fn check(inout: &VRFInOut, threshold: u128) -> bool { - u128::from_le_bytes(inout.make_bytes::<[u8; 16]>(BABE_VRF_PREFIX)) < threshold -} - -fn calculate_threshold( - c: (u64, u64), - authorities: &[(AuthorityId, BabeWeight)], - authority_index: usize, -) -> u128 { - use num_bigint::BigUint; - use num_rational::BigRational; - use num_traits::{cast::ToPrimitive, identities::One}; - - let c = c.0 as f64 / c.1 as f64; - - let theta = - authorities[authority_index].1 as f64 / - authorities.iter().map(|(_, weight)| weight).sum::() as f64; - - let calc = || { - let p = BigRational::from_float(1f64 - (1f64 - c).powf(theta))?; - let numer = p.numer().to_biguint()?; - let denom = p.denom().to_biguint()?; - ((BigUint::one() << 128) * numer / denom).to_u128() - }; - - calc().unwrap_or(u128::max_value()) -} - -/// Claim a slot if it is our turn. Returns `None` if it is not our turn. -/// -/// This hashes the slot number, epoch, genesis hash, and chain randomness into -/// the VRF. If the VRF produces a value less than `threshold`, it is our turn, -/// so it returns `Some(_)`. Otherwise, it returns `None`. -fn claim_slot( - slot_number: u64, - Epoch { ref authorities, ref randomness, epoch_index, .. }: Epoch, - c: (u64, u64), - keystore: &KeyStorePtr, -) -> Option<((VRFInOut, VRFProof, VRFProofBatchable), usize, AuthorityPair)> { - let keystore = keystore.read(); - let (key_pair, authority_index) = authorities.iter() - .enumerate() - .find_map(|(i, a)| { - keystore.key_pair::(&a.0).ok().map(|kp| (kp, i)) - })?; - let transcript = make_transcript(randomness, slot_number, epoch_index); - - // Compute the threshold we will use. - // - // We already checked that authorities contains `key.public()`, so it can't - // be empty. Therefore, this division in `calculate_threshold` is safe. - let threshold = calculate_threshold(c, authorities, authority_index); - - get_keypair(&key_pair) - .vrf_sign_after_check(transcript, |inout| check(inout, threshold)) - .map(|s|(s, authority_index, key_pair)) -} - -fn initialize_authorities_cache(client: &C) -> Result<(), ConsensusError> where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache, - C::Api: BabeApi, -{ - // no cache => no initialization - let cache = match client.cache() { - Some(cache) => cache, - None => return Ok(()), - }; - - // check if we already have initialized the cache - let genesis_id = BlockId::Number(Zero::zero()); - let genesis_epoch: Option = cache - .get_at(&well_known_cache_keys::EPOCH, &genesis_id) - .and_then(|(_, _, v)| Decode::decode(&mut &v[..]).ok()); - if genesis_epoch.is_some() { - return Ok(()); - } - - let map_err = |error| consensus_common::Error::from(consensus_common::Error::ClientImport( - format!( - "Error initializing authorities cache: {}", - error, - ))); - - let genesis_epoch = epoch(client, &genesis_id)?; - cache.initialize(&well_known_cache_keys::EPOCH, genesis_epoch.encode()) - .map_err(map_err) -} - -/// Tree of all epoch changes across all *seen* forks. Data stored in tree is -/// the hash and block number of the block signaling the epoch change, and the -/// epoch that was signalled at that block. -type EpochChanges = ForkTree< - ::Hash, - NumberFor, - Epoch, ->; - -/// A shared epoch changes tree. -#[derive(Clone)] -struct SharedEpochChanges { - inner: Arc>>, -} - -impl SharedEpochChanges { - fn new() -> Self { - SharedEpochChanges { - inner: Arc::new(Mutex::new(EpochChanges::::new())) - } - } - - fn lock(&self) -> MutexGuard> { - self.inner.lock() - } -} - -impl From> for SharedEpochChanges { - fn from(epoch_changes: EpochChanges) -> Self { - SharedEpochChanges { - inner: Arc::new(Mutex::new(epoch_changes)) - } - } -} - /// A block-import handler for BABE. /// /// This scans each imported block for epoch change signals. The signals are @@ -933,6 +789,7 @@ pub struct BabeBlockImport { client: Arc>, api: Arc, epoch_changes: SharedEpochChanges, + config: Config, } impl Clone for BabeBlockImport { @@ -942,6 +799,7 @@ impl Clone for BabeBlockImport BabeBlockImport { api: Arc, epoch_changes: SharedEpochChanges, block_import: I, + config: Config, ) -> Self { BabeBlockImport { client, api, inner: block_import, epoch_changes, + config, } } } @@ -977,78 +837,99 @@ impl BlockImport for BabeBlockImport, - mut new_cache: HashMap>, + new_cache: HashMap>, ) -> Result { let hash = block.post_header().hash(); let number = block.header.number().clone(); // early exit if block already in chain, otherwise the check for // epoch changes will error when trying to re-import an epoch change - #[allow(deprecated)] - match self.client.backend().blockchain().status(BlockId::Hash(hash)) { + match self.client.status(BlockId::Hash(hash)) { Ok(blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), Ok(blockchain::BlockStatus::Unknown) => {}, - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), + Err(e) => return Err(ConsensusError::ClientImport(e.to_string())), } - let slot_number = { - let pre_digest = find_pre_digest::(&block.header) - .expect("valid babe headers must contain a predigest; \ - header has been already verified; qed"); - let BabePreDigest { slot_number, .. } = pre_digest; - slot_number - }; + let pre_digest = find_pre_digest::(&block.header) + .expect("valid babe headers must contain a predigest; \ + header has been already verified; qed"); + let slot_number = pre_digest.slot_number(); - // returns a function for checking whether a block is a descendent of another - // consistent with querying client directly after importing the block. let parent_hash = *block.header.parent_hash(); - let is_descendent_of = is_descendent_of(&self.client, Some((&hash, &parent_hash))); + let parent_header = self.client.header(&BlockId::Hash(parent_hash)) + .map_err(|e| ConsensusError::ChainLookup(e.to_string()))? + .ok_or_else(|| ConsensusError::ChainLookup(babe_err( + Error::::ParentUnavailable(parent_hash, hash) + ).into()))?; + + let parent_slot = find_pre_digest::(&parent_header) + .map(|d| d.slot_number()) + .expect("parent is non-genesis; valid BABE headers contain a pre-digest; \ + header has already been verified; qed"); + + // make sure that slot number is strictly increasing + if slot_number <= parent_slot { + return Err( + ConsensusError::ClientImport(babe_err( + Error::::SlotNumberMustIncrease(parent_slot, slot_number) + ).into()) + ); + } - // check if there's any epoch change expected to happen at this slot let mut epoch_changes = self.epoch_changes.lock(); - let enacted_epoch = epoch_changes.find_node_where( - &hash, - &number, - &is_descendent_of, - &|epoch| epoch.start_slot <= slot_number, - ).map_err(|e| ConsensusError::from(ConsensusError::ClientImport(e.to_string())))?; - - let check_roots = || -> Result { - // this can only happen when the chain starts, since there's no - // epoch change at genesis. afterwards every time we expect an epoch - // change it means we will import another one. - for (root, _, _) in epoch_changes.roots() { - let is_descendent_of = is_descendent_of(root, &hash) - .map_err(|e| { - ConsensusError::from(ConsensusError::ClientImport(e.to_string())) - })?; - - if is_descendent_of { - return Ok(false); - } - } - Ok(true) + // check if there's any epoch change expected to happen at this slot. + // `epoch` is the epoch to verify the block under, and `first_in_epoch` is true + // if this is the first block in its chain for that epoch. + // + // also provides the total weight of the chain, including the imported block. + let (epoch, first_in_epoch, parent_weight) = { + let parent_weight = if *parent_header.number() == Zero::zero() { + 0 + } else { + aux_schema::load_block_weight(&*self.client, parent_hash) + .map_err(|e| ConsensusError::ClientImport(e.to_string()))? + .ok_or_else(|| ConsensusError::ClientImport( + babe_err(Error::::ParentBlockNoAssociatedWeight(hash)).into() + ))? + }; + + let epoch = epoch_changes.epoch_for_child_of( + descendent_query(&*self.client), + &parent_hash, + *parent_header.number(), + slot_number, + |slot| self.config.genesis_epoch(slot), + ) + .map_err(|e: fork_tree::Error| ConsensusError::ChainLookup( + babe_err(Error::::CouldNotLookUpEpoch(Box::new(e))).into() + ))? + .ok_or_else(|| ConsensusError::ClientImport( + babe_err(Error::::BlockNotValid(hash)).into() + ))?; + + let first_in_epoch = parent_slot < epoch.as_ref().start_slot; + (epoch, first_in_epoch, parent_weight) }; - let expected_epoch_change = enacted_epoch.is_some(); + let total_weight = parent_weight + pre_digest.added_weight(); + + // search for this all the time so we can reject unexpected announcements. let next_epoch_digest = find_next_epoch_digest::(&block.header) - .map_err(|e| ConsensusError::from(ConsensusError::ClientImport(e.to_string())))?; + .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; - match (expected_epoch_change, next_epoch_digest.is_some()) { + match (first_in_epoch, next_epoch_digest.is_some()) { (true, true) => {}, (false, false) => {}, (true, false) => { return Err( ConsensusError::ClientImport( - "Expected epoch change to happen by this block".into(), + babe_err(Error::::ExpectedEpochChange(hash, slot_number)).into(), ) ); }, (false, true) => { - if !check_roots()? { - return Err(ConsensusError::ClientImport("Unexpected epoch change".into())); - } + return Err(ConsensusError::ClientImport(Error::::UnexpectedEpochChange.into())); }, } @@ -1056,48 +937,46 @@ impl BlockImport for BabeBlockImport= start slot {}).", + epoch.as_ref().epoch_index, hash, slot_number, epoch.as_ref().start_slot); + babe_info!("Next epoch starts at slot {}", next_epoch.as_ref().start_slot); + + // prune the tree of epochs not part of the finalized chain or + // that are not live anymore, and then track the given epoch change + // in the tree. + // NOTE: it is important that these operations are done in this + // order, otherwise if pruning after import the `is_descendent_of` + // used by pruning may not know about the block that is being + // imported. + let prune_and_import = || { + prune_finalized( + &self.client, + &mut epoch_changes, + )?; + + epoch_changes.import( + descendent_query(&*self.client), + hash, + number, + *block.header.parent_hash(), + next_epoch, + ).map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; + + Ok(()) + }; + + if let Err(e) = prune_and_import() { + debug!(target: "babe", "Failed to launch next epoch: {:?}", e); + *epoch_changes = old_epoch_changes.expect("set `Some` above and not taken; qed"); + return Err(e); + } crate::aux_schema::write_epoch_changes::( &*epoch_changes, @@ -1107,6 +986,41 @@ impl BlockImport for BabeBlockImport last_best_weight { + true + } else if total_weight == last_best_weight { + number > last_best_number + } else { + false + }) + }; + let import_result = self.inner.import_block(block, new_cache); // revert to the original epoch changes in case there's an error @@ -1122,88 +1036,129 @@ impl BlockImport for BabeBlockImport, ) -> Result { - self.inner.check_block(hash, parent_hash).map_err(Into::into) + self.inner.check_block(block).map_err(Into::into) } } -/// Start an import queue for the BABE consensus algorithm. This method returns -/// the import queue, some data that needs to be passed to the block authoring -/// logic (`BabeLink`), a `BabeBlockImport` which should be used by the -/// authoring when importing its own blocks, and a future that must be run to +/// Gets the best finalized block and its slot, and prunes the given epoch tree. +fn prune_finalized( + client: &Client, + epoch_changes: &mut EpochChangesFor, +) -> Result<(), ConsensusError> where + Block: BlockT, + E: CallExecutor + Send + Sync, + B: Backend, + RA: Send + Sync, +{ + let info = client.info().chain; + + let finalized_slot = { + let finalized_header = client.header(&BlockId::Hash(info.finalized_hash)) + .map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))? + .expect("best finalized hash was given by client; \ + finalized headers must exist in db; qed"); + + find_pre_digest::(&finalized_header) + .expect("finalized header must be valid; \ + valid blocks have a pre-digest; qed") + .slot_number() + }; + + epoch_changes.prune_finalized( + descendent_query(&*client), + &info.finalized_hash, + info.finalized_number, + finalized_slot, + ).map_err(|e| ConsensusError::ClientImport(format!("{:?}", e)))?; + + Ok(()) +} + +/// Produce a BABE block-import object to be used later on in the construction of +/// an import-queue. +/// +/// Also returns a link object used to correctly instantiate the import queue +/// and background worker. +pub fn block_import, I, RA, PRA>( + config: Config, + wrapped_block_import: I, + client: Arc>, + api: Arc, +) -> ClientResult<(BabeBlockImport, BabeLink)> where + B: Backend, + E: CallExecutor + Send + Sync, + RA: Send + Sync, +{ + let epoch_changes = aux_schema::load_epoch_changes(&*client)?; + let link = BabeLink { + epoch_changes: epoch_changes.clone(), + time_source: Default::default(), + config: config.clone(), + }; + + // NOTE: this isn't entirely necessary, but since we didn't use to prune the + // epoch tree it is useful as a migration, so that nodes prune long trees on + // startup rather than waiting until importing the next epoch change block. + prune_finalized( + &client, + &mut epoch_changes.lock(), + )?; + + let import = BabeBlockImport::new( + client, + api, + epoch_changes, + wrapped_block_import, + config, + ); + + Ok((import, link)) +} + +/// Start an import queue for the BABE consensus algorithm. +/// +/// This method returns the import queue, some data that needs to be passed to the block authoring +/// logic (`BabeLink`), and a future that must be run to /// completion and is responsible for listening to finality notifications and /// pruning the epoch changes tree. -pub fn import_queue, I, RA, PRA, T>( - config: Config, +/// +/// The block import object provided must be the `BabeBlockImport` or a wrapper +/// of it, otherwise crucial import logic will be omitted. +pub fn import_queue, I, RA, PRA>( + babe_link: BabeLink, block_import: I, justification_import: Option>, finality_proof_import: Option>, client: Arc>, api: Arc, inherent_data_providers: InherentDataProviders, - transaction_pool: Option>, -) -> ClientResult<( - BabeImportQueue, - BabeLink, - BabeBlockImport, - impl futures01::Future, -)> where +) -> ClientResult> where B: Backend + 'static, - I: BlockImport + Clone + Send + Sync + 'static, - I::Error: Into, + I: BlockImport + Send + Sync + 'static, E: CallExecutor + Clone + Send + Sync + 'static, RA: Send + Sync + 'static, PRA: ProvideRuntimeApi + ProvideCache + Send + Sync + AuxStore + 'static, PRA::Api: BlockBuilderApi + BabeApi, - T: Send + Sync + 'static, { - register_babe_inherent_data_provider(&inherent_data_providers, config.get())?; - initialize_authorities_cache(&*api)?; + register_babe_inherent_data_provider(&inherent_data_providers, babe_link.config.slot_duration)?; let verifier = BabeVerifier { - api: api.clone(), + client: client.clone(), + api, inherent_data_providers, - time_source: Default::default(), - config, - transaction_pool, + config: babe_link.config, + epoch_changes: babe_link.epoch_changes, + time_source: babe_link.time_source, }; - #[allow(deprecated)] - let epoch_changes = aux_schema::load_epoch_changes(&**client.backend())?; - - let block_import = BabeBlockImport::new( - client.clone(), - api, - epoch_changes.clone(), - block_import, - ); - - let pruning_task = client.finality_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat() - .for_each(move |notification| { - let is_descendent_of = is_descendent_of(&client, None); - epoch_changes.lock().prune( - ¬ification.hash, - *notification.header.number(), - &is_descendent_of, - ).map_err(|e| { - debug!(target: "babe", "Error pruning epoch changes fork tree: {:?}", e) - })?; - - Ok(()) - }); - - let timestamp_core = verifier.time_source.clone(); - let queue = BasicQueue::new( + Ok(BasicQueue::new( verifier, - Box::new(block_import.clone()), + Box::new(block_import), justification_import, finality_proof_import, - ); - - Ok((queue, timestamp_core, block_import, pruning_task)) + )) } /// BABE test helpers. Utility methods for manually authoring blocks. @@ -1214,30 +1169,29 @@ pub mod test_helpers { /// Try to claim the given slot and return a `BabePreDigest` if /// successful. pub fn claim_slot( - client: &C, - at: &BlockId, slot_number: u64, - c: (u64, u64), + parent: &B::Header, + client: &C, keystore: &KeyStorePtr, + link: &BabeLink, ) -> Option where - B: BlockT, - C: ProvideRuntimeApi + ProvideCache, + B: BlockT, + C: ProvideRuntimeApi + ProvideCache + HeaderBackend + HeaderMetadata, C::Api: BabeApi, { - let epoch = epoch(client, at).unwrap(); + let epoch = link.epoch_changes.lock().epoch_for_child_of( + descendent_query(client), + &parent.hash(), + parent.number().clone(), + slot_number, + |slot| link.config.genesis_epoch(slot), + ).unwrap().unwrap(); - super::claim_slot( + authorship::claim_slot( slot_number, - epoch, - c, + epoch.as_ref(), + &link.config, keystore, - ).map(|((inout, vrf_proof, _), authority_index, _)| { - BabePreDigest { - vrf_proof, - vrf_output: inout.to_output(), - authority_index: authority_index as u32, - slot_number, - } - }) + ).map(|(digest, _)| digest) } } diff --git a/core/consensus/babe/src/tests.rs b/core/consensus/babe/src/tests.rs index 01e0acb96402abc568eac216b2e5025b2b1a7991..2e236f190b66a11d4d4961c5f149b9b65edfc581 100644 --- a/core/consensus/babe/src/tests.rs +++ b/core/consensus/babe/src/tests.rs @@ -20,22 +20,26 @@ // https://github.com/paritytech/substrate/issues/2532 #![allow(deprecated)] use super::*; -use super::generic::DigestItem; +use authorship::claim_slot; -use babe_primitives::AuthorityPair; -use client::{LongestChain, block_builder::BlockBuilder}; +use babe_primitives::{AuthorityPair, SlotNumber}; +use client::block_builder::BlockBuilder; use consensus_common::NoNetwork as DummyOracle; +use consensus_common::import_queue::{ + BoxBlockImport, BoxJustificationImport, BoxFinalityProofImport, +}; use network::test::*; use network::test::{Block as TestBlock, PeersClient}; -use sr_primitives::traits::{Block as BlockT, DigestFor}; +use network::config::BoxFinalityProofRequestBuilder; +use sr_primitives::{generic::DigestItem, traits::{Block as BlockT, DigestFor}}; use network::config::ProtocolConfig; use tokio::runtime::current_thread; -use keyring::sr25519::Keyring; use client::BlockchainEvents; use test_client; use log::debug; -use std::{time::Duration, borrow::Borrow, cell::RefCell}; -type Item = generic::DigestItem; +use std::{time::Duration, cell::RefCell}; + +type Item = DigestItem; type Error = client::error::Error; @@ -46,8 +50,28 @@ type TestClient = client::Client< test_client::runtime::RuntimeApi, >; -struct DummyFactory(Arc); -struct DummyProposer(u64, Arc); +#[derive(Copy, Clone, PartialEq)] +enum Stage { + PreSeal, + PostSeal, +} + +type Mutator = Arc; + +#[derive(Clone)] +struct DummyFactory { + client: Arc, + epoch_changes: crate::SharedEpochChanges, + config: Config, + mutator: Mutator, +} + +struct DummyProposer { + factory: DummyFactory, + parent_hash: Hash, + parent_number: u64, + parent_slot: SlotNumber, +} impl Environment for DummyFactory { type Proposer = DummyProposer; @@ -56,7 +80,71 @@ impl Environment for DummyFactory { fn init(&mut self, parent_header: &::Header) -> Result { - Ok(DummyProposer(parent_header.number + 1, self.0.clone())) + + let parent_slot = crate::find_pre_digest::(parent_header) + .expect("parent header has a pre-digest") + .slot_number(); + + Ok(DummyProposer { + factory: self.clone(), + parent_hash: parent_header.hash(), + parent_number: *parent_header.number(), + parent_slot, + }) + } +} + +impl DummyProposer { + fn propose_with(&mut self, pre_digests: DigestFor) + -> future::Ready> + { + use codec::Encode; + let block_builder = self.factory.client.new_block_at( + &BlockId::Hash(self.parent_hash), + pre_digests, + ).unwrap(); + + let mut block = match block_builder.bake().map_err(|e| e.into()) { + Ok(b) => b, + Err(e) => return future::ready(Err(e)), + }; + + let this_slot = crate::find_pre_digest::(block.header()) + .expect("baked block has valid pre-digest") + .slot_number(); + + // figure out if we should add a consensus digest, since the test runtime + // doesn't. + let epoch_changes = self.factory.epoch_changes.lock(); + let epoch = epoch_changes.epoch_for_child_of( + descendent_query(&*self.factory.client), + &self.parent_hash, + self.parent_number, + this_slot, + |slot| self.factory.config.genesis_epoch(slot), + ) + .expect("client has data to find epoch") + .expect("can compute epoch for baked block") + .into_inner(); + + let first_in_epoch = self.parent_slot < epoch.start_slot; + if first_in_epoch { + // push a `Consensus` digest signalling next change. + // we just reuse the same randomness and authorities as the prior + // epoch. this will break when we add light client support, since + // that will re-check the randomness logic off-chain. + let digest_data = ConsensusLog::NextEpochData(NextEpochDescriptor { + authorities: epoch.authorities.clone(), + randomness: epoch.randomness.clone(), + }).encode(); + let digest = DigestItem::Consensus(BABE_ENGINE_ID, digest_data); + block.header.digest_mut().push(digest) + } + + // mutate the block header according to the mutator. + (self.factory.mutator)(&mut block.header, Stage::PreSeal); + + future::ready(Ok(block)) } } @@ -67,28 +155,54 @@ impl Proposer for DummyProposer { fn propose( &mut self, _: InherentData, - digests: DigestFor, + pre_digests: DigestFor, _: Duration, ) -> Self::Create { - future::ready(self.1.new_block(digests).unwrap().bake().map_err(|e| e.into())) + self.propose_with(pre_digests) } } -type Mutator = Arc Fn(&'r mut TestHeader) + Send + Sync>; - thread_local! { - static MUTATOR: RefCell = RefCell::new(Arc::new(|_|())); + static MUTATOR: RefCell = RefCell::new(Arc::new(|_, _|())); +} + +#[derive(Clone)] +struct PanickingBlockImport(B); + +impl> BlockImport for PanickingBlockImport { + type Error = B::Error; + + fn import_block( + &mut self, + block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { + Ok(self.0.import_block(block, new_cache).expect("importing block failed")) + } + + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + Ok(self.0.check_block(block).expect("checking block failed")) + } } pub struct BabeTestNet { - peers: Vec>, + peers: Vec, DummySpecialization>>, } type TestHeader = ::Header; type TestExtrinsic = ::Extrinsic; pub struct TestVerifier { - inner: BabeVerifier, + inner: BabeVerifier< + test_client::Backend, + test_client::Executor, + TestBlock, + test_client::runtime::RuntimeApi, + PeersFullClient, + >, mutator: Mutator, } @@ -103,16 +217,22 @@ impl Verifier for TestVerifier { justification: Option, body: Option>, ) -> Result<(BlockImportParams, Option)>>), String> { - let cb: &(dyn Fn(&mut TestHeader) + Send + Sync) = self.mutator.borrow(); - cb(&mut header); + // apply post-sealing mutations (i.e. stripping seal, if desired). + (self.mutator)(&mut header, Stage::PostSeal); Ok(self.inner.verify(origin, header, justification, body).expect("verification failed!")) } } +pub struct PeerData { + link: BabeLink, + inherent_data_providers: InherentDataProviders, + block_import: Mutex>>, +} + impl TestNetFactory for BabeTestNet { type Specialization = DummySpecialization; type Verifier = TestVerifier; - type PeerData = (); + type PeerData = Option; /// Create new test network with peers and given config. fn from_config(_config: &ProtocolConfig) -> Self { @@ -122,30 +242,62 @@ impl TestNetFactory for BabeTestNet { } } - /// KLUDGE: this function gets the mutator from thread-local storage. - fn make_verifier(&self, client: PeersClient, _cfg: &ProtocolConfig) + fn make_block_import(&self, client: PeersClient) + -> ( + BoxBlockImport, + Option>, + Option>, + Option>, + Option, + ) + { + let client = client.as_full().expect("only full clients are tested"); + let inherent_data_providers = InherentDataProviders::new(); + + let config = Config::get_or_compute(&*client).expect("config available"); + let (block_import, link) = crate::block_import( + config, + client.clone(), + client.clone(), + client.clone(), + ).expect("can initialize block-import"); + + let block_import = PanickingBlockImport(block_import); + + let data_block_import = Mutex::new(Some(Box::new(block_import.clone()) as BoxBlockImport<_>)); + ( + Box::new(block_import), + None, + None, + None, + Some(PeerData { link, inherent_data_providers, block_import: data_block_import }), + ) + } + + fn make_verifier( + &self, + client: PeersClient, + _cfg: &ProtocolConfig, + maybe_link: &Option, + ) -> Self::Verifier { - let api = client.as_full().expect("only full clients are used in test"); + let client = client.as_full().expect("only full clients are used in test"); trace!(target: "babe", "Creating a verifier"); - let config = Config::get_or_compute(&*api) - .expect("slot duration available"); - let inherent_data_providers = InherentDataProviders::new(); - register_babe_inherent_data_provider( - &inherent_data_providers, - config.get() - ).expect("Registers babe inherent data provider"); - trace!(target: "babe", "Provider registered"); + + // ensure block import and verifier are linked correctly. + let data = maybe_link.as_ref().expect("babe link always provided to verifier instantiation"); TestVerifier { inner: BabeVerifier { - api, - inherent_data_providers, - config, - time_source: Default::default(), - transaction_pool : Default::default(), + client: client.clone(), + api: client, + inherent_data_providers: data.inherent_data_providers.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + time_source: data.link.time_source.clone(), }, - mutator: MUTATOR.with(|s| s.borrow().clone()), + mutator: MUTATOR.with(|m| m.borrow().clone()), } } @@ -180,8 +332,13 @@ fn rejects_empty_block() { }) } -fn run_one_test() { +fn run_one_test( + mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + 'static, +) { let _ = env_logger::try_init(); + let mutator = Arc::new(mutator) as Mutator; + + MUTATOR.with(|m| *m.borrow_mut() = mutator.clone()); let net = BabeTestNet::new(3); let peers = &[ @@ -194,40 +351,58 @@ fn run_one_test() { let mut import_notifications = Vec::new(); let mut runtime = current_thread::Runtime::new().unwrap(); let mut keystore_paths = Vec::new(); + for (peer_id, seed) in peers { + let mut net = net.lock(); + let peer = net.peer(*peer_id); + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let select_chain = peer.select_chain().expect("Full client has select_chain"); + let keystore_path = tempfile::tempdir().expect("Creates keystore path"); let keystore = keystore::Store::open(keystore_path.path(), None).expect("Creates keystore"); keystore.write().insert_ephemeral_from_seed::(seed).expect("Generates authority key"); keystore_paths.push(keystore_path); - let client = net.lock().peer(*peer_id).client().as_full().unwrap(); - let environ = DummyFactory(client.clone()); + let mut got_own = false; + let mut got_other = false; + + let data = peer.data.as_ref().expect("babe link set up during initialization"); + + let environ = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: mutator.clone(), + }; + import_notifications.push( + // run each future until we get one of our own blocks with number higher than 5 + // that was produced locally. client.import_notification_stream() - .take_while(|n| future::ready(!(n.origin != BlockOrigin::Own && n.header.number() < &5))) - .for_each(move |_| future::ready(())) + .take_while(move |n| future::ready(n.header.number() < &5 || { + if n.origin == BlockOrigin::Own { + got_own = true; + } else { + got_other = true; + } + + // continue until we have at least one block of our own + // and one of another peer. + !(got_own && got_other) + })) + .for_each(|_| future::ready(()) ) ); - let config = Config::get_or_compute(&*client).expect("slot duration available"); - - let inherent_data_providers = InherentDataProviders::new(); - register_babe_inherent_data_provider( - &inherent_data_providers, config.get() - ).expect("Registers babe inherent data provider"); - - #[allow(deprecated)] - let select_chain = LongestChain::new(client.backend().clone()); runtime.spawn(start_babe(BabeParams { - config, - block_import: client.clone(), + block_import: data.block_import.lock().take().expect("import set up during init"), select_chain, client, env: environ, sync_oracle: DummyOracle, - inherent_data_providers, + inherent_data_providers: data.inherent_data_providers.clone(), force_authoring: false, - time_source: Default::default(), + babe_link: data.link.clone(), keystore, }).expect("Starts babe")); } @@ -242,45 +417,41 @@ fn run_one_test() { } #[test] -fn authoring_blocks() { run_one_test() } +fn authoring_blocks() { + run_one_test(|_, _| ()) +} #[test] #[should_panic] fn rejects_missing_inherent_digest() { - MUTATOR.with(|s| *s.borrow_mut() = Arc::new(move |header: &mut TestHeader| { + run_one_test(|header: &mut TestHeader, stage| { let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); header.digest_mut().logs = v.into_iter() - .filter(|v| v.as_babe_pre_digest().is_none()) + .filter(|v| stage == Stage::PostSeal || v.as_babe_pre_digest().is_none()) .collect() - })); - run_one_test() + }) } #[test] #[should_panic] fn rejects_missing_seals() { - MUTATOR.with(|s| *s.borrow_mut() = Arc::new(move |header: &mut TestHeader| { + run_one_test(|header: &mut TestHeader, stage| { let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); header.digest_mut().logs = v.into_iter() - .filter(|v| v.as_babe_seal().is_none()) + .filter(|v| stage == Stage::PreSeal || v.as_babe_seal().is_none()) .collect() - })); - run_one_test() + }) } -// TODO: this test assumes that the test runtime will trigger epoch changes -// which isn't the case since it doesn't include the session module. #[test] #[should_panic] -#[ignore] fn rejects_missing_consensus_digests() { - MUTATOR.with(|s| *s.borrow_mut() = Arc::new(move |header: &mut TestHeader| { + run_one_test(|header: &mut TestHeader, stage| { let v = std::mem::replace(&mut header.digest_mut().logs, vec![]); header.digest_mut().logs = v.into_iter() - .filter(|v| v.as_babe_epoch().is_none()) + .filter(|v| stage == Stage::PostSeal || v.as_next_epoch_descriptor().is_none()) .collect() - })); - run_one_test() + }); } #[test] @@ -324,26 +495,284 @@ fn can_author_block() { epoch_index: 1, duration: 100, }; + + let mut config = crate::BabeConfiguration { + slot_duration: 1000, + epoch_length: 100, + c: (3, 10), + genesis_authorities: Vec::new(), + randomness: [0; 32], + secondary_slots: true, + }; + + // with secondary slots enabled it should never be empty + match claim_slot(i, &epoch, &config, &keystore) { + None => i += 1, + Some(s) => debug!(target: "babe", "Authored block {:?}", s.0), + } + + // otherwise with only vrf-based primary slots we might need to try a couple + // of times. + config.secondary_slots = false; loop { - match claim_slot(i, epoch.clone(), (3, 10), &keystore) { + match claim_slot(i, &epoch, &config, &keystore) { None => i += 1, Some(s) => { debug!(target: "babe", "Authored block {:?}", s.0); - break + break; } } } } +// Propose and import a new BABE block on top of the given parent. +fn propose_and_import_block( + parent: &TestHeader, + slot_number: Option, + proposer_factory: &mut DummyFactory, + block_import: &mut BoxBlockImport, +) -> H256 { + let mut proposer = proposer_factory.init(parent).unwrap(); + + let slot_number = slot_number.unwrap_or_else(|| { + let parent_pre_digest = find_pre_digest::(parent).unwrap(); + parent_pre_digest.slot_number() + 1 + }); + + let pre_digest = sr_primitives::generic::Digest { + logs: vec![ + Item::babe_pre_digest( + BabePreDigest::Secondary { + authority_index: 0, + slot_number, + }, + ), + ], + }; + + let mut block = futures::executor::block_on(proposer.propose_with(pre_digest)).unwrap(); + + let seal = { + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let pair = AuthorityPair::from_seed(&[1; 32]); + let pre_hash = block.header.hash(); + let signature = pair.sign(pre_hash.as_ref()); + Item::babe_seal(signature) + }; + + let post_hash = { + block.header.digest_mut().push(seal.clone()); + let h = block.header.hash(); + block.header.digest_mut().pop(); + h + }; + + let import_result = block_import.import_block( + BlockImportParams { + origin: BlockOrigin::Own, + header: block.header, + justification: None, + post_digests: vec![seal], + body: Some(block.extrinsics), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + }, + Default::default(), + ).unwrap(); + + match import_result { + ImportResult::Imported(_) => {}, + _ => panic!("expected block to be imported"), + } + + post_hash +} + #[test] -fn authorities_call_works() { - let _ = env_logger::try_init(); - let client = test_client::new(); - - assert_eq!(client.info().chain.best_number, 0); - assert_eq!(epoch(&client, &BlockId::Number(0)).unwrap().authorities, vec![ - (Keyring::Alice.public().into(), 1), - (Keyring::Bob.public().into(), 1), - (Keyring::Charlie.public().into(), 1), - ]); +fn importing_block_one_sets_genesis_epoch() { + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + + let genesis_header = client.header(&BlockId::Number(0)).unwrap().unwrap(); + + let block_hash = propose_and_import_block( + &genesis_header, + Some(999), + &mut proposer_factory, + &mut block_import, + ); + + let genesis_epoch = data.link.config.genesis_epoch(999); + + let epoch_changes = data.link.epoch_changes.lock(); + let epoch_for_second_block = epoch_changes.epoch_for_child_of( + descendent_query(&*client), + &block_hash, + 1, + 1000, + |slot| data.link.config.genesis_epoch(slot), + ).unwrap().unwrap().into_inner(); + + assert_eq!(epoch_for_second_block, genesis_epoch); +} + +#[test] +fn importing_epoch_change_block_prunes_tree() { + use client::backend::Finalizer; + + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + let epoch_changes = data.link.epoch_changes.clone(); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + // This is just boilerplate code for proposing and importing n valid BABE + // blocks that are built on top of the given parent. The proposer takes care + // of producing epoch change digests according to the epoch duration (which + // is set to 6 slots in the test runtime). + let mut propose_and_import_blocks = |parent_id, n| { + let mut hashes = Vec::new(); + let mut parent_header = client.header(&parent_id).unwrap().unwrap(); + + for _ in 0..n { + let block_hash = propose_and_import_block( + &parent_header, + None, + &mut proposer_factory, + &mut block_import, + ); + hashes.push(block_hash); + parent_header = client.header(&BlockId::Hash(block_hash)).unwrap().unwrap(); + } + + hashes + }; + + // This is the block tree that we're going to use in this test. Each node + // represents an epoch change block, the epoch duration is 6 slots. + // + // *---- F (#7) + // / *------ G (#19) - H (#25) + // / / + // A (#1) - B (#7) - C (#13) - D (#19) - E (#25) + // \ + // *------ I (#25) + + // Create and import the canon chain and keep track of fork blocks (A, C, D) + // from the diagram above. + let canon_hashes = propose_and_import_blocks(BlockId::Number(0), 30); + + // Create the forks + let fork_1 = propose_and_import_blocks(BlockId::Hash(canon_hashes[0]), 10); + let fork_2 = propose_and_import_blocks(BlockId::Hash(canon_hashes[12]), 15); + let fork_3 = propose_and_import_blocks(BlockId::Hash(canon_hashes[18]), 10); + + // We should be tracking a total of 9 epochs in the fork tree + assert_eq!( + epoch_changes.lock().tree().iter().count(), + 9, + ); + + // And only one root + assert_eq!( + epoch_changes.lock().tree().roots().count(), + 1, + ); + + // We finalize block #13 from the canon chain, so on the next epoch + // change the tree should be pruned, to not contain F (#7). + client.finalize_block(BlockId::Hash(canon_hashes[12]), None, false).unwrap(); + propose_and_import_blocks(BlockId::Hash(client.info().chain.best_hash), 7); + + // at this point no hashes from the first fork must exist on the tree + assert!( + !epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_1.contains(h)), + ); + + // but the epoch changes from the other forks must still exist + assert!( + epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h)) + ); + + assert!( + epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)), + ); + + // finalizing block #25 from the canon chain should prune out the second fork + client.finalize_block(BlockId::Hash(canon_hashes[24]), None, false).unwrap(); + propose_and_import_blocks(BlockId::Hash(client.info().chain.best_hash), 8); + + // at this point no hashes from the second fork must exist on the tree + assert!( + !epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_2.contains(h)), + ); + + // while epoch changes from the last fork should still exist + assert!( + epoch_changes.lock().tree().iter().map(|(h, _, _)| h).any(|h| fork_3.contains(h)), + ); +} + +#[test] +#[should_panic] +fn verify_slots_are_strictly_increasing() { + let mut net = BabeTestNet::new(1); + + let peer = net.peer(0); + let data = peer.data.as_ref().expect("babe link set up during initialization"); + + let client = peer.client().as_full().expect("Only full clients are used in tests").clone(); + let mut block_import = data.block_import.lock().take().expect("import set up during init"); + + let mut proposer_factory = DummyFactory { + client: client.clone(), + config: data.link.config.clone(), + epoch_changes: data.link.epoch_changes.clone(), + mutator: Arc::new(|_, _| ()), + }; + + let genesis_header = client.header(&BlockId::Number(0)).unwrap().unwrap(); + + // we should have no issue importing this block + let b1 = propose_and_import_block( + &genesis_header, + Some(999), + &mut proposer_factory, + &mut block_import, + ); + + let b1 = client.header(&BlockId::Hash(b1)).unwrap().unwrap(); + + // we should fail to import this block since the slot number didn't increase. + // we will panic due to the `PanickingBlockImport` defined above. + propose_and_import_block( + &b1, + Some(999), + &mut proposer_factory, + &mut block_import, + ); } diff --git a/core/consensus/babe/src/verification.rs b/core/consensus/babe/src/verification.rs new file mode 100644 index 0000000000000000000000000000000000000000..36e34dfb9578b8ace59b25ee0eff192b284a4a1e --- /dev/null +++ b/core/consensus/babe/src/verification.rs @@ -0,0 +1,217 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Verification for BABE headers. +use schnorrkel::vrf::{VRFOutput, VRFProof}; +use sr_primitives::{traits::Header, traits::DigestItemFor}; +use primitives::{Pair, Public}; +use babe_primitives::{Epoch, BabePreDigest, CompatibleDigestItem, AuthorityId}; +use babe_primitives::{AuthoritySignature, SlotNumber, AuthorityIndex, AuthorityPair}; +use slots::CheckedHeader; +use log::{debug, trace}; +use super::{find_pre_digest, babe_err, BlockT, Error}; +use super::authorship::{make_transcript, calculate_primary_threshold, check_primary_threshold, secondary_slot_author}; + +/// BABE verification parameters +pub(super) struct VerificationParams<'a, B: 'a + BlockT> { + /// the header being verified. + pub(super) header: B::Header, + /// the pre-digest of the header being verified. this is optional - if prior + /// verification code had to read it, it can be included here to avoid duplicate + /// work. + pub(super) pre_digest: Option, + /// the slot number of the current time. + pub(super) slot_now: SlotNumber, + /// epoch descriptor of the epoch this block _should_ be under, if it's valid. + pub(super) epoch: &'a Epoch, + /// genesis config of this BABE chain. + pub(super) config: &'a super::Config, +} + +/// Check a header has been signed by the right key. If the slot is too far in +/// the future, an error will be returned. If successful, returns the pre-header +/// and the digest item containing the seal. +/// +/// The seal must be the last digest. Otherwise, the whole header is considered +/// unsigned. This is required for security and must not be changed. +/// +/// This digest item will always return `Some` when used with `as_babe_pre_digest`. +/// +/// The given header can either be from a primary or secondary slot assignment, +/// with each having different validation logic. +pub(super) fn check_header( + params: VerificationParams, +) -> Result>, Error> where + DigestItemFor: CompatibleDigestItem, +{ + let VerificationParams { + mut header, + pre_digest, + slot_now, + epoch, + config, + } = params; + + let authorities = &epoch.authorities; + let pre_digest = pre_digest.map(Ok).unwrap_or_else(|| find_pre_digest::(&header))?; + + trace!(target: "babe", "Checking header"); + let seal = match header.digest_mut().pop() { + Some(x) => x, + None => return Err(babe_err(Error::HeaderUnsealed(header.hash()))), + }; + + let sig = seal.as_babe_seal().ok_or_else(|| { + babe_err(Error::HeaderBadSeal(header.hash())) + })?; + + // the pre-hash of the header doesn't include the seal + // and that's what we sign + let pre_hash = header.hash(); + + if pre_digest.slot_number() > slot_now { + header.digest_mut().push(seal); + return Ok(CheckedHeader::Deferred(header, pre_digest.slot_number())); + } + + let author = match authorities.get(pre_digest.authority_index() as usize) { + Some(author) => author.0.clone(), + None => return Err(babe_err(Error::SlotAuthorNotFound)), + }; + + match &pre_digest { + BabePreDigest::Primary { vrf_output, vrf_proof, authority_index, slot_number } => { + debug!(target: "babe", "Verifying Primary block"); + + let digest = (vrf_output, vrf_proof, *authority_index, *slot_number); + + check_primary_header::( + pre_hash, + digest, + sig, + &epoch, + config.c, + )?; + }, + BabePreDigest::Secondary { authority_index, slot_number } if config.secondary_slots => { + debug!(target: "babe", "Verifying Secondary block"); + + let digest = (*authority_index, *slot_number); + + check_secondary_header::( + pre_hash, + digest, + sig, + &epoch, + )?; + }, + _ => { + return Err(babe_err(Error::SecondarySlotAssignmentsDisabled)); + } + } + + let info = VerifiedHeaderInfo { + pre_digest: CompatibleDigestItem::babe_pre_digest(pre_digest), + seal, + author, + }; + Ok(CheckedHeader::Checked(header, info)) +} + +pub(super) struct VerifiedHeaderInfo { + pub(super) pre_digest: DigestItemFor, + pub(super) seal: DigestItemFor, + pub(super) author: AuthorityId, +} + +/// Check a primary slot proposal header. We validate that the given header is +/// properly signed by the expected authority, and that the contained VRF proof +/// is valid. Additionally, the weight of this block must increase compared to +/// its parent since it is a primary block. +fn check_primary_header( + pre_hash: B::Hash, + pre_digest: (&VRFOutput, &VRFProof, AuthorityIndex, SlotNumber), + signature: AuthoritySignature, + epoch: &Epoch, + c: (u64, u64), +) -> Result<(), Error> { + let (vrf_output, vrf_proof, authority_index, slot_number) = pre_digest; + + let author = &epoch.authorities[authority_index as usize].0; + + if AuthorityPair::verify(&signature, pre_hash, &author) { + let (inout, _) = { + let transcript = make_transcript( + &epoch.randomness, + slot_number, + epoch.epoch_index, + ); + + schnorrkel::PublicKey::from_bytes(author.as_slice()).and_then(|p| { + p.vrf_verify(transcript, vrf_output, vrf_proof) + }).map_err(|s| { + babe_err(Error::VRFVerificationFailed(s)) + })? + }; + + let threshold = calculate_primary_threshold( + c, + &epoch.authorities, + authority_index as usize, + ); + + if !check_primary_threshold(&inout, threshold) { + return Err(babe_err(Error::VRFVerificationOfBlockFailed(author.clone(), threshold))); + } + + Ok(()) + } else { + Err(babe_err(Error::BadSignature(pre_hash))) + } +} + +/// Check a secondary slot proposal header. We validate that the given header is +/// properly signed by the expected authority, which we have a deterministic way +/// of computing. Additionally, the weight of this block must stay the same +/// compared to its parent since it is a secondary block. +fn check_secondary_header( + pre_hash: B::Hash, + pre_digest: (AuthorityIndex, SlotNumber), + signature: AuthoritySignature, + epoch: &Epoch, +) -> Result<(), Error> { + let (authority_index, slot_number) = pre_digest; + + // check the signature is valid under the expected authority and + // chain state. + let expected_author = secondary_slot_author( + slot_number, + &epoch.authorities, + epoch.randomness, + ).ok_or_else(|| Error::NoSecondaryAuthorExpected)?; + + let author = &epoch.authorities[authority_index as usize].0; + + if expected_author != author { + return Err(Error::InvalidAuthor(expected_author.clone(), author.clone())); + } + + if AuthorityPair::verify(&signature, pre_hash.as_ref(), author) { + Ok(()) + } else { + Err(Error::BadSignature(pre_hash)) + } +} diff --git a/core/consensus/common/Cargo.toml b/core/consensus/common/Cargo.toml index 46c8121207562240ac073059c497fd49a0c3b192..9c4e96f65dceec5104cadef8ade442b4c5ae426f 100644 --- a/core/consensus/common/Cargo.toml +++ b/core/consensus/common/Cargo.toml @@ -6,13 +6,13 @@ description = "Common utilities for substrate consensus" edition = "2018" [dependencies] -derive_more = "0.14.0" -libp2p = { version = "0.11.0", default-features = false } -log = "0.4" +derive_more = "0.15.0" +libp2p = { version = "0.13.0", default-features = false } +log = "0.4.8" primitives = { package = "substrate-primitives", path= "../../primitives" } inherents = { package = "substrate-inherents", path = "../../inherents" } -futures-preview = "=0.3.0-alpha.17" -futures-timer = "0.2.1" +futures-preview = "0.3.0-alpha.19" +futures-timer = "0.4.0" rstd = { package = "sr-std", path = "../../sr-std" } runtime_version = { package = "sr-version", path = "../../sr-version" } sr-primitives = { path = "../../sr-primitives" } diff --git a/core/consensus/common/primitives/Cargo.toml b/core/consensus/common/primitives/Cargo.toml deleted file mode 100644 index de59c3723dd7d984a56cda9c383052a7fda1069d..0000000000000000000000000000000000000000 --- a/core/consensus/common/primitives/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "substrate-consensus-common-primitives" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Common consensus primitives" -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" } -client = { package = "substrate-client", path = "../../../client", default-features = false } -sr-primitives = { path = "../../../sr-primitives", default-features = false } -rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } - -[features] -default = ["std"] -std = [ - "rstd/std", - "client/std", - "codec/std", - "sr-primitives/std" -] diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs index 1ea442754e1a01c92e924359e5fd1323bc31c2ce..4342ee38df10a7626302bd57205e347fe05d3f6b 100644 --- a/core/consensus/common/src/block_import.rs +++ b/core/consensus/common/src/block_import.rs @@ -38,7 +38,7 @@ pub enum ImportResult { } /// Auxiliary data associated with an imported block result. -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Default, PartialEq, Eq)] pub struct ImportedAux { /// Clear all pending justification requests. pub clear_justification_requests: bool, @@ -48,24 +48,19 @@ pub struct ImportedAux { pub bad_justification: bool, /// Request a finality proof for the given block. pub needs_finality_proof: bool, -} - -impl Default for ImportedAux { - fn default() -> ImportedAux { - ImportedAux { - clear_justification_requests: false, - needs_justification: false, - bad_justification: false, - needs_finality_proof: false, - } - } + /// Whether the block that was imported is the new best block. + pub is_new_best: bool, } impl ImportResult { - /// Returns default value for `ImportResult::Imported` with both - /// `clear_justification_requests` and `needs_justification` set to false. - pub fn imported() -> ImportResult { - ImportResult::Imported(ImportedAux::default()) + /// Returns default value for `ImportResult::Imported` with + /// `clear_justification_requests`, `needs_justification`, + /// `bad_justification` and `needs_finality_proof` set to false. + pub fn imported(is_new_best: bool) -> ImportResult { + let mut aux = ImportedAux::default(); + aux.is_new_best = is_new_best; + + ImportResult::Imported(aux) } } @@ -95,7 +90,17 @@ pub enum ForkChoiceStrategy { Custom(bool), } -/// Data required to import a Block +/// Data required to check validity of a Block. +pub struct BlockCheckParams { + /// Hash of the block that we verify. + pub hash: Block::Hash, + /// Block number of the block that we verify. + pub number: NumberFor, + /// Parent hash of the block that we verify. + pub parent_hash: Block::Hash, +} + +/// Data required to import a Block. pub struct BlockImportParams { /// Origin of the Block pub origin: BlockOrigin, @@ -125,7 +130,8 @@ pub struct BlockImportParams { /// Contains a list of key-value pairs. If values are `None`, the keys /// will be deleted. pub auxiliary: Vec<(Vec, Option>)>, - /// Fork choice strategy of this import. + /// Fork choice strategy of this import. This should only be set by a + /// synchronous import, otherwise it may race against other imports. pub fork_choice: ForkChoiceStrategy, } @@ -176,8 +182,7 @@ pub trait BlockImport { /// Check block preconditions. fn check_block( &mut self, - hash: B::Hash, - parent_hash: B::Hash, + block: BlockCheckParams, ) -> Result; /// Import a block. @@ -190,17 +195,39 @@ pub trait BlockImport { ) -> Result; } -impl BlockImport for Arc +impl BlockImport for crate::import_queue::BoxBlockImport { + type Error = crate::error::Error; + + /// Check block preconditions. + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + (**self).check_block(block) + } + + /// Import a block. + /// + /// Cached data can be accessed through the blockchain cache. + fn import_block( + &mut self, + block: BlockImportParams, + cache: HashMap>, + ) -> Result { + (**self).import_block(block, cache) + } +} + +impl BlockImport for Arc where for<'r> &'r T: BlockImport { type Error = E; fn check_block( &mut self, - hash: B::Hash, - parent_hash: B::Hash, + block: BlockCheckParams, ) -> Result { - (&**self).check_block(hash, parent_hash) + (&**self).check_block(block) } fn import_block( diff --git a/core/consensus/common/src/block_validation.rs b/core/consensus/common/src/block_validation.rs new file mode 100644 index 0000000000000000000000000000000000000000..be181b05c6f4d2085f5dfca2012fa067911fdbd6 --- /dev/null +++ b/core/consensus/common/src/block_validation.rs @@ -0,0 +1,66 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. +// +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Block announcement validation. + +use crate::BlockStatus; +use sr_primitives::{generic::BlockId, traits::Block}; +use std::{error::Error, sync::Arc}; + +/// A type which provides access to chain information. +pub trait Chain { + /// Retrieve the status of the block denoted by the given [`BlockId`]. + fn block_status(&self, id: &BlockId) -> Result>; +} + +impl, B: Block> Chain for Arc { + fn block_status(&self, id: &BlockId) -> Result> { + (&**self).block_status(id) + } +} + +/// Result of `BlockAnnounceValidator::validate`. +#[derive(Debug, PartialEq, Eq)] +pub enum Validation { + /// Valid block announcement. + Success, + /// Invalid block announcement. + Failure, +} + +/// Type which checks incoming block announcements. +pub trait BlockAnnounceValidator { + /// Validate the announced header and its associated data. + fn validate(&mut self, header: &B::Header, data: &[u8]) -> Result>; +} + +/// Default implementation of `BlockAnnounceValidator`. +#[derive(Debug)] +pub struct DefaultBlockAnnounceValidator { + chain: C +} + +impl DefaultBlockAnnounceValidator { + pub fn new(chain: C) -> Self { + Self { chain } + } +} + +impl> BlockAnnounceValidator for DefaultBlockAnnounceValidator { + fn validate(&mut self, _h: &B::Header, _d: &[u8]) -> Result> { + Ok(Validation::Success) + } +} diff --git a/core/consensus/common/src/import_queue.rs b/core/consensus/common/src/import_queue.rs index 533df2b179abd70bf1bf1cda0ff1b8ecb6f2112d..dc1678fcf189d8f5aa00a514b0ca05dd9870d38e 100644 --- a/core/consensus/common/src/import_queue.rs +++ b/core/consensus/common/src/import_queue.rs @@ -30,7 +30,7 @@ use sr_primitives::{Justification, traits::{Block as BlockT, Header as _, Number use crate::error::Error as ConsensusError; use crate::block_import::{ BlockImport, BlockOrigin, BlockImportParams, ImportedAux, JustificationImport, ImportResult, - FinalityProofImport, + BlockCheckParams, FinalityProofImport, }; pub use basic_queue::BasicQueue; @@ -105,6 +105,7 @@ pub trait ImportQueue: Send { number: NumberFor, finality_proof: Vec ); + /// Polls for actions to perform on the network. /// /// This method should behave in a way similar to `Future::poll`. It can register the current @@ -193,7 +194,7 @@ pub fn import_single_block>( let number = header.number().clone(); let hash = header.hash(); - let parent = header.parent_hash().clone(); + let parent_hash = header.parent_hash().clone(); let import_error = |e| { match e { @@ -203,7 +204,7 @@ pub fn import_single_block>( }, Ok(ImportResult::Imported(aux)) => Ok(BlockImportResult::ImportedUnknown(number, aux, peer.clone())), Ok(ImportResult::UnknownParent) => { - debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent); + debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent_hash); Err(BlockImportError::UnknownParent) }, Ok(ImportResult::KnownBad) => { @@ -216,8 +217,7 @@ pub fn import_single_block>( } } }; - - match import_error(import_handle.check_block(hash, parent))? { + match import_error(import_handle.check_block(BlockCheckParams { hash, number, parent_hash }))? { BlockImportResult::ImportedUnknown { .. } => (), r => return Ok(r), // Any other successful result means that the block is already imported. } diff --git a/core/consensus/common/src/import_queue/basic_queue.rs b/core/consensus/common/src/import_queue/basic_queue.rs index da6dcd02934e54562d54fd1a91d86bcde4d2fa4b..2ab6d0c5e3b7dd43e12834a2ac3813348387ade7 100644 --- a/core/consensus/common/src/import_queue/basic_queue.rs +++ b/core/consensus/common/src/import_queue/basic_queue.rs @@ -15,7 +15,7 @@ // along with Substrate. If not, see . use std::{mem, pin::Pin, time::Duration}; -use futures::{prelude::*, channel::mpsc, task::SpawnExt as _, task::Context, task::Poll}; +use futures::{prelude::*, channel::mpsc, task::Context, task::Poll}; use futures_timer::Delay; use sr_primitives::{Justification, traits::{Block as BlockT, Header as HeaderT, NumberFor}}; @@ -70,9 +70,7 @@ impl BasicQueue { let manual_poll; if let Some(pool) = &mut pool { - // TODO: this expect() can be removed once - // https://github.com/rust-lang-nursery/futures-rs/pull/1750 is merged and deployed - pool.spawn(future).expect("ThreadPool can never fail to spawn tasks; QED"); + pool.spawn_ok(future); manual_poll = None; } else { manual_poll = Some(Box::pin(future) as Pin>); diff --git a/core/consensus/common/src/lib.rs b/core/consensus/common/src/lib.rs index a79bd157e2b0902fd4c2a49638c1964f368887bf..154ea7bb52f7c78c03b38d1cee86179cdaf179f4 100644 --- a/core/consensus/common/src/lib.rs +++ b/core/consensus/common/src/lib.rs @@ -35,6 +35,7 @@ use sr_primitives::traits::{Block as BlockT, DigestFor}; use futures::prelude::*; pub use inherents::InherentData; +pub mod block_validation; pub mod offline_tracker; pub mod error; pub mod block_import; @@ -47,11 +48,26 @@ const MAX_BLOCK_SIZE: usize = 4 * 1024 * 1024 + 512; pub use self::error::Error; pub use block_import::{ - BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, + BlockImport, BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, BlockCheckParams, ImportResult, JustificationImport, FinalityProofImport, }; pub use select_chain::SelectChain; +/// Block status. +#[derive(Debug, PartialEq, Eq)] +pub enum BlockStatus { + /// Added to the import queue. + Queued, + /// Already in the blockchain and the state is available. + InChainWithState, + /// In the blockchain, but the state is not available. + InChainPruned, + /// Block or parent is known to be bad. + KnownBad, + /// Not in the queue or the blockchain. + Unknown, +} + /// Environment producer for a Consensus instance. Creates proposer instance and communication streams. pub trait Environment { /// The proposer type this creates. diff --git a/core/consensus/common/src/select_chain.rs b/core/consensus/common/src/select_chain.rs index cae28656a13b90cc50319d3f4fb6449ebdf59de3..e696db6b877b47d1290637a00e76f7dc6cbf9ee5 100644 --- a/core/consensus/common/src/select_chain.rs +++ b/core/consensus/common/src/select_chain.rs @@ -42,8 +42,9 @@ pub trait SelectChain: Sync + Send + Clone { /// best chain to author new blocks upon and probably finalize. fn best_chain(&self) -> Result<::Header, Error>; - /// Get the best ancestor of `target_hash` that we should attempt - /// to finalize next. + /// Get the best descendent of `target_hash` that we should attempt to + /// finalize next, if any. It is valid to return the given `target_hash` + /// itself if no better descendent exists. fn finality_target( &self, target_hash: ::Hash, diff --git a/core/consensus/pow/Cargo.toml b/core/consensus/pow/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..86efcbb95da2bcdd7e89a42ee17ffa0d174f8ef7 --- /dev/null +++ b/core/consensus/pow/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "substrate-consensus-pow" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "PoW consensus algorithm for substrate" +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } +primitives = { package = "substrate-primitives", path = "../../primitives" } +sr-primitives = { path = "../../sr-primitives" } +client = { package = "substrate-client", path = "../../client" } +srml-timestamp = { path = "../../../srml/timestamp" } +inherents = { package = "substrate-inherents", path = "../../inherents" } +pow-primitives = { package = "substrate-consensus-pow-primitives", path = "primitives" } +consensus-common = { package = "substrate-consensus-common", path = "../common" } +log = "0.4.8" +futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } +derive_more = "0.15.0" diff --git a/core/consensus/pow/primitives/Cargo.toml b/core/consensus/pow/primitives/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..021e4c80a754c245367b5e71290f6eb984c38db0 --- /dev/null +++ b/core/consensus/pow/primitives/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "substrate-consensus-pow-primitives" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Primitives for Aura consensus" +edition = "2018" + +[dependencies] +substrate-client = { path = "../../../client", default-features = false } +rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } +sr-primitives = { path = "../../../sr-primitives", default-features = false } +primitives = { package = "substrate-primitives", path = "../../../primitives", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } + +[features] +default = ["std"] +std = [ + "rstd/std", + "substrate-client/std", + "sr-primitives/std", + "primitives/std", + "codec/std", +] diff --git a/core/consensus/pow/primitives/src/lib.rs b/core/consensus/pow/primitives/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..2079b1cbe7e88712499e93320f710169fb7c5722 --- /dev/null +++ b/core/consensus/pow/primitives/src/lib.rs @@ -0,0 +1,65 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for Substrate Proof-of-Work (PoW) consensus. + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::vec::Vec; +use sr_primitives::ConsensusEngineId; +use codec::Decode; +use substrate_client::decl_runtime_apis; + +/// The `ConsensusEngineId` of PoW. +pub const POW_ENGINE_ID: ConsensusEngineId = [b'p', b'o', b'w', b'_']; + +/// Type of seal. +pub type Seal = Vec; + +/// Define methods that total difficulty should implement. +pub trait TotalDifficulty { + fn increment(&mut self, other: Self); +} + +impl TotalDifficulty for primitives::U256 { + fn increment(&mut self, other: Self) { + let ret = self.saturating_add(other); + *self = ret; + } +} + +impl TotalDifficulty for u128 { + fn increment(&mut self, other: Self) { + let ret = self.saturating_add(other); + *self = ret; + } +} + +decl_runtime_apis! { + /// API necessary for timestamp-based difficulty adjustment algorithms. + pub trait TimestampApi { + /// Return the timestamp in the current block. + fn timestamp() -> Moment; + } + + /// API for those chains that put their difficulty adjustment algorithm directly + /// onto runtime. Note that while putting difficulty adjustment algorithm to + /// runtime is safe, putting the PoW algorithm on runtime is not. + pub trait DifficultyApi { + /// Return the target difficulty of the next block. + fn difficulty() -> Difficulty; + } +} diff --git a/core/consensus/pow/src/lib.rs b/core/consensus/pow/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..040eb01d9c5f01188ed80a2fd4ec386d1802ff3b --- /dev/null +++ b/core/consensus/pow/src/lib.rs @@ -0,0 +1,539 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Proof of work consensus for Substrate. +//! +//! To use this engine, you can need to have a struct that implements +//! `PowAlgorithm`. After that, pass an instance of the struct, along +//! with other necessary client references to `import_queue` to setup +//! the queue. Use the `start_mine` function for basic CPU mining. +//! +//! The auxiliary storage for PoW engine only stores the total difficulty. +//! For other storage requirements for particular PoW algorithm (such as +//! the actual difficulty for each particular blocks), you can take a client +//! reference in your `PowAlgorithm` implementation, and use a separate prefix +//! for the auxiliary storage. It is also possible to just use the runtime +//! as the storage, but it is not recommended as it won't work well with light +//! clients. + +use std::sync::Arc; +use std::thread; +use std::collections::HashMap; +use client::{ + BlockOf, blockchain::{HeaderBackend, ProvideCache}, + block_builder::api::BlockBuilder as BlockBuilderApi, backend::AuxStore, + well_known_cache_keys::Id as CacheKeyId, +}; +use sr_primitives::{Justification, RuntimeString}; +use sr_primitives::generic::{BlockId, Digest, DigestItem}; +use sr_primitives::traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi}; +use srml_timestamp::{TimestampInherentData, InherentError as TIError}; +use pow_primitives::{Seal, TotalDifficulty, POW_ENGINE_ID}; +use primitives::H256; +use inherents::{InherentDataProviders, InherentData}; +use consensus_common::{ + BlockImportParams, BlockOrigin, ForkChoiceStrategy, SyncOracle, Environment, Proposer, + SelectChain, Error as ConsensusError +}; +use consensus_common::import_queue::{BoxBlockImport, BasicQueue, Verifier}; +use codec::{Encode, Decode}; +use log::*; + +#[derive(derive_more::Display, Debug)] +pub enum Error { + #[display(fmt = "Header uses the wrong engine {:?}", _0)] + WrongEngine([u8; 4]), + #[display(fmt = "Header {:?} is unsealed", _0)] + HeaderUnsealed(B::Hash), + #[display(fmt = "PoW validation error: invalid seal")] + InvalidSeal, + #[display(fmt = "Rejecting block too far in future")] + TooFarInFuture, + #[display(fmt = "Fetching best header failed using select chain: {:?}", _0)] + BestHeaderSelectChain(ConsensusError), + #[display(fmt = "Fetching best header failed: {:?}", _0)] + BestHeader(client::error::Error), + #[display(fmt = "Best header does not exist")] + NoBestHeader, + #[display(fmt = "Block proposing error: {:?}", _0)] + BlockProposingError(String), + #[display(fmt = "Fetch best hash failed via select chain: {:?}", _0)] + BestHashSelectChain(ConsensusError), + #[display(fmt = "Error with block built on {:?}: {:?}", _0, _1)] + BlockBuiltError(B::Hash, ConsensusError), + #[display(fmt = "Creating inherents failed: {}", _0)] + CreateInherents(RuntimeString), + #[display(fmt = "Checking inherents failed: {}", _0)] + CheckInherents(String), + Client(client::error::Error), + Codec(codec::Error), + Environment(String), + Runtime(RuntimeString) +} + +impl std::convert::From> for String { + fn from(error: Error) -> String { + error.to_string() + } +} + +/// Auxiliary storage prefix for PoW engine. +pub const POW_AUX_PREFIX: [u8; 4] = *b"PoW:"; + +/// Get the auxiliary storage key used by engine to store total difficulty. +fn aux_key(hash: &H256) -> Vec { + POW_AUX_PREFIX.iter().chain(&hash[..]) + .cloned().collect::>() +} + +/// Auxiliary storage data for PoW. +#[derive(Encode, Decode, Clone, Debug, Default)] +pub struct PowAux { + /// Difficulty of the current block. + pub difficulty: Difficulty, + /// Total difficulty up to current block. + pub total_difficulty: Difficulty, +} + +impl PowAux where + Difficulty: Decode + Default, +{ + /// Read the auxiliary from client. + pub fn read(client: &C, hash: &H256) -> Result> { + let key = aux_key(hash); + + match client.get_aux(&key).map_err(Error::Client)? { + Some(bytes) => Self::decode(&mut &bytes[..]) + .map_err(Error::Codec), + None => Ok(Self::default()), + } + } +} + +/// Algorithm used for proof of work. +pub trait PowAlgorithm { + /// Difficulty for the algorithm. + type Difficulty: TotalDifficulty + Default + Encode + Decode + Ord + Clone + Copy; + + /// Get the next block's difficulty. + fn difficulty(&self, parent: &BlockId) -> Result>; + /// Verify proof of work against the given difficulty. + fn verify( + &self, + parent: &BlockId, + pre_hash: &H256, + seal: &Seal, + difficulty: Self::Difficulty, + ) -> Result>; + /// Mine a seal that satisfies the given difficulty. + fn mine( + &self, + parent: &BlockId, + pre_hash: &H256, + difficulty: Self::Difficulty, + round: u32, + ) -> Result, Error>; +} + +/// A verifier for PoW blocks. +pub struct PowVerifier, C, S, Algorithm> { + client: Arc, + algorithm: Algorithm, + inherent_data_providers: inherents::InherentDataProviders, + select_chain: Option, + check_inherents_after: <::Header as HeaderT>::Number, +} + +impl, C, S, Algorithm> PowVerifier { + pub fn new( + client: Arc, + algorithm: Algorithm, + check_inherents_after: <::Header as HeaderT>::Number, + select_chain: Option, + inherent_data_providers: inherents::InherentDataProviders, + ) -> Self { + Self { client, algorithm, inherent_data_providers, select_chain, check_inherents_after } + } + + fn check_header( + &self, + mut header: B::Header, + parent_block_id: BlockId, + ) -> Result<(B::Header, Algorithm::Difficulty, DigestItem), Error> where + Algorithm: PowAlgorithm, + { + let hash = header.hash(); + + let (seal, inner_seal) = match header.digest_mut().pop() { + Some(DigestItem::Seal(id, seal)) => { + if id == POW_ENGINE_ID { + (DigestItem::Seal(id, seal.clone()), seal) + } else { + return Err(Error::WrongEngine(id)) + } + }, + _ => return Err(Error::HeaderUnsealed(hash)), + }; + + let pre_hash = header.hash(); + let difficulty = self.algorithm.difficulty(&parent_block_id)?; + + if !self.algorithm.verify( + &parent_block_id, + &pre_hash, + &inner_seal, + difficulty, + )? { + return Err(Error::InvalidSeal); + } + + Ok((header, difficulty, seal)) + } + + fn check_inherents( + &self, + block: B, + block_id: BlockId, + inherent_data: InherentData, + timestamp_now: u64, + ) -> Result<(), Error> where + C: ProvideRuntimeApi, C::Api: BlockBuilderApi + { + const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; + + if *block.header().number() < self.check_inherents_after { + return Ok(()) + } + + let inherent_res = self.client.runtime_api().check_inherents( + &block_id, + block, + inherent_data, + ).map_err(Error::Client)?; + + if !inherent_res.ok() { + inherent_res + .into_errors() + .try_for_each(|(i, e)| match TIError::try_from(&i, &e) { + Some(TIError::ValidAtTimestamp(timestamp)) => { + if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { + return Err(Error::TooFarInFuture); + } + + Ok(()) + }, + Some(TIError::Other(e)) => Err(Error::Runtime(e)), + None => Err(Error::CheckInherents( + self.inherent_data_providers.error_to_string(&i, &e) + )), + }) + } else { + Ok(()) + } + } +} + +impl, C, S, Algorithm> Verifier for PowVerifier where + C: ProvideRuntimeApi + Send + Sync + HeaderBackend + AuxStore + ProvideCache + BlockOf, + C::Api: BlockBuilderApi, + S: SelectChain, + Algorithm: PowAlgorithm + Send + Sync, +{ + fn verify( + &mut self, + origin: BlockOrigin, + header: B::Header, + justification: Option, + mut body: Option>, + ) -> Result<(BlockImportParams, Option)>>), String> { + let inherent_data = self.inherent_data_providers + .create_inherent_data().map_err(String::from)?; + let timestamp_now = inherent_data.timestamp_inherent_data().map_err(String::from)?; + + let best_hash = match self.select_chain.as_ref() { + Some(select_chain) => select_chain.best_chain() + .map_err(|e| format!("Fetch best chain failed via select chain: {:?}", e))? + .hash(), + None => self.client.info().best_hash, + }; + let hash = header.hash(); + let parent_hash = *header.parent_hash(); + let best_aux = PowAux::read::<_, B>(self.client.as_ref(), &best_hash)?; + let mut aux = PowAux::read::<_, B>(self.client.as_ref(), &parent_hash)?; + + let (checked_header, difficulty, seal) = self.check_header( + header, + BlockId::Hash(parent_hash), + )?; + aux.difficulty = difficulty; + aux.total_difficulty.increment(difficulty); + + if let Some(inner_body) = body.take() { + let block = B::new(checked_header.clone(), inner_body); + + self.check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + timestamp_now + )?; + + let (_, inner_body) = block.deconstruct(); + body = Some(inner_body); + } + let key = aux_key(&hash); + let import_block = BlockImportParams { + origin, + header: checked_header, + post_digests: vec![seal], + body, + finalized: false, + justification, + auxiliary: vec![(key, Some(aux.encode()))], + fork_choice: ForkChoiceStrategy::Custom(aux.total_difficulty > best_aux.total_difficulty), + }; + + Ok((import_block, None)) + } +} + +/// Register the PoW inherent data provider, if not registered already. +pub fn register_pow_inherent_data_provider( + inherent_data_providers: &InherentDataProviders, +) -> Result<(), consensus_common::Error> { + if !inherent_data_providers.has_provider(&srml_timestamp::INHERENT_IDENTIFIER) { + inherent_data_providers + .register_provider(srml_timestamp::InherentDataProvider) + .map_err(Into::into) + .map_err(consensus_common::Error::InherentData) + } else { + Ok(()) + } +} + +/// The PoW import queue type. +pub type PowImportQueue = BasicQueue; + +/// Import queue for PoW engine. +pub fn import_queue( + block_import: BoxBlockImport, + client: Arc, + algorithm: Algorithm, + check_inherents_after: <::Header as HeaderT>::Number, + select_chain: Option, + inherent_data_providers: InherentDataProviders, +) -> Result, consensus_common::Error> where + B: BlockT, + C: ProvideRuntimeApi + HeaderBackend + BlockOf + ProvideCache + AuxStore, + C: Send + Sync + AuxStore + 'static, + C::Api: BlockBuilderApi, + Algorithm: PowAlgorithm + Send + Sync + 'static, + S: SelectChain + 'static, +{ + register_pow_inherent_data_provider(&inherent_data_providers)?; + + let verifier = PowVerifier::new( + client.clone(), + algorithm, + check_inherents_after, + select_chain, + inherent_data_providers, + ); + + Ok(BasicQueue::new( + verifier, + block_import, + None, + None + )) +} + +/// Start the background mining thread for PoW. Note that because PoW mining +/// is CPU-intensive, it is not possible to use an async future to define this. +/// However, it's not recommended to use background threads in the rest of the +/// codebase. +/// +/// `preruntime` is a parameter that allows a custom additional pre-runtime +/// digest to be inserted for blocks being built. This can encode authorship +/// information, or just be a graffiti. `round` is for number of rounds the +/// CPU miner runs each time. This parameter should be tweaked so that each +/// mining round is within sub-second time. +pub fn start_mine, C, Algorithm, E, SO, S>( + mut block_import: BoxBlockImport, + client: Arc, + algorithm: Algorithm, + mut env: E, + preruntime: Option>, + round: u32, + mut sync_oracle: SO, + build_time: std::time::Duration, + select_chain: Option, + inherent_data_providers: inherents::InherentDataProviders, +) where + C: HeaderBackend + AuxStore + 'static, + Algorithm: PowAlgorithm + Send + Sync + 'static, + E: Environment + Send + Sync + 'static, + E::Error: std::fmt::Debug, + SO: SyncOracle + Send + Sync + 'static, + S: SelectChain + 'static, +{ + if let Err(_) = register_pow_inherent_data_provider(&inherent_data_providers) { + warn!("Registering inherent data provider for timestamp failed"); + } + + thread::spawn(move || { + loop { + match mine_loop( + &mut block_import, + client.as_ref(), + &algorithm, + &mut env, + preruntime.as_ref(), + round, + &mut sync_oracle, + build_time.clone(), + select_chain.as_ref(), + &inherent_data_providers + ) { + Ok(()) => (), + Err(e) => error!( + "Mining block failed with {:?}. Sleep for 1 second before restarting...", + e + ), + } + std::thread::sleep(std::time::Duration::new(1, 0)); + } + }); +} + +fn mine_loop, C, Algorithm, E, SO, S>( + block_import: &mut BoxBlockImport, + client: &C, + algorithm: &Algorithm, + env: &mut E, + preruntime: Option<&Vec>, + round: u32, + sync_oracle: &mut SO, + build_time: std::time::Duration, + select_chain: Option<&S>, + inherent_data_providers: &inherents::InherentDataProviders, +) -> Result<(), Error> where + C: HeaderBackend + AuxStore, + Algorithm: PowAlgorithm, + E: Environment, + E::Error: std::fmt::Debug, + SO: SyncOracle, + S: SelectChain, +{ + 'outer: loop { + if sync_oracle.is_major_syncing() { + debug!(target: "pow", "Skipping proposal due to sync."); + std::thread::sleep(std::time::Duration::new(1, 0)); + continue 'outer + } + + let (best_hash, best_header) = match select_chain { + Some(select_chain) => { + let header = select_chain.best_chain() + .map_err(Error::BestHeaderSelectChain)?; + let hash = header.hash(); + (hash, header) + }, + None => { + let hash = client.info().best_hash; + let header = client.header(BlockId::Hash(hash)) + .map_err(Error::BestHeader)? + .ok_or(Error::NoBestHeader)?; + (hash, header) + }, + }; + let mut aux = PowAux::read(client, &best_hash)?; + let mut proposer = env.init(&best_header) + .map_err(|e| Error::Environment(format!("{:?}", e)))?; + + let inherent_data = inherent_data_providers + .create_inherent_data().map_err(Error::CreateInherents)?; + let mut inherent_digest = Digest::default(); + if let Some(preruntime) = &preruntime { + inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, preruntime.to_vec())); + } + let block = futures::executor::block_on(proposer.propose( + inherent_data, + inherent_digest, + build_time.clone(), + )).map_err(|e| Error::BlockProposingError(format!("{:?}", e)))?; + + let (header, body) = block.deconstruct(); + let (difficulty, seal) = { + let difficulty = algorithm.difficulty( + &BlockId::Hash(best_hash), + )?; + + loop { + let seal = algorithm.mine( + &BlockId::Hash(best_hash), + &header.hash(), + difficulty, + round, + )?; + + if let Some(seal) = seal { + break (difficulty, seal) + } + + if best_hash != client.info().best_hash { + continue 'outer + } + } + }; + + aux.difficulty = difficulty; + aux.total_difficulty.increment(difficulty); + let hash = { + let mut header = header.clone(); + header.digest_mut().push(DigestItem::Seal(POW_ENGINE_ID, seal.clone())); + header.hash() + }; + + let key = aux_key(&hash); + let best_hash = match select_chain { + Some(select_chain) => select_chain.best_chain() + .map_err(Error::BestHashSelectChain)? + .hash(), + None => client.info().best_hash, + }; + let best_aux = PowAux::::read(client, &best_hash)?; + + // if the best block has changed in the meantime drop our proposal + if best_aux.total_difficulty > aux.total_difficulty { + continue 'outer + } + + let import_block = BlockImportParams { + origin: BlockOrigin::Own, + header, + justification: None, + post_digests: vec![DigestItem::Seal(POW_ENGINE_ID, seal)], + body: Some(body), + finalized: false, + auxiliary: vec![(key, Some(aux.encode()))], + fork_choice: ForkChoiceStrategy::Custom(true), + }; + + block_import.import_block(import_block, HashMap::default()) + .map_err(|e| Error::BlockBuiltError(best_hash, e))?; + } +} diff --git a/core/consensus/rhd/Cargo.toml b/core/consensus/rhd/Cargo.toml index 801605c3f64ca2c5e4f25ebbb24074330d3c4101..48d0840b5592d5403f028008f7b5fafcaee67f85 100644 --- a/core/consensus/rhd/Cargo.toml +++ b/core/consensus/rhd/Cargo.toml @@ -6,8 +6,8 @@ description = "Rhododendron Round-Based consensus-algorithm for substrate" edition = "2018" [dependencies] -derive_more = "0.14.0" -futures = "0.1.17" +derive_more = "0.15.0" +futures = "0.1.29" codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../primitives" } consensus = { package = "substrate-consensus-common", path = "../common" } @@ -18,11 +18,11 @@ srml-system = { path = "../../../srml/system" } sr-primitives = { path = "../../sr-primitives" } runtime_version = { package = "sr-version", path = "../../sr-version" } runtime_io = { package = "sr-io", path = "../../sr-io" } -tokio = "0.1.7" +tokio = "0.1.22" parking_lot = "0.9.0" -log = "0.4" +log = "0.4.8" rhododendron = { version = "0.7.0", features = ["codec"] } -exit-future = "0.1" +exit-future = "0.1.4" [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../keyring" } diff --git a/core/consensus/slots/Cargo.toml b/core/consensus/slots/Cargo.toml index f74837a62f9de36970ccea2e8915276a4956c5ec..4074242502b7192e26c13372eb77411d0bd32ff0 100644 --- a/core/consensus/slots/Cargo.toml +++ b/core/consensus/slots/Cargo.toml @@ -4,18 +4,20 @@ version = "2.0.0" authors = ["Parity Technologies "] description = "Generic slots-based utilities for consensus" edition = "2018" +build = "build.rs" [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0" } client = { package = "substrate-client", path = "../../client" } primitives = { package = "substrate-primitives", path = "../../primitives" } sr-primitives = { path = "../../sr-primitives" } +substrate-telemetry = { path = "../../telemetry" } consensus_common = { package = "substrate-consensus-common", path = "../common" } inherents = { package = "substrate-inherents", path = "../../inherents" } -futures-preview = "=0.3.0-alpha.17" -futures-timer = "0.2.1" +futures-preview = "0.3.0-alpha.19" +futures-timer = "0.4.0" parking_lot = "0.9.0" -log = "0.4" +log = "0.4.8" [dev-dependencies] test-client = { package = "substrate-test-runtime-client", path = "../../test-runtime/client" } diff --git a/build.rs b/core/consensus/slots/build.rs similarity index 71% rename from build.rs rename to core/consensus/slots/build.rs index 273700c525c883579880be28b231a5f14e43c6d7..36730271c715eaa1daf6e957e4b1e01443a2bc7a 100644 --- a/build.rs +++ b/core/consensus/slots/build.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,11 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use vergen::{ConstantsFlags, generate_cargo_keys}; - -const ERROR_MSG: &str = "Failed to generate metadata files"; +use std::env; fn main() { - generate_cargo_keys(ConstantsFlags::all()).expect(ERROR_MSG); - println!("cargo:rerun-if-changed=.git/HEAD"); + if let Ok(profile) = env::var("PROFILE") { + println!("cargo:rustc-cfg=build_type=\"{}\"", profile); + } } diff --git a/core/consensus/slots/src/aux_schema.rs b/core/consensus/slots/src/aux_schema.rs index 1d54cb5c2ee6cf05e52edb70c6f6fea5621bb180..186288c17443227ec7b1661f758e73565a119a3b 100644 --- a/core/consensus/slots/src/aux_schema.rs +++ b/core/consensus/slots/src/aux_schema.rs @@ -38,7 +38,7 @@ fn load_decode(backend: &C, key: &[u8]) -> ClientResult> None => Ok(None), Some(t) => T::decode(&mut &t[..]) .map_err( - |e| ClientError::Backend(format!("Slots DB is corrupted. Decode error: {}", e.what())).into(), + |e| ClientError::Backend(format!("Slots DB is corrupted. Decode error: {}", e.what())), ) .map(Some) } diff --git a/core/consensus/slots/src/lib.rs b/core/consensus/slots/src/lib.rs index fc0134f746af79a72ec1224515ac595e3b0b1006..e33d00d25531f7c9d30e9b9ef59e6f37f8a8c906 100644 --- a/core/consensus/slots/src/lib.rs +++ b/core/consensus/slots/src/lib.rs @@ -31,13 +31,16 @@ use slots::Slots; pub use aux_schema::{check_equivocation, MAX_SLOT_CAPACITY, PRUNING_BOUND}; use codec::{Decode, Encode}; -use consensus_common::{SyncOracle, SelectChain}; +use consensus_common::{BlockImport, Proposer, SyncOracle, SelectChain}; use futures::{prelude::*, future::{self, Either}}; +use futures_timer::Delay; use inherents::{InherentData, InherentDataProviders}; use log::{debug, error, info, warn}; use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ApiRef, Block as BlockT, ProvideRuntimeApi}; -use std::{fmt::Debug, ops::Deref}; +use sr_primitives::traits::{ApiRef, Block as BlockT, Header, ProvideRuntimeApi}; +use std::{fmt::Debug, ops::Deref, pin::Pin, sync::Arc}; +use substrate_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO}; +use parking_lot::Mutex; /// A worker that should be invoked at every new slot. pub trait SlotWorker { @@ -49,6 +52,212 @@ pub trait SlotWorker { fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) -> Self::OnSlot; } +/// A skeleton implementation for `SlotWorker` which tries to claim a slot at +/// its beginning and tries to produce a block if successfully claimed, timing +/// out if block production takes too long. +pub trait SimpleSlotWorker { + /// A handle to a `BlockImport`. + type BlockImport: BlockImport + Send + 'static; + + /// A handle to a `SyncOracle`. + type SyncOracle: SyncOracle; + + /// The type of proposer to use to build blocks. + type Proposer: Proposer; + + /// Data associated with a slot claim. + type Claim: Send + 'static; + + /// Epoch data necessary for authoring. + type EpochData; + + /// The logging target to use when logging messages. + fn logging_target(&self) -> &'static str; + + /// A handle to a `BlockImport`. + fn block_import(&self) -> Arc>; + + /// Returns the epoch data necessary for authoring. For time-dependent epochs, + /// use the provided slot number as a canonical source of time. + fn epoch_data(&self, header: &B::Header, slot_number: u64) -> Result; + + /// Returns the number of authorities given the epoch data. + fn authorities_len(&self, epoch_data: &Self::EpochData) -> usize; + + /// Tries to claim the given slot, returning an object with claim data if successful. + fn claim_slot( + &self, + header: &B::Header, + slot_number: u64, + epoch_data: &Self::EpochData, + ) -> Option; + + /// Return the pre digest data to include in a block authored with the given claim. + fn pre_digest_data(&self, slot_number: u64, claim: &Self::Claim) -> Vec>; + + /// Returns a function which produces a `BlockImportParams`. + fn block_import_params(&self) -> Box, + Self::Claim, + ) -> consensus_common::BlockImportParams + Send>; + + /// Whether to force authoring if offline. + fn force_authoring(&self) -> bool; + + /// Returns a handle to a `SyncOracle`. + fn sync_oracle(&mut self) -> &mut Self::SyncOracle; + + /// Returns a `Proposer` to author on top of the given block. + fn proposer(&mut self, block: &B::Header) -> Result; + + /// Implements the `on_slot` functionality from `SlotWorker`. + fn on_slot(&mut self, chain_head: B::Header, slot_info: SlotInfo) + -> Pin> + Send>> where + Self: Send + Sync, + >::Create: Unpin + Send + 'static, + { + let (timestamp, slot_number, slot_duration) = + (slot_info.timestamp, slot_info.number, slot_info.duration); + + let epoch_data = match self.epoch_data(&chain_head, slot_number) { + Ok(epoch_data) => epoch_data, + Err(err) => { + warn!("Unable to fetch epoch data at block {:?}: {:?}", chain_head.hash(), err); + + telemetry!( + CONSENSUS_WARN; "slots.unable_fetching_authorities"; + "slot" => ?chain_head.hash(), + "err" => ?err, + ); + + return Box::pin(future::ready(Ok(()))); + } + }; + + let authorities_len = self.authorities_len(&epoch_data); + + if !self.force_authoring() && self.sync_oracle().is_offline() && authorities_len > 1 { + debug!(target: self.logging_target(), "Skipping proposal slot. Waiting for the network."); + telemetry!( + CONSENSUS_DEBUG; + "slots.skipping_proposal_slot"; + "authorities_len" => authorities_len, + ); + + return Box::pin(future::ready(Ok(()))); + } + + let claim = match self.claim_slot(&chain_head, slot_number, &epoch_data) { + None => return Box::pin(future::ready(Ok(()))), + Some(claim) => claim, + }; + + debug!( + target: self.logging_target(), "Starting authorship at slot {}; timestamp = {}", + slot_number, + timestamp, + ); + + telemetry!(CONSENSUS_DEBUG; "slots.starting_authorship"; + "slot_num" => slot_number, + "timestamp" => timestamp, + ); + + let mut proposer = match self.proposer(&chain_head) { + Ok(proposer) => proposer, + Err(err) => { + warn!("Unable to author block in slot {:?}: {:?}", slot_number, err); + + telemetry!(CONSENSUS_WARN; "slots.unable_authoring_block"; + "slot" => slot_number, "err" => ?err + ); + + return Box::pin(future::ready(Ok(()))); + }, + }; + + let remaining_duration = slot_info.remaining_duration(); + let logs = self.pre_digest_data(slot_number, &claim); + + // deadline our production to approx. the end of the slot + let proposal_work = futures::future::select( + proposer.propose( + slot_info.inherent_data, + sr_primitives::generic::Digest { + logs, + }, + remaining_duration, + ).map_err(|e| consensus_common::Error::ClientImport(format!("{:?}", e))), + Delay::new(remaining_duration) + .map_err(consensus_common::Error::FaultyTimer) + ).map(|v| match v { + futures::future::Either::Left((b, _)) => b.map(|b| (b, claim)), + futures::future::Either::Right((Ok(_), _)) => + Err(consensus_common::Error::ClientImport("Timeout in the Slots proposer".into())), + futures::future::Either::Right((Err(err), _)) => Err(err), + }); + + let block_import_params_maker = self.block_import_params(); + let block_import = self.block_import(); + let logging_target = self.logging_target(); + + Box::pin(proposal_work.map_ok(move |(block, claim)| { + // minor hack since we don't have access to the timestamp + // that is actually set by the proposer. + let slot_after_building = SignedDuration::default().slot_now(slot_duration); + if slot_after_building != slot_number { + info!("Discarding proposal for slot {}; block production took too long", slot_number); + // If the node was compiled with debug, tell the user to use release optimizations. + #[cfg(build_type="debug")] + info!("Recompile your node in `--release` mode to mitigate this problem."); + telemetry!(CONSENSUS_INFO; "slots.discarding_proposal_took_too_long"; + "slot" => slot_number, + ); + + return; + } + + let (header, body) = block.deconstruct(); + let header_num = *header.number(); + let header_hash = header.hash(); + let parent_hash = *header.parent_hash(); + + let block_import_params = block_import_params_maker( + header, + &header_hash, + body, + claim, + ); + + info!("Pre-sealed block for proposal at {}. Hash now {:?}, previously {:?}.", + header_num, + block_import_params.post_header().hash(), + header_hash, + ); + + telemetry!(CONSENSUS_INFO; "slots.pre_sealed_block"; + "header_num" => ?header_num, + "hash_now" => ?block_import_params.post_header().hash(), + "hash_previously" => ?header_hash, + ); + + if let Err(err) = block_import.lock().import_block(block_import_params, Default::default()) { + warn!(target: logging_target, + "Error with block built on {:?}: {:?}", + parent_hash, + err, + ); + + telemetry!(CONSENSUS_WARN; "slots.err_with_block_built_on"; + "hash" => ?parent_hash, "err" => ?err, + ); + } + })) + } +} + /// Slot compatible inherent data. pub trait SlotCompatible { /// Extract timestamp and slot from inherent data. @@ -151,7 +360,8 @@ impl SlotData for u64 { } /// A slot duration. Create with `get_or_compute`. -// The internal member should stay private here. +// The internal member should stay private here to maintain invariants of +// `get_or_compute`. #[derive(Clone, Copy, Debug, Encode, Decode, Hash, PartialOrd, Ord, PartialEq, Eq)] pub struct SlotDuration(T); @@ -189,11 +399,10 @@ impl SlotDuration { Some(v) => ::decode(&mut &v[..]) .map(SlotDuration) .map_err(|_| { - ::client::error::Error::Backend({ + client::error::Error::Backend({ error!(target: "slots", "slot duration kept in invalid format"); - format!("slot duration kept in invalid format") + "slot duration kept in invalid format".to_string() }) - .into() }), None => { use sr_primitives::traits::Zero; diff --git a/core/consensus/uncles/Cargo.toml b/core/consensus/uncles/Cargo.toml index 98b8adee8b7930ef94859492a84b632b4706b887..48203248709291e7f503b76887a46fd5b04ccb1e 100644 --- a/core/consensus/uncles/Cargo.toml +++ b/core/consensus/uncles/Cargo.toml @@ -12,4 +12,4 @@ sr-primitives = { path = "../../sr-primitives" } srml-authorship = { path = "../../../srml/authorship" } consensus_common = { package = "substrate-consensus-common", path = "../common" } inherents = { package = "substrate-inherents", path = "../../inherents" } -log = "0.4" +log = "0.4.8" diff --git a/core/executor/Cargo.toml b/core/executor/Cargo.toml index a4707fb89e3d408880db28cd7fb008e951c2a0f9..c5604d50e4a0f2a9ad0747ab15ecef297eee2f1b 100644 --- a/core/executor/Cargo.toml +++ b/core/executor/Cargo.toml @@ -5,32 +5,53 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -derive_more = "0.14.0" +derive_more = "0.15.0" codec = { package = "parity-scale-codec", version = "1.0.0" } runtime_io = { package = "sr-io", path = "../sr-io" } primitives = { package = "substrate-primitives", path = "../primitives" } trie = { package = "substrate-trie", path = "../trie" } serializer = { package = "substrate-serializer", path = "../serializer" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } runtime_version = { package = "sr-version", path = "../sr-version" } panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } -wasmi = "0.5.0" -parity-wasm = "0.31" -byteorder = "1.3" -lazy_static = "1.3" +wasmi = "0.5.1" +parity-wasm = "0.40.3" +lazy_static = "1.4.0" +wasm-interface = { package = "substrate-wasm-interface", path = "../wasm-interface" } +externalities = { package = "substrate-externalities", path = "../externalities" } parking_lot = "0.9.0" -log = "0.4" -libsecp256k1 = "0.2.1" -tiny-keccak = "1.4.2" +log = "0.4.8" +libsecp256k1 = "0.3.0" +tiny-keccak = "1.5.0" + +cranelift-codegen = { version = "0.46.1", optional = true } +cranelift-entity = { version = "0.46.1", optional = true } +cranelift-frontend = { version = "0.46.1", optional = true } +cranelift-native = { version = "0.46.1", optional = true } +cranelift-wasm = { version = "0.46.1", optional = true } +wasmtime-environ = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" } +wasmtime-jit = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" } +wasmtime-runtime = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" } [dev-dependencies] -assert_matches = "1.1" -wabt = "~0.7.4" -hex-literal = "0.2.0" +assert_matches = "1.3.0" +wabt = "0.9.2" +hex-literal = "0.2.1" runtime-test = { package = "substrate-runtime-test", path = "runtime-test" } substrate-client = { path = "../client" } substrate-offchain = { path = "../offchain/" } +state_machine = { package = "substrate-state-machine", path = "../state-machine" } +test-case = "0.3.3" [features] default = [] wasm-extern-trace = [] +wasmtime = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", +] diff --git a/core/executor/runtime-test/Cargo.toml b/core/executor/runtime-test/Cargo.toml index 28a0ed2b874aaa5fbf71ef4b17ea192524fa8a45..72041218bf9f2ac9959e85d0e63d34ff8e94788f 100644 --- a/core/executor/runtime-test/Cargo.toml +++ b/core/executor/runtime-test/Cargo.toml @@ -10,11 +10,11 @@ rstd = { package = "sr-std", path = "../../sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../../sr-io", default-features = false } sandbox = { package = "sr-sandbox", path = "../../sr-sandbox", default-features = false } primitives = { package = "substrate-primitives", path = "../../primitives", default-features = false } +sr-primitives = { package = "sr-primitives", path = "../../sr-primitives", default-features = false } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.2", path = "../../utils/wasm-builder-runner" } +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4", path = "../../utils/wasm-builder-runner" } [features] default = [ "std" ] -std = [] -no_std = [] +std = ["runtime_io/std", "sandbox/std", "rstd/std"] diff --git a/core/executor/runtime-test/build.rs b/core/executor/runtime-test/build.rs index 86bc3ad7fab28626123baf07d64780fa4fc5a053..68e5205f0c7a867bda0b7bad5efd2252a9fd33f9 100644 --- a/core/executor/runtime-test/build.rs +++ b/core/executor/runtime-test/build.rs @@ -21,7 +21,7 @@ fn main() { "wasm_binary.rs", WasmBuilderSource::CratesOrPath { path: "../../utils/wasm-builder", - version: "1.0.4", + version: "1.0.8", }, // This instructs LLD to export __heap_base as a global variable, which is used by the // external memory allocator. diff --git a/core/executor/runtime-test/src/lib.rs b/core/executor/runtime-test/src/lib.rs index 5e276a88141684eb520cea68bd0a114117a67881..61eca8dd4e23ffa37a1081b9aad9c14f5388b151 100644 --- a/core/executor/runtime-test/src/lib.rs +++ b/core/executor/runtime-test/src/lib.rs @@ -5,47 +5,23 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use rstd::{vec::Vec, slice, vec}; +#[cfg(not(feature = "std"))] +use rstd::{vec::Vec, vec}; +#[cfg(not(feature = "std"))] use runtime_io::{ - set_storage, storage, clear_prefix, print, blake2_128, blake2_256, - twox_128, twox_256, ed25519_verify, sr25519_verify, ordered_trie_root + set_storage, storage, clear_prefix, blake2_128, blake2_256, + twox_128, twox_256, ed25519_verify, sr25519_verify, }; +#[cfg(not(feature = "std"))] +use sr_primitives::{print, traits::{BlakeTwo256, Hash}}; +#[cfg(not(feature = "std"))] use primitives::{ed25519, sr25519}; -macro_rules! impl_stubs { - ( $( $new_name:ident => $invoke:expr, )* ) => { - $( - impl_stubs!(@METHOD $new_name => $invoke); - )* - }; - ( @METHOD $new_name:ident => $invoke:expr ) => { - #[no_mangle] - pub fn $new_name(input_data: *mut u8, input_len: usize) -> u64 { - let input: &[u8] = if input_len == 0 { - &[0u8; 0] - } else { - unsafe { - slice::from_raw_parts(input_data, input_len) - } - }; - - let output: Vec = $invoke(input); - let res = output.as_ptr() as u64 + ((output.len() as u64) << 32); - - // Leak the output vector to avoid it being freed. - // This is fine in a WASM context since the heap - // will be discarded after the call. - rstd::mem::forget(output); - res - } - }; -} - -impl_stubs!( - test_data_in => |input| { +primitives::wasm_export_functions! { + fn test_data_in(input: Vec) -> Vec { print("set_storage"); - set_storage(b"input", input); + set_storage(b"input", &input); print("storage"); let foo = storage(b"foo").unwrap(); @@ -55,25 +31,44 @@ impl_stubs!( print("finished!"); b"all ok!".to_vec() - }, - test_clear_prefix => |input| { - clear_prefix(input); + } + + fn test_clear_prefix(input: Vec) -> Vec { + clear_prefix(&input); b"all ok!".to_vec() - }, - test_empty_return => |_| Vec::new(), - test_exhaust_heap => |_| Vec::with_capacity(16777216), - test_panic => |_| panic!("test panic"), - test_conditional_panic => |input: &[u8]| { + } + + fn test_empty_return() {} + + fn test_exhaust_heap() -> Vec { Vec::with_capacity(16777216) } + + fn test_panic() { panic!("test panic") } + + fn test_conditional_panic(input: Vec) -> Vec { if input.len() > 0 { panic!("test panic") } - input.to_vec() - }, - test_blake2_256 => |input| blake2_256(input).to_vec(), - test_blake2_128 => |input| blake2_128(input).to_vec(), - test_twox_256 => |input| twox_256(input).to_vec(), - test_twox_128 => |input| twox_128(input).to_vec(), - test_ed25519_verify => |input: &[u8]| { + + input + } + + fn test_blake2_256(input: Vec) -> Vec { + blake2_256(&input).to_vec() + } + + fn test_blake2_128(input: Vec) -> Vec { + blake2_128(&input).to_vec() + } + + fn test_twox_256(input: Vec) -> Vec { + twox_256(&input).to_vec() + } + + fn test_twox_128(input: Vec) -> Vec { + twox_128(&input).to_vec() + } + + fn test_ed25519_verify(input: Vec) -> bool { let mut pubkey = [0; 32]; let mut sig = [0; 64]; @@ -81,9 +76,10 @@ impl_stubs!( sig.copy_from_slice(&input[32..96]); let msg = b"all ok!"; - [ed25519_verify(&ed25519::Signature(sig), &msg[..], &ed25519::Public(pubkey)) as u8].to_vec() - }, - test_sr25519_verify => |input: &[u8]| { + ed25519_verify(&ed25519::Signature(sig), &msg[..], &ed25519::Public(pubkey)) + } + + fn test_sr25519_verify(input: Vec) -> bool { let mut pubkey = [0; 32]; let mut sig = [0; 64]; @@ -91,34 +87,36 @@ impl_stubs!( sig.copy_from_slice(&input[32..96]); let msg = b"all ok!"; - [sr25519_verify(&sr25519::Signature(sig), &msg[..], &sr25519::Public(pubkey)) as u8].to_vec() - }, - test_ordered_trie_root => |_| { - ordered_trie_root::( - &[ - &b"zero"[..], - &b"one"[..], - &b"two"[..], - ] + sr25519_verify(&sr25519::Signature(sig), &msg[..], &sr25519::Public(pubkey)) + } + + fn test_ordered_trie_root() -> Vec { + BlakeTwo256::ordered_trie_root( + vec![ + b"zero"[..].into(), + b"one"[..].into(), + b"two"[..].into(), + ], ).as_ref().to_vec() - }, - test_sandbox => |code: &[u8]| { - let ok = execute_sandboxed(code, &[]).is_ok(); - [ok as u8].to_vec() - }, - test_sandbox_args => |code: &[u8]| { - let ok = execute_sandboxed( - code, + } + + fn test_sandbox(code: Vec) -> bool { + execute_sandboxed(&code, &[]).is_ok() + } + + fn test_sandbox_args(code: Vec) -> bool { + execute_sandboxed( + &code, &[ sandbox::TypedValue::I32(0x12345678), sandbox::TypedValue::I64(0x1234567887654321), - ] - ).is_ok(); - [ok as u8].to_vec() - }, - test_sandbox_return_val => |code: &[u8]| { + ], + ).is_ok() + } + + fn test_sandbox_return_val(code: Vec) -> bool { let ok = match execute_sandboxed( - code, + &code, &[ sandbox::TypedValue::I32(0x1336), ] @@ -126,41 +124,43 @@ impl_stubs!( Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) => true, _ => false, }; - [ok as u8].to_vec() - }, - test_sandbox_instantiate => |code: &[u8]| { + + ok + } + + fn test_sandbox_instantiate(code: Vec) -> u8 { let env_builder = sandbox::EnvironmentDefinitionBuilder::new(); - let code = match sandbox::Instance::new(code, &env_builder, &mut ()) { + let code = match sandbox::Instance::new(&code, &env_builder, &mut ()) { Ok(_) => 0, Err(sandbox::Error::Module) => 1, Err(sandbox::Error::Execution) => 2, Err(sandbox::Error::OutOfBounds) => 3, }; - [code].to_vec() - }, - test_offchain_local_storage => |_| { + + code + } + + fn test_offchain_local_storage() -> bool { let kind = primitives::offchain::StorageKind::PERSISTENT; assert_eq!(runtime_io::local_storage_get(kind, b"test"), None); runtime_io::local_storage_set(kind, b"test", b"asd"); assert_eq!(runtime_io::local_storage_get(kind, b"test"), Some(b"asd".to_vec())); let res = runtime_io::local_storage_compare_and_set(kind, b"test", Some(b"asd"), b""); - assert_eq!(res, true); assert_eq!(runtime_io::local_storage_get(kind, b"test"), Some(b"".to_vec())); + res + } - [0].to_vec() - }, - test_offchain_local_storage_with_none => |_| { + fn test_offchain_local_storage_with_none() { let kind = primitives::offchain::StorageKind::PERSISTENT; assert_eq!(runtime_io::local_storage_get(kind, b"test"), None); let res = runtime_io::local_storage_compare_and_set(kind, b"test", None, b"value"); assert_eq!(res, true); assert_eq!(runtime_io::local_storage_get(kind, b"test"), Some(b"value".to_vec())); + } - [0].to_vec() - }, - test_offchain_http => |_| { + fn test_offchain_http() -> bool { use primitives::offchain::HttpRequestStatus; let run = || -> Option<()> { let id = runtime_io::http_request_start("POST", "http://localhost:12345", &[]).ok()?; @@ -181,16 +181,23 @@ impl_stubs!( Some(()) }; - [if run().is_some() { 0 } else { 1 }].to_vec() - }, -); + run().is_some() + } + } -fn execute_sandboxed(code: &[u8], args: &[sandbox::TypedValue]) -> Result { +#[cfg(not(feature = "std"))] +fn execute_sandboxed( + code: &[u8], + args: &[sandbox::TypedValue], +) -> Result { struct State { counter: u32, } - fn env_assert(_e: &mut State, args: &[sandbox::TypedValue]) -> Result { + fn env_assert( + _e: &mut State, + args: &[sandbox::TypedValue], + ) -> Result { if args.len() != 1 { return Err(sandbox::HostError); } @@ -201,7 +208,10 @@ fn execute_sandboxed(code: &[u8], args: &[sandbox::TypedValue]) -> Result Result { + fn env_inc_counter( + e: &mut State, + args: &[sandbox::TypedValue], + ) -> Result { if args.len() != 1 { return Err(sandbox::HostError); } diff --git a/core/executor/src/allocator.rs b/core/executor/src/allocator.rs index 4cc8174f705b0840b143aaa3ad12251e763889e1..523499db71c6bdb13979b40d1ee198659fd995ab 100644 --- a/core/executor/src/allocator.rs +++ b/core/executor/src/allocator.rs @@ -15,14 +15,45 @@ // along with Substrate. If not, see . //! This module implements a freeing-bump allocator. -//! See more details at https://github.com/paritytech/substrate/issues/1615. +//! +//! The algorithm is as follows: +//! We store `N` linked list heads, where `N` is the total number of sizes +//! of allocations to support. A simple set is powers of two from 8 bytes +//! to 16,777,216 bytes (2^3 - 2^24 inclusive), resulting in `N = 22`: +//! +//! ```ignore +//! let mut heads [u64; N] = [0; N]; +//! fn size(n: u64) -> u64 { 8 << n } +//! let mut bumper = 0; +//! fn bump(n: u64) -> u64 { let res = bumper; bumper += n; res } +//! ``` +//! +//! We assume there is a slab of heap to be allocated: +//! +//! ```ignore +//! let mut heap = [0u8; HEAP_SIZE]; +//! ``` +//! +//! Whenever we allocate, we select the lowest linked list item size that +//! will fit the allocation (i.e. the next highest power of two). +//! We then check to see if the linked list is empty. If empty, we use +//! the bump allocator to get the allocation with an extra 8 bytes +//! preceding it. We initialise those preceding 8 bytes to identify the +//! list to which it belongs. If it is not empty, we unlink the first item from +//! the linked list and then reset the 8 preceding bytes so they now record +//! the identity of the linked list. +//! +//! To deallocate we use the preceding 8 bytes of the allocation to knit +//! back the allocation into the linked list from the head. use crate::error::{Error, Result}; use log::trace; -use wasmi::MemoryRef; -use wasmi::memory_units::Bytes; +use std::convert::{TryFrom, TryInto}; +use std::ops::Range; +use wasm_interface::{Pointer, WordSize}; -// The pointers need to be aligned to 8 bytes. +// The pointers need to be aligned to 8 bytes. This is because the +// maximum value type handled by wasm32 is u64. const ALIGNMENT: u32 = 8; // The pointer returned by `allocate()` needs to fulfill the alignment @@ -32,12 +63,15 @@ const ALIGNMENT: u32 = 8; // index) and then a subsequent item of 2^x bytes, where x = [3..24]. const N: usize = 22; const MAX_POSSIBLE_ALLOCATION: u32 = 16777216; // 2^24 bytes +const MIN_POSSIBLE_ALLOCATION: u32 = 8; + +// Each pointer is prefixed with 8 bytes, which identify the list index +// to which it belongs. +const PREFIX_SIZE: u32 = 8; pub struct FreeingBumpHeapAllocator { bumper: u32, heads: [u32; N], - heap: MemoryRef, - max_heap_size: u32, ptr_offset: u32, total_size: u32, } @@ -53,40 +87,41 @@ impl FreeingBumpHeapAllocator { /// /// # Arguments /// - /// - `mem` - reference to the linear memory instance on which this allocator operates. /// - `heap_base` - the offset from the beginning of the linear memory where the heap starts. - pub fn new(mem: MemoryRef, heap_base: u32) -> Self { - let current_size: Bytes = mem.current_size().into(); - let current_size = current_size.0 as u32; - - let mut ptr_offset = heap_base; - let padding = ptr_offset % ALIGNMENT; - if padding != 0 { - ptr_offset += ALIGNMENT - padding; - } - - let heap_size = current_size - ptr_offset; + pub fn new(heap_base: u32) -> Self { + // ptr_offset is the next alignment boundary on or after heap_base. + let ptr_offset = (heap_base + ALIGNMENT - 1) / ALIGNMENT * ALIGNMENT; FreeingBumpHeapAllocator { bumper: 0, heads: [0; N], - heap: mem, - max_heap_size: heap_size, - ptr_offset: ptr_offset, + ptr_offset, total_size: 0, } } /// Gets requested number of bytes to allocate and returns a pointer. /// The maximum size which can be allocated at once is 16 MiB. - pub fn allocate(&mut self, size: u32) -> Result { + /// There is no minimum size, but whatever size is passed into + /// this function is rounded to the next power of two. If the requested + /// size is below 8 bytes it will be rounded up to 8 bytes. + /// + /// # Arguments + /// + /// - `mem` - a slice representing the linear memory on which this allocator operates. + /// - `size` - size in bytes of the allocation request + pub fn allocate(&mut self, mem: &mut [u8], size: WordSize) -> Result> { + let mem_size = u32::try_from(mem.len()) + .expect("size of Wasm linear memory is <2^32"); + let max_heap_size = mem_size - self.ptr_offset; + if size > MAX_POSSIBLE_ALLOCATION { return Err(Error::RequestedAllocationTooLarge); } - let size = size.max(8); + let size = size.max(MIN_POSSIBLE_ALLOCATION); let item_size = size.next_power_of_two(); - if item_size + 8 + self.total_size > self.max_heap_size { + if item_size + PREFIX_SIZE + self.total_size > max_heap_size { return Err(Error::AllocatorOutOfSpace); } @@ -94,61 +129,72 @@ impl FreeingBumpHeapAllocator { let ptr: u32 = if self.heads[list_index] != 0 { // Something from the free list let item = self.heads[list_index]; - let four_bytes = self.get_heap_4bytes(item)?; - self.heads[list_index] = FreeingBumpHeapAllocator::le_bytes_to_u32(four_bytes); - item + 8 + let ptr = item + PREFIX_SIZE; + assert!( + ptr + item_size <= max_heap_size, + "Pointer is looked up in list of free entries, into which + only valid values are inserted; qed" + ); + + self.heads[list_index] = self.get_heap_u64(mem, item)? + .try_into() + .map_err(|_| error("read invalid free list pointer"))?; + ptr } else { // Nothing to be freed. Bump. - self.bump(item_size + 8) + 8 + self.bump(item_size, max_heap_size)? + PREFIX_SIZE }; - (1..8).try_for_each(|i| self.set_heap(ptr - i, 255))?; - - self.set_heap(ptr - 8, list_index as u8)?; + self.set_heap_u64(mem, ptr - PREFIX_SIZE, list_index as u64)?; - self.total_size = self.total_size + item_size + 8; + self.total_size = self.total_size + item_size + PREFIX_SIZE; trace!(target: "wasm-heap", "Heap size is {} bytes after allocation", self.total_size); - Ok(self.ptr_offset + ptr) + Ok(Pointer::new(self.ptr_offset + ptr)) } /// Deallocates the space which was allocated for a pointer. - pub fn deallocate(&mut self, ptr: u32) -> Result<()> { - let ptr = ptr - self.ptr_offset; - if ptr < 8 { + /// + /// # Arguments + /// + /// - `mem` - a slice representing the linear memory on which this allocator operates. + /// - `ptr` - pointer to the allocated chunk + pub fn deallocate(&mut self, mem: &mut [u8], ptr: Pointer) -> Result<()> { + let ptr = u32::from(ptr) - self.ptr_offset; + if ptr < PREFIX_SIZE { return Err(error("Invalid pointer for deallocation")); } - let list_index = usize::from(self.get_heap_byte(ptr - 8)?); - (1..8).try_for_each(|i| self.get_heap_byte(ptr - i).map(|byte| assert!(byte == 255)))?; - let tail = self.heads[list_index]; - self.heads[list_index] = ptr - 8; - - let mut slice = self.get_heap_4bytes(ptr - 8)?; - FreeingBumpHeapAllocator::write_u32_into_le_bytes(tail, &mut slice); - self.set_heap_4bytes(ptr - 8, slice)?; + let list_index: usize = self.get_heap_u64(mem, ptr - PREFIX_SIZE)? + .try_into() + .map_err(|_| error("read invalid list index"))?; + if list_index > self.heads.len() { + return Err(error("read invalid list index")); + } + self.set_heap_u64(mem, ptr - PREFIX_SIZE, self.heads[list_index] as u64)?; + self.heads[list_index] = ptr - PREFIX_SIZE; - let item_size = FreeingBumpHeapAllocator::get_item_size_from_index(list_index); - self.total_size = self.total_size.checked_sub(item_size as u32 + 8) + let item_size = Self::get_item_size_from_index(list_index); + self.total_size = self.total_size.checked_sub(item_size as u32 + PREFIX_SIZE) .ok_or_else(|| error("Unable to subtract from total heap size without overflow"))?; trace!(target: "wasm-heap", "Heap size is {} bytes after deallocation", self.total_size); Ok(()) } - fn bump(&mut self, n: u32) -> u32 { - let res = self.bumper; - self.bumper += n; - res - } - - fn le_bytes_to_u32(arr: [u8; 4]) -> u32 { - u32::from_le_bytes(arr) - } + /// Increases the `bumper` by `item_size + PREFIX_SIZE`. + /// + /// Returns the `bumper` from before the increase. + /// Returns an `Error::AllocatorOutOfSpace` if the operation + /// would exhaust the heap. + fn bump(&mut self, item_size: u32, max_heap_size: u32) -> Result { + if self.bumper + PREFIX_SIZE + item_size > max_heap_size { + return Err(Error::AllocatorOutOfSpace); + } - fn write_u32_into_le_bytes(bytes: u32, slice: &mut [u8]) { - let bytes: [u8; 4] = unsafe { std::mem::transmute::(bytes.to_le()) }; - for i in 0..4 { slice[i] = bytes[i]; } + let res = self.bumper; + self.bumper += item_size + PREFIX_SIZE; + Ok(res) } fn get_item_size_from_index(index: usize) -> usize { @@ -156,304 +202,329 @@ impl FreeingBumpHeapAllocator { 1 << 3 << index } - fn get_heap_4bytes(&mut self, ptr: u32) -> Result<[u8; 4]> { - let mut arr = [0u8; 4]; - self.heap.get_into(self.ptr_offset + ptr, &mut arr)?; - Ok(arr) + // Read a u64 from the heap in LE form. Used to read heap allocation prefixes. + fn get_heap_u64(&self, heap: &[u8], offset: u32) -> Result { + let range = self.heap_range(offset, 8, heap.len()) + .ok_or_else(|| error("read out of heap bounds"))?; + let bytes = heap[range].try_into() + .expect("[u8] slice of length 8 must be convertible to [u8; 8]"); + Ok(u64::from_le_bytes(bytes)) } - fn get_heap_byte(&mut self, ptr: u32) -> Result { - let mut arr = [0u8; 1]; - self.heap.get_into(self.ptr_offset + ptr, &mut arr)?; - Ok(arr[0]) - } - - fn set_heap(&mut self, ptr: u32, value: u8) -> Result<()> { - self.heap.set(self.ptr_offset + ptr, &[value]).map_err(Into::into) + // Write a u64 to the heap in LE form. Used to write heap allocation prefixes. + fn set_heap_u64(&self, heap: &mut [u8], offset: u32, val: u64) -> Result<()> { + let range = self.heap_range(offset, 8, heap.len()) + .ok_or_else(|| error("write out of heap bounds"))?; + let bytes = val.to_le_bytes(); + &mut heap[range].copy_from_slice(&bytes[..]); + Ok(()) } - fn set_heap_4bytes(&mut self, ptr: u32, value: [u8; 4]) -> Result<()> { - self.heap.set(self.ptr_offset + ptr, &value).map_err(Into::into) + fn heap_range(&self, offset: u32, length: u32, heap_len: usize) -> Option> { + let start = offset + .checked_add(self.ptr_offset)? + as usize; + let end = offset + .checked_add(self.ptr_offset)? + .checked_add(length)? + as usize; + if end <= heap_len { + Some(start..end) + } else { + None + } } - } #[cfg(test)] mod tests { use super::*; - use wasmi::MemoryInstance; - use wasmi::memory_units::*; const PAGE_SIZE: u32 = 65536; + /// Makes a pointer out of the given address. + fn to_pointer(address: u32) -> Pointer { + Pointer::new(address) + } + #[test] fn should_allocate_properly() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 0); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(0); // when - let ptr = heap.allocate(1).unwrap(); + let ptr = heap.allocate(&mut mem[..], 1).unwrap(); // then - assert_eq!(ptr, 8); + // returned pointer must start right after `PREFIX_SIZE` + assert_eq!(ptr, to_pointer(PREFIX_SIZE)); } #[test] fn should_always_align_pointers_to_multiples_of_8() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 13); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(13); // when - let ptr = heap.allocate(1).unwrap(); + let ptr = heap.allocate(&mut mem[..], 1).unwrap(); // then // the pointer must start at the next multiple of 8 from 13 // + the prefix of 8 bytes. - assert_eq!(ptr, 24); + assert_eq!(ptr, to_pointer(24)); } #[test] fn should_increment_pointers_properly() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 0); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(0); // when - let ptr1 = heap.allocate(1).unwrap(); - let ptr2 = heap.allocate(9).unwrap(); - let ptr3 = heap.allocate(1).unwrap(); + let ptr1 = heap.allocate(&mut mem[..], 1).unwrap(); + let ptr2 = heap.allocate(&mut mem[..], 9).unwrap(); + let ptr3 = heap.allocate(&mut mem[..], 1).unwrap(); // then // a prefix of 8 bytes is prepended to each pointer - assert_eq!(ptr1, 8); + assert_eq!(ptr1, to_pointer(PREFIX_SIZE)); // the prefix of 8 bytes + the content of ptr1 padded to the lowest possible // item size of 8 bytes + the prefix of ptr1 - assert_eq!(ptr2, 24); + assert_eq!(ptr2, to_pointer(24)); // ptr2 + its content of 16 bytes + the prefix of 8 bytes - assert_eq!(ptr3, 24 + 16 + 8); + assert_eq!(ptr3, to_pointer(24 + 16 + PREFIX_SIZE)); } #[test] fn should_free_properly() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 0); - let ptr1 = heap.allocate(1).unwrap(); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(0); + let ptr1 = heap.allocate(&mut mem[..], 1).unwrap(); // the prefix of 8 bytes is prepended to the pointer - assert_eq!(ptr1, 8); + assert_eq!(ptr1, to_pointer(PREFIX_SIZE)); - let ptr2 = heap.allocate(1).unwrap(); + let ptr2 = heap.allocate(&mut mem[..], 1).unwrap(); // the prefix of 8 bytes + the content of ptr 1 is prepended to the pointer - assert_eq!(ptr2, 24); + assert_eq!(ptr2, to_pointer(24)); // when - heap.deallocate(ptr2).unwrap(); + heap.deallocate(&mut mem[..], ptr2).unwrap(); // then // then the heads table should contain a pointer to the // prefix of ptr2 in the leftmost entry - assert_eq!(heap.heads[0], ptr2 - 8); + assert_eq!(heap.heads[0], u32::from(ptr2) - PREFIX_SIZE); } #[test] fn should_deallocate_and_reallocate_properly() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); + let mut mem = [0u8; PAGE_SIZE as usize]; let padded_offset = 16; - let mut heap = FreeingBumpHeapAllocator::new(mem, 13); + let mut heap = FreeingBumpHeapAllocator::new(13); - let ptr1 = heap.allocate(1).unwrap(); + let ptr1 = heap.allocate(&mut mem[..], 1).unwrap(); // the prefix of 8 bytes is prepended to the pointer - assert_eq!(ptr1, padded_offset + 8); + assert_eq!(ptr1, to_pointer(padded_offset + PREFIX_SIZE)); - let ptr2 = heap.allocate(9).unwrap(); + let ptr2 = heap.allocate(&mut mem[..], 9).unwrap(); // the padded_offset + the previously allocated ptr (8 bytes prefix + // 8 bytes content) + the prefix of 8 bytes which is prepended to the // current pointer - assert_eq!(ptr2, padded_offset + 16 + 8); + assert_eq!(ptr2, to_pointer(padded_offset + 16 + PREFIX_SIZE)); // when - heap.deallocate(ptr2).unwrap(); - let ptr3 = heap.allocate(9).unwrap(); + heap.deallocate(&mut mem[..], ptr2).unwrap(); + let ptr3 = heap.allocate(&mut mem[..], 9).unwrap(); // then // should have re-allocated - assert_eq!(ptr3, padded_offset + 16 + 8); + assert_eq!(ptr3, to_pointer(padded_offset + 16 + PREFIX_SIZE)); assert_eq!(heap.heads, [0; N]); } #[test] fn should_build_linked_list_of_free_areas_properly() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 0); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(0); - let ptr1 = heap.allocate(8).unwrap(); - let ptr2 = heap.allocate(8).unwrap(); - let ptr3 = heap.allocate(8).unwrap(); + let ptr1 = heap.allocate(&mut mem[..], 8).unwrap(); + let ptr2 = heap.allocate(&mut mem[..], 8).unwrap(); + let ptr3 = heap.allocate(&mut mem[..], 8).unwrap(); // when - heap.deallocate(ptr1).unwrap(); - heap.deallocate(ptr2).unwrap(); - heap.deallocate(ptr3).unwrap(); + heap.deallocate(&mut mem[..], ptr1).unwrap(); + heap.deallocate(&mut mem[..], ptr2).unwrap(); + heap.deallocate(&mut mem[..], ptr3).unwrap(); // then - let mut expected = [0; N]; - expected[0] = ptr3 - 8; - assert_eq!(heap.heads, expected); + assert_eq!(heap.heads[0], u32::from(ptr3) - PREFIX_SIZE); - let ptr4 = heap.allocate(8).unwrap(); + let ptr4 = heap.allocate(&mut mem[..], 8).unwrap(); assert_eq!(ptr4, ptr3); - expected[0] = ptr2 - 8; - assert_eq!(heap.heads, expected); + assert_eq!(heap.heads[0], u32::from(ptr2) - PREFIX_SIZE); } #[test] fn should_not_allocate_if_too_large() { // given - let mem = MemoryInstance::alloc(Pages(1), Some(Pages(1))).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 13); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(13); // when - let ptr = heap.allocate(PAGE_SIZE - 13); + let ptr = heap.allocate(&mut mem[..], PAGE_SIZE - 13); // then - assert_eq!(ptr.is_err(), true); - if let Err(err) = ptr { - match err { - Error::AllocatorOutOfSpace => {}, - _ => panic!("Expected out of space error"), - } + match ptr.unwrap_err() { + Error::AllocatorOutOfSpace => {}, + e => panic!("Expected allocator out of space error, got: {:?}", e), } } #[test] fn should_not_allocate_if_full() { // given - let mem = MemoryInstance::alloc(Pages(1), Some(Pages(1))).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 0); - let ptr1 = heap.allocate((PAGE_SIZE / 2) - 8).unwrap(); - assert_eq!(ptr1, 8); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(0); + let ptr1 = heap.allocate(&mut mem[..], (PAGE_SIZE / 2) - PREFIX_SIZE).unwrap(); + assert_eq!(ptr1, to_pointer(PREFIX_SIZE)); // when - let ptr2 = heap.allocate(PAGE_SIZE / 2); + let ptr2 = heap.allocate(&mut mem[..], PAGE_SIZE / 2); // then // there is no room for another half page incl. its 8 byte prefix - assert_eq!(ptr2.is_err(), true); - if let Err(err) = ptr2 { - match err { - Error::AllocatorOutOfSpace => {}, - _ => panic!("Expected out of space error"), - } + match ptr2.unwrap_err() { + Error::AllocatorOutOfSpace => {}, + e => panic!("Expected allocator out of space error, got: {:?}", e), } } #[test] fn should_allocate_max_possible_allocation_size() { // given - let pages_needed = (MAX_POSSIBLE_ALLOCATION as usize / PAGE_SIZE as usize) + 1; - let mem = MemoryInstance::alloc(Pages(pages_needed), Some(Pages(pages_needed))).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 0); + let mut mem = vec![0u8; (MAX_POSSIBLE_ALLOCATION + PAGE_SIZE) as usize]; + let mut heap = FreeingBumpHeapAllocator::new(0); // when - let ptr = heap.allocate(MAX_POSSIBLE_ALLOCATION).unwrap(); + let ptr = heap.allocate(&mut mem[..], MAX_POSSIBLE_ALLOCATION).unwrap(); // then - assert_eq!(ptr, 8); + assert_eq!(ptr, to_pointer(PREFIX_SIZE)); } #[test] fn should_not_allocate_if_requested_size_too_large() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 0); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(0); // when - let ptr = heap.allocate(MAX_POSSIBLE_ALLOCATION + 1); + let ptr = heap.allocate(&mut mem[..], MAX_POSSIBLE_ALLOCATION + 1); // then - assert_eq!(ptr.is_err(), true); - if let Err(err) = ptr { - match err { - Error::RequestedAllocationTooLarge => {}, - e => panic!("Expected out of space error, got: {:?}", e), - } + match ptr.unwrap_err() { + Error::RequestedAllocationTooLarge => {}, + e => panic!("Expected allocation size too large error, got: {:?}", e), } } #[test] - fn should_include_prefixes_in_total_heap_size() { + fn should_return_error_when_bumper_greater_than_heap_size() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 1); + let mut mem = [0u8; 64]; + let mut heap = FreeingBumpHeapAllocator::new(0); + + let ptr1 = heap.allocate(&mut mem[..], 32).unwrap(); + assert_eq!(ptr1, to_pointer(PREFIX_SIZE)); + heap.deallocate(&mut mem[..], ptr1).expect("failed freeing ptr1"); + assert_eq!(heap.total_size, 0); + assert_eq!(heap.bumper, 40); + + let ptr2 = heap.allocate(&mut mem[..], 16).unwrap(); + assert_eq!(ptr2, to_pointer(48)); + heap.deallocate(&mut mem[..], ptr2).expect("failed freeing ptr2"); + assert_eq!(heap.total_size, 0); + assert_eq!(heap.bumper, 64); // when - // an item size of 16 must be used then - heap.allocate(9).unwrap(); + // the `bumper` value is equal to `max_heap_size` here and any + // further allocation which would increment the bumper must fail. + // we try to allocate 8 bytes here, which will increment the + // bumper since no 8 byte item has been allocated+freed before. + let ptr = heap.allocate(&mut mem[..], 8); // then - assert_eq!(heap.total_size, 8 + 16); + match ptr.unwrap_err() { + Error::AllocatorOutOfSpace => {}, + e => panic!("Expected allocator out of space error, got: {:?}", e), + } } #[test] - fn should_calculate_total_heap_size_to_zero() { + fn should_include_prefixes_in_total_heap_size() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 13); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(1); // when - let ptr = heap.allocate(42).unwrap(); - assert_eq!(ptr, 16 + 8); - heap.deallocate(ptr).unwrap(); + // an item size of 16 must be used then + heap.allocate(&mut mem[..], 9).unwrap(); // then - assert_eq!(heap.total_size, 0); + assert_eq!(heap.total_size, PREFIX_SIZE + 16); } #[test] - fn should_calculate_total_size_of_zero() { + fn should_calculate_total_heap_size_to_zero() { // given - let mem = MemoryInstance::alloc(Pages(1), None).unwrap(); - let mut heap = FreeingBumpHeapAllocator::new(mem, 19); + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(13); // when - for _ in 1..10 { - let ptr = heap.allocate(42).unwrap(); - heap.deallocate(ptr).unwrap(); - } + let ptr = heap.allocate(&mut mem[..], 42).unwrap(); + assert_eq!(ptr, to_pointer(16 + PREFIX_SIZE)); + heap.deallocate(&mut mem[..], ptr).unwrap(); // then assert_eq!(heap.total_size, 0); } #[test] - fn should_write_u32_correctly_into_le() { + fn should_calculate_total_size_of_zero() { // given - let mut heap = vec![0; 5]; + let mut mem = [0u8; PAGE_SIZE as usize]; + let mut heap = FreeingBumpHeapAllocator::new(19); // when - FreeingBumpHeapAllocator::write_u32_into_le_bytes(1, &mut heap[0..4]); + for _ in 1..10 { + let ptr = heap.allocate(&mut mem[..], 42).unwrap(); + heap.deallocate(&mut mem[..], ptr).unwrap(); + } // then - assert_eq!(heap, [1, 0, 0, 0, 0]); + assert_eq!(heap.total_size, 0); } #[test] - fn should_write_u32_max_correctly_into_le() { + fn should_read_and_write_u64_correctly() { // given - let mut heap = vec![0; 5]; + let mut mem = [0u8; PAGE_SIZE as usize]; + let heap = FreeingBumpHeapAllocator::new(16); // when - FreeingBumpHeapAllocator::write_u32_into_le_bytes(u32::max_value(), &mut heap[0..4]); + heap.set_heap_u64(&mut mem[..], 40, 4480113).unwrap(); // then - assert_eq!(heap, [255, 255, 255, 255, 0]); + let value = heap.get_heap_u64(&mut mem[..], 40).unwrap(); + assert_eq!(value, 4480113); } #[test] diff --git a/core/executor/src/error.rs b/core/executor/src/error.rs index 9bfa05ff5f534f08a442b3c11a97cf3d8611df12..83168d598e03cfb83614c88199ea730829b36d7c 100644 --- a/core/executor/src/error.rs +++ b/core/executor/src/error.rs @@ -16,9 +16,10 @@ //! Rust executor possible errors. -use state_machine; use serializer; use wasmi; +#[cfg(feature = "wasmtime")] +use wasmtime_jit::{ActionError, SetupError}; /// Result type alias. pub type Result = std::result::Result; @@ -32,6 +33,9 @@ pub enum Error { Trap(wasmi::Trap), /// Wasmi loading/instantiating error Wasmi(wasmi::Error), + /// Wasmtime action error + #[cfg(feature = "wasmtime")] + Wasmtime(ActionError), /// Error in the API. Parameter is an error message. ApiError(String), /// Method is not found @@ -66,16 +70,19 @@ pub enum Error { #[display(fmt="The runtime has the `start` function")] RuntimeHasStartFn, /// Some other error occurred - Other(&'static str), + Other(String), /// Some error occurred in the allocator #[display(fmt="Error in allocator: {}", _0)] Allocator(&'static str), - /// The allocator run out of space. - #[display(fmt="Allocator run out of space")] + /// The allocator ran out of space. + #[display(fmt="Allocator ran out of space")] AllocatorOutOfSpace, /// Someone tried to allocate more memory than the allowed maximum per allocation. #[display(fmt="Requested allocation size is too large")] RequestedAllocationTooLarge, + /// Execution of a host function failed. + #[display(fmt="Host function {} execution failed with: {}", _0, _1)] + FunctionExecution(String, String), } impl std::error::Error for Error { @@ -89,12 +96,41 @@ impl std::error::Error for Error { } } -impl state_machine::Error for Error {} - impl wasmi::HostError for Error {} -impl From<&'static str> for Error { - fn from(err: &'static str) -> Error { +impl From for Error { + fn from(err: String) -> Error { Error::Other(err) } } + +impl From for Error { + fn from(err: WasmError) -> Error { + Error::Other(err.to_string()) + } +} + +/// Type for errors occurring during Wasm runtime construction. +#[derive(Debug, derive_more::Display)] +pub enum WasmError { + /// Code could not be read from the state. + CodeNotFound, + /// Failure to reinitialize runtime instance from snapshot. + ApplySnapshotFailed, + /// Wasm code failed validation. + InvalidModule, + /// Wasm code could not be deserialized. + CantDeserializeWasm, + /// The module does not export a linear memory named `memory`. + InvalidMemory, + /// The number of heap pages requested is disallowed by the module. + InvalidHeapPages, + /// Instantiation error. + Instantiation(String), + /// The compiler does not support the host machine as a target. + #[cfg(feature = "wasmtime")] + MissingCompilerSupport(&'static str), + /// Wasmtime setup error. + #[cfg(feature = "wasmtime")] + WasmtimeSetup(SetupError), +} diff --git a/core/executor/src/host_interface.rs b/core/executor/src/host_interface.rs new file mode 100644 index 0000000000000000000000000000000000000000..4d1515d76999b7fafcf4b899ebe90698999b89dd --- /dev/null +++ b/core/executor/src/host_interface.rs @@ -0,0 +1,1104 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Definition and implementation of the Substrate Wasm host interface. +//! +//! These are the host functions callable from within the Substrate runtime. + +use codec::Encode; +use std::{convert::TryFrom, str}; +use primitives::{ + blake2_128, blake2_256, twox_64, twox_128, twox_256, ed25519, sr25519, Blake2Hasher, Pair, + crypto::KeyTypeId, offchain, +}; +use trie::{TrieConfiguration, trie_types::Layout}; +use wasm_interface::{FunctionContext, Pointer, PointerType, Result as WResult, WordSize}; + +#[cfg(feature="wasm-extern-trace")] +macro_rules! debug_trace { + ( $( $x:tt )* ) => ( trace!( $( $x )* ) ) +} + +#[cfg(not(feature="wasm-extern-trace"))] +macro_rules! debug_trace { + ( $( $x:tt )* ) => () +} + +pub struct SubstrateExternals; + +enum RecoverResult { + Invalid(u32), + Valid(secp256k1::PublicKey), +} + +fn secp256k1_recover( + context: &mut dyn FunctionContext, + msg_data: Pointer, + sig_data: Pointer, +) -> WResult { + let mut sig = [0u8; 65]; + context.read_memory_into(sig_data, &mut sig[..]) + .map_err(|_| "Invalid attempt to get signature in ext_secp256k1_ecdsa_recover")?; + let rs = match secp256k1::Signature::parse_slice(&sig[0..64]) { + Ok(rs) => rs, + _ => return Ok(RecoverResult::Invalid(1)), + }; + + let recovery_id = if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8; + let v = match secp256k1::RecoveryId::parse(recovery_id) { + Ok(v) => v, + _ => return Ok(RecoverResult::Invalid(2)), + }; + + let mut msg = [0u8; 32]; + context.read_memory_into(msg_data, &mut msg[..]) + .map_err(|_| "Invalid attempt to get message in ext_secp256k1_ecdsa_recover")?; + + Ok(match secp256k1::recover(&secp256k1::Message::parse(&msg), &rs, &v) { + Ok(pubkey) => RecoverResult::Valid(pubkey), + Err(_) => RecoverResult::Invalid(3), + }) +} + +impl_wasm_host_interface! { + impl SubstrateExternals where context { + ext_malloc(size: WordSize) -> Pointer { + let r = context.allocate_memory(size)?; + debug_trace!(target: "sr-io", "malloc {} bytes at {:?}", size, r); + Ok(r) + } + + ext_free(addr: Pointer) { + context.deallocate_memory(addr)?; + debug_trace!(target: "sr-io", "free {:?}", addr); + Ok(()) + } + + ext_sandbox_instantiate( + dispatch_thunk_idx: u32, + wasm_ptr: Pointer, + wasm_len: WordSize, + imports_ptr: Pointer, + imports_len: WordSize, + state: u32, + ) -> u32 { + let wasm = context.read_memory(wasm_ptr, wasm_len) + .map_err(|_| "OOB while ext_sandbox_instantiate: wasm")?; + let raw_env_def = context.read_memory(imports_ptr, imports_len) + .map_err(|_| "OOB while ext_sandbox_instantiate: imports")?; + + context.sandbox().instance_new(dispatch_thunk_idx, &wasm, &raw_env_def, state) + } + + ext_sandbox_instance_teardown(instance_idx: u32) { + context.sandbox().instance_teardown(instance_idx) + } + + ext_sandbox_invoke( + instance_idx: u32, + export_ptr: Pointer, + export_len: WordSize, + args_ptr: Pointer, + args_len: WordSize, + return_val_ptr: Pointer, + return_val_len: WordSize, + state: u32, + ) -> u32 { + let export = context.read_memory(export_ptr, export_len) + .map_err(|_| "OOB while ext_sandbox_invoke: export") + .and_then(|b| + String::from_utf8(b) + .map_err(|_| "Export name should be a valid utf-8 sequence") + )?; + + // Deserialize arguments and convert them into wasmi types. + let serialized_args = context.read_memory(args_ptr, args_len) + .map_err(|_| "OOB while ext_sandbox_invoke: args")?; + + context.sandbox().invoke( + instance_idx, + &export, + &serialized_args, + return_val_ptr, + return_val_len, + state, + ) + } + + ext_sandbox_memory_new(initial: WordSize, maximum: WordSize) -> u32 { + context.sandbox().memory_new(initial, maximum) + } + + ext_sandbox_memory_get( + memory_idx: u32, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> u32 { + context.sandbox().memory_get(memory_idx, offset, buf_ptr, buf_len) + } + + ext_sandbox_memory_set( + memory_idx: u32, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> u32 { + context.sandbox().memory_set(memory_idx, offset, val_ptr, val_len) + } + + ext_sandbox_memory_teardown(memory_idx: u32) { + context.sandbox().memory_teardown(memory_idx) + } + + ext_print_utf8(utf8_data: Pointer, utf8_len: WordSize) { + if let Ok(utf8) = context.read_memory(utf8_data, utf8_len) { + runtime_io::print_utf8(&utf8); + } + Ok(()) + } + + ext_print_hex(data: Pointer, len: WordSize) { + if let Ok(hex) = context.read_memory(data, len) { + runtime_io::print_hex(&hex); + } + Ok(()) + } + + ext_print_num(number: u64) { + runtime_io::print_num(number); + Ok(()) + } + + ext_log( + level: u32, + target_data: Pointer, + target_len: WordSize, + message_data: Pointer, + message_len: WordSize, + ) { + let target = context.read_memory(target_data, target_len) + .map_err(|_| "Invalid attempt to determine target in ext_log")?; + let message = context.read_memory(message_data, message_len) + .map_err(|_| "Invalid attempt to determine message in ext_log")?; + + runtime_io::log(level.into(), &target, &message); + Ok(()) + } + + ext_set_storage( + key_data: Pointer, + key_len: WordSize, + value_data: Pointer, + value_len: WordSize, + ) { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_set_storage")?; + let value = context.read_memory(value_data, value_len) + .map_err(|_| "Invalid attempt to determine value in ext_set_storage")?; + Ok(runtime_io::set_storage(&key, &value)) + } + + ext_set_child_storage( + storage_key_data: Pointer, + storage_key_len: WordSize, + key_data: Pointer, + key_len: WordSize, + value_data: Pointer, + value_len: WordSize, + ) { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_set_child_storage")?; + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_set_child_storage")?; + let value = context.read_memory(value_data, value_len) + .map_err(|_| "Invalid attempt to determine value in ext_set_child_storage")?; + + Ok(runtime_io::set_child_storage(&storage_key, &key, &value)) + } + + ext_clear_child_storage( + storage_key_data: Pointer, + storage_key_len: WordSize, + key_data: Pointer, + key_len: WordSize, + ) { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_clear_child_storage")?; + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_clear_child_storage")?; + + Ok(runtime_io::clear_child_storage(&storage_key, &key)) + } + + ext_clear_storage(key_data: Pointer, key_len: WordSize) { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_clear_storage")?; + Ok(runtime_io::clear_storage(&key)) + } + + ext_exists_storage(key_data: Pointer, key_len: WordSize) -> u32 { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_exists_storage")?; + Ok(if runtime_io::exists_storage(&key) { 1 } else { 0 }) + } + + ext_exists_child_storage( + storage_key_data: Pointer, + storage_key_len: WordSize, + key_data: Pointer, + key_len: WordSize, + ) -> u32 { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_exists_child_storage")?; + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_exists_child_storage")?; + + Ok(if runtime_io::exists_child_storage(&storage_key, &key) { 1 } else { 0 }) + } + + ext_clear_prefix(prefix_data: Pointer, prefix_len: WordSize) { + let prefix = context.read_memory(prefix_data, prefix_len) + .map_err(|_| "Invalid attempt to determine prefix in ext_clear_prefix")?; + Ok(runtime_io::clear_prefix(&prefix)) + } + + ext_clear_child_prefix( + storage_key_data: Pointer, + storage_key_len: WordSize, + prefix_data: Pointer, + prefix_len: WordSize, + ) { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_clear_child_prefix")?; + let prefix = context.read_memory(prefix_data, prefix_len) + .map_err(|_| "Invalid attempt to determine prefix in ext_clear_child_prefix")?; + Ok(runtime_io::clear_child_prefix(&storage_key, &prefix)) + } + + ext_kill_child_storage(storage_key_data: Pointer, storage_key_len: WordSize) { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_kill_child_storage")?; + Ok(runtime_io::kill_child_storage(&storage_key)) + } + + ext_get_allocated_storage( + key_data: Pointer, + key_len: WordSize, + written_out: Pointer, + ) -> Pointer { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_get_allocated_storage")?; + + if let Some(value) = runtime_io::storage(&key) { + let offset = context.allocate_memory(value.len() as u32)?; + context.write_memory(offset, &value) + .map_err(|_| "Invalid attempt to set memory in ext_get_allocated_storage")?; + context.write_primitive(written_out, value.len() as u32) + .map_err(|_| "Invalid attempt to write written_out in ext_get_allocated_storage")?; + Ok(offset) + } else { + context.write_primitive(written_out, u32::max_value()) + .map_err(|_| "Invalid attempt to write failed written_out in ext_get_allocated_storage")?; + Ok(Pointer::null()) + } + } + + ext_get_allocated_child_storage( + storage_key_data: Pointer, + storage_key_len: WordSize, + key_data: Pointer, + key_len: WordSize, + written_out: Pointer, + ) -> Pointer { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_get_allocated_child_storage")?; + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to determine key in ext_get_allocated_child_storage")?; + + if let Some(value) = runtime_io::child_storage(&storage_key, &key) { + let offset = context.allocate_memory(value.len() as u32)?; + context.write_memory(offset, &value) + .map_err(|_| "Invalid attempt to set memory in ext_get_allocated_child_storage")?; + context.write_primitive(written_out, value.len() as u32) + .map_err(|_| "Invalid attempt to write written_out in ext_get_allocated_child_storage")?; + Ok(offset) + } else { + context.write_primitive(written_out, u32::max_value()) + .map_err(|_| "Invalid attempt to write failed written_out in ext_get_allocated_child_storage")?; + Ok(Pointer::null()) + } + } + + ext_get_storage_into( + key_data: Pointer, + key_len: WordSize, + value_data: Pointer, + value_len: WordSize, + value_offset: WordSize, + ) -> WordSize { + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to get key in ext_get_storage_into")?; + + if let Some(value) = runtime_io::storage(&key) { + let data = &value[value.len().min(value_offset as usize)..]; + let written = std::cmp::min(value_len as usize, data.len()); + context.write_memory(value_data, &data[..written]) + .map_err(|_| "Invalid attempt to set value in ext_get_storage_into")?; + Ok(value.len() as u32) + } else { + Ok(u32::max_value()) + } + } + + ext_get_child_storage_into( + storage_key_data: Pointer, + storage_key_len: WordSize, + key_data: Pointer, + key_len: WordSize, + value_data: Pointer, + value_len: WordSize, + value_offset: WordSize, + ) -> WordSize { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_get_child_storage_into")?; + let key = context.read_memory(key_data, key_len) + .map_err(|_| "Invalid attempt to get key in ext_get_child_storage_into")?; + + if let Some(value) = runtime_io::child_storage(&storage_key, &key) { + let data = &value[value.len().min(value_offset as usize)..]; + let written = std::cmp::min(value_len as usize, data.len()); + context.write_memory(value_data, &data[..written]) + .map_err(|_| "Invalid attempt to get value in ext_get_child_storage_into")?; + Ok(value.len() as u32) + } else { + Ok(u32::max_value()) + } + } + + ext_storage_root(result: Pointer) { + context.write_memory(result, runtime_io::storage_root().as_ref()) + .map_err(|_| "Invalid attempt to set memory in ext_storage_root".into()) + } + + ext_child_storage_root( + storage_key_data: Pointer, + storage_key_len: WordSize, + written_out: Pointer, + ) -> Pointer { + let storage_key = context.read_memory(storage_key_data, storage_key_len) + .map_err(|_| "Invalid attempt to determine storage_key in ext_child_storage_root")?; + let value = runtime_io::child_storage_root(&storage_key); + + let offset = context.allocate_memory(value.len() as u32)?; + context.write_memory(offset, &value) + .map_err(|_| "Invalid attempt to set memory in ext_child_storage_root")?; + context.write_primitive(written_out, value.len() as u32) + .map_err(|_| "Invalid attempt to write written_out in ext_child_storage_root")?; + Ok(offset) + } + + ext_storage_changes_root( + parent_hash_data: Pointer, + _len: WordSize, + result: Pointer, + ) -> u32 { + let mut parent_hash = [0u8; 32]; + context.read_memory_into(parent_hash_data, &mut parent_hash[..]) + .map_err(|_| "Invalid attempt to get parent_hash in ext_storage_changes_root")?; + + if let Some(r) = runtime_io::storage_changes_root(parent_hash) { + context.write_memory(result, &r[..]) + .map_err(|_| "Invalid attempt to set memory in ext_storage_changes_root")?; + Ok(1) + } else { + Ok(0) + } + } + + ext_blake2_256_enumerated_trie_root( + values_data: Pointer, + lens_data: Pointer, + lens_len: WordSize, + result: Pointer, + ) { + let values = (0..lens_len) + .map(|i| context.read_primitive(lens_data.offset(i).ok_or("Pointer overflow")?)) + .collect::, _>>()? + .into_iter() + .scan(0u32, |acc, v| { let o = *acc; *acc += v; Some((o, v)) }) + .map(|(offset, len)| + context.read_memory(values_data.offset(offset).ok_or("Pointer overflow")?, len) + .map_err(|_| + "Invalid attempt to get memory in ext_blake2_256_enumerated_trie_root" + ) + ) + .collect::, _>>()?; + let r = Layout::::ordered_trie_root(values.into_iter()); + context.write_memory(result, &r[..]) + .map_err(|_| "Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root")?; + Ok(()) + } + + ext_chain_id() -> u64 { + Ok(runtime_io::chain_id()) + } + + ext_twox_64(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 8] = if len == 0 { + let hashed = twox_64(&[0u8; 0]); + hashed + } else { + let key = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get key in ext_twox_64")?; + let hashed_key = twox_64(&key); + hashed_key + }; + + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_twox_64")?; + Ok(()) + } + + ext_twox_128(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 16] = if len == 0 { + let hashed = twox_128(&[0u8; 0]); + hashed + } else { + let key = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get key in ext_twox_128")?; + let hashed_key = twox_128(&key); + hashed_key + }; + + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_twox_128")?; + Ok(()) + } + + ext_twox_256(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 32] = if len == 0 { + twox_256(&[0u8; 0]) + } else { + let mem = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get data in ext_twox_256")?; + twox_256(&mem) + }; + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_twox_256")?; + Ok(()) + } + + ext_blake2_128(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 16] = if len == 0 { + let hashed = blake2_128(&[0u8; 0]); + hashed + } else { + let key = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get key in ext_blake2_128")?; + let hashed_key = blake2_128(&key); + hashed_key + }; + + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_blake2_128")?; + Ok(()) + } + + ext_blake2_256(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 32] = if len == 0 { + blake2_256(&[0u8; 0]) + } else { + let mem = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get data in ext_blake2_256")?; + blake2_256(&mem) + }; + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_blake2_256")?; + Ok(()) + } + + ext_keccak_256(data: Pointer, len: WordSize, out: Pointer) { + let result: [u8; 32] = if len == 0 { + tiny_keccak::keccak256(&[0u8; 0]) + } else { + let mem = context.read_memory(data, len) + .map_err(|_| "Invalid attempt to get data in ext_keccak_256")?; + tiny_keccak::keccak256(&mem) + }; + context.write_memory(out, &result) + .map_err(|_| "Invalid attempt to set result in ext_keccak_256")?; + Ok(()) + } + + ext_ed25519_public_keys(id_data: Pointer, result_len: Pointer) -> Pointer { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_ed25519_public_keys")?; + let key_type = KeyTypeId(id); + + let keys = runtime_io::ed25519_public_keys(key_type).encode(); + + let len = keys.len() as u32; + let offset = context.allocate_memory(len)?; + + context.write_memory(offset, keys.as_ref()) + .map_err(|_| "Invalid attempt to set memory in ext_ed25519_public_keys")?; + context.write_primitive(result_len, len) + .map_err(|_| "Invalid attempt to write result_len in ext_ed25519_public_keys")?; + + Ok(offset) + } + + ext_ed25519_verify( + msg_data: Pointer, + msg_len: WordSize, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + let mut sig = [0u8; 64]; + context.read_memory_into(sig_data, &mut sig[..]) + .map_err(|_| "Invalid attempt to get signature in ext_ed25519_verify")?; + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_verify")?; + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_ed25519_verify")?; + + Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { + 0 + } else { + 1 + }) + } + + ext_ed25519_generate( + id_data: Pointer, + seed: Pointer, + seed_len: WordSize, + out: Pointer, + ) { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_ed25519_generate")?; + let key_type = KeyTypeId(id); + + let seed = if seed_len == 0 { + None + } else { + Some( + context.read_memory(seed, seed_len) + .map_err(|_| "Invalid attempt to get seed in ext_ed25519_generate")? + ) + }; + + let seed = seed.as_ref() + .map(|seed| + std::str::from_utf8(&seed) + .map_err(|_| "Seed not a valid utf8 string in ext_sr25119_generate") + ).transpose()?; + + let pubkey = runtime_io::ed25519_generate(key_type, seed); + + context.write_memory(out, pubkey.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_ed25519_generate".into()) + } + + ext_ed25519_sign( + id_data: Pointer, + pubkey_data: Pointer, + msg_data: Pointer, + msg_len: WordSize, + out: Pointer, + ) -> u32 { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_ed25519_sign")?; + let key_type = KeyTypeId(id); + + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_sign")?; + + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_ed25519_sign")?; + + let pub_key = ed25519::Public::try_from(pubkey.as_ref()) + .map_err(|_| "Invalid `ed25519` public key")?; + + let signature = runtime_io::ed25519_sign(key_type, &pub_key, &msg); + + match signature { + Some(signature) => { + context.write_memory(out, signature.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_ed25519_sign")?; + Ok(0) + }, + None => Ok(1), + } + } + + ext_sr25519_public_keys(id_data: Pointer, result_len: Pointer) -> Pointer { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_sr25519_public_keys")?; + let key_type = KeyTypeId(id); + + let keys = runtime_io::sr25519_public_keys(key_type).encode(); + + let len = keys.len() as u32; + let offset = context.allocate_memory(len)?; + + context.write_memory(offset, keys.as_ref()) + .map_err(|_| "Invalid attempt to set memory in ext_sr25519_public_keys")?; + context.write_primitive(result_len, len) + .map_err(|_| "Invalid attempt to write result_len in ext_sr25519_public_keys")?; + + Ok(offset) + } + + ext_sr25519_verify( + msg_data: Pointer, + msg_len: WordSize, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + let mut sig = [0u8; 64]; + context.read_memory_into(sig_data, &mut sig[..]) + .map_err(|_| "Invalid attempt to get signature in ext_sr25519_verify")?; + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_verify")?; + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_sr25519_verify")?; + + Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { + 0 + } else { + 1 + }) + } + + ext_sr25519_generate( + id_data: Pointer, + seed: Pointer, + seed_len: WordSize, + out: Pointer, + ) { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_sr25519_generate")?; + let key_type = KeyTypeId(id); + let seed = if seed_len == 0 { + None + } else { + Some( + context.read_memory(seed, seed_len) + .map_err(|_| "Invalid attempt to get seed in ext_sr25519_generate")? + ) + }; + + let seed = seed.as_ref() + .map(|seed| + std::str::from_utf8(&seed) + .map_err(|_| "Seed not a valid utf8 string in ext_sr25119_generate") + ) + .transpose()?; + + let pubkey = runtime_io::sr25519_generate(key_type, seed); + + context.write_memory(out, pubkey.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_sr25519_generate".into()) + } + + ext_sr25519_sign( + id_data: Pointer, + pubkey_data: Pointer, + msg_data: Pointer, + msg_len: WordSize, + out: Pointer, + ) -> u32 { + let mut id = [0u8; 4]; + context.read_memory_into(id_data, &mut id[..]) + .map_err(|_| "Invalid attempt to get id in ext_sr25519_sign")?; + let key_type = KeyTypeId(id); + + let mut pubkey = [0u8; 32]; + context.read_memory_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_sign")?; + + let msg = context.read_memory(msg_data, msg_len) + .map_err(|_| "Invalid attempt to get message in ext_sr25519_sign")?; + + let pub_key = sr25519::Public::try_from(pubkey.as_ref()) + .map_err(|_| "Invalid `sr25519` public key")?; + + let signature = runtime_io::sr25519_sign(key_type, &pub_key, &msg); + + match signature { + Some(signature) => { + context.write_memory(out, signature.as_ref()) + .map_err(|_| "Invalid attempt to set out in ext_sr25519_sign")?; + Ok(0) + }, + None => Ok(1), + } + } + + ext_secp256k1_ecdsa_recover( + msg_data: Pointer, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + match secp256k1_recover(context, msg_data, sig_data)? { + RecoverResult::Invalid(c) => Ok(c), + RecoverResult::Valid(pubkey) => { + context.write_memory(pubkey_data, &pubkey.serialize()[1..65]) + .map_err(|_| "Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover")?; + Ok(0) + } + } + } + + ext_secp256k1_ecdsa_recover_compressed( + msg_data: Pointer, + sig_data: Pointer, + pubkey_data: Pointer, + ) -> u32 { + match secp256k1_recover(context, msg_data, sig_data)? { + RecoverResult::Invalid(c) => Ok(c), + RecoverResult::Valid(pubkey) => { + context.write_memory(pubkey_data, &pubkey.serialize_compressed()[..]) + .map_err(|_| "Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover")?; + Ok(0) + } + } + } + + ext_is_validator() -> u32 { + if runtime_io::is_validator() { Ok(1) } else { Ok(0) } + } + + ext_submit_transaction(msg_data: Pointer, len: WordSize) -> u32 { + let extrinsic = context.read_memory(msg_data, len) + .map_err(|_| "OOB while ext_submit_transaction: wasm")?; + + let res = runtime_io::submit_transaction(extrinsic); + + Ok(if res.is_ok() { 0 } else { 1 }) + } + + ext_network_state(written_out: Pointer) -> Pointer { + let res = runtime_io::network_state(); + + let encoded = res.encode(); + let len = encoded.len() as u32; + let offset = context.allocate_memory(len)?; + context.write_memory(offset, &encoded) + .map_err(|_| "Invalid attempt to set memory in ext_network_state")?; + + context.write_primitive(written_out, len) + .map_err(|_| "Invalid attempt to write written_out in ext_network_state")?; + + Ok(offset) + } + + ext_timestamp() -> u64 { + Ok(runtime_io::timestamp().unix_millis()) + } + + ext_sleep_until(deadline: u64) { + runtime_io::sleep_until(offchain::Timestamp::from_unix_millis(deadline)); + Ok(()) + } + + ext_random_seed(seed_data: Pointer) { + // NOTE the runtime as assumptions about seed size. + let seed = runtime_io::random_seed(); + + context.write_memory(seed_data, &seed) + .map_err(|_| "Invalid attempt to set value in ext_random_seed")?; + Ok(()) + } + + ext_local_storage_set( + kind: u32, + key: Pointer, + key_len: WordSize, + value: Pointer, + value_len: WordSize, + ) { + let kind = offchain::StorageKind::try_from(kind) + .map_err(|_| "storage kind OOB while ext_local_storage_set: wasm")?; + let key = context.read_memory(key, key_len) + .map_err(|_| "OOB while ext_local_storage_set: wasm")?; + let value = context.read_memory(value, value_len) + .map_err(|_| "OOB while ext_local_storage_set: wasm")?; + + runtime_io::local_storage_set(kind, &key, &value); + + Ok(()) + } + + ext_local_storage_get( + kind: u32, + key: Pointer, + key_len: WordSize, + value_len: Pointer, + ) -> Pointer { + let kind = offchain::StorageKind::try_from(kind) + .map_err(|_| "storage kind OOB while ext_local_storage_get: wasm")?; + let key = context.read_memory(key, key_len) + .map_err(|_| "OOB while ext_local_storage_get: wasm")?; + + let maybe_value = runtime_io::local_storage_get(kind, &key); + + let (offset, len) = if let Some(value) = maybe_value { + let offset = context.allocate_memory(value.len() as u32)?; + context.write_memory(offset, &value) + .map_err(|_| "Invalid attempt to set memory in ext_local_storage_get")?; + (offset, value.len() as u32) + } else { + (Pointer::null(), u32::max_value()) + }; + + context.write_primitive(value_len, len) + .map_err(|_| "Invalid attempt to write value_len in ext_local_storage_get")?; + + Ok(offset) + } + + ext_local_storage_compare_and_set( + kind: u32, + key: Pointer, + key_len: WordSize, + old_value: Pointer, + old_value_len: WordSize, + new_value: Pointer, + new_value_len: WordSize, + ) -> u32 { + let kind = offchain::StorageKind::try_from(kind) + .map_err(|_| "storage kind OOB while ext_local_storage_compare_and_set: wasm")?; + let key = context.read_memory(key, key_len) + .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; + let new_value = context.read_memory(new_value, new_value_len) + .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; + + let old_value = if old_value_len == u32::max_value() { + None + } else { + Some( + context.read_memory(old_value, old_value_len) + .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")? + ) + }; + + let res = runtime_io::local_storage_compare_and_set( + kind, + &key, + old_value.as_ref().map(|v| v.as_ref()), + &new_value, + ); + + Ok(if res { 0 } else { 1 }) + } + + ext_http_request_start( + method: Pointer, + method_len: WordSize, + url: Pointer, + url_len: WordSize, + meta: Pointer, + meta_len: WordSize, + ) -> u32 { + let method = context.read_memory(method, method_len) + .map_err(|_| "OOB while ext_http_request_start: wasm")?; + let url = context.read_memory(url, url_len) + .map_err(|_| "OOB while ext_http_request_start: wasm")?; + let meta = context.read_memory(meta, meta_len) + .map_err(|_| "OOB while ext_http_request_start: wasm")?; + + let method_str = str::from_utf8(&method) + .map_err(|_| "invalid str while ext_http_request_start: wasm")?; + let url_str = str::from_utf8(&url) + .map_err(|_| "invalid str while ext_http_request_start: wasm")?; + + let id = runtime_io::http_request_start(method_str, url_str, &meta); + + if let Ok(id) = id { + Ok(id.into()) + } else { + Ok(u32::max_value()) + } + } + + ext_http_request_add_header( + request_id: u32, + name: Pointer, + name_len: WordSize, + value: Pointer, + value_len: WordSize, + ) -> u32 { + let name = context.read_memory(name, name_len) + .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; + let value = context.read_memory(value, value_len) + .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; + + let name_str = str::from_utf8(&name) + .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; + let value_str = str::from_utf8(&value) + .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; + + let res = runtime_io::http_request_add_header( + offchain::HttpRequestId(request_id as u16), + name_str, + value_str, + ); + + Ok(if res.is_ok() { 0 } else { 1 }) + } + + ext_http_request_write_body( + request_id: u32, + chunk: Pointer, + chunk_len: WordSize, + deadline: u64, + ) -> u32 { + let chunk = context.read_memory(chunk, chunk_len) + .map_err(|_| "OOB while ext_http_request_write_body: wasm")?; + + let res = runtime_io::http_request_write_body( + offchain::HttpRequestId(request_id as u16), + &chunk, + deadline_to_timestamp(deadline), + ); + + Ok(match res { + Ok(()) => 0, + Err(e) => e.into(), + }) + } + + ext_http_response_wait( + ids: Pointer, + ids_len: WordSize, + statuses: Pointer, + deadline: u64, + ) { + let ids = (0..ids_len) + .map(|i| + context.read_primitive(ids.offset(i).ok_or("Point overflow")?) + .map(|id: u32| offchain::HttpRequestId(id as u16)) + .map_err(|_| "OOB while ext_http_response_wait: wasm") + ) + .collect::, _>>()?; + + let res = runtime_io::http_response_wait(&ids, deadline_to_timestamp(deadline)) + .into_iter() + .map(|status| u32::from(status)) + .enumerate() + // make sure to take up to `ids_len` to avoid exceeding the mem. + .take(ids_len as usize); + + for (i, status) in res { + context.write_primitive(statuses.offset(i as u32).ok_or("Point overflow")?, status) + .map_err(|_| "Invalid attempt to set memory in ext_http_response_wait")?; + } + + Ok(()) + } + + ext_http_response_headers( + request_id: u32, + written_out: Pointer, + ) -> Pointer { + use codec::Encode; + + let headers = runtime_io::http_response_headers(offchain::HttpRequestId(request_id as u16)); + + let encoded = headers.encode(); + let len = encoded.len() as u32; + let offset = context.allocate_memory(len)?; + + context.write_memory(offset, &encoded) + .map_err(|_| "Invalid attempt to set memory in ext_http_response_headers")?; + context.write_primitive(written_out, len) + .map_err(|_| "Invalid attempt to write written_out in ext_http_response_headers")?; + + Ok(offset) + } + + ext_http_response_read_body( + request_id: u32, + buffer: Pointer, + buffer_len: WordSize, + deadline: u64, + ) -> WordSize { + let mut internal_buffer = Vec::with_capacity(buffer_len as usize); + internal_buffer.resize(buffer_len as usize, 0); + + let res = runtime_io::http_response_read_body( + offchain::HttpRequestId(request_id as u16), + &mut internal_buffer, + deadline_to_timestamp(deadline), + ); + + Ok(match res { + Ok(read) => { + context.write_memory(buffer, &internal_buffer[..read]) + .map_err(|_| "Invalid attempt to set memory in ext_http_response_read_body")?; + + read as u32 + }, + Err(err) => { + u32::max_value() - u32::from(err) + 1 + } + }) + } + } +} + +trait WritePrimitive { + fn write_primitive(&mut self, ptr: Pointer, t: T) -> WResult<()>; +} + +impl WritePrimitive for &mut dyn FunctionContext { + fn write_primitive(&mut self, ptr: Pointer, t: u32) -> WResult<()> { + let r = t.to_le_bytes(); + self.write_memory(ptr.cast(), &r) + } +} + +trait ReadPrimitive { + fn read_primitive(&self, offset: Pointer) -> WResult; +} + +impl ReadPrimitive for &mut dyn FunctionContext { + fn read_primitive(&self, ptr: Pointer) -> WResult { + let mut r = [0u8; 4]; + self.read_memory_into(ptr.cast(), &mut r)?; + Ok(u32::from_le_bytes(r)) + } +} + +fn deadline_to_timestamp(deadline: u64) -> Option { + if deadline == 0 { + None + } else { + Some(offchain::Timestamp::from_unix_millis(deadline)) + } +} + diff --git a/core/executor/src/integration_tests/mod.rs b/core/executor/src/integration_tests/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..5a30e2f255d6c3e123e8c650bae5cee7334d75aa --- /dev/null +++ b/core/executor/src/integration_tests/mod.rs @@ -0,0 +1,451 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +mod sandbox; + +use codec::{Encode, Decode}; +use hex_literal::hex; +use primitives::{ + Blake2Hasher, blake2_128, blake2_256, ed25519, sr25519, map, Pair, offchain::OffchainExt, + traits::Externalities, +}; +use runtime_test::WASM_BINARY; +use state_machine::TestExternalities as CoreTestExternalities; +use substrate_offchain::testing; +use test_case::test_case; +use trie::{TrieConfiguration, trie_types::Layout}; + +use crate::{WasmExecutionMethod, call_in_wasm}; + +pub type TestExternalities = CoreTestExternalities; + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn returning_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let output = call_in_wasm( + "test_empty_return", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); + assert_eq!(output, vec![0u8; 0]); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn panicking_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let output = call_in_wasm( + "test_panic", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + assert!(output.is_err()); + + let output = call_in_wasm( + "test_conditional_panic", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + assert_eq!(Decode::decode(&mut &output.unwrap()[..]), Ok(Vec::::new())); + + let output = call_in_wasm( + "test_conditional_panic", + &vec![2].encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + assert!(output.is_err()); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn storage_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + + ext.with_ext(|mut ext| { + ext.set_storage(b"foo".to_vec(), b"bar".to_vec()); + let test_code = WASM_BINARY; + + let output = call_in_wasm( + "test_data_in", + &b"Hello world".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); + + assert_eq!(output, b"all ok!".to_vec().encode()); + }); + + let expected = TestExternalities::new((map![ + b"input".to_vec() => b"Hello world".to_vec(), + b"foo".to_vec() => b"bar".to_vec(), + b"baz".to_vec() => b"bar".to_vec() + ], map![])); + assert_eq!(ext, expected); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn clear_prefix_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + + ext.with_ext(|mut ext| { + ext.set_storage(b"aaa".to_vec(), b"1".to_vec()); + ext.set_storage(b"aab".to_vec(), b"2".to_vec()); + ext.set_storage(b"aba".to_vec(), b"3".to_vec()); + ext.set_storage(b"abb".to_vec(), b"4".to_vec()); + ext.set_storage(b"bbb".to_vec(), b"5".to_vec()); + let test_code = WASM_BINARY; + + // This will clear all entries which prefix is "ab". + let output = call_in_wasm( + "test_clear_prefix", + &b"ab".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(); + + assert_eq!(output, b"all ok!".to_vec().encode()); + }); + + let expected = TestExternalities::new((map![ + b"aaa".to_vec() => b"1".to_vec(), + b"aab".to_vec() => b"2".to_vec(), + b"bbb".to_vec() => b"5".to_vec() + ], map![])); + assert_eq!(expected, ext); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn blake2_256_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_blake2_256", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_256(&b""[..]).to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_blake2_256", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_256(&b"Hello world!"[..]).to_vec().encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn blake2_128_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_blake2_128", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_128(&b""[..]).to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_blake2_128", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + blake2_128(&b"Hello world!"[..]).to_vec().encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn twox_256_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_twox_256", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!( + "99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a" + ).to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_twox_256", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!( + "b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74" + ).to_vec().encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn twox_128_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_twox_128", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!("99e9d85137db46ef4bbea33613baafd5").to_vec().encode(), + ); + assert_eq!( + call_in_wasm( + "test_twox_128", + &b"Hello world!".to_vec().encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + hex!("b27dfd7f223f177f2a13647b533599af").to_vec().encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn ed25519_verify_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + let key = ed25519::Pair::from_seed(&blake2_256(b"test")); + let sig = key.sign(b"all ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_ed25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + + let other_sig = key.sign(b"all is not ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(other_sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_ed25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + false.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sr25519_verify_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + let key = sr25519::Pair::from_seed(&blake2_256(b"test")); + let sig = key.sign(b"all ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_sr25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + + let other_sig = key.sign(b"all is not ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(other_sig.as_ref()); + + assert_eq!( + call_in_wasm( + "test_sr25519_verify", + &calldata.encode(), + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + false.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn ordered_trie_root_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let trie_input = vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()]; + let test_code = WASM_BINARY; + assert_eq!( + call_in_wasm( + "test_ordered_trie_root", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + Layout::::ordered_trie_root(trie_input.iter()).as_bytes().encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn offchain_local_storage_should_work(wasm_method: WasmExecutionMethod) { + use substrate_client::backend::OffchainStorage; + + let mut ext = TestExternalities::default(); + let (offchain, state) = testing::TestOffchainExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + let test_code = WASM_BINARY; + ext.with_ext(|mut ext| { + assert_eq!( + call_in_wasm( + "test_offchain_local_storage", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + assert_eq!(state.read().persistent_storage.get(b"", b"test"), Some(vec![])); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn offchain_http_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let (offchain, state) = testing::TestOffchainExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + state.write().expect_request( + 0, + testing::PendingRequest { + method: "POST".into(), + uri: "http://localhost:12345".into(), + body: vec![1, 2, 3, 4], + headers: vec![("X-Auth".to_owned(), "test".to_owned())], + sent: true, + response: Some(vec![1, 2, 3]), + response_headers: vec![("X-Auth".to_owned(), "hello".to_owned())], + ..Default::default() + }, + ); + + let test_code = WASM_BINARY; + ext.with_ext(|mut ext| { + assert_eq!( + call_in_wasm( + "test_offchain_http", + &[0], + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + }); +} + diff --git a/core/executor/src/integration_tests/sandbox.rs b/core/executor/src/integration_tests/sandbox.rs new file mode 100644 index 0000000000000000000000000000000000000000..6c72a142977687c1f5f1cd6ba93741e8425b1966 --- /dev/null +++ b/core/executor/src/integration_tests/sandbox.rs @@ -0,0 +1,373 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::Encode; +use runtime_test::WASM_BINARY; +use test_case::test_case; +use wabt; + +use crate::{WasmExecutionMethod, call_in_wasm}; +use crate::integration_tests::TestExternalities; + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sandbox_should_work(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) + (func (export "call") + (drop + (call $inc_counter (i32.const 5)) + ) + + (call $inc_counter (i32.const 3)) + ;; current counter value is on the stack + + ;; check whether current == 8 + i32.const 8 + i32.eq + + call $assert + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sandbox_trap(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (func (export "call") + i32.const 0 + call $assert + ) + ) + "#).unwrap(); + + assert_eq!( + call_in_wasm( + "test_sandbox", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + vec![0], + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn sandbox_should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (func (export "call") + i32.const 0 + call $assert + ) + ) + "#).unwrap().encode(); + + let res = call_in_wasm( + "test_exhaust_heap", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + assert!(res.is_err()); + if let Err(err) = res { + assert!(err.to_string().contains("Allocator ran out of space")); + } + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn start_called(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) + + ;; Start function + (start $start) + (func $start + ;; Increment counter by 1 + (drop + (call $inc_counter (i32.const 1)) + ) + ) + + (func (export "call") + ;; Increment counter by 1. The current value is placed on the stack. + (call $inc_counter (i32.const 1)) + + ;; Counter is incremented twice by 1, once there and once in `start` func. + ;; So check the returned value is equal to 2. + i32.const 2 + i32.eq + call $assert + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn invoke_args(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + + (func (export "call") (param $x i32) (param $y i64) + ;; assert that $x = 0x12345678 + (call $assert + (i32.eq + (get_local $x) + (i32.const 0x12345678) + ) + ) + + (call $assert + (i64.eq + (get_local $y) + (i64.const 0x1234567887654321) + ) + ) + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_args", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn return_val(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (func (export "call") (param $x i32) (result i32) + (i32.add + (get_local $x) + (i32.const 1) + ) + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_return_val", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + true.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn unlinkable_module(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (import "env" "non-existent" (func)) + + (func (export "call") + ) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 1u8.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn corrupted_module(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + // Corrupted wasm file + let code = vec![0u8, 0, 0, 0, 1, 0, 0, 0].encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 1u8.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn start_fn_ok(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (func (export "call") + ) + + (func $start + ) + + (start $start) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 0u8.encode(), + ); + }); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn start_fn_traps(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let test_code = WASM_BINARY; + + let code = wabt::wat2wasm(r#" + (module + (func (export "call") + ) + + (func $start + unreachable + ) + + (start $start) + ) + "#).unwrap().encode(); + + assert_eq!( + call_in_wasm( + "test_sandbox_instantiate", + &code, + wasm_method, + &mut ext, + &test_code[..], + 8, + ).unwrap(), + 2u8.encode(), + ); + }); +} diff --git a/core/executor/src/lib.rs b/core/executor/src/lib.rs index 065de451c19dc65c241ee6cd90bd1b45af38886f..3e9dcb588ae4a09eaaae208bc78082a507c05739 100644 --- a/core/executor/src/lib.rs +++ b/core/executor/src/lib.rs @@ -14,39 +14,71 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Temporary crate for contracts implementations. +//! A crate that provides means of executing/dispatching calls into the runtime. //! -//! This will be replaced with WASM contracts stored on-chain. -//! ** NOTE *** -//! This is entirely deprecated with the idea of a single-module Wasm module for state transition. -//! The dispatch table should be replaced with the specific functions needed: -//! - execute_block(bytes) -//! - init_block(PrevBlock?) -> InProgressBlock -//! - add_transaction(InProgressBlock) -> InProgressBlock -//! It is left as is for now as it might be removed before this is ever done. +//! There are a few responsibilities of this crate at the moment: +//! +//! - It provides an implementation of a common entrypoint for calling into the runtime, both +//! wasm and compiled. +//! - It defines the environment for the wasm execution, namely the host functions that are to be +//! provided into the wasm runtime module. +//! - It also provides the required infrastructure for executing the current wasm runtime (specified +//! by the current value of `:code` in the provided externalities), i.e. interfacing with +//! wasm engine used, instance cache. #![warn(missing_docs)] #![recursion_limit="128"] #[macro_use] mod wasm_utils; -mod wasm_executor; +mod wasmi_execution; #[macro_use] mod native_executor; mod sandbox; mod allocator; -mod wasm_runtimes_cache; +mod host_interface; +mod wasm_runtime; +#[cfg(feature = "wasmtime")] +mod wasmtime; +#[cfg(test)] +mod integration_tests; pub mod error; pub use wasmi; -pub use wasm_executor::WasmExecutor; pub use native_executor::{with_native_environment, NativeExecutor, NativeExecutionDispatch}; -pub use wasm_runtimes_cache::RuntimesCache; -pub use state_machine::Externalities; pub use runtime_version::{RuntimeVersion, NativeVersion}; pub use codec::Codec; #[doc(hidden)] -pub use primitives::Blake2Hasher; +pub use primitives::traits::Externalities; +#[doc(hidden)] +pub use wasm_interface; +pub use wasm_runtime::WasmExecutionMethod; + +/// Call the given `function` in the given wasm `code`. +/// +/// The signature of `function` needs to follow the default Substrate function signature. +/// +/// - `call_data`: Will be given as input parameters to `function` +/// - `execution_method`: The execution method to use. +/// - `ext`: The externalities that should be set while executing the wasm function. +/// - `heap_pages`: The number of heap pages to allocate. +/// +/// Returns the `Vec` that contains the return value of the function. +pub fn call_in_wasm( + function: &str, + call_data: &[u8], + execution_method: WasmExecutionMethod, + ext: &mut E, + code: &[u8], + heap_pages: u64, +) -> error::Result> { + let mut instance = wasm_runtime::create_wasm_runtime_with_code( + execution_method, + heap_pages, + code, + )?; + instance.call(ext, function, call_data) +} /// Provides runtime information. pub trait RuntimeInfo { @@ -54,8 +86,31 @@ pub trait RuntimeInfo { fn native_version(&self) -> &NativeVersion; /// Extract RuntimeVersion of given :code block - fn runtime_version> ( + fn runtime_version ( &self, ext: &mut E, ) -> Option; } + +#[cfg(test)] +mod tests { + use super::*; + use runtime_test::WASM_BINARY; + use runtime_io::TestExternalities; + + #[test] + fn call_in_interpreted_wasm_works() { + let mut ext = TestExternalities::default(); + ext.with_ext(|mut ext| { + let res = call_in_wasm( + "test_empty_return", + &[], + WasmExecutionMethod::Interpreted, + &mut ext, + &WASM_BINARY, + 8, + ).unwrap(); + assert_eq!(res, vec![0u8; 0]); + }); + } +} diff --git a/core/executor/src/native_executor.rs b/core/executor/src/native_executor.rs index 937e0033539f0ea3dbd8abf0638be2f507cf443e..0fb84d9972b96eebd152931c29e131afdb4d6e88 100644 --- a/core/executor/src/native_executor.rs +++ b/core/executor/src/native_executor.rs @@ -14,46 +14,47 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::{result, cell::RefCell, panic::UnwindSafe}; +use std::{result, cell::RefCell, panic::{UnwindSafe, AssertUnwindSafe}}; use crate::error::{Error, Result}; -use state_machine::{CodeExecutor, Externalities}; -use crate::wasm_executor::WasmExecutor; +use crate::wasm_runtime::{RuntimesCache, WasmExecutionMethod, WasmRuntime}; +use crate::RuntimeInfo; use runtime_version::{NativeVersion, RuntimeVersion}; use codec::{Decode, Encode}; -use crate::RuntimeInfo; -use primitives::{Blake2Hasher, NativeOrEncoded}; +use primitives::{NativeOrEncoded, traits::{CodeExecutor, Externalities}}; use log::{trace, warn}; -use crate::RuntimesCache; - thread_local! { static RUNTIMES_CACHE: RefCell = RefCell::new(RuntimesCache::new()); } -fn safe_call(f: F) -> Result +/// Default num of pages for the heap +const DEFAULT_HEAP_PAGES: u64 = 1024; + +pub(crate) fn safe_call(f: F) -> Result where F: UnwindSafe + FnOnce() -> U { // Substrate uses custom panic hook that terminates process on panic. Disable termination for the native call. let _guard = panic_handler::AbortGuard::force_unwind(); - ::std::panic::catch_unwind(f).map_err(|_| Error::Runtime) + std::panic::catch_unwind(f).map_err(|_| Error::Runtime) } /// Set up the externalities and safe calling environment to execute calls to a native runtime. /// /// If the inner closure panics, it will be caught and return an error. -pub fn with_native_environment(ext: &mut dyn Externalities, f: F) -> Result +pub fn with_native_environment(ext: &mut dyn Externalities, f: F) -> Result where F: UnwindSafe + FnOnce() -> U { - ::runtime_io::with_externalities(ext, move || safe_call(f)) + externalities::set_and_run_with_externalities(ext, move || safe_call(f)) } -/// Delegate for dispatching a CodeExecutor call to native code. +/// Delegate for dispatching a CodeExecutor call. +/// +/// By dispatching we mean that we execute a runtime function specified by it's name. pub trait NativeExecutionDispatch: Send + Sync { - /// Get the wasm code that the native dispatch will be equivalent to. - fn native_equivalent() -> &'static [u8]; - - /// Dispatch a method and input data to be executed natively. - fn dispatch(ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result>; + /// Dispatch a method in the runtime. + /// + /// If the method with the specified name doesn't exist then `Err` is returned. + fn dispatch(ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result>; /// Provide native runtime version. fn native_version() -> NativeVersion; @@ -64,32 +65,82 @@ pub trait NativeExecutionDispatch: Send + Sync { #[derive(Debug)] pub struct NativeExecutor { /// Dummy field to avoid the compiler complaining about us not using `D`. - _dummy: ::std::marker::PhantomData, - /// The fallback executor in case native isn't available. - fallback: WasmExecutor, + _dummy: std::marker::PhantomData, + /// Method used to execute fallback Wasm code. + fallback_method: WasmExecutionMethod, /// Native runtime version info. native_version: NativeVersion, /// The number of 64KB pages to allocate for Wasm execution. - default_heap_pages: Option, + default_heap_pages: u64, } impl NativeExecutor { /// Create new instance. - pub fn new(default_heap_pages: Option) -> Self { + /// + /// # Parameters + /// + /// `fallback_method` - Method used to execute fallback Wasm code. + /// + /// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution. + /// Defaults to `DEFAULT_HEAP_PAGES` if `None` is provided. + pub fn new(fallback_method: WasmExecutionMethod, default_heap_pages: Option) -> Self { NativeExecutor { _dummy: Default::default(), - fallback: WasmExecutor::new(), + fallback_method, native_version: D::native_version(), - default_heap_pages: default_heap_pages, + default_heap_pages: default_heap_pages.unwrap_or(DEFAULT_HEAP_PAGES), } } + + /// Execute the given closure `f` with the latest runtime (based on the `CODE` key in `ext`). + /// + /// The closure `f` is expected to return `Err(_)` when there happened a `panic!` in native code + /// while executing the runtime in Wasm. If a `panic!` occurred, the runtime is invalidated to + /// prevent any poisoned state. Native runtime execution does not need to report back + /// any `panic!`. + /// + /// # Safety + /// + /// `runtime` and `ext` are given as `AssertUnwindSafe` to the closure. As described above, the + /// runtime is invalidated on any `panic!` to prevent a poisoned state. `ext` is already + /// implicitly handled as unwind safe, as we store it in a global variable while executing the + /// native runtime. + fn with_runtime( + &self, + ext: &mut E, + f: impl for<'a> FnOnce( + AssertUnwindSafe<&'a mut (dyn WasmRuntime + 'static)>, + &'a RuntimeVersion, + AssertUnwindSafe<&'a mut E>, + ) -> Result>, + ) -> Result where E: Externalities { + RUNTIMES_CACHE.with(|cache| { + let mut cache = cache.borrow_mut(); + let (runtime, version, code_hash) = cache.fetch_runtime( + ext, + self.fallback_method, + self.default_heap_pages, + )?; + + let runtime = AssertUnwindSafe(runtime); + let ext = AssertUnwindSafe(ext); + + match f(runtime, version, ext) { + Ok(res) => res, + Err(e) => { + cache.invalidate_runtime(self.fallback_method, code_hash); + Err(e) + } + } + }) + } } impl Clone for NativeExecutor { fn clone(&self) -> Self { NativeExecutor { _dummy: Default::default(), - fallback: self.fallback.clone(), + fallback_method: self.fallback_method, native_version: D::native_version(), default_heap_pages: self.default_heap_pages, } @@ -101,32 +152,28 @@ impl RuntimeInfo for NativeExecutor { &self.native_version } - fn runtime_version>( + fn runtime_version( &self, ext: &mut E, ) -> Option { - RUNTIMES_CACHE.with(|cache| { - let cache = &mut cache.borrow_mut(); - - match cache.fetch_runtime(&self.fallback, ext, self.default_heap_pages) { - Ok(runtime) => runtime.version(), - Err(e) => { - warn!(target: "executor", "Failed to fetch runtime: {:?}", e); - None - } + match self.with_runtime(ext, |_runtime, version, _ext| Ok(Ok(version.clone()))) { + Ok(version) => Some(version), + Err(e) => { + warn!(target: "executor", "Failed to fetch runtime: {:?}", e); + None } - }) + } } } -impl CodeExecutor for NativeExecutor { +impl CodeExecutor for NativeExecutor { type Error = Error; fn call < - E: Externalities, - R:Decode + Encode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe + E: Externalities, + R: Decode + Encode + PartialEq, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, ext: &mut E, @@ -135,20 +182,11 @@ impl CodeExecutor for NativeExecutor, ) -> (Result>, bool){ - RUNTIMES_CACHE.with(|cache| { - let cache = &mut cache.borrow_mut(); - let cached_runtime = match cache.fetch_runtime( - &self.fallback, ext, self.default_heap_pages, - ) { - Ok(cached_runtime) => cached_runtime, - Err(e) => return (Err(e), false), - }; - let onchain_version = cached_runtime.version(); + let mut used_native = false; + let result = self.with_runtime(ext, |mut runtime, onchain_version, mut ext| { match ( use_native, - onchain_version - .as_ref() - .map_or(false, |v| v.can_call_with(&self.native_version.runtime_version)), + onchain_version.can_call_with(&self.native_version.runtime_version), native_call, ) { (_, false, _) => { @@ -157,75 +195,63 @@ impl CodeExecutor for NativeExecutor".into(), |v| format!("{}", v)) ); - ( - cached_runtime.with(|module| - self.fallback - .call_in_wasm_module(ext, module, method, data) - .map(NativeOrEncoded::Encoded) - ), - false + + safe_call( + move || runtime.call(&mut **ext, method, data).map(NativeOrEncoded::Encoded) ) } (false, _, _) => { - ( - cached_runtime.with(|module| - self.fallback - .call_in_wasm_module(ext, module, method, data) - .map(NativeOrEncoded::Encoded) - ), - false + safe_call( + move || runtime.call(&mut **ext, method, data).map(NativeOrEncoded::Encoded) ) - } + }, (true, true, Some(call)) => { trace!( target: "executor", "Request for native execution with native call succeeded (native: {}, chain: {}).", self.native_version.runtime_version, onchain_version - .as_ref() - .map_or_else(||"".into(), |v| format!("{}", v)) ); - ( - with_native_environment(ext, move || (call)()) - .and_then(|r| r.map(NativeOrEncoded::Native).map_err(|s| Error::ApiError(s.to_string()))), - true - ) + + used_native = true; + let res = with_native_environment(&mut **ext, move || (call)()) + .and_then(|r| r + .map(NativeOrEncoded::Native) + .map_err(|s| Error::ApiError(s.to_string())) + ); + + Ok(res) } _ => { trace!( target: "executor", "Request for native execution succeeded (native: {}, chain: {})", self.native_version.runtime_version, - onchain_version.as_ref().map_or_else(||"".into(), |v| format!("{}", v)) + onchain_version ); - (D::dispatch(ext, method, data).map(NativeOrEncoded::Encoded), true) + + used_native = true; + Ok(D::dispatch(&mut **ext, method, data).map(NativeOrEncoded::Encoded)) } } - }) + }); + (result, used_native) } } /// Implements a `NativeExecutionDispatch` for provided parameters. #[macro_export] macro_rules! native_executor_instance { - ( $pub:vis $name:ident, $dispatcher:path, $version:path, $code:expr) => { + ( $pub:vis $name:ident, $dispatcher:path, $version:path $(,)?) => { /// A unit struct which implements `NativeExecutionDispatch` feeding in the hard-coded runtime. $pub struct $name; - $crate::native_executor_instance!(IMPL $name, $dispatcher, $version, $code); + $crate::native_executor_instance!(IMPL $name, $dispatcher, $version); }; - (IMPL $name:ident, $dispatcher:path, $version:path, $code:expr) => { + (IMPL $name:ident, $dispatcher:path, $version:path) => { impl $crate::NativeExecutionDispatch for $name { - fn native_equivalent() -> &'static [u8] { - // WARNING!!! This assumes that the runtime was built *before* the main project. Until we - // get a proper build script, this must be strictly adhered to or things will go wrong. - $code - } - fn dispatch( - ext: &mut $crate::Externalities<$crate::Blake2Hasher>, + ext: &mut $crate::Externalities, method: &str, data: &[u8] ) -> $crate::error::Result> { diff --git a/core/executor/src/sandbox.rs b/core/executor/src/sandbox.rs index 6687738abc89750acefae9b9dbdc39bba5a27ec1..87edae8c3037d9850ce6fb738b3e1995dd78436c 100644 --- a/core/executor/src/sandbox.rs +++ b/core/executor/src/sandbox.rs @@ -23,16 +23,23 @@ use std::{collections::HashMap, rc::Rc}; use codec::{Decode, Encode}; use primitives::sandbox as sandbox_primitives; use wasmi::{ - Externals, FuncRef, ImportResolver, MemoryInstance, MemoryRef, Module, ModuleInstance, + Externals, ImportResolver, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef, RuntimeArgs, RuntimeValue, Trap, TrapKind, memory_units::Pages, }; +use wasm_interface::{Pointer, WordSize}; /// Index of a function inside the supervisor. /// /// This is a typically an index in the default table of the supervisor, however /// the exact meaning of this index is depends on the implementation of dispatch function. #[derive(Copy, Clone, Debug, PartialEq)] -struct SupervisorFuncIndex(usize); +pub struct SupervisorFuncIndex(usize); + +impl From for usize { + fn from(index: SupervisorFuncIndex) -> Self { + index.0 + } +} /// Index of a function within guest index space. /// @@ -72,7 +79,7 @@ impl ImportResolver for Imports { module_name: &str, field_name: &str, signature: &::wasmi::Signature, - ) -> std::result::Result { + ) -> std::result::Result { let key = ( module_name.as_bytes().to_owned(), field_name.as_bytes().to_owned(), @@ -137,11 +144,14 @@ impl ImportResolver for Imports { /// /// Note that this functions are only called in the `supervisor` context. pub trait SandboxCapabilities { + /// Represents a function reference into the supervisor environment. + type SupervisorFuncRef; + /// Returns a reference to an associated sandbox `Store`. - fn store(&self) -> &Store; + fn store(&self) -> &Store; /// Returns a mutable reference to an associated sandbox `Store`. - fn store_mut(&mut self) -> &mut Store; + fn store_mut(&mut self) -> &mut Store; /// Allocate space of the specified length in the supervisor memory. /// @@ -150,7 +160,7 @@ pub trait SandboxCapabilities { /// Returns `Err` if allocation not possible or errors during heap management. /// /// Returns pointer to the allocated block. - fn allocate(&mut self, len: u32) -> Result; + fn allocate(&mut self, len: WordSize) -> Result>; /// Deallocate space specified by the pointer that was previously returned by [`allocate`]. /// @@ -159,35 +169,57 @@ pub trait SandboxCapabilities { /// Returns `Err` if deallocation not possible or because of errors in heap management. /// /// [`allocate`]: #tymethod.allocate - fn deallocate(&mut self, ptr: u32) -> Result<()>; + fn deallocate(&mut self, ptr: Pointer) -> Result<()>; /// Write `data` into the supervisor memory at offset specified by `ptr`. /// /// # Errors /// /// Returns `Err` if `ptr + data.len()` is out of bounds. - fn write_memory(&mut self, ptr: u32, data: &[u8]) -> Result<()>; + fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<()>; /// Read `len` bytes from the supervisor memory. /// /// # Errors /// /// Returns `Err` if `ptr + len` is out of bounds. - fn read_memory(&self, ptr: u32, len: u32) -> Result>; + fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result>; + + /// Invoke a function in the supervisor environment. + /// + /// This first invokes the dispatch_thunk function, passing in the function index of the + /// desired function to call and serialized arguments. The thunk calls the desired function + /// with the deserialized arguments, then serializes the result into memory and returns + /// reference. The pointer to and length of the result in linear memory is encoded into an i64, + /// with the upper 32 bits representing the pointer and the lower 32 bits representing the + /// length. + /// + /// # Errors + /// + /// Returns `Err` if the dispatch_thunk function has an incorrect signature or traps during + /// execution. + fn invoke( + &mut self, + dispatch_thunk: &Self::SupervisorFuncRef, + invoke_args_ptr: Pointer, + invoke_args_len: WordSize, + state: u32, + func_idx: SupervisorFuncIndex, + ) -> Result; } /// Implementation of [`Externals`] that allows execution of guest module with /// [externals][`Externals`] that might refer functions defined by supervisor. /// /// [`Externals`]: ../../wasmi/trait.Externals.html -pub struct GuestExternals<'a, FE: SandboxCapabilities + Externals + 'a> { +pub struct GuestExternals<'a, FE: SandboxCapabilities + 'a> { supervisor_externals: &'a mut FE, - sandbox_instance: &'a SandboxInstance, + sandbox_instance: &'a SandboxInstance, state: u32, } fn trap(msg: &'static str) -> Trap { - TrapKind::Host(Box::new(Error::Other(msg))).into() + TrapKind::Host(Box::new(Error::Other(msg.into()))).into() } fn deserialize_result(serialized_result: &[u8]) -> std::result::Result, Trap> { @@ -204,7 +236,7 @@ fn deserialize_result(serialized_result: &[u8]) -> std::result::Result Externals for GuestExternals<'a, FE> { +impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> { fn invoke_index( &mut self, index: usize, @@ -213,7 +245,6 @@ impl<'a, FE: SandboxCapabilities + Externals + 'a> Externals for GuestExternals< // Make `index` typesafe again. let index = GuestFuncIndex(index); - let dispatch_thunk = self.sandbox_instance.dispatch_thunk.clone(); let func_idx = self.sandbox_instance .guest_to_supervisor_mapping .func_by_guest_index(index) @@ -236,34 +267,26 @@ impl<'a, FE: SandboxCapabilities + Externals + 'a> Externals for GuestExternals< // Move serialized arguments inside the memory and invoke dispatch thunk and // then free allocated memory. - let invoke_args_ptr = self.supervisor_externals - .allocate(invoke_args_data.len() as u32)?; - self.supervisor_externals - .write_memory(invoke_args_ptr, &invoke_args_data)?; - let result = ::wasmi::FuncInstance::invoke( - &dispatch_thunk, - &[ - RuntimeValue::I32(invoke_args_ptr as i32), - RuntimeValue::I32(invoke_args_data.len() as i32), - RuntimeValue::I32(state as i32), - RuntimeValue::I32(func_idx.0 as i32), - ], - self.supervisor_externals, - ); + let invoke_args_len = invoke_args_data.len() as WordSize; + let invoke_args_ptr = self.supervisor_externals.allocate(invoke_args_len)?; + self.supervisor_externals.write_memory(invoke_args_ptr, &invoke_args_data)?; + let result = self.supervisor_externals.invoke( + &self.sandbox_instance.dispatch_thunk, + invoke_args_ptr, + invoke_args_len, + state, + func_idx, + )?; self.supervisor_externals.deallocate(invoke_args_ptr)?; // dispatch_thunk returns pointer to serialized arguments. - let (serialized_result_val_ptr, serialized_result_val_len) = match result { - // Unpack pointer and len of the serialized result data. - Ok(Some(RuntimeValue::I64(v))) => { - // Cast to u64 to use zero-extension. - let v = v as u64; - let ptr = (v as u64 >> 32) as u32; - let len = (v & 0xFFFFFFFF) as u32; - (ptr, len) - } - Ok(_) => return Err(trap("Supervisor function returned unexpected result!")), - Err(_) => return Err(trap("Supervisor function trapped!")), + // Unpack pointer and len of the serialized result data. + let (serialized_result_val_ptr, serialized_result_val_len) = { + // Cast to u64 to use zero-extension. + let v = result as u64; + let ptr = (v as u64 >> 32) as u32; + let len = (v & 0xFFFFFFFF) as u32; + (Pointer::new(ptr), len) }; let serialized_result_val = self.supervisor_externals @@ -271,21 +294,18 @@ impl<'a, FE: SandboxCapabilities + Externals + 'a> Externals for GuestExternals< self.supervisor_externals .deallocate(serialized_result_val_ptr)?; - // We do not have to check the signature here, because it's automatically - // checked by wasmi. - deserialize_result(&serialized_result_val) } } fn with_guest_externals( supervisor_externals: &mut FE, - sandbox_instance: &SandboxInstance, + sandbox_instance: &SandboxInstance, state: u32, f: F, ) -> R where - FE: SandboxCapabilities + Externals, + FE: SandboxCapabilities, F: FnOnce(&mut GuestExternals) -> R, { let mut guest_externals = GuestExternals { @@ -307,14 +327,16 @@ where /// it's required to provide supervisor externals: it will be used to execute /// code in the supervisor context. /// +/// This is generic over a supervisor function reference type. +/// /// [`invoke`]: #method.invoke -pub struct SandboxInstance { +pub struct SandboxInstance { instance: ModuleRef, - dispatch_thunk: FuncRef, + dispatch_thunk: FR, guest_to_supervisor_mapping: GuestToSupervisorFunctionMapping, } -impl SandboxInstance { +impl SandboxInstance { /// Invoke an exported function by a name. /// /// `supervisor_externals` is required to execute the implementations @@ -322,7 +344,7 @@ impl SandboxInstance { /// /// The `state` parameter can be used to provide custom data for /// these syscall implementations. - pub fn invoke( + pub fn invoke>( &self, export_name: &str, args: &[RuntimeValue], @@ -411,9 +433,9 @@ fn decode_environment_definition( /// - Module in `wasm` is invalid or couldn't be instantiated. /// /// [`EnvironmentDefinition`]: ../../sandbox/struct.EnvironmentDefinition.html -pub fn instantiate( +pub fn instantiate( supervisor_externals: &mut FE, - dispatch_thunk: FuncRef, + dispatch_thunk: FE::SupervisorFuncRef, wasm: &[u8], raw_env_def: &[u8], state: u32, @@ -452,15 +474,17 @@ pub fn instantiate( } /// This struct keeps track of all sandboxed components. -pub struct Store { +/// +/// This is generic over a supervisor function reference type. +pub struct Store { // Memories and instances are `Some` untill torndown. - instances: Vec>>, + instances: Vec>>>, memories: Vec>, } -impl Store { +impl Store { /// Create a new empty sandbox store. - pub fn new() -> Store { + pub fn new() -> Self { Store { instances: Vec::new(), memories: Vec::new(), @@ -496,7 +520,7 @@ impl Store { /// /// Returns `Err` If `instance_idx` isn't a valid index of an instance or /// instance is already torndown. - pub fn instance(&self, instance_idx: u32) -> Result> { + pub fn instance(&self, instance_idx: u32) -> Result>> { self.instances .get(instance_idx as usize) .cloned() @@ -552,274 +576,9 @@ impl Store { } } - fn register_sandbox_instance(&mut self, sandbox_instance: Rc) -> u32 { + fn register_sandbox_instance(&mut self, sandbox_instance: Rc>) -> u32 { let instance_idx = self.instances.len(); self.instances.push(Some(sandbox_instance)); instance_idx as u32 } } - -#[cfg(test)] -mod tests { - use super::*; - use primitives::{Blake2Hasher}; - use crate::wasm_executor::WasmExecutor; - use state_machine::TestExternalities as CoreTestExternalities; - use wabt; - use runtime_test::WASM_BINARY; - - type TestExternalities = CoreTestExternalities; - - #[test] - fn sandbox_should_work() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) - (func (export "call") - (drop - (call $inc_counter (i32.const 5)) - ) - - (call $inc_counter (i32.const 3)) - ;; current counter value is on the stack - - ;; check whether current == 8 - i32.const 8 - i32.eq - - call $assert - ) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(), - vec![1], - ); - } - - #[test] - fn sandbox_trap() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (func (export "call") - i32.const 0 - call $assert - ) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(), - vec![0], - ); - } - - #[test] - fn sandbox_should_trap_when_heap_exhausted() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (func (export "call") - i32.const 0 - call $assert - ) - ) - "#).unwrap(); - - let res = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_exhaust_heap", &code); - assert_eq!(res.is_err(), true); - if let Err(err) = res { - assert_eq!( - format!("{}", err), - format!("{}", wasmi::Error::Trap(Error::AllocatorOutOfSpace.into())) - ); - } - } - - #[test] - fn start_called() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - (import "env" "inc_counter" (func $inc_counter (param i32) (result i32))) - - ;; Start function - (start $start) - (func $start - ;; Increment counter by 1 - (drop - (call $inc_counter (i32.const 1)) - ) - ) - - (func (export "call") - ;; Increment counter by 1. The current value is placed on the stack. - (call $inc_counter (i32.const 1)) - - ;; Counter is incremented twice by 1, once there and once in `start` func. - ;; So check the returned value is equal to 2. - i32.const 2 - i32.eq - call $assert - ) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox", &code).unwrap(), - vec![1], - ); - } - - #[test] - fn invoke_args() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "assert" (func $assert (param i32))) - - (func (export "call") (param $x i32) (param $y i64) - ;; assert that $x = 0x12345678 - (call $assert - (i32.eq - (get_local $x) - (i32.const 0x12345678) - ) - ) - - (call $assert - (i64.eq - (get_local $y) - (i64.const 0x1234567887654321) - ) - ) - ) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_args", &code).unwrap(), - vec![1], - ); - } - - #[test] - fn return_val() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (func (export "call") (param $x i32) (result i32) - (i32.add - (get_local $x) - (i32.const 1) - ) - ) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_return_val", &code).unwrap(), - vec![1], - ); - } - - #[test] - fn unlinkable_module() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (import "env" "non-existent" (func)) - - (func (export "call") - ) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(), - vec![1], - ); - } - - #[test] - fn corrupted_module() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - // Corrupted wasm file - let code = &[0, 0, 0, 0, 1, 0, 0, 0]; - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", code).unwrap(), - vec![1], - ); - } - - #[test] - fn start_fn_ok() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (func (export "call") - ) - - (func $start - ) - - (start $start) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(), - vec![0], - ); - } - - #[test] - fn start_fn_traps() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - - let code = wabt::wat2wasm(r#" - (module - (func (export "call") - ) - - (func $start - unreachable - ) - - (start $start) - ) - "#).unwrap(); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sandbox_instantiate", &code).unwrap(), - vec![2], - ); - } -} diff --git a/core/executor/src/wasm_executor.rs b/core/executor/src/wasm_executor.rs deleted file mode 100644 index 3eed549773f1a03cc2994b42831bb8191b069e19..0000000000000000000000000000000000000000 --- a/core/executor/src/wasm_executor.rs +++ /dev/null @@ -1,1713 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Rust implementation of Substrate contracts. - -use std::{collections::HashMap, convert::TryFrom, str}; -use tiny_keccak; -use secp256k1; - -use wasmi::{ - Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, - memory_units::Pages, RuntimeValue::{I32, I64, self}, -}; -use state_machine::{Externalities, ChildStorageKey}; -use crate::error::{Error, Result}; -use codec::Encode; -use primitives::{ - blake2_128, blake2_256, twox_64, twox_128, twox_256, ed25519, sr25519, Pair, crypto::KeyTypeId, - offchain, hexdisplay::HexDisplay, sandbox as sandbox_primitives, H256, Blake2Hasher, -}; -use trie::{TrieConfiguration, trie_types::Layout}; -use crate::sandbox; -use crate::allocator; -use log::trace; - -#[cfg(feature="wasm-extern-trace")] -macro_rules! debug_trace { - ( $( $x:tt )* ) => ( trace!( $( $x )* ) ) -} -#[cfg(not(feature="wasm-extern-trace"))] -macro_rules! debug_trace { - ( $( $x:tt )* ) => () -} - -struct FunctionExecutor<'e, E: Externalities + 'e> { - sandbox_store: sandbox::Store, - heap: allocator::FreeingBumpHeapAllocator, - memory: MemoryRef, - table: Option, - ext: &'e mut E, - hash_lookup: HashMap, Vec>, -} - -impl<'e, E: Externalities> FunctionExecutor<'e, E> { - fn new(m: MemoryRef, heap_base: u32, t: Option, e: &'e mut E) -> Result { - Ok(FunctionExecutor { - sandbox_store: sandbox::Store::new(), - heap: allocator::FreeingBumpHeapAllocator::new(m.clone(), heap_base), - memory: m, - table: t, - ext: e, - hash_lookup: HashMap::new(), - }) - } -} - -impl<'e, E: Externalities> sandbox::SandboxCapabilities for FunctionExecutor<'e, E> { - fn store(&self) -> &sandbox::Store { - &self.sandbox_store - } - fn store_mut(&mut self) -> &mut sandbox::Store { - &mut self.sandbox_store - } - fn allocate(&mut self, len: u32) -> Result { - self.heap.allocate(len) - } - fn deallocate(&mut self, ptr: u32) -> Result<()> { - self.heap.deallocate(ptr) - } - fn write_memory(&mut self, ptr: u32, data: &[u8]) -> Result<()> { - self.memory.set(ptr, data).map_err(Into::into) - } - fn read_memory(&self, ptr: u32, len: u32) -> Result> { - self.memory.get(ptr, len as usize).map_err(Into::into) - } -} - -trait WritePrimitive { - fn write_primitive(&self, offset: u32, t: T) -> Result<()>; -} - -impl WritePrimitive for MemoryInstance { - fn write_primitive(&self, offset: u32, t: u32) -> Result<()> { - use byteorder::{LittleEndian, ByteOrder}; - let mut r = [0u8; 4]; - LittleEndian::write_u32(&mut r, t); - self.set(offset, &r).map_err(Into::into) - } -} - -trait ReadPrimitive { - fn read_primitive(&self, offset: u32) -> Result; -} - -impl ReadPrimitive for MemoryInstance { - fn read_primitive(&self, offset: u32) -> Result { - use byteorder::{LittleEndian, ByteOrder}; - let result = self.get(offset, 4)?; - Ok(LittleEndian::read_u32(&result)) - } -} - -fn deadline_to_timestamp(deadline: u64) -> Option { - if deadline == 0 { - None - } else { - Some(offchain::Timestamp::from_unix_millis(deadline)) - } -} - -impl_function_executor!(this: FunctionExecutor<'e, E>, - ext_print_utf8(utf8_data: *const u8, utf8_len: u32) => { - if let Ok(utf8) = this.memory.get(utf8_data, utf8_len as usize) { - if let Ok(message) = String::from_utf8(utf8) { - println!("{}", message); - } - } - Ok(()) - }, - ext_print_hex(data: *const u8, len: u32) => { - if let Ok(hex) = this.memory.get(data, len as usize) { - println!("{}", HexDisplay::from(&hex)); - } - Ok(()) - }, - ext_print_num(number: u64) => { - println!("{}", number); - Ok(()) - }, - ext_malloc(size: usize) -> *mut u8 => { - let r = this.heap.allocate(size)?; - debug_trace!(target: "sr-io", "malloc {} bytes at {}", size, r); - Ok(r) - }, - ext_free(addr: *mut u8) => { - this.heap.deallocate(addr)?; - debug_trace!(target: "sr-io", "free {}", addr); - Ok(()) - }, - ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => { - let key = this.memory.get(key_data, key_len as usize) - .map_err(|_| "Invalid attempt to determine key in ext_set_storage")?; - let value = this.memory.get(value_data, value_len as usize) - .map_err(|_| "Invalid attempt to determine value in ext_set_storage")?; - if let Some(_preimage) = this.hash_lookup.get(&key) { - debug_trace!( - target: "wasm-trace", - "*** Setting storage: %{} -> {} [k={}]", - primitives::hexdisplay::ascii_format(&_preimage), - HexDisplay::from(&value), - HexDisplay::from(&key), - ); - } else { - debug_trace!( - target: "wasm-trace", - "*** Setting storage: {} -> {} [k={}]", - primitives::hexdisplay::ascii_format(&key), - HexDisplay::from(&value), - HexDisplay::from(&key), - ); - } - this.ext.set_storage(key, value); - Ok(()) - }, - ext_set_child_storage( - storage_key_data: *const u8, - storage_key_len: u32, - key_data: *const u8, - key_len: u32, - value_data: *const u8, - value_len: u32 - ) => { - let storage_key = this.memory.get(storage_key_data, storage_key_len as usize) - .map_err(|_| "Invalid attempt to determine storage_key in ext_set_child_storage")?; - let key = this.memory.get(key_data, key_len as usize) - .map_err(|_| "Invalid attempt to determine key in ext_set_child_storage")?; - let value = this.memory.get(value_data, value_len as usize) - .map_err(|_| "Invalid attempt to determine value in ext_set_child_storage")?; - if let Some(_preimage) = this.hash_lookup.get(&key) { - debug_trace!( - target: "wasm-trace", "*** Setting child storage: {} -> %{} -> {} [k={}]", - primitives::hexdisplay::ascii_format(&storage_key), - primitives::hexdisplay::ascii_format(&_preimage), - HexDisplay::from(&value), - HexDisplay::from(&key) - ); - } else { - debug_trace!( - target: "wasm-trace", "*** Setting child storage: {} -> {} -> {} [k={}]", - primitives::hexdisplay::ascii_format(&storage_key), - primitives::hexdisplay::ascii_format(&key), - HexDisplay::from(&value), - HexDisplay::from(&key) - ); - } - let storage_key = ChildStorageKey::from_vec(storage_key) - .ok_or_else(|| "ext_set_child_storage: child storage key is invalid")?; - this.ext.set_child_storage(storage_key, key, value); - Ok(()) - }, - ext_clear_child_storage( - storage_key_data: *const u8, - storage_key_len: u32, - key_data: *const u8, - key_len: u32 - ) => { - let storage_key = this.memory.get( - storage_key_data, - storage_key_len as usize - ).map_err(|_| "Invalid attempt to determine storage_key in ext_clear_child_storage")?; - let key = this.memory.get(key_data, key_len as usize) - .map_err(|_| "Invalid attempt to determine key in ext_clear_child_storage")?; - debug_trace!( - target: "wasm-trace", "*** Clearing child storage: {} -> {} [k={}]", - primitives::hexdisplay::ascii_format(&storage_key), - if let Some(_preimage) = this.hash_lookup.get(&key) { - format!("%{}", primitives::hexdisplay::ascii_format(&_preimage)) - } else { - format!(" {}", primitives::hexdisplay::ascii_format(&key)) - }, - HexDisplay::from(&key) - ); - let storage_key = ChildStorageKey::from_vec(storage_key) - .ok_or_else(|| "ext_clear_child_storage: child storage key is not valid")?; - - this.ext.clear_child_storage(storage_key, &key); - Ok(()) - }, - ext_clear_storage(key_data: *const u8, key_len: u32) => { - let key = this.memory.get(key_data, key_len as usize) - .map_err(|_| "Invalid attempt to determine key in ext_clear_storage")?; - debug_trace!( - target: "wasm-trace", "*** Clearing storage: {} [k={}]", - if let Some(_preimage) = this.hash_lookup.get(&key) { - format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) - } else { - format!(" {}", ::primitives::hexdisplay::ascii_format(&key)) - }, - HexDisplay::from(&key) - ); - this.ext.clear_storage(&key); - Ok(()) - }, - ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 => { - let key = this.memory.get(key_data, key_len as usize) - .map_err(|_| "Invalid attempt to determine key in ext_exists_storage")?; - Ok(if this.ext.exists_storage(&key) { 1 } else { 0 }) - }, - ext_exists_child_storage( - storage_key_data: *const u8, - storage_key_len: u32, - key_data: *const u8, - key_len: u32 - ) -> u32 => { - let storage_key = this.memory.get( - storage_key_data, - storage_key_len as usize - ).map_err(|_| "Invalid attempt to determine storage_key in ext_exists_child_storage")?; - let key = this.memory.get(key_data, key_len as usize) - .map_err(|_| "Invalid attempt to determine key in ext_exists_child_storage")?; - let storage_key = ChildStorageKey::from_vec(storage_key) - .ok_or_else(|| "ext_exists_child_storage: child storage key is not valid")?; - Ok(if this.ext.exists_child_storage(storage_key, &key) { 1 } else { 0 }) - }, - ext_clear_prefix(prefix_data: *const u8, prefix_len: u32) => { - let prefix = this.memory.get(prefix_data, prefix_len as usize) - .map_err(|_| "Invalid attempt to determine prefix in ext_clear_prefix")?; - this.ext.clear_prefix(&prefix); - Ok(()) - }, - ext_clear_child_prefix( - storage_key_data: *const u8, - storage_key_len: u32, - prefix_data: *const u8, - prefix_len: u32 - ) => { - let storage_key = this.memory.get( - storage_key_data, - storage_key_len as usize - ).map_err(|_| "Invalid attempt to determine storage_key in ext_clear_child_prefix")?; - let storage_key = ChildStorageKey::from_vec(storage_key) - .ok_or_else(|| "ext_clear_child_prefix: child storage key is not valid")?; - let prefix = this.memory.get(prefix_data, prefix_len as usize) - .map_err(|_| "Invalid attempt to determine prefix in ext_clear_child_prefix")?; - this.ext.clear_child_prefix(storage_key, &prefix); - Ok(()) - }, - ext_kill_child_storage(storage_key_data: *const u8, storage_key_len: u32) => { - let storage_key = this.memory.get( - storage_key_data, - storage_key_len as usize - ).map_err(|_| "Invalid attempt to determine storage_key in ext_kill_child_storage")?; - let storage_key = ChildStorageKey::from_vec(storage_key) - .ok_or_else(|| "ext_exists_child_storage: child storage key is not valid")?; - this.ext.kill_child_storage(storage_key); - Ok(()) - }, - // return 0 and place u32::max_value() into written_out if no value exists for the key. - ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8 => { - let key = this.memory.get( - key_data, - key_len as usize - ).map_err(|_| "Invalid attempt to determine key in ext_get_allocated_storage")?; - let maybe_value = this.ext.storage(&key); - - debug_trace!( - target: "wasm-trace", "*** Getting storage: {} == {} [k={}]", - if let Some(_preimage) = this.hash_lookup.get(&key) { - format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) - } else { - format!(" {}", ::primitives::hexdisplay::ascii_format(&key)) - }, - if let Some(ref b) = maybe_value { - &format!("{}", HexDisplay::from(b)) - } else { - "" - }, - HexDisplay::from(&key), - ); - - if let Some(value) = maybe_value { - let offset = this.heap.allocate(value.len() as u32)? as u32; - this.memory.set(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_get_allocated_storage")?; - this.memory.write_primitive(written_out, value.len() as u32) - .map_err(|_| "Invalid attempt to write written_out in ext_get_allocated_storage")?; - Ok(offset) - } else { - this.memory.write_primitive(written_out, u32::max_value()) - .map_err(|_| "Invalid attempt to write failed written_out in ext_get_allocated_storage")?; - Ok(0) - } - }, - // return 0 and place u32::max_value() into written_out if no value exists for the key. - ext_get_allocated_child_storage( - storage_key_data: *const u8, - storage_key_len: u32, - key_data: *const u8, - key_len: u32, - written_out: *mut u32 - ) -> *mut u8 => { - let storage_key = this.memory.get( - storage_key_data, - storage_key_len as usize - ).map_err(|_| "Invalid attempt to determine storage_key in ext_get_allocated_child_storage")?; - let key = this.memory.get( - key_data, - key_len as usize - ).map_err(|_| "Invalid attempt to determine key in ext_get_allocated_child_storage")?; - - let maybe_value = { - let storage_key = ChildStorageKey::from_slice(&storage_key) - .ok_or_else(|| "ext_get_allocated_child_storage: child storage key is not valid")?; - this.ext.child_storage(storage_key, &key) - }; - - debug_trace!( - target: "wasm-trace", "*** Getting child storage: {} -> {} == {} [k={}]", - primitives::hexdisplay::ascii_format(&storage_key), - if let Some(_preimage) = this.hash_lookup.get(&key) { - format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) - } else { - format!(" {}", ::primitives::hexdisplay::ascii_format(&key)) - }, - if let Some(ref b) = maybe_value { - &format!("{}", HexDisplay::from(b)) - } else { - "" - }, - HexDisplay::from(&key), - ); - - if let Some(value) = maybe_value { - let offset = this.heap.allocate(value.len() as u32)? as u32; - this.memory.set(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_get_allocated_child_storage")?; - this.memory.write_primitive(written_out, value.len() as u32) - .map_err(|_| "Invalid attempt to write written_out in ext_get_allocated_child_storage")?; - Ok(offset) - } else { - this.memory.write_primitive(written_out, u32::max_value()) - .map_err(|_| "Invalid attempt to write failed written_out in ext_get_allocated_child_storage")?; - Ok(0) - } - }, - // return u32::max_value() if no value exists for the key. - ext_get_storage_into( - key_data: *const u8, - key_len: u32, - value_data: *mut u8, - value_len: u32, - value_offset: u32 - ) -> u32 => { - let key = this.memory.get(key_data, key_len as usize) - .map_err(|_| "Invalid attempt to get key in ext_get_storage_into")?; - let maybe_value = this.ext.storage(&key); - debug_trace!( - target: "wasm-trace", "*** Getting storage: {} == {} [k={}]", - if let Some(_preimage) = this.hash_lookup.get(&key) { - format!("%{}", primitives::hexdisplay::ascii_format(&_preimage)) - } else { - format!(" {}", primitives::hexdisplay::ascii_format(&key)) - }, - if let Some(ref b) = maybe_value { - &format!("{}", HexDisplay::from(b)) - } else { - "" - }, - HexDisplay::from(&key), - ); - - if let Some(value) = maybe_value { - let value = &value[value_offset as usize..]; - let written = std::cmp::min(value_len as usize, value.len()); - this.memory.set(value_data, &value[..written]) - .map_err(|_| "Invalid attempt to set value in ext_get_storage_into")?; - Ok(value.len() as u32) - } else { - Ok(u32::max_value()) - } - }, - // return u32::max_value() if no value exists for the key. - ext_get_child_storage_into( - storage_key_data: *const u8, - storage_key_len: u32, - key_data: *const u8, - key_len: u32, - value_data: *mut u8, - value_len: u32, - value_offset: u32 - ) -> u32 => { - let storage_key = this.memory.get( - storage_key_data, - storage_key_len as usize - ).map_err(|_| "Invalid attempt to determine storage_key in ext_get_child_storage_into")?; - let key = this.memory.get( - key_data, - key_len as usize - ).map_err(|_| "Invalid attempt to get key in ext_get_child_storage_into")?; - - let maybe_value = { - let storage_key = ChildStorageKey::from_slice(&*storage_key) - .ok_or_else(|| "ext_get_child_storage_into: child storage key is not valid")?; - this.ext.child_storage(storage_key, &key) - }; - debug_trace!( - target: "wasm-trace", "*** Getting storage: {} -> {} == {} [k={}]", - primitives::hexdisplay::ascii_format(&storage_key), - if let Some(_preimage) = this.hash_lookup.get(&key) { - format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) - } else { - format!(" {}", ::primitives::hexdisplay::ascii_format(&key)) - }, - if let Some(ref b) = maybe_value { - &format!("{}", HexDisplay::from(b)) - } else { - "" - }, - HexDisplay::from(&key), - ); - - if let Some(value) = maybe_value { - let value = &value[value_offset as usize..]; - let written = std::cmp::min(value_len as usize, value.len()); - this.memory.set(value_data, &value[..written]) - .map_err(|_| "Invalid attempt to set value in ext_get_child_storage_into")?; - Ok(value.len() as u32) - } else { - Ok(u32::max_value()) - } - }, - ext_storage_root(result: *mut u8) => { - let r = this.ext.storage_root(); - this.memory.set(result, r.as_ref()) - .map_err(|_| "Invalid attempt to set memory in ext_storage_root")?; - Ok(()) - }, - ext_child_storage_root( - storage_key_data: *const u8, - storage_key_len: u32, - written_out: *mut u32 - ) -> *mut u8 => { - let storage_key = this.memory.get(storage_key_data, storage_key_len as usize) - .map_err(|_| "Invalid attempt to determine storage_key in ext_child_storage_root")?; - let storage_key = ChildStorageKey::from_slice(&*storage_key) - .ok_or_else(|| "ext_child_storage_root: child storage key is not valid")?; - let value = this.ext.child_storage_root(storage_key); - - let offset = this.heap.allocate(value.len() as u32)? as u32; - this.memory.set(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_child_storage_root")?; - this.memory.write_primitive(written_out, value.len() as u32) - .map_err(|_| "Invalid attempt to write written_out in ext_child_storage_root")?; - Ok(offset) - }, - ext_storage_changes_root(parent_hash_data: *const u8, parent_hash_len: u32, result: *mut u8) -> u32 => { - let mut parent_hash = H256::default(); - if parent_hash_len != parent_hash.as_ref().len() as u32 { - return Err("Invalid parent_hash_len in ext_storage_changes_root".into()); - } - let raw_parent_hash = this.memory.get(parent_hash_data, parent_hash_len as usize) - .map_err(|_| "Invalid attempt to get parent_hash in ext_storage_changes_root")?; - parent_hash.as_mut().copy_from_slice(&raw_parent_hash[..]); - let r = this.ext.storage_changes_root(parent_hash) - .map_err(|_| "Invaid parent_hash passed to ext_storage_changes_root")?; - if let Some(r) = r { - this.memory.set(result, &r[..]) - .map_err(|_| "Invalid attempt to set memory in ext_storage_changes_root")?; - Ok(1) - } else { - Ok(0) - } - }, - ext_blake2_256_enumerated_trie_root( - values_data: *const u8, - lens_data: *const u32, - lens_len: u32, - result: *mut u8 - ) => { - let values = (0..lens_len) - .map(|i| this.memory.read_primitive(lens_data + i * 4)) - .collect::>>()? - .into_iter() - .scan(0u32, |acc, v| { let o = *acc; *acc += v; Some((o, v)) }) - .map(|(offset, len)| - this.memory.get(values_data + offset, len as usize) - .map_err(|_| - Error::from( - "Invalid attempt to get memory in ext_blake2_256_enumerated_trie_root" - ) - ) - ) - .collect::>>()?; - let r = Layout::::ordered_trie_root(values.into_iter()); - this.memory.set(result, &r[..]) - .map_err(|_| "Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root")?; - Ok(()) - }, - ext_chain_id() -> u64 => { - Ok(this.ext.chain_id()) - }, - ext_twox_64(data: *const u8, len: u32, out: *mut u8) => { - let result: [u8; 8] = if len == 0 { - let hashed = twox_64(&[0u8; 0]); - debug_trace!(target: "xxhash", "XXhash: '' -> {}", HexDisplay::from(&hashed)); - this.hash_lookup.insert(hashed.to_vec(), vec![]); - hashed - } else { - let key = this.memory.get(data, len as usize) - .map_err(|_| "Invalid attempt to get key in ext_twox_64")?; - let hashed_key = twox_64(&key); - - debug_trace!( - target: "xxhash", "XXhash: {} -> {}", - if let Ok(_skey) = str::from_utf8(&key) { - _skey - } else { - &format!("{}", HexDisplay::from(&key)) - }, - HexDisplay::from(&hashed_key), - ); - - this.hash_lookup.insert(hashed_key.to_vec(), key); - hashed_key - }; - - this.memory.set(out, &result).map_err(|_| "Invalid attempt to set result in ext_twox_64")?; - Ok(()) - }, - ext_twox_128(data: *const u8, len: u32, out: *mut u8) => { - let result: [u8; 16] = if len == 0 { - let hashed = twox_128(&[0u8; 0]); - debug_trace!(target: "xxhash", "XXhash: '' -> {}", HexDisplay::from(&hashed)); - this.hash_lookup.insert(hashed.to_vec(), vec![]); - hashed - } else { - let key = this.memory.get(data, len as usize) - .map_err(|_| "Invalid attempt to get key in ext_twox_128")?; - let hashed_key = twox_128(&key); - debug_trace!( - target: "xxhash", "XXhash: {} -> {}", - &if let Ok(_skey) = str::from_utf8(&key) { - *_skey - } else { - format!("{}", HexDisplay::from(&key)) - }, - HexDisplay::from(&hashed_key), - ); - this.hash_lookup.insert(hashed_key.to_vec(), key); - hashed_key - }; - - this.memory.set(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_twox_128")?; - Ok(()) - }, - ext_twox_256(data: *const u8, len: u32, out: *mut u8) => { - let result: [u8; 32] = if len == 0 { - twox_256(&[0u8; 0]) - } else { - let mem = this.memory.get(data, len as usize) - .map_err(|_| "Invalid attempt to get data in ext_twox_256")?; - twox_256(&mem) - }; - this.memory.set(out, &result).map_err(|_| "Invalid attempt to set result in ext_twox_256")?; - Ok(()) - }, - ext_blake2_128(data: *const u8, len: u32, out: *mut u8) => { - let result: [u8; 16] = if len == 0 { - let hashed = blake2_128(&[0u8; 0]); - this.hash_lookup.insert(hashed.to_vec(), vec![]); - hashed - } else { - let key = this.memory.get(data, len as usize) - .map_err(|_| "Invalid attempt to get key in ext_blake2_128")?; - let hashed_key = blake2_128(&key); - this.hash_lookup.insert(hashed_key.to_vec(), key); - hashed_key - }; - - this.memory.set(out, &result) - .map_err(|_| "Invalid attempt to set result in ext_blake2_128")?; - Ok(()) - }, - ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => { - let result: [u8; 32] = if len == 0 { - blake2_256(&[0u8; 0]) - } else { - let mem = this.memory.get(data, len as usize) - .map_err(|_| "Invalid attempt to get data in ext_blake2_256")?; - blake2_256(&mem) - }; - this.memory.set(out, &result).map_err(|_| "Invalid attempt to set result in ext_blake2_256")?; - Ok(()) - }, - ext_keccak_256(data: *const u8, len: u32, out: *mut u8) => { - let result: [u8; 32] = if len == 0 { - tiny_keccak::keccak256(&[0u8; 0]) - } else { - let mem = this.memory.get(data, len as usize) - .map_err(|_| "Invalid attempt to get data in ext_keccak_256")?; - tiny_keccak::keccak256(&mem) - }; - this.memory.set(out, &result).map_err(|_| "Invalid attempt to set result in ext_keccak_256")?; - Ok(()) - }, - ext_ed25519_public_keys(id_data: *const u8, result_len: *mut u32) -> *mut u8 => { - let mut id = [0u8; 4]; - this.memory.get_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_ed25519_public_keys")?; - let key_type = KeyTypeId(id); - - let keys = runtime_io::ed25519_public_keys(key_type).encode(); - - let len = keys.len() as u32; - let offset = this.heap.allocate(len)? as u32; - - this.memory.set(offset, keys.as_ref()) - .map_err(|_| "Invalid attempt to set memory in ext_ed25519_public_keys")?; - this.memory.write_primitive(result_len, len) - .map_err(|_| "Invalid attempt to write result_len in ext_ed25519_public_keys")?; - - Ok(offset) - }, - ext_ed25519_verify( - msg_data: *const u8, - msg_len: u32, - sig_data: *const u8, - pubkey_data: *const u8, - ) -> u32 => { - let mut sig = [0u8; 64]; - this.memory.get_into(sig_data, &mut sig[..]) - .map_err(|_| "Invalid attempt to get signature in ext_ed25519_verify")?; - let mut pubkey = [0u8; 32]; - this.memory.get_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_verify")?; - let msg = this.memory.get(msg_data, msg_len as usize) - .map_err(|_| "Invalid attempt to get message in ext_ed25519_verify")?; - - Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { - 0 - } else { - 5 - }) - }, - ext_ed25519_generate(id_data: *const u8, seed: *const u8, seed_len: u32, out: *mut u8) => { - let mut id = [0u8; 4]; - this.memory.get_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_ed25519_generate")?; - let key_type = KeyTypeId(id); - - let seed = if seed_len == 0 { - None - } else { - Some( - this.memory.get(seed, seed_len as usize) - .map_err(|_| "Invalid attempt to get seed in ext_ed25519_generate")? - ) - }; - - let seed = seed.as_ref() - .map(|seed| - std::str::from_utf8(&seed) - .map_err(|_| "Seed not a valid utf8 string in ext_sr25119_generate") - ).transpose()?; - - let pubkey = runtime_io::ed25519_generate(key_type, seed); - - this.memory.set(out, pubkey.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_ed25519_generate".into()) - }, - ext_ed25519_sign( - id_data: *const u8, - pubkey_data: *const u8, - msg_data: *const u8, - msg_len: u32, - out: *mut u8, - ) -> u32 => { - let mut id = [0u8; 4]; - this.memory.get_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_ed25519_sign")?; - let key_type = KeyTypeId(id); - - let mut pubkey = [0u8; 32]; - this.memory.get_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_ed25519_sign")?; - - let msg = this.memory.get(msg_data, msg_len as usize) - .map_err(|_| "Invalid attempt to get message in ext_ed25519_sign")?; - - let signature = runtime_io::ed25519_sign(key_type, &ed25519::Public(pubkey), &msg); - - match signature { - Some(signature) => { - this.memory - .set(out, signature.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_ed25519_sign")?; - Ok(0) - }, - None => Ok(1), - } - }, - ext_sr25519_public_keys(id_data: *const u8, result_len: *mut u32) -> *mut u8 => { - let mut id = [0u8; 4]; - this.memory.get_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_sr25519_public_keys")?; - let key_type = KeyTypeId(id); - - let keys = runtime_io::sr25519_public_keys(key_type).encode(); - - let len = keys.len() as u32; - let offset = this.heap.allocate(len)? as u32; - - this.memory.set(offset, keys.as_ref()) - .map_err(|_| "Invalid attempt to set memory in ext_sr25519_public_keys")?; - this.memory.write_primitive(result_len, len) - .map_err(|_| "Invalid attempt to write result_len in ext_sr25519_public_keys")?; - - Ok(offset) - }, - ext_sr25519_verify( - msg_data: *const u8, - msg_len: u32, - sig_data: *const u8, - pubkey_data: *const u8, - ) -> u32 => { - let mut sig = [0u8; 64]; - this.memory.get_into(sig_data, &mut sig[..]) - .map_err(|_| "Invalid attempt to get signature in ext_sr25519_verify")?; - let mut pubkey = [0u8; 32]; - this.memory.get_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_verify")?; - let msg = this.memory.get(msg_data, msg_len as usize) - .map_err(|_| "Invalid attempt to get message in ext_sr25519_verify")?; - - Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { - 0 - } else { - 5 - }) - }, - ext_sr25519_generate(id_data: *const u8, seed: *const u8, seed_len: u32, out: *mut u8) => { - let mut id = [0u8; 4]; - this.memory.get_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_sr25519_generate")?; - let key_type = KeyTypeId(id); - let seed = if seed_len == 0 { - None - } else { - Some( - this.memory.get(seed, seed_len as usize) - .map_err(|_| "Invalid attempt to get seed in ext_sr25519_generate")? - ) - }; - - let seed = seed.as_ref() - .map(|seed| - std::str::from_utf8(&seed) - .map_err(|_| "Seed not a valid utf8 string in ext_sr25119_generate") - ) - .transpose()?; - - let pubkey = runtime_io::sr25519_generate(key_type, seed); - - this.memory.set(out, pubkey.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_sr25519_generate".into()) - }, - ext_sr25519_sign( - id_data: *const u8, - pubkey_data: *const u8, - msg_data: *const u8, - msg_len: u32, - out: *mut u8, - ) -> u32 => { - let mut id = [0u8; 4]; - this.memory.get_into(id_data, &mut id[..]) - .map_err(|_| "Invalid attempt to get id in ext_sr25519_sign")?; - let key_type = KeyTypeId(id); - - let mut pubkey = [0u8; 32]; - this.memory.get_into(pubkey_data, &mut pubkey[..]) - .map_err(|_| "Invalid attempt to get pubkey in ext_sr25519_sign")?; - - let msg = this.memory.get(msg_data, msg_len as usize) - .map_err(|_| "Invalid attempt to get message in ext_sr25519_sign")?; - - let signature = runtime_io::sr25519_sign(key_type, &sr25519::Public(pubkey), &msg); - - match signature { - Some(signature) => { - this.memory.set(out, signature.as_ref()) - .map_err(|_| "Invalid attempt to set out in ext_sr25519_sign")?; - Ok(0) - }, - None => Ok(1), - } - }, - ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32 => { - let mut sig = [0u8; 65]; - this.memory.get_into(sig_data, &mut sig[..]) - .map_err(|_| "Invalid attempt to get signature in ext_secp256k1_ecdsa_recover")?; - let rs = match secp256k1::Signature::parse_slice(&sig[0..64]) { - Ok(rs) => rs, - _ => return Ok(1), - }; - let v = match secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) { - Ok(v) => v, - _ => return Ok(2), - }; - - - let mut msg = [0u8; 32]; - this.memory.get_into(msg_data, &mut msg[..]) - .map_err(|_| "Invalid attempt to get message in ext_secp256k1_ecdsa_recover")?; - - let pubkey = match secp256k1::recover(&secp256k1::Message::parse(&msg), &rs, &v) { - Ok(pk) => pk, - _ => return Ok(3), - }; - - this.memory.set(pubkey_data, &pubkey.serialize()[1..65]) - .map_err(|_| "Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover")?; - - Ok(0) - }, - ext_is_validator() -> u32 => { - Ok(if runtime_io::is_validator() { - 1 - } else { - 0 - }) - }, - ext_submit_transaction(msg_data: *const u8, len: u32) -> u32 => { - let extrinsic = this.memory.get(msg_data, len as usize) - .map_err(|_| "OOB while ext_submit_transaction: wasm")?; - - let res = this.ext.offchain() - .map(|api| api.submit_transaction(extrinsic)) - .ok_or_else(|| "Calling unavailable API ext_submit_transaction: wasm")?; - - Ok(if res.is_ok() { 0 } else { 1 }) - }, - ext_network_state(written_out: *mut u32) -> *mut u8 => { - let res = this.ext.offchain() - .map(|api| api.network_state()) - .ok_or_else(|| "Calling unavailable API ext_network_state: wasm")?; - - let encoded = res.encode(); - let len = encoded.len() as u32; - let offset = this.heap.allocate(len)? as u32; - this.memory.set(offset, &encoded) - .map_err(|_| "Invalid attempt to set memory in ext_network_state")?; - - this.memory.write_primitive(written_out, len) - .map_err(|_| "Invalid attempt to write written_out in ext_network_state")?; - - Ok(offset) - }, - ext_timestamp() -> u64 => { - let timestamp = this.ext.offchain() - .map(|api| api.timestamp()) - .ok_or_else(|| "Calling unavailable API ext_timestamp: wasm")?; - Ok(timestamp.unix_millis()) - }, - ext_sleep_until(deadline: u64) => { - this.ext.offchain() - .map(|api| api.sleep_until(offchain::Timestamp::from_unix_millis(deadline))) - .ok_or_else(|| "Calling unavailable API ext_sleep_until: wasm")?; - Ok(()) - }, - ext_random_seed(seed_data: *mut u8) => { - // NOTE the runtime as assumptions about seed size. - let seed: [u8; 32] = this.ext.offchain() - .map(|api| api.random_seed()) - .ok_or_else(|| "Calling unavailable API ext_random_seed: wasm")?; - - this.memory.set(seed_data, &seed) - .map_err(|_| "Invalid attempt to set value in ext_random_seed")?; - Ok(()) - }, - ext_local_storage_set(kind: u32, key: *const u8, key_len: u32, value: *const u8, value_len: u32) => { - let kind = offchain::StorageKind::try_from(kind) - .map_err(|_| "storage kind OOB while ext_local_storage_set: wasm")?; - let key = this.memory.get(key, key_len as usize) - .map_err(|_| "OOB while ext_local_storage_set: wasm")?; - let value = this.memory.get(value, value_len as usize) - .map_err(|_| "OOB while ext_local_storage_set: wasm")?; - - this.ext.offchain() - .map(|api| api.local_storage_set(kind, &key, &value)) - .ok_or_else(|| "Calling unavailable API ext_local_storage_set: wasm")?; - - Ok(()) - }, - ext_local_storage_get(kind: u32, key: *const u8, key_len: u32, value_len: *mut u32) -> *mut u8 => { - let kind = offchain::StorageKind::try_from(kind) - .map_err(|_| "storage kind OOB while ext_local_storage_get: wasm")?; - let key = this.memory.get(key, key_len as usize) - .map_err(|_| "OOB while ext_local_storage_get: wasm")?; - - let maybe_value = this.ext.offchain() - .map(|api| api.local_storage_get(kind, &key)) - .ok_or_else(|| "Calling unavailable API ext_local_storage_get: wasm")?; - - let (offset, len) = if let Some(value) = maybe_value { - let offset = this.heap.allocate(value.len() as u32)? as u32; - this.memory.set(offset, &value) - .map_err(|_| "Invalid attempt to set memory in ext_local_storage_get")?; - (offset, value.len() as u32) - } else { - (0, u32::max_value()) - }; - - this.memory.write_primitive(value_len, len) - .map_err(|_| "Invalid attempt to write value_len in ext_local_storage_get")?; - - Ok(offset) - }, - ext_local_storage_compare_and_set( - kind: u32, - key: *const u8, - key_len: u32, - old_value: *const u8, - old_value_len: u32, - new_value: *const u8, - new_value_len: u32 - ) -> u32 => { - let kind = offchain::StorageKind::try_from(kind) - .map_err(|_| "storage kind OOB while ext_local_storage_compare_and_set: wasm")?; - let key = this.memory.get(key, key_len as usize) - .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; - let new_value = this.memory.get(new_value, new_value_len as usize) - .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; - - let res = { - if old_value == u32::max_value() { - this.ext.offchain() - .map(|api| api.local_storage_compare_and_set(kind, &key, None, &new_value)) - .ok_or_else(|| "Calling unavailable API ext_local_storage_compare_and_set: wasm")? - } else { - let v = this.memory.get(old_value, old_value_len as usize) - .map_err(|_| "OOB while ext_local_storage_compare_and_set: wasm")?; - this.ext.offchain() - .map(|api| api.local_storage_compare_and_set(kind, &key, Some(v.as_slice()), &new_value)) - .ok_or_else(|| "Calling unavailable API ext_local_storage_compare_and_set: wasm")? - } - }; - - Ok(if res { 0 } else { 1 }) - }, - ext_http_request_start( - method: *const u8, - method_len: u32, - url: *const u8, - url_len: u32, - meta: *const u8, - meta_len: u32 - ) -> u32 => { - let method = this.memory.get(method, method_len as usize) - .map_err(|_| "OOB while ext_http_request_start: wasm")?; - let url = this.memory.get(url, url_len as usize) - .map_err(|_| "OOB while ext_http_request_start: wasm")?; - let meta = this.memory.get(meta, meta_len as usize) - .map_err(|_| "OOB while ext_http_request_start: wasm")?; - - let method_str = str::from_utf8(&method) - .map_err(|_| "invalid str while ext_http_request_start: wasm")?; - let url_str = str::from_utf8(&url) - .map_err(|_| "invalid str while ext_http_request_start: wasm")?; - - let id = this.ext.offchain() - .map(|api| api.http_request_start(method_str, url_str, &*meta)) - .ok_or_else(|| "Calling unavailable API ext_http_request_start: wasm")?; - - if let Ok(id) = id { - Ok(id.into()) - } else { - Ok(u32::max_value()) - } - }, - ext_http_request_add_header( - request_id: u32, - name: *const u8, - name_len: u32, - value: *const u8, - value_len: u32 - ) -> u32 => { - let name = this.memory.get(name, name_len as usize) - .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; - let value = this.memory.get(value, value_len as usize) - .map_err(|_| "OOB while ext_http_request_add_header: wasm")?; - - let name_str = str::from_utf8(&name) - .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; - let value_str = str::from_utf8(&value) - .map_err(|_| "Invalid str while ext_http_request_add_header: wasm")?; - - let res = this.ext.offchain() - .map(|api| api.http_request_add_header( - offchain::HttpRequestId(request_id as u16), - &name_str, - &value_str, - )) - .ok_or_else(|| "Calling unavailable API ext_http_request_add_header: wasm")?; - - Ok(if res.is_ok() { 0 } else { 1 }) - }, - ext_http_request_write_body( - request_id: u32, - chunk: *const u8, - chunk_len: u32, - deadline: u64 - ) -> u32 => { - let chunk = this.memory.get(chunk, chunk_len as usize) - .map_err(|_| "OOB while ext_http_request_write_body: wasm")?; - - let res = this.ext.offchain() - .map(|api| api.http_request_write_body( - offchain::HttpRequestId(request_id as u16), - &chunk, - deadline_to_timestamp(deadline) - )) - .ok_or_else(|| "Calling unavailable API ext_http_request_write_body: wasm")?; - - Ok(match res { - Ok(()) => 0, - Err(e) => e.into(), - }) - }, - ext_http_response_wait( - ids: *const u32, - ids_len: u32, - statuses: *mut u32, - deadline: u64 - ) => { - let ids = (0..ids_len) - .map(|i| - this.memory.read_primitive(ids + i * 4) - .map(|id: u32| offchain::HttpRequestId(id as u16)) - .map_err(|_| "OOB while ext_http_response_wait: wasm") - ) - .collect::<::std::result::Result, _>>()?; - - let res = this.ext.offchain() - .map(|api| api.http_response_wait(&ids, deadline_to_timestamp(deadline))) - .ok_or_else(|| "Calling unavailable API ext_http_response_wait: wasm")? - .into_iter() - .map(|status| status.into()) - .enumerate() - // make sure to take up to `ids_len` to avoid exceeding the mem. - .take(ids_len as usize); - - for (i, status) in res { - this.memory.write_primitive(statuses + i as u32 * 4, status) - .map_err(|_| "Invalid attempt to set memory in ext_http_response_wait")?; - } - - Ok(()) - }, - ext_http_response_headers( - request_id: u32, - written_out: *mut u32 - ) -> *mut u8 => { - use codec::Encode; - - let headers = this.ext.offchain() - .map(|api| api.http_response_headers(offchain::HttpRequestId(request_id as u16))) - .ok_or_else(|| "Calling unavailable API ext_http_response_headers: wasm")?; - - let encoded = headers.encode(); - let len = encoded.len() as u32; - let offset = this.heap.allocate(len)? as u32; - this.memory.set(offset, &encoded) - .map_err(|_| "Invalid attempt to set memory in ext_http_response_headers")?; - this.memory.write_primitive(written_out, len) - .map_err(|_| "Invalid attempt to write written_out in ext_http_response_headers")?; - - Ok(offset) - }, - ext_http_response_read_body( - request_id: u32, - buffer: *mut u8, - buffer_len: u32, - deadline: u64 - ) -> u32 => { - let mut internal_buffer = Vec::with_capacity(buffer_len as usize); - internal_buffer.resize(buffer_len as usize, 0); - - let res = this.ext.offchain() - .map(|api| api.http_response_read_body( - offchain::HttpRequestId(request_id as u16), - &mut internal_buffer, - deadline_to_timestamp(deadline), - )) - .ok_or_else(|| "Calling unavailable API ext_http_response_read_body: wasm")?; - - Ok(match res { - Ok(read) => { - this.memory.set(buffer, &internal_buffer[..read]) - .map_err(|_| "Invalid attempt to set memory in ext_http_response_read_body")?; - - read as u32 - }, - Err(err) => { - u32::max_value() - u32::from(err) + 1 - } - }) - }, - ext_sandbox_instantiate( - dispatch_thunk_idx: usize, - wasm_ptr: *const u8, - wasm_len: usize, - imports_ptr: *const u8, - imports_len: usize, - state: usize - ) -> u32 => { - let wasm = this.memory.get(wasm_ptr, wasm_len as usize) - .map_err(|_| "OOB while ext_sandbox_instantiate: wasm")?; - let raw_env_def = this.memory.get(imports_ptr, imports_len as usize) - .map_err(|_| "OOB while ext_sandbox_instantiate: imports")?; - - // Extract a dispatch thunk from instance's table by the specified index. - let dispatch_thunk = { - let table = this.table.as_ref() - .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?; - table.get(dispatch_thunk_idx) - .map_err(|_| "dispatch_thunk_idx is out of the table bounds")? - .ok_or_else(|| "dispatch_thunk_idx points on an empty table entry")? - .clone() - }; - - let instance_idx_or_err_code = - match sandbox::instantiate(this, dispatch_thunk, &wasm, &raw_env_def, state) { - Ok(instance_idx) => instance_idx, - Err(sandbox::InstantiationError::StartTrapped) => sandbox_primitives::ERR_EXECUTION, - Err(_) => sandbox_primitives::ERR_MODULE, - }; - - Ok(instance_idx_or_err_code as u32) - }, - ext_sandbox_instance_teardown(instance_idx: u32) => { - this.sandbox_store.instance_teardown(instance_idx)?; - Ok(()) - }, - ext_sandbox_invoke( - instance_idx: u32, - export_ptr: *const u8, - export_len: usize, - args_ptr: *const u8, - args_len: usize, - return_val_ptr: *const u8, - return_val_len: usize, - state: usize - ) -> u32 => { - use codec::{Decode, Encode}; - - trace!(target: "sr-sandbox", "invoke, instance_idx={}", instance_idx); - let export = this.memory.get(export_ptr, export_len as usize) - .map_err(|_| "OOB while ext_sandbox_invoke: export") - .and_then(|b| - String::from_utf8(b) - .map_err(|_| "Export name should be a valid utf-8 sequence") - )?; - - // Deserialize arguments and convert them into wasmi types. - let serialized_args = this.memory.get(args_ptr, args_len as usize) - .map_err(|_| "OOB while ext_sandbox_invoke: args")?; - let args = Vec::::decode(&mut &serialized_args[..]) - .map_err(|_| "Can't decode serialized arguments for the invocation")? - .into_iter() - .map(Into::into) - .collect::>(); - - let instance = this.sandbox_store.instance(instance_idx)?; - let result = instance.invoke(&export, &args, this, state); - - match result { - Ok(None) => Ok(sandbox_primitives::ERR_OK), - Ok(Some(val)) => { - // Serialize return value and write it back into the memory. - sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { - if val.len() > return_val_len as usize { - Err("Return value buffer is too small")?; - } - this.memory - .set(return_val_ptr, val) - .map_err(|_| "Return value buffer is OOB")?; - Ok(sandbox_primitives::ERR_OK) - }) - } - Err(_) => Ok(sandbox_primitives::ERR_EXECUTION), - } - }, - ext_sandbox_memory_new(initial: u32, maximum: u32) -> u32 => { - let mem_idx = this.sandbox_store.new_memory(initial, maximum)?; - Ok(mem_idx) - }, - ext_sandbox_memory_get(memory_idx: u32, offset: u32, buf_ptr: *mut u8, buf_len: u32) -> u32 => { - let sandboxed_memory = this.sandbox_store.memory(memory_idx)?; - - match MemoryInstance::transfer( - &sandboxed_memory, - offset as usize, - &this.memory, - buf_ptr as usize, - buf_len as usize, - ) { - Ok(()) => Ok(sandbox_primitives::ERR_OK), - Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), - } - }, - ext_sandbox_memory_set(memory_idx: u32, offset: u32, val_ptr: *const u8, val_len: u32) -> u32 => { - let sandboxed_memory = this.sandbox_store.memory(memory_idx)?; - - match MemoryInstance::transfer( - &this.memory, - val_ptr as usize, - &sandboxed_memory, - offset as usize, - val_len as usize, - ) { - Ok(()) => Ok(sandbox_primitives::ERR_OK), - Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), - } - }, - ext_sandbox_memory_teardown(memory_idx: u32) => { - this.sandbox_store.memory_teardown(memory_idx)?; - Ok(()) - }, - => <'e, E: Externalities + 'e> -); - -/// Wasm rust executor for contracts. -/// -/// Executes the provided code in a sandboxed wasm runtime. -#[derive(Debug, Clone)] -pub struct WasmExecutor; - -impl WasmExecutor { - - /// Create a new instance. - pub fn new() -> Self { - WasmExecutor - } - - /// Call a given method in the given code. - /// - /// Signature of this method needs to be `(I32, I32) -> I64`. - /// - /// This should be used for tests only. - pub fn call>( - &self, - ext: &mut E, - heap_pages: usize, - code: &[u8], - method: &str, - data: &[u8], - ) -> Result> { - let module = ::wasmi::Module::from_buffer(code)?; - let module = Self::instantiate_module::(heap_pages, &module)?; - self.call_in_wasm_module(ext, &module, method, data) - } - - /// Call a given method with a custom signature in the given code. - /// - /// This should be used for tests only. - pub fn call_with_custom_signature< - E: Externalities, - F: FnOnce(&mut dyn FnMut(&[u8]) -> Result) -> Result>, - FR: FnOnce(Option, &MemoryRef) -> Result>, - R, - >( - &self, - ext: &mut E, - heap_pages: usize, - code: &[u8], - method: &str, - create_parameters: F, - filter_result: FR, - ) -> Result { - let module = wasmi::Module::from_buffer(code)?; - let module = Self::instantiate_module::(heap_pages, &module)?; - self.call_in_wasm_module_with_custom_signature( - ext, - &module, - method, - create_parameters, - filter_result, - ) - } - - fn get_mem_instance(module: &ModuleRef) -> Result { - Ok(module - .export_by_name("memory") - .ok_or_else(|| Error::InvalidMemoryReference)? - .as_memory() - .ok_or_else(|| Error::InvalidMemoryReference)? - .clone()) - } - - /// Find the global named `__heap_base` in the given wasm module instance and - /// tries to get its value. - fn get_heap_base(module: &ModuleRef) -> Result { - let heap_base_val = module - .export_by_name("__heap_base") - .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? - .as_global() - .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? - .get(); - - Ok(match heap_base_val { - wasmi::RuntimeValue::I32(v) => v as u32, - _ => return Err(Error::HeapBaseNotFoundOrInvalid), - }) - } - - /// Call a given method in the given wasm-module runtime. - pub fn call_in_wasm_module>( - &self, - ext: &mut E, - module_instance: &ModuleRef, - method: &str, - data: &[u8], - ) -> Result> { - self.call_in_wasm_module_with_custom_signature( - ext, - module_instance, - method, - |alloc| { - let offset = alloc(data)?; - Ok(vec![I32(offset as i32), I32(data.len() as i32)]) - }, - |res, memory| { - if let Some(I64(r)) = res { - let offset = r as u32; - let length = (r as u64 >> 32) as usize; - memory.get(offset, length).map_err(|_| Error::Runtime).map(Some) - } else { - Ok(None) - } - } - ) - } - - /// Call a given method in the given wasm-module runtime. - fn call_in_wasm_module_with_custom_signature< - E: Externalities, - F: FnOnce(&mut dyn FnMut(&[u8]) -> Result) -> Result>, - FR: FnOnce(Option, &MemoryRef) -> Result>, - R, - >( - &self, - ext: &mut E, - module_instance: &ModuleRef, - method: &str, - create_parameters: F, - filter_result: FR, - ) -> Result { - // extract a reference to a linear memory, optional reference to a table - // and then initialize FunctionExecutor. - let memory = Self::get_mem_instance(module_instance)?; - let table: Option = module_instance - .export_by_name("__indirect_function_table") - .and_then(|e| e.as_table().cloned()); - let heap_base = Self::get_heap_base(module_instance)?; - - let mut fec = FunctionExecutor::new(memory.clone(), heap_base, table, ext)?; - let parameters = create_parameters(&mut |data: &[u8]| { - let offset = fec.heap.allocate(data.len() as u32)?; - memory.set(offset, &data)?; - Ok(offset) - })?; - - let result = module_instance.invoke_export( - method, - ¶meters, - &mut fec - ); - let result = match result { - Ok(val) => match filter_result(val, &memory)? { - Some(val) => Ok(val), - None => Err(Error::InvalidReturn), - }, - Err(e) => { - trace!(target: "wasm-executor", "Failed to execute code with {} pages", memory.current_size().0); - Err(e.into()) - }, - }; - - result - } - - /// Prepare module instance - pub fn instantiate_module>( - heap_pages: usize, - module: &Module, - ) -> Result { - // start module instantiation. Don't run 'start' function yet. - let intermediate_instance = ModuleInstance::new( - module, - &ImportsBuilder::new() - .with_resolver("env", FunctionExecutor::::resolver()) - )?; - - // Verify that the module has the heap base global variable. - let _ = Self::get_heap_base(intermediate_instance.not_started_instance())?; - - // Extract a reference to a linear memory. - let memory = Self::get_mem_instance(intermediate_instance.not_started_instance())?; - memory.grow(Pages(heap_pages)).map_err(|_| Error::Runtime)?; - - if intermediate_instance.has_start() { - // Runtime is not allowed to have the `start` function. - Err(Error::RuntimeHasStartFn) - } else { - Ok(intermediate_instance.assert_no_start()) - } - } -} - - -#[cfg(test)] -mod tests { - use super::*; - - use codec::Encode; - - use state_machine::TestExternalities as CoreTestExternalities; - use hex_literal::hex; - use primitives::map; - use runtime_test::WASM_BINARY; - use substrate_offchain::testing; - - type TestExternalities = CoreTestExternalities; - - #[test] - fn returning_should_work() { - let mut ext = TestExternalities::default(); - let test_code = WASM_BINARY; - - let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_empty_return", &[]).unwrap(); - assert_eq!(output, vec![0u8; 0]); - } - - #[test] - fn panicking_should_work() { - let mut ext = TestExternalities::default(); - let test_code = WASM_BINARY; - - let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_panic", &[]); - assert!(output.is_err()); - - let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_conditional_panic", &[]); - assert_eq!(output.unwrap(), vec![0u8; 0]); - - let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_conditional_panic", &[2]); - assert!(output.is_err()); - } - - #[test] - fn storage_should_work() { - let mut ext = TestExternalities::default(); - ext.set_storage(b"foo".to_vec(), b"bar".to_vec()); - let test_code = WASM_BINARY; - - let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_data_in", b"Hello world").unwrap(); - - assert_eq!(output, b"all ok!".to_vec()); - - let expected = TestExternalities::new((map![ - b"input".to_vec() => b"Hello world".to_vec(), - b"foo".to_vec() => b"bar".to_vec(), - b"baz".to_vec() => b"bar".to_vec() - ], map![])); - assert_eq!(ext, expected); - } - - #[test] - fn clear_prefix_should_work() { - let mut ext = TestExternalities::default(); - ext.set_storage(b"aaa".to_vec(), b"1".to_vec()); - ext.set_storage(b"aab".to_vec(), b"2".to_vec()); - ext.set_storage(b"aba".to_vec(), b"3".to_vec()); - ext.set_storage(b"abb".to_vec(), b"4".to_vec()); - ext.set_storage(b"bbb".to_vec(), b"5".to_vec()); - let test_code = WASM_BINARY; - - // This will clear all entries which prefix is "ab". - let output = WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_clear_prefix", b"ab").unwrap(); - - assert_eq!(output, b"all ok!".to_vec()); - - let expected = TestExternalities::new((map![ - b"aaa".to_vec() => b"1".to_vec(), - b"aab".to_vec() => b"2".to_vec(), - b"bbb".to_vec() => b"5".to_vec() - ], map![])); - assert_eq!(expected, ext); - } - - #[test] - fn blake2_256_should_work() { - let mut ext = TestExternalities::default(); - let test_code = WASM_BINARY; - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_blake2_256", &[]).unwrap(), - blake2_256(&b""[..]).encode() - ); - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_blake2_256", b"Hello world!").unwrap(), - blake2_256(&b"Hello world!"[..]).encode() - ); - } - - #[test] - fn blake2_128_should_work() { - let mut ext = TestExternalities::default(); - let test_code = WASM_BINARY; - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_blake2_128", &[]).unwrap(), - blake2_128(&b""[..]).encode() - ); - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_blake2_128", b"Hello world!").unwrap(), - blake2_128(&b"Hello world!"[..]).encode() - ); - } - - #[test] - fn twox_256_should_work() { - let mut ext = TestExternalities::default(); - let test_code = WASM_BINARY; - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_256", &[]).unwrap(), - hex!("99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a") - ); - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_256", b"Hello world!").unwrap(), - hex!("b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74") - ); - } - - #[test] - fn twox_128_should_work() { - let mut ext = TestExternalities::default(); - let test_code = WASM_BINARY; - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_128", &[]).unwrap(), - hex!("99e9d85137db46ef4bbea33613baafd5") - ); - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_twox_128", b"Hello world!").unwrap(), - hex!("b27dfd7f223f177f2a13647b533599af") - ); - } - - #[test] - fn ed25519_verify_should_work() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - let key = ed25519::Pair::from_seed(&blake2_256(b"test")); - let sig = key.sign(b"all ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(sig.as_ref()); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_ed25519_verify", &calldata).unwrap(), - vec![1] - ); - - let other_sig = key.sign(b"all is not ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(other_sig.as_ref()); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_ed25519_verify", &calldata).unwrap(), - vec![0] - ); - } - - #[test] - fn sr25519_verify_should_work() { - let mut ext = TestExternalities::::default(); - let test_code = WASM_BINARY; - let key = sr25519::Pair::from_seed(&blake2_256(b"test")); - let sig = key.sign(b"all ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(sig.as_ref()); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sr25519_verify", &calldata).unwrap(), - vec![1] - ); - - let other_sig = key.sign(b"all is not ok!"); - let mut calldata = vec![]; - calldata.extend_from_slice(key.public().as_ref()); - calldata.extend_from_slice(other_sig.as_ref()); - - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_sr25519_verify", &calldata).unwrap(), - vec![0] - ); - } - - #[test] - fn ordered_trie_root_should_work() { - let mut ext = TestExternalities::::default(); - let trie_input = vec![b"zero".to_vec(), b"one".to_vec(), b"two".to_vec()]; - let test_code = WASM_BINARY; - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_ordered_trie_root", &[]).unwrap(), - Layout::::ordered_trie_root(trie_input.iter()).as_fixed_bytes().encode() - ); - } - - #[test] - fn offchain_local_storage_should_work() { - use substrate_client::backend::OffchainStorage; - - let mut ext = TestExternalities::::default(); - let (offchain, state) = testing::TestOffchainExt::new(); - ext.set_offchain_externalities(offchain); - let test_code = WASM_BINARY; - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_offchain_local_storage", &[]).unwrap(), - vec![0] - ); - assert_eq!(state.read().persistent_storage.get(b"", b"test"), Some(vec![])); - } - - #[test] - fn offchain_http_should_work() { - let mut ext = TestExternalities::::default(); - let (offchain, state) = testing::TestOffchainExt::new(); - ext.set_offchain_externalities(offchain); - state.write().expect_request( - 0, - testing::PendingRequest { - method: "POST".into(), - uri: "http://localhost:12345".into(), - body: vec![1, 2, 3, 4], - headers: vec![("X-Auth".to_owned(), "test".to_owned())], - sent: true, - response: vec![1, 2, 3], - response_headers: vec![("X-Auth".to_owned(), "hello".to_owned())], - ..Default::default() - }, - ); - - let test_code = WASM_BINARY; - assert_eq!( - WasmExecutor::new().call(&mut ext, 8, &test_code[..], "test_offchain_http", &[]).unwrap(), - vec![0] - ); - } -} diff --git a/core/executor/src/wasm_runtime.rs b/core/executor/src/wasm_runtime.rs new file mode 100644 index 0000000000000000000000000000000000000000..caaa01c43027e4e353716fe50c59fb6d8bcba5d3 --- /dev/null +++ b/core/executor/src/wasm_runtime.rs @@ -0,0 +1,226 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Traits and accessor functions for calling into the Substrate Wasm runtime. +//! +//! The primary means of accessing the runtimes is through a cache which saves the reusable +//! components of the runtime that are expensive to initialize. + +use crate::error::{Error, WasmError}; +use crate::wasmi_execution; +#[cfg(feature = "wasmtime")] +use crate::wasmtime; +use log::{trace, warn}; +use codec::Decode; +use primitives::{storage::well_known_keys, traits::Externalities, H256}; +use runtime_version::RuntimeVersion; +use std::{collections::hash_map::{Entry, HashMap}, panic::AssertUnwindSafe}; + +/// The Substrate Wasm runtime. +pub trait WasmRuntime { + /// Attempt to update the number of heap pages available during execution. + /// + /// Returns false if the update cannot be applied. The function is guaranteed to return true if + /// the heap pages would not change from its current value. + fn update_heap_pages(&mut self, heap_pages: u64) -> bool; + + /// Call a method in the Substrate runtime by name. Returns the encoded result on success. + fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) + -> Result, Error>; +} + +/// Specification of different methods of executing the runtime Wasm code. +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +pub enum WasmExecutionMethod { + /// Uses the Wasmi interpreter. + Interpreted, + /// Uses the Wasmtime compiled runtime. + #[cfg(feature = "wasmtime")] + Compiled, +} + +/// A Wasm runtime object along with its cached runtime version. +struct VersionedRuntime { + runtime: Box, + /// Runtime version according to `Core_version`. + version: RuntimeVersion, +} + +/// Cache for the runtimes. +/// +/// When an instance is requested for the first time it is added to this cache. Metadata is kept +/// with the instance so that it can be efficiently reinitialized. +/// +/// When using the Wasmi interpreter execution method, the metadata includes the initial memory and +/// values of mutable globals. Follow-up requests to fetch a runtime return this one instance with +/// the memory reset to the initial memory. So, one runtime instance is reused for every fetch +/// request. +/// +/// For now the cache grows indefinitely, but that should be fine for now since runtimes can only be +/// upgraded rarely and there are no other ways to make the node to execute some other runtime. +pub struct RuntimesCache { + /// A cache of runtime instances along with metadata, ready to be reused. + /// + /// Instances are keyed by the Wasm execution method and the hash of their code. + instances: HashMap<(WasmExecutionMethod, [u8; 32]), Result>, +} + +impl RuntimesCache { + /// Creates a new instance of a runtimes cache. + pub fn new() -> RuntimesCache { + RuntimesCache { + instances: HashMap::new(), + } + } + + /// Fetches an instance of the runtime. + /// + /// On first use we create a new runtime instance, save it to the cache + /// and persist its initial memory. + /// + /// Each subsequent request will return this instance, with its memory restored + /// to the persisted initial memory. Thus, we reuse one single runtime instance + /// for every `fetch_runtime` invocation. + /// + /// # Parameters + /// + /// `ext` - Externalities to use for the runtime. This is used for setting + /// up an initial runtime instance. + /// + /// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution. + /// + /// # Return value + /// + /// If no error occurred a tuple `(&mut WasmRuntime, H256)` is + /// returned. `H256` is the hash of the runtime code. + /// + /// In case of failure one of two errors can be returned: + /// + /// `Err::InvalidCode` is returned for runtime code issues. + /// + /// `Error::InvalidMemoryReference` is returned if no memory export with the + /// identifier `memory` can be found in the runtime. + pub fn fetch_runtime( + &mut self, + ext: &mut E, + wasm_method: WasmExecutionMethod, + default_heap_pages: u64, + ) -> Result<(&mut (dyn WasmRuntime + 'static), &RuntimeVersion, H256), Error> { + let code_hash = ext + .original_storage_hash(well_known_keys::CODE) + .ok_or(Error::InvalidCode("`CODE` not found in storage.".into()))?; + + let heap_pages = ext + .storage(well_known_keys::HEAP_PAGES) + .and_then(|pages| u64::decode(&mut &pages[..]).ok()) + .unwrap_or(default_heap_pages); + + let result = match self.instances.entry((wasm_method, code_hash.into())) { + Entry::Occupied(o) => { + let result = o.into_mut(); + if let Ok(ref mut cached_runtime) = result { + if !cached_runtime.runtime.update_heap_pages(heap_pages) { + trace!( + target: "runtimes_cache", + "heap_pages were changed. Reinstantiating the instance", + ); + *result = create_versioned_wasm_runtime(ext, wasm_method, heap_pages); + if let Err(ref err) = result { + warn!(target: "runtimes_cache", "cannot create a runtime: {:?}", err); + } + } + } + result + }, + Entry::Vacant(v) => { + trace!(target: "runtimes_cache", "no instance found in cache, creating now."); + let result = create_versioned_wasm_runtime(ext, wasm_method, heap_pages); + if let Err(ref err) = result { + warn!(target: "runtimes_cache", "cannot create a runtime: {:?}", err); + } + v.insert(result) + } + }; + + result.as_mut() + .map(|entry| (entry.runtime.as_mut(), &entry.version, code_hash)) + .map_err(|ref e| Error::InvalidCode(format!("{:?}", e))) + } + + /// Invalidate the runtime for the given `wasm_method` and `code_hash`. + /// + /// Invalidation of a runtime is useful when there was a `panic!` in native while executing it. + /// The `panic!` maybe have brought the runtime into a poisoned state and so, it is better to + /// invalidate this runtime instance. + pub fn invalidate_runtime( + &mut self, + wasm_method: WasmExecutionMethod, + code_hash: H256, + ) { + // Just remove the instance, it will be re-created the next time it is requested. + self.instances.remove(&(wasm_method, code_hash.into())); + } +} + +/// Create a wasm runtime with the given `code`. +pub fn create_wasm_runtime_with_code( + wasm_method: WasmExecutionMethod, + heap_pages: u64, + code: &[u8], +) -> Result, WasmError> { + match wasm_method { + WasmExecutionMethod::Interpreted => + wasmi_execution::create_instance(code, heap_pages) + .map(|runtime| -> Box { Box::new(runtime) }), + #[cfg(feature = "wasmtime")] + WasmExecutionMethod::Compiled => + wasmtime::create_instance(code, heap_pages) + .map(|runtime| -> Box { Box::new(runtime) }), + } +} + +fn create_versioned_wasm_runtime( + ext: &mut E, + wasm_method: WasmExecutionMethod, + heap_pages: u64, +) -> Result { + let code = ext + .original_storage(well_known_keys::CODE) + .ok_or(WasmError::CodeNotFound)?; + let mut runtime = create_wasm_runtime_with_code(wasm_method, heap_pages, &code)?; + + // Call to determine runtime version. + let version_result = { + // `ext` is already implicitly handled as unwind safe, as we store it in a global variable. + let mut ext = AssertUnwindSafe(ext); + + // The following unwind safety assertion is OK because if the method call panics, the + // runtime will be dropped. + let mut runtime = AssertUnwindSafe(runtime.as_mut()); + crate::native_executor::safe_call( + move || runtime.call(&mut **ext, "Core_version", &[]) + ).map_err(|_| WasmError::Instantiation("panic in call to get runtime version".into()))? + }; + let encoded_version = version_result + .map_err(|e| WasmError::Instantiation(format!("failed to call \"Core_version\": {}", e)))?; + let version = RuntimeVersion::decode(&mut encoded_version.as_slice()) + .map_err(|_| WasmError::Instantiation("failed to decode \"Core_version\" result".into()))?; + + Ok(VersionedRuntime { + runtime, + version, + }) +} diff --git a/core/executor/src/wasm_runtimes_cache.rs b/core/executor/src/wasm_runtimes_cache.rs deleted file mode 100644 index 110a28fe7d305e8fe1ee5785caa50a85c09f4ccb..0000000000000000000000000000000000000000 --- a/core/executor/src/wasm_runtimes_cache.rs +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Implements a cache for pre-created Wasm runtime module instances. - -use crate::error::Error; -use crate::wasm_executor::WasmExecutor; -use log::{trace, warn}; -use codec::Decode; -use parity_wasm::elements::{deserialize_buffer, DataSegment, Instruction, Module as RawModule}; -use primitives::storage::well_known_keys; -use primitives::Blake2Hasher; -use runtime_version::RuntimeVersion; -use state_machine::Externalities; -use std::collections::hash_map::{Entry, HashMap}; -use std::mem; -use std::rc::Rc; -use wasmi::{Module as WasmModule, ModuleRef as WasmModuleInstanceRef, RuntimeValue}; - -#[derive(Debug)] -enum CacheError { - CodeNotFound, - ApplySnapshotFailed, - InvalidModule, - CantDeserializeWasm, - Instantiation(Error), -} - -/// A runtime along with its version and initial state snapshot. -#[derive(Clone)] -pub struct CachedRuntime { - /// A wasm module instance. - instance: WasmModuleInstanceRef, - /// Runtime version according to `Core_version`. - /// - /// Can be `None` if the runtime doesn't expose this function. - version: Option, - /// The snapshot of the instance's state taken just after the instantiation. - state_snapshot: StateSnapshot, -} - -impl CachedRuntime { - /// Perform an operation with the clean version of the runtime wasm instance. - pub fn with(&self, f: F) -> R - where - F: FnOnce(&WasmModuleInstanceRef) -> R, - { - self.state_snapshot.apply(&self.instance).expect( - "applying the snapshot can only fail if the passed instance is different - from the one that was used for creation of the snapshot; - we use the snapshot that is directly associated with the instance; - thus the snapshot was created using the instance; - qed", - ); - f(&self.instance) - } - - /// Returns the version of this cached runtime. - /// - /// Returns `None` if the runtime doesn't provide the information or there was an error - /// while fetching it. - pub fn version(&self) -> Option { - self.version.clone() - } -} - -/// A state snapshot of an instance taken just after instantiation. -/// -/// It is used for restoring the state of the module after execution. -#[derive(Clone)] -struct StateSnapshot { - /// The offset and the content of the memory segments that should be used to restore the snapshot - data_segments: Vec<(u32, Vec)>, - /// The list of all global mutable variables of the module in their sequential order. - global_mut_values: Vec, - heap_pages: u32, -} - -impl StateSnapshot { - // Returns `None` if instance is not valid. - fn take( - module_instance: &WasmModuleInstanceRef, - data_segments: Vec, - heap_pages: u32, - ) -> Option { - let prepared_segments = data_segments - .into_iter() - .map(|mut segment| { - // Just replace contents of the segment since the segments will be discarded later - // anyway. - let contents = mem::replace(segment.value_mut(), vec![]); - - let init_expr = segment.offset().code(); - // [op, End] - if init_expr.len() != 2 { - return None; - } - let offset = match init_expr[0] { - Instruction::I32Const(v) => v as u32, - Instruction::GetGlobal(idx) => { - let global_val = module_instance.globals().get(idx as usize)?.get(); - match global_val { - RuntimeValue::I32(v) => v as u32, - _ => return None, - } - } - _ => return None, - }; - - Some((offset, contents)) - }) - .collect::>>()?; - - // Collect all values of mutable globals. - let global_mut_values = module_instance - .globals() - .iter() - .filter(|g| g.is_mutable()) - .map(|g| g.get()) - .collect(); - - Some(Self { - data_segments: prepared_segments, - global_mut_values, - heap_pages, - }) - } - - /// Reset the runtime instance to the initial version by restoring - /// the preserved memory and globals. - /// - /// Returns `Err` if applying the snapshot is failed. - fn apply(&self, instance: &WasmModuleInstanceRef) -> Result<(), CacheError> { - let memory = instance - .export_by_name("memory") - .ok_or(CacheError::ApplySnapshotFailed)? - .as_memory() - .cloned() - .ok_or(CacheError::ApplySnapshotFailed)?; - - // First, erase the memory and copy the data segments into it. - memory - .erase() - .map_err(|_| CacheError::ApplySnapshotFailed)?; - for (offset, contents) in &self.data_segments { - memory - .set(*offset, contents) - .map_err(|_| CacheError::ApplySnapshotFailed)?; - } - - // Second, restore the values of mutable globals. - for (global_ref, global_val) in instance - .globals() - .iter() - .filter(|g| g.is_mutable()) - .zip(self.global_mut_values.iter()) - { - // the instance should be the same as used for preserving and - // we iterate the same way it as we do it for preserving values that means that the - // types should be the same and all the values are mutable. So no error is expected/ - global_ref - .set(*global_val) - .map_err(|_| CacheError::ApplySnapshotFailed)?; - } - Ok(()) - } -} - -/// Default num of pages for the heap -const DEFAULT_HEAP_PAGES: u64 = 1024; - -/// Cache for the runtimes. -/// -/// When an instance is requested for the first time it is added to this -/// cache. Furthermore its initial memory and values of mutable globals are preserved here. Follow-up -/// requests to fetch a runtime return this one instance with the memory -/// reset to the initial memory. So, one runtime instance is reused for -/// every fetch request. -/// -/// For now the cache grows indefinitely, but that should be fine for now since runtimes can only be -/// upgraded rarely and there are no other ways to make the node to execute some other runtime. -pub struct RuntimesCache { - /// A cache of runtime instances along with metadata, ready to be reused. - /// - /// Instances are keyed by the hash of their code. - instances: HashMap<[u8; 32], Result, CacheError>>, -} - -impl RuntimesCache { - /// Creates a new instance of a runtimes cache. - pub fn new() -> RuntimesCache { - RuntimesCache { - instances: HashMap::new(), - } - } - - /// Fetches an instance of the runtime. - /// - /// On first use we create a new runtime instance, save it to the cache - /// and persist its initial memory. - /// - /// Each subsequent request will return this instance, with its memory restored - /// to the persisted initial memory. Thus, we reuse one single runtime instance - /// for every `fetch_runtime` invocation. - /// - /// # Parameters - /// - /// `wasm_executor`- Rust wasm executor. Executes the provided code in a - /// sandboxed Wasm runtime. - /// - /// `ext` - Externalities to use for the runtime. This is used for setting - /// up an initial runtime instance. The parameter is only needed for calling - /// into the Wasm module to find out the `Core_version`. - /// - /// `default_heap_pages` - Number of 64KB pages to allocate for Wasm execution. - /// Defaults to `DEFAULT_HEAP_PAGES` if `None` is provided. - /// - /// # Return value - /// - /// If no error occurred a tuple `(wasmi::ModuleRef, Option)` is - /// returned. `RuntimeVersion` is contained if the call to `Core_version` returned - /// a version. - /// - /// In case of failure one of two errors can be returned: - /// - /// `Err::InvalidCode` is returned for runtime code issues. - /// - /// `Error::InvalidMemoryReference` is returned if no memory export with the - /// identifier `memory` can be found in the runtime. - pub fn fetch_runtime>( - &mut self, - wasm_executor: &WasmExecutor, - ext: &mut E, - default_heap_pages: Option, - ) -> Result, Error> { - let code_hash = ext - .original_storage_hash(well_known_keys::CODE) - .ok_or(Error::InvalidCode("`CODE` not found in storage.".into()))?; - - // This is direct result from fighting with borrowck. - let handle_result = - |cached_result: &Result, CacheError>| match *cached_result { - Err(ref e) => Err(Error::InvalidCode(format!("{:?}", e))), - Ok(ref cached_runtime) => Ok(Rc::clone(cached_runtime)), - }; - - match self.instances.entry(code_hash.into()) { - Entry::Occupied(o) => handle_result(o.get()), - Entry::Vacant(v) => { - trace!(target: "runtimes_cache", "no instance found in cache, creating now."); - let result = Self::create_wasm_instance(wasm_executor, ext, default_heap_pages); - if let Err(ref err) = result { - warn!(target: "runtimes_cache", "cannot create a runtime: {:?}", err); - } - handle_result(v.insert(result)) - } - } - } - - fn create_wasm_instance>( - wasm_executor: &WasmExecutor, - ext: &mut E, - default_heap_pages: Option, - ) -> Result, CacheError> { - let code = ext - .original_storage(well_known_keys::CODE) - .ok_or(CacheError::CodeNotFound)?; - let module = WasmModule::from_buffer(&code).map_err(|_| CacheError::InvalidModule)?; - - // Extract the data segments from the wasm code. - // - // A return of this error actually indicates that there is a problem in logic, since - // we just loaded and validated the `module` above. - let data_segments = extract_data_segments(&code).ok_or(CacheError::CantDeserializeWasm)?; - - let heap_pages = ext - .storage(well_known_keys::HEAP_PAGES) - .and_then(|pages| u64::decode(&mut &pages[..]).ok()) - .or(default_heap_pages) - .unwrap_or(DEFAULT_HEAP_PAGES); - - // Instantiate this module. - let instance = WasmExecutor::instantiate_module::(heap_pages as usize, &module) - .map_err(CacheError::Instantiation)?; - - // Take state snapshot before executing anything. - let state_snapshot = StateSnapshot::take(&instance, data_segments, heap_pages as u32) - .expect( - "`take` returns `Err` if the module is not valid; - we already loaded module above, thus the `Module` is proven to be valid at this point; - qed - ", - ); - - let version = wasm_executor - .call_in_wasm_module(ext, &instance, "Core_version", &[]) - .ok() - .and_then(|v| RuntimeVersion::decode(&mut v.as_slice()).ok()); - Ok(Rc::new(CachedRuntime { - instance, - version, - state_snapshot, - })) - } -} - -/// Extract the data segments from the given wasm code. -/// -/// Returns `Err` if the given wasm code cannot be deserialized. -fn extract_data_segments(wasm_code: &[u8]) -> Option> { - let raw_module: RawModule = deserialize_buffer(wasm_code).ok()?; - let segments = raw_module - .data_section() - .map(|ds| ds.entries()) - .unwrap_or(&[]) - .to_vec(); - Some(segments) -} diff --git a/core/executor/src/wasm_utils.rs b/core/executor/src/wasm_utils.rs index 80ef376df5212dcb8a329169d85d8e8bb376859e..6c1b1ebc50ac110ef9a7f802fe1a2609da5dfe4d 100644 --- a/core/executor/src/wasm_utils.rs +++ b/core/executor/src/wasm_utils.rs @@ -14,131 +14,98 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Rust implementation of Substrate contracts. +//! Utilities for defining the wasm host environment. -use wasmi::{ValueType, RuntimeValue}; -use wasmi::nan_preserving_float::{F32, F64}; - -pub trait ConvertibleToWasm { - const VALUE_TYPE: ValueType; - type NativeType; fn to_runtime_value(self) -> RuntimeValue; -} - -impl ConvertibleToWasm for i32 { - type NativeType = i32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self) } -} - -impl ConvertibleToWasm for u32 { - type NativeType = u32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as i32) } -} - -impl ConvertibleToWasm for i64 { - type NativeType = i64; - const VALUE_TYPE: ValueType = ValueType::I64; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I64(self) } -} - -impl ConvertibleToWasm for u64 { - type NativeType = u64; - const VALUE_TYPE: ValueType = ValueType::I64; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I64(self as i64) } -} - -impl ConvertibleToWasm for F32 { - type NativeType = F32; - const VALUE_TYPE: ValueType = ValueType::F32; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::F32(self) } -} - -impl ConvertibleToWasm for F64 { - type NativeType = F64; - const VALUE_TYPE: ValueType = ValueType::F64; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::F64(self) } -} - -impl ConvertibleToWasm for isize { - type NativeType = i32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as i32) } -} - -impl ConvertibleToWasm for usize { - type NativeType = u32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as u32 as i32) } -} - -impl ConvertibleToWasm for *const T { - type NativeType = u32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as isize as i32) } -} - -impl ConvertibleToWasm for *mut T { - type NativeType = u32; - const VALUE_TYPE: ValueType = ValueType::I32; - fn to_runtime_value(self) -> RuntimeValue { RuntimeValue::I32(self as isize as i32) } -} +use wasm_interface::{Pointer, WordSize}; /// Converts arguments into respective WASM types. #[macro_export] macro_rules! convert_args { () => ([]); - ( $( $t:ty ),* ) => ( [ $( { use $crate::wasm_utils::ConvertibleToWasm; <$t>::VALUE_TYPE }, )* ] ); + ( $( $t:ty ),* ) => ( [ $( <$t as $crate::wasm_interface::IntoValue>::VALUE_TYPE, )* ] ); } /// Generates a WASM signature for given list of parameters. #[macro_export] macro_rules! gen_signature { ( ( $( $params: ty ),* ) ) => ( - { - $crate::wasmi::Signature::new(&convert_args!($($params),*)[..], None) + $crate::wasm_interface::Signature { + args: std::borrow::Cow::Borrowed(&convert_args!( $( $params ),* )[..]), + return_value: None, } ); - - ( ( $( $params: ty ),* ) -> $returns: ty ) => ( - { - $crate::wasmi::Signature::new(&convert_args!($($params),*)[..], Some({ - use $crate::wasm_utils::ConvertibleToWasm; <$returns>::VALUE_TYPE - })) + ( ( $( $params: ty ),* ) -> $returns:ty ) => ( + $crate::wasm_interface::Signature { + args: std::borrow::Cow::Borrowed(&convert_args!( $( $params ),* )[..]), + return_value: Some(<$returns as $crate::wasm_interface::IntoValue>::VALUE_TYPE), } ); } -macro_rules! resolve_fn { - (@iter $index:expr, $sig_var:ident, $name_var:ident) => (); - (@iter $index:expr, $sig_var:ident, $name_var:ident $name:ident ( $( $params:ty ),* ) $( -> $returns:ty )* => $($tail:tt)* ) => ( - if $name_var == stringify!($name) { - let signature = gen_signature!( ( $( $params ),* ) $( -> $returns )* ); - if $sig_var != &signature { - return Err($crate::wasmi::Error::Instantiation( - format!("Export {} has different signature {:?}", $name_var, $sig_var), - )); +macro_rules! gen_functions { + (@INTERNAL + { $( $generated:tt )* } + $context:ident, + ) => ( + &[ $( $generated )* ] + ); + (@INTERNAL + { $( $generated:tt )* } + $context:ident, + $name:ident ( $( $names:ident: $params:ty ),* ) $( -> $returns:ty )? { $( $body:tt )* } + $( $tail:tt )* + ) => ( + gen_functions! { + @INTERNAL + { + $( $generated )* + { + struct $name; + + #[allow(unused)] + impl $crate::wasm_interface::Function for $name { + fn name(&self) -> &str { + stringify!($name) + } + fn signature(&self) -> $crate::wasm_interface::Signature { + gen_signature!( ( $( $params ),* ) $( -> $returns )? ) + } + fn execute( + &self, + context: &mut dyn $crate::wasm_interface::FunctionContext, + args: &mut dyn Iterator, + ) -> ::std::result::Result, String> { + let mut $context = context; + marshall! { + args, + ( $( $names : $params ),* ) $( -> $returns )? => { $( $body )* } + } + } + } + + &$name as &dyn $crate::wasm_interface::Function + }, } - return Ok($crate::wasmi::FuncInstance::alloc_host(signature, $index)); + $context, + $( $tail )* } - resolve_fn!(@iter $index + 1, $sig_var, $name_var $($tail)*) ); - ($sig_var:ident, $name_var:ident, $($tail:tt)* ) => ( - resolve_fn!(@iter 0, $sig_var, $name_var $($tail)*); + ( $context:ident, $( $tail:tt )* ) => ( + gen_functions!(@INTERNAL {} $context, $($tail)*); ); } /// Converts the list of arguments coming from WASM into their native types. #[macro_export] macro_rules! unmarshall_args { - ( $body:tt, $objectname:ident, $args_iter:ident, $( $names:ident : $params:ty ),*) => ({ + ( $body:tt, $args_iter:ident, $( $names:ident : $params:ty ),*) => ({ $( - let $names : <$params as $crate::wasm_utils::ConvertibleToWasm>::NativeType = + let $names : $params = $args_iter.next() - .and_then(|rt_val| rt_val.try_into()) + .and_then(|val| <$params as $crate::wasm_interface::TryFromValue>::try_from_value(val)) .expect( - "`$args_iter` comes from an argument of Externals::invoke_index; + "`$args_iter` comes from an argument of Externals::execute_function; args to an external call always matches the signature of the external; external signatures are built with count and types and in order defined by `$params`; here, we iterating on `$params`; @@ -160,7 +127,7 @@ macro_rules! unmarshall_args { #[inline(always)] pub fn constrain_closure(f: F) -> F where - F: FnOnce() -> Result + F: FnOnce() -> Result { f } @@ -168,104 +135,52 @@ where /// Pass the list of parameters by converting them to respective WASM types. #[macro_export] macro_rules! marshall { - ( $args_iter:ident, $objectname:ident, ( $( $names:ident : $params:ty ),* ) -> $returns:ty => $body:tt ) => ({ - let body = $crate::wasm_utils::constrain_closure::< - <$returns as $crate::wasm_utils::ConvertibleToWasm>::NativeType, _ - >(|| { - unmarshall_args!($body, $objectname, $args_iter, $( $names : $params ),*) + ( $args_iter:ident, ( $( $names:ident : $params:ty ),* ) -> $returns:ty => $body:tt ) => ({ + let body = $crate::wasm_utils::constrain_closure::<$returns, _>(|| { + unmarshall_args!($body, $args_iter, $( $names : $params ),*) }); - let r = body().map_err(wasmi::Trap::from)?; - return Ok(Some({ use $crate::wasm_utils::ConvertibleToWasm; r.to_runtime_value() })) + let r = body()?; + return Ok(Some($crate::wasm_interface::IntoValue::into_value(r))) }); - ( $args_iter:ident, $objectname:ident, ( $( $names:ident : $params:ty ),* ) => $body:tt ) => ({ + ( $args_iter:ident, ( $( $names:ident : $params:ty ),* ) => $body:tt ) => ({ let body = $crate::wasm_utils::constrain_closure::<(), _>(|| { - unmarshall_args!($body, $objectname, $args_iter, $( $names : $params ),*) + unmarshall_args!($body, $args_iter, $( $names : $params ),*) }); - body().map_err(wasmi::Trap::from)?; + body()?; return Ok(None) }) } -macro_rules! dispatch_fn { - ( @iter $index:expr, $index_ident:ident, $objectname:ident, $args_iter:ident) => { - // `$index` comes from an argument of Externals::invoke_index; - // externals are always invoked with index given by resolve_fn! at resolve time; - // For each next function resolve_fn! gives new index, starting from 0; - // Both dispatch_fn! and resolve_fn! are called with the same list of functions; - // qed; - panic!("fn with index {} is undefined", $index); - }; - - (@iter - $index:expr, - $index_ident:ident, - $objectname:ident, - $args_iter:ident, - $name:ident ( $( $names:ident : $params:ty ),* ) $( -> $returns:ty )* => $body:tt $($tail:tt)* - ) => ( - if $index_ident == $index { - { marshall!($args_iter, $objectname, ( $( $names : $params ),* ) $( -> $returns )* => $body) } - } - dispatch_fn!( @iter $index + 1, $index_ident, $objectname, $args_iter $($tail)*) - ); - - ( $index_ident:ident, $objectname:ident, $args_iter:ident, $($tail:tt)* ) => ( - dispatch_fn!( @iter 0, $index_ident, $objectname, $args_iter, $($tail)*); - ); -} - -/// Implements `wasmi::Externals` trait and `Resolver` for given struct. +/// Implements the wasm host interface for the given type. #[macro_export] -macro_rules! impl_function_executor { +macro_rules! impl_wasm_host_interface { ( - $objectname:ident : $structname:ty, - $( - $name:ident - ( $( $names:ident : $params:ty ),* $(,)? ) - $( -> $returns:ty )? => { $( $body:tt )* }, - )* - => $( $pre:tt )+ - ) => ( - impl $( $pre ) + $structname { - #[allow(unused)] - fn resolver() -> &'static dyn $crate::wasmi::ModuleImportResolver { - struct Resolver; - impl $crate::wasmi::ModuleImportResolver for Resolver { - fn resolve_func( - &self, - name: &str, - signature: &$crate::wasmi::Signature - ) -> std::result::Result<$crate::wasmi::FuncRef, $crate::wasmi::Error> { - resolve_fn!( - signature, - name, - $( $name( $( $params ),* ) $( -> $returns )? => )* - ); - - Err($crate::wasmi::Error::Instantiation( - format!("Export {} not found", name), - )) - } - } - &Resolver - } + impl $interface_name:ident where $context:ident { + $( + $name:ident($( $names:ident : $params:ty ),* $(,)? ) $( -> $returns:ty )? + { $( $body:tt )* } + )* } - - impl $( $pre ) + $crate::wasmi::Externals for $structname { - fn invoke_index( - &mut self, - index: usize, - args: $crate::wasmi::RuntimeArgs, - ) -> std::result::Result, $crate::wasmi::Trap> { - let $objectname = self; - let mut args = args.as_ref().iter(); - dispatch_fn! { - index, - $objectname, - args, - $( $name( $( $names : $params ),* ) $( -> $returns )? => { $( $body )* } ),* - }; + ) => ( + impl $crate::wasm_interface::HostFunctions for $interface_name { + #[allow(non_camel_case_types)] + fn functions() -> &'static [&'static dyn $crate::wasm_interface::Function] { + gen_functions!( + $context, + $( $name( $( $names: $params ),* ) $( -> $returns )? { $( $body )* } )* + ) } } ); } + +/// Runtime API functions return an i64 which encodes a pointer in the least-significant 32 bits +/// and a length in the most-significant 32 bits. This interprets the returned value as a pointer, +/// length tuple. +pub fn interpret_runtime_api_result(retval: i64) -> (Pointer, WordSize) { + let ptr = >::new(retval as u32); + // The first cast to u64 is necessary so that the right shift does not sign-extend. + let len = ((retval as u64) >> 32) as WordSize; + (ptr, len) +} + diff --git a/core/executor/src/wasmi_execution.rs b/core/executor/src/wasmi_execution.rs new file mode 100644 index 0000000000000000000000000000000000000000..dcd6ae89094bcc944c6e9aec783443894bf9dbcf --- /dev/null +++ b/core/executor/src/wasmi_execution.rs @@ -0,0 +1,636 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of a Wasm runtime using the Wasmi interpreter. + +use std::{str, mem}; +use wasmi::{ + Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, + memory_units::Pages, RuntimeValue::{I32, I64, self}, +}; +use crate::error::{Error, WasmError}; +use codec::{Encode, Decode}; +use primitives::{sandbox as sandbox_primitives, traits::Externalities}; +use crate::host_interface::SubstrateExternals; +use crate::sandbox; +use crate::allocator; +use crate::wasm_utils::interpret_runtime_api_result; +use crate::wasm_runtime::WasmRuntime; +use log::trace; +use parity_wasm::elements::{deserialize_buffer, DataSegment, Instruction, Module as RawModule}; +use wasm_interface::{ + FunctionContext, HostFunctions, Pointer, WordSize, Sandbox, MemoryId, Result as WResult, +}; + +struct FunctionExecutor { + sandbox_store: sandbox::Store, + heap: allocator::FreeingBumpHeapAllocator, + memory: MemoryRef, + table: Option, +} + +impl FunctionExecutor { + fn new(m: MemoryRef, heap_base: u32, t: Option) -> Result { + Ok(FunctionExecutor { + sandbox_store: sandbox::Store::new(), + heap: allocator::FreeingBumpHeapAllocator::new(heap_base), + memory: m, + table: t, + }) + } +} + +impl sandbox::SandboxCapabilities for FunctionExecutor { + type SupervisorFuncRef = wasmi::FuncRef; + + fn store(&self) -> &sandbox::Store { + &self.sandbox_store + } + fn store_mut(&mut self) -> &mut sandbox::Store { + &mut self.sandbox_store + } + fn allocate(&mut self, len: WordSize) -> Result, Error> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.allocate(mem, len) + }) + } + fn deallocate(&mut self, ptr: Pointer) -> Result<(), Error> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.deallocate(mem, ptr) + }) + } + fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<(), Error> { + self.memory.set(ptr.into(), data).map_err(Into::into) + } + fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result, Error> { + self.memory.get(ptr.into(), len as usize).map_err(Into::into) + } + + fn invoke( + &mut self, + dispatch_thunk: &Self::SupervisorFuncRef, + invoke_args_ptr: Pointer, + invoke_args_len: WordSize, + state: u32, + func_idx: sandbox::SupervisorFuncIndex, + ) -> Result + { + let result = wasmi::FuncInstance::invoke( + dispatch_thunk, + &[ + RuntimeValue::I32(u32::from(invoke_args_ptr) as i32), + RuntimeValue::I32(invoke_args_len as i32), + RuntimeValue::I32(state as i32), + RuntimeValue::I32(usize::from(func_idx) as i32), + ], + self, + ); + match result { + Ok(Some(RuntimeValue::I64(val))) => Ok(val), + Ok(_) => return Err("Supervisor function returned unexpected result!".into()), + Err(err) => Err(Error::Trap(err)), + } + } +} + +impl FunctionContext for FunctionExecutor { + fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> WResult<()> { + self.memory.get_into(address.into(), dest).map_err(|e| e.to_string()) + } + + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> WResult<()> { + self.memory.set(address.into(), data).map_err(|e| e.to_string()) + } + + fn allocate_memory(&mut self, size: WordSize) -> WResult> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.allocate(mem, size).map_err(|e| e.to_string()) + }) + } + + fn deallocate_memory(&mut self, ptr: Pointer) -> WResult<()> { + let heap = &mut self.heap; + self.memory.with_direct_access_mut(|mem| { + heap.deallocate(mem, ptr).map_err(|e| e.to_string()) + }) + } + + fn sandbox(&mut self) -> &mut dyn Sandbox { + self + } +} + +impl Sandbox for FunctionExecutor { + fn memory_get( + &mut self, + memory_id: MemoryId, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> WResult { + let sandboxed_memory = self.sandbox_store.memory(memory_id).map_err(|e| e.to_string())?; + + match MemoryInstance::transfer( + &sandboxed_memory, + offset as usize, + &self.memory, + buf_ptr.into(), + buf_len as usize, + ) { + Ok(()) => Ok(sandbox_primitives::ERR_OK), + Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + } + } + + fn memory_set( + &mut self, + memory_id: MemoryId, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> WResult { + let sandboxed_memory = self.sandbox_store.memory(memory_id).map_err(|e| e.to_string())?; + + match MemoryInstance::transfer( + &self.memory, + val_ptr.into(), + &sandboxed_memory, + offset as usize, + val_len as usize, + ) { + Ok(()) => Ok(sandbox_primitives::ERR_OK), + Err(_) => Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + } + } + + fn memory_teardown(&mut self, memory_id: MemoryId) -> WResult<()> { + self.sandbox_store.memory_teardown(memory_id).map_err(|e| e.to_string()) + } + + fn memory_new( + &mut self, + initial: u32, + maximum: u32, + ) -> WResult { + self.sandbox_store.new_memory(initial, maximum).map_err(|e| e.to_string()) + } + + fn invoke( + &mut self, + instance_id: u32, + export_name: &str, + args: &[u8], + return_val: Pointer, + return_val_len: WordSize, + state: u32, + ) -> WResult { + trace!(target: "sr-sandbox", "invoke, instance_idx={}", instance_id); + + // Deserialize arguments and convert them into wasmi types. + let args = Vec::::decode(&mut &args[..]) + .map_err(|_| "Can't decode serialized arguments for the invocation")? + .into_iter() + .map(Into::into) + .collect::>(); + + let instance = self.sandbox_store.instance(instance_id).map_err(|e| e.to_string())?; + let result = instance.invoke(export_name, &args, self, state); + + match result { + Ok(None) => Ok(sandbox_primitives::ERR_OK), + Ok(Some(val)) => { + // Serialize return value and write it back into the memory. + sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { + if val.len() > return_val_len as usize { + Err("Return value buffer is too small")?; + } + self.write_memory(return_val, val).map_err(|_| "Return value buffer is OOB")?; + Ok(sandbox_primitives::ERR_OK) + }) + } + Err(_) => Ok(sandbox_primitives::ERR_EXECUTION), + } + } + + fn instance_teardown(&mut self, instance_id: u32) -> WResult<()> { + self.sandbox_store.instance_teardown(instance_id).map_err(|e| e.to_string()) + } + + fn instance_new( + &mut self, + dispatch_thunk_id: u32, + wasm: &[u8], + raw_env_def: &[u8], + state: u32, + ) -> WResult { + // Extract a dispatch thunk from instance's table by the specified index. + let dispatch_thunk = { + let table = self.table.as_ref() + .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?; + table.get(dispatch_thunk_id) + .map_err(|_| "dispatch_thunk_idx is out of the table bounds")? + .ok_or_else(|| "dispatch_thunk_idx points on an empty table entry")? + .clone() + }; + + let instance_idx_or_err_code = + match sandbox::instantiate(self, dispatch_thunk, wasm, raw_env_def, state) { + Ok(instance_idx) => instance_idx, + Err(sandbox::InstantiationError::StartTrapped) => + sandbox_primitives::ERR_EXECUTION, + Err(_) => sandbox_primitives::ERR_MODULE, + }; + + Ok(instance_idx_or_err_code as u32) + } +} + +impl FunctionExecutor { + fn resolver() -> &'static dyn wasmi::ModuleImportResolver { + struct Resolver; + impl wasmi::ModuleImportResolver for Resolver { + fn resolve_func(&self, name: &str, signature: &wasmi::Signature) + -> std::result::Result + { + let signature = wasm_interface::Signature::from(signature); + + if let Some((index, func)) = SubstrateExternals::functions().iter() + .enumerate() + .find(|f| name == f.1.name()) + { + if signature == func.signature() { + Ok(wasmi::FuncInstance::alloc_host(signature.into(), index)) + } else { + Err(wasmi::Error::Instantiation( + format!( + "Invalid signature for function `{}` expected `{:?}`, got `{:?}`", + func.name(), + signature, + func.signature(), + ) + )) + } + } else { + Err(wasmi::Error::Instantiation( + format!("Export {} not found", name), + )) + } + } + } + &Resolver + } +} + +impl wasmi::Externals for FunctionExecutor { + fn invoke_index(&mut self, index: usize, args: wasmi::RuntimeArgs) + -> Result, wasmi::Trap> + { + let mut args = args.as_ref().iter().copied().map(Into::into); + let function = SubstrateExternals::functions().get(index).ok_or_else(|| + Error::from( + format!("Could not find host function with index: {}", index), + ) + )?; + + function.execute(self, &mut args) + .map_err(|msg| Error::FunctionExecution(function.name().to_string(), msg)) + .map_err(wasmi::Trap::from) + .map(|v| v.map(Into::into)) + } +} + +fn get_mem_instance(module: &ModuleRef) -> Result { + Ok(module + .export_by_name("memory") + .ok_or_else(|| Error::InvalidMemoryReference)? + .as_memory() + .ok_or_else(|| Error::InvalidMemoryReference)? + .clone()) +} + +/// Find the global named `__heap_base` in the given wasm module instance and +/// tries to get its value. +fn get_heap_base(module: &ModuleRef) -> Result { + let heap_base_val = module + .export_by_name("__heap_base") + .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? + .as_global() + .ok_or_else(|| Error::HeapBaseNotFoundOrInvalid)? + .get(); + + match heap_base_val { + wasmi::RuntimeValue::I32(v) => Ok(v as u32), + _ => Err(Error::HeapBaseNotFoundOrInvalid), + } +} + +/// Call a given method in the given wasm-module runtime. +fn call_in_wasm_module( + ext: &mut dyn Externalities, + module_instance: &ModuleRef, + method: &str, + data: &[u8], +) -> Result, Error> { + call_in_wasm_module_with_custom_signature( + ext, + module_instance, + method, + |alloc| { + let offset = alloc(data)?; + Ok(vec![I32(offset as i32), I32(data.len() as i32)]) + }, + |res, memory| { + if let Some(I64(retval)) = res { + let (ptr, length) = interpret_runtime_api_result(retval); + memory.get(ptr.into(), length as usize).map_err(|_| Error::Runtime).map(Some) + } else { + Ok(None) + } + } + ) +} + +/// Call a given method in the given wasm-module runtime. +fn call_in_wasm_module_with_custom_signature< + F: FnOnce(&mut dyn FnMut(&[u8]) -> Result) -> Result, Error>, + FR: FnOnce(Option, &MemoryRef) -> Result, Error>, + R, +>( + ext: &mut dyn Externalities, + module_instance: &ModuleRef, + method: &str, + create_parameters: F, + filter_result: FR, +) -> Result { + // extract a reference to a linear memory, optional reference to a table + // and then initialize FunctionExecutor. + let memory = get_mem_instance(module_instance)?; + let table: Option = module_instance + .export_by_name("__indirect_function_table") + .and_then(|e| e.as_table().cloned()); + let heap_base = get_heap_base(module_instance)?; + + let mut fec = FunctionExecutor::new( + memory.clone(), + heap_base, + table, + )?; + + let parameters = create_parameters(&mut |data: &[u8]| { + let offset = fec.allocate_memory(data.len() as u32)?; + fec.write_memory(offset, data).map(|_| offset.into()).map_err(Into::into) + })?; + + let result = externalities::set_and_run_with_externalities( + ext, + || module_instance.invoke_export(method, ¶meters, &mut fec), + ); + + match result { + Ok(val) => match filter_result(val, &memory)? { + Some(val) => Ok(val), + None => Err(Error::InvalidReturn), + }, + Err(e) => { + trace!( + target: "wasm-executor", + "Failed to execute code with {} pages", + memory.current_size().0 + ); + Err(e.into()) + }, + } +} + +/// Prepare module instance +fn instantiate_module( + heap_pages: usize, + module: &Module, +) -> Result { + // start module instantiation. Don't run 'start' function yet. + let intermediate_instance = ModuleInstance::new( + module, + &ImportsBuilder::new() + .with_resolver("env", FunctionExecutor::resolver()) + )?; + + // Verify that the module has the heap base global variable. + let _ = get_heap_base(intermediate_instance.not_started_instance())?; + + // Extract a reference to a linear memory. + let memory = get_mem_instance(intermediate_instance.not_started_instance())?; + memory.grow(Pages(heap_pages)).map_err(|_| Error::Runtime)?; + + if intermediate_instance.has_start() { + // Runtime is not allowed to have the `start` function. + Err(Error::RuntimeHasStartFn) + } else { + Ok(intermediate_instance.assert_no_start()) + } +} + +/// A state snapshot of an instance taken just after instantiation. +/// +/// It is used for restoring the state of the module after execution. +#[derive(Clone)] +struct StateSnapshot { + /// The offset and the content of the memory segments that should be used to restore the snapshot + data_segments: Vec<(u32, Vec)>, + /// The list of all global mutable variables of the module in their sequential order. + global_mut_values: Vec, + heap_pages: u64, +} + +impl StateSnapshot { + // Returns `None` if instance is not valid. + fn take( + module_instance: &ModuleRef, + data_segments: Vec, + heap_pages: u64, + ) -> Option { + let prepared_segments = data_segments + .into_iter() + .map(|mut segment| { + // Just replace contents of the segment since the segments will be discarded later + // anyway. + let contents = mem::replace(segment.value_mut(), vec![]); + + let init_expr = match segment.offset() { + Some(offset) => offset.code(), + // Return if the segment is passive + None => return None + }; + + // [op, End] + if init_expr.len() != 2 { + return None; + } + let offset = match init_expr[0] { + Instruction::I32Const(v) => v as u32, + Instruction::GetGlobal(idx) => { + let global_val = module_instance.globals().get(idx as usize)?.get(); + match global_val { + RuntimeValue::I32(v) => v as u32, + _ => return None, + } + } + _ => return None, + }; + + Some((offset, contents)) + }) + .collect::>>()?; + + // Collect all values of mutable globals. + let global_mut_values = module_instance + .globals() + .iter() + .filter(|g| g.is_mutable()) + .map(|g| g.get()) + .collect(); + + Some(Self { + data_segments: prepared_segments, + global_mut_values, + heap_pages, + }) + } + + /// Reset the runtime instance to the initial version by restoring + /// the preserved memory and globals. + /// + /// Returns `Err` if applying the snapshot is failed. + fn apply(&self, instance: &ModuleRef) -> Result<(), WasmError> { + let memory = instance + .export_by_name("memory") + .ok_or(WasmError::ApplySnapshotFailed)? + .as_memory() + .cloned() + .ok_or(WasmError::ApplySnapshotFailed)?; + + // First, erase the memory and copy the data segments into it. + memory + .erase() + .map_err(|_| WasmError::ApplySnapshotFailed)?; + for (offset, contents) in &self.data_segments { + memory + .set(*offset, contents) + .map_err(|_| WasmError::ApplySnapshotFailed)?; + } + + // Second, restore the values of mutable globals. + for (global_ref, global_val) in instance + .globals() + .iter() + .filter(|g| g.is_mutable()) + .zip(self.global_mut_values.iter()) + { + // the instance should be the same as used for preserving and + // we iterate the same way it as we do it for preserving values that means that the + // types should be the same and all the values are mutable. So no error is expected/ + global_ref + .set(*global_val) + .map_err(|_| WasmError::ApplySnapshotFailed)?; + } + Ok(()) + } +} + +/// A runtime along with its initial state snapshot. +#[derive(Clone)] +pub struct WasmiRuntime { + /// A wasm module instance. + instance: ModuleRef, + /// The snapshot of the instance's state taken just after the instantiation. + state_snapshot: StateSnapshot, +} + +impl WasmiRuntime { + /// Perform an operation with the clean version of the runtime wasm instance. + fn with(&self, f: F) -> R + where + F: FnOnce(&ModuleRef) -> R, + { + self.state_snapshot.apply(&self.instance).expect( + "applying the snapshot can only fail if the passed instance is different + from the one that was used for creation of the snapshot; + we use the snapshot that is directly associated with the instance; + thus the snapshot was created using the instance; + qed", + ); + f(&self.instance) + } +} + +impl WasmRuntime for WasmiRuntime { + fn update_heap_pages(&mut self, heap_pages: u64) -> bool { + self.state_snapshot.heap_pages == heap_pages + } + + fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) + -> Result, Error> + { + self.with(|module| { + call_in_wasm_module(ext, module, method, data) + }) + } +} + +pub fn create_instance(code: &[u8], heap_pages: u64) -> Result { + let module = Module::from_buffer(&code).map_err(|_| WasmError::InvalidModule)?; + + // Extract the data segments from the wasm code. + // + // A return of this error actually indicates that there is a problem in logic, since + // we just loaded and validated the `module` above. + let data_segments = extract_data_segments(&code)?; + + // Instantiate this module. + let instance = instantiate_module(heap_pages as usize, &module) + .map_err(|e| WasmError::Instantiation(e.to_string()))?; + + // Take state snapshot before executing anything. + let state_snapshot = StateSnapshot::take(&instance, data_segments, heap_pages) + .expect( + "`take` returns `Err` if the module is not valid; + we already loaded module above, thus the `Module` is proven to be valid at this point; + qed + ", + ); + + Ok(WasmiRuntime { + instance, + state_snapshot, + }) +} + +/// Extract the data segments from the given wasm code. +/// +/// Returns `Err` if the given wasm code cannot be deserialized. +fn extract_data_segments(wasm_code: &[u8]) -> Result, WasmError> { + let raw_module: RawModule = deserialize_buffer(wasm_code) + .map_err(|_| WasmError::CantDeserializeWasm)?; + + let segments = raw_module + .data_section() + .map(|ds| ds.entries()) + .unwrap_or(&[]) + .to_vec(); + Ok(segments) +} diff --git a/core/executor/src/wasmtime/function_executor.rs b/core/executor/src/wasmtime/function_executor.rs new file mode 100644 index 0000000000000000000000000000000000000000..5dc8f42b280c45a53ef7c4829e03bd086c19e64d --- /dev/null +++ b/core/executor/src/wasmtime/function_executor.rs @@ -0,0 +1,387 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::allocator::FreeingBumpHeapAllocator; +use crate::error::{Error, Result}; +use crate::sandbox::{self, SandboxCapabilities, SupervisorFuncIndex}; +use crate::wasmtime::util::{ + checked_range, cranelift_ir_signature, read_memory_into, write_memory_from, +}; + +use codec::{Decode, Encode}; +use cranelift_codegen::ir; +use cranelift_codegen::isa::TargetFrontendConfig; +use log::trace; +use primitives::sandbox as sandbox_primitives; +use std::{cmp, mem, ptr}; +use wasmtime_environ::translate_signature; +use wasmtime_jit::{ActionError, Compiler}; +use wasmtime_runtime::{Export, VMCallerCheckedAnyfunc, VMContext, wasmtime_call_trampoline}; +use wasm_interface::{ + FunctionContext, MemoryId, Pointer, Result as WResult, Sandbox, Signature, Value, ValueType, + WordSize, +}; + +/// Wrapper type for pointer to a Wasm table entry. +/// +/// The wrapper type is used to ensure that the function reference is valid as it must be unsafely +/// dereferenced from within the safe method `::invoke`. +#[derive(Clone, Copy)] +pub struct SupervisorFuncRef(*const VMCallerCheckedAnyfunc); + +/// The state required to construct a FunctionExecutor context. The context only lasts for one host +/// call, whereas the state is maintained for the duration of a Wasm runtime call, which may make +/// many different host calls that must share state. +/// +/// This is stored as part of the host state of the "env" Wasmtime instance. +pub struct FunctionExecutorState { + sandbox_store: sandbox::Store, + heap: FreeingBumpHeapAllocator, +} + +impl FunctionExecutorState { + /// Constructs a new `FunctionExecutorState`. + pub fn new(heap_base: u32) -> Self { + FunctionExecutorState { + sandbox_store: sandbox::Store::new(), + heap: FreeingBumpHeapAllocator::new(heap_base), + } + } + + /// Returns a mutable reference to the heap allocator. + pub fn heap(&mut self) -> &mut FreeingBumpHeapAllocator { + &mut self.heap + } +} + +/// A `FunctionExecutor` implements `FunctionContext` for making host calls from a Wasmtime +/// runtime. The `FunctionExecutor` exists only for the lifetime of the call and borrows state from +/// a longer-living `FunctionExecutorState`. +pub struct FunctionExecutor<'a> { + compiler: &'a mut Compiler, + sandbox_store: &'a mut sandbox::Store, + heap: &'a mut FreeingBumpHeapAllocator, + memory: &'a mut [u8], + table: Option<&'a [VMCallerCheckedAnyfunc]>, +} + +impl<'a> FunctionExecutor<'a> { + /// Construct a new `FunctionExecutor`. + /// + /// The vmctx MUST come from a call to a function in the "env" module. + /// The state MUST be looked up from the host state of the "env" module. + pub unsafe fn new( + vmctx: *mut VMContext, + compiler: &'a mut Compiler, + state: &'a mut FunctionExecutorState, + ) -> Result + { + let memory = match (*vmctx).lookup_global_export("memory") { + Some(Export::Memory { definition, vmctx: _, memory: _ }) => + std::slice::from_raw_parts_mut( + (*definition).base, + (*definition).current_length, + ), + _ => return Err(Error::InvalidMemoryReference), + }; + let table = match (*vmctx).lookup_global_export("__indirect_function_table") { + Some(Export::Table { definition, vmctx: _, table: _ }) => + Some(std::slice::from_raw_parts( + (*definition).base as *const VMCallerCheckedAnyfunc, + (*definition).current_elements as usize, + )), + _ => None, + }; + Ok(FunctionExecutor { + compiler, + sandbox_store: &mut state.sandbox_store, + heap: &mut state.heap, + memory, + table, + }) + } +} + +impl<'a> SandboxCapabilities for FunctionExecutor<'a> { + type SupervisorFuncRef = SupervisorFuncRef; + + fn store(&self) -> &sandbox::Store { + &self.sandbox_store + } + + fn store_mut(&mut self) -> &mut sandbox::Store { + &mut self.sandbox_store + } + + fn allocate(&mut self, len: WordSize) -> Result> { + self.heap.allocate(self.memory, len) + } + + fn deallocate(&mut self, ptr: Pointer) -> Result<()> { + self.heap.deallocate(self.memory, ptr) + } + + fn write_memory(&mut self, ptr: Pointer, data: &[u8]) -> Result<()> { + write_memory_from(self.memory, ptr, data) + } + + fn read_memory(&self, ptr: Pointer, len: WordSize) -> Result> { + let mut output = vec![0; len as usize]; + read_memory_into(self.memory, ptr, output.as_mut())?; + Ok(output) + } + + fn invoke( + &mut self, + dispatch_thunk: &Self::SupervisorFuncRef, + invoke_args_ptr: Pointer, + invoke_args_len: WordSize, + state: u32, + func_idx: SupervisorFuncIndex, + ) -> Result + { + let func_ptr = unsafe { (*dispatch_thunk.0).func_ptr }; + let vmctx = unsafe { (*dispatch_thunk.0).vmctx }; + + // The following code is based on the wasmtime_jit::Context::invoke. + let value_size = mem::size_of::(); + let (signature, mut values_vec) = generate_signature_and_args( + &[ + Value::I32(u32::from(invoke_args_ptr) as i32), + Value::I32(invoke_args_len as i32), + Value::I32(state as i32), + Value::I32(usize::from(func_idx) as i32), + ], + Some(ValueType::I64), + self.compiler.frontend_config(), + ); + + // Get the trampoline to call for this function. + let exec_code_buf = self.compiler + .get_published_trampoline(func_ptr, &signature, value_size) + .map_err(ActionError::Setup) + .map_err(Error::Wasmtime)?; + + // Call the trampoline. + if let Err(message) = unsafe { + wasmtime_call_trampoline( + vmctx, + exec_code_buf, + values_vec.as_mut_ptr() as *mut u8, + ) + } { + return Err(Error::Other(message)); + } + + // Load the return value out of `values_vec`. + Ok(unsafe { ptr::read(values_vec.as_ptr() as *const i64) }) + } +} + +impl<'a> FunctionContext for FunctionExecutor<'a> { + fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> WResult<()> { + read_memory_into(self.memory, address, dest).map_err(|e| e.to_string()) + } + + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> WResult<()> { + write_memory_from(self.memory, address, data).map_err(|e| e.to_string()) + } + + fn allocate_memory(&mut self, size: WordSize) -> WResult> { + self.heap.allocate(self.memory, size).map_err(|e| e.to_string()) + } + + fn deallocate_memory(&mut self, ptr: Pointer) -> WResult<()> { + self.heap.deallocate(self.memory, ptr).map_err(|e| e.to_string()) + } + + fn sandbox(&mut self) -> &mut dyn Sandbox { + self + } +} + +impl<'a> Sandbox for FunctionExecutor<'a> { + fn memory_get( + &mut self, + memory_id: MemoryId, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> WResult + { + let sandboxed_memory = self.sandbox_store.memory(memory_id) + .map_err(|e| e.to_string())?; + sandboxed_memory.with_direct_access(|memory| { + let len = buf_len as usize; + let src_range = match checked_range(offset as usize, len, memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + let dst_range = match checked_range(buf_ptr.into(), len, self.memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + &mut self.memory[dst_range].copy_from_slice(&memory[src_range]); + Ok(sandbox_primitives::ERR_OK) + }) + } + + fn memory_set( + &mut self, + memory_id: MemoryId, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> WResult + { + let sandboxed_memory = self.sandbox_store.memory(memory_id) + .map_err(|e| e.to_string())?; + sandboxed_memory.with_direct_access_mut(|memory| { + let len = val_len as usize; + let src_range = match checked_range(val_ptr.into(), len, self.memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + let dst_range = match checked_range(offset as usize, len, memory.len()) { + Some(range) => range, + None => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS), + }; + &mut memory[dst_range].copy_from_slice(&self.memory[src_range]); + Ok(sandbox_primitives::ERR_OK) + }) + } + + fn memory_teardown(&mut self, memory_id: MemoryId) + -> WResult<()> + { + self.sandbox_store.memory_teardown(memory_id).map_err(|e| e.to_string()) + } + + fn memory_new(&mut self, initial: u32, maximum: MemoryId) -> WResult { + self.sandbox_store.new_memory(initial, maximum).map_err(|e| e.to_string()) + } + + fn invoke( + &mut self, + instance_id: u32, + export_name: &str, + args: &[u8], + return_val: Pointer, + return_val_len: u32, + state: u32, + ) -> WResult { + trace!(target: "sr-sandbox", "invoke, instance_idx={}", instance_id); + + // Deserialize arguments and convert them into wasmi types. + let args = Vec::::decode(&mut &args[..]) + .map_err(|_| "Can't decode serialized arguments for the invocation")? + .into_iter() + .map(Into::into) + .collect::>(); + + let instance = self.sandbox_store.instance(instance_id).map_err(|e| e.to_string())?; + let result = instance.invoke(export_name, &args, self, state); + + match result { + Ok(None) => Ok(sandbox_primitives::ERR_OK), + Ok(Some(val)) => { + // Serialize return value and write it back into the memory. + sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { + if val.len() > return_val_len as usize { + Err("Return value buffer is too small")?; + } + FunctionContext::write_memory(self, return_val, val)?; + Ok(sandbox_primitives::ERR_OK) + }) + } + Err(_) => Ok(sandbox_primitives::ERR_EXECUTION), + } + } + + fn instance_teardown(&mut self, instance_id: u32) -> WResult<()> { + self.sandbox_store.instance_teardown(instance_id).map_err(|e| e.to_string()) + } + + fn instance_new(&mut self, dispatch_thunk_id: u32, wasm: &[u8], raw_env_def: &[u8], state: u32) + -> WResult + { + // Extract a dispatch thunk from instance's table by the specified index. + let dispatch_thunk = { + let table = self.table.as_ref() + .ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?; + let func_ref = table.get(dispatch_thunk_id as usize) + .ok_or_else(|| "dispatch_thunk_idx is out of the table bounds")?; + SupervisorFuncRef(func_ref) + }; + + let instance_idx_or_err_code = + match sandbox::instantiate(self, dispatch_thunk, wasm, raw_env_def, state) { + Ok(instance_idx) => instance_idx, + Err(sandbox::InstantiationError::StartTrapped) => + sandbox_primitives::ERR_EXECUTION, + Err(_) => sandbox_primitives::ERR_MODULE, + }; + + Ok(instance_idx_or_err_code as u32) + } +} + +// The storage for a Wasmtime invocation argument. +#[derive(Debug, Default, Copy, Clone)] +#[repr(C, align(8))] +struct VMInvokeArgument([u8; 8]); + +fn generate_signature_and_args( + args: &[Value], + result_type: Option, + frontend_config: TargetFrontendConfig, +) -> (ir::Signature, Vec) +{ + // This code is based on the wasmtime_jit::Context::invoke. + + let param_types = args.iter() + .map(|arg| arg.value_type()) + .collect::>(); + let signature = translate_signature( + cranelift_ir_signature( + Signature::new(param_types, result_type), + &frontend_config.default_call_conv + ), + frontend_config.pointer_type() + ); + + let mut values_vec = vec![ + VMInvokeArgument::default(); + cmp::max(args.len(), result_type.iter().len()) + ]; + + // Store the argument values into `values_vec`. + for (index, arg) in args.iter().enumerate() { + unsafe { + let ptr = values_vec.as_mut_ptr().add(index); + + match arg { + Value::I32(x) => ptr::write(ptr as *mut i32, *x), + Value::I64(x) => ptr::write(ptr as *mut i64, *x), + Value::F32(x) => ptr::write(ptr as *mut u32, *x), + Value::F64(x) => ptr::write(ptr as *mut u64, *x), + } + } + } + + (signature, values_vec) +} + diff --git a/core/executor/src/wasmtime/mod.rs b/core/executor/src/wasmtime/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..7f442417ab8499906f41f72eb02b8161cdf7e3e5 --- /dev/null +++ b/core/executor/src/wasmtime/mod.rs @@ -0,0 +1,24 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +///! Defines a `WasmRuntime` that uses the Wasmtime JIT to execute. + +mod function_executor; +mod runtime; +mod trampoline; +mod util; + +pub use runtime::create_instance; diff --git a/core/executor/src/wasmtime/runtime.rs b/core/executor/src/wasmtime/runtime.rs new file mode 100644 index 0000000000000000000000000000000000000000..da668e9c309994576af6d52b8990f7fdb7436db2 --- /dev/null +++ b/core/executor/src/wasmtime/runtime.rs @@ -0,0 +1,364 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Defines the compiled Wasm runtime that uses Wasmtime internally. + +use crate::error::{Error, Result, WasmError}; +use crate::host_interface::SubstrateExternals; +use crate::wasm_runtime::WasmRuntime; +use crate::wasm_utils::interpret_runtime_api_result; +use crate::wasmtime::function_executor::FunctionExecutorState; +use crate::wasmtime::trampoline::{EnvState, make_trampoline}; +use crate::wasmtime::util::{cranelift_ir_signature, read_memory_into, write_memory_from}; +use crate::Externalities; + +use cranelift_codegen::ir; +use cranelift_codegen::isa::TargetIsa; +use cranelift_entity::{EntityRef, PrimaryMap}; +use cranelift_frontend::FunctionBuilderContext; +use cranelift_wasm::DefinedFuncIndex; +use std::cell::RefCell; +use std::collections::HashMap; +use std::convert::TryFrom; +use std::rc::Rc; +use wasm_interface::{HostFunctions, Pointer, WordSize}; +use wasmtime_environ::{Module, translate_signature}; +use wasmtime_jit::{ + ActionOutcome, ActionError, CodeMemory, CompilationStrategy, CompiledModule, Compiler, Context, + SetupError, RuntimeValue, +}; +use wasmtime_runtime::{Export, Imports, InstanceHandle, VMFunctionBody}; + +/// A `WasmRuntime` implementation using the Wasmtime JIT to compile the runtime module to native +/// and execute the compiled code. +pub struct WasmtimeRuntime { + module: CompiledModule, + context: Context, + max_heap_pages: Option, + heap_pages: u32, +} + +impl WasmRuntime for WasmtimeRuntime { + fn update_heap_pages(&mut self, heap_pages: u64) -> bool { + match heap_pages_valid(heap_pages, self.max_heap_pages) { + Some(heap_pages) => { + self.heap_pages = heap_pages; + true + } + None => false, + } + } + + fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result> { + call_method( + &mut self.context, + &mut self.module, + ext, + method, + data, + self.heap_pages, + ) + } +} + +/// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to +/// machine code, which can be computationally heavy. +pub fn create_instance(code: &[u8], heap_pages: u64) + -> std::result::Result +{ + let (compiled_module, context) = create_compiled_unit(code)?; + + // Inspect the module for the min and max memory sizes. + let (min_memory_size, max_memory_size) = { + let module = compiled_module.module_ref(); + let memory_index = match module.exports.get("memory") { + Some(wasmtime_environ::Export::Memory(memory_index)) => *memory_index, + _ => return Err(WasmError::InvalidMemory), + }; + let memory_plan = module.memory_plans.get(memory_index) + .expect("memory_index is retrieved from the module's exports map; qed"); + (memory_plan.memory.minimum, memory_plan.memory.maximum) + }; + + // Check that heap_pages is within the allowed range. + let max_heap_pages = max_memory_size.map(|max| max.saturating_sub(min_memory_size)); + let heap_pages = heap_pages_valid(heap_pages, max_heap_pages) + .ok_or_else(|| WasmError::InvalidHeapPages)?; + + Ok(WasmtimeRuntime { + module: compiled_module, + context, + max_heap_pages, + heap_pages, + }) +} + +fn create_compiled_unit(code: &[u8]) + -> std::result::Result<(CompiledModule, Context), WasmError> +{ + let compilation_strategy = CompilationStrategy::Cranelift; + + let compiler = new_compiler(compilation_strategy)?; + let mut context = Context::new(Box::new(compiler)); + + // Enable/disable producing of debug info. + context.set_debug_info(false); + + // Instantiate and link the env module. + let global_exports = context.get_global_exports(); + let compiler = new_compiler(compilation_strategy)?; + let env_module = instantiate_env_module(global_exports, compiler)?; + context.name_instance("env".to_owned(), env_module); + + // Compile the wasm module. + let module = context.compile_module(&code) + .map_err(WasmError::WasmtimeSetup)?; + + Ok((module, context)) +} + +/// Call a function inside a precompiled Wasm module. +fn call_method( + context: &mut Context, + module: &mut CompiledModule, + ext: &mut dyn Externalities, + method: &str, + data: &[u8], + heap_pages: u32, +) -> Result> { + // Old exports get clobbered in `InstanceHandle::new` if we don't explicitly remove them first. + // + // The global exports mechanism is temporary in Wasmtime and expected to be removed. + // https://github.com/CraneStation/wasmtime/issues/332 + clear_globals(&mut *context.get_global_exports().borrow_mut()); + + let mut instance = module.instantiate() + .map_err(SetupError::Instantiate) + .map_err(ActionError::Setup) + .map_err(Error::Wasmtime)?; + + // Ideally there would be a way to set the heap pages during instantiation rather than + // growing the memory after the fact. Currently this may require an additional mmap and copy. + // However, the wasmtime API doesn't support modifying the size of memory on instantiation + // at this time. + grow_memory(&mut instance, heap_pages)?; + + // Initialize the function executor state. + let heap_base = get_heap_base(&instance)?; + let executor_state = FunctionExecutorState::new(heap_base); + reset_env_state_and_take_trap(context, Some(executor_state))?; + + // Write the input data into guest memory. + let (data_ptr, data_len) = inject_input_data(context, &mut instance, data)?; + let args = [RuntimeValue::I32(u32::from(data_ptr) as i32), RuntimeValue::I32(data_len as i32)]; + + // Invoke the function in the runtime. + let outcome = externalities::set_and_run_with_externalities(ext, || { + context + .invoke(&mut instance, method, &args[..]) + .map_err(Error::Wasmtime) + })?; + let trap_error = reset_env_state_and_take_trap(context, None)?; + let (output_ptr, output_len) = match outcome { + ActionOutcome::Returned { values } => match values.as_slice() { + [RuntimeValue::I64(retval)] => + interpret_runtime_api_result(*retval), + _ => return Err(Error::InvalidReturn), + } + ActionOutcome::Trapped { message } => + return Err(trap_error.unwrap_or_else(|| + format!("Wasm execution trapped: {}", message).into() + )), + }; + + // Read the output data from guest memory. + let mut output = vec![0; output_len as usize]; + let memory = get_memory_mut(&mut instance)?; + read_memory_into(memory, output_ptr, &mut output)?; + Ok(output) +} + +/// The implementation is based on wasmtime_wasi::instantiate_wasi. +fn instantiate_env_module( + global_exports: Rc>>>, + compiler: Compiler, +) -> std::result::Result +{ + let isa = target_isa()?; + let pointer_type = isa.pointer_type(); + let call_conv = isa.default_call_conv(); + + let mut fn_builder_ctx = FunctionBuilderContext::new(); + let mut module = Module::new(); + let mut finished_functions = >::new(); + let mut code_memory = CodeMemory::new(); + + for function in SubstrateExternals::functions().iter() { + let sig = translate_signature( + cranelift_ir_signature(function.signature(), &call_conv), + pointer_type + ); + let sig_id = module.signatures.push(sig.clone()); + let func_id = module.functions.push(sig_id); + module + .exports + .insert(function.name().to_string(), wasmtime_environ::Export::Function(func_id)); + + let trampoline = make_trampoline( + isa.as_ref(), + &mut code_memory, + &mut fn_builder_ctx, + func_id.index() as u32, + &sig, + )?; + finished_functions.push(trampoline); + } + + code_memory.publish(); + + let imports = Imports::none(); + let data_initializers = Vec::new(); + let signatures = PrimaryMap::new(); + let env_state = EnvState::new::(code_memory, compiler); + + let result = InstanceHandle::new( + Rc::new(module), + global_exports, + finished_functions.into_boxed_slice(), + imports, + &data_initializers, + signatures.into_boxed_slice(), + None, + Box::new(env_state), + ); + result.map_err(|e| WasmError::WasmtimeSetup(SetupError::Instantiate(e))) +} + +/// Build a new TargetIsa for the host machine. +fn target_isa() -> std::result::Result, WasmError> { + let isa_builder = cranelift_native::builder() + .map_err(WasmError::MissingCompilerSupport)?; + let flag_builder = cranelift_codegen::settings::builder(); + Ok(isa_builder.finish(cranelift_codegen::settings::Flags::new(flag_builder))) +} + +fn new_compiler(strategy: CompilationStrategy) -> std::result::Result { + let isa = target_isa()?; + Ok(Compiler::new(isa, strategy)) +} + +fn clear_globals(global_exports: &mut HashMap>) { + global_exports.remove("memory"); + global_exports.remove("__heap_base"); + global_exports.remove("__indirect_function_table"); +} + +fn grow_memory(instance: &mut InstanceHandle, pages: u32) -> Result<()> { + // This is safe to wrap in an unsafe block as: + // - The result of the `lookup_immutable` call is not mutated + // - The definition pointer is returned by a lookup on a valid instance + let memory_index = unsafe { + match instance.lookup_immutable("memory") { + Some(Export::Memory { definition, vmctx: _, memory: _ }) => + instance.memory_index(&*definition), + _ => return Err(Error::InvalidMemoryReference), + } + }; + instance.memory_grow(memory_index, pages) + .map(|_| ()) + .ok_or_else(|| "requested heap_pages would exceed maximum memory size".into()) +} + +fn get_env_state(context: &mut Context) -> Result<&mut EnvState> { + let env_instance = context.get_instance("env") + .map_err(|err| format!("cannot find \"env\" module: {}", err))?; + env_instance + .host_state() + .downcast_mut::() + .ok_or_else(|| "cannot get \"env\" module host state".into()) +} + +fn reset_env_state_and_take_trap( + context: &mut Context, + executor_state: Option, +) -> Result> +{ + let env_state = get_env_state(context)?; + env_state.executor_state = executor_state; + Ok(env_state.take_trap()) +} + +fn inject_input_data( + context: &mut Context, + instance: &mut InstanceHandle, + data: &[u8], +) -> Result<(Pointer, WordSize)> { + let env_state = get_env_state(context)?; + let executor_state = env_state.executor_state + .as_mut() + .ok_or_else(|| "cannot get \"env\" module executor state")?; + + let memory = get_memory_mut(instance)?; + + let data_len = data.len() as WordSize; + let data_ptr = executor_state.heap().allocate(memory, data_len)?; + write_memory_from(memory, data_ptr, data)?; + Ok((data_ptr, data_len)) +} + +fn get_memory_mut(instance: &mut InstanceHandle) -> Result<&mut [u8]> { + match instance.lookup("memory") { + // This is safe to wrap in an unsafe block as: + // - The definition pointer is returned by a lookup on a valid instance and thus points to + // a valid memory definition + Some(Export::Memory { definition, vmctx: _, memory: _ }) => unsafe { + Ok(std::slice::from_raw_parts_mut( + (*definition).base, + (*definition).current_length, + )) + }, + _ => Err(Error::InvalidMemoryReference), + } +} + +fn get_heap_base(instance: &InstanceHandle) -> Result { + // This is safe to wrap in an unsafe block as: + // - The result of the `lookup_immutable` call is not mutated + // - The definition pointer is returned by a lookup on a valid instance + // - The defined value is checked to be an I32, which can be read safely as a u32 + unsafe { + match instance.lookup_immutable("__heap_base") { + Some(Export::Global { definition, vmctx: _, global }) + if global.ty == ir::types::I32 => + Ok(*(*definition).as_u32()), + _ => return Err(Error::HeapBaseNotFoundOrInvalid), + } + } +} + +/// Checks whether the heap_pages parameter is within the valid range and converts it to a u32. +/// Returns None if heaps_pages in not in range. +fn heap_pages_valid(heap_pages: u64, max_heap_pages: Option) + -> Option +{ + let heap_pages = u32::try_from(heap_pages).ok()?; + if let Some(max_heap_pages) = max_heap_pages { + if heap_pages > max_heap_pages { + return None; + } + } + Some(heap_pages) +} diff --git a/core/executor/src/wasmtime/trampoline.rs b/core/executor/src/wasmtime/trampoline.rs new file mode 100644 index 0000000000000000000000000000000000000000..7abc59faa5ef5c4bb908b5b0eeba044357a1618a --- /dev/null +++ b/core/executor/src/wasmtime/trampoline.rs @@ -0,0 +1,329 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! The trampoline is the dynamically generated entry point to a runtime host call. +//! +//! This code is based on and large parts are copied from wasmtime's +//! wasmtime-api/src/trampoline/func.rs. + +use cranelift_codegen::{Context, binemit, ir, isa}; +use cranelift_codegen::ir::{InstBuilder, StackSlotData, StackSlotKind, TrapCode}; +use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; +use wasmtime_jit::{CodeMemory, Compiler}; +use wasmtime_runtime::{VMContext, VMFunctionBody}; +use wasm_interface::{HostFunctions, Function, Value, ValueType}; +use std::{cmp, panic, ptr}; + +use crate::error::{Error, WasmError}; +use crate::wasmtime::function_executor::{FunctionExecutorState, FunctionExecutor}; + +const CALL_SUCCESS: u32 = 0; +const CALL_FAILED_WITH_ERROR: u32 = 1; +const CALL_WITH_BAD_HOST_STATE: u32 = 2; +const CALL_PANICKED: u32 = 3; + +/// A code to trap with that indicates a host call error. +const TRAP_USER_CODE: u16 = 0; + +/// The only Wasm types allowed in host function signatures (I32, I64, F32, F64) are all +/// represented in at most 8 bytes. +const MAX_WASM_TYPE_SIZE: usize = 8; + +/// The top-level host state of the "env" module. This state is used by the trampoline function to +/// construct a `FunctionExecutor` which can execute the host call. +pub struct EnvState { + externals: &'static [&'static dyn Function], + compiler: Compiler, + // The code memory must be kept around on the state to prevent it from being dropped. + #[allow(dead_code)] + code_memory: CodeMemory, + trap: Option, + /// The executor state stored across host calls during a single Wasm runtime call. + /// During a runtime call, this MUST be `Some`. + pub executor_state: Option, +} + +impl EnvState { + /// Construct a new `EnvState` which owns the given code memory. + pub fn new(code_memory: CodeMemory, compiler: Compiler) -> Self { + EnvState { + externals: HF::functions(), + trap: None, + compiler, + code_memory, + executor_state: None, + } + } + + /// Resets the trap error to None and returns the current value. + pub fn take_trap(&mut self) -> Option { + self.trap.take() + } +} + +/// This is called by the dynamically generated trampoline taking the function index and reference +/// to the call arguments on the stack as arguments. Returns zero on success and a non-zero value +/// on failure. +unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, func_index: u32, values_vec: *mut i64) -> u32 { + let result = panic::catch_unwind(|| { + if let Some(state) = (*vmctx).host_state().downcast_mut::() { + match stub_fn_inner( + vmctx, + state.externals, + &mut state.compiler, + state.executor_state.as_mut(), + func_index, + values_vec, + ) { + Ok(()) => CALL_SUCCESS, + Err(err) => { + state.trap = Some(err); + CALL_FAILED_WITH_ERROR + } + } + } else { + // Well, we can't even set a trap message, so we'll just exit without one. + CALL_WITH_BAD_HOST_STATE + } + }); + result.unwrap_or(CALL_PANICKED) +} + +/// Implements most of the logic in `stub_fn` but returning a `Result` instead of an integer error +/// for the sake of readability. +unsafe fn stub_fn_inner( + vmctx: *mut VMContext, + externals: &[&dyn Function], + compiler: &mut Compiler, + executor_state: Option<&mut FunctionExecutorState>, + func_index: u32, + values_vec: *mut i64, +) -> Result<(), Error> +{ + let func = externals.get(func_index as usize) + .ok_or_else(|| format!("call to undefined external function with index {}", func_index))?; + let executor_state = executor_state + .ok_or_else(|| "executor state is None during call to external function")?; + + // Build the external function context. + let mut context = FunctionExecutor::new(vmctx, compiler, executor_state)?; + + let signature = func.signature(); + + // Read the arguments from the stack. + let mut args = signature.args.iter() + .enumerate() + .map(|(i, ¶m_type)| read_value_from(values_vec.offset(i as isize), param_type)); + + // Execute and write output back to the stack. + let return_val = func.execute(&mut context, &mut args) + .map_err(|e| Error::FunctionExecution(func.name().to_string(), e))?; + if let Some(val) = return_val { + write_value_to(values_vec, val); + } + + Ok(()) +} + +/// Create a trampoline for invoking a host function. +/// +/// The trampoline is a dynamically generated entry point to a runtime host call. The function is +/// generated by manually constructing Cranelift IR and using the Cranelift compiler. The +/// trampoline embeds the function index as a constant and delegates to a stub function in Rust, +/// which takes the function index and a memory reference to the stack arguments and return value +/// slots. +/// +/// This code is of modified copy of wasmtime's wasmtime-api/src/trampoline/func.rs. +pub fn make_trampoline( + isa: &dyn isa::TargetIsa, + code_memory: &mut CodeMemory, + fn_builder_ctx: &mut FunctionBuilderContext, + func_index: u32, + signature: &ir::Signature, +) -> Result<*const VMFunctionBody, WasmError> { + // Mostly reverse copy of the similar method from wasmtime's + // wasmtime-jit/src/compiler.rs. + let pointer_type = isa.pointer_type(); + let mut stub_sig = ir::Signature::new(isa.frontend_config().default_call_conv); + + // Ensure that the first parameter of the generated function is the `VMContext` pointer. + assert_eq!( + signature.params[0], + ir::AbiParam::special(pointer_type, ir::ArgumentPurpose::VMContext) + ); + + // Add the `vmctx` parameter. + stub_sig.params.push(ir::AbiParam::special( + pointer_type, + ir::ArgumentPurpose::VMContext, + )); + + // Add the `func_index` parameter. + stub_sig.params.push(ir::AbiParam::new(ir::types::I32)); + + // Add the `values_vec` parameter. + stub_sig.params.push(ir::AbiParam::new(pointer_type)); + + // Add error/trap return. + stub_sig.returns.push(ir::AbiParam::new(ir::types::I32)); + + // Each parameter and return value gets a 64-bit (8-byte) wide slot on the stack, as that is + // large enough to fit all Wasm primitive types that can be used in host function signatures. + // The `VMContext` pointer, which is a parameter of the function signature, is excluded as it + // is passed directly to the stub function rather than being looked up on the caller stack from + // the `values_vec` pointer. + let values_vec_len = cmp::max(signature.params.len() - 1, signature.returns.len()); + let values_vec_size = (MAX_WASM_TYPE_SIZE * values_vec_len) as u32; + + let mut context = Context::new(); + context.func = + ir::Function::with_name_signature(ir::ExternalName::user(0, 0), signature.clone()); + + let ss = context.func.create_stack_slot(StackSlotData::new( + StackSlotKind::ExplicitSlot, + values_vec_size, + )); + + { + let mut builder = FunctionBuilder::new(&mut context.func, fn_builder_ctx); + let block0 = builder.create_ebb(); + + builder.append_ebb_params_for_function_params(block0); + builder.switch_to_block(block0); + builder.seal_block(block0); + + let values_vec_ptr_val = builder.ins().stack_addr(pointer_type, ss, 0); + let mflags = ir::MemFlags::trusted(); + for i in 1..signature.params.len() { + let val = builder.func.dfg.ebb_params(block0)[i]; + builder.ins().store( + mflags, + val, + values_vec_ptr_val, + ((i - 1) * MAX_WASM_TYPE_SIZE) as i32, + ); + } + + let vmctx_ptr_val = builder.func.dfg.ebb_params(block0)[0]; + let func_index_val = builder.ins().iconst(ir::types::I32, func_index as i64); + + let callee_args = vec![vmctx_ptr_val, func_index_val, values_vec_ptr_val]; + + let new_sig = builder.import_signature(stub_sig.clone()); + + let callee_value = builder + .ins() + .iconst(pointer_type, stub_fn as *const VMFunctionBody as i64); + let call = builder + .ins() + .call_indirect(new_sig, callee_value, &callee_args); + + let call_result = builder.func.dfg.inst_results(call)[0]; + builder.ins().trapnz(call_result, TrapCode::User(TRAP_USER_CODE)); + + let mflags = ir::MemFlags::trusted(); + let mut results = Vec::new(); + for (i, r) in signature.returns.iter().enumerate() { + let load = builder.ins().load( + r.value_type, + mflags, + values_vec_ptr_val, + (i * MAX_WASM_TYPE_SIZE) as i32, + ); + results.push(load); + } + builder.ins().return_(&results); + builder.finalize() + } + + let mut code_buf: Vec = Vec::new(); + let mut reloc_sink = RelocSink; + let mut trap_sink = binemit::NullTrapSink {}; + let mut stackmap_sink = binemit::NullStackmapSink {}; + context + .compile_and_emit( + isa, + &mut code_buf, + &mut reloc_sink, + &mut trap_sink, + &mut stackmap_sink, + ) + .map_err(|e| WasmError::Instantiation(format!("failed to compile trampoline: {}", e)))?; + + let func_ref = code_memory + .allocate_copy_of_byte_slice(&code_buf) + .map_err(|e| WasmError::Instantiation(format!("failed to allocate code memory: {}", e)))?; + + Ok(func_ref.as_ptr()) +} + +/// We don't expect trampoline compilation to produce any relocations, so +/// this `RelocSink` just asserts that it doesn't recieve any. +struct RelocSink; + +impl binemit::RelocSink for RelocSink { + fn reloc_ebb( + &mut self, + _offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _ebb_offset: binemit::CodeOffset, + ) { + panic!("trampoline compilation should not produce ebb relocs"); + } + fn reloc_external( + &mut self, + _offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _name: &ir::ExternalName, + _addend: binemit::Addend, + ) { + panic!("trampoline compilation should not produce external symbol relocs"); + } + fn reloc_constant( + &mut self, + _code_offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _constant_offset: ir::ConstantOffset, + ) { + panic!("trampoline compilation should not produce constant relocs"); + } + fn reloc_jt( + &mut self, + _offset: binemit::CodeOffset, + _reloc: binemit::Reloc, + _jt: ir::JumpTable, + ) { + panic!("trampoline compilation should not produce jump table relocs"); + } +} + +unsafe fn write_value_to(p: *mut i64, val: Value) { + match val { + Value::I32(i) => ptr::write(p as *mut i32, i), + Value::I64(i) => ptr::write(p as *mut i64, i), + Value::F32(u) => ptr::write(p as *mut u32, u), + Value::F64(u) => ptr::write(p as *mut u64, u), + } +} + +unsafe fn read_value_from(p: *const i64, ty: ValueType) -> Value { + match ty { + ValueType::I32 => Value::I32(ptr::read(p as *const i32)), + ValueType::I64 => Value::I64(ptr::read(p as *const i64)), + ValueType::F32 => Value::F32(ptr::read(p as *const u32)), + ValueType::F64 => Value::F64(ptr::read(p as *const u64)), + } +} diff --git a/core/executor/src/wasmtime/util.rs b/core/executor/src/wasmtime/util.rs new file mode 100644 index 0000000000000000000000000000000000000000..874ccc8c85fbe2073b3633513237e38681c48297 --- /dev/null +++ b/core/executor/src/wasmtime/util.rs @@ -0,0 +1,113 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::error::{Error, Result}; + +use cranelift_codegen::{ir, isa}; +use std::ops::Range; +use wasm_interface::{Pointer, Signature, ValueType}; + +/// Read data from a slice of memory into a destination buffer. +/// +/// Returns an error if the read would go out of the memory bounds. +pub fn read_memory_into(memory: &[u8], address: Pointer, dest: &mut [u8]) -> Result<()> { + let range = checked_range(address.into(), dest.len(), memory.len()) + .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; + dest.copy_from_slice(&memory[range]); + Ok(()) +} + +/// Write data to a slice of memory. +/// +/// Returns an error if the write would go out of the memory bounds. +pub fn write_memory_from(memory: &mut [u8], address: Pointer, data: &[u8]) -> Result<()> { + let range = checked_range(address.into(), data.len(), memory.len()) + .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; + &mut memory[range].copy_from_slice(data); + Ok(()) +} + +/// Construct a range from an offset to a data length after the offset. +/// Returns None if the end of the range would exceed some maximum offset. +pub fn checked_range(offset: usize, len: usize, max: usize) -> Option> { + let end = offset.checked_add(len)?; + if end <= max { + Some(offset..end) + } else { + None + } +} + +/// Convert a wasm_interface Signature into a cranelift_codegen Signature. +pub fn cranelift_ir_signature(signature: Signature, call_conv: &isa::CallConv) -> ir::Signature { + ir::Signature { + params: signature.args.iter() + .map(cranelift_ir_type) + .map(ir::AbiParam::new) + .collect(), + returns: signature.return_value.iter() + .map(cranelift_ir_type) + .map(ir::AbiParam::new) + .collect(), + call_conv: call_conv.clone(), + } +} + +/// Convert a wasm_interface ValueType into a cranelift_codegen Type. +pub fn cranelift_ir_type(value_type: &ValueType) -> ir::types::Type { + match value_type { + ValueType::I32 => ir::types::I32, + ValueType::I64 => ir::types::I64, + ValueType::F32 => ir::types::F32, + ValueType::F64 => ir::types::F64, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use assert_matches::assert_matches; + + #[test] + fn test_read_memory_into() { + let mut memory = [0; 20]; + let mut dest = [0; 5]; + + &mut memory[15..20].copy_from_slice(b"hello"); + + read_memory_into(&memory[..], Pointer::new(15), &mut dest[..]).unwrap(); + + // Test that out of bounds read fails. + assert_matches!( + read_memory_into(&memory[..], Pointer::new(16), &mut dest[..]), + Err(Error::Other(_)) + ) + } + + #[test] + fn test_write_memory_from() { + let mut memory = [0; 20]; + let data = b"hello"; + + write_memory_from(&mut memory[..], Pointer::new(15), data).unwrap(); + + // Test that out of bounds write fails. + assert_matches!( + write_memory_from(&mut memory[..], Pointer::new(16), data), + Err(Error::Other(_)) + ) + } +} diff --git a/core/externalities/Cargo.toml b/core/externalities/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..babb3e7f9f4a2c856d68855dca7c3df50049dd7e --- /dev/null +++ b/core/externalities/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "substrate-externalities" +version = "2.0.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +primitive-types = { version = "0.6", features = ["codec"] } +primitives-storage = { package = "substrate-primitives-storage", path = "../primitives/storage" } +rstd = { package = "sr-std", path = "../sr-std" } +environmental = { version = "1.0.2" } diff --git a/core/externalities/src/extensions.rs b/core/externalities/src/extensions.rs new file mode 100644 index 0000000000000000000000000000000000000000..a1a83cb197d4f55075abff855dd0227787a1ad8d --- /dev/null +++ b/core/externalities/src/extensions.rs @@ -0,0 +1,137 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Externalities extensions storage. +//! +//! Externalities support to register a wide variety custom extensions. The [`Extensions`] provides +//! some convenience functionality to store and retrieve these extensions. +//! +//! It is required that each extension implements the [`Extension`] trait. + +use std::{collections::HashMap, any::{Any, TypeId}, ops::DerefMut}; + +/// Marker trait for types that should be registered as [`Externalities`](crate::Externalities) extension. +/// +/// As extensions are stored as `Box`, this trait should give more confidence that the correct +/// type is registered and requested. +pub trait Extension: Send + Any { + /// Return the extension as `&mut dyn Any`. + /// + /// This is a trick to make the trait type castable into an `Any`. + fn as_mut_any(&mut self) -> &mut dyn Any; +} + +/// Macro for declaring an extension that usable with [`Extensions`]. +/// +/// The extension will be an unit wrapper struct that implements [`Extension`], `Deref` and +/// `DerefMut`. The wrapped type is given by the user. +/// +/// # Example +/// ``` +/// # use substrate_externalities::decl_extension; +/// decl_extension! { +/// /// Some test extension +/// struct TestExt(String); +/// } +/// ``` +#[macro_export] +macro_rules! decl_extension { + ( + $( #[ $attr:meta ] )* + $vis:vis struct $ext_name:ident ($inner:ty); + ) => { + $( #[ $attr ] )* + $vis struct $ext_name (pub $inner); + + impl $crate::Extension for $ext_name { + fn as_mut_any(&mut self) -> &mut dyn std::any::Any { + self + } + } + + impl std::ops::Deref for $ext_name { + type Target = $inner; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl std::ops::DerefMut for $ext_name { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + } +} + +/// Something that provides access to the [`Extensions`] store. +/// +/// This is a super trait of the [`Externalities`](crate::Externalities). +pub trait ExtensionStore { + /// Tries to find a registered extension by the given `type_id` and returns it as a `&mut dyn Any`. + /// + /// It is advised to use [`ExternalitiesExt::extension`](crate::ExternalitiesExt::extension) + /// instead of this function to get type system support and automatic type downcasting. + fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any>; +} + +/// Stores extensions that should be made available through the externalities. +#[derive(Default)] +pub struct Extensions { + extensions: HashMap>, +} + +impl Extensions { + /// Create new instance of `Self`. + pub fn new() -> Self { + Self::default() + } + + /// Register the given extension. + pub fn register(&mut self, ext: E) { + self.extensions.insert(ext.type_id(), Box::new(ext)); + } + + /// Return a mutable reference to the requested extension. + pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> { + self.extensions.get_mut(&ext_type_id).map(DerefMut::deref_mut).map(Extension::as_mut_any) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + decl_extension! { + struct DummyExt(u32); + } + decl_extension! { + struct DummyExt2(u32); + } + + #[test] + fn register_and_retrieve_extension() { + let mut exts = Extensions::new(); + exts.register(DummyExt(1)); + exts.register(DummyExt2(2)); + + let ext = exts.get_mut(TypeId::of::()).expect("Extension is registered"); + let ext_ty = ext.downcast_mut::().expect("Downcasting works"); + + assert_eq!(ext_ty.0, 1); + } +} diff --git a/core/externalities/src/lib.rs b/core/externalities/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..ecd5f7a7a751da68d9b069ab749c2c96edec7ae0 --- /dev/null +++ b/core/externalities/src/lib.rs @@ -0,0 +1,139 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate externalities abstraction +//! +//! The externalities mainly provide access to storage and to registered extensions. Extensions +//! are for example the keystore or the offchain externalities. These externalities are used to +//! access the node from the runtime via the runtime interfaces. +//! +//! This crate exposes the main [`Externalities`] trait. + +use primitive_types::H256; + +use std::any::{Any, TypeId}; + +use primitives_storage::ChildStorageKey; + +pub use scope_limited::{set_and_run_with_externalities, with_externalities}; +pub use extensions::{Extension, Extensions, ExtensionStore}; + +mod extensions; +mod scope_limited; + +/// The Substrate externalities. +/// +/// Provides access to the storage and to other registered extensions. +pub trait Externalities: ExtensionStore { + /// Read runtime storage. + fn storage(&self, key: &[u8]) -> Option>; + + /// Get storage value hash. This may be optimized for large values. + fn storage_hash(&self, key: &[u8]) -> Option; + + /// Get child storage value hash. This may be optimized for large values. + fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option; + + /// Read original runtime storage, ignoring any overlayed changes. + fn original_storage(&self, key: &[u8]) -> Option>; + + /// Read original runtime child storage, ignoring any overlayed changes. + fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; + + /// Get original storage value hash, ignoring any overlayed changes. + /// This may be optimized for large values. + fn original_storage_hash(&self, key: &[u8]) -> Option; + + /// Get original child storage value hash, ignoring any overlayed changes. + /// This may be optimized for large values. + fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option; + + /// Read child runtime storage. + fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; + + /// Set storage entry `key` of current contract being called (effective immediately). + fn set_storage(&mut self, key: Vec, value: Vec) { + self.place_storage(key, Some(value)); + } + + /// Set child storage entry `key` of current contract being called (effective immediately). + fn set_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Vec) { + self.place_child_storage(storage_key, key, Some(value)) + } + + /// Clear a storage entry (`key`) of current contract being called (effective immediately). + fn clear_storage(&mut self, key: &[u8]) { + self.place_storage(key.to_vec(), None); + } + + /// Clear a child storage entry (`key`) of current contract being called (effective immediately). + fn clear_child_storage(&mut self, storage_key: ChildStorageKey, key: &[u8]) { + self.place_child_storage(storage_key, key.to_vec(), None) + } + + /// Whether a storage entry exists. + fn exists_storage(&self, key: &[u8]) -> bool { + self.storage(key).is_some() + } + + /// Whether a child storage entry exists. + fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { + self.child_storage(storage_key, key).is_some() + } + + /// Clear an entire child storage. + fn kill_child_storage(&mut self, storage_key: ChildStorageKey); + + /// Clear storage entries which keys are start with the given prefix. + fn clear_prefix(&mut self, prefix: &[u8]); + + /// Clear child storage entries which keys are start with the given prefix. + fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]); + + /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). + fn place_storage(&mut self, key: Vec, value: Option>); + + /// Set or clear a child storage entry. Return whether the operation succeeds. + fn place_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Option>); + + /// Get the identity of the chain. + fn chain_id(&self) -> u64; + + /// Get the trie root of the current storage map. This will also update all child storage keys + /// in the top-level storage map. + fn storage_root(&mut self) -> H256; + + /// Get the trie root of a child storage map. This will also update the value of the child + /// storage keys in the top-level storage map. + /// If the storage root equals the default hash as defined by the trie, the key in the top-level + /// storage map will be removed. + fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec; + + /// Get the change trie root of the current storage overlay at a block with given parent. + fn storage_changes_root(&mut self, parent: H256) -> Result, ()>; +} + +/// Extension for the [`Externalities`] trait. +pub trait ExternalitiesExt { + /// Tries to find a registered extension and returns a mutable reference. + fn extension(&mut self) -> Option<&mut T>; +} + +impl ExternalitiesExt for T { + fn extension(&mut self) -> Option<&mut A> { + self.extension_by_type_id(TypeId::of::()).and_then(Any::downcast_mut) + } +} diff --git a/core/externalities/src/scope_limited.rs b/core/externalities/src/scope_limited.rs new file mode 100644 index 0000000000000000000000000000000000000000..ae185449be2b0cf2573872787ba4ce3f916fa28b --- /dev/null +++ b/core/externalities/src/scope_limited.rs @@ -0,0 +1,37 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Stores the externalities in an `environmental` value to make it scope limited available. + +use crate::Externalities; + +environmental::environmental!(ext: trait Externalities); + +/// Set the given externalities while executing the given closure. To get access to the externalities +/// while executing the given closure [`with_externalities`] grants access to them. The externalities +/// are only set for the same thread this function was called from. +pub fn set_and_run_with_externalities(ext: &mut dyn Externalities, f: F) -> R + where F: FnOnce() -> R +{ + ext::using(ext, f) +} + +/// Execute the given closure with the currently set externalities. +/// +/// Returns `None` if no externalities are set or `Some(_)` with the result of the closure. +pub fn with_externalities R, R>(f: F) -> Option { + ext::with(f) +} diff --git a/core/finality-grandpa/Cargo.toml b/core/finality-grandpa/Cargo.toml index 22237c5a0b5a0f886fe2853604270627b272cf79..a4c6a0278a44504bc184a4d40af6779b86664d40 100644 --- a/core/finality-grandpa/Cargo.toml +++ b/core/finality-grandpa/Cargo.toml @@ -6,24 +6,24 @@ edition = "2018" [dependencies] fork-tree = { path = "../../core/utils/fork-tree" } -futures = "0.1" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.17", features = ["compat"] } -log = "0.4" +futures = "0.1.29" +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } +log = "0.4.8" parking_lot = "0.9.0" -tokio-executor = "0.1.7" +tokio-executor = "0.1.8" tokio-timer = "0.2.11" -rand = "0.6" +rand = "0.7.2" codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } sr-primitives = { path = "../sr-primitives" } consensus_common = { package = "substrate-consensus-common", path = "../consensus/common" } primitives = { package = "substrate-primitives", path = "../primitives" } substrate-telemetry = { path = "../telemetry" } keystore = { package = "substrate-keystore", path = "../keystore" } -serde_json = "1.0" +serde_json = "1.0.41" client = { package = "substrate-client", path = "../client" } +header-metadata = { package = "substrate-header-metadata", path = "../client/header-metadata" } inherents = { package = "substrate-inherents", path = "../../core/inherents" } network = { package = "substrate-network", path = "../network" } -service = { package = "substrate-service", path = "../service", optional = true } srml-finality-tracker = { path = "../../srml/finality-tracker" } fg_primitives = { package = "substrate-finality-grandpa-primitives", path = "primitives" } grandpa = { package = "finality-grandpa", version = "0.9.0", features = ["derive-codec"] } @@ -34,10 +34,7 @@ network = { package = "substrate-network", path = "../network", features = ["tes keyring = { package = "substrate-keyring", path = "../keyring" } test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client"} babe_primitives = { package = "substrate-consensus-babe-primitives", path = "../consensus/babe/primitives" } -env_logger = "0.6" -tokio = "0.1.17" -tempfile = "3.1" - -[features] -default = ["service-integration"] -service-integration = ["service"] +state_machine = { package = "substrate-state-machine", path = "../state-machine" } +env_logger = "0.7.0" +tokio = "0.1.22" +tempfile = "3.1.0" diff --git a/core/finality-grandpa/primitives/Cargo.toml b/core/finality-grandpa/primitives/Cargo.toml index ecbaf2e1ecc70b8bce006fc710137ae915c00e8f..02439d4150d81016d6bd37a6253f17bc73ba7f4d 100644 --- a/core/finality-grandpa/primitives/Cargo.toml +++ b/core/finality-grandpa/primitives/Cargo.toml @@ -10,7 +10,7 @@ app-crypto = { package = "substrate-application-crypto", path = "../../applicati codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } sr-primitives = { path = "../../sr-primitives", default-features = false } rstd = { package = "sr-std", path = "../../sr-std", default-features = false } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } [features] default = ["std"] diff --git a/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs index b92444e26295ce20415e7db64eaf638bdbd7fc2d..27139bbeeffa8366e1313f1b40ff8e0cfaafae7d 100644 --- a/core/finality-grandpa/primitives/src/lib.rs +++ b/core/finality-grandpa/primitives/src/lib.rs @@ -24,7 +24,7 @@ extern crate alloc; #[cfg(feature = "std")] use serde::Serialize; use codec::{Encode, Decode, Codec}; -use sr_primitives::{ConsensusEngineId, traits::{DigestFor, NumberFor}}; +use sr_primitives::{ConsensusEngineId, RuntimeDebug}; use client::decl_runtime_apis; use rstd::vec::Vec; @@ -52,9 +52,15 @@ pub type AuthorityWeight = u64; /// The index of an authority. pub type AuthorityIndex = u64; +/// The monotonic identifier of a GRANDPA set of authorities. +pub type SetId = u64; + +/// The round indicator. +pub type RoundNumber = u64; + /// A scheduled change of authority set. -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[derive(Clone, Eq, PartialEq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Serialize))] +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] pub struct ScheduledChange { /// The new authorities after the change, along with their respective weights. pub next_authorities: Vec<(AuthorityId, AuthorityWeight)>, @@ -63,13 +69,14 @@ pub struct ScheduledChange { } /// An consensus log item for GRANDPA. -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -#[derive(Decode, Encode, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize))] +#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)] pub enum ConsensusLog { /// Schedule an authority set change. /// - /// Precedence towards earlier or later digest items can be given - /// based on the rules of the chain. + /// The earliest digest of this type in a single block will be respected, + /// provided that there is no `ForcedChange` digest. If there is, then the + /// `ForcedChange` will take precedence. /// /// No change should be scheduled if one is already and the delay has not /// passed completely. @@ -84,8 +91,8 @@ pub enum ConsensusLog { /// Forced changes are applied after a delay of _imported_ blocks, /// while pending changes are applied after a delay of _finalized_ blocks. /// - /// Precedence towards earlier or later digest items can be given - /// based on the rules of the chain. + /// The earliest digest of this type in a single block will be respected, + /// with others ignored. /// /// No change should be scheduled if one is already and the delay has not /// passed completely. @@ -159,43 +166,6 @@ decl_runtime_apis! { /// The consensus protocol will coordinate the handoff externally. #[api_version(2)] pub trait GrandpaApi { - /// Check a digest for pending changes. - /// Return `None` if there are no pending changes. - /// - /// Precedence towards earlier or later digest items can be given - /// based on the rules of the chain. - /// - /// No change should be scheduled if one is already and the delay has not - /// passed completely. - /// - /// This should be a pure function: i.e. as long as the runtime can interpret - /// the digest type it should return the same result regardless of the current - /// state. - fn grandpa_pending_change(digest: &DigestFor) - -> Option>>; - - /// Check a digest for forced changes. - /// Return `None` if there are no forced changes. Otherwise, return a - /// tuple containing the pending change and the median last finalized - /// block number at the time the change was signaled. - /// - /// Added in version 2. - /// - /// Forced changes are applied after a delay of _imported_ blocks, - /// while pending changes are applied after a delay of _finalized_ blocks. - /// - /// Precedence towards earlier or later digest items can be given - /// based on the rules of the chain. - /// - /// No change should be scheduled if one is already and the delay has not - /// passed completely. - /// - /// This should be a pure function: i.e. as long as the runtime can interpret - /// the digest type it should return the same result regardless of the current - /// state. - fn grandpa_forced_change(digest: &DigestFor) - -> Option<(NumberFor, ScheduledChange>)>; - /// Get the current GRANDPA authorities and weights. This should not change except /// for when changes are scheduled and the corresponding delay has passed. /// diff --git a/core/finality-grandpa/src/aux_schema.rs b/core/finality-grandpa/src/aux_schema.rs index 78c1741d519037fdd6adcde19a1f4be883f3118d..a2b05a0cd60e1f4b237b45549b1efd1cf56ccc95 100644 --- a/core/finality-grandpa/src/aux_schema.rs +++ b/core/finality-grandpa/src/aux_schema.rs @@ -25,8 +25,7 @@ use fork_tree::ForkTree; use grandpa::round::State as RoundState; use sr_primitives::traits::{Block as BlockT, NumberFor}; use log::{info, warn}; -use substrate_telemetry::{telemetry, CONSENSUS_INFO}; -use fg_primitives::AuthorityId; +use fg_primitives::{AuthorityId, AuthorityWeight, SetId, RoundNumber}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; @@ -47,16 +46,16 @@ const CURRENT_VERSION: u32 = 2; #[cfg_attr(test, derive(PartialEq))] pub enum V1VoterSetState { /// The voter set state, currently paused. - Paused(u64, RoundState), + Paused(RoundNumber, RoundState), /// The voter set state, currently live. - Live(u64, RoundState), + Live(RoundNumber, RoundState), } -type V0VoterSetState = (u64, RoundState); +type V0VoterSetState = (RoundNumber, RoundState); #[derive(Debug, Clone, Encode, Decode, PartialEq)] struct V0PendingChange { - next_authorities: Vec<(AuthorityId, u64)>, + next_authorities: Vec<(AuthorityId, AuthorityWeight)>, delay: N, canon_height: N, canon_hash: H, @@ -64,8 +63,8 @@ struct V0PendingChange { #[derive(Debug, Clone, Encode, Decode, PartialEq)] struct V0AuthoritySet { - current_authorities: Vec<(AuthorityId, u64)>, - set_id: u64, + current_authorities: Vec<(AuthorityId, AuthorityWeight)>, + set_id: SetId, pending_changes: Vec>, } @@ -267,7 +266,7 @@ pub(crate) fn load_persistent( -> ClientResult> where B: AuxStore, - G: FnOnce() -> ClientResult>, + G: FnOnce() -> ClientResult>, { let version: Option = load_decode(backend, VERSION_KEY)?; let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)? @@ -376,17 +375,6 @@ pub(crate) fn update_authority_set( let encoded_set = set.encode(); if let Some(new_set) = new_set { - telemetry!(CONSENSUS_INFO; "afg.authority_set"; - "hash" => ?new_set.canon_hash, - "number" => ?new_set.canon_number, - "authority_set_id" => ?new_set.set_id, - "authorities" => { - let authorities: Vec = - new_set.authorities.iter().map(|(id, _)| format!("{}", id)).collect(); - format!("{:?}", authorities) - } - ); - // we also overwrite the "last completed round" entry with a blank slate // because from the perspective of the finality gadget, the chain has // reset. @@ -448,7 +436,7 @@ mod test { let authorities = vec![(AuthorityId::default(), 100)]; let set_id = 3; - let round_number: u64 = 42; + let round_number: RoundNumber = 42; let round_state = RoundState:: { prevote_ghost: Some((H256::random(), 32)), finalized: None, @@ -536,7 +524,7 @@ mod test { let authorities = vec![(AuthorityId::default(), 100)]; let set_id = 3; - let round_number: u64 = 42; + let round_number: RoundNumber = 42; let round_state = RoundState:: { prevote_ghost: Some((H256::random(), 32)), finalized: None, diff --git a/core/finality-grandpa/src/communication/gossip.rs b/core/finality-grandpa/src/communication/gossip.rs index 20a629b6ae378142db98edc4f38a71d17775974c..efcd1d48c67f795c3f72dcbf0fabca7d42ebcf07 100644 --- a/core/finality-grandpa/src/communication/gossip.rs +++ b/core/finality-grandpa/src/communication/gossip.rs @@ -132,7 +132,7 @@ struct View { impl Default for View { fn default() -> Self { View { - round: Round(0), + round: Round(1), set_id: SetId(0), last_commit: None, } @@ -144,7 +144,7 @@ impl View { fn update_set(&mut self, set_id: SetId) { if set_id != self.set_id { self.set_id = set_id; - self.round = Round(0); + self.round = Round(1); } } @@ -183,7 +183,13 @@ impl View { const KEEP_RECENT_ROUNDS: usize = 3; -/// Tracks topics we keep messages for. +/// Tracks gossip topics that we are keeping messages for. We keep topics of: +/// +/// - the last `KEEP_RECENT_ROUNDS` complete GRANDPA rounds, +/// +/// - the topic for the current and next round, +/// +/// - and a global topic for commit and catch-up messages. struct KeepTopics { current_set: SetId, rounds: VecDeque<(Round, SetId)>, @@ -194,21 +200,30 @@ impl KeepTopics { fn new() -> Self { KeepTopics { current_set: SetId(0), - rounds: VecDeque::with_capacity(KEEP_RECENT_ROUNDS + 1), + rounds: VecDeque::with_capacity(KEEP_RECENT_ROUNDS + 2), reverse_map: HashMap::new(), } } fn push(&mut self, round: Round, set_id: SetId) { self.current_set = std::cmp::max(self.current_set, set_id); - self.rounds.push_back((round, set_id)); - // the 1 is for the current round. - while self.rounds.len() > KEEP_RECENT_ROUNDS + 1 { + // under normal operation the given round is already tracked (since we + // track one round ahead). if we skip rounds (with a catch up) the given + // round topic might not be tracked yet. + if !self.rounds.contains(&(round, set_id)) { + self.rounds.push_back((round, set_id)); + } + + // we also accept messages for the next round + self.rounds.push_back((Round(round.0.saturating_add(1)), set_id)); + + // the 2 is for the current and next round. + while self.rounds.len() > KEEP_RECENT_ROUNDS + 2 { let _ = self.rounds.pop_front(); } - let mut map = HashMap::with_capacity(KEEP_RECENT_ROUNDS + 2); + let mut map = HashMap::with_capacity(KEEP_RECENT_ROUNDS + 3); map.insert(super::global_topic::(self.current_set.0), (None, self.current_set)); for &(round, set) in &self.rounds { @@ -247,7 +262,7 @@ fn neighbor_topics(view: &View>) -> Vec { #[derive(Debug, Encode, Decode)] pub(super) enum GossipMessage { /// Grandpa message with round and set info. - VoteOrPrecommit(VoteOrPrecommitMessage), + Vote(VoteMessage), /// Grandpa commit message with round and set info. Commit(FullCommitMessage), /// A neighbor packet. Not repropagated. @@ -264,9 +279,9 @@ impl From>> for GossipMessage { +pub(super) struct VoteMessage { /// The round this message is from. pub(super) round: Round, /// The voter set ID this message is from. @@ -386,12 +401,14 @@ impl Misbehavior { struct PeerInfo { view: View, + roles: Roles, } impl PeerInfo { - fn new() -> Self { + fn new(roles: Roles) -> Self { PeerInfo { view: View::default(), + roles, } } } @@ -408,8 +425,8 @@ impl Default for Peers { } impl Peers { - fn new_peer(&mut self, who: PeerId) { - self.inner.insert(who, PeerInfo::new()); + fn new_peer(&mut self, who: PeerId, roles: Roles) { + self.inner.insert(who, PeerInfo::new(roles)); } fn peer_disconnected(&mut self, who: &PeerId) { @@ -495,6 +512,40 @@ enum PendingCatchUp { }, } +/// Configuration for the round catch-up mechanism. +enum CatchUpConfig { + /// Catch requests are enabled, our node will issue them whenever it sees a + /// neighbor packet for a round further than `CATCH_UP_THRESHOLD`. If + /// `only_from_authorities` is set, the node will only send catch-up + /// requests to other authorities it is connected to. This is useful if the + /// GRANDPA observer protocol is live on the network, in which case full + /// nodes (non-authorities) don't have the necessary round data to answer + /// catch-up requests. + Enabled { only_from_authorities: bool }, + /// Catch-up requests are disabled, our node will never issue them. This is + /// useful for the GRANDPA observer mode, where we are only interested in + /// commit messages and don't need to follow the full round protocol. + Disabled, +} + +impl CatchUpConfig { + fn enabled(only_from_authorities: bool) -> CatchUpConfig { + CatchUpConfig::Enabled { only_from_authorities } + } + + fn disabled() -> CatchUpConfig { + CatchUpConfig::Disabled + } + + fn request_allowed(&self, peer: &PeerInfo) -> bool { + match self { + CatchUpConfig::Disabled => false, + CatchUpConfig::Enabled { only_from_authorities, .. } => + !only_from_authorities || peer.roles.is_authority(), + } + } +} + struct Inner { local_view: Option>>, peers: Peers>, @@ -503,12 +554,30 @@ struct Inner { config: crate::Config, next_rebroadcast: Instant, pending_catch_up: PendingCatchUp, + catch_up_config: CatchUpConfig, } type MaybeMessage = Option<(Vec, NeighborPacket>)>; impl Inner { fn new(config: crate::Config) -> Self { + let catch_up_config = if config.observer_enabled { + if config.is_authority { + // since the observer protocol is enabled, we will only issue + // catch-up requests if we are an authority (and only to other + // authorities). + CatchUpConfig::enabled(true) + } else { + // otherwise, we are running the observer protocol and don't + // care about catch-up requests. + CatchUpConfig::disabled() + } + } else { + // if the observer protocol isn't enabled, then any full node should + // be able to answer catch-up requests. + CatchUpConfig::enabled(false) + }; + Inner { local_view: None, peers: Peers::default(), @@ -516,6 +585,7 @@ impl Inner { next_rebroadcast: Instant::now() + REBROADCAST_AFTER, authorities: Vec::new(), pending_catch_up: PendingCatchUp::None, + catch_up_config, config, } } @@ -550,7 +620,7 @@ impl Inner { { let local_view = match self.local_view { ref mut x @ None => x.get_or_insert(View { - round: Round(0), + round: Round(1), set_id, last_commit: None, }), @@ -562,7 +632,7 @@ impl Inner { }; local_view.update_set(set_id); - self.live_topics.push(Round(0), set_id); + self.live_topics.push(Round(1), set_id); self.authorities = authorities; } self.multicast_neighbor_packet() @@ -599,7 +669,7 @@ impl Inner { cost::PAST_REJECTION } - fn validate_round_message(&self, who: &PeerId, full: &VoteOrPrecommitMessage) + fn validate_round_message(&self, who: &PeerId, full: &VoteMessage) -> Action { match self.consider_vote(full.round, full.set_id) { @@ -729,7 +799,9 @@ impl Inner { // race where the peer sent us the request before it observed that // we had transitioned to a new set. In this case we charge a lower // cost. - if local_view.round.0.saturating_sub(CATCH_UP_THRESHOLD) == 0 { + if request.set_id.0.saturating_add(1) == local_view.set_id.0 && + local_view.round.0.saturating_sub(CATCH_UP_THRESHOLD) == 0 + { return (None, Action::Discard(cost::HONEST_OUT_OF_SCOPE_CATCH_UP)); } @@ -807,9 +879,12 @@ impl Inner { // if the peer is on the same set and ahead of us by a margin bigger // than `CATCH_UP_THRESHOLD` then we should ask it for a catch up - // message. + // message. we only send catch-up requests to authorities, observers + // won't be able to reply since they don't follow the full GRANDPA + // protocol and therefore might not have the vote data available. if let (Some(peer), Some(local_view)) = (self.peers.peer(who), &self.local_view) { - if peer.view.set_id == local_view.set_id && + if self.catch_up_config.request_allowed(&peer) && + peer.view.set_id == local_view.set_id && peer.view.round.0.saturating_sub(CATCH_UP_THRESHOLD) > local_view.round.0 { // send catch up request if allowed @@ -915,10 +990,13 @@ pub(super) struct GossipValidator { } impl GossipValidator { - /// Create a new gossip-validator. This initialized the current set to 0. - pub(super) fn new(config: crate::Config, set_state: environment::SharedVoterSetState) - -> (GossipValidator, ReportStream) - { + /// Create a new gossip-validator. The current set is initialized to 0. If + /// `catch_up_enabled` is set to false then the validator will not issue any + /// catch up requests (useful e.g. when running just the GRANDPA observer). + pub(super) fn new( + config: crate::Config, + set_state: environment::SharedVoterSetState, + ) -> (GossipValidator, ReportStream) { let (tx, rx) = mpsc::unbounded(); let val = GossipValidator { inner: parking_lot::RwLock::new(Inner::new(config)), @@ -977,7 +1055,7 @@ impl GossipValidator { let action = { match GossipMessage::::decode(&mut data) { - Ok(GossipMessage::VoteOrPrecommit(ref message)) + Ok(GossipMessage::Vote(ref message)) => self.inner.write().validate_round_message(who, message), Ok(GossipMessage::Commit(ref message)) => self.inner.write().validate_commit_message(who, message), Ok(GossipMessage::Neighbor(update)) => { @@ -1021,10 +1099,10 @@ impl GossipValidator { } impl network_gossip::Validator for GossipValidator { - fn new_peer(&self, context: &mut dyn ValidatorContext, who: &PeerId, _roles: Roles) { + fn new_peer(&self, context: &mut dyn ValidatorContext, who: &PeerId, roles: Roles) { let packet = { let mut inner = self.inner.write(); - inner.peers.new_peer(who.clone()); + inner.peers.new_peer(who.clone(), roles); inner.local_view.as_ref().map(|v| { NeighborPacket { @@ -1137,7 +1215,7 @@ impl network_gossip::Validator for GossipValidator Ok(GossipMessage::Neighbor(_)) => false, Ok(GossipMessage::CatchUpRequest(_)) => false, Ok(GossipMessage::CatchUp(_)) => false, - Ok(GossipMessage::VoteOrPrecommit(_)) => false, // should not be the case. + Ok(GossipMessage::Vote(_)) => false, // should not be the case. } }) } @@ -1242,6 +1320,8 @@ mod tests { justification_period: 256, keystore: None, name: None, + is_authority: true, + observer_enabled: true, } } @@ -1312,7 +1392,7 @@ mod tests { assert!(res.unwrap().is_none()); // connect & disconnect. - peers.new_peer(id.clone()); + peers.new_peer(id.clone(), Roles::AUTHORITY); peers.peer_disconnected(&id); let res = peers.update_peer_state(&id, update.clone()); @@ -1348,7 +1428,7 @@ mod tests { let mut peers = Peers::default(); let id = PeerId::random(); - peers.new_peer(id.clone()); + peers.new_peer(id.clone(), Roles::AUTHORITY); let mut check_update = move |update: NeighborPacket<_>| { let view = peers.update_peer_state(&id, update.clone()).unwrap().unwrap(); @@ -1368,7 +1448,7 @@ mod tests { let mut peers = Peers::default(); let id = PeerId::random(); - peers.new_peer(id.clone()); + peers.new_peer(id.clone(), Roles::AUTHORITY); peers.update_peer_state(&id, NeighborPacket { round: Round(10), @@ -1447,11 +1527,11 @@ mod tests { let peer = PeerId::random(); val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); - val.note_round(Round(0), |_, _| {}); + val.note_round(Round(1), |_, _| {}); let inner = val.inner.read(); - let unknown_voter = inner.validate_round_message(&peer, &VoteOrPrecommitMessage { - round: Round(0), + let unknown_voter = inner.validate_round_message(&peer, &VoteMessage { + round: Round(1), set_id: SetId(set_id), message: SignedMessage:: { message: grandpa::Message::Prevote(grandpa::Prevote { @@ -1463,8 +1543,8 @@ mod tests { } }); - let bad_sig = inner.validate_round_message(&peer, &VoteOrPrecommitMessage { - round: Round(0), + let bad_sig = inner.validate_round_message(&peer, &VoteMessage { + round: Round(1), set_id: SetId(set_id), message: SignedMessage:: { message: grandpa::Message::Prevote(grandpa::Prevote { @@ -1492,7 +1572,7 @@ mod tests { let peer = PeerId::random(); val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); - val.note_round(Round(0), |_, _| {}); + val.note_round(Round(1), |_, _| {}); let validate_catch_up = || { let mut inner = val.inner.write(); @@ -1528,19 +1608,19 @@ mod tests { #[test] fn unanswerable_catch_up_requests_discarded() { - // create voter set state with round 1 completed + // create voter set state with round 2 completed let set_state: SharedVoterSetState = { let mut completed_rounds = voter_set_state().read().completed_rounds(); completed_rounds.push(environment::CompletedRound { - number: 1, + number: 2, state: grandpa::round::State::genesis(Default::default()), base: Default::default(), votes: Default::default(), }); let mut current_rounds = environment::CurrentRounds::new(); - current_rounds.insert(2, environment::HasVoted::No); + current_rounds.insert(3, environment::HasVoted::No); let set_state = environment::VoterSetState::::Live { completed_rounds, @@ -1560,12 +1640,12 @@ mod tests { let peer = PeerId::random(); val.note_set(SetId(set_id), vec![auth.clone()], |_, _| {}); - val.note_round(Round(2), |_, _| {}); + val.note_round(Round(3), |_, _| {}); // add the peer making the request to the validator, // otherwise it is discarded let mut inner = val.inner.write(); - inner.peers.new_peer(peer.clone()); + inner.peers.new_peer(peer.clone(), Roles::AUTHORITY); let res = inner.handle_catch_up_request( &peer, @@ -1576,7 +1656,7 @@ mod tests { &set_state, ); - // we're at round 2, a catch up request for round 10 is out of scope + // we're at round 3, a catch up request for round 10 is out of scope assert!(res.0.is_none()); assert_eq!(res.1, Action::Discard(cost::OUT_OF_SCOPE_MESSAGE)); @@ -1584,20 +1664,331 @@ mod tests { &peer, CatchUpRequestMessage { set_id: SetId(set_id), - round: Round(1), + round: Round(2), }, &set_state, ); - // a catch up request for round 1 should be answered successfully + // a catch up request for round 2 should be answered successfully match res.0.unwrap() { GossipMessage::CatchUp(catch_up) => { assert_eq!(catch_up.set_id, SetId(set_id)); - assert_eq!(catch_up.message.round_number, 1); + assert_eq!(catch_up.message.round_number, 2); assert_eq!(res.1, Action::Discard(cost::CATCH_UP_REPLY)); }, _ => panic!("expected catch up message"), }; } + + #[test] + fn detects_honest_out_of_scope_catch_requests() { + let set_state = voter_set_state(); + let (val, _) = GossipValidator::::new( + config(), + set_state.clone(), + ); + + // the validator starts at set id 2 + val.note_set(SetId(2), Vec::new(), |_, _| {}); + + // add the peer making the request to the validator, + // otherwise it is discarded + let peer = PeerId::random(); + val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); + + let send_request = |set_id, round| { + let mut inner = val.inner.write(); + inner.handle_catch_up_request( + &peer, + CatchUpRequestMessage { + set_id: SetId(set_id), + round: Round(round), + }, + &set_state, + ) + }; + + let assert_res = |res: (Option<_>, Action<_>), honest| { + assert!(res.0.is_none()); + assert_eq!( + res.1, + if honest { + Action::Discard(cost::HONEST_OUT_OF_SCOPE_CATCH_UP) + } else { + Action::Discard(Misbehavior::OutOfScopeMessage.cost()) + }, + ); + }; + + // the validator is at set id 2 and round 0. requests for set id 1 + // should not be answered but they should be considered an honest + // mistake + assert_res( + send_request(1, 1), + true, + ); + + assert_res( + send_request(1, 10), + true, + ); + + // requests for set id 0 should be considered out of scope + assert_res( + send_request(0, 1), + false, + ); + + assert_res( + send_request(0, 10), + false, + ); + + // after the validator progresses further than CATCH_UP_THRESHOLD in set + // id 2, any request for set id 1 should no longer be considered an + // honest mistake. + val.note_round(Round(3), |_, _| {}); + + assert_res( + send_request(1, 1), + false, + ); + + assert_res( + send_request(1, 2), + false, + ); + } + + #[test] + fn issues_catch_up_request_on_neighbor_packet_import() { + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peer making the request to the validator, + // otherwise it is discarded. + let peer = PeerId::random(); + val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); + + let import_neighbor_message = |set_id, round| { + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer, + NeighborPacket { + round: Round(round), + set_id: SetId(set_id), + commit_finalized_height: 42, + }, + ); + + catch_up_request + }; + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request for the previous round. + match import_neighbor_message(1, 42) { + Some(GossipMessage::CatchUpRequest(request)) => { + assert_eq!(request.set_id, SetId(1)); + assert_eq!(request.round, Round(41)); + }, + _ => panic!("expected catch up message"), + } + + // we note that we're at round 41. + val.note_round(Round(41), |_, _| {}); + + // if we import a neighbor message within CATCH_UP_THRESHOLD then we + // won't request a catch up. + match import_neighbor_message(1, 42) { + None => {}, + _ => panic!("expected no catch up message"), + } + + // or if the peer is on a lower round. + match import_neighbor_message(1, 40) { + None => {}, + _ => panic!("expected no catch up message"), + } + + // we also don't request a catch up if the peer is in a different set. + match import_neighbor_message(2, 42) { + None => {}, + _ => panic!("expected no catch up message"), + } + } + + #[test] + fn doesnt_send_catch_up_requests_when_disabled() { + // we create a gossip validator with catch up requests disabled. + let config = { + let mut c = config(); + + // if the observer protocol is enabled and we are not an authority, + // then we don't issue any catch-up requests. + c.is_authority = false; + c.observer_enabled = true; + + c + }; + + let (val, _) = GossipValidator::::new( + config, + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peer making the request to the validator, + // otherwise it is discarded. + let peer = PeerId::random(); + val.inner.write().peers.new_peer(peer.clone(), Roles::AUTHORITY); + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request but since they're disabled + // we should get `None`. + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer, + NeighborPacket { + round: Round(42), + set_id: SetId(1), + commit_finalized_height: 50, + }, + ); + + match catch_up_request { + None => {}, + _ => panic!("expected no catch up message"), + } + } + + #[test] + fn doesnt_send_catch_up_requests_to_non_authorities_when_observer_enabled() { + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peers making the requests to the validator, + // otherwise it is discarded. + let peer_authority = PeerId::random(); + let peer_full = PeerId::random(); + + val.inner.write().peers.new_peer(peer_authority.clone(), Roles::AUTHORITY); + val.inner.write().peers.new_peer(peer_full.clone(), Roles::FULL); + + let import_neighbor_message = |peer| { + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer, + NeighborPacket { + round: Round(42), + set_id: SetId(1), + commit_finalized_height: 50, + }, + ); + + catch_up_request + }; + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request but since the node is not an + // authority we should get `None`. + if import_neighbor_message(peer_full).is_some() { + panic!("expected no catch up message"); + } + + // importing the same neighbor message from a peer who is an authority + // should lead to a catch up request. + match import_neighbor_message(peer_authority) { + Some(GossipMessage::CatchUpRequest(request)) => { + assert_eq!(request.set_id, SetId(1)); + assert_eq!(request.round, Round(41)); + }, + _ => panic!("expected catch up message"), + } + } + + #[test] + fn sends_catch_up_requests_to_non_authorities_when_observer_disabled() { + let config = { + let mut c = config(); + + // if the observer protocol is disable any full-node should be able + // to answer catch-up requests. + c.observer_enabled = false; + + c + }; + + let (val, _) = GossipValidator::::new( + config, + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // add the peer making the requests to the validator, otherwise it is + // discarded. + let peer_full = PeerId::random(); + val.inner.write().peers.new_peer(peer_full.clone(), Roles::FULL); + + let (_, _, catch_up_request, _) = val.inner.write().import_neighbor_message( + &peer_full, + NeighborPacket { + round: Round(42), + set_id: SetId(1), + commit_finalized_height: 50, + }, + ); + + // importing a neighbor message from a peer in the same set in a later + // round should lead to a catch up request, the node is not an + // authority, but since the observer protocol is disabled we should + // issue a catch-up request to it anyway. + match catch_up_request { + Some(GossipMessage::CatchUpRequest(request)) => { + assert_eq!(request.set_id, SetId(1)); + assert_eq!(request.round, Round(41)); + }, + _ => panic!("expected catch up message"), + } + } + + #[test] + fn doesnt_expire_next_round_messages() { + // NOTE: this is a regression test + let (val, _) = GossipValidator::::new( + config(), + voter_set_state(), + ); + + // the validator starts at set id 1. + val.note_set(SetId(1), Vec::new(), |_, _| {}); + + // we are at round 10 + val.note_round(Round(9), |_, _| {}); + val.note_round(Round(10), |_, _| {}); + + let mut is_expired = val.message_expired(); + + // we accept messages from rounds 9, 10 and 11 + // therefore neither of those should be considered expired + for round in &[9, 10, 11] { + assert!( + !is_expired( + crate::communication::round_topic::(*round, 1), + &[], + ) + ) + } + } } diff --git a/core/finality-grandpa/src/communication/mod.rs b/core/finality-grandpa/src/communication/mod.rs index 2aa2618535948821e99984b9934c17b79a46f95e..4cc772fe9d4a03aa06a3e93655803b100d6f55f5 100644 --- a/core/finality-grandpa/src/communication/mod.rs +++ b/core/finality-grandpa/src/communication/mod.rs @@ -31,6 +31,7 @@ use std::sync::Arc; use futures::prelude::*; use futures::sync::{oneshot, mpsc}; +use futures03::stream::{StreamExt, TryStreamExt}; use grandpa::Message::{Prevote, Precommit, PrimaryPropose}; use grandpa::{voter, voter_set::VoterSet}; use log::{debug, trace}; @@ -38,7 +39,7 @@ use network::{consensus_gossip as network_gossip, NetworkService}; use network_gossip::ConsensusMessage; use codec::{Encode, Decode}; use primitives::Pair; -use sr_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; +use sr_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor}; use substrate_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; use tokio_executor::Executor; @@ -48,9 +49,11 @@ use crate::{ }; use crate::environment::HasVoted; use gossip::{ - GossipMessage, FullCatchUpMessage, FullCommitMessage, VoteOrPrecommitMessage, GossipValidator + GossipMessage, FullCatchUpMessage, FullCommitMessage, VoteMessage, GossipValidator +}; +use fg_primitives::{ + AuthorityPair, AuthorityId, AuthoritySignature, SetId as SetIdNumber, RoundNumber, }; -use fg_primitives::{AuthorityPair, AuthorityId, AuthoritySignature}; pub mod gossip; mod periodic; @@ -98,7 +101,7 @@ mod benefit { /// Intended to be a lightweight handle such as an `Arc`. pub trait Network: Clone + Send + 'static { /// A stream of input messages for a topic. - type In: Stream; + type In: Stream; /// Get a stream of messages for a specific gossip topic. fn messages_for(&self, topic: Block::Hash) -> Self::In; @@ -125,16 +128,24 @@ pub trait Network: Clone + Send + 'static { fn report(&self, who: network::PeerId, cost_benefit: i32); /// Inform peers that a block with given hash should be downloaded. - fn announce(&self, block: Block::Hash); + fn announce(&self, block: Block::Hash, associated_data: Vec); + + /// Notifies the sync service to try and sync the given block from the given + /// peers. + /// + /// If the given vector of peers is empty then the underlying implementation + /// should make a best effort to fetch the block from any peers it is + /// connected to (NOTE: this assumption will change in the future #3629). + fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor); } /// Create a unique topic for a round and set-id combo. -pub(crate) fn round_topic(round: u64, set_id: u64) -> B::Hash { +pub(crate) fn round_topic(round: RoundNumber, set_id: SetIdNumber) -> B::Hash { <::Hashing as HashT>::hash(format!("{}-{}", set_id, round).as_bytes()) } /// Create a unique topic for global messages on a set ID. -pub(crate) fn global_topic(set_id: u64) -> B::Hash { +pub(crate) fn global_topic(set_id: SetIdNumber) -> B::Hash { <::Hashing as HashT>::hash(format!("{}-GLOBAL", set_id).as_bytes()) } @@ -143,15 +154,30 @@ impl Network for Arc> where S: network::specialization::NetworkSpecialization, H: network::ExHashT, { - type In = NetworkStream; + type In = NetworkStream< + Box + Send + 'static>, + >; fn messages_for(&self, topic: B::Hash) -> Self::In { + // Given that one can only communicate with the Substrate network via the `NetworkService` via message-passing, + // and given that methods on the network consensus gossip are not exposed but only reachable by passing a + // closure into `with_gossip` on the `NetworkService` this function needs to make use of the `NetworkStream` + // construction. + // + // We create a oneshot channel and pass the sender within a closure to the network. At some point in the future + // the network passes the message channel back through the oneshot channel. But the consumer of this function + // expects a stream, not a stream within a oneshot. This complexity is abstracted within `NetworkStream`, + // waiting for the oneshot to resolve and from there on acting like a normal message channel. let (tx, rx) = oneshot::channel(); self.with_gossip(move |gossip, _| { - let inner_rx = gossip.messages_for(GRANDPA_ENGINE_ID, topic); + let inner_rx: Box + Send> = Box::new(gossip + .messages_for(GRANDPA_ENGINE_ID, topic) + .map(|x| Ok(x)) + .compat() + ); let _ = tx.send(inner_rx); }); - NetworkStream { outer: rx, inner: None } + NetworkStream::PollingOneshot(rx) } fn register_validator(&self, validator: Arc>) { @@ -195,33 +221,52 @@ impl Network for Arc> where self.report_peer(who, cost_benefit) } - fn announce(&self, block: B::Hash) { - self.announce_block(block) + fn announce(&self, block: B::Hash, associated_data: Vec) { + self.announce_block(block, associated_data) + } + + fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { + NetworkService::set_sync_fork_request(self, peers, hash, number) } } -/// A stream used by NetworkBridge in its implementation of Network. -pub struct NetworkStream { - inner: Option>, - outer: oneshot::Receiver> +/// A stream used by NetworkBridge in its implementation of Network. Given a oneshot that eventually returns a channel +/// which eventually returns messages, instead of: +/// +/// 1. polling the oneshot until it returns a message channel +/// +/// 2. polling the message channel for messages +/// +/// `NetworkStream` combines the two steps into one, requiring a consumer to only poll `NetworkStream` to retrieve +/// messages directly. +pub enum NetworkStream { + PollingOneshot(oneshot::Receiver), + PollingTopicNotifications(R), } -impl Stream for NetworkStream { - type Item = network_gossip::TopicNotification; +impl Stream for NetworkStream +where + R: Stream, +{ + type Item = R::Item; type Error = (); fn poll(&mut self) -> Poll, Self::Error> { - if let Some(ref mut inner) = self.inner { - return inner.poll(); - } - match self.outer.poll() { - Ok(futures::Async::Ready(mut inner)) => { - let poll_result = inner.poll(); - self.inner = Some(inner); - poll_result + match self { + NetworkStream::PollingOneshot(oneshot) => { + match oneshot.poll() { + Ok(futures::Async::Ready(mut stream)) => { + let poll_result = stream.poll(); + *self = NetworkStream::PollingTopicNotifications(stream); + poll_result + }, + Ok(futures::Async::NotReady) => Ok(futures::Async::NotReady), + Err(_) => Err(()) + } + }, + NetworkStream::PollingTopicNotifications(stream) => { + stream.poll() }, - Ok(futures::Async::NotReady) => Ok(futures::Async::NotReady), - Err(_) => Err(()) } } } @@ -231,24 +276,29 @@ pub(crate) struct NetworkBridge> { service: N, validator: Arc>, neighbor_sender: periodic::NeighborPacketSender, + announce_sender: periodic::BlockAnnounceSender, } impl> NetworkBridge { /// Create a new NetworkBridge to the given NetworkService. Returns the service /// handle and a future that must be polled to completion to finish startup. - /// If a voter set state is given it registers previous round votes with the - /// gossip service. + /// On creation it will register previous rounds' votes with the gossip + /// service taken from the VoterSetState. pub(crate) fn new( service: N, config: crate::Config, set_state: crate::environment::SharedVoterSetState, - on_exit: impl Future + Clone + Send + 'static, + on_exit: impl Future + Clone + Send + 'static, ) -> ( Self, - impl futures::Future + Send + 'static, + impl Future + Send + 'static, ) { - let (validator, report_stream) = GossipValidator::new(config, set_state.clone()); + let (validator, report_stream) = GossipValidator::new( + config, + set_state.clone(), + ); + let validator = Arc::new(validator); service.register_validator(validator.clone()); @@ -266,8 +316,8 @@ impl> NetworkBridge { validator.note_round(Round(round.number), |_, _| {}); for signed in round.votes.iter() { - let message = gossip::GossipMessage::VoteOrPrecommit( - gossip::VoteOrPrecommitMessage:: { + let message = gossip::GossipMessage::Vote( + gossip::VoteMessage:: { message: signed.clone(), round: Round(round.number), set_id: SetId(set_id), @@ -291,9 +341,10 @@ impl> NetworkBridge { } let (rebroadcast_job, neighbor_sender) = periodic::neighbor_packet_worker(service.clone()); + let (announce_job, announce_sender) = periodic::block_announce_worker(service.clone()); let reporting_job = report_stream.consume(service.clone()); - let bridge = NetworkBridge { service, validator, neighbor_sender }; + let bridge = NetworkBridge { service, validator, neighbor_sender, announce_sender }; let startup_work = futures::future::lazy(move || { // lazily spawn these jobs onto their own tasks. the lazy future has access @@ -301,6 +352,8 @@ impl> NetworkBridge { let mut executor = tokio_executor::DefaultExecutor::current(); executor.spawn(Box::new(rebroadcast_job.select(on_exit.clone()).then(|_| Ok(())))) .expect("failed to spawn grandpa rebroadcast job task"); + executor.spawn(Box::new(announce_job.select(on_exit.clone()).then(|_| Ok(())))) + .expect("failed to spawn grandpa block announce job task"); executor.spawn(Box::new(reporting_job.select(on_exit.clone()).then(|_| Ok(())))) .expect("failed to spawn grandpa reporting job task"); Ok(()) @@ -320,22 +373,17 @@ impl> NetworkBridge { self.validator.note_set( set_id, voters.voters().iter().map(|(v, _)| v.clone()).collect(), - |to, neighbor| self.service.send_message( - to, - GossipMessage::::from(neighbor).encode() - ), + |to, neighbor| self.neighbor_sender.send(to, neighbor), ); self.validator.note_round( round, - |to, neighbor| self.service.send_message( - to, - GossipMessage::::from(neighbor).encode() - ), + |to, neighbor| self.neighbor_sender.send(to, neighbor), ); } - /// Get the round messages for a round in the current set ID. These are signature-checked. + /// Get a stream of signature-checked round messages from the network as well as a sink for round messages to the + /// network all within the current set. pub(crate) fn round_communication( &self, round: Round, @@ -373,7 +421,7 @@ impl> NetworkBridge { }) .and_then(move |msg| { match msg { - GossipMessage::VoteOrPrecommit(msg) => { + GossipMessage::Vote(msg) => { // check signature. if !voters.contains_key(&msg.message.id) { debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id); @@ -422,6 +470,7 @@ impl> NetworkBridge { network: self.service.clone(), locals, sender: tx, + announce_sender: self.announce_sender.clone(), has_voted, }; @@ -429,6 +478,9 @@ impl> NetworkBridge { format!("Failed to receive on unbounded receiver for round {}", round.0) )); + // Combine incoming votes from external GRANDPA nodes with outgoing + // votes from our own GRANDPA voter to have a single + // vote-import-pipeline. let incoming = incoming.select(out_rx); (incoming, outgoing) @@ -447,18 +499,25 @@ impl> NetworkBridge { self.validator.note_set( set_id, voters.voters().iter().map(|(v, _)| v.clone()).collect(), - |to, neighbor| self.service.send_message(to, GossipMessage::::from(neighbor).encode()), + |to, neighbor| self.neighbor_sender.send(to, neighbor), ); let service = self.service.clone(); let topic = global_topic::(set_id.0); - let incoming = incoming_global(service, topic, voters, self.validator.clone()); + let incoming = incoming_global( + service, + topic, + voters, + self.validator.clone(), + self.neighbor_sender.clone(), + ); let outgoing = CommitsOut::::new( self.service.clone(), set_id.0, is_voter, self.validator.clone(), + self.neighbor_sender.clone(), ); let outgoing = outgoing.with(|out| { @@ -468,6 +527,16 @@ impl> NetworkBridge { (incoming, outgoing) } + + /// Notifies the sync service to try and sync the given block from the given + /// peers. + /// + /// If the given vector of peers is empty then the underlying implementation + /// should make a best effort to fetch the block from any peers it is + /// connected to (NOTE: this assumption will change in the future #3629). + pub(crate) fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { + self.service.set_sync_fork_request(peers, hash, number) + } } fn incoming_global>( @@ -475,6 +544,7 @@ fn incoming_global>( topic: B::Hash, voters: Arc>, gossip_validator: Arc>, + neighbor_sender: periodic::NeighborPacketSender, ) -> impl Stream, Error = Error> { let process_commit = move | msg: FullCommitMessage, @@ -512,6 +582,7 @@ fn incoming_global>( let finalized_number = commit.target_number; let gossip_validator = gossip_validator.clone(); let service = service.clone(); + let neighbor_sender = neighbor_sender.clone(); let cb = move |outcome| match outcome { voter::CommitProcessingOutcome::Good(_) => { // if it checks out, gossip it. not accounting for @@ -519,10 +590,7 @@ fn incoming_global>( // finalized number. gossip_validator.note_commit_finalized( finalized_number, - |to, neighbor_msg| service.send_message( - to, - GossipMessage::::from(neighbor_msg).encode(), - ), + |to, neighbor| neighbor_sender.send(to, neighbor), ); service.gossip_message(topic, notification.message.clone(), false); @@ -608,29 +676,30 @@ impl> Clone for NetworkBridge { service: self.service.clone(), validator: Arc::clone(&self.validator), neighbor_sender: self.neighbor_sender.clone(), + announce_sender: self.announce_sender.clone(), } } } -fn localized_payload(round: u64, set_id: u64, message: &E) -> Vec { +pub(crate) fn localized_payload(round: RoundNumber, set_id: SetIdNumber, message: &E) -> Vec { (message, round, set_id).encode() } -/// Type-safe wrapper around u64 when indicating that it's a round number. +/// Type-safe wrapper around a round number. #[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] -pub struct Round(pub u64); +pub struct Round(pub RoundNumber); -/// Type-safe wrapper around u64 when indicating that it's a set ID. +/// Type-safe wrapper around a set ID. #[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)] -pub struct SetId(pub u64); +pub struct SetId(pub SetIdNumber); // check a message. pub(crate) fn check_message_sig( message: &Message, id: &AuthorityId, signature: &AuthoritySignature, - round: u64, - set_id: u64, + round: RoundNumber, + set_id: SetIdNumber, ) -> Result<(), ()> { let as_public = id.clone(); let encoded_raw = localized_payload(round, set_id, message); @@ -650,10 +719,11 @@ pub(crate) fn check_message_sig( /// `ed25519` and `BLS` signatures (which we might use in the future), care must /// be taken when switching to different key types. struct OutgoingMessages> { - round: u64, - set_id: u64, + round: RoundNumber, + set_id: SetIdNumber, locals: Option<(AuthorityPair, AuthorityId)>, sender: mpsc::UnboundedSender>, + announce_sender: periodic::BlockAnnounceSender, network: N, has_voted: HasVoted, } @@ -692,7 +762,7 @@ impl> Sink for OutgoingMessages id: local_id.clone(), }; - let message = GossipMessage::VoteOrPrecommit(VoteOrPrecommitMessage:: { + let message = GossipMessage::Vote(VoteMessage:: { message: signed.clone(), round: Round(self.round), set_id: SetId(self.set_id), @@ -711,10 +781,10 @@ impl> Sink for OutgoingMessages "block" => ?target_hash, "round" => ?self.round, "set_id" => ?self.set_id, ); - // announce our block hash to peers and propagate the - // message. - self.network.announce(target_hash); + // send the target block hash to the background block announcer + self.announce_sender.send(target_hash, Vec::new()); + // propagate the message to peers let topic = round_topic::(self.round, self.set_id); self.network.gossip_message(topic, message.encode(), false); @@ -845,8 +915,8 @@ fn check_catch_up( fn check_signatures<'a, B, I>( messages: I, - round: u64, - set_id: u64, + round: RoundNumber, + set_id: SetIdNumber, mut signatures_checked: usize, ) -> Result where B: BlockT, @@ -907,30 +977,33 @@ struct CommitsOut> { set_id: SetId, is_voter: bool, gossip_validator: Arc>, + neighbor_sender: periodic::NeighborPacketSender, } impl> CommitsOut { /// Create a new commit output stream. pub(crate) fn new( network: N, - set_id: u64, + set_id: SetIdNumber, is_voter: bool, gossip_validator: Arc>, + neighbor_sender: periodic::NeighborPacketSender, ) -> Self { CommitsOut { network, set_id: SetId(set_id), is_voter, gossip_validator, + neighbor_sender, } } } impl> Sink for CommitsOut { - type SinkItem = (u64, Commit); + type SinkItem = (RoundNumber, Commit); type SinkError = Error; - fn start_send(&mut self, input: (u64, Commit)) -> StartSend { + fn start_send(&mut self, input: (RoundNumber, Commit)) -> StartSend { if !self.is_voter { return Ok(AsyncSink::Ready); } @@ -964,10 +1037,7 @@ impl> Sink for CommitsOut { // before gossiping self.gossip_validator.note_commit_finalized( commit.target_number, - |to, neighbor| self.network.send_message( - to, - GossipMessage::::from(neighbor).encode(), - ), + |to, neighbor| self.neighbor_sender.send(to, neighbor), ); self.network.gossip_message(topic, message.encode(), false); diff --git a/core/finality-grandpa/src/communication/periodic.rs b/core/finality-grandpa/src/communication/periodic.rs index 7265fe34a2a8659783c9b7cd2e5afa1bed05b560..81c18891d03b52f6aae572c8768433218322aa05 100644 --- a/core/finality-grandpa/src/communication/periodic.rs +++ b/core/finality-grandpa/src/communication/periodic.rs @@ -16,26 +16,49 @@ //! Periodic rebroadcast of neighbor packets. -use super::{gossip::{NeighborPacket, GossipMessage}, Network}; +use std::collections::VecDeque; +use std::time::{Instant, Duration}; + +use codec::Encode; use futures::prelude::*; use futures::sync::mpsc; -use sr_primitives::traits::{NumberFor, Block as BlockT}; -use network::PeerId; +use log::{debug, warn}; use tokio_timer::Delay; -use log::warn; -use codec::Encode; -use std::time::{Instant, Duration}; +use network::PeerId; +use sr_primitives::traits::{NumberFor, Block as BlockT}; +use super::{gossip::{NeighborPacket, GossipMessage}, Network}; // how often to rebroadcast, if no other const REBROADCAST_AFTER: Duration = Duration::from_secs(2 * 60); +/// The number of block hashes that we have previously voted on that we should +/// keep around for announcement. The current value should be enough for 3 +/// rounds assuming we have prevoted and precommited on different blocks. +const LATEST_VOTED_BLOCKS_TO_ANNOUNCE: usize = 6; + fn rebroadcast_instant() -> Instant { Instant::now() + REBROADCAST_AFTER } /// A sender used to send neighbor packets to a background job. -pub(super) type NeighborPacketSender = mpsc::UnboundedSender<(Vec, NeighborPacket>)>; +#[derive(Clone)] +pub(super) struct NeighborPacketSender( + mpsc::UnboundedSender<(Vec, NeighborPacket>)> +); + +impl NeighborPacketSender { + /// Send a neighbor packet for the background worker to gossip to peers. + pub fn send( + &self, + who: Vec, + neighbor_packet: NeighborPacket>, + ) { + if let Err(err) = self.0.unbounded_send((who, neighbor_packet)) { + debug!(target: "afg", "Failed to send neighbor packet: {:?}", err); + } + } +} /// Does the work of sending neighbor packets, asynchronously. /// @@ -89,5 +112,141 @@ pub(super) fn neighbor_packet_worker(net: N) -> ( } }); - (work, tx) + (work, NeighborPacketSender(tx)) +} + +/// A background worker for performing block announcements. +struct BlockAnnouncer { + net: N, + block_rx: mpsc::UnboundedReceiver<(B::Hash, Vec)>, + latest_voted_blocks: VecDeque, + reannounce_after: Duration, + delay: Delay, +} + +/// A background worker for announcing block hashes to peers. The worker keeps +/// track of `LATEST_VOTED_BLOCKS_TO_ANNOUNCE` and periodically announces these +/// blocks to all peers if no new blocks to announce are noted (i.e. presumably +/// GRANDPA progress is stalled). +pub(super) fn block_announce_worker>(net: N) -> ( + impl Future, + BlockAnnounceSender, +) { + block_announce_worker_aux(net, REBROADCAST_AFTER) +} + +#[cfg(test)] +pub(super) fn block_announce_worker_with_delay>( + net: N, + reannounce_after: Duration, +) -> ( + impl Future, + BlockAnnounceSender, +) { + block_announce_worker_aux(net, reannounce_after) +} + +fn block_announce_worker_aux>( + net: N, + reannounce_after: Duration, +) -> ( + impl Future, + BlockAnnounceSender, +) { + let latest_voted_blocks = VecDeque::with_capacity(LATEST_VOTED_BLOCKS_TO_ANNOUNCE); + + let (block_tx, block_rx) = mpsc::unbounded(); + + let announcer = BlockAnnouncer { + net, + block_rx, + latest_voted_blocks, + reannounce_after, + delay: Delay::new(Instant::now() + reannounce_after), + }; + + (announcer, BlockAnnounceSender(block_tx)) +} + + +impl BlockAnnouncer { + fn note_block(&mut self, block: B::Hash) -> bool { + if !self.latest_voted_blocks.contains(&block) { + if self.latest_voted_blocks.len() >= LATEST_VOTED_BLOCKS_TO_ANNOUNCE { + self.latest_voted_blocks.pop_front(); + } + + self.latest_voted_blocks.push_back(block); + + true + } else { + false + } + } + + fn reset_delay(&mut self) { + self.delay.reset(Instant::now() + self.reannounce_after); + } +} + +impl> Future for BlockAnnouncer { + type Item = (); + type Error = (); + + fn poll(&mut self) -> Poll { + // note any new blocks to announce and announce them + loop { + match self.block_rx.poll().expect("unbounded receivers do not error; qed") { + Async::Ready(None) => return Ok(Async::Ready(())), + Async::Ready(Some(block)) => { + if self.note_block(block.0) { + self.net.announce(block.0, block.1); + self.reset_delay(); + } + }, + Async::NotReady => break, + } + } + + // check the reannouncement delay timer, has to be done in a loop + // because it needs to be polled after re-scheduling. + loop { + match self.delay.poll() { + Err(e) => { + warn!(target: "afg", "Error in periodic block announcer timer: {:?}", e); + self.reset_delay(); + }, + // after the delay fires announce all blocks that we have + // stored. note that this only happens if we don't receive any + // new blocks above for the duration of `reannounce_after`. + Ok(Async::Ready(())) => { + self.reset_delay(); + + debug!( + target: "afg", + "Re-announcing latest voted blocks due to lack of progress: {:?}", + self.latest_voted_blocks, + ); + + for block in self.latest_voted_blocks.iter() { + self.net.announce(*block, Vec::new()); + } + }, + Ok(Async::NotReady) => return Ok(Async::NotReady), + } + } + } +} + +/// A sender used to send block hashes to announce to a background job. +#[derive(Clone)] +pub(super) struct BlockAnnounceSender(mpsc::UnboundedSender<(B::Hash, Vec)>); + +impl BlockAnnounceSender { + /// Send a block hash for the background worker to announce. + pub fn send(&self, block: B::Hash, associated_data: Vec) { + if let Err(err) = self.0.unbounded_send((block, associated_data)) { + debug!(target: "afg", "Failed to send block to background announcer: {:?}", err); + } + } } diff --git a/core/finality-grandpa/src/communication/tests.rs b/core/finality-grandpa/src/communication/tests.rs index de5a084039268193e840f7511e322cf41155940e..f918f47258d499c4deb8692e65946276ef3e9a20 100644 --- a/core/finality-grandpa/src/communication/tests.rs +++ b/core/finality-grandpa/src/communication/tests.rs @@ -25,6 +25,7 @@ use tokio::runtime::current_thread; use std::sync::Arc; use keyring::Ed25519Keyring; use codec::Encode; +use sr_primitives::traits::NumberFor; use crate::environment::SharedVoterSetState; use super::gossip::{self, GossipValidator}; @@ -88,9 +89,12 @@ impl super::Network for TestNetwork { } /// Inform peers that a block with given hash should be downloaded. - fn announce(&self, block: Hash) { + fn announce(&self, block: Hash, _associated_data: Vec) { let _ = self.sender.unbounded_send(Event::Announce(block)); } + + /// Notify the sync service to try syncing the given chain. + fn set_sync_fork_request(&self, _peers: Vec, _hash: Hash, _number: NumberFor) {} } impl network_gossip::ValidatorContext for TestNetwork { @@ -135,6 +139,8 @@ fn config() -> crate::Config { justification_period: 256, keystore: None, name: None, + is_authority: true, + observer_enabled: true, } } @@ -216,7 +222,7 @@ fn good_commit_leads_to_relay() { let public = make_ids(&private[..]); let voter_set = Arc::new(public.iter().cloned().collect::>()); - let round = 0; + let round = 1; let set_id = 1; let commit = { @@ -331,7 +337,7 @@ fn bad_commit_leads_to_report() { let public = make_ids(&private[..]); let voter_set = Arc::new(public.iter().cloned().collect::>()); - let round = 0; + let round = 1; let set_id = 1; let commit = { @@ -447,8 +453,8 @@ fn peer_with_higher_view_leads_to_catch_up_request() { let (tester, mut net) = make_test_network(); let test = tester .and_then(move |tester| { - // register a peer. - tester.gossip_validator.new_peer(&mut NoopContext, &id, network::config::Roles::FULL); + // register a peer with authority role. + tester.gossip_validator.new_peer(&mut NoopContext, &id, network::config::Roles::AUTHORITY); Ok((tester, id)) }) .and_then(move |(tester, id)| { @@ -497,3 +503,79 @@ fn peer_with_higher_view_leads_to_catch_up_request() { current_thread::block_on_all(test).unwrap(); } + +#[test] +fn periodically_reannounce_voted_blocks_on_stall() { + use futures::try_ready; + use std::collections::HashSet; + use std::sync::Arc; + use std::time::Duration; + use parking_lot::Mutex; + + let (tester, net) = make_test_network(); + let (announce_worker, announce_sender) = super::periodic::block_announce_worker_with_delay( + net, + Duration::from_secs(1), + ); + + let hashes = Arc::new(Mutex::new(Vec::new())); + + fn wait_all(tester: Tester, hashes: &[Hash]) -> impl Future { + struct WaitAll { + remaining_hashes: Arc>>, + events_fut: Box>, + } + + impl Future for WaitAll { + type Item = Tester; + type Error = (); + + fn poll(&mut self) -> Poll { + let tester = try_ready!(self.events_fut.poll()); + + if self.remaining_hashes.lock().is_empty() { + return Ok(Async::Ready(tester)); + } + + let remaining_hashes = self.remaining_hashes.clone(); + self.events_fut = Box::new(tester.filter_network_events(move |event| match event { + Event::Announce(h) => + remaining_hashes.lock().remove(&h) || panic!("unexpected announce"), + _ => false, + })); + + self.poll() + } + } + + WaitAll { + remaining_hashes: Arc::new(Mutex::new(hashes.iter().cloned().collect())), + events_fut: Box::new(futures::future::ok(tester)), + } + } + + let test = tester + .and_then(move |tester| { + current_thread::spawn(announce_worker); + Ok(tester) + }) + .and_then(|tester| { + // announce 12 blocks + for _ in 0..=12 { + let hash = Hash::random(); + hashes.lock().push(hash); + announce_sender.send(hash, Vec::new()); + } + + // we should see an event for each of those announcements + wait_all(tester, &hashes.lock()) + }) + .and_then(|tester| { + // after a period of inactivity we should see the last + // `LATEST_VOTED_BLOCKS_TO_ANNOUNCE` being rebroadcast + wait_all(tester, &hashes.lock()[7..=12]) + }); + + let mut runtime = current_thread::Runtime::new().unwrap(); + runtime.block_on(test).unwrap(); +} diff --git a/core/finality-grandpa/src/environment.rs b/core/finality-grandpa/src/environment.rs index 5761093c5eb676a2c5e3ec56c01d636a1216d033..149b00e80f92033ff73cafc90567113cd1d7e4a5 100644 --- a/core/finality-grandpa/src/environment.rs +++ b/core/finality-grandpa/src/environment.rs @@ -26,8 +26,9 @@ use tokio_timer::Delay; use parking_lot::RwLock; use client::{ - backend::Backend, BlockchainEvents, CallExecutor, Client, error::Error as ClientError, - utils::is_descendent_of, + backend::Backend, apply_aux, BlockchainEvents, CallExecutor, + Client, error::Error as ClientError, utils::is_descendent_of, + blockchain::HeaderBackend, backend::Finalizer, }; use grandpa::{ BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState, @@ -51,7 +52,8 @@ use crate::authorities::{AuthoritySet, SharedAuthoritySet}; use crate::consensus_changes::SharedConsensusChanges; use crate::justification::GrandpaJustification; use crate::until_imported::UntilVoteTargetImported; -use fg_primitives::{AuthorityId, AuthoritySignature}; +use crate::voting_rule::VotingRule; +use fg_primitives::{AuthorityId, AuthoritySignature, SetId, RoundNumber}; type HistoricalVotes = grandpa::HistoricalVotes< ::Hash, @@ -65,7 +67,7 @@ type HistoricalVotes = grandpa::HistoricalVotes< #[derive(Debug, Clone, Decode, Encode, PartialEq)] pub struct CompletedRound { /// The round number. - pub number: u64, + pub number: RoundNumber, /// The round state (prevote ghost, estimate, finalized, etc.) pub state: RoundState>, /// The target block base used for voting in the round. @@ -80,7 +82,7 @@ pub struct CompletedRound { #[derive(Debug, Clone, PartialEq)] pub struct CompletedRounds { rounds: Vec>, - set_id: u64, + set_id: SetId, voters: Vec, } @@ -100,7 +102,7 @@ impl codec::EncodeLike for CompletedRounds {} impl Decode for CompletedRounds { fn decode(value: &mut I) -> Result { - <(Vec>, u64, Vec)>::decode(value) + <(Vec>, SetId, Vec)>::decode(value) .map(|(rounds, set_id, voters)| CompletedRounds { rounds: rounds.into(), set_id, @@ -113,7 +115,7 @@ impl CompletedRounds { /// Create a new completed rounds tracker with NUM_LAST_COMPLETED_ROUNDS capacity. pub(crate) fn new( genesis: CompletedRound, - set_id: u64, + set_id: SetId, voters: &AuthoritySet>, ) -> CompletedRounds @@ -126,7 +128,7 @@ impl CompletedRounds { } /// Get the set-id and voter set of the completed rounds. - pub fn set_info(&self) -> (u64, &[AuthorityId]) { + pub fn set_info(&self) -> (SetId, &[AuthorityId]) { (self.set_id, &self.voters[..]) } @@ -162,7 +164,7 @@ impl CompletedRounds { /// A map with voter status information for currently live rounds, /// which votes have we cast and what are they. -pub type CurrentRounds = BTreeMap>; +pub type CurrentRounds = BTreeMap>; /// The state of the current voter set, whether it is currently active or not /// and information related to the previously completed rounds. Current round @@ -190,7 +192,7 @@ impl VoterSetState { /// the given genesis state and the given authorities. Round 1 is added as a /// current round (with state `HasVoted::No`). pub(crate) fn live( - set_id: u64, + set_id: SetId, authority_set: &AuthoritySet>, genesis_state: (Block::Hash, NumberFor), ) -> VoterSetState { @@ -237,7 +239,7 @@ impl VoterSetState { /// Returns the voter set state validating that it includes the given round /// in current rounds and that the voter isn't paused. - pub fn with_current_round(&self, round: u64) + pub fn with_current_round(&self, round: RoundNumber) -> Result<(&CompletedRounds, &CurrentRounds), Error> { if let VoterSetState::Live { completed_rounds, current_rounds } = self { @@ -344,7 +346,7 @@ impl SharedVoterSetState { } /// Return vote status information for the current round. - pub(crate) fn has_voted(&self, round: u64) -> HasVoted { + pub(crate) fn has_voted(&self, round: RoundNumber) -> HasVoted { match &*self.inner.read() { VoterSetState::Live { current_rounds, .. } => { current_rounds.get(&round).and_then(|has_voted| match has_voted { @@ -367,19 +369,20 @@ impl SharedVoterSetState { } /// The environment we run GRANDPA in. -pub(crate) struct Environment, RA, SC> { - pub(crate) inner: Arc>, +pub(crate) struct Environment, RA, SC, VR> { + pub(crate) client: Arc>, pub(crate) select_chain: SC, pub(crate) voters: Arc>, pub(crate) config: Config, pub(crate) authority_set: SharedAuthoritySet>, pub(crate) consensus_changes: SharedConsensusChanges>, pub(crate) network: crate::communication::NetworkBridge, - pub(crate) set_id: u64, + pub(crate) set_id: SetId, pub(crate) voter_set_state: SharedVoterSetState, + pub(crate) voting_rule: VR, } -impl, RA, SC> Environment { +impl, RA, SC, VR> Environment { /// Updates the voter set state using the given closure. The write lock is /// held during evaluation of the closure and the environment's voter set /// state is set to its result if successful. @@ -395,20 +398,22 @@ impl, RA, SC> Environment, B, E, N, RA, SC> +impl, B, E, N, RA, SC, VR> grandpa::Chain> -for Environment +for Environment where Block: 'static, B: Backend + 'static, - E: CallExecutor + 'static, + E: CallExecutor + Send + Sync + 'static, N: Network + 'static, N::In: 'static, SC: SelectChain + 'static, + VR: VotingRule>, + RA: Send + Sync, NumberFor: BlockNumberOps, { fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { - ancestry(&self.inner, base, block) + ancestry(&self.client, base, block) } fn best_chain_containing(&self, block: Block::Hash) -> Option<(Block::Hash, NumberFor)> { @@ -428,8 +433,8 @@ where debug!(target: "afg", "Finding best chain containing block {:?} with number limit {:?}", block, limit); match self.select_chain.finality_target(block, None) { - Ok(Some(mut best_hash)) => { - let base_header = self.inner.header(&BlockId::Hash(block)).ok()? + Ok(Some(best_hash)) => { + let base_header = self.client.header(&BlockId::Hash(block)).ok()? .expect("Header known to exist after `best_containing` call; qed"); if let Some(limit) = limit { @@ -444,35 +449,51 @@ where } } - let mut best_header = self.inner.header(&BlockId::Hash(best_hash)).ok()? + let best_header = self.client.header(&BlockId::Hash(best_hash)).ok()? .expect("Header known to exist after `best_containing` call; qed"); - // we target a vote towards 3/4 of the unfinalized chain (rounding up) - let target = { - let two = NumberFor::::one() + One::one(); - let three = two + One::one(); - let four = three + One::one(); - - let diff = *best_header.number() - *base_header.number(); - let diff = ((diff * three) + two) / four; + // check if our vote is currently being limited due to a pending change + let limit = limit.filter(|limit| limit < best_header.number()); + let target; + + let target_header = if let Some(target_number) = limit { + let mut target_header = best_header.clone(); + + // walk backwards until we find the target block + loop { + if *target_header.number() < target_number { + unreachable!( + "we are traversing backwards from a known block; \ + blocks are stored contiguously; \ + qed" + ); + } + + if *target_header.number() == target_number { + break; + } + + target_header = self.client.header(&BlockId::Hash(*target_header.parent_hash())).ok()? + .expect("Header known to exist after `best_containing` call; qed"); + } - *base_header.number() + diff + target = target_header; + &target + } else { + // otherwise just use the given best as the target + &best_header }; - // unless our vote is currently being limited due to a pending change - let target = limit.map(|limit| limit.min(target)).unwrap_or(target); - - // walk backwards until we find the target block - loop { - if *best_header.number() < target { unreachable!(); } - if *best_header.number() == target { - return Some((best_hash, *best_header.number())); - } - - best_hash = *best_header.parent_hash(); - best_header = self.inner.header(&BlockId::Hash(best_hash)).ok()? - .expect("Header known to exist after `best_containing` call; qed"); - } + // restrict vote according to the given voting rule, if the + // voting rule doesn't restrict the vote then we keep the + // previous target. + // + // note that we pass the original `best_header`, i.e. before the + // authority set limit filter, which can be considered a + // mandatory/implicit voting rule. + self.voting_rule + .restrict_vote(&*self.client, &base_header, &best_header, target_header) + .or(Some((target_header.hash(), *target_header.number()))) }, Ok(None) => { debug!(target: "afg", "Encountered error finding best chain containing {:?}: couldn't find target block", block); @@ -497,12 +518,7 @@ pub(crate) fn ancestry, E, RA>( { if base == block { return Err(GrandpaError::NotDescendent) } - let tree_route_res = ::client::blockchain::tree_route( - #[allow(deprecated)] - client.backend().blockchain(), - BlockId::Hash(block), - BlockId::Hash(base), - ); + let tree_route_res = header_metadata::tree_route(client, block, base); let tree_route = match tree_route_res { Ok(tree_route) => tree_route, @@ -523,9 +539,9 @@ pub(crate) fn ancestry, E, RA>( Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect()) } -impl, N, RA, SC> +impl, N, RA, SC, VR> voter::Environment> -for Environment +for Environment where Block: 'static, B: Backend + 'static, @@ -534,6 +550,7 @@ where N::In: 'static + Send, RA: 'static + Send + Sync, SC: SelectChain + 'static, + VR: VotingRule>, NumberFor: BlockNumberOps, { type Timer = Box + Send>; @@ -554,7 +571,7 @@ where fn round_data( &self, - round: u64 + round: RoundNumber, ) -> voter::RoundData { let now = Instant::now(); let prevote_timer = Delay::new(now + self.config.gossip_duration * 2); @@ -584,9 +601,11 @@ where // schedule incoming messages from the network to be held until // corresponding blocks are imported. let incoming = Box::new(UntilVoteTargetImported::new( - self.inner.import_notification_stream(), - self.inner.clone(), + self.client.import_notification_stream(), + self.network.clone(), + self.client.clone(), incoming, + "round", ).map_err(Into::into)); // schedule network message cleanup when sink drops. @@ -601,7 +620,7 @@ where } } - fn proposed(&self, round: u64, propose: PrimaryPropose) -> Result<(), Self::Error> { + fn proposed(&self, round: RoundNumber, propose: PrimaryPropose) -> Result<(), Self::Error> { let local_id = crate::is_voter(&self.voters, &self.config.keystore); let local_id = match local_id { @@ -632,8 +651,7 @@ where current_rounds, }; - #[allow(deprecated)] - crate::aux_schema::write_voter_set_state(&**self.inner.backend(), &set_state)?; + crate::aux_schema::write_voter_set_state(&*self.client, &set_state)?; Ok(Some(set_state)) })?; @@ -641,7 +659,7 @@ where Ok(()) } - fn prevoted(&self, round: u64, prevote: Prevote) -> Result<(), Self::Error> { + fn prevoted(&self, round: RoundNumber, prevote: Prevote) -> Result<(), Self::Error> { let local_id = crate::is_voter(&self.voters, &self.config.keystore); let local_id = match local_id { @@ -674,8 +692,7 @@ where current_rounds, }; - #[allow(deprecated)] - crate::aux_schema::write_voter_set_state(&**self.inner.backend(), &set_state)?; + crate::aux_schema::write_voter_set_state(&*self.client, &set_state)?; Ok(Some(set_state)) })?; @@ -683,7 +700,7 @@ where Ok(()) } - fn precommitted(&self, round: u64, precommit: Precommit) -> Result<(), Self::Error> { + fn precommitted(&self, round: RoundNumber, precommit: Precommit) -> Result<(), Self::Error> { let local_id = crate::is_voter(&self.voters, &self.config.keystore); let local_id = match local_id { @@ -726,8 +743,7 @@ where current_rounds, }; - #[allow(deprecated)] - crate::aux_schema::write_voter_set_state(&**self.inner.backend(), &set_state)?; + crate::aux_schema::write_voter_set_state(&*self.client, &set_state)?; Ok(Some(set_state)) })?; @@ -737,7 +753,7 @@ where fn completed( &self, - round: u64, + round: RoundNumber, state: RoundState>, base: (Block::Hash, NumberFor), historical_votes: &HistoricalVotes, @@ -785,8 +801,7 @@ where current_rounds, }; - #[allow(deprecated)] - crate::aux_schema::write_voter_set_state(&**self.inner.backend(), &set_state)?; + crate::aux_schema::write_voter_set_state(&*self.client, &set_state)?; Ok(Some(set_state)) })?; @@ -794,27 +809,15 @@ where Ok(()) } - fn finalize_block(&self, hash: Block::Hash, number: NumberFor, round: u64, commit: Commit) -> Result<(), Self::Error> { - use client::blockchain::HeaderBackend; - - #[allow(deprecated)] - let blockchain = self.inner.backend().blockchain(); - let status = blockchain.info(); - if number <= status.finalized_number && blockchain.hash(number)? == Some(hash) { - // This can happen after a forced change (triggered by the finality tracker when finality is stalled), since - // the voter will be restarted at the median last finalized block, which can be lower than the local best - // finalized block. - warn!(target: "afg", "Re-finalized block #{:?} ({:?}) in the canonical chain, current best finalized is #{:?}", - hash, - number, - status.finalized_number, - ); - - return Ok(()); - } - + fn finalize_block( + &self, + hash: Block::Hash, + number: NumberFor, + round: RoundNumber, + commit: Commit, + ) -> Result<(), Self::Error> { finalize_block( - &*self.inner, + &*self.client, &self.authority_set, &self.consensus_changes, Some(self.config.justification_period.into()), @@ -836,7 +839,7 @@ where fn prevote_equivocation( &self, - _round: u64, + _round: RoundNumber, equivocation: ::grandpa::Equivocation, Self::Signature> ) { warn!(target: "afg", "Detected prevote equivocation in the finality worker: {:?}", equivocation); @@ -845,7 +848,7 @@ where fn precommit_equivocation( &self, - _round: u64, + _round: RoundNumber, equivocation: Equivocation, Self::Signature> ) { warn!(target: "afg", "Detected precommit equivocation in the finality worker: {:?}", equivocation); @@ -855,11 +858,11 @@ where pub(crate) enum JustificationOrCommit { Justification(GrandpaJustification), - Commit((u64, Commit)), + Commit((RoundNumber, Commit)), } -impl From<(u64, Commit)> for JustificationOrCommit { - fn from(commit: (u64, Commit)) -> JustificationOrCommit { +impl From<(RoundNumber, Commit)> for JustificationOrCommit { + fn from(commit: (RoundNumber, Commit)) -> JustificationOrCommit { JustificationOrCommit::Commit(commit) } } @@ -887,9 +890,25 @@ pub(crate) fn finalize_block, E, RA>( E: CallExecutor + Send + Sync, RA: Send + Sync, { - // lock must be held through writing to DB to avoid race + // NOTE: lock must be held through writing to DB to avoid race. this lock + // also implicitly synchronizes the check for last finalized number + // below. let mut authority_set = authority_set.inner().write(); + let status = client.info().chain; + if number <= status.finalized_number && client.hash(number)? == Some(hash) { + // This can happen after a forced change (triggered by the finality tracker when finality is stalled), since + // the voter will be restarted at the median last finalized block, which can be lower than the local best + // finalized block. + warn!(target: "afg", "Re-finalized block #{:?} ({:?}) in the canonical chain, current best finalized is #{:?}", + hash, + number, + status.finalized_number, + ); + + return Ok(()); + } + // FIXME #1483: clone only when changed let old_authority_set = authority_set.clone(); // holds the old consensus changes in case it is changed below, needed for @@ -906,7 +925,7 @@ pub(crate) fn finalize_block, E, RA>( let status = authority_set.apply_standard_changes( hash, number, - &is_descendent_of(client, None), + &is_descendent_of::<_, _, Block::Hash>(client, None), ).map_err(|e| Error::Safety(e.to_string()))?; // check if this is this is the first finalization of some consensus changes @@ -918,7 +937,7 @@ pub(crate) fn finalize_block, E, RA>( let write_result = crate::aux_schema::update_consensus_changes( &*consensus_changes, - |insert| client.apply_aux(import_op, insert, &[]), + |insert| apply_aux(import_op, insert, &[]), ); if let Err(e) = write_result { @@ -1011,7 +1030,7 @@ pub(crate) fn finalize_block, E, RA>( let write_result = crate::aux_schema::update_authority_set::( &authority_set, new_authorities.as_ref(), - |insert| client.apply_aux(import_op, insert, &[]), + |insert| apply_aux(import_op, insert, &[]), ); if let Err(e) = write_result { @@ -1042,15 +1061,12 @@ pub(crate) fn finalize_block, E, RA>( /// Using the given base get the block at the given height on this chain. The /// target block must be an ancestor of base, therefore `height <= base.height`. -pub(crate) fn canonical_at_height, RA>( - client: &Client, +pub(crate) fn canonical_at_height, C: HeaderBackend>( + provider: C, base: (Block::Hash, NumberFor), base_is_canonical: bool, height: NumberFor, -) -> Result, ClientError> where - B: Backend, - E: CallExecutor + Send + Sync, -{ +) -> Result, ClientError> { if height > base.1 { return Ok(None); } @@ -1059,17 +1075,17 @@ pub(crate) fn canonical_at_height, RA>( if base_is_canonical { return Ok(Some(base.0)); } else { - return Ok(client.block_hash(height).unwrap_or(None)); + return Ok(provider.hash(height).unwrap_or(None)); } } else if base_is_canonical { - return Ok(client.block_hash(height).unwrap_or(None)); + return Ok(provider.hash(height).unwrap_or(None)); } let one = NumberFor::::one(); // start by getting _canonical_ block with number at parent position and then iterating // backwards by hash. - let mut current = match client.header(&BlockId::Number(base.1 - one))? { + let mut current = match provider.header(BlockId::Number(base.1 - one))? { Some(header) => header, _ => return Ok(None), }; @@ -1078,7 +1094,7 @@ pub(crate) fn canonical_at_height, RA>( let mut steps = base.1 - height - one; while steps > NumberFor::::zero() { - current = match client.header(&BlockId::Hash(*current.parent_hash()))? { + current = match provider.header(BlockId::Hash(*current.parent_hash()))? { Some(header) => header, _ => return Ok(None), }; diff --git a/core/finality-grandpa/src/finality_proof.rs b/core/finality-grandpa/src/finality_proof.rs index 6262ad74a7acb2e6a120af422367472057cef77b..bd22a7bbac287ecc383ce58508852ccb069bb204 100644 --- a/core/finality-grandpa/src/finality_proof.rs +++ b/core/finality-grandpa/src/finality_proof.rs @@ -40,14 +40,13 @@ use log::{trace, warn}; use client::{ backend::Backend, blockchain::Backend as BlockchainBackend, CallExecutor, Client, error::{Error as ClientError, Result as ClientResult}, - light::fetcher::{FetchChecker, RemoteCallRequest}, - ExecutionStrategy, NeverOffchainExt, + light::fetcher::{FetchChecker, RemoteCallRequest, StorageProof}, ExecutionStrategy, }; use codec::{Encode, Decode}; use grandpa::BlockNumberOps; -use sr_primitives::{Justification, generic::BlockId}; -use sr_primitives::traits::{ - NumberFor, Block as BlockT, Header as HeaderT, One, +use sr_primitives::{ + Justification, generic::BlockId, + traits::{NumberFor, Block as BlockT, Header as HeaderT, One}, }; use primitives::{H256, Blake2Hasher}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; @@ -63,7 +62,7 @@ pub trait AuthoritySetForFinalityProver: Send + Sync { /// Call GrandpaApi::grandpa_authorities at given block. fn authorities(&self, block: &BlockId) -> ClientResult>; /// Prove call of GrandpaApi::grandpa_authorities at given block. - fn prove_authorities(&self, block: &BlockId) -> ClientResult>>; + fn prove_authorities(&self, block: &BlockId) -> ClientResult; } /// Client-based implementation of AuthoritySetForFinalityProver. @@ -79,14 +78,14 @@ impl, RA> AuthoritySetForFinalityProver fo "GrandpaApi_grandpa_authorities", &[], ExecutionStrategy::NativeElseWasm, - NeverOffchainExt::new(), + None, ).and_then(|call_result| Decode::decode(&mut &call_result[..]) .map_err(|err| ClientError::CallResultDecode( "failed to decode GRANDPA authorities set proof".into(), err ))) } - fn prove_authorities(&self, block: &BlockId) -> ClientResult>> { + fn prove_authorities(&self, block: &BlockId) -> ClientResult { self.execution_proof(block, "GrandpaApi_grandpa_authorities",&[]).map(|(_, proof)| proof) } } @@ -98,7 +97,7 @@ pub trait AuthoritySetForFinalityChecker: Send + Sync { &self, hash: Block::Hash, header: Block::Header, - proof: Vec>, + proof: StorageProof, ) -> ClientResult>; } @@ -108,7 +107,7 @@ impl AuthoritySetForFinalityChecker for Arc>, + proof: StorageProof, ) -> ClientResult> { let request = RemoteCallRequest { block: hash, @@ -130,36 +129,31 @@ impl AuthoritySetForFinalityChecker for Arc, RA> { - client: Arc>, +pub struct FinalityProofProvider> { + backend: Arc, authority_provider: Arc>, } -impl, RA> FinalityProofProvider - where - B: Backend + Send + Sync + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, +impl> FinalityProofProvider + where B: Backend + Send + Sync + 'static { /// Create new finality proof provider using: /// - /// - client for accessing blockchain data; + /// - backend for accessing blockchain data; /// - authority_provider for calling and proving runtime methods. pub fn new( - client: Arc>, + backend: Arc, authority_provider: Arc>, ) -> Self { - FinalityProofProvider { client, authority_provider } + FinalityProofProvider { backend, authority_provider } } } -impl network::FinalityProofProvider for FinalityProofProvider +impl network::FinalityProofProvider for FinalityProofProvider where Block: BlockT, NumberFor: BlockNumberOps, B: Backend + Send + Sync + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, { fn prove_finality( &self, @@ -173,8 +167,7 @@ impl network::FinalityProofProvider for FinalityProofPro })?; match request { FinalityProofRequest::Original(request) => prove_finality::<_, _, GrandpaJustification>( - #[allow(deprecated)] - &*self.client.backend().blockchain(), + &*self.backend.blockchain(), &*self.authority_provider, request.authorities_set_id, request.last_finalized, @@ -214,7 +207,7 @@ struct FinalityProofFragment { /// The set of headers in the range (U; F] that we believe are unknown to the caller. Ordered. pub unknown_headers: Vec

, /// Optional proof of execution of GRANDPA::authorities(). - pub authorities_proof: Option>>, + pub authorities_proof: Option, } /// Proof of finality is the ordered set of finality fragments, where: @@ -589,13 +582,13 @@ pub(crate) mod tests { impl AuthoritySetForFinalityProver for (GetAuthorities, ProveAuthorities) where GetAuthorities: Send + Sync + Fn(BlockId) -> ClientResult>, - ProveAuthorities: Send + Sync + Fn(BlockId) -> ClientResult>>, + ProveAuthorities: Send + Sync + Fn(BlockId) -> ClientResult, { fn authorities(&self, block: &BlockId) -> ClientResult> { self.0(*block) } - fn prove_authorities(&self, block: &BlockId) -> ClientResult>> { + fn prove_authorities(&self, block: &BlockId) -> ClientResult { self.1(*block) } } @@ -604,13 +597,13 @@ pub(crate) mod tests { impl AuthoritySetForFinalityChecker for ClosureAuthoritySetForFinalityChecker where - Closure: Send + Sync + Fn(H256, Header, Vec>) -> ClientResult>, + Closure: Send + Sync + Fn(H256, Header, StorageProof) -> ClientResult>, { fn check_authorities_proof( &self, hash: H256, header: Header, - proof: Vec>, + proof: StorageProof, ) -> ClientResult> { self.0(hash, header, proof) } @@ -831,8 +824,8 @@ pub(crate) mod tests { _ => unreachable!("no other authorities should be fetched: {:?}", block_id), }, |block_id| match block_id { - BlockId::Number(4) => Ok(vec![vec![40]]), - BlockId::Number(6) => Ok(vec![vec![60]]), + BlockId::Number(4) => Ok(StorageProof::new(vec![vec![40]])), + BlockId::Number(6) => Ok(StorageProof::new(vec![vec![60]])), _ => unreachable!("no other authorities should be proved: {:?}", block_id), }, ), @@ -848,14 +841,14 @@ pub(crate) mod tests { block: header(5).hash(), justification: just5, unknown_headers: Vec::new(), - authorities_proof: Some(vec![vec![40]]), + authorities_proof: Some(StorageProof::new(vec![vec![40]])), }, // last fragment provides justification for #7 && unknown#7 FinalityProofFragment { block: header(7).hash(), justification: just7, unknown_headers: vec![header(7)], - authorities_proof: Some(vec![vec![60]]), + authorities_proof: Some(StorageProof::new(vec![vec![60]])), }, ]); } @@ -902,7 +895,7 @@ pub(crate) mod tests { block: header(4).hash(), justification: TestJustification(true, vec![7]).encode(), unknown_headers: vec![header(4)], - authorities_proof: Some(vec![vec![42]]), + authorities_proof: Some(StorageProof::new(vec![vec![42]])), }, FinalityProofFragment { block: header(5).hash(), justification: TestJustification(true, vec![8]).encode(), @@ -949,7 +942,7 @@ pub(crate) mod tests { block: header(2).hash(), justification: TestJustification(true, vec![7]).encode(), unknown_headers: Vec::new(), - authorities_proof: Some(vec![vec![42]]), + authorities_proof: Some(StorageProof::new(vec![vec![42]])), }, FinalityProofFragment { block: header(4).hash(), justification: TestJustification(true, vec![8]).encode(), diff --git a/core/finality-grandpa/src/import.rs b/core/finality-grandpa/src/import.rs index bb548cd8381cf3d3964a335f93b30533f269f36f..8fbe0791e8c058132e7c091f623b8162dadfc47e 100644 --- a/core/finality-grandpa/src/import.rs +++ b/core/finality-grandpa/src/import.rs @@ -24,19 +24,17 @@ use parking_lot::RwLockWriteGuard; use client::{blockchain, CallExecutor, Client, well_known_cache_keys}; use client::blockchain::HeaderBackend; use client::backend::Backend; -use client::runtime_api::ApiExt; use client::utils::is_descendent_of; use consensus_common::{ BlockImport, Error as ConsensusError, - BlockImportParams, ImportResult, JustificationImport, - SelectChain, import_queue::CacheKeyId, + BlockCheckParams, BlockImportParams, ImportResult, JustificationImport, + SelectChain, }; -use fg_primitives::GrandpaApi; +use fg_primitives::{GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog}; use sr_primitives::Justification; -use sr_primitives::generic::BlockId; +use sr_primitives::generic::{BlockId, OpaqueDigestItemId}; use sr_primitives::traits::{ - Block as BlockT, DigestFor, - Header as HeaderT, NumberFor, ProvideRuntimeApi, + Block as BlockT, DigestFor, Header as HeaderT, NumberFor, }; use primitives::{H256, Blake2Hasher}; @@ -55,17 +53,16 @@ use crate::justification::GrandpaJustification; /// /// When using GRANDPA, the block import worker should be using this block import /// object. -pub struct GrandpaBlockImport, RA, PRA, SC> { +pub struct GrandpaBlockImport, RA, SC> { inner: Arc>, select_chain: SC, authority_set: SharedAuthoritySet>, send_voter_commands: mpsc::UnboundedSender>>, consensus_changes: SharedConsensusChanges>, - api: Arc, } -impl, RA, PRA, SC: Clone> Clone for - GrandpaBlockImport +impl, RA, SC: Clone> Clone for + GrandpaBlockImport { fn clone(&self) -> Self { GrandpaBlockImport { @@ -74,20 +71,17 @@ impl, RA, PRA, SC: Clone> Clone for authority_set: self.authority_set.clone(), send_voter_commands: self.send_voter_commands.clone(), consensus_changes: self.consensus_changes.clone(), - api: self.api.clone(), } } } -impl, RA, PRA, SC> JustificationImport - for GrandpaBlockImport where +impl, RA, SC> JustificationImport + for GrandpaBlockImport where NumberFor: grandpa::BlockNumberOps, B: Backend + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, RA: Send + Sync, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, SC: SelectChain, { type Error = ConsensusError; @@ -174,75 +168,69 @@ impl<'a, Block: 'a + BlockT> Drop for PendingSetChanges<'a, Block> { } } -impl, RA, PRA, SC> - GrandpaBlockImport +fn find_scheduled_change(header: &B::Header) + -> Option>> +{ + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + + let filter_log = |log: ConsensusLog>| match log { + ConsensusLog::ScheduledChange(change) => Some(change), + _ => None, + }; + + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) +} + +fn find_forced_change(header: &B::Header) + -> Option<(NumberFor, ScheduledChange>)> +{ + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + + let filter_log = |log: ConsensusLog>| match log { + ConsensusLog::ForcedChange(delay, change) => Some((delay, change)), + _ => None, + }; + + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) +} + +impl, RA, SC> + GrandpaBlockImport where NumberFor: grandpa::BlockNumberOps, B: Backend + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, RA: Send + Sync, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, { // check for a new authority set change. fn check_new_change(&self, header: &Block::Header, hash: Block::Hash) - -> Result>>, ConsensusError> + -> Option>> { - let at = BlockId::hash(*header.parent_hash()); - let digest = header.digest(); - - let api = self.api.runtime_api(); - // check for forced change. - { - let maybe_change = api.grandpa_forced_change( - &at, - digest, - ); - - match maybe_change { - Err(e) => match api.has_api_with::, _>(&at, |v| v >= 2) { - Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), - Ok(true) => { - // API version is high enough to support forced changes - // but got error, so it is legitimate. - return Err(ConsensusError::ClientImport(e.to_string()).into()) - }, - Ok(false) => { - // API version isn't high enough to support forced changes - }, - }, - Ok(None) => {}, - Ok(Some((median_last_finalized, change))) => return Ok(Some(PendingChange { - next_authorities: change.next_authorities, - delay: change.delay, - canon_height: *header.number(), - canon_hash: hash, - delay_kind: DelayKind::Best { median_last_finalized }, - })), - } + if let Some((median_last_finalized, change)) = find_forced_change::(header) { + return Some(PendingChange { + next_authorities: change.next_authorities, + delay: change.delay, + canon_height: *header.number(), + canon_hash: hash, + delay_kind: DelayKind::Best { median_last_finalized }, + }); } // check normal scheduled change. - { - let maybe_change = api.grandpa_pending_change( - &at, - digest, - ); - - match maybe_change { - Err(e) => Err(ConsensusError::ClientImport(e.to_string()).into()), - Ok(Some(change)) => Ok(Some(PendingChange { - next_authorities: change.next_authorities, - delay: change.delay, - canon_height: *header.number(), - canon_hash: hash, - delay_kind: DelayKind::Finalized, - })), - Ok(None) => Ok(None), - } - } + let change = find_scheduled_change::(header)?; + Some(PendingChange { + next_authorities: change.next_authorities, + delay: change.delay, + canon_height: *header.number(), + canon_hash: hash, + delay_kind: DelayKind::Finalized, + }) } fn make_authorities_changes<'a>(&'a self, block: &mut BlockImportParams, hash: Block::Hash) @@ -289,12 +277,12 @@ where let maybe_change = self.check_new_change( &block.header, hash, - )?; + ); // returns a function for checking whether a block is a descendent of another // consistent with querying client directly after importing the block. let parent_hash = *block.header.parent_hash(); - let is_descendent_of = is_descendent_of(&self.inner, Some((&hash, &parent_hash))); + let is_descendent_of = is_descendent_of(&*self.inner, Some((&hash, &parent_hash))); let mut guard = InnerGuard { guard: Some(self.authority_set.inner().write()), @@ -333,16 +321,10 @@ where // for the canon block the new authority set should start // with. we use the minimum between the median and the local // best finalized block. - - #[allow(deprecated)] - let best_finalized_number = self.inner.backend().blockchain().info() - .finalized_number; - + let best_finalized_number = self.inner.info().chain.finalized_number; let canon_number = best_finalized_number.min(median_last_finalized_number); - - #[allow(deprecated)] let canon_hash = - self.inner.backend().blockchain().header(BlockId::Number(canon_number)) + self.inner.header(&BlockId::Number(canon_number)) .map_err(|e| ConsensusError::ClientImport(e.to_string()))? .expect("the given block number is less or equal than the current best finalized number; \ current best finalized number must exist in chain; qed.") @@ -394,28 +376,27 @@ where } } -impl, RA, PRA, SC> BlockImport - for GrandpaBlockImport where +impl, RA, SC> BlockImport + for GrandpaBlockImport where NumberFor: grandpa::BlockNumberOps, B: Backend + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, RA: Send + Sync, - PRA: ProvideRuntimeApi, - PRA::Api: GrandpaApi, { type Error = ConsensusError; - fn import_block(&mut self, mut block: BlockImportParams, new_cache: HashMap>) - -> Result - { + fn import_block( + &mut self, + mut block: BlockImportParams, + new_cache: HashMap>, + ) -> Result { let hash = block.post_header().hash(); let number = block.header.number().clone(); // early exit if block already in chain, otherwise the check for // authority changes will error when trying to re-import a change block - #[allow(deprecated)] - match self.inner.backend().blockchain().status(BlockId::Hash(hash)) { + match self.inner.status(BlockId::Hash(hash)) { Ok(blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain), Ok(blockchain::BlockStatus::Unknown) => {}, Err(e) => return Err(ConsensusError::ClientImport(e.to_string()).into()), @@ -425,7 +406,7 @@ impl, RA, PRA, SC> BlockImport // we don't want to finalize on `inner.import_block` let mut justification = block.justification.take(); - let enacts_consensus_change = new_cache.contains_key(&well_known_cache_keys::AUTHORITIES); + let enacts_consensus_change = !new_cache.is_empty(); let import_result = (&*self.inner).import_block(block, new_cache); let mut imported_aux = { @@ -484,17 +465,15 @@ impl, RA, PRA, SC> BlockImport _ => {}, } - if !needs_justification && !enacts_consensus_change { - return Ok(ImportResult::Imported(imported_aux)); - } - match justification { Some(justification) => { self.import_justification(hash, number, justification, needs_justification).unwrap_or_else(|err| { - debug!(target: "finality", "Imported block #{} that enacts authority set change with \ - invalid justification: {:?}, requesting justification from peers.", number, err); - imported_aux.bad_justification = true; - imported_aux.needs_justification = true; + if needs_justification || enacts_consensus_change { + debug!(target: "finality", "Imported block #{} that enacts authority set change with \ + invalid justification: {:?}, requesting justification from peers.", number, err); + imported_aux.bad_justification = true; + imported_aux.needs_justification = true; + } }); }, None => { @@ -504,6 +483,8 @@ impl, RA, PRA, SC> BlockImport "Imported unjustified block #{} that enacts authority set change, waiting for finality for enactment.", number, ); + + imported_aux.needs_justification = true; } // we have imported block with consensus data changes, but without justification @@ -511,8 +492,6 @@ impl, RA, PRA, SC> BlockImport if enacts_consensus_change { self.consensus_changes.lock().note_change((number, hash)); } - - imported_aux.needs_justification = true; } } @@ -521,15 +500,14 @@ impl, RA, PRA, SC> BlockImport fn check_block( &mut self, - hash: Block::Hash, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - self.inner.check_block(hash, parent_hash) + self.inner.check_block(block) } } -impl, RA, PRA, SC> - GrandpaBlockImport +impl, RA, SC> + GrandpaBlockImport { pub(crate) fn new( inner: Arc>, @@ -537,21 +515,19 @@ impl, RA, PRA, SC> authority_set: SharedAuthoritySet>, send_voter_commands: mpsc::UnboundedSender>>, consensus_changes: SharedConsensusChanges>, - api: Arc, - ) -> GrandpaBlockImport { + ) -> GrandpaBlockImport { GrandpaBlockImport { inner, select_chain, authority_set, send_voter_commands, consensus_changes, - api, } } } -impl, RA, PRA, SC> - GrandpaBlockImport +impl, RA, SC> + GrandpaBlockImport where NumberFor: grandpa::BlockNumberOps, B: Backend + 'static, @@ -597,9 +573,8 @@ where info!(target: "finality", "Imported justification for block #{} that triggers \ command {}, signaling voter.", number, command); - if let Err(e) = self.send_voter_commands.unbounded_send(command) { - return Err(ConsensusError::ClientImport(e.to_string()).into()); - } + // send the command to the voter + let _ = self.send_voter_commands.unbounded_send(command); }, Err(CommandOrError::Error(e)) => { return Err(match e { diff --git a/core/finality-grandpa/src/justification.rs b/core/finality-grandpa/src/justification.rs index a6554b1e90d1b8ea3d33689061ed9fa3ebb55524..f5965df3e1228b38eea7b44d50929727872df688 100644 --- a/core/finality-grandpa/src/justification.rs +++ b/core/finality-grandpa/src/justification.rs @@ -18,7 +18,6 @@ use std::collections::{HashMap, HashSet}; use client::{CallExecutor, Client}; use client::backend::Backend; -use client::blockchain::HeaderBackend; use client::error::Error as ClientError; use codec::{Encode, Decode}; use grandpa::voter_set::VoterSet; @@ -40,7 +39,7 @@ use crate::communication; /// This is meant to be stored in the db and passed around the network to other /// nodes, and are used by syncing nodes to prove authority set handoffs. #[derive(Encode, Decode)] -pub(crate) struct GrandpaJustification { +pub struct GrandpaJustification { round: u64, pub(crate) commit: Commit, votes_ancestries: Vec, @@ -71,8 +70,7 @@ impl> GrandpaJustification { loop { if current_hash == commit.target_hash { break; } - #[allow(deprecated)] - match client.backend().blockchain().header(BlockId::Hash(current_hash))? { + match client.header(&BlockId::Hash(current_hash))? { Some(current_header) => { if *current_header.number() <= commit.target_number { return error(); diff --git a/core/finality-grandpa/src/lib.rs b/core/finality-grandpa/src/lib.rs index 5c6835e3bb4df92a0082d0e6327c164eeb49c398..0decea58117b0d9d6a90649f54b15f9e3f8f0ad6 100644 --- a/core/finality-grandpa/src/lib.rs +++ b/core/finality-grandpa/src/lib.rs @@ -22,11 +22,11 @@ //! //! # Usage //! -//! First, create a block-import wrapper with the `block_import` function. -//! The GRANDPA worker needs to be linked together with this block import object, -//! so a `LinkHalf` is returned as well. All blocks imported (from network or consensus or otherwise) -//! must pass through this wrapper, otherwise consensus is likely to break in -//! unexpected ways. +//! First, create a block-import wrapper with the `block_import` function. The +//! GRANDPA worker needs to be linked together with this block import object, so +//! a `LinkHalf` is returned as well. All blocks imported (from network or +//! consensus or otherwise) must pass through this wrapper, otherwise consensus +//! is likely to break in unexpected ways. //! //! Next, use the `LinkHalf` and a local configuration to `run_grandpa_voter`. //! This requires a `Network` implementation. The returned future should be @@ -68,7 +68,7 @@ use fg_primitives::{GrandpaApi, AuthorityPair}; use keystore::KeyStorePtr; use inherents::InherentDataProviders; use consensus_common::SelectChain; -use primitives::{H256, Blake2Hasher}; +use primitives::{H256, Blake2Hasher, Pair}; use substrate_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG, CONSENSUS_WARN}; use serde_json; @@ -92,23 +92,23 @@ mod justification; mod light_import; mod observer; mod until_imported; +mod voting_rule; -#[cfg(feature="service-integration")] -mod service_integration; -#[cfg(feature="service-integration")] -pub use service_integration::{LinkHalfForService, BlockImportForService, BlockImportForLightService}; pub use communication::Network; pub use finality_proof::FinalityProofProvider; +pub use justification::GrandpaJustification; pub use light_import::light_block_import; pub use observer::run_grandpa_observer; +pub use voting_rule::{ + BeforeBestBlock, ThreeQuartersOfTheUnfinalizedChain, VotingRule, VotingRulesBuilder +}; use aux_schema::PersistentData; -use environment::{Environment, SharedVoterSetState, VoterSetState}; +use environment::{Environment, VoterSetState}; use import::GrandpaBlockImport; use until_imported::UntilGlobalMessageBlocksImported; use communication::NetworkBridge; -use service::TelemetryOnConnect; -use fg_primitives::AuthoritySignature; +use fg_primitives::{AuthoritySignature, SetId, AuthorityWeight}; // Re-export these two because it's just so damn convenient. pub use fg_primitives::{AuthorityId, ScheduledChange}; @@ -201,6 +201,13 @@ pub struct Config { /// at least every justification_period blocks. There are some other events which might cause /// justification generation. pub justification_period: u32, + /// Whether the GRANDPA observer protocol is live on the network and thereby + /// a full-node not running as a validator is running the GRANDPA observer + /// protocol (we will only issue catch-up requests to authorities when the + /// observer protocol is enabled). + pub observer_enabled: bool, + /// Whether the node is running as an authority (i.e. running the full GRANDPA protocol). + pub is_authority: bool, /// Some local identifier of the voter. pub name: Option, /// The keystore that manages the keys of this node. @@ -243,7 +250,7 @@ impl From for Error { } /// Something which can determine if a block is known. -pub trait BlockStatus { +pub(crate) trait BlockStatus { /// Return `Ok(Some(number))` or `Ok(None)` depending on whether the block /// is definitely known and has been imported. /// If an unexpected error occurs, return that. @@ -262,13 +269,33 @@ impl, RA> BlockStatus for Arc { + /// Notifies the sync service to try and sync the given block from the given + /// peers. + /// + /// If the given vector of peers is empty then the underlying implementation + /// should make a best effort to fetch the block from any peers it is + /// connected to (NOTE: this assumption will change in the future #3629). + fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor); +} + +impl BlockSyncRequester for NetworkBridge where + Block: BlockT, + N: communication::Network, +{ + fn set_sync_fork_request(&self, peers: Vec, hash: Block::Hash, number: NumberFor) { + NetworkBridge::set_sync_fork_request(self, peers, hash, number) + } +} + /// A new authority set along with the canonical block it changed at. #[derive(Debug)] pub(crate) struct NewAuthoritySet { pub(crate) canon_number: N, pub(crate) canon_hash: H, - pub(crate) set_id: u64, - pub(crate) authorities: Vec<(AuthorityId, u64)>, + pub(crate) set_id: SetId, + pub(crate) authorities: Vec<(AuthorityId, AuthorityWeight)>, } /// Commands issued to the voter. @@ -344,10 +371,10 @@ pub struct LinkHalf, RA, SC> { /// to it. pub fn block_import, RA, PRA, SC>( client: Arc>, - api: Arc, + api: &PRA, select_chain: SC, ) -> Result<( - GrandpaBlockImport, + GrandpaBlockImport, LinkHalf ), ClientError> where @@ -364,8 +391,7 @@ where let genesis_hash = chain_info.chain.genesis_hash; let persistent_data = aux_schema::load_persistent( - #[allow(deprecated)] - &**client.backend(), + &*client, genesis_hash, >::zero(), || { @@ -387,7 +413,6 @@ where persistent_data.authority_set.clone(), voter_commands_tx, persistent_data.consensus_changes.clone(), - api, ), LinkHalf { client, @@ -399,7 +424,7 @@ where } fn global_communication, B, E, N, RA>( - set_id: u64, + set_id: SetId, voters: &Arc>, client: &Arc>, network: &NetworkBridge, @@ -432,8 +457,10 @@ fn global_communication, B, E, N, RA>( // block commit and catch up messages until relevant blocks are imported. let global_in = UntilGlobalMessageBlocksImported::new( client.import_notification_stream(), + network.clone(), client.clone(), global_in, + "global", ); let global_in = global_in.map_err(CommandOrError::from); @@ -457,7 +484,7 @@ fn register_finality_tracker_inherent_data_provider ?info.finalized_number, "finalized_hash" => ?info.finalized_hash, @@ -472,7 +499,7 @@ fn register_finality_tracker_inherent_data_provider, N, RA, SC, X> { +pub struct GrandpaParams, N, RA, SC, VR, X> { /// Configuration for the GRANDPA service. pub config: Config, /// A link to the block import worker. @@ -484,13 +511,15 @@ pub struct GrandpaParams, N, RA, SC, X> { /// Handle to a future that will resolve on exit. pub on_exit: X, /// If supplied, can be used to hook on telemetry connection established events. - pub telemetry_on_connect: Option, + pub telemetry_on_connect: Option>, + /// A voting rule used to potentially restrict target votes. + pub voting_rule: VR, } /// Run a GRANDPA voter as a task. Provide configuration and a link to a /// block import worker that has already been instantiated with `block_import`. -pub fn run_grandpa_voter, N, RA, SC, X>( - grandpa_params: GrandpaParams, +pub fn run_grandpa_voter, N, RA, SC, VR, X>( + grandpa_params: GrandpaParams, ) -> client::error::Result + Send + 'static> where Block::Hash: Ord, B: Backend + 'static, @@ -498,6 +527,7 @@ pub fn run_grandpa_voter, N, RA, SC, X>( N: Network + Send + Sync + 'static, N::In: Send + 'static, SC: SelectChain + 'static, + VR: VotingRule> + Clone + 'static, NumberFor: BlockNumberOps, DigestFor: Encode, RA: Send + Sync + 'static, @@ -510,10 +540,9 @@ pub fn run_grandpa_voter, N, RA, SC, X>( inherent_data_providers, on_exit, telemetry_on_connect, + voting_rule, } = grandpa_params; - use futures::future::{self, Loop as FutureLoop}; - let LinkHalf { client, select_chain, @@ -521,31 +550,34 @@ pub fn run_grandpa_voter, N, RA, SC, X>( voter_commands_rx, } = link; - let PersistentData { authority_set, set_state, consensus_changes } = persistent_data; - let (network, network_startup) = NetworkBridge::new( network, config.clone(), - set_state.clone(), + persistent_data.set_state.clone(), on_exit.clone(), ); register_finality_tracker_inherent_data_provider(client.clone(), &inherent_data_providers)?; + let conf = config.clone(); let telemetry_task = if let Some(telemetry_on_connect) = telemetry_on_connect { - let authorities = authority_set.clone(); - let events = telemetry_on_connect.telemetry_connection_sinks + let authorities = persistent_data.authority_set.clone(); + let events = telemetry_on_connect .for_each(move |_| { + let curr = authorities.current_authorities(); + let mut auths = curr.voters().into_iter().map(|(p, _)| p); + let maybe_authority_id = authority_id(&mut auths, &conf.keystore) + .unwrap_or(Default::default()); + telemetry!(CONSENSUS_INFO; "afg.authority_set"; - "authority_set_id" => ?authorities.set_id(), - "authorities" => { - let curr = authorities.current_authorities(); - let voters = curr.voters(); - let authorities: Vec = - voters.iter().map(|(id, _)| id.to_string()).collect(); + "authority_id" => maybe_authority_id.to_string(), + "authority_set_id" => ?authorities.set_id(), + "authorities" => { + let authorities: Vec = curr.voters() + .iter().map(|(id, _)| id.to_string()).collect(); serde_json::to_string(&authorities) .expect("authorities is always at least an empty vector; elements are always of type string") - } + } ); Ok(()) }) @@ -555,176 +587,272 @@ pub fn run_grandpa_voter, N, RA, SC, X>( futures::future::Either::B(futures::future::empty()) }; - let voters = authority_set.current_authorities(); - let initial_environment = Arc::new(Environment { - inner: client.clone(), - config: config.clone(), - select_chain: select_chain.clone(), - voters: Arc::new(voters), - network: network.clone(), - set_id: authority_set.set_id(), - authority_set: authority_set.clone(), - consensus_changes: consensus_changes.clone(), - voter_set_state: set_state.clone(), - }); - - let initial_state = (initial_environment, voter_commands_rx.into_future()); - let voter_work = future::loop_fn(initial_state, move |params| { - let (env, voter_commands_rx) = params; - debug!(target: "afg", "{}: Starting new voter with set ID {}", config.name(), env.set_id); + let voter_work = VoterWork::new( + client, + config, + network, + select_chain, + voting_rule, + persistent_data, + voter_commands_rx, + ); + + let voter_work = voter_work + .map(|_| ()) + .map_err(|e| { + error!("GRANDPA Voter failed: {:?}", e); + telemetry!(CONSENSUS_WARN; "afg.voter_failed"; "e" => ?e); + }); + + let voter_work = network_startup.and_then(move |()| voter_work); + + // Make sure that `telemetry_task` doesn't accidentally finish and kill grandpa. + let telemetry_task = telemetry_task + .then(|_| futures::future::empty::<(), ()>()); + + Ok(voter_work.select(on_exit).select2(telemetry_task).then(|_| Ok(()))) +} + +/// Future that powers the voter. +#[must_use] +struct VoterWork, RA, SC, VR> { + voter: Box>> + Send>, + env: Arc>, + voter_commands_rx: mpsc::UnboundedReceiver>>, +} + +impl VoterWork +where + Block: BlockT, + N: Network + Sync, + N::In: Send + 'static, + NumberFor: BlockNumberOps, + RA: 'static + Send + Sync, + E: CallExecutor + Send + Sync + 'static, + B: Backend + 'static, + SC: SelectChain + 'static, + VR: VotingRule> + Clone + 'static, +{ + fn new( + client: Arc>, + config: Config, + network: NetworkBridge, + select_chain: SC, + voting_rule: VR, + persistent_data: PersistentData, + voter_commands_rx: mpsc::UnboundedReceiver>>, + ) -> Self { + + let voters = persistent_data.authority_set.current_authorities(); + let env = Arc::new(Environment { + client, + select_chain, + voting_rule, + voters: Arc::new(voters), + config, + network, + set_id: persistent_data.authority_set.set_id(), + authority_set: persistent_data.authority_set.clone(), + consensus_changes: persistent_data.consensus_changes.clone(), + voter_set_state: persistent_data.set_state.clone(), + }); + + let mut work = VoterWork { + // `voter` is set to a temporary value and replaced below when + // calling `rebuild_voter`. + voter: Box::new(futures::empty()) as Box<_>, + env, + voter_commands_rx, + }; + work.rebuild_voter(); + work + } + + /// Rebuilds the `self.voter` field using the current authority set + /// state. This method should be called when we know that the authority set + /// has changed (e.g. as signalled by a voter command). + fn rebuild_voter(&mut self) { + debug!(target: "afg", "{}: Starting new voter with set ID {}", self.env.config.name(), self.env.set_id); + + let authority_id = is_voter(&self.env.voters, &self.env.config.keystore) + .map(|ap| ap.public()) + .unwrap_or(Default::default()); + telemetry!(CONSENSUS_DEBUG; "afg.starting_new_voter"; - "name" => ?config.name(), "set_id" => ?env.set_id + "name" => ?self.env.config.name(), + "set_id" => ?self.env.set_id, + "authority_id" => authority_id.to_string(), ); - let mut maybe_voter = match &*env.voter_set_state.read() { - VoterSetState::Live { completed_rounds, .. } => { - let chain_info = client.info(); + let chain_info = self.env.client.info(); + telemetry!(CONSENSUS_INFO; "afg.authority_set"; + "number" => ?chain_info.chain.finalized_number, + "hash" => ?chain_info.chain.finalized_hash, + "authority_id" => authority_id.to_string(), + "authority_set_id" => ?self.env.set_id, + "authorities" => { + let authorities: Vec = self.env.voters.voters() + .iter().map(|(id, _)| id.to_string()).collect(); + serde_json::to_string(&authorities) + .expect("authorities is always at least an empty vector; elements are always of type string") + }, + ); + match &*self.env.voter_set_state.read() { + VoterSetState::Live { completed_rounds, .. } => { let last_finalized = ( chain_info.chain.finalized_hash, chain_info.chain.finalized_number, ); let global_comms = global_communication( - env.set_id, - &env.voters, - &client, - &network, - &config.keystore, + self.env.set_id, + &self.env.voters, + &self.env.client, + &self.env.network, + &self.env.config.keystore, ); let last_completed_round = completed_rounds.last(); - Some(voter::Voter::new( - env.clone(), - (*env.voters).clone(), + let voter = voter::Voter::new( + self.env.clone(), + (*self.env.voters).clone(), global_comms, last_completed_round.number, last_completed_round.state.clone(), last_finalized, - )) + ); + + self.voter = Box::new(voter); }, - VoterSetState::Paused { .. } => None, + VoterSetState::Paused { .. } => + self.voter = Box::new(futures::empty()), }; + } - // needs to be combined with another future otherwise it can deadlock. - let poll_voter = future::poll_fn(move || match maybe_voter { - Some(ref mut voter) => voter.poll(), - None => Ok(Async::NotReady), - }); - - let client = client.clone(); - let config = config.clone(); - let network = network.clone(); - let select_chain = select_chain.clone(); - let authority_set = authority_set.clone(); - let consensus_changes = consensus_changes.clone(); - - let handle_voter_command = move |command: VoterCommand<_, _>, voter_commands_rx| { - match command { - VoterCommand::ChangeAuthorities(new) => { - let voters: Vec = new.authorities.iter().map(move |(a, _)| { - format!("{}", a) - }).collect(); - telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; - "number" => ?new.canon_number, - "hash" => ?new.canon_hash, - "voters" => ?voters, - "set_id" => ?new.set_id, - ); + fn handle_voter_command( + &mut self, + command: VoterCommand> + ) -> Result<(), Error> { + match command { + VoterCommand::ChangeAuthorities(new) => { + let voters: Vec = new.authorities.iter().map(move |(a, _)| { + format!("{}", a) + }).collect(); + telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities"; + "number" => ?new.canon_number, + "hash" => ?new.canon_hash, + "voters" => ?voters, + "set_id" => ?new.set_id, + ); + self.env.update_voter_set_state(|_| { // start the new authority set using the block where the // set changed (not where the signal happened!) as the base. let set_state = VoterSetState::live( new.set_id, - &*authority_set.inner().read(), + &*self.env.authority_set.inner().read(), (new.canon_hash, new.canon_number), ); - #[allow(deprecated)] - aux_schema::write_voter_set_state(&**client.backend(), &set_state)?; - - let set_state: SharedVoterSetState<_> = set_state.into(); + aux_schema::write_voter_set_state(&*self.env.client, &set_state)?; + Ok(Some(set_state)) + })?; + + self.env = Arc::new(Environment { + voters: Arc::new(new.authorities.into_iter().collect()), + set_id: new.set_id, + voter_set_state: self.env.voter_set_state.clone(), + // Fields below are simply transferred and not updated. + client: self.env.client.clone(), + select_chain: self.env.select_chain.clone(), + config: self.env.config.clone(), + authority_set: self.env.authority_set.clone(), + consensus_changes: self.env.consensus_changes.clone(), + network: self.env.network.clone(), + voting_rule: self.env.voting_rule.clone(), + }); + + self.rebuild_voter(); + Ok(()) + } + VoterCommand::Pause(reason) => { + info!(target: "afg", "Pausing old validator set: {}", reason); - let env = Arc::new(Environment { - inner: client, - select_chain, - config, - voters: Arc::new(new.authorities.into_iter().collect()), - set_id: new.set_id, - network, - authority_set, - consensus_changes, - voter_set_state: set_state, - }); + // not racing because old voter is shut down. + self.env.update_voter_set_state(|voter_set_state| { + let completed_rounds = voter_set_state.completed_rounds(); + let set_state = VoterSetState::Paused { completed_rounds }; - Ok(FutureLoop::Continue((env, voter_commands_rx))) - } - VoterCommand::Pause(reason) => { - info!(target: "afg", "Pausing old validator set: {}", reason); + aux_schema::write_voter_set_state(&*self.env.client, &set_state)?; + Ok(Some(set_state)) + })?; - // not racing because old voter is shut down. - env.update_voter_set_state(|voter_set_state| { - let completed_rounds = voter_set_state.completed_rounds(); - let set_state = VoterSetState::Paused { completed_rounds }; + self.rebuild_voter(); + Ok(()) + } + } + } +} - #[allow(deprecated)] - aux_schema::write_voter_set_state(&**client.backend(), &set_state)?; - Ok(Some(set_state)) - })?; +impl Future for VoterWork +where + Block: BlockT, + N: Network + Sync, + N::In: Send + 'static, + NumberFor: BlockNumberOps, + RA: 'static + Send + Sync, + E: CallExecutor + Send + Sync + 'static, + B: Backend + 'static, + SC: SelectChain + 'static, + VR: VotingRule> + Clone + 'static, +{ + type Item = (); + type Error = Error; - Ok(FutureLoop::Continue((env, voter_commands_rx))) - }, + fn poll(&mut self) -> Poll { + match self.voter.poll() { + Ok(Async::NotReady) => {} + Ok(Async::Ready(())) => { + // voters don't conclude naturally + return Err(Error::Safety("GRANDPA voter has concluded.".into())) } - }; + Err(CommandOrError::Error(e)) => { + // return inner observer error + return Err(e) + } + Err(CommandOrError::VoterCommand(command)) => { + // some command issued internally + self.handle_voter_command(command)?; + futures::task::current().notify(); + } + } - poll_voter.select2(voter_commands_rx).then(move |res| match res { - Ok(future::Either::A(((), _))) => { - // voters don't conclude naturally - Err(Error::Safety("GRANDPA voter has concluded.".into())) - }, - Err(future::Either::B(_)) => { + match self.voter_commands_rx.poll() { + Ok(Async::NotReady) => {} + Err(_) => { // the `voter_commands_rx` stream should not fail. - Ok(FutureLoop::Break(())) - }, - Ok(future::Either::B(((None, _), _))) => { + return Ok(Async::Ready(())) + } + Ok(Async::Ready(None)) => { // the `voter_commands_rx` stream should never conclude since it's never closed. - Ok(FutureLoop::Break(())) - }, - Err(future::Either::A((CommandOrError::Error(e), _))) => { - // return inner voter error - Err(e) + return Ok(Async::Ready(())) } - Ok(future::Either::B(((Some(command), voter_commands_rx), _))) => { - // some command issued externally. - handle_voter_command(command, voter_commands_rx.into_future()) + Ok(Async::Ready(Some(command))) => { + // some command issued externally + self.handle_voter_command(command)?; + futures::task::current().notify(); } - Err(future::Either::A((CommandOrError::VoterCommand(command), voter_commands_rx))) => { - // some command issued internally. - handle_voter_command(command, voter_commands_rx) - }, - }) - }); - - let voter_work = voter_work - .map(|_| ()) - .map_err(|e| { - error!("GRANDPA Voter failed: {:?}", e); - telemetry!(CONSENSUS_WARN; "afg.voter_failed"; "e" => ?e); - }); - - let voter_work = network_startup.and_then(move |()| voter_work); - - // Make sure that `telemetry_task` doesn't accidentally finish and kill grandpa. - let telemetry_task = telemetry_task - .then(|_| futures::future::empty::<(), ()>()); + } - Ok(voter_work.select(on_exit).select2(telemetry_task).then(|_| Ok(()))) + Ok(Async::NotReady) + } } -#[deprecated(since = "1.1", note = "Please switch to run_grandpa_voter.")] -pub fn run_grandpa, N, RA, SC, X>( - grandpa_params: GrandpaParams, +#[deprecated(since = "1.1.0", note = "Please switch to run_grandpa_voter.")] +pub fn run_grandpa, N, RA, SC, VR, X>( + grandpa_params: GrandpaParams, ) -> ::client::error::Result + Send + 'static> where Block::Hash: Ord, B: Backend + 'static, @@ -735,6 +863,7 @@ pub fn run_grandpa, N, RA, SC, X>( NumberFor: BlockNumberOps, DigestFor: Encode, RA: Send + Sync + 'static, + VR: VotingRule> + Clone + 'static, X: Future + Clone + Send + 'static, { run_grandpa_voter(grandpa_params) @@ -780,3 +909,23 @@ fn is_voter( None => None, } } + +/// Returns the authority id of this node, if available. +fn authority_id<'a, I>( + authorities: &mut I, + keystore: &Option, +) -> Option where + I: Iterator, +{ + match keystore { + Some(keystore) => { + authorities + .find_map(|p| { + keystore.read().key_pair::(&p) + .ok() + .map(|ap| ap.public()) + }) + } + None => None, + } +} diff --git a/core/finality-grandpa/src/light_import.rs b/core/finality-grandpa/src/light_import.rs index b92374a54e171b3f5df0418f6e0322c935a98341..30af3a06d3f760fb405900b418be582b2bc17072 100644 --- a/core/finality-grandpa/src/light_import.rs +++ b/core/finality-grandpa/src/light_import.rs @@ -21,7 +21,7 @@ use parking_lot::RwLock; use client::{ CallExecutor, Client, - backend::{AuxStore, Backend}, + backend::{AuxStore, Backend, Finalizer}, blockchain::HeaderBackend, error::Error as ClientError, well_known_cache_keys, @@ -30,14 +30,14 @@ use codec::{Encode, Decode}; use consensus_common::{ import_queue::Verifier, BlockOrigin, BlockImport, FinalityProofImport, BlockImportParams, ImportResult, ImportedAux, - Error as ConsensusError, + BlockCheckParams, Error as ConsensusError, }; use network::config::{BoxFinalityProofRequestBuilder, FinalityProofRequestBuilder}; use sr_primitives::Justification; use sr_primitives::traits::{ NumberFor, Block as BlockT, Header as HeaderT, ProvideRuntimeApi, DigestFor, }; -use fg_primitives::{GrandpaApi, AuthorityId}; +use fg_primitives::{self, GrandpaApi, AuthorityId}; use sr_primitives::generic::BlockId; use primitives::{H256, Blake2Hasher}; @@ -55,6 +55,7 @@ const LIGHT_CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; /// Create light block importer. pub fn light_block_import, RA, PRA>( client: Arc>, + backend: Arc, authority_set_provider: Arc>, api: Arc, ) -> Result, ClientError> @@ -66,10 +67,10 @@ pub fn light_block_import, RA, PRA>( PRA::Api: GrandpaApi, { let info = client.info(); - #[allow(deprecated)] - let import_data = load_aux_import_data(info.chain.finalized_hash, &**client.backend(), api)?; + let import_data = load_aux_import_data(info.chain.finalized_hash, &*client, api)?; Ok(GrandpaLightBlockImport { client, + backend, authority_set_provider, data: Arc::new(RwLock::new(import_data)), }) @@ -82,6 +83,7 @@ pub fn light_block_import, RA, PRA>( /// - fetching finality proofs for blocks that are enacting consensus changes. pub struct GrandpaLightBlockImport, RA> { client: Arc>, + backend: Arc, authority_set_provider: Arc>, data: Arc>>, } @@ -90,6 +92,7 @@ impl, RA> Clone for GrandpaLightBlockImport Self { GrandpaLightBlockImport { client: self.client.clone(), + backend: self.backend.clone(), authority_set_provider: self.authority_set_provider.clone(), data: self.data.clone(), } @@ -132,17 +135,16 @@ impl, RA> BlockImport block: BlockImportParams, new_cache: HashMap>, ) -> Result { - do_import_block::<_, _, _, _, GrandpaJustification>( + do_import_block::<_, _, _, GrandpaJustification>( &*self.client, &mut *self.data.write(), block, new_cache ) } fn check_block( &mut self, - hash: Block::Hash, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - self.client.check_block(hash, parent_hash) + self.client.check_block(block) } } @@ -177,8 +179,9 @@ impl, RA> FinalityProofImport finality_proof: Vec, verifier: &mut dyn Verifier, ) -> Result<(Block::Hash, NumberFor), Self::Error> { - do_import_finality_proof::<_, _, _, _, GrandpaJustification>( + do_import_finality_proof::<_, _, _, GrandpaJustification>( &*self.client, + self.backend.clone(), &*self.authority_set_provider, &mut *self.data.write(), hash, @@ -193,7 +196,7 @@ impl LightAuthoritySet { /// Get a genesis set with given authorities. pub fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self { LightAuthoritySet { - set_id: 0, + set_id: fg_primitives::SetId::default(), authorities: initial, } } @@ -228,16 +231,19 @@ impl> FinalityProofRequestBuilder for GrandpaFinalityPro } /// Try to import new block. -fn do_import_block, RA, J>( - mut client: &Client, +fn do_import_block, J>( + mut client: C, data: &mut LightImportData, mut block: BlockImportParams, new_cache: HashMap>, ) -> Result where + C: HeaderBackend + + AuxStore + + Finalizer + + BlockImport + + Clone, B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, NumberFor: grandpa::BlockNumberOps, DigestFor: Encode, J: ProvableJustification, @@ -247,8 +253,8 @@ fn do_import_block, RA, J>( // we don't want to finalize on `inner.import_block` let justification = block.justification.take(); - let enacts_consensus_change = new_cache.contains_key(&well_known_cache_keys::AUTHORITIES); - let import_result = BlockImport::import_block(&mut client, block, new_cache); + let enacts_consensus_change = !new_cache.is_empty(); + let import_result = client.import_block(block, new_cache); let mut imported_aux = match import_result { Ok(ImportResult::Imported(aux)) => aux, @@ -265,7 +271,7 @@ fn do_import_block, RA, J>( hash, ); - do_import_justification::<_, _, _, _, J>(client, data, hash, number, justification) + do_import_justification::<_, _, _, J>(client, data, hash, number, justification) }, None if enacts_consensus_change => { trace!( @@ -284,8 +290,9 @@ fn do_import_block, RA, J>( } /// Try to import finality proof. -fn do_import_finality_proof, RA, J>( - client: &Client, +fn do_import_finality_proof, J>( + client: C, + backend: Arc, authority_set_provider: &dyn AuthoritySetForFinalityChecker, data: &mut LightImportData, _hash: Block::Hash, @@ -294,9 +301,12 @@ fn do_import_finality_proof, RA, J>( verifier: &mut dyn Verifier, ) -> Result<(Block::Hash, NumberFor), ConsensusError> where + C: HeaderBackend + + AuxStore + + Finalizer + + BlockImport + + Clone, B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, DigestFor: Encode, NumberFor: grandpa::BlockNumberOps, J: ProvableJustification, @@ -304,8 +314,7 @@ fn do_import_finality_proof, RA, J>( let authority_set_id = data.authority_set.set_id(); let authorities = data.authority_set.authorities(); let finality_effects = crate::finality_proof::check_finality_proof( - #[allow(deprecated)] - &*client.backend().blockchain(), + backend.blockchain(), authority_set_id, authorities, authority_set_provider, @@ -323,13 +332,12 @@ fn do_import_finality_proof, RA, J>( if let Some(authorities) = new_authorities { cache.insert(well_known_cache_keys::AUTHORITIES, authorities.encode()); } - do_import_block::<_, _, _, _, J>(client, data, block_to_import, cache)?; + do_import_block::<_, _, _, J>(client.clone(), data, block_to_import, cache)?; } // try to import latest justification let finalized_block_hash = finality_effects.block; - #[allow(deprecated)] - let finalized_block_number = client.backend().blockchain() + let finalized_block_number = backend.blockchain() .expect_block_number_from_id(&BlockId::Hash(finality_effects.block)) .map_err(|e| ConsensusError::ClientImport(e.to_string()))?; do_finalize_block( @@ -350,17 +358,19 @@ fn do_import_finality_proof, RA, J>( } /// Try to import justification. -fn do_import_justification, RA, J>( - client: &Client, +fn do_import_justification, J>( + client: C, data: &mut LightImportData, hash: Block::Hash, number: NumberFor, justification: Justification, ) -> Result where + C: HeaderBackend + + AuxStore + + Finalizer + + Clone, B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, NumberFor: grandpa::BlockNumberOps, J: ProvableJustification, { @@ -419,17 +429,19 @@ fn do_import_justification, RA, J>( } /// Finalize the block. -fn do_finalize_block, RA>( - client: &Client, +fn do_finalize_block>( + client: C, data: &mut LightImportData, hash: Block::Hash, number: NumberFor, justification: Justification, ) -> Result where + C: HeaderBackend + + AuxStore + + Finalizer + + Clone, B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, - RA: Send + Sync, NumberFor: grandpa::BlockNumberOps, { // finalize the block @@ -440,7 +452,7 @@ fn do_finalize_block, RA>( // forget obsoleted consensus changes let consensus_finalization_res = data.consensus_changes - .finalize((number, hash), |at_height| canonical_at_height(&client, (hash, number), true, at_height)); + .finalize((number, hash), |at_height| canonical_at_height(client.clone(), (hash, number), true, at_height)); match consensus_finalization_res { Ok((true, _)) => require_insert_aux( &client, @@ -455,7 +467,8 @@ fn do_finalize_block, RA>( // update last finalized block reference data.last_finalized = hash; - Ok(ImportResult::imported()) + // we just finalized this block, so if we were importing it, it is now the new best + Ok(ImportResult::imported(true)) } /// Load light import aux data from the store. @@ -507,20 +520,14 @@ fn load_aux_import_data, PRA>( } /// Insert into aux store. If failed, return error && show inconsistency warning. -fn require_insert_aux, RA>( - client: &Client, +fn require_insert_aux( + store: &A, key: &[u8], value: &T, value_type: &str, -) -> Result<(), ConsensusError> - where - B: Backend + 'static, - E: CallExecutor + 'static + Clone + Send + Sync, -{ - #[allow(deprecated)] - let backend = &**client.backend(); +) -> Result<(), ConsensusError> { let encoded = value.encode(); - let update_res = Backend::insert_aux(backend, &[(key, &encoded[..])], &[]); + let update_res = store.insert_aux(&[(key, &encoded[..])], &[]); if let Err(error) = update_res { return Err(on_post_finalization_error(error, value_type)); } @@ -583,10 +590,9 @@ pub mod tests { fn check_block( &mut self, - hash: Block::Hash, - parent_hash: Block::Hash, + block: BlockCheckParams, ) -> Result { - self.0.check_block(hash, parent_hash) + self.0.check_block(block) } } @@ -618,6 +624,7 @@ pub mod tests { /// Creates light block import that ignores justifications that came outside of finality proofs. pub fn light_block_import_without_justifications, RA, PRA>( client: Arc>, + backend: Arc, authority_set_provider: Arc>, api: Arc, ) -> Result, ClientError> @@ -628,14 +635,14 @@ pub mod tests { PRA: ProvideRuntimeApi, PRA::Api: GrandpaApi, { - light_block_import(client, authority_set_provider, api).map(NoJustificationsImport) + light_block_import(client, backend, authority_set_provider, api).map(NoJustificationsImport) } fn import_block( new_cache: HashMap>, justification: Option, ) -> ImportResult { - let client = test_client::new_light(); + let (client, _backend) = test_client::new_light(); let mut import_data = LightImportData { last_finalized: Default::default(), authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_slice(&[1; 32]), 1)]), @@ -657,7 +664,7 @@ pub mod tests { auxiliary: Vec::new(), fork_choice: ForkChoiceStrategy::LongestChain, }; - do_import_block::<_, _, _, _, TestJustification>( + do_import_block::<_, _, _, TestJustification>( &client, &mut import_data, block, @@ -672,6 +679,7 @@ pub mod tests { needs_justification: false, bad_justification: false, needs_finality_proof: false, + is_new_best: true, })); } @@ -683,6 +691,7 @@ pub mod tests { needs_justification: false, bad_justification: false, needs_finality_proof: false, + is_new_best: true, })); } @@ -695,6 +704,7 @@ pub mod tests { needs_justification: false, bad_justification: false, needs_finality_proof: true, + is_new_best: true, })); } @@ -710,6 +720,7 @@ pub mod tests { needs_justification: false, bad_justification: false, needs_finality_proof: true, + is_new_best: false, }, )); } diff --git a/core/finality-grandpa/src/observer.rs b/core/finality-grandpa/src/observer.rs index bce292262e028792aeb5a02a2796e052b3a45ef2..e4d90ddc22e77b658a1cca8478bd509bbe788c52 100644 --- a/core/finality-grandpa/src/observer.rs +++ b/core/finality-grandpa/src/observer.rs @@ -175,8 +175,9 @@ pub fn run_grandpa_observer, N, RA, SC>( network, config.clone(), persistent_data.set_state.clone(), - on_exit.clone() + on_exit.clone(), ); + let observer_work = ObserverWork::new( client, network, @@ -299,8 +300,7 @@ where let completed_rounds = self.persistent_data.set_state.read().completed_rounds(); let set_state = VoterSetState::Paused { completed_rounds }; - #[allow(deprecated)] - crate::aux_schema::write_voter_set_state(&**self.client.backend(), &set_state)?; + crate::aux_schema::write_voter_set_state(&*self.client, &set_state)?; set_state }, @@ -313,8 +313,7 @@ where (new.canon_hash, new.canon_number), ); - #[allow(deprecated)] - crate::aux_schema::write_voter_set_state(&**self.client.backend(), &set_state)?; + crate::aux_schema::write_voter_set_state(&*self.client, &set_state)?; set_state }, diff --git a/core/finality-grandpa/src/service_integration.rs b/core/finality-grandpa/src/service_integration.rs deleted file mode 100644 index 9f19b9204190bdcc16f3766db3c20a400ed40331..0000000000000000000000000000000000000000 --- a/core/finality-grandpa/src/service_integration.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -/// Integrate grandpa finality with substrate service - -use client; -use service::{FullBackend, FullExecutor, LightBackend, LightExecutor, ServiceFactory}; - -pub type BlockImportForService = crate::GrandpaBlockImport< - FullBackend, - FullExecutor, - ::Block, - ::RuntimeApi, - client::Client< - FullBackend, - FullExecutor, - ::Block, - ::RuntimeApi - >, - ::SelectChain, ->; - -pub type LinkHalfForService = crate::LinkHalf< - FullBackend, - FullExecutor, - ::Block, - ::RuntimeApi, - ::SelectChain ->; - -pub type BlockImportForLightService = crate::light_import::GrandpaLightBlockImport< - LightBackend, - LightExecutor, - ::Block, - ::RuntimeApi, ->; diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs index bbaae1e9b7e018929cb55c367327e35a97818d3c..2339379a609d480de4c76b4205b474bd774907ef 100644 --- a/core/finality-grandpa/src/tests.rs +++ b/core/finality-grandpa/src/tests.rs @@ -27,7 +27,7 @@ use tokio::runtime::current_thread; use keyring::Ed25519Keyring; use client::{ error::Result, - runtime_api::{Core, RuntimeVersion, ApiExt}, + runtime_api::{Core, RuntimeVersion, ApiExt, StorageProof}, LongestChain, }; use test_client::{self, runtime::BlockNumber}; @@ -37,9 +37,10 @@ use std::collections::{HashMap, HashSet}; use std::result; use codec::Decode; use sr_primitives::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT}; -use sr_primitives::generic::BlockId; +use sr_primitives::generic::{BlockId, DigestItem}; use primitives::{NativeOrEncoded, ExecutionContext, crypto::Public}; -use fg_primitives::AuthorityId; +use fg_primitives::{GRANDPA_ENGINE_ID, AuthorityId}; +use state_machine::{backend::InMemory, prove_read, read_proof_check}; use authorities::AuthoritySet; use finality_proof::{FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker}; @@ -98,7 +99,12 @@ impl TestNetFactory for GrandpaTestNet { } } - fn make_verifier(&self, _client: PeersClient, _cfg: &ProtocolConfig) -> Self::Verifier { + fn make_verifier( + &self, + _client: PeersClient, + _cfg: &ProtocolConfig, + _: &PeerData, + ) -> Self::Verifier { PassThroughVerifier(false) // use non-instant finality. } @@ -112,21 +118,17 @@ impl TestNetFactory for GrandpaTestNet { ) { match client { - PeersClient::Full(ref client) => { - #[allow(deprecated)] - let select_chain = LongestChain::new( - client.backend().clone() - ); + PeersClient::Full(ref client, ref backend) => { let (import, link) = block_import( client.clone(), - Arc::new(self.test_config.clone()), - select_chain, + &self.test_config, + LongestChain::new(backend.clone()), ).expect("Could not create block import for fresh peer."); let justification_import = Box::new(import.clone()); let block_import = Box::new(import); (block_import, Some(justification_import), None, None, Mutex::new(Some(link))) }, - PeersClient::Light(ref client) => { + PeersClient::Light(ref client, ref backend) => { use crate::light_import::tests::light_block_import_without_justifications; let authorities_provider = Arc::new(self.test_config.clone()); @@ -134,6 +136,7 @@ impl TestNetFactory for GrandpaTestNet { // => light clients will try to fetch finality proofs let import = light_block_import_without_justifications( client.clone(), + backend.clone(), authorities_provider, Arc::new(self.test_config.clone()) ).expect("Could not create block import for fresh peer."); @@ -150,11 +153,11 @@ impl TestNetFactory for GrandpaTestNet { client: PeersClient ) -> Option>> { match client { - PeersClient::Full(ref client) => { + PeersClient::Full(_, ref backend) => { let authorities_provider = Arc::new(self.test_config.clone()); - Some(Arc::new(FinalityProofProvider::new(client.clone(), authorities_provider))) + Some(Arc::new(FinalityProofProvider::new(backend.clone(), authorities_provider))) }, - PeersClient::Light(_) => None, + PeersClient::Light(_, _) => None, } } @@ -186,16 +189,12 @@ impl Future for Exit { #[derive(Default, Clone)] pub(crate) struct TestApi { genesis_authorities: Vec<(AuthorityId, u64)>, - scheduled_changes: Arc>>>, - forced_changes: Arc)>>>, } impl TestApi { pub fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self { TestApi { genesis_authorities, - scheduled_changes: Arc::new(Mutex::new(HashMap::new())), - forced_changes: Arc::new(Mutex::new(HashMap::new())), } } } @@ -260,7 +259,7 @@ impl ApiExt for RuntimeApi { unimplemented!("Not required for testing!") } - fn extract_proof(&mut self) -> Option>> { + fn extract_proof(&mut self) -> Option { unimplemented!("Not required for testing!") } } @@ -275,41 +274,6 @@ impl GrandpaApi for RuntimeApi { ) -> Result>> { Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) } - - fn GrandpaApi_grandpa_pending_change_runtime_api_impl( - &self, - at: &BlockId, - _: ExecutionContext, - _: Option<(&DigestFor)>, - _: Vec, - ) -> Result>>>> { - let parent_hash = match at { - &BlockId::Hash(at) => at, - _ => panic!("not requested by block hash!!"), - }; - - // we take only scheduled changes at given block number where there are no - // extrinsics. - Ok(self.inner.scheduled_changes.lock().get(&parent_hash).map(|c| c.clone())).map(NativeOrEncoded::Native) - } - - fn GrandpaApi_grandpa_forced_change_runtime_api_impl( - &self, - at: &BlockId, - _: ExecutionContext, - _: Option<(&DigestFor)>, - _: Vec, - ) - -> Result, ScheduledChange>)>>> { - let parent_hash = match at { - &BlockId::Hash(at) => at, - _ => panic!("not requested by block hash!!"), - }; - - // we take only scheduled changes at given block number where there are no - // extrinsics. - Ok(self.inner.forced_changes.lock().get(&parent_hash).map(|c| c.clone())).map(NativeOrEncoded::Native) - } } impl AuthoritySetForFinalityProver for TestApi { @@ -322,8 +286,14 @@ impl AuthoritySetForFinalityProver for TestApi { }) } - fn prove_authorities(&self, block: &BlockId) -> Result>> { - self.authorities(block).map(|auth| vec![auth.encode()]) + fn prove_authorities(&self, block: &BlockId) -> Result { + let authorities = self.authorities(block)?; + let backend = >::from(vec![ + (None, b"authorities".to_vec(), Some(authorities.encode())) + ]); + let proof = prove_read(backend, vec![b"authorities"]) + .expect("failure proving read from in-memory storage backend"); + Ok(proof) } } @@ -331,11 +301,20 @@ impl AuthoritySetForFinalityChecker for TestApi { fn check_authorities_proof( &self, _hash: ::Hash, - _header: ::Header, - proof: Vec>, + header: ::Header, + proof: StorageProof, ) -> Result> { - Decode::decode(&mut &proof[0][..]) - .map_err(|_| unreachable!("incorrect value is passed as GRANDPA authorities proof")) + let results = read_proof_check::( + *header.state_root(), proof, vec![b"authorities"] + ) + .expect("failure checking read proof for authorities"); + let encoded = results.get(&b"authorities"[..]) + .expect("returned map must contain all proof keys") + .as_ref() + .expect("authorities in proof is None"); + let authorities = Decode::decode(&mut &encoded[..]) + .expect("failure decoding authorities read from proof"); + Ok(authorities) } } @@ -416,12 +395,15 @@ fn run_to_completion_with( justification_period: 32, keystore: Some(keystore), name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, }, link: link, network: net_service, inherent_data_providers: InherentDataProviders::new(), on_exit: Exit, telemetry_on_connect: None, + voting_rule: (), }; let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); @@ -451,6 +433,24 @@ fn run_to_completion( run_to_completion_with(runtime, blocks, net, peers, |_| None) } +fn add_scheduled_change(block: &mut Block, change: ScheduledChange) { + block.header.digest_mut().push(DigestItem::Consensus( + GRANDPA_ENGINE_ID, + fg_primitives::ConsensusLog::ScheduledChange(change).encode(), + )); +} + +fn add_forced_change( + block: &mut Block, + median_last_finalized: BlockNumber, + change: ScheduledChange, +) { + block.header.digest_mut().push(DigestItem::Consensus( + GRANDPA_ENGINE_ID, + fg_primitives::ConsensusLog::ForcedChange(median_last_finalized, change).encode(), + )); +} + #[test] fn finalize_3_voters_no_observers() { let _ = env_logger::try_init(); @@ -529,12 +529,15 @@ fn finalize_3_voters_1_full_observer() { justification_period: 32, keystore, name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, }, link: link, network: net_service, inherent_data_providers: InherentDataProviders::new(), on_exit: Exit, telemetry_on_connect: None, + voting_rule: (), }; let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); @@ -576,7 +579,6 @@ fn transition_3_voters_twice_1_full_observer() { let genesis_voters = make_ids(peers_a); let api = TestApi::new(genesis_voters); - let transitions = api.scheduled_changes.clone(); let net = Arc::new(Mutex::new(GrandpaTestNet::new(api, 8))); let mut runtime = current_thread::Runtime::new().unwrap(); @@ -589,10 +591,7 @@ fn transition_3_voters_twice_1_full_observer() { assert_eq!(full_client.info().chain.best_number, 1, "Peer #{} failed to sync", i); - let set: AuthoritySet = crate::aux_schema::load_authorities( - #[allow(deprecated)] - &**full_client.backend() - ).unwrap(); + let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); assert_eq!(set.current(), (0, make_ids(peers_a).as_slice())); assert_eq!(set.pending_changes().count(), 0); @@ -601,10 +600,6 @@ fn transition_3_voters_twice_1_full_observer() { { let net = net.clone(); let client = net.lock().peers[0].client().clone(); - let transitions = transitions.clone(); - let add_transition = move |parent_hash, change| { - transitions.lock().insert(parent_hash, change); - }; let peers_c = peers_c.clone(); // wait for blocks to be finalized before generating new ones @@ -620,8 +615,8 @@ fn transition_3_voters_twice_1_full_observer() { 14 => { // generate transition at block 15, applied at 20. net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let block = builder.bake().unwrap(); - add_transition(*block.header.parent_hash(), ScheduledChange { + let mut block = builder.bake().unwrap(); + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(peers_b), delay: 4, }); @@ -634,8 +629,8 @@ fn transition_3_voters_twice_1_full_observer() { // at block 21 we do another transition, but this time instant. // add more until we have 30. net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let block = builder.bake().unwrap(); - add_transition(*block.header.parent_hash(), ScheduledChange { + let mut block = builder.bake().unwrap(); + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(&peers_c), delay: 0, }); @@ -685,10 +680,7 @@ fn transition_3_voters_twice_1_full_observer() { .for_each(move |_| Ok(())) .map(move |()| { let full_client = client.as_full().expect("only full clients are used in test"); - let set: AuthoritySet = crate::aux_schema::load_authorities( - #[allow(deprecated)] - &**full_client.backend() - ).unwrap(); + let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); assert_eq!(set.current(), (2, make_ids(peers_c).as_slice())); assert_eq!(set.pending_changes().count(), 0); @@ -700,12 +692,15 @@ fn transition_3_voters_twice_1_full_observer() { justification_period: 32, keystore: Some(keystore), name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, }, link: link, network: net_service, inherent_data_providers: InherentDataProviders::new(), on_exit: Exit, telemetry_on_connect: None, + voting_rule: (), }; let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network"); @@ -787,7 +782,6 @@ fn sync_justifications_on_change_blocks() { // 4 peers, 3 of them are authorities and participate in grandpa let api = TestApi::new(voters); - let transitions = api.scheduled_changes.clone(); let mut net = GrandpaTestNet::new(api, 4); // add 20 blocks @@ -795,8 +789,8 @@ fn sync_justifications_on_change_blocks() { // at block 21 we do add a transition which is instant net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let block = builder.bake().unwrap(); - transitions.lock().insert(*block.header.parent_hash(), ScheduledChange { + let mut block = builder.bake().unwrap(); + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(peers_b), delay: 0, }); @@ -849,7 +843,6 @@ fn finalizes_multiple_pending_changes_in_order() { // 6 peers, 3 of them are authorities and participate in grandpa from genesis let api = TestApi::new(genesis_voters); - let transitions = api.scheduled_changes.clone(); let mut net = GrandpaTestNet::new(api, 6); // add 20 blocks @@ -857,8 +850,8 @@ fn finalizes_multiple_pending_changes_in_order() { // at block 21 we do add a transition which is instant net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let block = builder.bake().unwrap(); - transitions.lock().insert(*block.header.parent_hash(), ScheduledChange { + let mut block = builder.bake().unwrap(); + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(peers_b), delay: 0, }); @@ -870,8 +863,8 @@ fn finalizes_multiple_pending_changes_in_order() { // at block 26 we add another which is enacted at block 30 net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| { - let block = builder.bake().unwrap(); - transitions.lock().insert(*block.header.parent_hash(), ScheduledChange { + let mut block = builder.bake().unwrap(); + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(peers_c), delay: 4, }); @@ -893,30 +886,6 @@ fn finalizes_multiple_pending_changes_in_order() { run_to_completion(&mut runtime, 30, net.clone(), all_peers); } -#[test] -fn doesnt_vote_on_the_tip_of_the_chain() { - let mut runtime = current_thread::Runtime::new().unwrap(); - let peers_a = &[Ed25519Keyring::Alice, Ed25519Keyring::Bob, Ed25519Keyring::Charlie]; - let voters = make_ids(peers_a); - let api = TestApi::new(voters); - let mut net = GrandpaTestNet::new(api, 3); - - // add 100 blocks - net.peer(0).push_blocks(100, false); - net.block_until_sync(&mut runtime); - - for i in 0..3 { - assert_eq!(net.peer(i).client().info().chain.best_number, 100, - "Peer #{} failed to sync", i); - } - - let net = Arc::new(Mutex::new(net)); - let highest = run_to_completion(&mut runtime, 75, net.clone(), peers_a); - - // the highest block to be finalized will be 3/4 deep in the unfinalized chain - assert_eq!(highest, 75); -} - #[test] fn force_change_to_new_set() { let _ = env_logger::try_init(); @@ -933,27 +902,26 @@ fn force_change_to_new_set() { let api = TestApi::new(make_ids(genesis_authorities)); let voters = make_ids(peers_a); - let normal_transitions = api.scheduled_changes.clone(); - let forced_transitions = api.forced_changes.clone(); let net = GrandpaTestNet::new(api, 3); let net = Arc::new(Mutex::new(net)); - net.lock().peer(0).push_blocks(1, false); + net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + let mut block = builder.bake().unwrap(); - { // add a forced transition at block 12. - let parent_hash = net.lock().peer(0).client().info().chain.best_hash; - forced_transitions.lock().insert(parent_hash, (0, ScheduledChange { + add_forced_change(&mut block, 0, ScheduledChange { next_authorities: voters.clone(), delay: 10, - })); + }); // add a normal transition too to ensure that forced changes take priority. - normal_transitions.lock().insert(parent_hash, ScheduledChange { + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(genesis_authorities), delay: 5, }); - } + + block + }); net.lock().peer(0).push_blocks(25, false); net.lock().block_until_sync(&mut runtime); @@ -963,10 +931,7 @@ fn force_change_to_new_set() { "Peer #{} failed to sync", i); let full_client = peer.client().as_full().expect("only full clients are used in test"); - let set: AuthoritySet = crate::aux_schema::load_authorities( - #[allow(deprecated)] - &**full_client.backend() - ).unwrap(); + let set: AuthoritySet = crate::aux_schema::load_authorities(&*full_client).unwrap(); assert_eq!(set.current(), (1, voters.as_slice())); assert_eq!(set.pending_changes().count(), 0); @@ -991,8 +956,8 @@ fn allows_reimporting_change_blocks() { let full_client = client.as_full().unwrap(); let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - let block = builder.bake().unwrap(); - api.scheduled_changes.lock().insert(*block.header.parent_hash(), ScheduledChange { + let mut block = builder.bake().unwrap(); + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(peers_b), delay: 0, }); @@ -1018,6 +983,7 @@ fn allows_reimporting_change_blocks() { clear_justification_requests: false, bad_justification: false, needs_finality_proof: false, + is_new_best: true, }), ); @@ -1040,8 +1006,9 @@ fn test_bad_justification() { let full_client = client.as_full().expect("only full clients are used in test"); let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); - let block = builder.bake().unwrap(); - api.scheduled_changes.lock().insert(*block.header.parent_hash(), ScheduledChange { + let mut block = builder.bake().unwrap(); + + add_scheduled_change(&mut block, ScheduledChange { next_authorities: make_ids(peers_b), delay: 0, }); @@ -1066,6 +1033,7 @@ fn test_bad_justification() { needs_justification: true, clear_justification_requests: false, bad_justification: true, + is_new_best: true, ..Default::default() }), ); @@ -1099,9 +1067,13 @@ fn voter_persists_its_votes() { assert_eq!(net.peer(0).client().info().chain.best_number, 20, "Peer #{} failed to sync", 0); - let client = net.peer(0).client().clone(); + + let peer = net.peer(0); + let client = peer.client().clone(); let net = Arc::new(Mutex::new(net)); + // channel between the voter and the main controller. + // sending a message on the `voter_tx` restarts the voter. let (voter_tx, voter_rx) = mpsc::unbounded::<()>(); let mut keystore_paths = Vec::new(); @@ -1110,61 +1082,82 @@ fn voter_persists_its_votes() { // channel. whenever a message is received the voter is restarted. when the // sender is dropped the voter is stopped. { - let net = net.clone(); - let client = client.clone(); - let (keystore, keystore_path) = create_keystore(peers[0]); keystore_paths.push(keystore_path); - let voter = future::loop_fn(voter_rx, move |rx| { - let (_block_import, _, _, _, link) = net.lock().make_block_import(client.clone()); - let link = link.lock().take().unwrap(); + struct ResettableVoter { + voter: Box + Send>, + voter_rx: mpsc::UnboundedReceiver<()>, + net: Arc>, + client: PeersClient, + keystore: KeyStorePtr, + } - let grandpa_params = GrandpaParams { - config: Config { - gossip_duration: TEST_GOSSIP_DURATION, - justification_period: 32, - keystore: Some(keystore.clone()), - name: Some(format!("peer#{}", 0)), - }, - link, - network: net.lock().peers[0].network_service().clone(), - inherent_data_providers: InherentDataProviders::new(), - on_exit: Exit, - telemetry_on_connect: None, - }; + impl Future for ResettableVoter { + type Item = (); + type Error = (); - let voter = run_grandpa_voter(grandpa_params) - .expect("all in order with client and network") - .then(move |r| { - // we need to keep the block_import alive since it owns the - // sender for the voter commands channel, if that gets dropped - // then the voter will stop - drop(_block_import); - r - }); - - voter.select2(rx.into_future()).then(|res| match res { - Ok(future::Either::A(x)) => { - panic!("voter stopped unexpectedly: {:?}", x); - }, - Ok(future::Either::B(((Some(()), rx), _))) => { - Ok(future::Loop::Continue(rx)) - }, - Ok(future::Either::B(((None, _), _))) => { - Ok(future::Loop::Break(())) - }, - Err(future::Either::A(err)) => { - panic!("unexpected error: {:?}", err); - }, - Err(future::Either::B(..)) => { - // voter_rx dropped, stop the voter. - Ok(future::Loop::Break(())) - }, - }) - }); + fn poll(&mut self) -> Poll { + match self.voter.poll() { + Ok(Async::Ready(())) | Err(_) => panic!("error in the voter"), + Ok(Async::NotReady) => {}, + } - runtime.spawn(voter); + match self.voter_rx.poll() { + Err(_) | Ok(Async::Ready(None)) => return Ok(Async::Ready(())), + Ok(Async::NotReady) => {} + Ok(Async::Ready(Some(()))) => { + let (_block_import, _, _, _, link) = + self.net.lock().make_block_import(self.client.clone()); + let link = link.lock().take().unwrap(); + + let grandpa_params = GrandpaParams { + config: Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: Some(self.keystore.clone()), + name: Some(format!("peer#{}", 0)), + is_authority: true, + observer_enabled: true, + }, + link, + network: self.net.lock().peers[0].network_service().clone(), + inherent_data_providers: InherentDataProviders::new(), + on_exit: Exit, + telemetry_on_connect: None, + voting_rule: VotingRulesBuilder::default().build(), + }; + + let voter = run_grandpa_voter(grandpa_params) + .expect("all in order with client and network") + .then(move |r| { + // we need to keep the block_import alive since it owns the + // sender for the voter commands channel, if that gets dropped + // then the voter will stop + drop(_block_import); + r + }); + + self.voter = Box::new(voter); + // notify current task in order to poll the voter + futures::task::current().notify(); + } + }; + + Ok(Async::NotReady) + } + } + + // we create a "dummy" voter by setting it to `empty` and triggering the `tx`. + // this way, the `ResettableVoter` will reset its `voter` field to a value ASAP. + voter_tx.unbounded_send(()).unwrap(); + runtime.spawn(ResettableVoter { + voter: Box::new(futures::future::empty()), + voter_rx, + net: net.clone(), + client: client.clone(), + keystore, + }); } let (exit_tx, exit_rx) = futures::sync::oneshot::channel::<()>(); @@ -1181,6 +1174,8 @@ fn voter_persists_its_votes() { justification_period: 32, keystore: Some(keystore), name: Some(format!("peer#{}", 1)), + is_authority: true, + observer_enabled: true, }; let set_state = { @@ -1237,9 +1232,8 @@ fn voter_persists_its_votes() { }) .for_each(|_| Ok(())) .and_then(move |_| { - #[allow(deprecated)] let block_30_hash = - net.lock().peer(0).client().as_full().unwrap().backend().blockchain().hash(30).unwrap().unwrap(); + net.lock().peer(0).client().as_full().unwrap().hash(30).unwrap().unwrap(); // we restart alice's voter voter_tx.unbounded_send(()).unwrap(); @@ -1330,6 +1324,8 @@ fn finalize_3_voters_1_light_observer() { justification_period: 32, keystore: None, name: Some("observer".to_string()), + is_authority: false, + observer_enabled: true, }, link, net.lock().peers[3].network_service().clone(), @@ -1396,20 +1392,21 @@ fn empty_finality_proof_is_returned_to_light_client_when_authority_set_is_differ let api = TestApi::new(make_ids(&genesis_authorities)); let voters = make_ids(peers_a); - let forced_transitions = api.forced_changes.clone(); let net = GrandpaTestNet::new(api, 3); let net = Arc::new(Mutex::new(net)); - net.lock().peer(0).push_blocks(1, false); // best is #1 - - // add a forced transition at block 5. - if FORCE_CHANGE { - let parent_hash = net.lock().peer(0).client().info().chain.best_hash; - forced_transitions.lock().insert(parent_hash, (0, ScheduledChange { - next_authorities: voters.clone(), - delay: 3, - })); - } + // best is #1 + net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| { + // add a forced transition at block 5. + let mut block = builder.bake().unwrap(); + if FORCE_CHANGE { + add_forced_change(&mut block, 0, ScheduledChange { + next_authorities: voters.clone(), + delay: 3, + }); + } + block + }); // ensure block#10 enacts authorities set change => justification is generated // normally it will reach light client, but because of the forced change, it will not @@ -1456,12 +1453,15 @@ fn voter_catches_up_to_latest_round_when_behind() { justification_period: 32, keystore, name: Some(format!("peer#{}", peer_id)), + is_authority: true, + observer_enabled: true, }, link, network: net.lock().peer(peer_id).network_service().clone(), inherent_data_providers: InherentDataProviders::new(), on_exit: Exit, telemetry_on_connect: None, + voting_rule: (), }; Box::new(run_grandpa_voter(grandpa_params).expect("all in order with client and network")) @@ -1543,3 +1543,198 @@ fn voter_catches_up_to_latest_round_when_behind() { let drive_to_completion = futures::future::poll_fn(|| { net.lock().poll(); Ok(Async::NotReady) }); let _ = runtime.block_on(test.select(drive_to_completion).map_err(|_| ())).unwrap(); } + +#[test] +fn grandpa_environment_respects_voting_rules() { + use grandpa::Chain; + use network::test::TestClient; + + let peers = &[Ed25519Keyring::Alice]; + let voters = make_ids(peers); + + let mut net = GrandpaTestNet::new(TestApi::new(voters), 1); + let peer = net.peer(0); + let network_service = peer.network_service().clone(); + let link = peer.data.lock().take().unwrap(); + + // create a voter environment with a given voting rule + let environment = |voting_rule: Box>| { + let PersistentData { + ref authority_set, + ref consensus_changes, + ref set_state, + .. + } = link.persistent_data; + + let config = Config { + gossip_duration: TEST_GOSSIP_DURATION, + justification_period: 32, + keystore: None, + name: None, + is_authority: true, + observer_enabled: true, + }; + + let (network, _) = NetworkBridge::new( + network_service.clone(), + config.clone(), + set_state.clone(), + Exit, + ); + + Environment { + authority_set: authority_set.clone(), + config: config.clone(), + consensus_changes: consensus_changes.clone(), + client: link.client.clone(), + select_chain: link.select_chain.clone(), + set_id: authority_set.set_id(), + voter_set_state: set_state.clone(), + voters: Arc::new(authority_set.current_authorities()), + network, + voting_rule, + } + }; + + // add 20 blocks + peer.push_blocks(20, false); + + // create an environment with no voting rule restrictions + let unrestricted_env = environment(Box::new(())); + + // another with 3/4 unfinalized chain voting rule restriction + let three_quarters_env = environment(Box::new( + voting_rule::ThreeQuartersOfTheUnfinalizedChain + )); + + // and another restricted with the default voting rules: i.e. 3/4 rule and + // always below best block + let default_env = environment(Box::new( + VotingRulesBuilder::default().build() + )); + + // the unrestricted environment should just return the best block + assert_eq!( + unrestricted_env.best_chain_containing( + peer.client().info().chain.finalized_hash + ).unwrap().1, + 20, + ); + + // both the other environments should return block 15, which is 3/4 of the + // way in the unfinalized chain + assert_eq!( + three_quarters_env.best_chain_containing( + peer.client().info().chain.finalized_hash + ).unwrap().1, + 15, + ); + + assert_eq!( + default_env.best_chain_containing( + peer.client().info().chain.finalized_hash + ).unwrap().1, + 15, + ); + + // we finalize block 19 with block 20 being the best block + peer.client().finalize_block(BlockId::Number(19), None, false).unwrap(); + + // the 3/4 environment should propose block 20 for voting + assert_eq!( + three_quarters_env.best_chain_containing( + peer.client().info().chain.finalized_hash + ).unwrap().1, + 20, + ); + + // while the default environment will always still make sure we don't vote + // on the best block + assert_eq!( + default_env.best_chain_containing( + peer.client().info().chain.finalized_hash + ).unwrap().1, + 19, + ); +} + +#[test] +fn imports_justification_for_regular_blocks_on_import() { + // NOTE: this is a regression test since initially we would only import + // justifications for authority change blocks, and would discard any + // existing justification otherwise. + let peers = &[Ed25519Keyring::Alice]; + let voters = make_ids(peers); + let api = TestApi::new(voters); + let mut net = GrandpaTestNet::new(api.clone(), 1); + + let client = net.peer(0).client().clone(); + let (mut block_import, ..) = net.make_block_import(client.clone()); + + let full_client = client.as_full().expect("only full clients are used in test"); + let builder = full_client.new_block_at(&BlockId::Number(0), Default::default()).unwrap(); + let block = builder.bake().unwrap(); + + let block_hash = block.hash(); + + // create a valid justification, with one precommit targeting the block + let justification = { + let round = 1; + let set_id = 0; + + let precommit = grandpa::Precommit { + target_hash: block_hash, + target_number: *block.header.number(), + }; + + let msg = grandpa::Message::Precommit(precommit.clone()); + let encoded = communication::localized_payload(round, set_id, &msg); + let signature = peers[0].sign(&encoded[..]).into(); + + let precommit = grandpa::SignedPrecommit { + precommit, + signature, + id: peers[0].public().into(), + }; + + let commit = grandpa::Commit { + target_hash: block_hash, + target_number: *block.header.number(), + precommits: vec![precommit], + }; + + GrandpaJustification::from_commit( + &full_client, + round, + commit, + ).unwrap() + }; + + // we import the block with justification attached + let block = BlockImportParams { + origin: BlockOrigin::File, + header: block.header, + justification: Some(justification.encode()), + post_digests: Vec::new(), + body: Some(block.extrinsics), + finalized: false, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + }; + + assert_eq!( + block_import.import_block(block, HashMap::new()).unwrap(), + ImportResult::Imported(ImportedAux { + needs_justification: false, + clear_justification_requests: false, + bad_justification: false, + is_new_best: true, + ..Default::default() + }), + ); + + // the justification should be imported and available from the client + assert!( + client.justification(&BlockId::Hash(block_hash)).unwrap().is_some(), + ); +} diff --git a/core/finality-grandpa/src/until_imported.rs b/core/finality-grandpa/src/until_imported.rs index af797c99ab39bdda781ee6d1fecfb4d781573746..5fca476a82b6a45ae47a5f63d143f8ce9ed0040d 100644 --- a/core/finality-grandpa/src/until_imported.rs +++ b/core/finality-grandpa/src/until_imported.rs @@ -20,7 +20,13 @@ //! //! This is used for votes and commit messages currently. -use super::{BlockStatus, CommunicationIn, Error, SignedMessage}; +use super::{ + BlockStatus as BlockStatusT, + BlockSyncRequester as BlockSyncRequesterT, + CommunicationIn, + Error, + SignedMessage, +}; use log::{debug, warn}; use client::{BlockImportNotification, ImportNotifications}; @@ -54,8 +60,8 @@ pub(crate) trait BlockUntilImported: Sized { wait: Wait, ready: Ready, ) -> Result<(), Error> where - S: BlockStatus, - Wait: FnMut(Block::Hash, Self), + S: BlockStatusT, + Wait: FnMut(Block::Hash, NumberFor, Self), Ready: FnMut(Self::Blocked); /// called when the wait has completed. The canonical number is passed through @@ -64,23 +70,33 @@ pub(crate) trait BlockUntilImported: Sized { } /// Buffering imported messages until blocks with given hashes are imported. -pub(crate) struct UntilImported> { +pub(crate) struct UntilImported> { import_notifications: Fuse, Error = ()> + Send>>, - status_check: Status, + block_sync_requester: BlockSyncRequester, + status_check: BlockStatus, inner: Fuse, ready: VecDeque, check_pending: Interval, - pending: HashMap)>, + /// Mapping block hashes to their block number, the point in time it was + /// first encountered (Instant) and a list of GRANDPA messages referencing + /// the block hash. + pending: HashMap, Instant, Vec)>, + identifier: &'static str, } -impl UntilImported - where Status: BlockStatus, M: BlockUntilImported +impl UntilImported where + Block: BlockT, + BlockStatus: BlockStatusT, + M: BlockUntilImported, + I: Stream, { /// Create a new `UntilImported` wrapper. pub(crate) fn new( import_notifications: ImportNotifications, - status_check: Status, + block_sync_requester: BlockSyncRequester, + status_check: BlockStatus, stream: I, + identifier: &'static str, ) -> Self { // how often to check if pending messages that are waiting for blocks to be // imported can be checked. @@ -96,17 +112,21 @@ impl UntilImported let stream = import_notifications.map::<_, fn(_) -> _>(|v| Ok::<_, ()>(v)).compat(); Box::new(stream) as Box + Send> }.fuse(), + block_sync_requester, status_check, inner: stream.fuse(), ready: VecDeque::new(), check_pending, pending: HashMap::new(), + identifier, } } } -impl Stream for UntilImported where - Status: BlockStatus, +impl Stream for UntilImported where + Block: BlockT, + BStatus: BlockStatusT, + BSyncRequester: BlockSyncRequesterT, I: Stream, M: BlockUntilImported, { @@ -125,10 +145,10 @@ impl Stream for UntilImported M::schedule_wait( input, &self.status_check, - |target_hash, wait| pending + |target_hash, target_number, wait| pending .entry(target_hash) - .or_insert_with(|| (Instant::now(), Vec::new())) - .1 + .or_insert_with(|| (target_number, Instant::now(), Vec::new())) + .2 .push(wait), |ready_item| ready.push_back(ready_item), )?; @@ -143,7 +163,7 @@ impl Stream for UntilImported Ok(Async::Ready(None)) => return Ok(Async::Ready(None)), Ok(Async::Ready(Some(notification))) => { // new block imported. queue up all messages tied to that hash. - if let Some((_, messages)) = self.pending.remove(¬ification.hash) { + if let Some((_, _, messages)) = self.pending.remove(¬ification.hash) { let canon_number = notification.header.number().clone(); let ready_messages = messages.into_iter() .filter_map(|m| m.wait_completed(canon_number)); @@ -162,18 +182,29 @@ impl Stream for UntilImported if update_interval { let mut known_keys = Vec::new(); - for (&block_hash, &mut (ref mut last_log, ref v)) in &mut self.pending { + for (&block_hash, &mut (block_number, ref mut last_log, ref v)) in &mut self.pending { if let Some(number) = self.status_check.block_number(block_hash)? { known_keys.push((block_hash, number)); } else { let next_log = *last_log + LOG_PENDING_INTERVAL; - if Instant::now() <= next_log { + if Instant::now() >= next_log { debug!( target: "afg", - "Waiting to import block {} before {} votes can be imported. \ + "Waiting to import block {} before {} {} messages can be imported. \ + Requesting network sync service to retrieve block from. \ Possible fork?", block_hash, v.len(), + self.identifier, + ); + + // NOTE: when sending an empty vec of peers the + // underlying should make a best effort to sync the + // block from any peers it knows about. + self.block_sync_requester.set_sync_fork_request( + vec![], + block_hash, + block_number, ); *last_log = next_log; @@ -182,7 +213,7 @@ impl Stream for UntilImported } for (known_hash, canon_number) in known_keys { - if let Some((_, pending_messages)) = self.pending.remove(&known_hash) { + if let Some((_, _, pending_messages)) = self.pending.remove(&known_hash) { let ready_messages = pending_messages.into_iter() .filter_map(|m| m.wait_completed(canon_number)); @@ -216,14 +247,14 @@ fn warn_authority_wrong_target(hash: H, id: AuthorityId) impl BlockUntilImported for SignedMessage { type Blocked = Self; - fn schedule_wait( + fn schedule_wait( msg: Self::Blocked, - status_check: &S, + status_check: &BlockStatus, mut wait: Wait, mut ready: Ready, ) -> Result<(), Error> where - S: BlockStatus, - Wait: FnMut(Block::Hash, Self), + BlockStatus: BlockStatusT, + Wait: FnMut(Block::Hash, NumberFor, Self), Ready: FnMut(Self::Blocked), { let (&target_hash, target_number) = msg.target(); @@ -235,7 +266,7 @@ impl BlockUntilImported for SignedMessage { ready(msg); } } else { - wait(target_hash, msg) + wait(target_hash, target_number, msg) } Ok(()) @@ -255,7 +286,13 @@ impl BlockUntilImported for SignedMessage { /// Helper type definition for the stream which waits until vote targets for /// signed messages are imported. -pub(crate) type UntilVoteTargetImported = UntilImported>; +pub(crate) type UntilVoteTargetImported = UntilImported< + Block, + BlockStatus, + BlockSyncRequester, + I, + SignedMessage, +>; /// This blocks a global message import, i.e. a commit or catch up messages, /// until all blocks referenced in its votes are known. @@ -270,14 +307,14 @@ pub(crate) struct BlockGlobalMessage { impl BlockUntilImported for BlockGlobalMessage { type Blocked = CommunicationIn; - fn schedule_wait( + fn schedule_wait( input: Self::Blocked, - status_check: &S, + status_check: &BlockStatus, mut wait: Wait, mut ready: Ready, ) -> Result<(), Error> where - S: BlockStatus, - Wait: FnMut(Block::Hash, Self), + BlockStatus: BlockStatusT, + Wait: FnMut(Block::Hash, NumberFor, Self), Ready: FnMut(Self::Blocked), { use std::collections::hash_map::Entry; @@ -379,7 +416,7 @@ impl BlockUntilImported for BlockGlobalMessage { // if this is taking a long time. for (hash, is_known) in checked_hashes { if let KnownOrUnknown::Unknown(target_number) = is_known { - wait(hash, BlockGlobalMessage { + wait(hash, target_number, BlockGlobalMessage { inner: locked_global.clone(), target_number, }) @@ -421,9 +458,10 @@ impl BlockUntilImported for BlockGlobalMessage { /// A stream which gates off incoming global messages, i.e. commit and catch up /// messages, until all referenced block hashes have been imported. -pub(crate) type UntilGlobalMessageBlocksImported = UntilImported< +pub(crate) type UntilGlobalMessageBlocksImported = UntilImported< Block, - Status, + BlockStatus, + BlockSyncRequester, I, BlockGlobalMessage, >; @@ -472,6 +510,7 @@ mod tests { origin: BlockOrigin::File, header, is_new_best: false, + retracted: vec![], }).unwrap(); } } @@ -480,12 +519,31 @@ mod tests { inner: Arc>>, } - impl BlockStatus for TestBlockStatus { + impl BlockStatusT for TestBlockStatus { fn block_number(&self, hash: Hash) -> Result, Error> { Ok(self.inner.lock().get(&hash).map(|x| x.clone())) } } + #[derive(Clone)] + struct TestBlockSyncRequester { + requests: Arc)>>>, + } + + impl Default for TestBlockSyncRequester { + fn default() -> Self { + TestBlockSyncRequester { + requests: Arc::new(Mutex::new(Vec::new())), + } + } + } + + impl BlockSyncRequesterT for TestBlockSyncRequester { + fn set_sync_fork_request(&self, _peers: Vec, hash: Hash, number: NumberFor) { + self.requests.lock().push((hash, number)); + } + } + fn make_header(number: u64) -> Header { Header::new( number, @@ -530,8 +588,10 @@ mod tests { let until_imported = UntilGlobalMessageBlocksImported::new( import_notifications, + TestBlockSyncRequester::default(), block_status, global_rx.map_err(|_| panic!("should never error")), + "global", ); global_tx.unbounded_send(msg).unwrap(); @@ -555,8 +615,10 @@ mod tests { let until_imported = UntilGlobalMessageBlocksImported::new( import_notifications, + TestBlockSyncRequester::default(), block_status, global_rx.map_err(|_| panic!("should never error")), + "global", ); global_tx.unbounded_send(msg).unwrap(); @@ -799,4 +861,80 @@ mod tests { unapply_catch_up(unknown_catch_up()), ); } + + #[test] + fn request_block_sync_for_needed_blocks() { + let (chain_state, import_notifications) = TestChainState::new(); + let block_status = chain_state.block_status(); + + let (global_tx, global_rx) = futures::sync::mpsc::unbounded(); + + let block_sync_requester = TestBlockSyncRequester::default(); + + let until_imported = UntilGlobalMessageBlocksImported::new( + import_notifications, + block_sync_requester.clone(), + block_status, + global_rx.map_err(|_| panic!("should never error")), + "global", + ); + + let h1 = make_header(5); + let h2 = make_header(6); + let h3 = make_header(7); + + // we create a commit message, with precommits for blocks 6 and 7 which + // we haven't imported. + let unknown_commit = CompactCommit:: { + target_hash: h1.hash(), + target_number: 5, + precommits: vec![ + Precommit { + target_hash: h2.hash(), + target_number: 6, + }, + Precommit { + target_hash: h3.hash(), + target_number: 7, + }, + ], + auth_data: Vec::new(), // not used + }; + + let unknown_commit = || voter::CommunicationIn::Commit( + 0, + unknown_commit.clone(), + voter::Callback::Blank, + ); + + // we send the commit message and spawn the until_imported stream + global_tx.unbounded_send(unknown_commit()).unwrap(); + + let mut runtime = Runtime::new().unwrap(); + runtime.spawn(until_imported.into_future().map(|_| ()).map_err(|_| ())); + + // assert that we will make sync requests + let assert = futures::future::poll_fn::<(), (), _>(|| { + let block_sync_requests = block_sync_requester.requests.lock(); + + // we request blocks targeted by the precommits that aren't imported + if block_sync_requests.contains(&(h2.hash(), *h2.number())) && + block_sync_requests.contains(&(h3.hash(), *h3.number())) + { + return Ok(Async::Ready(())); + } + + Ok(Async::NotReady) + }); + + // the `until_imported` stream doesn't request the blocks immediately, + // but it should request them after a small timeout + let timeout = Delay::new(Instant::now() + Duration::from_secs(60)); + let test = assert.select2(timeout).map(|res| match res { + Either::A(_) => {}, + Either::B(_) => panic!("timed out waiting for block sync request"), + }).map_err(|_| ()); + + runtime.block_on(test).unwrap(); + } } diff --git a/core/finality-grandpa/src/voting_rule.rs b/core/finality-grandpa/src/voting_rule.rs new file mode 100644 index 0000000000000000000000000000000000000000..355fa0cd2d08068d8b0de1197b0e01cd32e1a884 --- /dev/null +++ b/core/finality-grandpa/src/voting_rule.rs @@ -0,0 +1,270 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Handling custom voting rules for GRANDPA. +//! +//! This exposes the `VotingRule` trait used to implement arbitrary voting +//! restrictions that are taken into account by the GRANDPA environment when +//! selecting a finality target to vote on. + +use std::sync::Arc; + +use client::blockchain::HeaderBackend; +use sr_primitives::generic::BlockId; +use sr_primitives::traits::{Block as BlockT, Header, NumberFor, One, Zero}; + +/// A trait for custom voting rules in GRANDPA. +pub trait VotingRule: Send + Sync where + Block: BlockT, + B: HeaderBackend, +{ + /// Restrict the given `current_target` vote, returning the block hash and + /// number of the block to vote on, and `None` in case the vote should not + /// be restricted. `base` is the block that we're basing our votes on in + /// order to pick our target (e.g. last round estimate), and `best_target` + /// is the initial best vote target before any vote rules were applied. When + /// applying multiple `VotingRule`s both `base` and `best_target` should + /// remain unchanged. + /// + /// The contract of this interface requires that when restricting a vote, the + /// returned value **must** be an ancestor of the given `current_target`, + /// this also means that a variant must be maintained throughout the + /// execution of voting rules wherein `current_target <= best_target`. + fn restrict_vote( + &self, + backend: &B, + base: &Block::Header, + best_target: &Block::Header, + current_target: &Block::Header, + ) -> Option<(Block::Hash, NumberFor)>; +} + +impl VotingRule for () where + Block: BlockT, + B: HeaderBackend, +{ + fn restrict_vote( + &self, + _backend: &B, + _base: &Block::Header, + _best_target: &Block::Header, + _current_target: &Block::Header, + ) -> Option<(Block::Hash, NumberFor)> { + None + } +} + +/// A custom voting rule that guarantees that our vote is always behind the best +/// block, in the best case exactly one block behind it. +#[derive(Clone)] +pub struct BeforeBestBlock; +impl VotingRule for BeforeBestBlock where + Block: BlockT, + B: HeaderBackend, +{ + fn restrict_vote( + &self, + _backend: &B, + _base: &Block::Header, + best_target: &Block::Header, + current_target: &Block::Header, + ) -> Option<(Block::Hash, NumberFor)> { + if current_target.number().is_zero() { + return None; + } + + if current_target.number() == best_target.number() { + return Some(( + current_target.parent_hash().clone(), + *current_target.number() - One::one(), + )); + } + + None + } +} + +/// A custom voting rule that limits votes towards 3/4 of the unfinalized chain, +/// using the given `base` and `best_target` to figure where the 3/4 target +/// should fall. +pub struct ThreeQuartersOfTheUnfinalizedChain; + +impl VotingRule for ThreeQuartersOfTheUnfinalizedChain where + Block: BlockT, + B: HeaderBackend, +{ + fn restrict_vote( + &self, + backend: &B, + base: &Block::Header, + best_target: &Block::Header, + current_target: &Block::Header, + ) -> Option<(Block::Hash, NumberFor)> { + // target a vote towards 3/4 of the unfinalized chain (rounding up) + let target_number = { + let two = NumberFor::::one() + One::one(); + let three = two + One::one(); + let four = three + One::one(); + + let diff = *best_target.number() - *base.number(); + let diff = ((diff * three) + two) / four; + + *base.number() + diff + }; + + // our current target is already lower than this rule would restrict + if target_number >= *current_target.number() { + return None; + } + + let mut target_header = current_target.clone(); + let mut target_hash = current_target.hash(); + + // walk backwards until we find the target block + loop { + if *target_header.number() < target_number { + unreachable!( + "we are traversing backwards from a known block; \ + blocks are stored contiguously; \ + qed" + ); + } + if *target_header.number() == target_number { + return Some((target_hash, target_number)); + } + + target_hash = *target_header.parent_hash(); + target_header = backend.header(BlockId::Hash(target_hash)).ok()? + .expect("Header known to exist due to the existence of one of its descendents; qed"); + } + } +} + +struct VotingRules { + rules: Arc>>>, +} + +impl Clone for VotingRules { + fn clone(&self) -> Self { + VotingRules { + rules: self.rules.clone(), + } + } +} + +impl VotingRule for VotingRules where + Block: BlockT, + B: HeaderBackend, +{ + fn restrict_vote( + &self, + backend: &B, + base: &Block::Header, + best_target: &Block::Header, + current_target: &Block::Header, + ) -> Option<(Block::Hash, NumberFor)> { + let restricted_target = self.rules.iter().fold( + current_target.clone(), + |current_target, rule| { + rule.restrict_vote( + backend, + base, + best_target, + ¤t_target, + ) + .and_then(|(hash, _)| backend.header(BlockId::Hash(hash)).ok()) + .and_then(std::convert::identity) + .unwrap_or(current_target) + }, + ); + + let restricted_hash = restricted_target.hash(); + + if restricted_hash != current_target.hash() { + Some((restricted_hash, *restricted_target.number())) + } else { + None + } + } +} + +/// A builder of a composite voting rule that applies a set of rules to +/// progressively restrict the vote. +pub struct VotingRulesBuilder { + rules: Vec>>, +} + +impl Default for VotingRulesBuilder where + Block: BlockT, + B: HeaderBackend, +{ + fn default() -> Self { + VotingRulesBuilder::new() + .add(BeforeBestBlock) + .add(ThreeQuartersOfTheUnfinalizedChain) + } +} + +impl VotingRulesBuilder where + Block: BlockT, + B: HeaderBackend, +{ + /// Return a new voting rule builder using the given backend. + pub fn new() -> Self { + VotingRulesBuilder { + rules: Vec::new(), + } + } + + /// Add a new voting rule to the builder. + pub fn add(mut self, rule: R) -> Self where + R: VotingRule + 'static, + { + self.rules.push(Box::new(rule)); + self + } + + /// Add all given voting rules to the builder. + pub fn add_all(mut self, rules: I) -> Self where + I: IntoIterator>>, + { + self.rules.extend(rules); + self + } + + /// Return a new `VotingRule` that applies all of the previously added + /// voting rules in-order. + pub fn build(self) -> impl VotingRule + Clone { + VotingRules { + rules: Arc::new(self.rules), + } + } +} + +impl VotingRule for Box> where + Block: BlockT, + B: HeaderBackend, +{ + fn restrict_vote( + &self, + backend: &B, + base: &Block::Header, + best_target: &Block::Header, + current_target: &Block::Header, + ) -> Option<(Block::Hash, NumberFor)> { + (**self).restrict_vote(backend, base, best_target, current_target) + } +} diff --git a/core/keyring/Cargo.toml b/core/keyring/Cargo.toml index 1a58dc133e35891acc816082dc3ae36eab089de9..0147689985fa95b7565a07e3e94893dd63a165e7 100644 --- a/core/keyring/Cargo.toml +++ b/core/keyring/Cargo.toml @@ -7,6 +7,6 @@ edition = "2018" [dependencies] primitives = { package = "substrate-primitives", path = "../primitives" } sr-primitives = { path = "../sr-primitives" } -lazy_static = { version = "1.0" } +lazy_static = "1.4.0" strum = "0.15.0" strum_macros = "0.15.0" diff --git a/core/keyring/src/ed25519.rs b/core/keyring/src/ed25519.rs index 56bdb1ce8c0e60d3a43116631378b38592a8f762..c1a357fc0e427f16f58e39fd502ed7e2a56f8e33 100644 --- a/core/keyring/src/ed25519.rs +++ b/core/keyring/src/ed25519.rs @@ -20,6 +20,7 @@ use std::{collections::HashMap, ops::Deref}; use lazy_static::lazy_static; use primitives::{ed25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; pub use primitives::ed25519; +use sr_primitives::AccountId32; /// Set of test accounts. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum_macros::Display, strum_macros::EnumIter)] @@ -39,6 +40,10 @@ impl Keyring { Self::iter().find(|&k| &Public::from(k) == who) } + pub fn from_account_id(who: &AccountId32) -> Option { + Self::iter().find(|&k| &k.to_account_id() == who) + } + pub fn from_raw_public(who: [u8; 32]) -> Option { Self::from_public(&Public::from_raw(who)) } @@ -59,6 +64,10 @@ impl Keyring { Public::from(self).to_raw_vec() } + pub fn to_account_id(self) -> AccountId32 { + self.to_raw_public().into() + } + pub fn sign(self, msg: &[u8]) -> Signature { Pair::from(self).sign(msg) } @@ -119,6 +128,12 @@ impl From for Public { } } +impl From for AccountId32 { + fn from(k: Keyring) -> Self { + k.to_account_id() + } +} + impl From for Pair { fn from(k: Keyring) -> Self { k.pair() diff --git a/core/keyring/src/sr25519.rs b/core/keyring/src/sr25519.rs index bb3aaa6b51db19569208bbad3128b269f5cb7707..b37b2bdf9b22a2f1e3f02c799f72eda5f447d719 100644 --- a/core/keyring/src/sr25519.rs +++ b/core/keyring/src/sr25519.rs @@ -21,6 +21,7 @@ use std::ops::Deref; use lazy_static::lazy_static; use primitives::{sr25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; pub use primitives::sr25519; +use sr_primitives::AccountId32; /// Set of test accounts. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum_macros::Display, strum_macros::EnumIter)] @@ -40,6 +41,10 @@ impl Keyring { Self::iter().find(|&k| &Public::from(k) == who) } + pub fn from_account_id(who: &AccountId32) -> Option { + Self::iter().find(|&k| &k.to_account_id() == who) + } + pub fn from_raw_public(who: [u8; 32]) -> Option { Self::from_public(&Public::from_raw(who)) } @@ -60,6 +65,10 @@ impl Keyring { Public::from(self).to_raw_vec() } + pub fn to_account_id(self) -> AccountId32 { + self.to_raw_public().into() + } + pub fn sign(self, msg: &[u8]) -> Signature { Pair::from(self).sign(msg) } @@ -114,6 +123,12 @@ lazy_static! { }; } +impl From for AccountId32 { + fn from(k: Keyring) -> Self { + k.to_account_id() + } +} + impl From for Public { fn from(k: Keyring) -> Self { (*PUBLIC_KEYS).get(&k).unwrap().clone() diff --git a/core/keystore/Cargo.toml b/core/keystore/Cargo.toml index c56b9ba67dcbdf055697fac19b56c0ad97b16274..cc491337cf83a0d861f1955b76c518b0514fa4be 100644 --- a/core/keystore/Cargo.toml +++ b/core/keystore/Cargo.toml @@ -8,11 +8,11 @@ edition = "2018" derive_more = "0.15.0" primitives = { package = "substrate-primitives", path = "../primitives" } app-crypto = { package = "substrate-application-crypto", path = "../application-crypto" } -hex = "0.3" -rand = "0.6" -serde_json = "1.0" -subtle = "2.0" +hex = "0.3.2" +rand = "0.7.2" +serde_json = "1.0.41" +subtle = "2.1.1" parking_lot = "0.9.0" [dev-dependencies] -tempdir = "0.3" +tempdir = "0.3.7" diff --git a/core/keystore/src/lib.rs b/core/keystore/src/lib.rs index 9125ddbda650228f4ace7233248b7b84083dac12..c86e9f8b8850ce6d64da82f3bd6fcfb06c4f8694 100644 --- a/core/keystore/src/lib.rs +++ b/core/keystore/src/lib.rs @@ -318,7 +318,7 @@ impl BareCryptoStore for Store { mod tests { use super::*; use tempdir::TempDir; - use primitives::crypto::{Ss58Codec, key_types}; + use primitives::{testing::{SR25519}, crypto::{Ss58Codec}}; #[test] fn basic_store() { @@ -410,14 +410,14 @@ mod tests { let key_pair = sr25519::AppPair::from_string(secret_uri, None).expect("Generates key pair"); store.write().insert_unknown( - key_types::SR25519, + SR25519, secret_uri, key_pair.public().as_ref(), ).expect("Inserts unknown key"); let store_key_pair = store.read().key_pair_by_type::( &key_pair.public(), - key_types::SR25519, + SR25519, ).expect("Gets key pair from keystore"); assert_eq!(key_pair.public(), store_key_pair.public()); diff --git a/core/network/Cargo.toml b/core/network/Cargo.toml index dac6ecdd72cf27a533e0b628f9cbac7a4e9cd4b9..216b898277b4b28ad793c98cbcf408489596574c 100644 --- a/core/network/Cargo.toml +++ b/core/network/Cargo.toml @@ -7,54 +7,55 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -bytes = "0.4" -derive_more = "0.14.0" -either = "1.5.2" -log = "0.4" +bytes = "0.4.12" +derive_more = "0.15.0" +either = "1.5.3" +log = "0.4.8" parking_lot = "0.9.0" -bitflags = "1.0" -fnv = "1.0" -futures = "0.1.17" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.17", features = ["compat"] } -futures-timer = "0.2.1" -linked-hash-map = "0.5" +bitflags = "1.2.0" +fnv = "1.0.6" +futures = "0.1.29" +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } +futures-timer = "0.4.0" +linked-hash-map = "0.5.2" linked_hash_set = "0.1.3" -lru-cache = "0.1.1" -rustc-hex = "2.0" -rand = "0.6" -libp2p = { version = "0.11.0", default-features = false, features = ["secp256k1", "libp2p-websocket"] } +lru-cache = "0.1.2" +rustc-hex = "2.0.1" +rand = "0.7.2" +libp2p = { version = "0.13.0", default-features = false, features = ["libp2p-websocket"] } fork-tree = { path = "../../core/utils/fork-tree" } consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common" } client = { package = "substrate-client", path = "../../core/client" } +header_metadata = { package = "substrate-header-metadata", path = "../../core/client/header-metadata" } sr-primitives = { path = "../../core/sr-primitives" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } peerset = { package = "substrate-peerset", path = "../../core/peerset" } -serde = { version = "1.0.70", features = ["derive"] } -serde_json = "1.0.24" -slog = { version = "^2", features = ["nested-values"] } +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" +slog = { version = "2.5.2", features = ["nested-values"] } slog_derive = "0.1.1" -smallvec = "0.6" -tokio-io = "0.1" -tokio = { version = "0.1.11", optional = true } -unsigned-varint = { version = "0.2.1", features = ["codec"] } +smallvec = "0.6.10" +tokio-io = "0.1.12" +tokio = { version = "0.1.22", optional = true } +unsigned-varint = { version = "0.2.2", features = ["codec"] } keyring = { package = "substrate-keyring", path = "../../core/keyring", optional = true } test_client = { package = "substrate-test-client", path = "../../core/test-client", optional = true } test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client", optional = true } erased-serde = "0.3.9" -void = "1.0" -zeroize = "0.9.0" +void = "1.0.2" +zeroize = "0.10.1" babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../consensus/babe/primitives" } [dev-dependencies] -env_logger = { version = "0.6" } +env_logger = "0.7.0" keyring = { package = "substrate-keyring", path = "../../core/keyring" } -quickcheck = "0.8.5" -rand = "0.6.5" +quickcheck = "0.9.0" +rand = "0.7.2" test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } test_runtime = { package = "substrate-test-runtime", path = "../../core/test-runtime" } -tempdir = "0.3" -tokio = "0.1.11" +tempdir = "0.3.7" +tokio = "0.1.22" [features] default = [] diff --git a/core/network/src/behaviour.rs b/core/network/src/behaviour.rs index f2144c89a5654e1278706fb6112acfb7366f2825..28830b326eaee87265ffaea3b066e244d65d8aac 100644 --- a/core/network/src/behaviour.rs +++ b/core/network/src/behaviour.rs @@ -23,10 +23,10 @@ use crate::protocol::{CustomMessageOutcome, Protocol}; use futures::prelude::*; use libp2p::NetworkBehaviour; use libp2p::core::{Multiaddr, PeerId, PublicKey}; +use libp2p::kad::record; use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess}; use libp2p::core::{nodes::Substream, muxing::StreamMuxerBox}; -use libp2p::multihash::Multihash; -use log::warn; +use log::{debug, warn}; use sr_primitives::traits::Block as BlockT; use std::iter; use void; @@ -101,12 +101,12 @@ impl, H: ExHashT> Behaviour { } /// Start querying a record from the DHT. Will later produce either a `ValueFound` or a `ValueNotFound` event. - pub fn get_value(&mut self, key: &Multihash) { + pub fn get_value(&mut self, key: &record::Key) { self.discovery.get_value(key); } /// Starts putting a record into DHT. Will later produce either a `ValuePut` or a `ValuePutFailed` event. - pub fn put_value(&mut self, key: Multihash, value: Vec) { + pub fn put_value(&mut self, key: record::Key, value: Vec) { self.discovery.put_value(key, value); } } @@ -133,7 +133,7 @@ impl, H: ExHashT> NetworkBehaviourEventPr warn!(target: "sub-libp2p", "Connected to a non-Substrate node: {:?}", info); } if info.listen_addrs.len() > 30 { - warn!(target: "sub-libp2p", "Node {:?} has reported more than 30 addresses; \ + debug!(target: "sub-libp2p", "Node {:?} has reported more than 30 addresses; \ it is identified by {:?} and {:?}", peer_id, info.protocol_version, info.agent_version ); diff --git a/core/network/src/chain.rs b/core/network/src/chain.rs index e857aa095c9f97eefc7bd462cd8f534a64bf73ec..2b32c07009fc7a732ff5818d5ca6364cb5ec9008 100644 --- a/core/network/src/chain.rs +++ b/core/network/src/chain.rs @@ -16,10 +16,10 @@ //! Blockchain access trait -use client::{self, Client as SubstrateClient, ClientInfo, BlockStatus, CallExecutor}; +use client::{self, Client as SubstrateClient, ClientInfo, CallExecutor}; use client::error::Error; -use client::light::fetcher::ChangesProof; -use consensus::{BlockImport, Error as ConsensusError}; +use client::light::fetcher::{ChangesProof, StorageProof}; +use consensus::{BlockImport, BlockStatus, Error as ConsensusError}; use sr_primitives::traits::{Block as BlockT, Header as HeaderT}; use sr_primitives::generic::{BlockId}; use sr_primitives::Justification; @@ -46,13 +46,22 @@ pub trait Client: Send + Sync { fn justification(&self, id: &BlockId) -> Result, Error>; /// Get block header proof. - fn header_proof(&self, block_number: ::Number) -> Result<(Block::Header, Vec>), Error>; + fn header_proof(&self, block_number: ::Number) + -> Result<(Block::Header, StorageProof), Error>; /// Get storage read execution proof. - fn read_proof(&self, block: &Block::Hash, key: &[u8]) -> Result>, Error>; + fn read_proof(&self, block: &Block::Hash, keys: &[Vec]) -> Result; + + /// Get child storage read execution proof. + fn read_child_proof( + &self, + block: &Block::Hash, + storage_key: &[u8], + keys: &[Vec], + ) -> Result; /// Get method execution proof. - fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error>; + fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, StorageProof), Error>; /// Get key changes proof. fn key_changes_proof( @@ -61,6 +70,7 @@ pub trait Client: Send + Sync { last: Block::Hash, min: Block::Hash, max: Block::Hash, + storage_key: Option<&StorageKey>, key: &StorageKey ) -> Result, Error>; @@ -74,6 +84,12 @@ pub trait FinalityProofProvider: Send + Sync { fn prove_finality(&self, for_block: Block::Hash, request: &[u8]) -> Result>, Error>; } +impl FinalityProofProvider for () { + fn prove_finality(&self, _for_block: Block::Hash, _request: &[u8]) -> Result>, Error> { + Ok(None) + } +} + impl Client for SubstrateClient where B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + 'static, @@ -105,15 +121,27 @@ impl Client for SubstrateClient where (self as &SubstrateClient).justification(id) } - fn header_proof(&self, block_number: ::Number) -> Result<(Block::Header, Vec>), Error> { + fn header_proof(&self, block_number: ::Number) + -> Result<(Block::Header, StorageProof), Error> + { (self as &SubstrateClient).header_proof(&BlockId::Number(block_number)) } - fn read_proof(&self, block: &Block::Hash, key: &[u8]) -> Result>, Error> { - (self as &SubstrateClient).read_proof(&BlockId::Hash(block.clone()), key) + fn read_proof(&self, block: &Block::Hash, keys: &[Vec]) -> Result { + (self as &SubstrateClient).read_proof(&BlockId::Hash(block.clone()), keys) } - fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error> { + fn read_child_proof( + &self, + block: &Block::Hash, + storage_key: &[u8], + keys: &[Vec], + ) -> Result { + (self as &SubstrateClient) + .read_child_proof(&BlockId::Hash(block.clone()), storage_key, keys) + } + + fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, StorageProof), Error> { (self as &SubstrateClient).execution_proof(&BlockId::Hash(block.clone()), method, data) } @@ -123,9 +151,10 @@ impl Client for SubstrateClient where last: Block::Hash, min: Block::Hash, max: Block::Hash, - key: &StorageKey + storage_key: Option<&StorageKey>, + key: &StorageKey, ) -> Result, Error> { - (self as &SubstrateClient).key_changes_proof(first, last, min, max, key) + (self as &SubstrateClient).key_changes_proof(first, last, min, max, storage_key, key) } fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result { @@ -133,13 +162,8 @@ impl Client for SubstrateClient where return Ok(false); } - let tree_route = ::client::blockchain::tree_route( - #[allow(deprecated)] - self.backend().blockchain(), - BlockId::Hash(*block), - BlockId::Hash(*base), - )?; + let ancestor = header_metadata::lowest_common_ancestor(self, *block, *base)?; - Ok(tree_route.common_block().hash == *base) + Ok(ancestor.hash == *base) } } diff --git a/core/network/src/config.rs b/core/network/src/config.rs index 46bb8aeff4ddd69deb3de94cdfaa0b561b6a214a..be01b90c363636183f195f8dceb58b7505d7cd5d 100644 --- a/core/network/src/config.rs +++ b/core/network/src/config.rs @@ -26,14 +26,13 @@ use crate::chain::{Client, FinalityProofProvider}; use crate::on_demand_layer::OnDemand; use crate::service::{ExHashT, TransactionPool}; use bitflags::bitflags; -use consensus::import_queue::ImportQueue; +use consensus::{block_validation::BlockAnnounceValidator, import_queue::ImportQueue}; use sr_primitives::traits::{Block as BlockT}; -use std::sync::Arc; -use libp2p::identity::{Keypair, secp256k1, ed25519}; +use libp2p::identity::{Keypair, ed25519}; use libp2p::wasm_ext; use libp2p::{PeerId, Multiaddr, multiaddr}; -use std::error::Error; -use std::{io::{self, Write}, iter, fmt, fs, net::Ipv4Addr, path::{Path, PathBuf}}; +use core::{fmt, iter}; +use std::{error::Error, fs, io::{self, Write}, net::Ipv4Addr, path::{Path, PathBuf}, sync::Arc}; use zeroize::Zeroize; /// Network initialization parameters. @@ -80,6 +79,9 @@ pub struct Params { /// Customization of the network. Use this to plug additional networking capabilities. pub specialization: S, + + /// Type to check incoming block announcements. + pub block_announce_validator: Box + Send> } bitflags! { @@ -205,23 +207,23 @@ pub enum ParseErr { } impl fmt::Display for ParseErr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ParseErr::MultiaddrParse(err) => write!(f, "{}", err), - ParseErr::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"), - ParseErr::PeerIdMissing => write!(f, "Peer id is missing from the address"), - } - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ParseErr::MultiaddrParse(err) => write!(f, "{}", err), + ParseErr::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"), + ParseErr::PeerIdMissing => write!(f, "Peer id is missing from the address"), + } + } } impl std::error::Error for ParseErr { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - ParseErr::MultiaddrParse(err) => Some(err), - ParseErr::InvalidPeerId => None, - ParseErr::PeerIdMissing => None, - } - } + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + ParseErr::MultiaddrParse(err) => Some(err), + ParseErr::InvalidPeerId => None, + ParseErr::PeerIdMissing => None, + } + } } impl From for ParseErr { @@ -231,7 +233,7 @@ impl From for ParseErr { } /// Network service configuration. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct NetworkConfiguration { /// Directory path to store general network configuration. None means nothing will be saved. pub config_path: Option, @@ -314,7 +316,7 @@ impl NetworkConfiguration { } /// Configuration for the transport layer. -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum TransportConfig { /// Normal transport mode. Normal { @@ -359,17 +361,12 @@ impl NonReservedPeerMode { /// The configuration of a node's secret key, describing the type of key /// and how it is obtained. A node's identity keypair is the result of /// the evaluation of the node key configuration. -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum NodeKeyConfig { - /// A Secp256k1 secret key configuration. - Secp256k1(Secret), /// A Ed25519 secret key configuration. Ed25519(Secret) } -/// The options for obtaining a Secp256k1 secret key. -pub type Secp256k1Secret = Secret; - /// The options for obtaining a Ed25519 secret key. pub type Ed25519Secret = Secret; @@ -382,13 +379,22 @@ pub enum Secret { /// it is created with a newly generated secret key `K`. The format /// of the file is determined by `K`: /// - /// * `secp256k1::SecretKey`: An unencoded 32 bytes Secp256k1 secret key. /// * `ed25519::SecretKey`: An unencoded 32 bytes Ed25519 secret key. File(PathBuf), /// Always generate a new secret key `K`. New } +impl fmt::Debug for Secret { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Secret::Input(_) => f.debug_tuple("Secret::Input").finish(), + Secret::File(path) => f.debug_tuple("Secret::File").field(path).finish(), + Secret::New => f.debug_tuple("Secret::New").finish(), + } + } +} + impl NodeKeyConfig { /// Evaluate a `NodeKeyConfig` to obtain an identity `Keypair`: /// @@ -403,20 +409,6 @@ impl NodeKeyConfig { pub fn into_keypair(self) -> io::Result { use NodeKeyConfig::*; match self { - Secp256k1(Secret::New) => - Ok(Keypair::generate_secp256k1()), - - Secp256k1(Secret::Input(k)) => - Ok(Keypair::Secp256k1(k.into())), - - Secp256k1(Secret::File(f)) => - get_secret(f, - |mut b| secp256k1::SecretKey::from_bytes(&mut b), - secp256k1::SecretKey::generate, - |b| b.to_bytes().to_vec()) - .map(secp256k1::Keypair::from) - .map(Keypair::Secp256k1), - Ed25519(Secret::New) => Ok(Keypair::generate_ed25519()), @@ -523,9 +515,9 @@ mod tests { #[test] fn test_secret_input() { - let sk = secp256k1::SecretKey::generate(); - let kp1 = NodeKeyConfig::Secp256k1(Secret::Input(sk.clone())).into_keypair().unwrap(); - let kp2 = NodeKeyConfig::Secp256k1(Secret::Input(sk)).into_keypair().unwrap(); + let sk = ed25519::SecretKey::generate(); + let kp1 = NodeKeyConfig::Ed25519(Secret::Input(sk.clone())).into_keypair().unwrap(); + let kp2 = NodeKeyConfig::Ed25519(Secret::Input(sk)).into_keypair().unwrap(); assert!(secret_bytes(&kp1) == secret_bytes(&kp2)); } diff --git a/core/network/src/debug_info.rs b/core/network/src/debug_info.rs index 3b0d5513ef281dd9f449960e458d9fd3be477581..0283853a5fa14e5b3a2d721c96f9ac4c9242e7d3 100644 --- a/core/network/src/debug_info.rs +++ b/core/network/src/debug_info.rs @@ -21,7 +21,7 @@ use libp2p::Multiaddr; use libp2p::core::{ConnectedPoint, either::EitherOutput, PeerId, PublicKey}; use libp2p::swarm::{IntoProtocolsHandler, IntoProtocolsHandlerSelect, ProtocolsHandler}; use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; -use libp2p::identify::{Identify, IdentifyEvent, protocol::IdentifyInfo}; +use libp2p::identify::{Identify, IdentifyEvent, IdentifyInfo}; use libp2p::ping::{Ping, PingConfig, PingEvent, PingSuccess}; use log::{debug, trace, error}; use std::collections::hash_map::Entry; @@ -287,16 +287,14 @@ where TSubstream: AsyncRead + AsyncWrite { Async::NotReady => break, Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => { match event { - IdentifyEvent::Identified { peer_id, info, .. } => { + IdentifyEvent::Received { peer_id, info, .. } => { self.handle_identify_report(&peer_id, &info); let event = DebugInfoEvent::Identified { peer_id, info }; return Async::Ready(NetworkBehaviourAction::GenerateEvent(event)); } - IdentifyEvent::Error { .. } => {} - IdentifyEvent::SendBack { result: Err(ref err), ref peer_id } => - debug!(target: "sub-libp2p", "Error when sending back identify info \ - to {:?} => {}", peer_id, err), - IdentifyEvent::SendBack { .. } => {} + IdentifyEvent::Error { peer_id, error } => + debug!(target: "sub-libp2p", "Identification with peer {:?} failed => {}", peer_id, error), + IdentifyEvent::Sent { .. } => {} } }, Async::Ready(NetworkBehaviourAction::DialAddress { address }) => diff --git a/core/network/src/discovery.rs b/core/network/src/discovery.rs index 9fa6b2a80fc895c69ccc5170e5692bd85dda9b6c..f956875ca518fa28eaca3399c43ff3548f3dfe35 100644 --- a/core/network/src/discovery.rs +++ b/core/network/src/discovery.rs @@ -52,18 +52,18 @@ use libp2p::core::{ConnectedPoint, Multiaddr, PeerId, PublicKey}; use libp2p::swarm::{ProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; use libp2p::kad::{Kademlia, KademliaEvent, Quorum, Record}; use libp2p::kad::GetClosestPeersError; -use libp2p::kad::record::store::MemoryStore; +use libp2p::kad::record::{self, store::MemoryStore}; #[cfg(not(target_os = "unknown"))] use libp2p::{swarm::toggle::Toggle}; #[cfg(not(target_os = "unknown"))] use libp2p::core::{nodes::Substream, muxing::StreamMuxerBox}; #[cfg(not(target_os = "unknown"))] use libp2p::mdns::{Mdns, MdnsEvent}; -use libp2p::multihash::Multihash; use libp2p::multiaddr::Protocol; use log::{debug, info, trace, warn}; use std::{cmp, collections::VecDeque, time::Duration}; use tokio_io::{AsyncRead, AsyncWrite}; +use primitives::hexdisplay::HexDisplay; /// Implementation of `NetworkBehaviour` that discovers the nodes on the network. pub struct DiscoveryBehaviour { @@ -159,7 +159,7 @@ impl DiscoveryBehaviour { /// Start fetching a record from the DHT. /// /// A corresponding `ValueFound` or `ValueNotFound` event will later be generated. - pub fn get_value(&mut self, key: &Multihash) { + pub fn get_value(&mut self, key: &record::Key) { self.kademlia.get_record(key, Quorum::One) } @@ -167,7 +167,7 @@ impl DiscoveryBehaviour { /// `get_value`. /// /// A corresponding `ValuePut` or `ValuePutFailed` event will later be generated. - pub fn put_value(&mut self, key: Multihash, value: Vec) { + pub fn put_value(&mut self, key: record::Key, value: Vec) { self.kademlia.put_record(Record::new(key, value), Quorum::All); } } @@ -187,16 +187,16 @@ pub enum DiscoveryOut { UnroutablePeer(PeerId), /// The DHT yeided results for the record request, grouped in (key, value) pairs. - ValueFound(Vec<(Multihash, Vec)>), + ValueFound(Vec<(record::Key, Vec)>), /// The record requested was not found in the DHT. - ValueNotFound(Multihash), + ValueNotFound(record::Key), /// The record with a given key was successfully inserted into the DHT. - ValuePut(Multihash), + ValuePut(record::Key), /// Inserting a value into the DHT failed. - ValuePutFailed(Multihash), + ValuePutFailed(record::Key), } impl NetworkBehaviour for DiscoveryBehaviour @@ -317,16 +317,16 @@ where KademliaEvent::GetClosestPeersResult(res) => { match res { Err(GetClosestPeersError::Timeout { key, peers }) => { - warn!(target: "sub-libp2p", - "Libp2p => Query for {:?} timed out with {:?} results", - key, peers.len()); + debug!(target: "sub-libp2p", + "Libp2p => Query for {:?} timed out with {} results", + HexDisplay::from(&key), peers.len()); }, Ok(ok) => { trace!(target: "sub-libp2p", "Libp2p => Query for {:?} yielded {:?} results", - ok.key, ok.peers.len()); + HexDisplay::from(&ok.key), ok.peers.len()); if ok.peers.is_empty() && self.num_connections != 0 { - warn!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \ + debug!(target: "sub-libp2p", "Libp2p => Random Kademlia query has yielded empty \ results"); } } @@ -437,16 +437,24 @@ mod tests { // Build swarms whose behaviour is `DiscoveryBehaviour`. let mut swarms = (0..25).map(|_| { let keypair = Keypair::generate_ed25519(); + let keypair2 = keypair.clone(); let transport = MemoryTransport - .with_upgrade(libp2p::secio::SecioConfig::new(keypair.clone())) .and_then(move |out, endpoint| { - let peer_id = out.remote_key.into_peer_id(); + let secio = libp2p::secio::SecioConfig::new(keypair2); + libp2p::core::upgrade::apply( + out, + secio, + endpoint, + libp2p::core::upgrade::Version::V1 + ) + }) + .and_then(move |(peer_id, stream), endpoint| { let peer_id2 = peer_id.clone(); let upgrade = libp2p::yamux::Config::default() .map_inbound(move |muxer| (peer_id, muxer)) .map_outbound(move |muxer| (peer_id2, muxer)); - upgrade::apply(out.stream, upgrade, endpoint) + upgrade::apply(stream, upgrade, endpoint, libp2p::core::upgrade::Version::V1) }); let behaviour = DiscoveryBehaviour::new(keypair.public(), user_defined.clone(), false); diff --git a/core/network/src/error.rs b/core/network/src/error.rs index 95a1dc5abe76b42b450835212ba9b823a2020101..c3f89e43c17107ecbcb0ae6b05f346c172d14fc2 100644 --- a/core/network/src/error.rs +++ b/core/network/src/error.rs @@ -18,16 +18,42 @@ use client; +use libp2p::{PeerId, Multiaddr}; + +use std::fmt; + /// Result type alias for the network. pub type Result = std::result::Result; /// Error type for the network. -#[derive(Debug, derive_more::Display, derive_more::From)] +#[derive(derive_more::Display, derive_more::From)] pub enum Error { /// Io error Io(std::io::Error), /// Client error Client(client::error::Error), + /// The same bootnode (based on address) is registered with two different peer ids. + #[display( + fmt = "The same bootnode (`{}`) is registered with two different peer ids: `{}` and `{}`", + address, + first_id, + second_id, + )] + DuplicateBootnode { + /// The address of the bootnode. + address: Multiaddr, + /// The first peer id that was found for the bootnode. + first_id: PeerId, + /// The second peer id that was found for the bootnode. + second_id: PeerId, + }, +} + +// Make `Debug` use the `Display` implementation. +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } } impl std::error::Error for Error { @@ -35,6 +61,7 @@ impl std::error::Error for Error { match self { Error::Io(ref err) => Some(err), Error::Client(ref err) => Some(err), + Error::DuplicateBootnode { .. } => None, } } } diff --git a/core/network/src/legacy_proto/behaviour.rs b/core/network/src/legacy_proto/behaviour.rs index 1c83329ba0e100195db9adb480b14ba58e775ea4..d1d378174a21b0ec7b35923b0eee7f1c841d31bc 100644 --- a/core/network/src/legacy_proto/behaviour.rs +++ b/core/network/src/legacy_proto/behaviour.rs @@ -17,7 +17,7 @@ use crate::{DiscoveryNetBehaviour, config::ProtocolId}; use crate::legacy_proto::handler::{CustomProtoHandlerProto, CustomProtoHandlerOut, CustomProtoHandlerIn}; use crate::legacy_proto::upgrade::RegisteredProtocol; -use crate::protocol::message::Message; +use bytes::BytesMut; use fnv::FnvHashMap; use futures::prelude::*; use futures03::{compat::Compat, TryFutureExt as _, StreamExt as _, TryStreamExt as _}; @@ -25,7 +25,6 @@ use libp2p::core::{ConnectedPoint, Multiaddr, PeerId}; use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; use log::{debug, error, trace, warn}; use rand::distributions::{Distribution as _, Uniform}; -use sr_primitives::traits::Block as BlockT; use smallvec::SmallVec; use std::{borrow::Cow, collections::hash_map::Entry, cmp, error, marker::PhantomData, mem, pin::Pin}; use std::time::{Duration, Instant}; @@ -61,9 +60,9 @@ use tokio_io::{AsyncRead, AsyncWrite}; /// Note that this "banning" system is not an actual ban. If a "banned" node tries to connect to /// us, we accept the connection. The "banning" system is only about delaying dialing attempts. /// -pub struct LegacyProto { +pub struct LegacyProto< TSubstream> { /// List of protocols to open with peers. Never modified. - protocol: RegisteredProtocol, + protocol: RegisteredProtocol, /// Receiver for instructions about who to connect to or disconnect from. peerset: peerset::Peerset, @@ -80,7 +79,7 @@ pub struct LegacyProto { next_incoming_index: peerset::IncomingIndex, /// Events to produce from `poll()`. - events: SmallVec<[NetworkBehaviourAction, LegacyProtoOut>; 4]>, + events: SmallVec<[NetworkBehaviourAction; 4]>, /// Marker to pin the generics. marker: PhantomData, @@ -189,7 +188,7 @@ struct IncomingPeer { /// Event that can be emitted by the `LegacyProto`. #[derive(Debug)] -pub enum LegacyProtoOut { +pub enum LegacyProtoOut { /// Opened a custom protocol with the remote. CustomProtocolOpen { /// Version of the protocol that has been opened. @@ -213,7 +212,7 @@ pub enum LegacyProtoOut { /// Id of the peer the message came from. peer_id: PeerId, /// Message that has been received. - message: Message, + message: BytesMut, }, /// The substream used by the protocol is pretty large. We should print avoid sending more @@ -222,11 +221,11 @@ pub enum LegacyProtoOut { /// Id of the peer which is clogged. peer_id: PeerId, /// Copy of the messages that are within the buffer, for further diagnostic. - messages: Vec>, + messages: Vec>, }, } -impl LegacyProto { +impl LegacyProto { /// Creates a `CustomProtos`. pub fn new( protocol: impl Into, @@ -350,8 +349,7 @@ impl LegacyProto { /// /// Also note that even we have a valid open substream, it may in fact be already closed /// without us knowing, in which case the packet will not be received. - pub fn send_packet(&mut self, target: &PeerId, message: Message) - where B: BlockT { + pub fn send_packet(&mut self, target: &PeerId, message: Vec) { if !self.is_open(target) { return; } @@ -607,7 +605,7 @@ impl LegacyProto { } } -impl DiscoveryNetBehaviour for LegacyProto { +impl DiscoveryNetBehaviour for LegacyProto { fn add_discovered_nodes(&mut self, peer_ids: impl Iterator) { self.peerset.discovered(peer_ids.into_iter().map(|peer_id| { debug!(target: "sub-libp2p", "PSM <= Discovered({:?})", peer_id); @@ -616,13 +614,12 @@ impl DiscoveryNetBehaviour for LegacyProto } } -impl NetworkBehaviour for LegacyProto +impl NetworkBehaviour for LegacyProto where TSubstream: AsyncRead + AsyncWrite, - B: BlockT, { - type ProtocolsHandler = CustomProtoHandlerProto; - type OutEvent = LegacyProtoOut; + type ProtocolsHandler = CustomProtoHandlerProto; + type OutEvent = LegacyProtoOut; fn new_handler(&mut self) -> Self::ProtocolsHandler { CustomProtoHandlerProto::new(self.protocol.clone()) @@ -825,7 +822,7 @@ where fn inject_node_event( &mut self, source: PeerId, - event: CustomProtoHandlerOut, + event: CustomProtoHandlerOut, ) { match event { CustomProtoHandlerOut::CustomProtocolClosed { reason } => { @@ -954,7 +951,7 @@ where _params: &mut impl PollParameters, ) -> Async< NetworkBehaviourAction< - CustomProtoHandlerIn, + CustomProtoHandlerIn, Self::OutEvent, >, > { diff --git a/core/network/src/legacy_proto/handler.rs b/core/network/src/legacy_proto/handler.rs index 3fe88d3cfd410a83392cb875e8edb813854f70e3..7bdbe4a31ff7cdab0d74ade7d1a3812494010aa1 100644 --- a/core/network/src/legacy_proto/handler.rs +++ b/core/network/src/legacy_proto/handler.rs @@ -15,7 +15,7 @@ // along with Substrate. If not, see . use crate::legacy_proto::upgrade::{RegisteredProtocol, RegisteredProtocolEvent, RegisteredProtocolSubstream}; -use crate::protocol::message::Message; +use bytes::BytesMut; use futures::prelude::*; use futures03::{compat::Compat, TryFutureExt as _}; use futures_timer::Delay; @@ -29,7 +29,6 @@ use libp2p::swarm::{ SubstreamProtocol, }; use log::{debug, error}; -use sr_primitives::traits::Block as BlockT; use smallvec::{smallvec, SmallVec}; use std::{borrow::Cow, error, fmt, io, marker::PhantomData, mem, time::Duration}; use tokio_io::{AsyncRead, AsyncWrite}; @@ -88,21 +87,20 @@ use tokio_io::{AsyncRead, AsyncWrite}; /// We consider that we are now "closed" if the remote closes all the existing substreams. /// Re-opening it can then be performed by closing all active substream and re-opening one. /// -pub struct CustomProtoHandlerProto { +pub struct CustomProtoHandlerProto { /// Configuration for the protocol upgrade to negotiate. - protocol: RegisteredProtocol, + protocol: RegisteredProtocol, /// Marker to pin the generic type. marker: PhantomData, } -impl CustomProtoHandlerProto +impl CustomProtoHandlerProto where TSubstream: AsyncRead + AsyncWrite, - B: BlockT, { /// Builds a new `CustomProtoHandlerProto`. - pub fn new(protocol: RegisteredProtocol) -> Self { + pub fn new(protocol: RegisteredProtocol) -> Self { CustomProtoHandlerProto { protocol, marker: PhantomData, @@ -110,14 +108,13 @@ where } } -impl IntoProtocolsHandler for CustomProtoHandlerProto +impl IntoProtocolsHandler for CustomProtoHandlerProto where TSubstream: AsyncRead + AsyncWrite, - B: BlockT, { - type Handler = CustomProtoHandler; + type Handler = CustomProtoHandler; - fn inbound_protocol(&self) -> RegisteredProtocol { + fn inbound_protocol(&self) -> RegisteredProtocol { self.protocol.clone() } @@ -136,12 +133,12 @@ where } /// The actual handler once the connection has been established. -pub struct CustomProtoHandler { +pub struct CustomProtoHandler { /// Configuration for the protocol upgrade to negotiate. - protocol: RegisteredProtocol, + protocol: RegisteredProtocol, /// State of the communications with the remote. - state: ProtocolState, + state: ProtocolState, /// Identifier of the node we're talking to. Used only for logging purposes and shouldn't have /// any influence on the behaviour. @@ -155,15 +152,15 @@ pub struct CustomProtoHandler { /// /// This queue must only ever be modified to insert elements at the back, or remove the first /// element. - events_queue: SmallVec<[ProtocolsHandlerEvent, (), CustomProtoHandlerOut>; 16]>, + events_queue: SmallVec<[ProtocolsHandlerEvent; 16]>, } /// State of the handler. -enum ProtocolState { +enum ProtocolState { /// Waiting for the behaviour to tell the handler whether it is enabled or disabled. Init { /// List of substreams opened by the remote but that haven't been processed yet. - substreams: SmallVec<[RegisteredProtocolSubstream; 6]>, + substreams: SmallVec<[RegisteredProtocolSubstream; 6]>, /// Deadline after which the initialization is abnormally long. init_deadline: Compat, }, @@ -179,9 +176,9 @@ enum ProtocolState { /// If we are in this state, we have sent a `CustomProtocolOpen` message to the outside. Normal { /// The substreams where bidirectional communications happen. - substreams: SmallVec<[RegisteredProtocolSubstream; 4]>, + substreams: SmallVec<[RegisteredProtocolSubstream; 4]>, /// Contains substreams which are being shut down. - shutdown: SmallVec<[RegisteredProtocolSubstream; 4]>, + shutdown: SmallVec<[RegisteredProtocolSubstream; 4]>, }, /// We are disabled. Contains substreams that are being closed. @@ -189,7 +186,7 @@ enum ProtocolState { /// outside or we have never sent any `CustomProtocolOpen` in the first place. Disabled { /// List of substreams to shut down. - shutdown: SmallVec<[RegisteredProtocolSubstream; 6]>, + shutdown: SmallVec<[RegisteredProtocolSubstream; 6]>, /// If true, we should reactivate the handler after all the substreams in `shutdown` have /// been closed. @@ -210,7 +207,7 @@ enum ProtocolState { /// Event that can be received by a `CustomProtoHandler`. #[derive(Debug)] -pub enum CustomProtoHandlerIn { +pub enum CustomProtoHandlerIn { /// The node should start using custom protocols. Enable, @@ -220,13 +217,13 @@ pub enum CustomProtoHandlerIn { /// Sends a message through a custom protocol substream. SendCustomMessage { /// The message to send. - message: Message, + message: Vec, }, } /// Event that can be emitted by a `CustomProtoHandler`. #[derive(Debug)] -pub enum CustomProtoHandlerOut { +pub enum CustomProtoHandlerOut { /// Opened a custom protocol with the remote. CustomProtocolOpen { /// Version of the protocol that has been opened. @@ -242,14 +239,14 @@ pub enum CustomProtoHandlerOut { /// Receives a message on a custom protocol substream. CustomMessage { /// Message that has been received. - message: Message, + message: BytesMut, }, /// A substream to the remote is clogged. The send buffer is very large, and we should print /// a diagnostic message and/or avoid sending more data. Clogged { /// Copy of the messages that are within the buffer, for further diagnostic. - messages: Vec>, + messages: Vec>, }, /// An error has happened on the protocol level with this node. @@ -261,10 +258,9 @@ pub enum CustomProtoHandlerOut { }, } -impl CustomProtoHandler +impl CustomProtoHandler where TSubstream: AsyncRead + AsyncWrite, - B: BlockT, { /// Enables the handler. fn enable(&mut self) { @@ -342,7 +338,7 @@ where /// Polls the state for events. Optionally returns an event to produce. #[must_use] fn poll_state(&mut self) - -> Option, (), CustomProtoHandlerOut>> { + -> Option> { match mem::replace(&mut self.state, ProtocolState::Poisoned) { ProtocolState::Poisoned => { error!(target: "sub-libp2p", "Handler with {:?} is in poisoned state", @@ -471,7 +467,7 @@ where /// Called by `inject_fully_negotiated_inbound` and `inject_fully_negotiated_outbound`. fn inject_fully_negotiated( &mut self, - mut substream: RegisteredProtocolSubstream + mut substream: RegisteredProtocolSubstream ) { self.state = match mem::replace(&mut self.state, ProtocolState::Poisoned) { ProtocolState::Poisoned => { @@ -516,7 +512,7 @@ where } /// Sends a message to the remote. - fn send_message(&mut self, message: Message) { + fn send_message(&mut self, message: Vec) { match self.state { ProtocolState::Normal { ref mut substreams, .. } => substreams[0].send_message(message), @@ -527,14 +523,14 @@ where } } -impl ProtocolsHandler for CustomProtoHandler -where TSubstream: AsyncRead + AsyncWrite, B: BlockT { - type InEvent = CustomProtoHandlerIn; - type OutEvent = CustomProtoHandlerOut; +impl ProtocolsHandler for CustomProtoHandler +where TSubstream: AsyncRead + AsyncWrite { + type InEvent = CustomProtoHandlerIn; + type OutEvent = CustomProtoHandlerOut; type Substream = TSubstream; type Error = ConnectionKillError; - type InboundProtocol = RegisteredProtocol; - type OutboundProtocol = RegisteredProtocol; + type InboundProtocol = RegisteredProtocol; + type OutboundProtocol = RegisteredProtocol; type OutboundOpenInfo = (); fn listen_protocol(&self) -> SubstreamProtocol { @@ -556,7 +552,7 @@ where TSubstream: AsyncRead + AsyncWrite, B: BlockT { self.inject_fully_negotiated(proto); } - fn inject_event(&mut self, message: CustomProtoHandlerIn) { + fn inject_event(&mut self, message: CustomProtoHandlerIn) { match message { CustomProtoHandlerIn::Disable => self.disable(), CustomProtoHandlerIn::Enable => self.enable(), @@ -613,7 +609,7 @@ where TSubstream: AsyncRead + AsyncWrite, B: BlockT { } } -impl fmt::Debug for CustomProtoHandler +impl fmt::Debug for CustomProtoHandler where TSubstream: AsyncRead + AsyncWrite, { @@ -625,9 +621,9 @@ where /// Given a list of substreams, tries to shut them down. The substreams that have been successfully /// shut down are removed from the list. -fn shutdown_list - (list: &mut SmallVec>>) -where TSubstream: AsyncRead + AsyncWrite, B: BlockT { +fn shutdown_list + (list: &mut SmallVec>>) +where TSubstream: AsyncRead + AsyncWrite { 'outer: for n in (0..list.len()).rev() { let mut substream = list.swap_remove(n); loop { diff --git a/core/network/src/legacy_proto/tests.rs b/core/network/src/legacy_proto/tests.rs index 8fd47843df2e56f07d3a2a2c77a50159400b1bbd..dc6d40eb040d70f189d3b46dccdffceeb8492428 100644 --- a/core/network/src/legacy_proto/tests.rs +++ b/core/network/src/legacy_proto/tests.rs @@ -17,6 +17,7 @@ #![cfg(test)] use futures::{future, prelude::*, try_ready}; +use codec::{Encode, Decode}; use libp2p::core::nodes::Substream; use libp2p::core::{ConnectedPoint, transport::boxed::Boxed, muxing::StreamMuxerBox}; use libp2p::swarm::{Swarm, ProtocolsHandler, IntoProtocolsHandler}; @@ -24,9 +25,9 @@ use libp2p::swarm::{PollParameters, NetworkBehaviour, NetworkBehaviourAction}; use libp2p::{PeerId, Multiaddr, Transport}; use rand::seq::SliceRandom; use std::{io, time::Duration, time::Instant}; -use test_client::runtime::Block; -use crate::message::generic::Message; +use crate::message::Message; use crate::legacy_proto::{LegacyProto, LegacyProtoOut}; +use test_client::runtime::Block; /// Builds two nodes that have each other as bootstrap nodes. /// This is to be used only for testing, and a panic will happen if something goes wrong. @@ -43,14 +44,27 @@ fn build_nodes() .collect(); for index in 0 .. 2 { + let keypair = keypairs[index].clone(); let transport = libp2p::core::transport::MemoryTransport - .with_upgrade(libp2p::secio::SecioConfig::new(keypairs[index].clone())) .and_then(move |out, endpoint| { - let peer_id = out.remote_key.into_peer_id(); - libp2p::core::upgrade::apply(out.stream, libp2p::yamux::Config::default(), endpoint) + let secio = libp2p::secio::SecioConfig::new(keypair); + libp2p::core::upgrade::apply( + out, + secio, + endpoint, + libp2p::core::upgrade::Version::V1 + ) + }) + .and_then(move |(peer_id, stream), endpoint| { + libp2p::core::upgrade::apply( + stream, + libp2p::yamux::Config::default(), + endpoint, + libp2p::core::upgrade::Version::V1 + ) .map(|muxer| (peer_id, libp2p::core::muxing::StreamMuxerBox::new(muxer))) }) - .with_timeout(Duration::from_secs(20)) + .timeout(Duration::from_secs(20)) .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) .boxed(); @@ -101,12 +115,12 @@ fn build_nodes() /// Wraps around the `CustomBehaviour` network behaviour, and adds hardcoded node addresses to it. struct CustomProtoWithAddr { - inner: LegacyProto>, + inner: LegacyProto>, addrs: Vec<(PeerId, Multiaddr)>, } impl std::ops::Deref for CustomProtoWithAddr { - type Target = LegacyProto>; + type Target = LegacyProto>; fn deref(&self) -> &Self::Target { &self.inner @@ -121,8 +135,8 @@ impl std::ops::DerefMut for CustomProtoWithAddr { impl NetworkBehaviour for CustomProtoWithAddr { type ProtocolsHandler = - > as NetworkBehaviour>::ProtocolsHandler; - type OutEvent = > as NetworkBehaviour>::OutEvent; + > as NetworkBehaviour>::ProtocolsHandler; + type OutEvent = > as NetworkBehaviour>::OutEvent; fn new_handler(&mut self) -> Self::ProtocolsHandler { self.inner.new_handler() @@ -209,7 +223,7 @@ fn two_nodes_transfer_lots_of_packets() { for n in 0 .. NUM_PACKETS { service1.send_packet( &peer_id, - Message::ChainSpecific(vec![(n % 256) as u8]) + Message::::ChainSpecific(vec![(n % 256) as u8]).encode() ); } }, @@ -223,11 +237,16 @@ fn two_nodes_transfer_lots_of_packets() { loop { match try_ready!(service2.poll()) { Some(LegacyProtoOut::CustomProtocolOpen { .. }) => {}, - Some(LegacyProtoOut::CustomMessage { message: Message::ChainSpecific(message), .. }) => { - assert_eq!(message.len(), 1); - packet_counter += 1; - if packet_counter == NUM_PACKETS { - return Ok(Async::Ready(())) + Some(LegacyProtoOut::CustomMessage { message, .. }) => { + match Message::::decode(&mut &message[..]).unwrap() { + Message::::ChainSpecific(message) => { + assert_eq!(message.len(), 1); + packet_counter += 1; + if packet_counter == NUM_PACKETS { + return Ok(Async::Ready(())) + } + }, + _ => panic!(), } } _ => panic!(), @@ -248,7 +267,7 @@ fn basic_two_nodes_requests_in_parallel() { let mut to_send = Vec::new(); for _ in 0..200 { // Note: don't make that number too high or the CPU usage will explode. let msg = (0..10).map(|_| rand::random::()).collect::>(); - to_send.push(Message::ChainSpecific(msg)); + to_send.push(Message::::ChainSpecific(msg)); } to_send }; @@ -263,7 +282,7 @@ fn basic_two_nodes_requests_in_parallel() { match try_ready!(service1.poll()) { Some(LegacyProtoOut::CustomProtocolOpen { peer_id, .. }) => { for msg in to_send.drain(..) { - service1.send_packet(&peer_id, msg); + service1.send_packet(&peer_id, msg.encode()); } }, _ => panic!(), @@ -276,7 +295,7 @@ fn basic_two_nodes_requests_in_parallel() { match try_ready!(service2.poll()) { Some(LegacyProtoOut::CustomProtocolOpen { .. }) => {}, Some(LegacyProtoOut::CustomMessage { message, .. }) => { - let pos = to_receive.iter().position(|m| *m == message).unwrap(); + let pos = to_receive.iter().position(|m| m.encode() == message).unwrap(); to_receive.remove(pos); if to_receive.is_empty() { return Ok(Async::Ready(())) diff --git a/core/network/src/legacy_proto/upgrade.rs b/core/network/src/legacy_proto/upgrade.rs index 8831d16f91636ae0a94c1a20fd843b4d781c0a57..fdf23ec351c8a1cfcffdbe31fe6786b04065060e 100644 --- a/core/network/src/legacy_proto/upgrade.rs +++ b/core/network/src/legacy_proto/upgrade.rs @@ -15,15 +15,11 @@ // along with Substrate. If not, see . use crate::config::ProtocolId; -use crate::protocol::message::Message; -use bytes::Bytes; +use bytes::{Bytes, BytesMut}; use libp2p::core::{Negotiated, Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName}; use libp2p::tokio_codec::Framed; -use log::debug; -use std::{collections::VecDeque, io, marker::PhantomData, vec::IntoIter as VecIntoIter}; +use std::{collections::VecDeque, io, vec::IntoIter as VecIntoIter}; use futures::{prelude::*, future, stream}; -use codec::{Decode, Encode}; -use sr_primitives::traits::Block as BlockT; use tokio_io::{AsyncRead, AsyncWrite}; use unsigned_varint::codec::UviBytes; @@ -31,7 +27,7 @@ use unsigned_varint::codec::UviBytes; /// /// Note that "a single protocol" here refers to `par` for example. However /// each protocol can have multiple different versions for networking purposes. -pub struct RegisteredProtocol { +pub struct RegisteredProtocol { /// Id of the protocol for API purposes. id: ProtocolId, /// Base name of the protocol as advertised on the network. @@ -40,11 +36,9 @@ pub struct RegisteredProtocol { /// List of protocol versions that we support. /// Ordered in descending order so that the best comes first. supported_versions: Vec, - /// Marker to pin the generic. - marker: PhantomData, } -impl RegisteredProtocol { +impl RegisteredProtocol { /// Creates a new `RegisteredProtocol`. The `custom_data` parameter will be /// passed inside the `RegisteredProtocolOutput`. pub fn new(protocol: impl Into, versions: &[u8]) @@ -62,24 +56,22 @@ impl RegisteredProtocol { tmp.sort_unstable_by(|a, b| b.cmp(&a)); tmp }, - marker: PhantomData, } } } -impl Clone for RegisteredProtocol { +impl Clone for RegisteredProtocol { fn clone(&self) -> Self { RegisteredProtocol { id: self.id.clone(), base_name: self.base_name.clone(), supported_versions: self.supported_versions.clone(), - marker: PhantomData, } } } /// Output of a `RegisteredProtocol` upgrade. -pub struct RegisteredProtocolSubstream { +pub struct RegisteredProtocolSubstream { /// If true, we are in the process of closing the sink. is_closing: bool, /// Whether the local node opened this substream (dialer), or we received this substream from @@ -96,11 +88,9 @@ pub struct RegisteredProtocolSubstream { /// If true, we have sent a "remote is clogged" event recently and shouldn't send another one /// unless the buffer empties then fills itself again. clogged_fuse: bool, - /// Marker to pin the generic. - marker: PhantomData, } -impl RegisteredProtocolSubstream { +impl RegisteredProtocolSubstream { /// Returns the version of the protocol that was negotiated. pub fn protocol_version(&self) -> u8 { self.protocol_version @@ -124,33 +114,32 @@ impl RegisteredProtocolSubstream { } /// Sends a message to the substream. - pub fn send_message(&mut self, data: Message) - where B: BlockT { + pub fn send_message(&mut self, data: Vec) { if self.is_closing { return } - self.send_queue.push_back(data.encode()); + self.send_queue.push_back(data); } } /// Event produced by the `RegisteredProtocolSubstream`. #[derive(Debug, Clone)] -pub enum RegisteredProtocolEvent { +pub enum RegisteredProtocolEvent { /// Received a message from the remote. - Message(Message), + Message(BytesMut), /// Diagnostic event indicating that the connection is clogged and we should avoid sending too /// many messages to it. Clogged { /// Copy of the messages that are within the buffer, for further diagnostic. - messages: Vec>, + messages: Vec>, }, } -impl Stream for RegisteredProtocolSubstream -where TSubstream: AsyncRead + AsyncWrite, B: BlockT { - type Item = RegisteredProtocolEvent; +impl Stream for RegisteredProtocolSubstream +where TSubstream: AsyncRead + AsyncWrite { + type Item = RegisteredProtocolEvent; type Error = io::Error; fn poll(&mut self) -> Poll, Self::Error> { @@ -179,8 +168,7 @@ where TSubstream: AsyncRead + AsyncWrite, B: BlockT { self.clogged_fuse = true; return Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { messages: self.send_queue.iter() - .map(|m| Decode::decode(&mut &m[..])) - .filter_map(Result::ok) + .map(|m| m.clone()) .collect(), }))) } @@ -199,15 +187,7 @@ where TSubstream: AsyncRead + AsyncWrite, B: BlockT { // Note that `inner` is wrapped in a `Fuse`, therefore we can poll it forever. match self.inner.poll()? { Async::Ready(Some(data)) => { - let message = as Decode>::decode(&mut &data[..]) - .map_err(|err| { - debug!( - target: "sub-libp2p", - "Couldn't decode packet sent by the remote: {:?}: {}", data, err.what(), - ); - io::ErrorKind::InvalidData - })?; - Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) + Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(data)))) } Async::Ready(None) => if !self.requires_poll_complete && self.send_queue.is_empty() { @@ -220,7 +200,7 @@ where TSubstream: AsyncRead + AsyncWrite, B: BlockT { } } -impl UpgradeInfo for RegisteredProtocol { +impl UpgradeInfo for RegisteredProtocol { type Info = RegisteredProtocolName; type InfoIter = VecIntoIter; @@ -255,10 +235,10 @@ impl ProtocolName for RegisteredProtocolName { } } -impl InboundUpgrade for RegisteredProtocol +impl InboundUpgrade for RegisteredProtocol where TSubstream: AsyncRead + AsyncWrite, { - type Output = RegisteredProtocolSubstream; + type Output = RegisteredProtocolSubstream; type Future = future::FutureResult; type Error = io::Error; @@ -281,12 +261,11 @@ where TSubstream: AsyncRead + AsyncWrite, inner: framed.fuse(), protocol_version: info.version, clogged_fuse: false, - marker: PhantomData, }) } } -impl OutboundUpgrade for RegisteredProtocol +impl OutboundUpgrade for RegisteredProtocol where TSubstream: AsyncRead + AsyncWrite, { type Output = >::Output; @@ -308,7 +287,6 @@ where TSubstream: AsyncRead + AsyncWrite, inner: framed.fuse(), protocol_version: info.version, clogged_fuse: false, - marker: PhantomData, }) } } diff --git a/core/network/src/lib.rs b/core/network/src/lib.rs index e5714c66f20a52a9762e3c8687b48d12b53f4a8a..d0977d90c90053fba40cddecd105d54bb83b9e02 100644 --- a/core/network/src/lib.rs +++ b/core/network/src/lib.rs @@ -24,9 +24,7 @@ //! # Node identities and addresses //! //! In a decentralized network, each node possesses a network private key and a network public key. -//! In Substrate, the keys are based on the ed25519 curve. As of the writing of this documentation, -//! the secp256k1 curve can also be used, but is deprecated. Our local node's keypair must be -//! passed as part of the network configuration. +//! In Substrate, the keys are based on the ed25519 curve. //! //! From a node's public key, we can derive its *identity*. In Substrate and libp2p, a node's //! identity is represented with the [`PeerId`] struct. All network communications between nodes on @@ -192,6 +190,7 @@ pub use service::{ NetworkStateInfo, }; pub use protocol::{PeerInfo, Context, consensus_gossip, message, specialization}; +pub use protocol::event::{Event, DhtEvent}; pub use protocol::sync::SyncState; pub use libp2p::{Multiaddr, PeerId}; #[doc(inline)] @@ -286,8 +285,8 @@ pub enum NetworkStatePeerEndpoint { Dialing(Multiaddr), /// We are listening. Listening { - /// Address we're listening on that received the connection. - listen_addr: Multiaddr, + /// Local address of the connection. + local_addr: Multiaddr, /// Address data is sent back to. send_back_addr: Multiaddr, }, @@ -298,9 +297,9 @@ impl From for NetworkStatePeerEndpoint { match endpoint { ConnectedPoint::Dialer { address } => NetworkStatePeerEndpoint::Dialing(address), - ConnectedPoint::Listener { listen_addr, send_back_addr } => + ConnectedPoint::Listener { local_addr, send_back_addr } => NetworkStatePeerEndpoint::Listening { - listen_addr, + local_addr, send_back_addr } } diff --git a/core/network/src/on_demand_layer.rs b/core/network/src/on_demand_layer.rs index 818230eea54b8c3ad741fa0467a141192c914c69..cdcb99a25f99e4854c66f28101af7b44ff698276 100644 --- a/core/network/src/on_demand_layer.rs +++ b/core/network/src/on_demand_layer.rs @@ -17,6 +17,7 @@ //! On-demand requests service. use crate::protocol::light_dispatch::RequestData; +use std::collections::HashMap; use std::sync::Arc; use futures::{prelude::*, sync::mpsc, sync::oneshot}; use futures03::compat::{Compat01As03, Future01CompatExt as _}; @@ -84,7 +85,7 @@ impl Fetcher for OnDemand where B::Header: HeaderT, { type RemoteHeaderResult = Compat01As03>; - type RemoteReadResult = Compat01As03>>>; + type RemoteReadResult = Compat01As03, Option>>>>; type RemoteCallResult = Compat01As03>>; type RemoteChangesResult = Compat01As03, u32)>>>; type RemoteBodyResult = Compat01As03>>; diff --git a/core/network/src/protocol.rs b/core/network/src/protocol.rs index b561322b5bbf8342d7729508152cf4116f7d8da5..35de679489e2512c894689d6fa46b6c465734410 100644 --- a/core/network/src/protocol.rs +++ b/core/network/src/protocol.rs @@ -16,6 +16,7 @@ use crate::{DiscoveryNetBehaviour, config::ProtocolId}; use crate::legacy_proto::{LegacyProto, LegacyProtoOut}; +use bytes::BytesMut; use futures::prelude::*; use futures03::{StreamExt as _, TryStreamExt as _}; use libp2p::{Multiaddr, PeerId}; @@ -23,16 +24,19 @@ use libp2p::core::{ConnectedPoint, nodes::Substream, muxing::StreamMuxerBox}; use libp2p::swarm::{ProtocolsHandler, IntoProtocolsHandler}; use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters}; use primitives::storage::StorageKey; -use consensus::{import_queue::IncomingBlock, import_queue::Origin, BlockOrigin}; +use consensus::{ + BlockOrigin, + block_validation::BlockAnnounceValidator, + import_queue::{BlockImportResult, BlockImportError, IncomingBlock, Origin} +}; +use codec::{Decode, Encode}; use sr_primitives::{generic::BlockId, ConsensusEngineId, Justification}; use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, NumberFor, One, Zero, CheckedSub, SaturatedConversion }; -use consensus::import_queue::{BlockImportResult, BlockImportError}; -use message::{BlockAttributes, Direction, FromBlock, Message, RequestId}; +use message::{BlockAnnounce, BlockAttributes, Direction, FromBlock, Message, RequestId}; use message::generic::{Message as GenericMessage, ConsensusMessage}; -use event::Event; use consensus_gossip::{ConsensusGossip, MessageRecipient as GossipMessageRecipient}; use light_dispatch::{LightDispatch, LightDispatchNetwork, RequestData}; use specialization::NetworkSpecialization; @@ -42,10 +46,11 @@ use crate::config::{BoxFinalityProofRequestBuilder, Roles}; use rustc_hex::ToHex; use std::collections::{BTreeMap, HashMap}; use std::sync::Arc; +use std::fmt::Write; use std::{cmp, num::NonZeroUsize, time}; use log::{trace, debug, warn, error}; use crate::chain::{Client, FinalityProofProvider}; -use client::light::fetcher::{FetchChecker, ChangesProof}; +use client::light::fetcher::{FetchChecker, ChangesProof, StorageProof}; use crate::error; use util::LruHashSet; @@ -64,9 +69,9 @@ const TICK_TIMEOUT: time::Duration = time::Duration::from_millis(1100); const PROPAGATE_TIMEOUT: time::Duration = time::Duration::from_millis(2900); /// Current protocol version. -pub(crate) const CURRENT_VERSION: u32 = 3; +pub(crate) const CURRENT_VERSION: u32 = 4; /// Lowest version we support -pub(crate) const MIN_VERSION: u32 = 2; +pub(crate) const MIN_VERSION: u32 = 3; // Maximum allowed entries in `BlockResponse` const MAX_BLOCK_DATA_RESPONSE: u32 = 128; @@ -85,9 +90,13 @@ const UNEXPECTED_STATUS_REPUTATION_CHANGE: i32 = -(1 << 20); /// Reputation change when we are a light client and a peer is behind us. const PEER_BEHIND_US_LIGHT_REPUTATION_CHANGE: i32 = -(1 << 8); /// Reputation change when a peer sends us an extrinsic that we didn't know about. -const NEW_EXTRINSIC_REPUTATION_CHANGE: i32 = 1 << 7; +const GOOD_EXTRINSIC_REPUTATION_CHANGE: i32 = 1 << 7; +/// Reputation change when a peer sends us a bad extrinsic. +const BAD_EXTRINSIC_REPUTATION_CHANGE: i32 = -(1 << 12); /// We sent an RPC query to the given node, but it failed. const RPC_FAILED_REPUTATION_CHANGE: i32 = -(1 << 12); +/// We received a message that failed to decode. +const BAD_MESSAGE_REPUTATION_CHANGE: i32 = -(1 << 12); // Lock must always be taken in order declared here. pub struct Protocol, H: ExHashT> { @@ -111,7 +120,15 @@ pub struct Protocol, H: ExHashT> { /// When asked for a proof of finality, we use this struct to build one. finality_proof_provider: Option>>, /// Handles opening the unique substream and sending and receiving raw messages. - behaviour: LegacyProto>, + behaviour: LegacyProto>, +} + +#[derive(Default)] +struct PacketStats { + bytes_in: u64, + bytes_out: u64, + count_in: u64, + count_out: u64, } /// A peer that we are connected to @@ -149,12 +166,12 @@ pub struct PeerInfo { pub best_number: ::Number, } -struct LightDispatchIn<'a, B: BlockT> { - behaviour: &'a mut LegacyProto>, +struct LightDispatchIn<'a> { + behaviour: &'a mut LegacyProto>, peerset: peerset::PeersetHandle, } -impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { +impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a> { fn report_peer(&mut self, who: &PeerId, reputation: i32) { self.peerset.report_peer(who.clone(), reputation) } @@ -164,22 +181,28 @@ impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { } fn send_header_request(&mut self, who: &PeerId, id: RequestId, block: <::Header as HeaderT>::Number) { - let message = message::generic::Message::RemoteHeaderRequest(message::RemoteHeaderRequest { + let message: Message = message::generic::Message::RemoteHeaderRequest(message::RemoteHeaderRequest { id, block, }); - self.behaviour.send_packet(who, message) + self.behaviour.send_packet(who, message.encode()) } - fn send_read_request(&mut self, who: &PeerId, id: RequestId, block: ::Hash, key: Vec) { - let message = message::generic::Message::RemoteReadRequest(message::RemoteReadRequest { + fn send_read_request( + &mut self, + who: &PeerId, + id: RequestId, + block: ::Hash, + keys: Vec>, + ) { + let message: Message = message::generic::Message::RemoteReadRequest(message::RemoteReadRequest { id, block, - key, + keys, }); - self.behaviour.send_packet(who, message) + self.behaviour.send_packet(who, message.encode()) } fn send_read_child_request( @@ -188,16 +211,16 @@ impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { id: RequestId, block: ::Hash, storage_key: Vec, - key: Vec + keys: Vec>, ) { - let message = message::generic::Message::RemoteReadChildRequest(message::RemoteReadChildRequest { + let message: Message = message::generic::Message::RemoteReadChildRequest(message::RemoteReadChildRequest { id, block, storage_key, - key, + keys, }); - self.behaviour.send_packet(who, message) + self.behaviour.send_packet(who, message.encode()) } fn send_call_request( @@ -208,14 +231,14 @@ impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { method: String, data: Vec ) { - let message = message::generic::Message::RemoteCallRequest(message::RemoteCallRequest { + let message: Message = message::generic::Message::RemoteCallRequest(message::RemoteCallRequest { id, block, method, data, }); - self.behaviour.send_packet(who, message) + self.behaviour.send_packet(who, message.encode()) } fn send_changes_request( @@ -226,18 +249,20 @@ impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { last: ::Hash, min: ::Hash, max: ::Hash, - key: Vec + storage_key: Option>, + key: Vec, ) { - let message = message::generic::Message::RemoteChangesRequest(message::RemoteChangesRequest { + let message: Message = message::generic::Message::RemoteChangesRequest(message::RemoteChangesRequest { id, first, last, min, max, + storage_key, key, }); - self.behaviour.send_packet(who, message) + self.behaviour.send_packet(who, message.encode()) } fn send_body_request( @@ -250,7 +275,7 @@ impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { direction: Direction, max: Option ) { - let message = message::generic::Message::BlockRequest(message::BlockRequest:: { + let message: Message = message::generic::Message::BlockRequest(message::BlockRequest:: { id, fields, from, @@ -259,7 +284,7 @@ impl<'a, B: BlockT> LightDispatchNetwork for LightDispatchIn<'a, B> { max, }); - self.behaviour.send_packet(who, message) + self.behaviour.send_packet(who, message.encode()) } } @@ -281,7 +306,7 @@ pub trait Context { /// Protocol context. struct ProtocolContext<'a, B: 'a + BlockT, H: 'a + ExHashT> { - behaviour: &'a mut LegacyProto>, + behaviour: &'a mut LegacyProto>, context_data: &'a mut ContextData, peerset_handle: &'a peerset::PeersetHandle, } @@ -289,7 +314,7 @@ struct ProtocolContext<'a, B: 'a + BlockT, H: 'a + ExHashT> { impl<'a, B: BlockT + 'a, H: 'a + ExHashT> ProtocolContext<'a, B, H> { fn new( context_data: &'a mut ContextData, - behaviour: &'a mut LegacyProto>, + behaviour: &'a mut LegacyProto>, peerset_handle: &'a peerset::PeersetHandle, ) -> Self { ProtocolContext { context_data, peerset_handle, behaviour } @@ -306,19 +331,19 @@ impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, } fn send_consensus(&mut self, who: PeerId, consensus: ConsensusMessage) { - send_message( + send_message:: ( self.behaviour, - &mut self.context_data.peers, - who, + &mut self.context_data.stats, + &who, GenericMessage::Consensus(consensus) ) } fn send_chain_specific(&mut self, who: PeerId, message: Vec) { - send_message( + send_message:: ( self.behaviour, - &mut self.context_data.peers, - who, + &mut self.context_data.stats, + &who, GenericMessage::ChainSpecific(message) ) } @@ -328,6 +353,7 @@ impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context for ProtocolContext<'a, B, struct ContextData { // All connected peers peers: HashMap>, + stats: HashMap<&'static str, PacketStats>, pub chain: Arc>, } @@ -358,9 +384,16 @@ impl, H: ExHashT> Protocol { finality_proof_request_builder: Option>, protocol_id: ProtocolId, peerset_config: peerset::PeersetConfig, + block_announce_validator: Box + Send> ) -> error::Result<(Protocol, peerset::PeersetHandle)> { let info = chain.info(); - let sync = ChainSync::new(config.roles, chain.clone(), &info, finality_proof_request_builder); + let sync = ChainSync::new( + config.roles, + chain.clone(), + &info, + finality_proof_request_builder, + block_announce_validator, + ); let (peerset, peerset_handle) = peerset::Peerset::from_config(peerset_config); let versions = &((MIN_VERSION as u8)..=(CURRENT_VERSION as u8)).collect::>(); let behaviour = LegacyProto::new(protocol_id, versions, peerset); @@ -368,15 +401,16 @@ impl, H: ExHashT> Protocol { let protocol = Protocol { tick_timeout: Box::new(futures_timer::Interval::new(TICK_TIMEOUT).map(|v| Ok::<_, ()>(v)).compat()), propagate_timeout: Box::new(futures_timer::Interval::new(PROPAGATE_TIMEOUT).map(|v| Ok::<_, ()>(v)).compat()), - config: config, + config, context_data: ContextData { peers: HashMap::new(), + stats: HashMap::new(), chain, }, light_dispatch: LightDispatch::new(checker), genesis_hash: info.chain.genesis_hash, sync, - specialization: specialization, + specialization, consensus_gossip: ConsensusGossip::new(), handshaking_peers: HashMap::new(), transaction_pool, @@ -497,15 +531,25 @@ impl, H: ExHashT> Protocol { self.context_data.peers.iter().map(|(id, peer)| (id, &peer.info)) } - pub fn on_event(&mut self, event: Event) { - self.specialization.on_event(event); - } - pub fn on_custom_message( &mut self, who: PeerId, - message: Message, + data: BytesMut, ) -> CustomMessageOutcome { + + let message = match as Decode>::decode(&mut &data[..]) { + Ok(message) => message, + Err(err) => { + debug!(target: "sync", "Couldn't decode packet sent by {}: {:?}: {}", who, data, err.what()); + self.peerset_handle.report_peer(who.clone(), BAD_MESSAGE_REPUTATION_CHANGE); + return CustomMessageOutcome::None; + } + }; + + let mut stats = self.context_data.stats.entry(message.id()).or_default(); + stats.bytes_in += data.len() as u64; + stats.count_in += 1; + match message { GenericMessage::Status(s) => self.on_status_message(who, s), GenericMessage::BlockRequest(r) => self.on_block_request(who, r), @@ -547,7 +591,8 @@ impl, H: ExHashT> Protocol { self.on_finality_proof_request(who, request), GenericMessage::FinalityProofResponse(response) => return self.on_finality_proof_response(who, response), - GenericMessage::RemoteReadChildRequest(_) => {} + GenericMessage::RemoteReadChildRequest(request) => + self.on_remote_read_child_request(who, request), GenericMessage::Consensus(msg) => { if self.context_data.peers.get(&who).map_or(false, |peer| peer.info.protocol_version > 2) { self.consensus_gossip.on_incoming( @@ -567,15 +612,25 @@ impl, H: ExHashT> Protocol { CustomMessageOutcome::None } - fn send_message(&mut self, who: PeerId, message: Message) { - send_message::( + fn send_request(&mut self, who: &PeerId, message: Message) { + send_request::( &mut self.behaviour, + &mut self.context_data.stats, &mut self.context_data.peers, who, message, ); } + fn send_message(&mut self, who: &PeerId, message: Message) { + send_message::( + &mut self.behaviour, + &mut self.context_data.stats, + who, + message, + ); + } + /// Locks `self` and returns a context plus the `ConsensusGossip` struct. pub fn consensus_gossip_lock<'a>( &'a mut self, @@ -608,7 +663,7 @@ impl, H: ExHashT> Protocol { GossipMessageRecipient::BroadcastNew => self.consensus_gossip.multicast(&mut context, topic, message, false), GossipMessageRecipient::Peer(who) => - self.send_message(who, GenericMessage::Consensus(message)), + self.send_message(&who, GenericMessage::Consensus(message)), } } @@ -731,7 +786,7 @@ impl, H: ExHashT> Protocol { blocks: blocks, }; trace!(target: "sync", "Sending BlockResponse with {} blocks", response.blocks.len()); - self.send_message(peer, GenericMessage::BlockResponse(response)) + self.send_message(&peer, GenericMessage::BlockResponse(response)) } /// Adjusts the reputation of a node. @@ -778,7 +833,7 @@ impl, H: ExHashT> Protocol { Ok(sync::OnBlockData::Import(origin, blocks)) => CustomMessageOutcome::BlockImport(origin, blocks), Ok(sync::OnBlockData::Request(peer, req)) => { - self.send_message(peer, GenericMessage::BlockRequest(req)); + self.send_request(&peer, GenericMessage::BlockRequest(req)); CustomMessageOutcome::None } Err(sync::BadPeer(id, repu)) => { @@ -925,7 +980,7 @@ impl, H: ExHashT> Protocol { }, who.clone(), status.roles, status.best_number); match self.sync.new_peer(who.clone(), info) { Ok(None) => (), - Ok(Some(req)) => self.send_message(who.clone(), GenericMessage::BlockRequest(req)), + Ok(Some(req)) => self.send_request(&who, GenericMessage::BlockRequest(req)), Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id); self.peerset_handle.report_peer(id, repu) @@ -944,6 +999,14 @@ impl, H: ExHashT> Protocol { who: PeerId, extrinsics: message::Transactions ) { + // sending extrinsic to light node is considered a bad behavior + if !self.config.roles.is_full() { + trace!(target: "sync", "Peer {} is trying to send extrinsic to the light node", who); + self.behaviour.disconnect_peer(&who); + self.peerset_handle.report_peer(who, i32::min_value()); + return; + } + // Accept extrinsics only when fully synced if self.sync.status().state != SyncState::Idle { trace!(target: "sync", "{} Ignoring extrinsics while syncing", who); @@ -952,12 +1015,16 @@ impl, H: ExHashT> Protocol { trace!(target: "sync", "Received {} extrinsics from {}", extrinsics.len(), who); if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { for t in extrinsics { - if let Some(hash) = self.transaction_pool.import(&t) { - self.peerset_handle.report_peer(who.clone(), NEW_EXTRINSIC_REPUTATION_CHANGE); - peer.known_extrinsics.insert(hash); - } else { - trace!(target: "sync", "Extrinsic rejected"); - } + let hash = self.transaction_pool.hash_of(&t); + peer.known_extrinsics.insert(hash); + + self.transaction_pool.import( + self.peerset_handle.clone().into(), + who.clone(), + GOOD_EXTRINSIC_REPUTATION_CHANGE, + BAD_EXTRINSIC_REPUTATION_CHANGE, + t, + ); } } } @@ -976,6 +1043,11 @@ impl, H: ExHashT> Protocol { let extrinsics = self.transaction_pool.transactions(); let mut propagated_to = HashMap::new(); for (who, peer) in self.context_data.peers.iter_mut() { + // never send extrinsics to the light node + if !peer.info.roles.is_full() { + continue; + } + let (hashes, to_send): (Vec<_>, Vec<_>) = extrinsics .iter() .filter(|&(ref hash, _)| peer.known_extrinsics.insert(hash.clone())) @@ -990,7 +1062,12 @@ impl, H: ExHashT> Protocol { .push(who.to_base58()); } trace!(target: "sync", "Sending {} transactions to {}", to_send.len(), who); - self.behaviour.send_packet(who, GenericMessage::Transactions(to_send)) + send_message:: ( + &mut self.behaviour, + &mut self.context_data.stats, + &who, + GenericMessage::Transactions(to_send) + ) } } @@ -1001,7 +1078,7 @@ impl, H: ExHashT> Protocol { /// /// In chain-based consensus, we often need to make sure non-best forks are /// at least temporarily synced. - pub fn announce_block(&mut self, hash: B::Hash) { + pub fn announce_block(&mut self, hash: B::Hash, data: Vec) { let header = match self.context_data.chain.header(&BlockId::Hash(hash)) { Ok(Some(header)) => header, Ok(None) => { @@ -1019,14 +1096,43 @@ impl, H: ExHashT> Protocol { return; } - let hash = header.hash(); + let is_best = self.context_data.chain.info().chain.best_hash == hash; + debug!(target: "sync", "Reannouncing block {:?}", hash); + self.send_announcement(&header, data, is_best, true) + } - let message = GenericMessage::BlockAnnounce(message::BlockAnnounce { header: header.clone() }); + fn send_announcement(&mut self, header: &B::Header, data: Vec, is_best: bool, force: bool) { + let hash = header.hash(); for (who, ref mut peer) in self.context_data.peers.iter_mut() { - trace!(target: "sync", "Reannouncing block {:?} to {}", hash, who); - peer.known_blocks.insert(hash); - self.behaviour.send_packet(who, message.clone()) + trace!(target: "sync", "Announcing block {:?} to {}", hash, who); + let inserted = peer.known_blocks.insert(hash); + if inserted || force { + let message: Message = GenericMessage::BlockAnnounce(message::BlockAnnounce { + header: header.clone(), + state: if peer.info.protocol_version >= 4 { + if is_best { + Some(message::BlockState::Best) + } else { + Some(message::BlockState::Normal) + } + } else { + None + }, + data: if peer.info.protocol_version >= 4 { + Some(data.clone()) + } else { + None + }, + }); + + send_message:: ( + &mut self.behaviour, + &mut self.context_data.stats, + &who, + message, + ) + } } } @@ -1043,39 +1149,32 @@ impl, H: ExHashT> Protocol { chain_status: self.specialization.status(), }; - self.send_message(who, GenericMessage::Status(status)) + self.send_message(&who, GenericMessage::Status(status)) } - fn on_block_announce( - &mut self, - who: PeerId, - announce: message::BlockAnnounce - ) -> CustomMessageOutcome { - let header = announce.header; - let hash = header.hash(); - { - if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { - peer.known_blocks.insert(hash.clone()); - } + fn on_block_announce(&mut self, who: PeerId, announce: BlockAnnounce) -> CustomMessageOutcome { + let hash = announce.header.hash(); + if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { + peer.known_blocks.insert(hash.clone()); } self.light_dispatch.update_best_number(LightDispatchIn { behaviour: &mut self.behaviour, peerset: self.peerset_handle.clone(), - }, who.clone(), *header.number()); + }, who.clone(), *announce.header.number()); - match self.sync.on_block_announce(who.clone(), hash, &header) { - sync::OnBlockAnnounce::Request(peer, req) => { - self.send_message(peer, GenericMessage::BlockRequest(req)); - return CustomMessageOutcome::None - } + let is_their_best = match announce.state.unwrap_or(message::BlockState::Best) { + message::BlockState::Best => true, + message::BlockState::Normal => false, + }; + + match self.sync.on_block_announce(who.clone(), hash, &announce, is_their_best) { sync::OnBlockAnnounce::Nothing => { - // try_import is only true when we have all data required to import block + // `on_block_announce` returns `OnBlockAnnounce::ImportHeader` + // when we have all data required to import the block // in the BlockAnnounce message. This is only when: // 1) we're on light client; // AND - // - EITHER 2.1) announced block is stale; - // - OR 2.2) announced block is NEW and we normally only want to download this single block (i.e. - // there are no ascendants of this block scheduled for retrieval) + // 2) parent block is already imported and not pruned. return CustomMessageOutcome::None } sync::OnBlockAnnounce::ImportHeader => () // We proceed with the import. @@ -1098,7 +1197,7 @@ impl, H: ExHashT> Protocol { blocks: vec![ message::generic::BlockData { hash: hash, - header: Some(header), + header: Some(announce.header), body: None, receipt: None, message_queue: None, @@ -1110,7 +1209,7 @@ impl, H: ExHashT> Protocol { match blocks_to_import { Ok(sync::OnBlockData::Import(origin, blocks)) => CustomMessageOutcome::BlockImport(origin, blocks), Ok(sync::OnBlockData::Request(peer, req)) => { - self.send_message(peer, GenericMessage::BlockRequest(req)); + self.send_request(&peer, GenericMessage::BlockRequest(req)); CustomMessageOutcome::None } Err(sync::BadPeer(id, repu)) => { @@ -1123,8 +1222,10 @@ impl, H: ExHashT> Protocol { /// Call this when a block has been imported in the import queue and we should announce it on /// the network. - pub fn on_block_imported(&mut self, hash: B::Hash, header: &B::Header) { - self.sync.update_chain_info(header); + pub fn on_block_imported(&mut self, hash: B::Hash, header: &B::Header, data: Vec, is_best: bool) { + if is_best { + self.sync.update_chain_info(header); + } self.specialization.on_block_imported( &mut ProtocolContext::new(&mut self.context_data, &mut self.behaviour, &self.peerset_handle), hash.clone(), @@ -1137,15 +1238,7 @@ impl, H: ExHashT> Protocol { } // send out block announcements - - let message = GenericMessage::BlockAnnounce(message::BlockAnnounce { header: header.clone() }); - - for (who, ref mut peer) in self.context_data.peers.iter_mut() { - if peer.known_blocks.insert(hash.clone()) { - trace!(target: "sync", "Announcing block {:?} to {}", hash, who); - self.behaviour.send_packet(who, message.clone()) - } - } + self.send_announcement(header, data, is_best, false); } /// Call this when a block has been finalized. The sync layer may have some additional @@ -1180,12 +1273,12 @@ impl, H: ExHashT> Protocol { error ); self.peerset_handle.report_peer(who.clone(), RPC_FAILED_REPUTATION_CHANGE); - Default::default() + StorageProof::empty() } }; self.send_message( - who, + &who, GenericMessage::RemoteCallResponse(message::RemoteCallResponse { id: request.id, proof, @@ -1201,6 +1294,13 @@ impl, H: ExHashT> Protocol { self.sync.request_justification(&hash, number) } + /// Request syncing for the given block from given set of peers. + /// Uses `protocol` to queue a new block download request and tries to dispatch all pending + /// requests. + pub fn set_sync_fork_request(&mut self, peers: Vec, hash: &B::Hash, number: NumberFor) { + self.sync.set_sync_fork_request(peers, hash, number) + } + /// A batch of blocks have been processed, with or without errors. /// Call this when a batch of blocks have been processed by the importqueue, with or without /// errors. @@ -1221,7 +1321,13 @@ impl, H: ExHashT> Protocol { match result { Ok((id, req)) => { let msg = GenericMessage::BlockRequest(req); - send_message(&mut self.behaviour, &mut self.context_data.peers, id, msg) + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + msg + ) } Err(sync::BadPeer(id, repu)) => { self.behaviour.disconnect_peer(&id); @@ -1269,23 +1375,75 @@ impl, H: ExHashT> Protocol { who: PeerId, request: message::RemoteReadRequest, ) { + let keys_str = || match request.keys.len() { + 1 => request.keys[0].to_hex::(), + _ => format!( + "{}..{}", + request.keys[0].to_hex::(), + request.keys[request.keys.len() - 1].to_hex::(), + ), + }; + trace!(target: "sync", "Remote read request {} from {} ({} at {})", - request.id, who, request.key.to_hex::(), request.block); - let proof = match self.context_data.chain.read_proof(&request.block, &request.key) { + request.id, who, keys_str(), request.block); + let proof = match self.context_data.chain.read_proof(&request.block, &request.keys) { Ok(proof) => proof, Err(error) => { trace!(target: "sync", "Remote read request {} from {} ({} at {}) failed with: {}", request.id, who, - request.key.to_hex::(), + keys_str(), request.block, error ); - Default::default() + StorageProof::empty() } }; self.send_message( - who, + &who, + GenericMessage::RemoteReadResponse(message::RemoteReadResponse { + id: request.id, + proof, + }), + ); + } + + fn on_remote_read_child_request( + &mut self, + who: PeerId, + request: message::RemoteReadChildRequest, + ) { + let keys_str = || match request.keys.len() { + 1 => request.keys[0].to_hex::(), + _ => format!( + "{}..{}", + request.keys[0].to_hex::(), + request.keys[request.keys.len() - 1].to_hex::(), + ), + }; + + trace!(target: "sync", "Remote read child request {} from {} ({} {} at {})", + request.id, who, request.storage_key.to_hex::(), keys_str(), request.block); + let proof = match self.context_data.chain.read_child_proof( + &request.block, + &request.storage_key, + &request.keys, + ) { + Ok(proof) => proof, + Err(error) => { + trace!(target: "sync", "Remote read child request {} from {} ({} {} at {}) failed with: {}", + request.id, + who, + request.storage_key.to_hex::(), + keys_str(), + request.block, + error + ); + StorageProof::empty() + } + }; + self.send_message( + &who, GenericMessage::RemoteReadResponse(message::RemoteReadResponse { id: request.id, proof, @@ -1321,11 +1479,11 @@ impl, H: ExHashT> Protocol { request.block, error ); - (Default::default(), Default::default()) + (Default::default(), StorageProof::empty()) } }; self.send_message( - who, + &who, GenericMessage::RemoteHeaderResponse(message::RemoteHeaderResponse { id: request.id, header, @@ -1354,24 +1512,34 @@ impl, H: ExHashT> Protocol { trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{})", request.id, who, - request.key.to_hex::(), + if let Some(sk) = request.storage_key.as_ref() { + format!("{} : {}", sk.to_hex::(), request.key.to_hex::()) + } else { + request.key.to_hex::() + }, request.first, request.last ); + let storage_key = request.storage_key.map(|sk| StorageKey(sk)); let key = StorageKey(request.key); let proof = match self.context_data.chain.key_changes_proof( request.first, request.last, request.min, request.max, - &key + storage_key.as_ref(), + &key, ) { Ok(proof) => proof, Err(error) => { trace!(target: "sync", "Remote changes proof request {} from {} for key {} ({}..{}) failed with: {}", request.id, who, - key.0.to_hex::(), + if let Some(sk) = storage_key { + format!("{} : {}", sk.0.to_hex::(), key.0.to_hex::()) + } else { + key.0.to_hex::() + }, request.first, request.last, error @@ -1380,12 +1548,12 @@ impl, H: ExHashT> Protocol { max_block: Zero::zero(), proof: vec![], roots: BTreeMap::new(), - roots_proof: vec![], + roots_proof: StorageProof::empty(), } } }; self.send_message( - who, + &who, GenericMessage::RemoteChangesResponse(message::RemoteChangesResponse { id: request.id, max: proof.max_block, @@ -1435,7 +1603,7 @@ impl, H: ExHashT> Protocol { }, }; self.send_message( - who, + &who, GenericMessage::FinalityProofResponse(message::FinalityProofResponse { id: 0, block: request.block, @@ -1472,6 +1640,22 @@ impl, H: ExHashT> Protocol { peerset: self.peerset_handle.clone(), }, peer, response); } + + fn format_stats(&self) -> String { + let mut out = String::new(); + for (id, stats) in &self.context_data.stats { + let _ = writeln!( + &mut out, + "{}: In: {} bytes ({}), Out: {} bytes ({})", + id, + stats.bytes_in, + stats.count_in, + stats.bytes_out, + stats.count_out, + ); + } + out + } } /// Outcome of an incoming custom message. @@ -1483,14 +1667,15 @@ pub enum CustomMessageOutcome { None, } -fn send_message( - behaviour: &mut LegacyProto>, +fn send_request( + behaviour: &mut LegacyProto>, + stats: &mut HashMap<&'static str, PacketStats>, peers: &mut HashMap>, - who: PeerId, + who: &PeerId, mut message: Message, ) { if let GenericMessage::BlockRequest(ref mut r) = message { - if let Some(ref mut peer) = peers.get_mut(&who) { + if let Some(ref mut peer) = peers.get_mut(who) { r.id = peer.next_request_id; peer.next_request_id = peer.next_request_id + 1; if let Some((timestamp, request)) = peer.block_request.take() { @@ -1500,12 +1685,25 @@ fn send_message( peer.block_request = Some((time::Instant::now(), r.clone())); } } - behaviour.send_packet(&who, message); + send_message::(behaviour, stats, who, message) +} + +fn send_message( + behaviour: &mut LegacyProto>, + stats: &mut HashMap<&'static str, PacketStats>, + who: &PeerId, + message: Message, +) { + let encoded = message.encode(); + let mut stats = stats.entry(message.id()).or_default(); + stats.bytes_out += encoded.len() as u64; + stats.count_out += 1; + behaviour.send_packet(who, encoded); } impl, H: ExHashT> NetworkBehaviour for Protocol { - type ProtocolsHandler = > as NetworkBehaviour>::ProtocolsHandler; + type ProtocolsHandler = > as NetworkBehaviour>::ProtocolsHandler; type OutEvent = CustomMessageOutcome; fn new_handler(&mut self) -> Self::ProtocolsHandler { @@ -1550,13 +1748,30 @@ Protocol { } for (id, r) in self.sync.block_requests() { - send_message(&mut self.behaviour, &mut self.context_data.peers, id, GenericMessage::BlockRequest(r)) + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + GenericMessage::BlockRequest(r) + ) } for (id, r) in self.sync.justification_requests() { - send_message(&mut self.behaviour, &mut self.context_data.peers, id, GenericMessage::BlockRequest(r)) + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + GenericMessage::BlockRequest(r) + ) } for (id, r) in self.sync.finality_proof_requests() { - send_message(&mut self.behaviour, &mut self.context_data.peers, id, GenericMessage::FinalityProofRequest(r)) + send_request( + &mut self.behaviour, + &mut self.context_data.stats, + &mut self.context_data.peers, + &id, + GenericMessage::FinalityProofRequest(r)) } let event = match self.behaviour.poll(params) { @@ -1590,8 +1805,9 @@ Protocol { LegacyProtoOut::Clogged { peer_id, messages } => { debug!(target: "sync", "{} clogging messages:", messages.len()); for msg in messages.into_iter().take(5) { - debug!(target: "sync", "{:?}", msg); - self.on_clogged_peer(peer_id.clone(), Some(msg)); + let message: Option> = Decode::decode(&mut &msg[..]).ok(); + debug!(target: "sync", "{:?}", message); + self.on_clogged_peer(peer_id.clone(), message); } CustomMessageOutcome::None } @@ -1639,3 +1855,9 @@ impl, H: ExHashT> DiscoveryNetBehaviour f self.behaviour.add_discovered_nodes(peer_ids) } } + +impl, H: ExHashT> Drop for Protocol { + fn drop(&mut self) { + debug!(target: "sync", "Network stats:\n{}", self.format_stats()); + } +} diff --git a/core/network/src/protocol/consensus_gossip.rs b/core/network/src/protocol/consensus_gossip.rs index 328fe197ea54055ed0a3cde9c70437dae4128b19..f3d4e536a788d2d238c01d5d7adb794e921e3402 100644 --- a/core/network/src/protocol/consensus_gossip.rs +++ b/core/network/src/protocol/consensus_gossip.rs @@ -14,15 +14,41 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Utility for gossip of network messages between authorities. +//! Utility for gossip of network messages between nodes. //! Handles chain-specific and standard BFT messages. +//! +//! Gossip messages are separated by two categories: "topics" and consensus engine ID. +//! The consensus engine ID is sent over the wire with the message, while the topic is not, +//! with the expectation that the topic can be derived implicitly from the content of the +//! message, assuming it is valid. +//! +//! Topics are a single 32-byte tag associated with a message, used to group those messages +//! in an opaque way. Consensus code can invoke `broadcast_topic` to attempt to send all messages +//! under a single topic to all peers who don't have them yet, and `send_topic` to +//! send all messages under a single topic to a specific peer. +//! +//! Each consensus engine ID must have an associated, +//! registered `Validator` for all gossip messages. The primary role of this `Validator` is +//! to process incoming messages from peers, and decide whether to discard them or process +//! them. It also decides whether to re-broadcast the message. +//! +//! The secondary role of the `Validator` is to check if a message is allowed to be sent to a given +//! peer. All messages, before being sent, will be checked against this filter. +//! This enables the validator to use information it's aware of about connected peers to decide +//! whether to send messages to them at any given moment in time - In particular, to wait until +//! peers can accept and process the message before sending it. +//! +//! Lastly, the fact that gossip validators can decide not to rebroadcast messages +//! opens the door for neighbor status packets to be baked into the gossip protocol. +//! These status packets will typically contain light pieces of information +//! used to inform peers of a current view of protocol state. use std::collections::{HashMap, HashSet, hash_map::Entry}; use std::sync::Arc; use std::iter; use std::time; use log::{trace, debug}; -use futures::sync::mpsc; +use futures03::channel::mpsc; use lru_cache::LruCache; use libp2p::PeerId; use sr_primitives::traits::{Block as BlockT, Hash, HashFor}; @@ -63,6 +89,7 @@ struct MessageEntry { message_hash: B::Hash, topic: B::Hash, message: ConsensusMessage, + sender: Option, } /// Consensus message destination. @@ -296,12 +323,14 @@ impl ConsensusGossip { message_hash: B::Hash, topic: B::Hash, message: ConsensusMessage, + sender: Option, ) { if self.known_messages.insert(message_hash.clone(), ()).is_none() { self.messages.push(MessageEntry { message_hash, topic, message, + sender, }); } } @@ -317,7 +346,7 @@ impl ConsensusGossip { message: ConsensusMessage, ) { let message_hash = HashFor::::hash(&message.data[..]); - self.register_message_hashed(message_hash, topic, message); + self.register_message_hashed(message_hash, topic, message, None); } /// Call when a peer has been disconnected to stop tracking gossip status. @@ -403,7 +432,7 @@ impl ConsensusGossip { { tx.unbounded_send(TopicNotification { message: entry.message.data.clone(), - sender: None, + sender: entry.sender.clone(), }) .expect("receiver known to be live; qed"); } @@ -472,7 +501,7 @@ impl ConsensusGossip { } } if keep { - self.register_message_hashed(message_hash, topic, message); + self.register_message_hashed(message_hash, topic, message, Some(who.clone())); } } else { trace!(target:"gossip", "Ignored statement from unregistered peer {}", who); @@ -527,7 +556,7 @@ impl ConsensusGossip { force: bool, ) { let message_hash = HashFor::::hash(&message.data); - self.register_message_hashed(message_hash, topic, message.clone()); + self.register_message_hashed(message_hash, topic, message.clone(), None); let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast }; propagate(protocol, iter::once((&message_hash, &topic, &message)), intent, &mut self.peers, &self.validators); } @@ -579,7 +608,7 @@ impl Validator for DiscardAll { #[cfg(test)] mod tests { use sr_primitives::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; - use futures::Stream; + use futures03::executor::block_on_stream; use super::*; @@ -592,6 +621,7 @@ mod tests { message_hash: $hash, topic: $topic, message: ConsensusMessage { data: $m, engine_id: [0, 0, 0, 0]}, + sender: None, }); } } @@ -640,7 +670,7 @@ mod tests { let m2 = vec![4, 5, 6]; push_msg!(consensus, prev_hash, m1_hash, m1); - push_msg!(consensus, best_hash, m2_hash, m2.clone()); + push_msg!(consensus, best_hash, m2_hash, m2); consensus.known_messages.insert(m1_hash, ()); consensus.known_messages.insert(m2_hash, ()); @@ -662,8 +692,6 @@ mod tests { #[test] fn message_stream_include_those_sent_before_asking_for_stream() { - use futures::Stream; - let mut consensus = ConsensusGossip::::new(); consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); @@ -671,9 +699,9 @@ mod tests { let topic = HashFor::::hash(&[1,2,3]); consensus.register_message(topic, message.clone()); - let stream = consensus.messages_for([0, 0, 0, 0], topic); + let mut stream = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); - assert_eq!(stream.wait().next(), Some(Ok(TopicNotification { message: message.data, sender: None }))); + assert_eq!(stream.next(), Some(TopicNotification { message: message.data, sender: None })); } #[test] @@ -695,16 +723,17 @@ mod tests { let mut consensus = ConsensusGossip::::new(); consensus.register_validator_internal([0, 0, 0, 0], Arc::new(AllowAll)); - let message = ConsensusMessage { data: vec![4, 5, 6], engine_id: [0, 0, 0, 0] }; - let topic = HashFor::::hash(&[1,2,3]); + let data = vec![4, 5, 6]; + let message = ConsensusMessage { data: data.clone(), engine_id: [0, 0, 0, 0] }; + let topic = HashFor::::hash(&[1, 2, 3]); consensus.register_message(topic, message.clone()); - let stream1 = consensus.messages_for([0, 0, 0, 0], topic); - let stream2 = consensus.messages_for([0, 0, 0, 0], topic); + let mut stream1 = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); + let mut stream2 = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); - assert_eq!(stream1.wait().next(), Some(Ok(TopicNotification { message: message.data.clone(), sender: None }))); - assert_eq!(stream2.wait().next(), Some(Ok(TopicNotification { message: message.data, sender: None }))); + assert_eq!(stream1.next(), Some(TopicNotification { message: data.clone(), sender: None })); + assert_eq!(stream2.next(), Some(TopicNotification { message: data, sender: None })); } #[test] @@ -719,9 +748,10 @@ mod tests { consensus.register_message(topic, msg_a); consensus.register_message(topic, msg_b); - let mut stream = consensus.messages_for([0, 0, 0, 0], topic).wait(); + let mut stream = block_on_stream(consensus.messages_for([0, 0, 0, 0], topic)); + + assert_eq!(stream.next(), Some(TopicNotification { message: vec![1, 2, 3], sender: None })); - assert_eq!(stream.next(), Some(Ok(TopicNotification { message: vec![1, 2, 3], sender: None }))); let _ = consensus.live_message_sinks.remove(&([0, 0, 0, 0], topic)); assert_eq!(stream.next(), None); } diff --git a/core/network/src/protocol/event.rs b/core/network/src/protocol/event.rs index 2edbb0fbf7563120dd2378f2c4ccb5eab97c115a..c8bee5588c704f09a9c2c14d1b5b8245cf6bd1cc 100644 --- a/core/network/src/protocol/event.rs +++ b/core/network/src/protocol/event.rs @@ -17,24 +17,26 @@ //! Network event types. These are are not the part of the protocol, but rather //! events that happen on the network like DHT get/put results received. -use libp2p::multihash::Multihash; +use libp2p::kad::record::Key; /// Events generated by DHT as a response to get_value and put_value requests. +#[derive(Debug, Clone)] pub enum DhtEvent { /// The value was found. - ValueFound(Vec<(Multihash, Vec)>), + ValueFound(Vec<(Key, Vec)>), /// The requested record has not been found in the DHT. - ValueNotFound(Multihash), + ValueNotFound(Key), /// The record has been successfully inserted into the DHT. - ValuePut(Multihash), + ValuePut(Key), /// An error has occured while putting a record into the DHT. - ValuePutFailed(Multihash), + ValuePutFailed(Key), } /// Type for events generated by networking layer. +#[derive(Debug, Clone)] pub enum Event { /// Event generated by a DHT. Dht(DhtEvent), diff --git a/core/network/src/protocol/light_dispatch.rs b/core/network/src/protocol/light_dispatch.rs index 8102e378b26660b23b1f6398135b6b5e7a2e9cdd..71322cc78124d59d965291b89fa63e1d00b33110 100644 --- a/core/network/src/protocol/light_dispatch.rs +++ b/core/network/src/protocol/light_dispatch.rs @@ -28,7 +28,7 @@ use linked_hash_map::{Entry, LinkedHashMap}; use client::error::Error as ClientError; use client::light::fetcher::{FetchChecker, RemoteHeaderRequest, RemoteCallRequest, RemoteReadRequest, RemoteChangesRequest, ChangesProof, - RemoteReadChildRequest, RemoteBodyRequest}; + RemoteReadChildRequest, RemoteBodyRequest, StorageProof}; use crate::message::{self, BlockAttributes, Direction, FromBlock, RequestId}; use libp2p::PeerId; use crate::config::Roles; @@ -53,7 +53,13 @@ pub trait LightDispatchNetwork { fn send_header_request(&mut self, who: &PeerId, id: RequestId, block: <::Header as HeaderT>::Number); /// Send to `who` a read request. - fn send_read_request(&mut self, who: &PeerId, id: RequestId, block: ::Hash, key: Vec); + fn send_read_request( + &mut self, + who: &PeerId, + id: RequestId, + block: ::Hash, + keys: Vec>, + ); /// Send to `who` a child read request. fn send_read_child_request( @@ -62,7 +68,7 @@ pub trait LightDispatchNetwork { id: RequestId, block: ::Hash, storage_key: Vec, - key: Vec + keys: Vec>, ); /// Send to `who` a call request. @@ -84,7 +90,8 @@ pub trait LightDispatchNetwork { last: ::Hash, min: ::Hash, max: ::Hash, - key: Vec + storage_key: Option>, + key: Vec, ); /// Send to `who` a body request. @@ -134,10 +141,13 @@ struct Request { pub(crate) enum RequestData { RemoteBody(RemoteBodyRequest, OneShotSender, ClientError>>), RemoteHeader(RemoteHeaderRequest, OneShotSender>), - RemoteRead(RemoteReadRequest, OneShotSender>, ClientError>>), + RemoteRead( + RemoteReadRequest, + OneShotSender, Option>>, ClientError>>, + ), RemoteReadChild( RemoteReadChildRequest, - OneShotSender>, ClientError>> + OneShotSender, Option>>, ClientError>> ), RemoteCall(RemoteCallRequest, OneShotSender, ClientError>>), RemoteChanges( @@ -164,7 +174,7 @@ impl FetchChecker for AlwaysBadChecker { &self, _request: &RemoteHeaderRequest, _remote_header: Option, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> Result { Err(ClientError::Msg("AlwaysBadChecker".into())) } @@ -172,23 +182,23 @@ impl FetchChecker for AlwaysBadChecker { fn check_read_proof( &self, _request: &RemoteReadRequest, - _remote_proof: Vec> - ) -> Result>, ClientError> { + _remote_proof: StorageProof, + ) -> Result,Option>>, ClientError> { Err(ClientError::Msg("AlwaysBadChecker".into())) } fn check_read_child_proof( &self, _request: &RemoteReadChildRequest, - _remote_proof: Vec> - ) -> Result>, ClientError> { + _remote_proof: StorageProof, + ) -> Result, Option>>, ClientError> { Err(ClientError::Msg("AlwaysBadChecker".into())) } fn check_execution_proof( &self, _request: &RemoteCallRequest, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> Result, ClientError> { Err(ClientError::Msg("AlwaysBadChecker".into())) } @@ -603,7 +613,7 @@ impl Request { peer, self.id, data.block, - data.key.clone(), + data.keys.clone(), ), RequestData::RemoteReadChild(ref data, _) => out.send_read_child_request( @@ -611,7 +621,7 @@ impl Request { self.id, data.block, data.storage_key.clone(), - data.key.clone(), + data.keys.clone(), ), RequestData::RemoteCall(ref data, _) => out.send_call_request( @@ -629,6 +639,7 @@ impl Request { data.last_block.1.clone(), data.tries_roots.1.clone(), data.max_block.1.clone(), + data.storage_key.clone(), data.key.clone(), ), RequestData::RemoteBody(ref data, _) => @@ -661,7 +672,7 @@ impl RequestData { #[cfg(test)] pub mod tests { - use std::collections::HashSet; + use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::time::Instant; use futures::{Future, sync::oneshot}; @@ -669,12 +680,12 @@ pub mod tests { use sr_primitives::traits::{Block as BlockT, NumberFor, Header as HeaderT}; use client::{error::{Error as ClientError, Result as ClientResult}}; use client::light::fetcher::{FetchChecker, RemoteHeaderRequest, - ChangesProof, RemoteCallRequest, RemoteReadRequest, + ChangesProof, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest, RemoteChangesRequest, RemoteBodyRequest}; use crate::config::Roles; use crate::message::{self, BlockAttributes, Direction, FromBlock, RequestId}; use libp2p::PeerId; - use super::{REQUEST_TIMEOUT, LightDispatch, LightDispatchNetwork, RequestData}; + use super::{REQUEST_TIMEOUT, LightDispatch, LightDispatchNetwork, RequestData, StorageProof}; use test_client::runtime::{Block, Extrinsic, Header}; struct DummyFetchChecker { ok: bool } @@ -684,7 +695,7 @@ pub mod tests { &self, _request: &RemoteHeaderRequest
, header: Option
, - _remote_proof: Vec> + _remote_proof: StorageProof, ) -> ClientResult
{ match self.ok { true if header.is_some() => Ok(header.unwrap()), @@ -692,25 +703,39 @@ pub mod tests { } } - fn check_read_proof(&self, _: &RemoteReadRequest
, _: Vec>) -> ClientResult>> { + fn check_read_proof( + &self, + request: &RemoteReadRequest
, + _: StorageProof, + ) -> ClientResult, Option>>> { match self.ok { - true => Ok(Some(vec![42])), + true => Ok(request.keys + .iter() + .cloned() + .map(|k| (k, Some(vec![42]))) + .collect() + ), false => Err(ClientError::Backend("Test error".into())), } } fn check_read_child_proof( &self, - _: &RemoteReadChildRequest
, - _: Vec> - ) -> ClientResult>> { + request: &RemoteReadChildRequest
, + _: StorageProof, + ) -> ClientResult, Option>>> { match self.ok { - true => Ok(Some(vec![42])), + true => Ok(request.keys + .iter() + .cloned() + .map(|k| (k, Some(vec![42]))) + .collect() + ), false => Err(ClientError::Backend("Test error".into())), } } - fn check_execution_proof(&self, _: &RemoteCallRequest
, _: Vec>) -> ClientResult> { + fn check_execution_proof(&self, _: &RemoteCallRequest
, _: StorageProof) -> ClientResult> { match self.ok { true => Ok(vec![42]), false => Err(ClientError::Backend("Test error".into())), @@ -756,7 +781,7 @@ pub mod tests { ) { light_dispatch.on_remote_call_response(network_interface, peer, message::RemoteCallResponse { id: id, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); } @@ -781,12 +806,12 @@ pub mod tests { self.disconnected_peers.insert(who.clone()); } fn send_header_request(&mut self, _: &PeerId, _: RequestId, _: <::Header as HeaderT>::Number) {} - fn send_read_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: Vec) {} + fn send_read_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: Vec>) {} fn send_read_child_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: Vec, - _: Vec) {} + _: Vec>) {} fn send_call_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: String, _: Vec) {} fn send_changes_request(&mut self, _: &PeerId, _: RequestId, _: ::Hash, _: ::Hash, - _: ::Hash, _: ::Hash, _: Vec) {} + _: ::Hash, _: ::Hash, _: Option>, _: Vec) {} fn send_body_request(&mut self, _: &PeerId, _: RequestId, _: BlockAttributes, _: FromBlock<::Hash, <::Header as HeaderT>::Number>, _: Option, _: Direction, _: Option) {} } @@ -919,7 +944,7 @@ pub mod tests { light_dispatch.on_remote_read_response(&mut network_interface, peer0.clone(), message::RemoteReadResponse { id: 0, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); assert_disconnected_peer(&network_interface); assert_eq!(light_dispatch.pending_requests.len(), 1); @@ -983,15 +1008,15 @@ pub mod tests { light_dispatch.add_request(&mut network_interface, RequestData::RemoteRead(RemoteReadRequest { header: dummy_header(), block: Default::default(), - key: b":key".to_vec(), + keys: vec![b":key".to_vec()], retry_count: None, }, tx)); light_dispatch.on_remote_read_response(&mut network_interface, peer0.clone(), message::RemoteReadResponse { id: 0, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); - assert_eq!(response.wait().unwrap().unwrap(), Some(vec![42])); + assert_eq!(response.wait().unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42])); } #[test] @@ -1006,16 +1031,16 @@ pub mod tests { header: dummy_header(), block: Default::default(), storage_key: b":child_storage:sub".to_vec(), - key: b":key".to_vec(), + keys: vec![b":key".to_vec()], retry_count: None, }, tx)); light_dispatch.on_remote_read_response(&mut network_interface, peer0.clone(), message::RemoteReadResponse { id: 0, - proof: vec![vec![2]], + proof: StorageProof::empty(), }); - assert_eq!(response.wait().unwrap().unwrap(), Some(vec![42])); + assert_eq!(response.wait().unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42])); } #[test] @@ -1041,7 +1066,7 @@ pub mod tests { extrinsics_root: Default::default(), digest: Default::default(), }), - proof: vec![vec![2]], + proof: StorageProof::empty(), }); assert_eq!( response.wait().unwrap().unwrap().hash(), @@ -1064,6 +1089,7 @@ pub mod tests { max_block: (100, Default::default()), tries_roots: (1, Default::default(), vec![]), key: vec![], + storage_key: None, retry_count: None, }, tx)); @@ -1072,7 +1098,7 @@ pub mod tests { max: 1000, proof: vec![vec![2]], roots: vec![], - roots_proof: vec![], + roots_proof: StorageProof::empty(), }); assert_eq!(response.wait().unwrap().unwrap(), vec![(100, 2)]); } @@ -1120,7 +1146,7 @@ pub mod tests { light_dispatch.on_remote_header_response(&mut network_interface, peer1.clone(), message::RemoteHeaderResponse { id: 0, header: Some(dummy_header()), - proof: vec![], + proof: StorageProof::empty(), }); assert!(!light_dispatch.idle_peers.iter().any(|_| true)); diff --git a/core/network/src/protocol/message.rs b/core/network/src/protocol/message.rs index 4110970f99cec48c97a5e706ea4dafa4567cd1ba..22fb35806da86ffef39d48ba28ab8dc8322c9aae 100644 --- a/core/network/src/protocol/message.rs +++ b/core/network/src/protocol/message.rs @@ -26,6 +26,7 @@ pub use self::generic::{ FinalityProofRequest, FinalityProofResponse, FromBlock, RemoteReadChildRequest, }; +use client::light::fetcher::StorageProof; /// A unique ID of a request. pub type RequestId = u64; @@ -107,13 +108,22 @@ pub enum Direction { Descending = 1, } +/// Block state in the chain. +#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode)] +pub enum BlockState { + /// Block is not part of the best chain. + Normal, + /// Latest best block. + Best, +} + /// Remote call response. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub struct RemoteCallResponse { /// Id of a request this response was made for. pub id: RequestId, /// Execution proof. - pub proof: Vec>, + pub proof: StorageProof, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -122,17 +132,18 @@ pub struct RemoteReadResponse { /// Id of a request this response was made for. pub id: RequestId, /// Read proof. - pub proof: Vec>, + pub proof: StorageProof, } /// Generic types. pub mod generic { - use codec::{Encode, Decode}; + use codec::{Encode, Decode, Input, Output}; use sr_primitives::Justification; use crate::config::Roles; use super::{ RemoteReadResponse, Transactions, Direction, RequestId, BlockAttributes, RemoteCallResponse, ConsensusEngineId, + BlockState, StorageProof, }; /// Consensus is mostly opaque to us #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -211,6 +222,32 @@ pub mod generic { ChainSpecific(Vec), } + impl Message { + /// Message id useful for logging. + pub fn id(&self) -> &'static str { + match self { + Message::Status(_) => "Status", + Message::BlockRequest(_) => "BlockRequest", + Message::BlockResponse(_) => "BlockResponse", + Message::BlockAnnounce(_) => "BlockAnnounce", + Message::Transactions(_) => "Transactions", + Message::Consensus(_) => "Consensus", + Message::RemoteCallRequest(_) => "RemoteCallRequest", + Message::RemoteCallResponse(_) => "RemoteCallResponse", + Message::RemoteReadRequest(_) => "RemoteReadRequest", + Message::RemoteReadResponse(_) => "RemoteReadResponse", + Message::RemoteHeaderRequest(_) => "RemoteHeaderRequest", + Message::RemoteHeaderResponse(_) => "RemoteHeaderResponse", + Message::RemoteChangesRequest(_) => "RemoteChangesRequest", + Message::RemoteChangesResponse(_) => "RemoteChangesResponse", + Message::RemoteReadChildRequest(_) => "RemoteReadChildRequest", + Message::FinalityProofRequest(_) => "FinalityProofRequest", + Message::FinalityProofResponse(_) => "FinalityProofResponse", + Message::ChainSpecific(_) => "ChainSpecific", + } + } + } + /// Status sent on connection. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub struct Status { @@ -257,10 +294,42 @@ pub mod generic { } /// Announce a new complete relay chain block on the network. - #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] + #[derive(Debug, PartialEq, Eq, Clone)] pub struct BlockAnnounce { /// New block header. pub header: H, + /// Block state. TODO: Remove `Option` and custom encoding when v4 becomes common. + pub state: Option, + /// Data associated with this block announcement, e.g. a candidate message. + pub data: Option>, + } + + // Custom Encode/Decode impl to maintain backwards compatibility with v3. + // This assumes that the packet contains nothing but the announcement message. + // TODO: Get rid of it once protocol v4 is common. + impl Encode for BlockAnnounce { + fn encode_to(&self, dest: &mut T) { + self.header.encode_to(dest); + if let Some(state) = &self.state { + state.encode_to(dest); + } + if let Some(data) = &self.data { + data.encode_to(dest) + } + } + } + + impl Decode for BlockAnnounce { + fn decode(input: &mut I) -> Result { + let header = H::decode(input)?; + let state = BlockState::decode(input).ok(); + let data = Vec::decode(input).ok(); + Ok(BlockAnnounce { + header, + state, + data, + }) + } } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -284,7 +353,7 @@ pub mod generic { /// Block at which to perform call. pub block: H, /// Storage key. - pub key: Vec, + pub keys: Vec>, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -297,7 +366,7 @@ pub mod generic { /// Child Storage key. pub storage_key: Vec, /// Storage key. - pub key: Vec, + pub keys: Vec>, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -317,7 +386,7 @@ pub mod generic { /// Header. None if proof generation has failed (e.g. header is unknown). pub header: Option
, /// Header proof. - pub proof: Vec>, + pub proof: StorageProof, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -334,6 +403,8 @@ pub mod generic { pub min: H, /// Hash of the last block that we can use when querying changes. pub max: H, + /// Storage child node key which changes are requested. + pub storage_key: Option>, /// Storage key which changes are requested. pub key: Vec, } @@ -351,7 +422,7 @@ pub mod generic { /// Changes tries roots missing on the requester' node. pub roots: Vec<(N, H)>, /// Missing changes tries roots proof. - pub roots_proof: Vec>, + pub roots_proof: StorageProof, } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] diff --git a/core/network/src/protocol/specialization.rs b/core/network/src/protocol/specialization.rs index e2c444ea889d6b8d336394c6c1cdff67119bd520..1a15c47c87d3a45d9653e029831367c56c33efff 100644 --- a/core/network/src/protocol/specialization.rs +++ b/core/network/src/protocol/specialization.rs @@ -42,7 +42,8 @@ pub trait NetworkSpecialization: Send + Sync + 'static { ); /// Called when a network-specific event arrives. - fn on_event(&mut self, event: Event); + #[deprecated(note = "This method is never called; please use `with_dht_event_tx` when building the service")] + fn on_event(&mut self, _event: Event) {} /// Called on abort. #[deprecated(note = "This method is never called; aborting corresponds to dropping the object")] diff --git a/core/network/src/protocol/sync.rs b/core/network/src/protocol/sync.rs index bd67c6cde7e6c868b95f340cff32ca398c5aee09..34bc68f933686bf13d2b90ddc7357fb2a1dcc02c 100644 --- a/core/network/src/protocol/sync.rs +++ b/core/network/src/protocol/sync.rs @@ -28,11 +28,15 @@ //! use blocks::BlockCollection; -use client::{BlockStatus, ClientInfo, error::Error as ClientError}; -use consensus::{BlockOrigin, import_queue::{IncomingBlock, BlockImportResult, BlockImportError}}; +use client::{ClientInfo, error::Error as ClientError}; +use consensus::{BlockOrigin, BlockStatus, + block_validation::{BlockAnnounceValidator, Validation}, + import_queue::{IncomingBlock, BlockImportResult, BlockImportError} +}; use crate::{ config::{Roles, BoxFinalityProofRequestBuilder}, - message::{self, generic::FinalityProofRequest, BlockAttributes, BlockRequest, BlockResponse, FinalityProofResponse}, + message::{self, generic::FinalityProofRequest, BlockAnnounce, BlockAttributes, BlockRequest, BlockResponse, + FinalityProofResponse}, protocol }; use either::Either; @@ -65,9 +69,6 @@ const MAJOR_SYNC_BLOCKS: u8 = 5; /// Number of recently announced blocks to track for each peer. const ANNOUNCE_HISTORY_SIZE: usize = 64; -/// Max number of blocks to download for unknown forks. -const MAX_UNKNOWN_FORK_DOWNLOAD_LEN: u32 = 32; - /// Reputation change when a peer sent us a status message that led to a /// database read error. const BLOCKCHAIN_STATUS_READ_ERROR_REPUTATION_CHANGE: i32 = -(1 << 16); @@ -119,9 +120,14 @@ pub struct ChainSync { queue_blocks: HashSet, /// The best block number that we are currently importing. best_importing_number: NumberFor, + /// Finality proof handler. request_builder: Option>, + /// Fork sync targets. + fork_targets: HashMap>, /// A flag that caches idle state with no pending requests. is_idle: bool, + /// A type to check incoming block announcements. + block_announce_validator: Box + Send> } /// All the data we have about a Peer that we are trying to sync with @@ -151,6 +157,12 @@ pub struct PeerInfo { pub best_number: NumberFor } +struct ForkTarget { + number: NumberFor, + parent_hash: Option, + peers: HashSet, +} + /// The state of syncing between a Peer and ourselves. /// /// Generally two categories, "busy" or `Available`. If busy, the enum @@ -228,13 +240,11 @@ pub enum OnBlockData { /// Result of [`ChainSync::on_block_announce`]. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum OnBlockAnnounce { +pub enum OnBlockAnnounce { /// The announcement does not require further handling. Nothing, /// The announcement header should be imported. ImportHeader, - /// Another block request to the given peer is necessary. - Request(PeerId, BlockRequest) } /// Result of [`ChainSync::on_block_justification`]. @@ -271,7 +281,8 @@ impl ChainSync { role: Roles, client: Arc>, info: &ClientInfo, - request_builder: Option> + request_builder: Option>, + block_announce_validator: Box + Send> ) -> Self { let mut required_block_attributes = BlockAttributes::HEADER | BlockAttributes::JUSTIFICATION; @@ -292,7 +303,9 @@ impl ChainSync { queue_blocks: Default::default(), best_importing_number: Zero::zero(), request_builder, + fork_targets: Default::default(), is_idle: false, + block_announce_validator, } } @@ -379,7 +392,8 @@ impl ChainSync { state: PeerSyncState::Available, recently_announced: Default::default(), }); - return Ok(self.select_new_blocks(who).map(|(_, req)| req)) + self.is_idle = false; + return Ok(None) } let common_best = std::cmp::min(self.best_queued_number, info.best_number); @@ -441,6 +455,62 @@ impl ChainSync { }) } + /// Request syncing for the given block from given set of peers. + // The implementation is similar to on_block_announce with unknown parent hash. + pub fn set_sync_fork_request(&mut self, mut peers: Vec, hash: &B::Hash, number: NumberFor) { + if peers.is_empty() { + debug!( + target: "sync", + "Explicit sync request for block {:?} with no peers specified. \ + Syncing from all connected peers {:?} instead.", + hash, peers, + ); + + peers = self.peers.iter() + // Only request blocks from peers who are ahead or on a par. + .filter(|(_, peer)| peer.best_number >= number) + .map(|(id, _)| id.clone()) + .collect(); + } else { + debug!(target: "sync", "Explicit sync request for block {:?} with {:?}", hash, peers); + } + + if self.is_known(&hash) { + debug!(target: "sync", "Refusing to sync known hash {:?}", hash); + return; + } + + let block_status = self.client.block_status(&BlockId::Number(number - One::one())) + .unwrap_or(BlockStatus::Unknown); + if block_status == BlockStatus::InChainPruned { + trace!(target: "sync", "Refusing to sync ancient block {:?}", hash); + return; + } + + self.is_idle = false; + for peer_id in &peers { + if let Some(peer) = self.peers.get_mut(peer_id) { + if let PeerSyncState::AncestorSearch(_, _) = peer.state { + continue; + } + + if number > peer.best_number { + peer.best_number = number; + peer.best_hash = hash.clone(); + } + } + } + + self.fork_targets + .entry(hash.clone()) + .or_insert_with(|| ForkTarget { + number, + peers: Default::default(), + parent_hash: None, + }) + .peers.extend(peers); + } + /// Get an iterator over all scheduled justification requests. pub fn justification_requests(&mut self) -> impl Iterator)> + '_ { let peers = &mut self.peers; @@ -498,15 +568,37 @@ impl ChainSync { trace!(target: "sync", "Too many blocks in the queue."); return Either::Left(std::iter::empty()) } + let major_sync = self.status().state == SyncState::Downloading; let blocks = &mut self.blocks; let attrs = &self.required_block_attributes; + let fork_targets = &self.fork_targets; let mut have_requests = false; + let last_finalized = self.client.info().chain.finalized_number; + let best_queued = self.best_queued_number; + let client = &self.client; + let queue = &self.queue_blocks; let iter = self.peers.iter_mut().filter_map(move |(id, peer)| { if !peer.state.is_available() { trace!(target: "sync", "Peer {} is busy", id); return None } - if let Some((range, req)) = peer_block_request(id, peer, blocks, attrs) { + if let Some((hash, req)) = fork_sync_request( + id, + fork_targets, + best_queued, + last_finalized, + attrs, + |hash| if queue.contains(hash) { + BlockStatus::Queued + } else { + client.block_status(&BlockId::Hash(*hash)).unwrap_or(BlockStatus::Unknown) + }, + ) { + trace!(target: "sync", "Downloading fork {:?} from {}", hash, id); + peer.state = PeerSyncState::DownloadingStale(hash); + have_requests = true; + Some((id.clone(), req)) + } else if let Some((range, req)) = peer_block_request(id, peer, blocks, attrs, major_sync) { peer.state = PeerSyncState::DownloadingNew(range.start); trace!(target: "sync", "New block request for {}", id); have_requests = true; @@ -595,6 +687,26 @@ impl ChainSync { peer.state = PeerSyncState::AncestorSearch(next_num, next_state); return Ok(OnBlockData::Request(who, ancestry_request::(next_num))) } else { + // Ancestry search is complete. Check if peer is on a stale fork unknown to us and + // add it to sync targets if necessary. + trace!(target: "sync", "Ancestry search complete. Ours={} ({}), Theirs={} ({}), Common={}", + self.best_queued_hash, + self.best_queued_number, + peer.best_hash, + peer.best_number, + peer.common_number + ); + if peer.common_number < peer.best_number && peer.best_number < self.best_queued_number { + trace!(target: "sync", "Added fork target {} for {}" , peer.best_hash, who); + self.fork_targets + .entry(peer.best_hash.clone()) + .or_insert_with(|| ForkTarget { + number: peer.best_number, + parent_hash: None, + peers: Default::default(), + }) + .peers.insert(who); + } peer.state = PeerSyncState::Available; Vec::new() } @@ -659,8 +771,6 @@ impl ChainSync { peer.state = PeerSyncState::Available; // We only request one justification at a time - debug_assert_eq!(1, response.blocks.len()); - if let Some(block) = response.blocks.into_iter().next() { if hash != block.hash { info!( @@ -815,12 +925,7 @@ impl ChainSync { /// with or without errors. pub fn on_justification_import(&mut self, hash: B::Hash, number: NumberFor, success: bool) { let finalization_result = if success { Ok((hash, number)) } else { Err(()) }; - if !self.extra_justifications.try_finalize_root((hash, number), finalization_result, true) { - debug!(target: "sync", "Got justification import result for unknown justification {:?} {:?} request.", - hash, - number, - ) - } + self.extra_justifications.try_finalize_root((hash, number), finalization_result, true); self.is_idle = false; } @@ -859,11 +964,14 @@ impl ChainSync { self.best_queued_number = number; self.best_queued_hash = *hash; } + if let Some(_) = self.fork_targets.remove(&hash) { + trace!(target: "sync", "Completed fork sync {:?}", hash); + } // Update common blocks for (n, peer) in self.peers.iter_mut() { if let PeerSyncState::AncestorSearch(_, _) = peer.state { - // Abort search. - peer.state = PeerSyncState::Available; + // Wait for ancestry search to complete first. + continue; } let new_common_number = if peer.best_number >= number { number @@ -886,11 +994,14 @@ impl ChainSync { /// Call when a node announces a new block. /// - /// If true is returned, then the caller MUST try to import passed + /// If `OnBlockAnnounce::ImportHeader` is returned, then the caller MUST try to import passed /// header (call `on_block_data`). The network request isn't sent /// in this case. Both hash and header is passed as an optimization /// to avoid rehashing the header. - pub fn on_block_announce(&mut self, who: PeerId, hash: B::Hash, header: &B::Header) -> OnBlockAnnounce { + pub fn on_block_announce(&mut self, who: PeerId, hash: B::Hash, announce: &BlockAnnounce, is_best: bool) + -> OnBlockAnnounce + { + let header = &announce.header; let number = *header.number(); debug!(target: "sync", "Received block announcement with number {:?}", number); if number.is_zero() { @@ -912,7 +1023,7 @@ impl ChainSync { peer.recently_announced.pop_front(); } peer.recently_announced.push_back(hash.clone()); - if number > peer.best_number { + if is_best && number > peer.best_number { // update their best block peer.best_number = number; peer.best_hash = hash; @@ -920,61 +1031,35 @@ impl ChainSync { if let PeerSyncState::AncestorSearch(_, _) = peer.state { return OnBlockAnnounce::Nothing } - // We assume that the announced block is the latest they have seen, and so our common number + // If the announced block is the best they have seen, our common number // is either one further ahead or it's the one they just announced, if we know about it. - if header.parent_hash() == &self.best_queued_hash || known_parent { - peer.common_number = number - One::one(); - } else if known { + if known && is_best { peer.common_number = number + } else if header.parent_hash() == &self.best_queued_hash || known_parent { + peer.common_number = number - One::one(); } self.is_idle = false; // known block case if known || self.is_already_downloading(&hash) { trace!(target: "sync", "Known block announce from {}: {}", who, hash); + if let Some(target) = self.fork_targets.get_mut(&hash) { + target.peers.insert(who); + } return OnBlockAnnounce::Nothing } - // stale block case - let requires_additional_data = !self.role.is_light(); - if number <= self.best_queued_number { - if !(known_parent || self.is_already_downloading(header.parent_hash())) { - let block_status = self.client.block_status(&BlockId::Number(*header.number())) - .unwrap_or(BlockStatus::Unknown); - if block_status == BlockStatus::InChainPruned { - trace!( - target: "sync", - "Ignored unknown ancient block announced from {}: {} {:?}", who, hash, header - ); - return OnBlockAnnounce::Nothing - } - trace!( - target: "sync", - "Considering new unknown stale block announced from {}: {} {:?}", who, hash, header - ); - if let Some(request) = self.download_unknown_stale(&who, &hash) { - if requires_additional_data { - return OnBlockAnnounce::Request(who, request) - } else { - return OnBlockAnnounce::ImportHeader - } - } else { - return OnBlockAnnounce::Nothing - } - } else { - if ancient_parent { - trace!(target: "sync", "Ignored ancient stale block announced from {}: {} {:?}", who, hash, header); - return OnBlockAnnounce::Nothing - } - if let Some(request) = self.download_stale(&who, &hash) { - if requires_additional_data { - return OnBlockAnnounce::Request(who, request) - } else { - return OnBlockAnnounce::ImportHeader - } - } else { - return OnBlockAnnounce::Nothing - } + // Let external validator check the block announcement. + let assoc_data = announce.data.as_ref().map_or(&[][..], |v| v.as_slice()); + match self.block_announce_validator.validate(&header, assoc_data) { + Ok(Validation::Success) => (), + Ok(Validation::Failure) => { + debug!(target: "sync", "Block announcement validation of block {} from {} failed", hash, who); + return OnBlockAnnounce::Nothing + } + Err(e) => { + error!(target: "sync", "Block announcement validation errored: {}", e); + return OnBlockAnnounce::Nothing } } @@ -983,22 +1068,28 @@ impl ChainSync { return OnBlockAnnounce::Nothing } - trace!(target: "sync", "Considering new block announced from {}: {} {:?}", who, hash, header); - - let (range, request) = match self.select_new_blocks(who.clone()) { - Some((range, request)) => (range, request), - None => return OnBlockAnnounce::Nothing - }; - - let is_required_data_available = !requires_additional_data - && range.end - range.start == One::one() - && range.start == *header.number(); + let requires_additional_data = !self.role.is_light() || !known_parent; + if !requires_additional_data { + trace!(target: "sync", "Importing new header announced from {}: {} {:?}", who, hash, header); + return OnBlockAnnounce::ImportHeader + } - if !is_required_data_available { - return OnBlockAnnounce::Request(who, request) + if number <= self.best_queued_number { + trace!( + target: "sync", + "Added sync target for block announced from {}: {} {:?}", who, hash, header + ); + self.fork_targets + .entry(hash.clone()) + .or_insert_with(|| ForkTarget { + number, + parent_hash: Some(header.parent_hash().clone()), + peers: Default::default(), + }) + .peers.insert(who); } - OnBlockAnnounce::ImportHeader + OnBlockAnnounce::Nothing } /// Call when a peer has disconnected. @@ -1034,73 +1125,6 @@ impl ChainSync { }) } - /// Download old block with known parent. - fn download_stale(&mut self, who: &PeerId, hash: &B::Hash) -> Option> { - let peer = self.peers.get_mut(who)?; - if !peer.state.is_available() { - return None - } - peer.state = PeerSyncState::DownloadingStale(*hash); - Some(message::generic::BlockRequest { - id: 0, - fields: self.required_block_attributes.clone(), - from: message::FromBlock::Hash(*hash), - to: None, - direction: message::Direction::Ascending, - max: Some(1), - }) - } - - /// Download old block with unknown parent. - fn download_unknown_stale(&mut self, who: &PeerId, hash: &B::Hash) -> Option> { - let peer = self.peers.get_mut(who)?; - if !peer.state.is_available() { - return None - } - peer.state = PeerSyncState::DownloadingStale(*hash); - Some(message::generic::BlockRequest { - id: 0, - fields: self.required_block_attributes.clone(), - from: message::FromBlock::Hash(*hash), - to: None, - direction: message::Direction::Descending, - max: Some(MAX_UNKNOWN_FORK_DOWNLOAD_LEN), - }) - } - - /// Select a range of new blocks to download from the given peer. - fn select_new_blocks(&mut self, who: PeerId) -> Option<(Range>, BlockRequest)> { - // when there are too many blocks in the queue => do not try to download new blocks - if self.queue_blocks.len() > MAX_IMPORTING_BLOCKS { - trace!(target: "sync", "Too many blocks in the queue."); - return None - } - - let peer = self.peers.get_mut(&who)?; - - if !peer.state.is_available() { - trace!(target: "sync", "Peer {} is busy", who); - return None - } - - trace!( - target: "sync", - "Considering new block download from {}, common block is {}, best is {:?}", - who, - peer.common_number, - peer.best_number - ); - - if let Some((range, req)) = peer_block_request(&who, peer, &mut self.blocks, &self.required_block_attributes) { - trace!(target: "sync", "Requesting blocks from {}, ({} to {})", who, range.start, range.end); - peer.state = PeerSyncState::DownloadingNew(range.start); - Some((range, req)) - } else { - trace!(target: "sync", "Nothing to request from {}", who); - None - } - } - /// What is the status of the block corresponding to the given hash? fn block_status(&self, hash: &B::Hash) -> Result { if self.queue_blocks.contains(hash) { @@ -1199,8 +1223,16 @@ fn peer_block_request( peer: &PeerSync, blocks: &mut BlockCollection, attrs: &message::BlockAttributes, + major_sync: bool, ) -> Option<(Range>, BlockRequest)> { - if let Some(range) = blocks.needed_blocks(id.clone(), MAX_BLOCKS_TO_REQUEST, peer.best_number, peer.common_number) { + let max_parallel = if major_sync { 1 } else { 3 }; + if let Some(range) = blocks.needed_blocks( + id.clone(), + MAX_BLOCKS_TO_REQUEST, + peer.best_number, + peer.common_number, + max_parallel, + ) { let request = message::generic::BlockRequest { id: 0, fields: attrs.clone(), @@ -1214,3 +1246,38 @@ fn peer_block_request( None } } + +/// Get pending fork sync targets for a peer. +fn fork_sync_request( + id: &PeerId, + targets: &HashMap>, + best_num: NumberFor, + finalized: NumberFor, + attributes: &message::BlockAttributes, + check_block: impl Fn(&B::Hash) -> BlockStatus, +) -> Option<(B::Hash, BlockRequest)> +{ + for (hash, r) in targets { + if !r.peers.contains(id) { + continue + } + if r.number <= best_num { + trace!(target: "sync", "Downloading requested fork {:?} from {}", hash, id); + let parent_status = r.parent_hash.as_ref().map_or(BlockStatus::Unknown, check_block); + let mut count = (r.number - finalized).saturated_into::(); // up to the last finalized block + if parent_status != BlockStatus::Unknown { + // request only single block + count = 1; + } + return Some((hash.clone(), message::generic::BlockRequest { + id: 0, + fields: attributes.clone(), + from: message::FromBlock::Hash(hash.clone()), + to: None, + direction: message::Direction::Descending, + max: Some(count), + })) + } + } + None +} diff --git a/core/network/src/protocol/sync/blocks.rs b/core/network/src/protocol/sync/blocks.rs index 90264249ea03ce113fa4c6946596089d735fb526..a972caf9519ec49dae6a2e42747902cee8a69af8 100644 --- a/core/network/src/protocol/sync/blocks.rs +++ b/core/network/src/protocol/sync/blocks.rs @@ -24,8 +24,6 @@ use libp2p::PeerId; use sr_primitives::traits::{Block as BlockT, NumberFor, One}; use crate::message; -const MAX_PARALLEL_DOWNLOADS: u32 = 1; - /// Block data with origin. #[derive(Debug, Clone, PartialEq, Eq)] pub struct BlockData { @@ -84,9 +82,7 @@ impl BlockCollection { match self.blocks.get(&start) { Some(&BlockRangeState::Downloading { .. }) => { - trace!(target: "sync", "Ignored block data still marked as being downloaded: {}", start); - debug_assert!(false); - return; + trace!(target: "sync", "Inserting block data still marked as being downloaded: {}", start); }, Some(&BlockRangeState::Complete(ref existing)) if existing.len() >= blocks.len() => { trace!(target: "sync", "Ignored block data already downloaded: {}", start); @@ -100,8 +96,15 @@ impl BlockCollection { } /// Returns a set of block hashes that require a header download. The returned set is marked as being downloaded. - pub fn needed_blocks(&mut self, who: PeerId, count: usize, peer_best: NumberFor, common: NumberFor) - -> Option>> { + pub fn needed_blocks( + &mut self, + who: PeerId, + count: usize, + peer_best: NumberFor, + common: NumberFor, + max_parallel: u32, + ) -> Option>> + { // First block number that we need to download let first_different = common + >::one(); let count = (count as u32).into(); @@ -112,7 +115,7 @@ impl BlockCollection { let next = downloading_iter.next(); break match &(prev, next) { &(Some((start, &BlockRangeState::Downloading { ref len, downloading })), _) - if downloading < MAX_PARALLEL_DOWNLOADS => + if downloading < max_parallel => (*start .. *start + *len, downloading), &(Some((start, r)), Some((next_start, _))) if *start + r.len() < *next_start => (*start + r.len() .. cmp::min(*next_start, *start + r.len() + count), 0), // gap @@ -185,7 +188,6 @@ impl BlockCollection { true }, _ => { - debug_assert!(false); false } }; @@ -242,18 +244,18 @@ mod test { let peer2 = PeerId::random(); let blocks = generate_blocks(150); - assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0), Some(1 .. 41)); - assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0), Some(41 .. 81)); - assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 0), Some(81 .. 121)); + assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0, 1), Some(1 .. 41)); + assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0, 1), Some(41 .. 81)); + assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 0, 1), Some(81 .. 121)); bc.clear_peer_download(&peer1); bc.insert(41, blocks[41..81].to_vec(), peer1.clone()); assert_eq!(bc.drain(1), vec![]); - assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0), Some(121 .. 151)); + assert_eq!(bc.needed_blocks(peer1.clone(), 40, 150, 0, 1), Some(121 .. 151)); bc.clear_peer_download(&peer0); bc.insert(1, blocks[1..11].to_vec(), peer0.clone()); - assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0), Some(11 .. 41)); + assert_eq!(bc.needed_blocks(peer0.clone(), 40, 150, 0, 1), Some(11 .. 41)); assert_eq!(bc.drain(1), blocks[1..11].iter() .map(|b| BlockData { block: b.clone(), origin: Some(peer0.clone()) }).collect::>()); @@ -267,7 +269,7 @@ mod test { .map(|b| BlockData { block: b.clone(), origin: Some(peer1.clone()) }).collect::>()[..]); bc.clear_peer_download(&peer2); - assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 80), Some(81 .. 121)); + assert_eq!(bc.needed_blocks(peer2.clone(), 40, 150, 80, 1), Some(81 .. 121)); bc.clear_peer_download(&peer2); bc.insert(81, blocks[81..121].to_vec(), peer2.clone()); bc.clear_peer_download(&peer1); @@ -292,7 +294,7 @@ mod test { bc.blocks.insert(114305, BlockRangeState::Complete(blocks)); let peer0 = PeerId::random(); - assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 000), Some(1 .. 100)); - assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 600), Some(100 + 128 .. 100 + 128 + 128)); + assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 000, 1), Some(1 .. 100)); + assert_eq!(bc.needed_blocks(peer0.clone(), 128, 10000, 600, 1), Some(100 + 128 .. 100 + 128 + 128)); } } diff --git a/core/network/src/protocol/sync/extra_requests.rs b/core/network/src/protocol/sync/extra_requests.rs index 0ee009cab8689a63a1831ee2f94fab6b722731d2..28ed5fed9f6829a7894f7cc18b7c578a6977ff2c 100644 --- a/core/network/src/protocol/sync/extra_requests.rs +++ b/core/network/src/protocol/sync/extra_requests.rs @@ -18,8 +18,8 @@ use client::error::Error as ClientError; use crate::protocol::sync::{PeerSync, PeerSyncState}; use fork_tree::ForkTree; use libp2p::PeerId; -use log::warn; -use sr_primitives::traits::{Block as BlockT, NumberFor}; +use log::{debug, warn}; +use sr_primitives::traits::{Block as BlockT, NumberFor, Zero}; use std::collections::{HashMap, HashSet, VecDeque}; use std::time::{Duration, Instant}; @@ -38,6 +38,8 @@ pub(crate) type ExtraRequest = (::Hash, NumberFor); #[derive(Debug)] pub(crate) struct ExtraRequests { tree: ForkTree, ()>, + /// best finalized block number that we have seen since restart + best_seen_finalized_number: NumberFor, /// requests which have been queued for later processing pending_requests: VecDeque>, /// requests which are currently underway to some peer @@ -52,6 +54,7 @@ impl ExtraRequests { pub(crate) fn new() -> Self { ExtraRequests { tree: ForkTree::new(), + best_seen_finalized_number: Zero::zero(), pending_requests: VecDeque::new(), active_requests: HashMap::new(), failed_requests: HashMap::new(), @@ -80,11 +83,17 @@ impl ExtraRequests { match self.tree.import(request.0, request.1, (), &is_descendent_of) { Ok(true) => { // this is a new root so we add it to the current `pending_requests` - self.pending_requests.push_back((request.0, request.1)) + self.pending_requests.push_back((request.0, request.1)); } + Err(fork_tree::Error::Revert) => { + // we have finalized further than the given request, presumably + // by some other part of the system (not sync). we can safely + // ignore the `Revert` error. + return; + }, Err(err) => { - warn!(target: "sync", "Failed to insert request {:?} into tree: {:?}", request, err); - return + debug!(target: "sync", "Failed to insert request {:?} into tree: {:?}", request, err); + return; } _ => () } @@ -93,7 +102,7 @@ impl ExtraRequests { /// Retry any pending request if a peer disconnected. pub(crate) fn peer_disconnected(&mut self, who: &PeerId) { if let Some(request) = self.active_requests.remove(who) { - self.pending_requests.push_front(request) + self.pending_requests.push_front(request); } } @@ -128,7 +137,25 @@ impl ExtraRequests { return Ok(()) } - self.tree.finalize(best_finalized_hash, best_finalized_number, &is_descendent_of)?; + if best_finalized_number > self.best_seen_finalized_number { + // normally we'll receive finality notifications for every block => finalize would be enough + // but if many blocks are finalized at once, some notifications may be omitted + // => let's use finalize_with_ancestors here + match self.tree.finalize_with_ancestors( + best_finalized_hash, + best_finalized_number, + &is_descendent_of, + ) { + Err(fork_tree::Error::Revert) => { + // we might have finalized further already in which case we + // will get a `Revert` error which we can safely ignore. + }, + Err(err) => return Err(err), + Ok(_) => {}, + } + + self.best_seen_finalized_number = best_finalized_number; + } let roots = self.tree.roots().collect::>(); @@ -176,6 +203,7 @@ impl ExtraRequests { self.active_requests.clear(); self.pending_requests.clear(); self.pending_requests.extend(self.tree.roots().map(|(&h, &n, _)| (h, n))); + self.best_seen_finalized_number = finalized_number; true } @@ -412,6 +440,26 @@ mod tests { assert_eq!(finality_proofs.pending_requests.iter().collect::>(), Vec::<&(Hash, u64)>::new()); } + #[test] + fn anecstor_roots_are_finalized_when_finality_notification_is_missed() { + let mut finality_proofs = ExtraRequests::::new(); + + let hash4 = [4; 32].into(); + let hash5 = [5; 32].into(); + + fn is_descendent_of(base: &Hash, target: &Hash) -> Result { + Ok(target[0] >= base[0]) + } + + // schedule request for #4 + finality_proofs.schedule((hash4, 4), is_descendent_of); + + // receive finality notification for #5 (missing notification for #4!!!) + finality_proofs.importing_requests.insert((hash4, 5)); + finality_proofs.on_block_finalized(&hash5, 5, is_descendent_of).unwrap(); + assert_eq!(finality_proofs.tree.roots().count(), 0); + } + // Some Arbitrary instances to allow easy construction of random peer sets: #[derive(Debug, Clone)] diff --git a/core/network/src/service.rs b/core/network/src/service.rs index d5ba8db7ae4885c0c7449043c1085339653c85ea..e73bff9b1cd2e760a7fadb000a779c992d89a0bd 100644 --- a/core/network/src/service.rs +++ b/core/network/src/service.rs @@ -33,7 +33,7 @@ use consensus::import_queue::{BlockImportResult, BlockImportError}; use futures::{prelude::*, sync::mpsc}; use futures03::TryFutureExt as _; use log::{warn, error, info}; -use libp2p::{PeerId, Multiaddr, multihash::Multihash}; +use libp2p::{PeerId, Multiaddr, kad::record}; use libp2p::core::{transport::boxed::Boxed, muxing::StreamMuxerBox}; use libp2p::swarm::NetworkBehaviour; use parking_lot::Mutex; @@ -42,7 +42,7 @@ use sr_primitives::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId}; use crate::{behaviour::{Behaviour, BehaviourOut}, config::{parse_str_addr, parse_addr}}; use crate::{NetworkState, NetworkStateNotConnectedPeer, NetworkStatePeer}; -use crate::{transport, config::NodeKeyConfig, config::NonReservedPeerMode}; +use crate::{transport, config::NonReservedPeerMode}; use crate::config::{Params, TransportConfig}; use crate::error::Error; use crate::protocol::{self, Protocol, Context, CustomMessageOutcome, PeerInfo}; @@ -52,21 +52,29 @@ use crate::protocol::specialization::NetworkSpecialization; use crate::protocol::sync::SyncState; /// Minimum Requirements for a Hash within Networking -pub trait ExHashT: - ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static -{ -} +pub trait ExHashT: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static {} + impl ExHashT for T where - T: ::std::hash::Hash + Eq + ::std::fmt::Debug + Clone + Send + Sync + 'static -{ -} + T: std::hash::Hash + Eq + std::fmt::Debug + Clone + Send + Sync + 'static +{} /// Transaction pool interface pub trait TransactionPool: Send + Sync { /// Get transactions from the pool that are ready to be propagated. fn transactions(&self) -> Vec<(H, B::Extrinsic)>; + /// Get hash of transaction. + fn hash_of(&self, transaction: &B::Extrinsic) -> H; /// Import a transaction into the pool. - fn import(&self, transaction: &B::Extrinsic) -> Option; + /// + /// Peer reputation is changed by reputation_change if transaction is accepted by the pool. + fn import( + &self, + report_handle: ReportHandle, + who: PeerId, + reputation_change_good: i32, + reputation_change_bad: i32, + transaction: B::Extrinsic, + ); /// Notify the pool about transactions broadcast. fn on_broadcasted(&self, propagations: HashMap>); } @@ -77,6 +85,12 @@ pub struct ReportHandle { inner: PeersetHandle, // wraps it so we don't have to worry about breaking API. } +impl From for ReportHandle { + fn from(peerset_handle: PeersetHandle) -> Self { + ReportHandle { inner: peerset_handle } + } +} + impl ReportHandle { /// Report a given peer as either beneficial (+) or costly (-) according to the /// given scalar. @@ -113,9 +127,7 @@ impl, H: ExHashT> NetworkWorker /// Returns a `NetworkWorker` that implements `Future` and must be regularly polled in order /// for the network processing to advance. From it, you can extract a `NetworkService` using /// `worker.service()`. The `NetworkService` can be shared through the codebase. - pub fn new( - params: Params, - ) -> Result, Error> { + pub fn new(params: Params) -> Result, Error> { let (to_worker, from_worker) = mpsc::unbounded(); if let Some(ref path) = params.network_config.net_config_path { @@ -138,6 +150,23 @@ impl, H: ExHashT> NetworkWorker } } + // Check for duplicate bootnodes. + known_addresses.iter() + .try_for_each(|(peer_id, addr)| + if let Some(other) = known_addresses + .iter() + .find(|o| o.1 == *addr && o.0 != *peer_id) + { + Err(Error::DuplicateBootnode { + address: addr.clone(), + first_id: peer_id.clone(), + second_id: other.0.clone(), + }) + } else { + Ok(()) + } + )?; + // Initialize the reserved peers. for reserved in params.network_config.reserved_nodes.iter() { if let Ok((peer_id, addr)) = parse_str_addr(reserved) { @@ -157,9 +186,6 @@ impl, H: ExHashT> NetworkWorker }; // Private and public keys configuration. - if let NodeKeyConfig::Secp256k1(_) = params.network_config.node_key { - warn!(target: "sub-libp2p", "Secp256k1 keys are deprecated in favour of ed25519"); - } let local_identity = params.network_config.node_key.clone().into_keypair()?; let local_public = local_identity.public(); let local_peer_id = local_public.clone().into_peer_id(); @@ -178,6 +204,7 @@ impl, H: ExHashT> NetworkWorker params.finality_proof_request_builder, params.protocol_id, peerset_config, + params.block_announce_validator )?; // Build the swarm. @@ -297,8 +324,8 @@ impl, H: ExHashT> NetworkWorker } /// You must call this when a new block is imported by the client. - pub fn on_block_imported(&mut self, hash: B::Hash, header: B::Header) { - self.network_service.user_protocol_mut().on_block_imported(hash, &header); + pub fn on_block_imported(&mut self, hash: B::Hash, header: B::Header, data: Vec, is_best: bool) { + self.network_service.user_protocol_mut().on_block_imported(hash, &header, data, is_best); } /// You must call this when a new block is finalized by the client. @@ -394,8 +421,8 @@ impl, H: ExHashT> NetworkServic /// /// In chain-based consensus, we often need to make sure non-best forks are /// at least temporarily synced. This function forces such an announcement. - pub fn announce_block(&self, hash: B::Hash) { - let _ = self.to_worker.unbounded_send(ServerToWorkerMsg::AnnounceBlock(hash)); + pub fn announce_block(&self, hash: B::Hash, data: Vec) { + let _ = self.to_worker.unbounded_send(ServerToWorkerMsg::AnnounceBlock(hash, data)); } /// Send a consensus message through the gossip @@ -454,9 +481,9 @@ impl, H: ExHashT> NetworkServic /// Start getting a value from the DHT. /// - /// This will generate either a `ValueFound` or a `ValueNotFound` event and pass it to - /// `on_event` on the network specialization. - pub fn get_value(&self, key: &Multihash) { + /// This will generate either a `ValueFound` or a `ValueNotFound` event and pass it as an + /// item on the [`NetworkWorker`] stream. + pub fn get_value(&self, key: &record::Key) { let _ = self .to_worker .unbounded_send(ServerToWorkerMsg::GetValue(key.clone())); @@ -464,9 +491,9 @@ impl, H: ExHashT> NetworkServic /// Start putting a value in the DHT. /// - /// This will generate either a `ValuePut` or a `ValuePutFailed` event and pass it to - /// `on_event` on the network specialization. - pub fn put_value(&self, key: Multihash, value: Vec) { + /// This will generate either a `ValuePut` or a `ValuePutFailed` event and pass it as an + /// item on the [`NetworkWorker`] stream. + pub fn put_value(&self, key: record::Key, value: Vec) { let _ = self .to_worker .unbounded_send(ServerToWorkerMsg::PutValue(key, value)); @@ -497,6 +524,18 @@ impl, H: ExHashT> NetworkServic Ok(()) } + /// Configure an explicit fork sync request. + /// Note that this function should not be used for recent blocks. + /// Sync should be able to download all the recent forks normally. + /// `set_sync_fork_request` should only be used if external code detects that there's + /// a stale fork missing. + /// Passing empty `peers` set effectively removes the sync request. + pub fn set_sync_fork_request(&self, peers: Vec, hash: B::Hash, number: NumberFor) { + let _ = self + .to_worker + .unbounded_send(ServerToWorkerMsg::SyncFork(peers, hash, number)); + } + /// Modify a peerset priority group. pub fn set_priority_group(&self, group_id: String, peers: HashSet) -> Result<(), String> { let peers = peers.into_iter().map(|p| { @@ -526,8 +565,9 @@ impl, H: ExHashT> NetworkServic } } -impl, H: ExHashT> - ::consensus::SyncOracle for NetworkService { +impl, H: ExHashT> consensus::SyncOracle + for NetworkService +{ fn is_major_syncing(&mut self) -> bool { NetworkService::is_major_syncing(self) } @@ -537,8 +577,9 @@ impl, H: ExHashT> } } -impl<'a, B: BlockT + 'static, S: NetworkSpecialization, H: ExHashT> - ::consensus::SyncOracle for &'a NetworkService { +impl<'a, B: BlockT + 'static, S: NetworkSpecialization, H: ExHashT> consensus::SyncOracle + for &'a NetworkService +{ fn is_major_syncing(&mut self) -> bool { NetworkService::is_major_syncing(self) } @@ -580,13 +621,14 @@ impl NetworkStateInfo for NetworkService enum ServerToWorkerMsg> { PropagateExtrinsics, RequestJustification(B::Hash, NumberFor), - AnnounceBlock(B::Hash), + AnnounceBlock(B::Hash, Vec), ExecuteWithSpec(Box) + Send>), ExecuteWithGossip(Box, &mut dyn Context) + Send>), GossipConsensusMessage(B::Hash, ConsensusEngineId, Vec, GossipMessageRecipient), - GetValue(Multihash), - PutValue(Multihash, Vec), + GetValue(record::Key), + PutValue(record::Key, Vec), AddKnownAddress(PeerId, Multiaddr), + SyncFork(Vec, B::Hash, NumberFor), } /// Main network worker. Must be polled in order for the network to advance. @@ -612,11 +654,11 @@ pub struct NetworkWorker, H: Ex light_client_rqs: Option>>, } -impl, H: ExHashT> Future for NetworkWorker { - type Item = (); +impl, H: ExHashT> Stream for NetworkWorker { + type Item = Event; type Error = io::Error; - fn poll(&mut self) -> Poll { + fn poll(&mut self) -> Poll, Self::Error> { // Poll the import queue for actions to perform. let _ = futures03::future::poll_fn(|cx| { self.import_queue.poll_actions(cx, &mut NetworkLink { @@ -636,7 +678,7 @@ impl, H: ExHashT> Future for Ne // Process the next message coming from the `NetworkService`. let msg = match self.from_worker.poll() { Ok(Async::Ready(Some(msg))) => msg, - Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())), + Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(None)), Ok(Async::NotReady) => break, }; @@ -653,8 +695,8 @@ impl, H: ExHashT> Future for Ne } ServerToWorkerMsg::GossipConsensusMessage(topic, engine_id, message, recipient) => self.network_service.user_protocol_mut().gossip_consensus_message(topic, engine_id, message, recipient), - ServerToWorkerMsg::AnnounceBlock(hash) => - self.network_service.user_protocol_mut().announce_block(hash), + ServerToWorkerMsg::AnnounceBlock(hash, data) => + self.network_service.user_protocol_mut().announce_block(hash, data), ServerToWorkerMsg::RequestJustification(hash, number) => self.network_service.user_protocol_mut().request_justification(&hash, number), ServerToWorkerMsg::PropagateExtrinsics => @@ -665,6 +707,8 @@ impl, H: ExHashT> Future for Ne self.network_service.put_value(key, value), ServerToWorkerMsg::AddKnownAddress(peer_id, addr) => self.network_service.add_known_address(peer_id, addr), + ServerToWorkerMsg::SyncFork(peer_ids, hash, number) => + self.network_service.user_protocol_mut().set_sync_fork_request(peer_ids, &hash, number), } } @@ -675,11 +719,8 @@ impl, H: ExHashT> Future for Ne let outcome = match poll_value { Ok(Async::NotReady) => break, Ok(Async::Ready(Some(BehaviourOut::SubstrateAction(outcome)))) => outcome, - Ok(Async::Ready(Some(BehaviourOut::Dht(ev)))) => { - self.network_service.user_protocol_mut() - .on_event(Event::Dht(ev)); - CustomMessageOutcome::None - }, + Ok(Async::Ready(Some(BehaviourOut::Dht(ev)))) => + return Ok(Async::Ready(Some(Event::Dht(ev)))), Ok(Async::Ready(None)) => CustomMessageOutcome::None, Err(err) => { error!(target: "sync", "Error in the network: {:?}", err); diff --git a/core/network/src/test/block_import.rs b/core/network/src/test/block_import.rs index ceb0451166c9e0d14f023ec9d2818ea2dba73adf..f2830548a501a500420282b6034d2dd62b7be03c 100644 --- a/core/network/src/test/block_import.rs +++ b/core/network/src/test/block_import.rs @@ -16,8 +16,9 @@ //! Testing block import logic. +use consensus::ImportedAux; use consensus::import_queue::{ - import_single_block, IncomingBlock, BasicQueue, BlockImportError, BlockImportResult + import_single_block, BasicQueue, BlockImportError, BlockImportResult, IncomingBlock, }; use test_client::{self, prelude::*}; use test_client::runtime::{Block, Hash}; @@ -45,9 +46,13 @@ fn prepare_good_block() -> (TestClient, Hash, u64, PeerId, IncomingBlock) #[test] fn import_single_good_block_works() { let (_, _hash, number, peer_id, block) = prepare_good_block(); + + let mut expected_aux = ImportedAux::default(); + expected_aux.is_new_best = true; + match import_single_block(&mut test_client::new(), BlockOrigin::File, block, &mut PassThroughVerifier(true)) { Ok(BlockImportResult::ImportedUnknown(ref num, ref aux, ref org)) - if *num == number && *aux == Default::default() && *org == Some(peer_id) => {} + if *num == number && *aux == expected_aux && *org == Some(peer_id) => {} _ => panic!() } } diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs index e2533ba2eb1dc2f1d5f38483518e935cb3343eeb..330988169db9b2cba03a7ccda202314e0c8484d8 100644 --- a/core/network/src/test/mod.rs +++ b/core/network/src/test/mod.rs @@ -29,27 +29,29 @@ use log::trace; use crate::chain::FinalityProofProvider; use client::{ self, ClientInfo, BlockchainEvents, BlockImportNotification, - FinalityNotifications, FinalityNotification, + FinalityNotifications, ImportNotifications, + FinalityNotification, LongestChain, + error::Result as ClientResult, well_known_cache_keys::{self, Id as CacheKeyId}, }; -use client::{in_mem::Backend as InMemoryBackend, error::Result as ClientResult}; use client::block_builder::BlockBuilder; -use client::backend::AuxStore; +use client::backend::{AuxStore, Backend, Finalizer}; use crate::config::Roles; +use consensus::block_validation::DefaultBlockAnnounceValidator; use consensus::import_queue::BasicQueue; use consensus::import_queue::{ BoxBlockImport, BoxJustificationImport, Verifier, BoxFinalityProofImport, }; use consensus::block_import::{BlockImport, ImportResult}; use consensus::Error as ConsensusError; -use consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, JustificationImport}; +use consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport}; use futures::prelude::*; use futures03::{StreamExt as _, TryStreamExt as _}; -use crate::{NetworkWorker, NetworkService, config::ProtocolId}; +use crate::{NetworkWorker, NetworkService, ReportHandle, config::ProtocolId}; use crate::config::{NetworkConfiguration, TransportConfig, BoxFinalityProofRequestBuilder}; use libp2p::PeerId; use parking_lot::Mutex; -use primitives::{H256, Blake2Hasher}; +use primitives::H256; use crate::protocol::{Context, ProtocolConfig}; use sr_primitives::generic::{BlockId, OpaqueDigestItemId}; use sr_primitives::traits::{Block as BlockT, Header, NumberFor}; @@ -59,13 +61,14 @@ use crate::specialization::NetworkSpecialization; use test_client::{self, AccountKeyring}; pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer}; -pub use test_client::TestClient; +pub use test_client::{TestClient, TestClientBuilder, TestClientBuilderExt}; type AuthorityId = babe_primitives::AuthorityId; #[cfg(any(test, feature = "test-helpers"))] /// A Verifier that accepts all blocks and passes them on with the configured /// finality to be imported. +#[derive(Clone)] pub struct PassThroughVerifier(pub bool); #[cfg(any(test, feature = "test-helpers"))] @@ -121,11 +124,6 @@ impl NetworkSpecialization for DummySpecialization { _peer_id: PeerId, _message: Vec, ) {} - - fn on_event( - &mut self, - _event: crate::specialization::Event - ) {} } pub type PeersFullClient = @@ -135,66 +133,64 @@ pub type PeersLightClient = #[derive(Clone)] pub enum PeersClient { - Full(Arc), - Light(Arc), + Full(Arc, Arc), + Light(Arc, Arc), } impl PeersClient { pub fn as_full(&self) -> Option> { match *self { - PeersClient::Full(ref client) => Some(client.clone()), + PeersClient::Full(ref client, ref _backend) => Some(client.clone()), _ => None, } } pub fn as_block_import(&self) -> BoxBlockImport { match *self { - PeersClient::Full(ref client) => Box::new(client.clone()) as _, - PeersClient::Light(ref client) => Box::new(client.clone()) as _, - } - } - - pub fn as_in_memory_backend(&self) -> InMemoryBackend { - #[allow(deprecated)] - match *self { - PeersClient::Full(ref client) => client.backend().as_in_memory(), - PeersClient::Light(_) => unimplemented!("TODO"), + PeersClient::Full(ref client, ref _backend) => Box::new(client.clone()) as _, + PeersClient::Light(ref client, ref _backend) => Box::new(client.clone()) as _, } } pub fn get_aux(&self, key: &[u8]) -> ClientResult>> { - #[allow(deprecated)] match *self { - PeersClient::Full(ref client) => client.backend().get_aux(key), - PeersClient::Light(ref client) => client.backend().get_aux(key), + PeersClient::Full(ref client, ref _backend) => client.get_aux(key), + PeersClient::Light(ref client, ref _backend) => client.get_aux(key), } } pub fn info(&self) -> ClientInfo { match *self { - PeersClient::Full(ref client) => client.info(), - PeersClient::Light(ref client) => client.info(), + PeersClient::Full(ref client, ref _backend) => client.info(), + PeersClient::Light(ref client, ref _backend) => client.info(), } } pub fn header(&self, block: &BlockId) -> ClientResult::Header>> { match *self { - PeersClient::Full(ref client) => client.header(block), - PeersClient::Light(ref client) => client.header(block), + PeersClient::Full(ref client, ref _backend) => client.header(block), + PeersClient::Light(ref client, ref _backend) => client.header(block), } } pub fn justification(&self, block: &BlockId) -> ClientResult> { match *self { - PeersClient::Full(ref client) => client.justification(block), - PeersClient::Light(ref client) => client.justification(block), + PeersClient::Full(ref client, ref _backend) => client.justification(block), + PeersClient::Light(ref client, ref _backend) => client.justification(block), } } pub fn finality_notification_stream(&self) -> FinalityNotifications { match *self { - PeersClient::Full(ref client) => client.finality_notification_stream(), - PeersClient::Light(ref client) => client.finality_notification_stream(), + PeersClient::Full(ref client, ref _backend) => client.finality_notification_stream(), + PeersClient::Light(ref client, ref _backend) => client.finality_notification_stream(), + } + } + + pub fn import_notification_stream(&self) -> ImportNotifications{ + match *self { + PeersClient::Full(ref client, ref _backend) => client.import_notification_stream(), + PeersClient::Light(ref client, ref _backend) => client.import_notification_stream(), } } @@ -205,8 +201,8 @@ impl PeersClient { notify: bool ) -> ClientResult<()> { match *self { - PeersClient::Full(ref client) => client.finalize_block(id, justification, notify), - PeersClient::Light(ref client) => client.finalize_block(id, justification, notify), + PeersClient::Full(ref client, ref _backend) => client.finalize_block(id, justification, notify), + PeersClient::Light(ref client, ref _backend) => client.finalize_block(id, justification, notify), } } } @@ -220,17 +216,29 @@ pub struct Peer> { /// We keep a copy of the block_import so that we can invoke it for locally-generated blocks, /// instead of going through the import queue. block_import: Box>, + select_chain: Option>, + backend: Option>, network: NetworkWorker::Hash>, imported_blocks_stream: Box, Error = ()> + Send>, finality_notification_stream: Box, Error = ()> + Send>, } impl> Peer { + /// Get this peer ID. + pub fn id(&self) -> PeerId { + self.network.service().local_peer_id() + } + /// Returns true if we're major syncing. pub fn is_major_syncing(&self) -> bool { self.network.service().is_major_syncing() } + // Returns a clone of the local SelectChain, only available on full nodes + pub fn select_chain(&self) -> Option> { + self.select_chain.clone() + } + /// Returns the number of peers we're connected to. pub fn num_peers(&self) -> usize { self.network.num_connected_peers() @@ -247,8 +255,13 @@ impl> Peer { } /// Announces an important block on the network. - pub fn announce_block(&self, hash: ::Hash) { - self.network.service().announce_block(hash); + pub fn announce_block(&self, hash: ::Hash, data: Vec) { + self.network.service().announce_block(hash, data); + } + + /// Request explicit fork sync. + pub fn set_sync_fork_request(&self, peers: Vec, hash: ::Hash, number: NumberFor) { + self.network.service().set_sync_fork_request(peers, hash, number); } /// Add blocks to the peer -- edit the block before adding @@ -295,11 +308,11 @@ impl> Peer { Default::default() }; self.block_import.import_block(import_block, cache).expect("block_import failed"); - self.network.on_block_imported(hash, header); + self.network.on_block_imported(hash, header, Vec::new(), true); at = hash; } - self.network.service().announce_block(at.clone()); + self.network.service().announce_block(at.clone(), Vec::new()); at } @@ -346,6 +359,33 @@ impl> Peer { pub fn network_service(&self) -> &Arc::Hash>> { &self.network.service() } + + /// Test helper to compare the blockchain state of multiple (networked) + /// clients. + /// Potentially costly, as it creates in-memory copies of both blockchains in order + /// to compare them. If you have easier/softer checks that are sufficient, e.g. + /// by using .info(), you should probably use it instead of this. + pub fn blockchain_canon_equals(&self, other: &Self) -> bool { + if let (Some(mine), Some(others)) = (self.backend.clone(), other.backend.clone()) { + mine.as_in_memory().blockchain() + .canon_equals_to(others.as_in_memory().blockchain()) + } else { + false + } + } + + /// Count the current number of known blocks. Note that: + /// 1. this might be expensive as it creates an in-memory-copy of the chain + /// to count the blocks, thus if you have a different way of testing this + /// (e.g. `info.best_hash`) - use that. + /// 2. This is not always increasing nor accurate, as the + /// orphaned and proven-to-never-finalized blocks may be pruned at any time. + /// Therefore, this number can drop again. + pub fn blocks_count(&self) -> usize { + self.backend.as_ref().map( + |backend| backend.as_in_memory().blockchain().blocks_count() + ).unwrap_or(0) + } } pub struct EmptyTransactionPool; @@ -355,10 +395,19 @@ impl TransactionPool for EmptyTransactionPool { Vec::new() } - fn import(&self, _transaction: &Extrinsic) -> Option { - None + fn hash_of(&self, _transaction: &Extrinsic) -> Hash { + Hash::default() } + fn import( + &self, + _report_handle: ReportHandle, + _who: PeerId, + _rep_change_good: i32, + _rep_change_bad: i32, + _transaction: Extrinsic + ) {} + fn on_broadcasted(&self, _: HashMap>) {} } @@ -386,8 +435,11 @@ impl Clone for BlockImportAdapter { impl> BlockImport for BlockImportAdapter { type Error = T::Error; - fn check_block(&mut self, hash: Hash, parent_hash: Hash) -> Result { - self.0.lock().check_block(hash, parent_hash) + fn check_block( + &mut self, + block: BlockCheckParams, + ) -> Result { + self.0.lock().check_block(block) } fn import_block( @@ -427,7 +479,12 @@ pub trait TestNetFactory: Sized { /// These two need to be implemented! fn from_config(config: &ProtocolConfig) -> Self; - fn make_verifier(&self, client: PeersClient, config: &ProtocolConfig) -> Self::Verifier; + fn make_verifier( + &self, + client: PeersClient, + config: &ProtocolConfig, + peer_data: &Self::PeerData, + ) -> Self::Verifier; /// Get reference to peer. fn peer(&mut self, i: usize) -> &mut Peer; @@ -471,13 +528,27 @@ pub trait TestNetFactory: Sized { /// Add a full peer. fn add_full_peer(&mut self, config: &ProtocolConfig) { - let client = Arc::new(test_client::new()); - let verifier = self.make_verifier(PeersClient::Full(client.clone()), config); - let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); - let (block_import, justification_import, finality_proof_import, finality_proof_request_builder, data) - = self.make_block_import(PeersClient::Full(client.clone())); + let test_client_builder = TestClientBuilder::with_default_backend(); + let backend = test_client_builder.backend(); + let (c, longest_chain) = test_client_builder.build_with_longest_chain(); + let client = Arc::new(c); + + let ( + block_import, + justification_import, + finality_proof_import, + finality_proof_request_builder, + data, + ) = self.make_block_import(PeersClient::Full(client.clone(), backend.clone())); let block_import = BlockImportAdapter(Arc::new(Mutex::new(block_import))); + let verifier = self.make_verifier( + PeersClient::Full(client.clone(), backend.clone()), + config, + &data, + ); + let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); + let import_queue = Box::new(BasicQueue::new( verifier.clone(), Box::new(block_import.clone()), @@ -495,13 +566,14 @@ pub trait TestNetFactory: Sized { ..NetworkConfiguration::default() }, chain: client.clone(), - finality_proof_provider: self.make_finality_proof_provider(PeersClient::Full(client.clone())), + finality_proof_provider: self.make_finality_proof_provider(PeersClient::Full(client.clone(), backend.clone())), finality_proof_request_builder, on_demand: None, transaction_pool: Arc::new(EmptyTransactionPool), protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), import_queue, specialization: self::SpecializationFactory::create(), + block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())) }).unwrap(); self.mut_peers(|peers| { @@ -516,7 +588,9 @@ pub trait TestNetFactory: Sized { peers.push(Peer { data, - client: PeersClient::Full(client), + client: PeersClient::Full(client, backend.clone()), + select_chain: Some(longest_chain), + backend: Some(backend), imported_blocks_stream, finality_notification_stream, block_import: Box::new(block_import), @@ -531,13 +605,24 @@ pub trait TestNetFactory: Sized { let mut config = config.clone(); config.roles = Roles::LIGHT; - let client = Arc::new(test_client::new_light()); - let verifier = self.make_verifier(PeersClient::Light(client.clone()), &config); - let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); - let (block_import, justification_import, finality_proof_import, finality_proof_request_builder, data) - = self.make_block_import(PeersClient::Light(client.clone())); + let (c, backend) = test_client::new_light(); + let client = Arc::new(c); + let ( + block_import, + justification_import, + finality_proof_import, + finality_proof_request_builder, + data, + ) = self.make_block_import(PeersClient::Light(client.clone(), backend.clone())); let block_import = BlockImportAdapter(Arc::new(Mutex::new(block_import))); + let verifier = self.make_verifier( + PeersClient::Light(client.clone(), backend.clone()), + &config, + &data, + ); + let verifier = VerifierAdapter(Arc::new(Mutex::new(Box::new(verifier) as Box<_>))); + let import_queue = Box::new(BasicQueue::new( verifier.clone(), Box::new(block_import.clone()), @@ -555,13 +640,14 @@ pub trait TestNetFactory: Sized { ..NetworkConfiguration::default() }, chain: client.clone(), - finality_proof_provider: self.make_finality_proof_provider(PeersClient::Light(client.clone())), + finality_proof_provider: self.make_finality_proof_provider(PeersClient::Light(client.clone(), backend.clone())), finality_proof_request_builder, on_demand: None, transaction_pool: Arc::new(EmptyTransactionPool), protocol_id: ProtocolId::from(&b"test-protocol-name"[..]), import_queue, specialization: self::SpecializationFactory::create(), + block_announce_validator: Box::new(DefaultBlockAnnounceValidator::new(client.clone())) }).unwrap(); self.mut_peers(|peers| { @@ -577,8 +663,10 @@ pub trait TestNetFactory: Sized { peers.push(Peer { data, verifier, + select_chain: None, + backend: None, block_import: Box::new(block_import), - client: PeersClient::Light(client), + client: PeersClient::Light(client, backend), imported_blocks_stream, finality_notification_stream, network, @@ -618,11 +706,13 @@ pub trait TestNetFactory: Sized { fn poll(&mut self) { self.mut_peers(|peers| { for peer in peers { + trace!(target: "sync", "-- Polling {}", peer.id()); peer.network.poll().unwrap(); + trace!(target: "sync", "-- Polling complete {}", peer.id()); // We poll `imported_blocks_stream`. while let Ok(Async::Ready(Some(notification))) = peer.imported_blocks_stream.poll() { - peer.network.on_block_imported(notification.hash, notification.header); + peer.network.on_block_imported(notification.hash, notification.header, Vec::new(), true); } // We poll `finality_notification_stream`, but we only take the last event. @@ -654,7 +744,7 @@ impl TestNetFactory for TestNet { } } - fn make_verifier(&self, _client: PeersClient, _config: &ProtocolConfig) + fn make_verifier(&self, _client: PeersClient, _config: &ProtocolConfig, _peer_data: &()) -> Self::Verifier { PassThroughVerifier(false) @@ -700,8 +790,8 @@ impl TestNetFactory for JustificationTestNet { JustificationTestNet(TestNet::from_config(config)) } - fn make_verifier(&self, client: PeersClient, config: &ProtocolConfig) -> Self::Verifier { - self.0.make_verifier(client, config) + fn make_verifier(&self, client: PeersClient, config: &ProtocolConfig, peer_data: &()) -> Self::Verifier { + self.0.make_verifier(client, config, peer_data) } fn peer(&mut self, i: usize) -> &mut Peer { diff --git a/core/network/src/test/sync.rs b/core/network/src/test/sync.rs index f3a8f0c8ea4281cf1fdf054d892fc1441ab2a93d..b1b2b9d407262c7a32f25638120c4ec76aa14354 100644 --- a/core/network/src/test/sync.rs +++ b/core/network/src/test/sync.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use client::{backend::Backend, blockchain::HeaderBackend}; use crate::config::Roles; use consensus::BlockOrigin; use futures03::TryFutureExt as _; @@ -36,8 +35,8 @@ fn test_ancestor_search_when_common_is(n: usize) { net.peer(2).push_blocks(100, false); net.block_until_sync(&mut runtime); - assert!(net.peer(0).client.as_in_memory_backend().blockchain() - .canon_equals_to(net.peer(1).client.as_in_memory_backend().blockchain())); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); } #[test] @@ -156,8 +155,8 @@ fn sync_from_two_peers_works() { net.peer(1).push_blocks(100, false); net.peer(2).push_blocks(100, false); net.block_until_sync(&mut runtime); - assert!(net.peer(0).client.as_in_memory_backend().blockchain() - .equals_to(net.peer(1).client.as_in_memory_backend().blockchain())); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); assert!(!net.peer(0).is_major_syncing()); } @@ -170,8 +169,8 @@ fn sync_from_two_peers_with_ancestry_search_works() { net.peer(1).push_blocks(100, false); net.peer(2).push_blocks(100, false); net.block_until_sync(&mut runtime); - assert!(net.peer(0).client.as_in_memory_backend().blockchain() - .canon_equals_to(net.peer(1).client.as_in_memory_backend().blockchain())); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); } #[test] @@ -185,8 +184,8 @@ fn ancestry_search_works_when_backoff_is_one() { net.peer(2).push_blocks(2, false); net.block_until_sync(&mut runtime); - assert!(net.peer(0).client.as_in_memory_backend().blockchain() - .canon_equals_to(net.peer(1).client.as_in_memory_backend().blockchain())); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); } #[test] @@ -200,8 +199,8 @@ fn ancestry_search_works_when_ancestor_is_genesis() { net.peer(2).push_blocks(100, false); net.block_until_sync(&mut runtime); - assert!(net.peer(0).client.as_in_memory_backend().blockchain() - .canon_equals_to(net.peer(1).client.as_in_memory_backend().blockchain())); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); } #[test] @@ -226,8 +225,8 @@ fn sync_long_chain_works() { let mut net = TestNet::new(2); net.peer(1).push_blocks(500, false); net.block_until_sync(&mut runtime); - assert!(net.peer(0).client.as_in_memory_backend().blockchain() - .equals_to(net.peer(1).client.as_in_memory_backend().blockchain())); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); } #[test] @@ -238,8 +237,8 @@ fn sync_no_common_longer_chain_fails() { net.peer(0).push_blocks(20, true); net.peer(1).push_blocks(20, false); net.block_until_sync(&mut runtime); - assert!(!net.peer(0).client.as_in_memory_backend().blockchain() - .canon_equals_to(net.peer(1).client.as_in_memory_backend().blockchain())); + let peer1 = &net.peers()[1]; + assert!(!net.peers()[0].blockchain_canon_equals(peer1)); } #[test] @@ -334,11 +333,11 @@ fn sync_after_fork_works() { net.peer(2).push_blocks(1, false); // peer 1 has the best chain - let peer1_chain = net.peer(1).client.as_in_memory_backend().blockchain().clone(); net.block_until_sync(&mut runtime); - assert!(net.peer(0).client.as_in_memory_backend().blockchain().canon_equals_to(&peer1_chain)); - assert!(net.peer(1).client.as_in_memory_backend().blockchain().canon_equals_to(&peer1_chain)); - assert!(net.peer(2).client.as_in_memory_backend().blockchain().canon_equals_to(&peer1_chain)); + let peer1 = &net.peers()[1]; + assert!(net.peers()[0].blockchain_canon_equals(peer1)); + (net.peers()[1].blockchain_canon_equals(peer1)); + (net.peers()[2].blockchain_canon_equals(peer1)); } #[test] @@ -354,8 +353,8 @@ fn syncs_all_forks() { net.block_until_sync(&mut runtime); // Check that all peers have all of the blocks. - assert_eq!(9, net.peer(0).client.as_in_memory_backend().blockchain().blocks_count()); - assert_eq!(9, net.peer(1).client.as_in_memory_backend().blockchain().blocks_count()); + assert_eq!(9, net.peer(0).blocks_count()); + assert_eq!(9, net.peer(1).blocks_count()); } #[test] @@ -368,11 +367,11 @@ fn own_blocks_are_announced() { net.block_until_sync(&mut runtime); - assert_eq!(net.peer(0).client.as_in_memory_backend().blockchain().info().best_number, 1); - assert_eq!(net.peer(1).client.as_in_memory_backend().blockchain().info().best_number, 1); - let peer0_chain = net.peer(0).client.as_in_memory_backend().blockchain().clone(); - assert!(net.peer(1).client.as_in_memory_backend().blockchain().canon_equals_to(&peer0_chain)); - assert!(net.peer(2).client.as_in_memory_backend().blockchain().canon_equals_to(&peer0_chain)); + assert_eq!(net.peer(0).client.info().chain.best_number, 1); + assert_eq!(net.peer(1).client.info().chain.best_number, 1); + let peer0 = &net.peers()[0]; + assert!(net.peers()[1].blockchain_canon_equals(peer0)); + (net.peers()[2].blockchain_canon_equals(peer0)); } #[test] @@ -445,7 +444,7 @@ fn can_sync_small_non_best_forks() { assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); assert!(!net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); - net.peer(0).announce_block(small_hash); + net.peer(0).announce_block(small_hash, Vec::new()); // after announcing, peer 1 downloads the block. @@ -458,6 +457,17 @@ fn can_sync_small_non_best_forks() { } Ok(Async::Ready(())) })).unwrap(); + net.block_until_sync(&mut runtime); + + let another_fork = net.peer(0).push_blocks_at(BlockId::Number(35), 2, true); + net.peer(0).announce_block(another_fork, Vec::new()); + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(1).client().header(&BlockId::Hash(another_fork)).unwrap().is_none() { + return Ok(Async::NotReady) + } + Ok(Async::Ready(())) + })).unwrap(); } #[test] @@ -500,7 +510,7 @@ fn light_peer_imports_header_from_announce() { let mut runtime = current_thread::Runtime::new().unwrap(); fn import_with_announce(net: &mut TestNet, runtime: &mut current_thread::Runtime, hash: H256) { - net.peer(0).announce_block(hash); + net.peer(0).announce_block(hash, Vec::new()); runtime.block_on(futures::future::poll_fn::<(), (), _>(|| { net.poll(); @@ -527,3 +537,58 @@ fn light_peer_imports_header_from_announce() { let known_stale_hash = net.peer(0).push_blocks_at(BlockId::Number(0), 1, true); import_with_announce(&mut net, &mut runtime, known_stale_hash); } + +#[test] +fn can_sync_explicit_forks() { + let _ = ::env_logger::try_init(); + let mut runtime = current_thread::Runtime::new().unwrap(); + let mut net = TestNet::new(2); + net.peer(0).push_blocks(30, false); + net.peer(1).push_blocks(30, false); + + // small fork + reorg on peer 1. + net.peer(0).push_blocks_at(BlockId::Number(30), 2, true); + let small_hash = net.peer(0).client().info().chain.best_hash; + let small_number = net.peer(0).client().info().chain.best_number; + net.peer(0).push_blocks_at(BlockId::Number(30), 10, false); + assert_eq!(net.peer(0).client().info().chain.best_number, 40); + + // peer 1 only ever had the long fork. + net.peer(1).push_blocks(10, false); + assert_eq!(net.peer(1).client().info().chain.best_number, 40); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none()); + + // poll until the two nodes connect, otherwise announcing the block will not work + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + if net.peer(0).num_peers() == 0 || net.peer(1).num_peers() == 0 { + Ok(Async::NotReady) + } else { + Ok(Async::Ready(())) + } + })).unwrap(); + + // synchronization: 0 synced to longer chain and 1 didn't sync to small chain. + + assert_eq!(net.peer(0).client().info().chain.best_number, 40); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + assert!(!net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + + // request explicit sync + let first_peer_id = net.peer(0).id(); + net.peer(1).set_sync_fork_request(vec![first_peer_id], small_hash, small_number); + + // peer 1 downloads the block. + runtime.block_on(futures::future::poll_fn::<(), (), _>(|| -> Result<_, ()> { + net.poll(); + + assert!(net.peer(0).client().header(&BlockId::Hash(small_hash)).unwrap().is_some()); + if net.peer(1).client().header(&BlockId::Hash(small_hash)).unwrap().is_none() { + return Ok(Async::NotReady) + } + Ok(Async::Ready(())) + })).unwrap(); +} diff --git a/core/network/src/transport.rs b/core/network/src/transport.rs index 901ec18581e1d3e851034bb8a97e9154c786890d..24c79bfa30fdb23553ca7aceb9a6e97ffc8ea6d8 100644 --- a/core/network/src/transport.rs +++ b/core/network/src/transport.rs @@ -22,8 +22,8 @@ use libp2p::{ #[cfg(not(target_os = "unknown"))] use libp2p::{tcp, dns, websocket, noise}; #[cfg(not(target_os = "unknown"))] -use libp2p::core::{upgrade, either::EitherError, either::EitherOutput}; -use libp2p::core::{self, transport::boxed::Boxed, transport::OptionalTransport, muxing::StreamMuxerBox}; +use libp2p::core::{either::EitherError, either::EitherOutput}; +use libp2p::core::{self, upgrade, transport::boxed::Boxed, transport::OptionalTransport, muxing::StreamMuxerBox}; use std::{io, sync::Arc, time::Duration, usize}; pub use self::bandwidth::BandwidthSinks; @@ -90,7 +90,7 @@ pub fn build_transport( #[cfg(not(target_os = "unknown"))] let transport = transport.and_then(move |stream, endpoint| { let upgrade = core::upgrade::SelectUpgrade::new(noise_config, secio_config); - core::upgrade::apply(stream, upgrade, endpoint) + core::upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1) .and_then(|out| match out { // We negotiated noise EitherOutput::First((remote_id, out)) => { @@ -101,16 +101,16 @@ pub fn build_transport( Ok((EitherOutput::First(out), remote_key.into_peer_id())) } // We negotiated secio - EitherOutput::Second(out) => - Ok((EitherOutput::Second(out.stream), out.remote_key.into_peer_id())) + EitherOutput::Second((remote_id, out)) => + Ok((EitherOutput::Second(out), remote_id)) }) }); // For WASM, we only support secio for now. #[cfg(target_os = "unknown")] let transport = transport.and_then(move |stream, endpoint| { - core::upgrade::apply(stream, secio_config, endpoint) - .and_then(|out| Ok((out.stream, out.remote_key.into_peer_id()))) + core::upgrade::apply(stream, secio_config, endpoint, upgrade::Version::V1) + .and_then(|(id, stream)| Ok((stream, id))) }); // Multiplexing @@ -120,11 +120,11 @@ pub fn build_transport( .map_inbound(move |muxer| (peer_id, muxer)) .map_outbound(move |muxer| (peer_id2, muxer)); - core::upgrade::apply(stream, upgrade, endpoint) + core::upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1) .map(|(id, muxer)| (id, core::muxing::StreamMuxerBox::new(muxer))) }) - .with_timeout(Duration::from_secs(20)) + .timeout(Duration::from_secs(20)) .map_err(|err| io::Error::new(io::ErrorKind::Other, err)) .boxed(); diff --git a/core/offchain/Cargo.toml b/core/offchain/Cargo.toml index 4c8891eb6b14ce58947dc12283ceb1e716a74a1d..b52118aae7b70ed3b8a15cec681c2ac7214cb0d0 100644 --- a/core/offchain/Cargo.toml +++ b/core/offchain/Cargo.toml @@ -7,22 +7,34 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] +bytes = "0.4.12" client = { package = "substrate-client", path = "../../core/client" } -futures-preview = "=0.3.0-alpha.17" -log = "0.4" +fnv = "1.0.6" +futures01 = { package = "futures", version = "0.1" } +futures-preview = "0.3.0-alpha.19" +futures-timer = "0.4.0" +log = "0.4.8" +threadpool = "1.7" +num_cpus = "1.10" offchain-primitives = { package = "substrate-offchain-primitives", path = "./primitives" } codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } parking_lot = "0.9.0" primitives = { package = "substrate-primitives", path = "../../core/primitives" } +rand = "0.7.2" sr-primitives = { path = "../../core/sr-primitives" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } network = { package = "substrate-network", path = "../../core/network" } keystore = { package = "substrate-keystore", path = "../keystore" } +[target.'cfg(not(target_os = "unknown"))'.dependencies] +hyper = "0.12.35" +hyper-tls = "0.3.2" + [dev-dependencies] -env_logger = "0.6" +env_logger = "0.7.0" client-db = { package = "substrate-client-db", path = "../../core/client/db/", default-features = true } test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } +tokio = "0.1.22" [features] default = [] diff --git a/core/offchain/primitives/src/lib.rs b/core/offchain/primitives/src/lib.rs index d51239483aa013aa9f19b2530c42d81aaafd4baf..79fed8cb34150a45f4a3b357fd446e536dfc0613 100644 --- a/core/offchain/primitives/src/lib.rs +++ b/core/offchain/primitives/src/lib.rs @@ -22,10 +22,14 @@ use client::decl_runtime_apis; use sr_primitives::traits::NumberFor; +/// Local Storage Prefix used by the Offchain Worker API to +pub const STORAGE_PREFIX: &[u8] = b"storage"; + decl_runtime_apis! { /// The offchain worker api. pub trait OffchainWorkerApi { /// Starts the off-chain task for given block number. + #[skip_initialize_block] fn offchain_worker(number: NumberFor); } } diff --git a/core/offchain/src/api.rs b/core/offchain/src/api.rs index 225e7c3f725a49dae8d761fba451da2018f4ed35..b4d55e5f06823b1304cda8a6d3304b17e7ad0730 100644 --- a/core/offchain/src/api.rs +++ b/core/offchain/src/api.rs @@ -17,13 +17,12 @@ use std::{ str::FromStr, sync::Arc, - convert::{TryFrom, TryInto}, - time::{SystemTime, Duration}, + convert::TryFrom, thread::sleep, }; use client::backend::OffchainStorage; -use futures::{StreamExt as _, Future, future, channel::mpsc}; +use futures::{StreamExt as _, Future, FutureExt as _, future, channel::mpsc}; use log::{info, debug, warn, error}; use network::{PeerId, Multiaddr, NetworkStateInfo}; use codec::{Encode, Decode}; @@ -31,9 +30,20 @@ use primitives::offchain::{ Externalities as OffchainExt, HttpRequestId, Timestamp, HttpRequestStatus, HttpError, OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, StorageKind, }; +pub use offchain_primitives::STORAGE_PREFIX; use sr_primitives::{generic::BlockId, traits::{self, Extrinsic}}; use transaction_pool::txpool::{Pool, ChainApi}; +#[cfg(not(target_os = "unknown"))] +mod http; + +#[cfg(target_os = "unknown")] +use http_dummy as http; +#[cfg(target_os = "unknown")] +mod http_dummy; + +mod timestamp; + /// A message between the offchain extension and the processing thread. enum ExtMessage { SubmitExtrinsic(Vec), @@ -49,6 +59,8 @@ pub(crate) struct Api { _at: BlockId, /// Is this node a potential validator? is_validator: bool, + /// Everything HTTP-related is handled by a different struct. + http: http::HttpApi, } fn unavailable_yet(name: &str) -> R { @@ -60,7 +72,6 @@ fn unavailable_yet(name: &str) -> R { } const LOCAL_DB: &str = "LOCAL (fork-aware) DB"; -const STORAGE_PREFIX: &[u8] = b"storage"; impl OffchainExt for Api where @@ -89,33 +100,15 @@ where } fn timestamp(&mut self) -> Timestamp { - let now = SystemTime::now(); - let epoch_duration = now.duration_since(SystemTime::UNIX_EPOCH); - match epoch_duration { - Err(_) => { - // Current time is earlier than UNIX_EPOCH. - Timestamp::from_unix_millis(0) - }, - Ok(d) => { - let duration = d.as_millis(); - // Assuming overflow won't happen for a few hundred years. - Timestamp::from_unix_millis(duration.try_into() - .expect("epoch milliseconds won't overflow u64 for hundreds of years; qed")) - } - } + timestamp::now() } fn sleep_until(&mut self, deadline: Timestamp) { - // Get current timestamp. - let now = self.timestamp(); - // Calculate the diff with the deadline. - let diff = deadline.diff(&now); - // Call thread::sleep for the diff duration. - sleep(Duration::from_millis(diff.millis())); + sleep(timestamp::timestamp_from_now(deadline)); } fn random_seed(&mut self) -> [u8; 32] { - unavailable_yet("random_seed") + rand::random() } fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { @@ -149,58 +142,53 @@ where fn http_request_start( &mut self, - _method: &str, - _uri: &str, + method: &str, + uri: &str, _meta: &[u8] ) -> Result { - unavailable_yet::<()>("http_request_start"); - Err(()) + self.http.request_start(method, uri) } fn http_request_add_header( &mut self, - _request_id: HttpRequestId, - _name: &str, - _value: &str + request_id: HttpRequestId, + name: &str, + value: &str ) -> Result<(), ()> { - unavailable_yet::<()>("http_request_add_header"); - Err(()) + self.http.request_add_header(request_id, name, value) } fn http_request_write_body( &mut self, - _request_id: HttpRequestId, - _chunk: &[u8], - _deadline: Option + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option ) -> Result<(), HttpError> { - unavailable_yet::<()>("http_request_write_body"); - Err(HttpError::IoError) + self.http.request_write_body(request_id, chunk, deadline) } fn http_response_wait( &mut self, ids: &[HttpRequestId], - _deadline: Option + deadline: Option ) -> Vec { - unavailable_yet::<()>("http_response_wait"); - ids.iter().map(|_| HttpRequestStatus::Unknown).collect() + self.http.response_wait(ids, deadline) } fn http_response_headers( &mut self, - _request_id: HttpRequestId + request_id: HttpRequestId ) -> Vec<(Vec, Vec)> { - unavailable_yet("http_response_headers") + self.http.response_headers(request_id) } fn http_response_read_body( &mut self, - _request_id: HttpRequestId, - _buffer: &mut [u8], - _deadline: Option + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option ) -> Result { - unavailable_yet::<()>("http_response_read_body"); - Err(HttpError::IoError) + self.http.response_read_body(request_id, buffer, deadline) } } @@ -276,6 +264,8 @@ pub(crate) struct AsyncApi { receiver: Option>, transaction_pool: Arc>, at: BlockId, + /// Everything HTTP-related is handled by a different struct. + http: Option, } impl AsyncApi { @@ -289,18 +279,22 @@ impl AsyncApi { ) -> (Api, AsyncApi) { let (sender, rx) = mpsc::unbounded(); + let (http_api, http_worker) = http::http(); + let api = Api { sender, db, network_state, _at: at, is_validator, + http: http_api, }; let async_api = AsyncApi { receiver: Some(rx), transaction_pool, at, + http: Some(http_worker), }; (api, async_api) @@ -309,38 +303,41 @@ impl AsyncApi { /// Run a processing task for the API pub fn process(mut self) -> impl Future { let receiver = self.receiver.take().expect("Take invoked only once."); + let http = self.http.take().expect("Take invoked only once."); - receiver.for_each(move |msg| { + let extrinsics = receiver.for_each(move |msg| { match msg { ExtMessage::SubmitExtrinsic(ext) => self.submit_extrinsic(ext), } - future::ready(()) - }) + }); + + future::join(extrinsics, http) + .map(|((), ())| ()) } - fn submit_extrinsic(&mut self, ext: Vec) { + fn submit_extrinsic(&mut self, ext: Vec) -> impl Future { let xt = match ::Extrinsic::decode(&mut &*ext) { Ok(xt) => xt, Err(e) => { warn!("Unable to decode extrinsic: {:?}: {}", ext, e.what()); - return + return future::Either::Left(future::ready(())) }, }; - info!("Submitting to the pool: {:?} (isSigned: {:?})", xt, xt.is_signed()); - match self.transaction_pool.submit_one(&self.at, xt.clone()) { - Ok(hash) => debug!("[{:?}] Offchain transaction added to the pool.", hash), - Err(e) => { - debug!("Couldn't submit transaction: {:?}", e); - }, - } + info!("Submitting transaction to the pool: {:?} (isSigned: {:?})", xt, xt.is_signed()); + future::Either::Right(self.transaction_pool + .submit_one(&self.at, xt.clone()) + .map(|result| match result { + Ok(hash) => { debug!("[{:?}] Offchain transaction added to the pool.", hash); }, + Err(e) => { warn!("Couldn't submit offchain transaction: {:?}", e); }, + })) } } #[cfg(test)] mod tests { use super::*; - use std::convert::TryFrom; + use std::{convert::{TryFrom, TryInto}, time::SystemTime}; use sr_primitives::traits::Zero; use client_db::offchain::LocalStorage; use network::PeerId; @@ -363,7 +360,7 @@ mod tests { let db = LocalStorage::new_test(); let client = Arc::new(test_client::new()); let pool = Arc::new( - Pool::new(Default::default(), transaction_pool::ChainApi::new(client.clone())) + Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone())) ); let mock = Arc::new(MockNetworkStateInfo()); @@ -475,4 +472,13 @@ mod tests { // then assert_eq!(state, converted_back_state); } + + #[test] + fn should_get_random_seed() { + // given + let mut api = offchain_api().0; + let seed = api.random_seed(); + // then + assert_ne!(seed, [0; 32]); + } } diff --git a/core/offchain/src/api/http.rs b/core/offchain/src/api/http.rs new file mode 100644 index 0000000000000000000000000000000000000000..6744a42f959c7fddd40bcada579ca860003575ca --- /dev/null +++ b/core/offchain/src/api/http.rs @@ -0,0 +1,1004 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! This module is composed of two structs: [`HttpApi`] and [`HttpWorker`]. Calling the [`http`] +//! function returns a pair of [`HttpApi`] and [`HttpWorker`] that share some state. +//! +//! The [`HttpApi`] is (indirectly) passed to the runtime when calling an offchain worker, while +//! the [`HttpWorker`] must be processed in the background. The [`HttpApi`] mimicks the API of the +//! HTTP-related methods available to offchain workers. +//! +//! The reason for this design is driven by the fact that HTTP requests should continue running +//! (i.e.: the socket should continue being processed) in the background even if the runtime isn't +//! actively calling any function. + +use crate::api::timestamp; +use bytes::Buf as _; +use fnv::FnvHashMap; +use futures::{prelude::*, channel::mpsc, compat::Compat01As03}; +use log::{warn, error}; +use primitives::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; +use std::{fmt, io::Read as _, mem, pin::Pin, task::Context, task::Poll}; + +/// Creates a pair of [`HttpApi`] and [`HttpWorker`]. +pub fn http() -> (HttpApi, HttpWorker) { + let (to_worker, from_api) = mpsc::unbounded(); + let (to_api, from_worker) = mpsc::unbounded(); + + let api = HttpApi { + to_worker, + from_worker: from_worker.fuse(), + // We start with a random ID for the first HTTP request, to prevent mischievous people from + // writing runtime code with hardcoded IDs. + next_id: HttpRequestId(rand::random::() % 2000), + requests: FnvHashMap::default(), + }; + + let engine = HttpWorker { + to_api, + from_api, + // TODO: don't unwrap; we should fall back to the HttpConnector if we fail to create the + // Https one; there doesn't seem to be any built-in way to do this + http_client: HyperClient::new(), + requests: Vec::new(), + }; + + (api, engine) +} + +/// Provides HTTP capabilities. +/// +/// Since this struct is a helper for offchain workers, its API is mimicking the API provided +/// to offchain workers. +pub struct HttpApi { + /// Used to sends messages to the worker. + to_worker: mpsc::UnboundedSender, + /// Used to receive messages from the worker. + /// We use a `Fuse` in order to have an extra protection against panicking. + from_worker: stream::Fuse>, + /// Id to assign to the next HTTP request that is started. + next_id: HttpRequestId, + /// List of HTTP requests in preparation or in progress. + requests: FnvHashMap, +} + +/// One active request within `HttpApi`. +enum HttpApiRequest { + /// The request object is being constructed locally and not started yet. + NotDispatched(hyper::Request, hyper::body::Sender), + /// The request has been dispatched and we're in the process of sending out the body (if the + /// field is `Some`) or waiting for a response (if the field is `None`). + Dispatched(Option), + /// Received a response. + Response(HttpApiRequestRp), + /// A request has been dispatched but the worker notified us of an error. We report this + /// failure to the user as an `IoError` and remove the request from the list as soon as + /// possible. + Fail(hyper::Error), +} + +/// A request within `HttpApi` that has received a response. +struct HttpApiRequestRp { + /// We might still be writing the request's body when the response comes. + /// This field allows to continue writing that body. + sending_body: Option, + /// Status code of the response. + status_code: hyper::StatusCode, + /// Headers of the response. + headers: hyper::HeaderMap, + /// Body of the response, as a channel of `Chunk` objects. + /// While the code is designed to drop the `Receiver` once it ends, we wrap it within a + /// `Fuse` in order to be extra precautious about panics. + /// Elements extracted from the channel are first put into `current_read_chunk`. + /// If the channel produces an error, then that is translated into an `IoError` and the request + /// is removed from the list. + body: stream::Fuse>>, + /// Chunk that has been extracted from the channel and that is currently being read. + /// Reading data from the response should read from this field in priority. + current_read_chunk: Option>, +} + +impl HttpApi { + /// Mimicks the corresponding method in the offchain API. + pub fn request_start( + &mut self, + method: &str, + uri: &str + ) -> Result { + // Start by building the prototype of the request. + // We do this first so that we don't touch anything in `self` if building the prototype + // fails. + let (body_sender, body) = hyper::Body::channel(); + let mut request = hyper::Request::new(body); + *request.method_mut() = hyper::Method::from_bytes(method.as_bytes()).map_err(|_| ())?; + *request.uri_mut() = hyper::Uri::from_shared(From::from(uri)).map_err(|_| ())?; + + let new_id = self.next_id; + debug_assert!(!self.requests.contains_key(&new_id)); + match self.next_id.0.checked_add(1) { + Some(new_id) => self.next_id.0 = new_id, + None => { + error!("Overflow in offchain worker HTTP request ID assignment"); + return Err(()); + } + }; + self.requests.insert(new_id, HttpApiRequest::NotDispatched(request, body_sender)); + + Ok(new_id) + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_add_header( + &mut self, + request_id: HttpRequestId, + name: &str, + value: &str + ) -> Result<(), ()> { + let request = match self.requests.get_mut(&request_id) { + Some(&mut HttpApiRequest::NotDispatched(ref mut rq, _)) => rq, + _ => return Err(()) + }; + + let name = hyper::header::HeaderName::from_bytes(name.as_bytes()).map_err(|_| ())?; + let value = hyper::header::HeaderValue::from_str(value).map_err(|_| ())?; + // Note that we're always appending headers and never replacing old values. + // We assume here that the user knows what they're doing. + request.headers_mut().append(name, value); + Ok(()) + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option + ) -> Result<(), HttpError> { + // Extract the request from the list. + // Don't forget to add it back if necessary when returning. + let mut request = match self.requests.remove(&request_id) { + None => return Err(HttpError::Invalid), + Some(r) => r, + }; + + let mut deadline = timestamp::deadline_to_future(deadline); + // Closure that writes data to a sender, taking the deadline into account. Can return `Ok` + // (if the body has been written), or `DeadlineReached`, or `IoError`. + // If `IoError` is returned, don't forget to remove the request from the list. + let mut poll_sender = move |sender: &mut hyper::body::Sender| -> Result<(), HttpError> { + let mut when_ready = future::maybe_done(Compat01As03::new( + futures01::future::poll_fn(|| sender.poll_ready()) + )); + futures::executor::block_on(future::select(&mut when_ready, &mut deadline)); + match when_ready { + future::MaybeDone::Done(Ok(())) => {} + future::MaybeDone::Done(Err(_)) => return Err(HttpError::IoError), + future::MaybeDone::Future(_) | + future::MaybeDone::Gone => { + debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); + return Err(HttpError::DeadlineReached) + } + }; + + match sender.send_data(hyper::Chunk::from(chunk.to_owned())) { + Ok(()) => Ok(()), + Err(_chunk) => { + error!("HTTP sender refused data despite being ready"); + Err(HttpError::IoError) + }, + } + }; + + loop { + request = match request { + HttpApiRequest::NotDispatched(request, sender) => { + // If the request is not dispatched yet, dispatch it and loop again. + let _ = self.to_worker.unbounded_send(ApiToWorker::Dispatch { + id: request_id, + request + }); + HttpApiRequest::Dispatched(Some(sender)) + } + + HttpApiRequest::Dispatched(Some(mut sender)) => + if !chunk.is_empty() { + match poll_sender(&mut sender) { + Err(HttpError::IoError) => return Err(HttpError::IoError), + other => { + self.requests.insert( + request_id, + HttpApiRequest::Dispatched(Some(sender)) + ); + return other + } + } + } else { + // Writing an empty body is a hint that we should stop writing. Dropping + // the sender. + self.requests.insert(request_id, HttpApiRequest::Dispatched(None)); + return Ok(()) + } + + HttpApiRequest::Response(mut response @ HttpApiRequestRp { sending_body: Some(_), .. }) => + if !chunk.is_empty() { + match poll_sender(response.sending_body.as_mut() + .expect("Can only enter this match branch if Some; qed")) { + Err(HttpError::IoError) => return Err(HttpError::IoError), + other => { + self.requests.insert(request_id, HttpApiRequest::Response(response)); + return other + } + } + + } else { + // Writing an empty body is a hint that we should stop writing. Dropping + // the sender. + self.requests.insert(request_id, HttpApiRequest::Response(HttpApiRequestRp { + sending_body: None, + ..response + })); + return Ok(()) + } + + HttpApiRequest::Fail(_) => + // If the request has already failed, return without putting back the request + // in the list. + return Err(HttpError::IoError), + + v @ HttpApiRequest::Dispatched(None) | + v @ HttpApiRequest::Response(HttpApiRequestRp { sending_body: None, .. }) => { + // We have already finished sending this body. + self.requests.insert(request_id, v); + return Err(HttpError::Invalid) + } + } + } + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_wait( + &mut self, + ids: &[HttpRequestId], + deadline: Option + ) -> Vec { + // First of all, dispatch all the non-dispatched requests and drop all senders so that the + // user can't write anymore data. + for id in ids { + match self.requests.get_mut(id) { + Some(HttpApiRequest::NotDispatched(_, _)) => {} + Some(HttpApiRequest::Dispatched(sending_body)) | + Some(HttpApiRequest::Response(HttpApiRequestRp { sending_body, .. })) => { + let _ = sending_body.take(); + continue + } + _ => continue + }; + + let (request, _sender) = match self.requests.remove(id) { + Some(HttpApiRequest::NotDispatched(rq, s)) => (rq, s), + _ => unreachable!("we checked for NotDispatched above; qed") + }; + + let _ = self.to_worker.unbounded_send(ApiToWorker::Dispatch { + id: *id, + request + }); + + // We also destroy the sender in order to forbid writing more data. + self.requests.insert(*id, HttpApiRequest::Dispatched(None)); + } + + let mut deadline = timestamp::deadline_to_future(deadline); + + loop { + // Within that loop, first try to see if we have all the elements for a response. + // This includes the situation where the deadline is reached. + { + let mut output = Vec::with_capacity(ids.len()); + let mut must_wait_more = false; + for id in ids { + output.push(match self.requests.get_mut(id) { + None => HttpRequestStatus::Invalid, + Some(HttpApiRequest::NotDispatched(_, _)) => + unreachable!("we replaced all the NotDispatched with Dispatched earlier; qed"), + Some(HttpApiRequest::Dispatched(_)) => { + must_wait_more = true; + HttpRequestStatus::DeadlineReached + }, + Some(HttpApiRequest::Fail(_)) => HttpRequestStatus::IoError, + Some(HttpApiRequest::Response(HttpApiRequestRp { status_code, .. })) => + HttpRequestStatus::Finished(status_code.as_u16()), + }); + } + debug_assert_eq!(output.len(), ids.len()); + + // Are we ready to call `return`? + let is_done = if let future::MaybeDone::Done(_) = deadline { + true + } else if !must_wait_more { + true + } else { + false + }; + + if is_done { + // Requests in "fail" mode are purged before returning. + debug_assert_eq!(output.len(), ids.len()); + for n in (0..ids.len()).rev() { + if let HttpRequestStatus::IoError = output[n] { + self.requests.remove(&ids[n]); + } + } + return output + } + } + + // Grab next message from the worker. We call `continue` if deadline is reached so that + // we loop back and `return`. + let next_message = { + let mut next_msg = future::maybe_done(self.from_worker.next()); + futures::executor::block_on(future::select(&mut next_msg, &mut deadline)); + if let future::MaybeDone::Done(msg) = next_msg { + msg + } else { + debug_assert!(if let future::MaybeDone::Done(_) = deadline { true } else { false }); + continue + } + }; + + // Update internal state based on received message. + match next_message { + Some(WorkerToApi::Response { id, status_code, headers, body }) => + match self.requests.remove(&id) { + Some(HttpApiRequest::Dispatched(sending_body)) => { + self.requests.insert(id, HttpApiRequest::Response(HttpApiRequestRp { + sending_body, + status_code, + headers, + body: body.fuse(), + current_read_chunk: None, + })); + } + None => {} // can happen if we detected an IO error when sending the body + _ => error!("State mismatch between the API and worker"), + } + + Some(WorkerToApi::Fail { id, error }) => + match self.requests.remove(&id) { + Some(HttpApiRequest::Dispatched(_)) => { + self.requests.insert(id, HttpApiRequest::Fail(error)); + } + None => {} // can happen if we detected an IO error when sending the body + _ => error!("State mismatch between the API and worker"), + } + + None => { + error!("Worker has crashed"); + return ids.iter().map(|_| HttpRequestStatus::IoError).collect() + } + } + + } + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_headers( + &mut self, + request_id: HttpRequestId + ) -> Vec<(Vec, Vec)> { + // Do an implicit non-blocking wait on the request. + let _ = self.response_wait(&[request_id], Some(timestamp::now())); + + let headers = match self.requests.get(&request_id) { + Some(HttpApiRequest::Response(HttpApiRequestRp { headers, .. })) => headers, + _ => return Vec::new() + }; + + headers + .iter() + .map(|(name, value)| (name.as_str().as_bytes().to_owned(), value.as_bytes().to_owned())) + .collect() + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option + ) -> Result { + // Do an implicit wait on the request. + let _ = self.response_wait(&[request_id], deadline); + + // Remove the request from the list and handle situations where the request is invalid or + // in the wrong state. + let mut response = match self.requests.remove(&request_id) { + Some(HttpApiRequest::Response(r)) => r, + // Because we called `response_wait` above, we know that the deadline has been reached + // and we still haven't received a response. + Some(rq @ HttpApiRequest::Dispatched(_)) => { + self.requests.insert(request_id, rq); + return Err(HttpError::DeadlineReached) + }, + // The request has failed. + Some(HttpApiRequest::Fail { .. }) => + return Err(HttpError::IoError), + // Request hasn't been dispatched yet; reading the body is invalid. + Some(rq @ HttpApiRequest::NotDispatched(_, _)) => { + self.requests.insert(request_id, rq); + return Err(HttpError::Invalid) + } + None => return Err(HttpError::Invalid) + }; + + // Convert the deadline into a `Future` that resolves when the deadline is reached. + let mut deadline = timestamp::deadline_to_future(deadline); + + loop { + // First read from `current_read_chunk`. + if let Some(mut current_read_chunk) = response.current_read_chunk.take() { + match current_read_chunk.read(buffer) { + Ok(0) => {} + Ok(n) => { + self.requests.insert(request_id, HttpApiRequest::Response(HttpApiRequestRp { + current_read_chunk: Some(current_read_chunk), + .. response + })); + return Ok(n) + }, + Err(err) => { + // This code should never be reached unless there's a logic error somewhere. + error!("Failed to read from current read chunk: {:?}", err); + return Err(HttpError::IoError) + } + } + } + + // If we reach here, that means the `current_read_chunk` is empty and needs to be + // filled with a new chunk from `body`. We block on either the next body or the + // deadline. + let mut next_body = future::maybe_done(response.body.next()); + futures::executor::block_on(future::select(&mut next_body, &mut deadline)); + + if let future::MaybeDone::Done(next_body) = next_body { + match next_body { + Some(Ok(chunk)) => response.current_read_chunk = Some(chunk.reader()), + Some(Err(_)) => return Err(HttpError::IoError), + None => return Ok(0), // eof + } + } + + if let future::MaybeDone::Done(_) = deadline { + self.requests.insert(request_id, HttpApiRequest::Response(response)); + return Err(HttpError::DeadlineReached) + } + } + } +} + +impl fmt::Debug for HttpApi { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.requests.iter()) + .finish() + } +} + +impl fmt::Debug for HttpApiRequest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + HttpApiRequest::NotDispatched(_, _) => + f.debug_tuple("HttpApiRequest::NotDispatched").finish(), + HttpApiRequest::Dispatched(_) => + f.debug_tuple("HttpApiRequest::Dispatched").finish(), + HttpApiRequest::Response(HttpApiRequestRp { status_code, headers, .. }) => + f.debug_tuple("HttpApiRequest::Response").field(status_code).field(headers).finish(), + HttpApiRequest::Fail(err) => + f.debug_tuple("HttpApiRequest::Fail").field(err).finish(), + } + } +} + +/// Message send from the API to the worker. +enum ApiToWorker { + /// Dispatches a new HTTP request. + Dispatch { + /// ID to send back when the response comes back. + id: HttpRequestId, + /// Request to start executing. + request: hyper::Request, + } +} + +/// Message send from the API to the worker. +enum WorkerToApi { + /// A request has succeeded. + Response { + /// The ID that was passed to the worker. + id: HttpRequestId, + /// Status code of the response. + status_code: hyper::StatusCode, + /// Headers of the response. + headers: hyper::HeaderMap, + /// Body of the response, as a channel of `Chunk` objects. + /// We send the body back through a channel instead of returning the hyper `Body` object + /// because we don't want the `HttpApi` to have to drive the reading. + /// Instead, reading an item from the channel will notify the worker task, which will push + /// the next item. + /// Can also be used to send an error, in case an error happend on the HTTP socket. After + /// an error is sent, the channel will close. + body: mpsc::Receiver>, + }, + /// A request has failed because of an error. The request is then no longer valid. + Fail { + /// The ID that was passed to the worker. + id: HttpRequestId, + /// Error that happened. + error: hyper::Error, + }, +} + +/// Wraps around a `hyper::Client` with either TLS enabled or disabled. +enum HyperClient { + /// Everything is ok and HTTPS is available. + Https(hyper::Client, hyper::Body>), + /// We failed to initialize HTTPS and therefore only allow HTTP. + Http(hyper::Client), +} + +impl HyperClient { + /// Creates new hyper client. + /// + /// By default we will try to initialize the `HttpsConnector`, + /// If that's not possible we'll fall back to `HttpConnector`. + pub fn new() -> Self { + match hyper_tls::HttpsConnector::new(1) { + Ok(tls) => HyperClient::Https(hyper::Client::builder().build(tls)), + Err(e) => { + warn!("Unable to initialize TLS client. Falling back to HTTP-only: {:?}", e); + HyperClient::Http(hyper::Client::new()) + }, + } + } +} + +/// Must be continuously polled for the [`HttpApi`] to properly work. +pub struct HttpWorker { + /// Used to sends messages to the `HttpApi`. + to_api: mpsc::UnboundedSender, + /// Used to receive messages from the `HttpApi`. + from_api: mpsc::UnboundedReceiver, + /// The engine that runs HTTP requests. + http_client: HyperClient, + /// HTTP requests that are being worked on by the engine. + requests: Vec<(HttpRequestId, HttpWorkerRequest)>, +} + +/// HTTP request being processed by the worker. +enum HttpWorkerRequest { + /// Request has been dispatched and is waiting for a response from the Internet. + Dispatched(Compat01As03), + /// Progressively reading the body of the response and sending it to the channel. + ReadBody { + /// Body to read `Chunk`s from. Only used if the channel is ready to accept data. + body: Compat01As03, + /// Channel to the [`HttpApi`] where we send the chunks to. + tx: mpsc::Sender>, + }, +} + +impl Future for HttpWorker { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + // Reminder: this is continuously run in the background. + + // We use a `me` variable because the compiler isn't smart enough to allow borrowing + // multiple fields at once through a `Deref`. + let me = &mut *self; + + // We remove each element from `requests` one by one and add them back only if necessary. + for n in (0..me.requests.len()).rev() { + let (id, request) = me.requests.swap_remove(n); + match request { + HttpWorkerRequest::Dispatched(mut future) => { + // Check for an HTTP response from the Internet. + let mut response = match Future::poll(Pin::new(&mut future), cx) { + Poll::Pending => { + me.requests.push((id, HttpWorkerRequest::Dispatched(future))); + continue + }, + Poll::Ready(Ok(response)) => response, + Poll::Ready(Err(err)) => { + let _ = me.to_api.unbounded_send(WorkerToApi::Fail { + id, + error: err, + }); + continue; // don't insert the request back + } + }; + + // We received a response! Decompose it into its parts. + let status_code = response.status(); + let headers = mem::replace(response.headers_mut(), hyper::HeaderMap::new()); + let body = Compat01As03::new(response.into_body()); + + let (body_tx, body_rx) = mpsc::channel(3); + let _ = me.to_api.unbounded_send(WorkerToApi::Response { + id, + status_code, + headers, + body: body_rx, + }); + + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx: body_tx })); + cx.waker().wake_by_ref(); // reschedule in order to poll the new future + continue + } + + HttpWorkerRequest::ReadBody { mut body, mut tx } => { + // Before reading from the HTTP response, check that `tx` is ready to accept + // a new chunk. + match tx.poll_ready(cx) { + Poll::Ready(Ok(())) => {} + Poll::Ready(Err(_)) => continue, // don't insert the request back + Poll::Pending => { + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); + continue + } + } + + // `tx` is ready. Read a chunk from the socket and send it to the channel. + match Stream::poll_next(Pin::new(&mut body), cx) { + Poll::Ready(Some(Ok(chunk))) => { + let _ = tx.start_send(Ok(chunk)); + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); + cx.waker().wake_by_ref(); // reschedule in order to continue reading + } + Poll::Ready(Some(Err(err))) => { + let _ = tx.start_send(Err(err)); + // don't insert the request back + }, + Poll::Ready(None) => {} // EOF; don't insert the request back + Poll::Pending => { + me.requests.push((id, HttpWorkerRequest::ReadBody { body, tx })); + }, + } + } + } + } + + // Check for messages coming from the [`HttpApi`]. + match Stream::poll_next(Pin::new(&mut me.from_api), cx) { + Poll::Pending => {}, + Poll::Ready(None) => return Poll::Ready(()), // stops the worker + Poll::Ready(Some(ApiToWorker::Dispatch { id, request })) => { + let future = Compat01As03::new(match me.http_client { + HyperClient::Http(ref mut c) => c.request(request), + HyperClient::Https(ref mut c) => c.request(request), + }); + debug_assert!(me.requests.iter().all(|(i, _)| *i != id)); + me.requests.push((id, HttpWorkerRequest::Dispatched(future))); + cx.waker().wake_by_ref(); // reschedule the task to poll the request + } + } + + Poll::Pending + } +} + +impl fmt::Debug for HttpWorker { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.requests.iter()) + .finish() + } +} + +impl fmt::Debug for HttpWorkerRequest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + HttpWorkerRequest::Dispatched(_) => + f.debug_tuple("HttpWorkerRequest::Dispatched").finish(), + HttpWorkerRequest::ReadBody { .. } => + f.debug_tuple("HttpWorkerRequest::Response").finish(), + } + } +} + +#[cfg(test)] +mod tests { + use crate::api::timestamp; + use super::http; + use futures::prelude::*; + use futures01::Future as _; + use primitives::offchain::{HttpError, HttpRequestId, HttpRequestStatus, Duration}; + + // Returns an `HttpApi` whose worker is ran in the background, and a `SocketAddr` to an HTTP + // server that runs in the background as well. + macro_rules! build_api_server { + () => {{ + let (api, worker) = http(); + // Note: we have to use tokio because hyper still uses old futures. + std::thread::spawn(move || { + tokio::run(futures::compat::Compat::new(worker.map(|()| Ok::<(), ()>(())))) + }); + let (addr_tx, addr_rx) = std::sync::mpsc::channel(); + std::thread::spawn(move || { + let server = hyper::Server::bind(&"127.0.0.1:0".parse().unwrap()) + .serve(|| { + hyper::service::service_fn_ok(move |_: hyper::Request| { + hyper::Response::new(hyper::Body::from("Hello World!")) + }) + }); + let _ = addr_tx.send(server.local_addr()); + hyper::rt::run(server.map_err(|e| panic!("{:?}", e))); + }); + (api, addr_rx.recv().unwrap()) + }}; + } + + #[test] + fn basic_localhost() { + let deadline = timestamp::now().add(Duration::from_millis(10_000)); + + // Performs an HTTP query to a background HTTP server. + + let (mut api, addr) = build_api_server!(); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[], Some(deadline)).unwrap(); + + match api.response_wait(&[id], Some(deadline))[0] { + HttpRequestStatus::Finished(200) => {}, + v => panic!("Connecting to localhost failed: {:?}", v) + } + + let headers = api.response_headers(id); + assert!(headers.iter().any(|(h, _)| h.eq_ignore_ascii_case(b"Date"))); + + let mut buf = vec![0; 2048]; + let n = api.response_read_body(id, &mut buf, Some(deadline)).unwrap(); + assert_eq!(&buf[..n], b"Hello World!"); + } + + #[test] + fn request_start_invalid_call() { + let (mut api, addr) = build_api_server!(); + + match api.request_start("\0", &format!("http://{}", addr)) { + Err(()) => {} + Ok(_) => panic!() + }; + + match api.request_start("GET", "http://\0localhost") { + Err(()) => {} + Ok(_) => panic!() + }; + } + + #[test] + fn request_add_header_invalid_call() { + let (mut api, addr) = build_api_server!(); + + match api.request_add_header(HttpRequestId(0xdead), "Foo", "bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + match api.request_add_header(id, "\0", "bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + match api.request_add_header(id, "Foo", "\0") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_add_header(id, "Foo", "Bar").unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + match api.request_add_header(id, "Foo2", "Bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_headers(id); + match api.request_add_header(id, "Foo2", "Bar") { + Err(()) => {} + Ok(_) => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_read_body(id, &mut [], None).unwrap(); + match api.request_add_header(id, "Foo2", "Bar") { + Err(()) => {} + Ok(_) => panic!() + }; + } + + #[test] + fn request_write_body_invalid_call() { + let (mut api, addr) = build_api_server!(); + + match api.request_write_body(HttpRequestId(0xdead), &[1, 2, 3], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + match api.request_write_body(HttpRequestId(0xdead), &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[], None).unwrap(); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.request_write_body(id, &[], None).unwrap(); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.response_wait(&[id], None); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[1, 2, 3, 4], None).unwrap(); + api.response_wait(&[id], None); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.response_headers(id); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_headers(id); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.response_read_body(id, &mut [], None).unwrap(); + match api.request_write_body(id, &[1, 2, 3, 4], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.response_read_body(id, &mut [], None).unwrap(); + match api.request_write_body(id, &[], None) { + Err(HttpError::Invalid) => {} + _ => panic!() + }; + } + + #[test] + fn response_headers_invalid_call() { + let (mut api, addr) = build_api_server!(); + assert!(api.response_headers(HttpRequestId(0xdead)).is_empty()); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + assert!(api.response_headers(id).is_empty()); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_write_body(id, &[], None).unwrap(); + while api.response_headers(id).is_empty() { + std::thread::sleep(std::time::Duration::from_millis(100)); + } + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.response_wait(&[id], None); + assert!(!api.response_headers(id).is_empty()); + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + let mut buf = [0; 128]; + while api.response_read_body(id, &mut buf, None).unwrap() != 0 {} + assert!(api.response_headers(id).is_empty()); + } + + #[test] + fn response_header_invalid_call() { + let (mut api, addr) = build_api_server!(); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + assert!(api.response_headers(id).is_empty()); + + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + api.request_add_header(id, "Foo", "Bar").unwrap(); + assert!(api.response_headers(id).is_empty()); + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + api.request_add_header(id, "Foo", "Bar").unwrap(); + api.request_write_body(id, &[], None).unwrap(); + // Note: this test actually sends out the request, and is supposed to test a situation + // where we haven't received any response yet. This test can theoretically fail if the + // HTTP response comes back faster than the kernel schedules our thread, but that is highly + // unlikely. + assert!(api.response_headers(id).is_empty()); + } + + #[test] + fn response_read_body_invalid_call() { + let (mut api, addr) = build_api_server!(); + let mut buf = [0; 512]; + + match api.response_read_body(HttpRequestId(0xdead), &mut buf, None) { + Err(HttpError::Invalid) => {} + _ => panic!() + } + + let id = api.request_start("GET", &format!("http://{}", addr)).unwrap(); + while api.response_read_body(id, &mut buf, None).unwrap() != 0 {} + match api.response_read_body(id, &mut buf, None) { + Err(HttpError::Invalid) => {} + _ => panic!() + } + } + + #[test] + fn fuzzing() { + // Uses the API in random ways to try to trigger panicks. + // Doesn't test some paths, such as waiting for multiple requests. Also doesn't test what + // happens if the server force-closes our socket. + + let (mut api, addr) = build_api_server!(); + + for _ in 0..50 { + let id = api.request_start("POST", &format!("http://{}", addr)).unwrap(); + + for _ in 0..250 { + match rand::random::() % 6 { + 0 => { let _ = api.request_add_header(id, "Foo", "Bar"); } + 1 => { let _ = api.request_write_body(id, &[1, 2, 3, 4], None); } + 2 => { let _ = api.request_write_body(id, &[], None); } + 3 => { let _ = api.response_wait(&[id], None); } + 4 => { let _ = api.response_headers(id); } + 5 => { + let mut buf = [0; 512]; + let _ = api.response_read_body(id, &mut buf, None); + } + 6 ..= 255 => unreachable!() + } + } + } + } +} diff --git a/core/offchain/src/api/http_dummy.rs b/core/offchain/src/api/http_dummy.rs new file mode 100644 index 0000000000000000000000000000000000000000..e3cb272a0d07583ac669a04d6ba6b1afb425bda3 --- /dev/null +++ b/core/offchain/src/api/http_dummy.rs @@ -0,0 +1,109 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Contains the same API as the `http` module, except that everything returns an error. + +use primitives::offchain::{HttpRequestId, Timestamp, HttpRequestStatus, HttpError}; +use std::{future::Future, pin::Pin, task::Context, task::Poll}; + +/// Creates a pair of [`HttpApi`] and [`HttpWorker`]. +pub fn http() -> (HttpApi, HttpWorker) { + (HttpApi, HttpWorker) +} + +/// Dummy implementation of HTTP capabilities. +#[derive(Debug)] +pub struct HttpApi; + +/// Dummy implementation of HTTP capabilities. +#[derive(Debug)] +pub struct HttpWorker; + +impl HttpApi { + /// Mimicks the corresponding method in the offchain API. + pub fn request_start( + &mut self, + _: &str, + _: &str + ) -> Result { + /// Because this always returns an error, none of the other methods should ever be called. + Err(()) + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_add_header( + &mut self, + _: HttpRequestId, + _: &str, + _: &str + ) -> Result<(), ()> { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } + + /// Mimicks the corresponding method in the offchain API. + pub fn request_write_body( + &mut self, + _: HttpRequestId, + _: &[u8], + _: Option + ) -> Result<(), HttpError> { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_wait( + &mut self, + requests: &[HttpRequestId], + _: Option + ) -> Vec { + if requests.is_empty() { + Vec::new() + } else { + unreachable!("Creating a request always fails, thus the list of requests should \ + always be empty; qed") + } + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_headers( + &mut self, + _: HttpRequestId + ) -> Vec<(Vec, Vec)> { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } + + /// Mimicks the corresponding method in the offchain API. + pub fn response_read_body( + &mut self, + _: HttpRequestId, + _: &mut [u8], + _: Option + ) -> Result { + unreachable!("Creating a request always fails, thus this function will \ + never be called; qed") + } +} + +impl Future for HttpWorker { + type Output = (); + + fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll { + Poll::Ready(()) + } +} diff --git a/core/offchain/src/api/timestamp.rs b/core/offchain/src/api/timestamp.rs new file mode 100644 index 0000000000000000000000000000000000000000..445c7f3878474aef80646351871ea417b959ae67 --- /dev/null +++ b/core/offchain/src/api/timestamp.rs @@ -0,0 +1,62 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Helper methods dedicated to timestamps. + +use primitives::offchain::Timestamp; +use std::convert::TryInto; +use std::time::{SystemTime, Duration}; + +/// Returns the current time as a `Timestamp`. +pub fn now() -> Timestamp { + let now = SystemTime::now(); + let epoch_duration = now.duration_since(SystemTime::UNIX_EPOCH); + match epoch_duration { + Err(_) => { + // Current time is earlier than UNIX_EPOCH. + Timestamp::from_unix_millis(0) + }, + Ok(d) => { + let duration = d.as_millis(); + // Assuming overflow won't happen for a few hundred years. + Timestamp::from_unix_millis(duration.try_into() + .expect("epoch milliseconds won't overflow u64 for hundreds of years; qed")) + } + } +} + +/// Returns how a `Timestamp` compares to "now". +/// +/// In other words, returns `timestamp - now()`. +pub fn timestamp_from_now(timestamp: Timestamp) -> Duration { + Duration::from_millis(timestamp.diff(&now()).millis()) +} + +/// Converts the deadline into a `Future` that resolves when the deadline is reached. +/// +/// If `None`, returns a never-ending `Future`. +pub fn deadline_to_future( + deadline: Option, +) -> futures::future::MaybeDone { + use futures::future; + + future::maybe_done(match deadline { + Some(deadline) => future::Either::Left( + futures_timer::Delay::new(timestamp_from_now(deadline)) + ), + None => future::Either::Right(future::pending()) + }) +} diff --git a/core/offchain/src/lib.rs b/core/offchain/src/lib.rs index b38b202c62e084c008c0686489ff8aaf10770825..69147295896bacca2eeb74dea1ef6b357337cbba 100644 --- a/core/offchain/src/lib.rs +++ b/core/offchain/src/lib.rs @@ -39,11 +39,13 @@ use std::{ sync::Arc, }; +use parking_lot::Mutex; +use threadpool::ThreadPool; use client::runtime_api::ApiExt; use futures::future::Future; use log::{debug, warn}; use network::NetworkStateInfo; -use primitives::ExecutionContext; +use primitives::{offchain, ExecutionContext}; use sr_primitives::{generic::BlockId, traits::{self, ProvideRuntimeApi}}; use transaction_pool::txpool::{Pool, ChainApi}; @@ -51,13 +53,14 @@ mod api; pub mod testing; -pub use offchain_primitives::OffchainWorkerApi; +pub use offchain_primitives::{OffchainWorkerApi, STORAGE_PREFIX}; /// An offchain workers manager. pub struct OffchainWorkers { client: Arc, db: Storage, _block: PhantomData, + thread_pool: Mutex, } impl OffchainWorkers { @@ -67,6 +70,7 @@ impl OffchainWorkers OffchainWorkers< debug!("Spawning offchain workers at {:?}", at); let number = *number; let client = self.client.clone(); - spawn_worker(move || { + self.spawn_worker(move || { let runtime = client.runtime_api(); let api = Box::new(api); debug!("Running offchain workers at {:?}", at); let run = runtime.offchain_worker_with_context( &at, - ExecutionContext::OffchainWorker(api), + ExecutionContext::OffchainCall(Some((api, offchain::Capabilities::all()))), number, ); if let Err(e) = run { @@ -134,19 +138,18 @@ impl OffchainWorkers< futures::future::Either::Right(futures::future::ready(())) } } -} -/// Spawns a new offchain worker. -/// -/// We spawn offchain workers for each block in a separate thread, -/// since they can run for a significant amount of time -/// in a blocking fashion and we don't want to block the runtime. -/// -/// Note that we should avoid that if we switch to future-based runtime in the future, -/// alternatively: -/// TODO [ToDr] (#1458) we can consider using a thread pool instead. -fn spawn_worker(f: impl FnOnce() -> () + Send + 'static) { - std::thread::spawn(f); + /// Spawns a new offchain worker. + /// + /// We spawn offchain workers for each block in a separate thread, + /// since they can run for a significant amount of time + /// in a blocking fashion and we don't want to block the runtime. + /// + /// Note that we should avoid that if we switch to future-based runtime in the future, + /// alternatively: + fn spawn_worker(&self, f: impl FnOnce() -> () + Send + 'static) { + self.thread_pool.lock().execute(f); + } } #[cfg(test)] @@ -171,7 +174,7 @@ mod tests { // given let _ = env_logger::try_init(); let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), transaction_pool::ChainApi::new(client.clone()))); + let pool = Arc::new(Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone()))); let db = client_db::offchain::LocalStorage::new_test(); let network_state = Arc::new(MockNetworkStateInfo()); diff --git a/core/offchain/src/testing.rs b/core/offchain/src/testing.rs index cdf2878c13e3fa19d67a372ceebf476db54f8af9..3f4415efa7a1d01fabc73b25a4cd22c58bf19a17 100644 --- a/core/offchain/src/testing.rs +++ b/core/offchain/src/testing.rs @@ -48,7 +48,7 @@ pub struct PendingRequest { /// Has the request been sent already. pub sent: bool, /// Response body - pub response: Vec, + pub response: Option>, /// Number of bytes already read from the response body. pub read: usize, /// Response headers @@ -67,6 +67,8 @@ pub struct State { pub persistent_storage: client::in_mem::OffchainStorage, /// Local storage pub local_storage: client::in_mem::OffchainStorage, + /// A vector of transactions submitted from the runtime. + pub transactions: Vec>, } impl State { @@ -87,7 +89,7 @@ impl State { *req, expected, ); - req.response = response.into(); + req.response = Some(response.into()); req.response_headers = response_headers.into_iter().collect(); } } @@ -95,7 +97,7 @@ impl State { fn fulfill_expected(&mut self, id: u16) { if let Some(mut req) = self.expected_requests.remove(&RequestId(id)) { - let response = std::mem::replace(&mut req.response, vec![]); + let response = req.response.take().expect("Response checked while added."); let headers = std::mem::replace(&mut req.response_headers, vec![]); self.fulfill_pending_request(id, req, response, headers); } @@ -108,13 +110,17 @@ impl State { /// Expected request has to be fulfilled before this struct is dropped, /// the `response` and `response_headers` fields will be used to return results to the callers. pub fn expect_request(&mut self, id: u16, expected: PendingRequest) { + if expected.response.is_none() { + panic!("Expected request needs to have a response."); + } self.expected_requests.insert(RequestId(id), expected); } } impl Drop for State { fn drop(&mut self) { - if !self.expected_requests.is_empty() { + // If we panic! while we are already in a panic, the test dies with an illegal instruction. + if !self.expected_requests.is_empty() && !std::thread::panicking() { panic!("Unfulfilled expected requests: {:?}", self.expected_requests); } } @@ -138,12 +144,17 @@ impl offchain::Externalities for TestOffchainExt { unimplemented!("not needed in tests so far") } - fn submit_transaction(&mut self, _ex: Vec) -> Result<(), ()> { - unimplemented!("not needed in tests so far") + fn submit_transaction(&mut self, ex: Vec) -> Result<(), ()> { + let mut state = self.0.write(); + state.transactions.push(ex); + Ok(()) } fn network_state(&self) -> Result { - unimplemented!("not needed in tests so far") + Ok(OpaqueNetworkState { + peer_id: Default::default(), + external_addresses: vec![], + }) } fn timestamp(&mut self) -> Timestamp { @@ -247,8 +258,9 @@ impl offchain::Externalities for TestOffchainExt { let state = self.0.read(); ids.iter().map(|id| match state.requests.get(id) { - Some(req) if req.response.is_empty() => RequestStatus::DeadlineReached, - None => RequestStatus::Unknown, + Some(req) if req.response.is_none() => + panic!("No `response` provided for request with id: {:?}", id), + None => RequestStatus::Invalid, _ => RequestStatus::Finished(200), }).collect() } @@ -274,13 +286,17 @@ impl offchain::Externalities for TestOffchainExt { ) -> Result { let mut state = self.0.write(); if let Some(req) = state.requests.get_mut(&request_id) { - if req.read >= req.response.len() { + let response = req.response + .as_mut() + .expect(&format!("No response provided for request: {:?}", request_id)); + + if req.read >= response.len() { // Remove the pending request as per spec. state.requests.remove(&request_id); Ok(0) } else { - let read = std::cmp::min(buffer.len(), req.response[req.read..].len()); - buffer[0..read].copy_from_slice(&req.response[req.read..read]); + let read = std::cmp::min(buffer.len(), response[req.read..].len()); + buffer[0..read].copy_from_slice(&response[req.read..read]); req.read += read; Ok(read) } diff --git a/core/panic-handler/Cargo.toml b/core/panic-handler/Cargo.toml index 054bd643ac3e6adee588e176ccf243c6e6c854f4..9724b9291926a8098a0124b247f6f8feb0c7ab3e 100644 --- a/core/panic-handler/Cargo.toml +++ b/core/panic-handler/Cargo.toml @@ -6,5 +6,5 @@ description = "Substrate panic handler." edition = "2018" [dependencies] -backtrace = "0.3" -log = "0.4" +backtrace = "0.3.38" +log = "0.4.8" diff --git a/core/panic-handler/src/lib.rs b/core/panic-handler/src/lib.rs index 287ff72a6aa1cd0bf649c37ddd9fa2a6487ee76d..1df05120c119d5f046b09f1143e017f1e29306f0 100644 --- a/core/panic-handler/src/lib.rs +++ b/core/panic-handler/src/lib.rs @@ -31,7 +31,18 @@ use std::cell::Cell; use std::thread; thread_local! { - static ABORT: Cell = Cell::new(true); + static ON_PANIC: Cell = Cell::new(OnPanic::Abort); +} + +/// Panic action. +#[derive(Debug, Clone, Copy, PartialEq)] +enum OnPanic { + /// Abort when panic occurs. + Abort, + /// Unwind when panic occurs. + Unwind, + /// Always unwind even if someone changes strategy to Abort afterwards. + NeverAbort, } /// Set the panic hook. @@ -40,8 +51,13 @@ thread_local! { /// /// The `bug_url` parameter is an invitation for users to visit that URL to submit a bug report /// in the case where a panic happens. -pub fn set(bug_url: &'static str) { - panic::set_hook(Box::new(move |c| panic_hook(c, bug_url))); +pub fn set(bug_url: &'static str, version: &str) { + panic::set_hook(Box::new({ + let version = version.to_string(); + move |c| { + panic_hook(c, bug_url, &version) + } + })); } macro_rules! ABOUT_PANIC { @@ -52,10 +68,13 @@ This is a bug. Please report it at: ")} /// Set aborting flag. Returns previous value of the flag. -fn set_abort(enabled: bool) -> bool { - ABORT.with(|flag| { - let prev = flag.get(); - flag.set(enabled); +fn set_abort(on_panic: OnPanic) -> OnPanic { + ON_PANIC.with(|val| { + let prev = val.get(); + match prev { + OnPanic::Abort | OnPanic::Unwind => val.set(on_panic), + OnPanic::NeverAbort => (), + } prev }) } @@ -69,7 +88,7 @@ fn set_abort(enabled: bool) -> bool { /// > the `AbortGuard` on the stack and let it destroy itself naturally. pub struct AbortGuard { /// Value that was in `ABORT` before we created this guard. - previous_val: bool, + previous_val: OnPanic, /// Marker so that `AbortGuard` doesn't implement `Send`. _not_send: PhantomData> } @@ -79,7 +98,7 @@ impl AbortGuard { /// unwind the stack (unless another guard is created afterwards). pub fn force_unwind() -> AbortGuard { AbortGuard { - previous_val: set_abort(false), + previous_val: set_abort(OnPanic::Unwind), _not_send: PhantomData } } @@ -88,7 +107,16 @@ impl AbortGuard { /// abort the process (unless another guard is created afterwards). pub fn force_abort() -> AbortGuard { AbortGuard { - previous_val: set_abort(true), + previous_val: set_abort(OnPanic::Abort), + _not_send: PhantomData + } + } + + /// Create a new guard. While the guard is alive, panics that happen in the current thread will + /// **never** abort the process (even if `AbortGuard::force_abort()` guard will be created afterwards). + pub fn never_abort() -> AbortGuard { + AbortGuard { + previous_val: set_abort(OnPanic::NeverAbort), _not_send: PhantomData } } @@ -101,7 +129,7 @@ impl Drop for AbortGuard { } /// Function being called when a panic happens. -fn panic_hook(info: &PanicInfo, report_url: &'static str) { +fn panic_hook(info: &PanicInfo, report_url: &'static str, version: &str) { let location = info.location(); let file = location.as_ref().map(|l| l.file()).unwrap_or(""); let line = location.as_ref().map(|l| l.line()).unwrap_or(0); @@ -124,6 +152,8 @@ fn panic_hook(info: &PanicInfo, report_url: &'static str) { let _ = writeln!(stderr, ""); let _ = writeln!(stderr, "===================="); let _ = writeln!(stderr, ""); + let _ = writeln!(stderr, "Version: {}", version); + let _ = writeln!(stderr, ""); let _ = writeln!(stderr, "{:?}", backtrace); let _ = writeln!(stderr, ""); let _ = writeln!( @@ -133,8 +163,8 @@ fn panic_hook(info: &PanicInfo, report_url: &'static str) { ); let _ = writeln!(stderr, ABOUT_PANIC!(), report_url); - ABORT.with(|flag| { - if flag.get() { + ON_PANIC.with(|val| { + if val.get() == OnPanic::Abort { ::std::process::exit(1); } }) @@ -146,8 +176,16 @@ mod tests { #[test] fn does_not_abort() { - set("test"); + set("test", "1.2.3"); let _guard = AbortGuard::force_unwind(); ::std::panic::catch_unwind(|| panic!()).ok(); } + + #[test] + fn does_not_abort_after_never_abort() { + set("test", "1.2.3"); + let _guard = AbortGuard::never_abort(); + let _guard = AbortGuard::force_abort(); + std::panic::catch_unwind(|| panic!()).ok(); + } } diff --git a/core/peerset/Cargo.toml b/core/peerset/Cargo.toml index 7bf0617a9ef5d7bd2e7e2b0e88c08381feaa4beb..1b46737d2ac4421b69027f69a779ec6c715af0d9 100644 --- a/core/peerset/Cargo.toml +++ b/core/peerset/Cargo.toml @@ -8,12 +8,12 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -futures-preview = "=0.3.0-alpha.17" -libp2p = { version = "0.11.0", default-features = false } -linked-hash-map = "0.5" -log = "0.4" +futures-preview = "0.3.0-alpha.19" +libp2p = { version = "0.13.0", default-features = false } +linked-hash-map = "0.5.2" +log = "0.4.8" lru-cache = "0.1.2" -serde_json = "1.0.24" +serde_json = "1.0.41" [dev-dependencies] -rand = "0.6" +rand = "0.7.2" diff --git a/core/peerset/src/lib.rs b/core/peerset/src/lib.rs index c7c7850f16087799a38fb455e349bf3642ad6f10..a243fd00bd2b77f845d61179d8a014788ab383f6 100644 --- a/core/peerset/src/lib.rs +++ b/core/peerset/src/lib.rs @@ -178,7 +178,7 @@ impl Peerset { }; let mut peerset = Peerset { - data: peersstate::PeersState::new(config.in_peers, config.out_peers), + data: peersstate::PeersState::new(config.in_peers, config.out_peers, config.reserved_only), tx, rx, reserved_only: config.reserved_only, @@ -224,9 +224,11 @@ impl Peerset { } fn on_set_reserved_only(&mut self, reserved_only: bool) { - // Disconnect non-reserved nodes. self.reserved_only = reserved_only; + self.data.set_priority_only(reserved_only); + if self.reserved_only { + // Disconnect non-reserved nodes. let reserved = self.data.get_priority_group(RESERVED_NODES).unwrap_or_default(); for peer_id in self.data.connected_peers().cloned().collect::>().into_iter() { let peer = self.data.peer(&peer_id).into_connected() diff --git a/core/peerset/src/peersstate.rs b/core/peerset/src/peersstate.rs index e02d6304046bc6f74b9a69e8a1cfbc2dc322f5ab..57dfc50d345b0814f92ab51b80dbc821c0db1059 100644 --- a/core/peerset/src/peersstate.rs +++ b/core/peerset/src/peersstate.rs @@ -50,6 +50,9 @@ pub struct PeersState { /// Priority groups. Each group is identified by a string ID and contains a set of peer IDs. priority_nodes: HashMap>, + + /// Only allow connections to/from peers in a priority group. + priority_only: bool, } /// State of a single node that we know about. @@ -96,7 +99,7 @@ impl ConnectionState { impl PeersState { /// Builds a new empty `PeersState`. - pub fn new(in_peers: u32, out_peers: u32) -> Self { + pub fn new(in_peers: u32, out_peers: u32, priority_only: bool) -> Self { PeersState { nodes: HashMap::new(), num_in: 0, @@ -104,6 +107,7 @@ impl PeersState { max_in: in_peers, max_out: out_peers, priority_nodes: HashMap::new(), + priority_only, } } @@ -220,9 +224,15 @@ impl PeersState { /// Sets the peer as connected with an outgoing connection. fn try_outgoing(&mut self, peer_id: &PeerId) -> bool { + let is_priority = self.is_priority(peer_id); + + // We are only accepting connections from priority nodes. + if !is_priority && self.priority_only { + return false; + } + // Note that it is possible for num_out to be strictly superior to the max, in case we were // connected to reserved node then marked them as not reserved. - let is_priority = self.is_priority(peer_id); if self.num_out >= self.max_out && !is_priority { return false; } @@ -245,6 +255,12 @@ impl PeersState { /// Note that reserved nodes don't count towards the number of slots. fn try_accept_incoming(&mut self, peer_id: &PeerId) -> bool { let is_priority = self.is_priority(peer_id); + + // We are only accepting connections from priority nodes. + if !is_priority && self.priority_only { + return false; + } + // Note that it is possible for num_in to be strictly superior to the max, in case we were // connected to reserved node then marked them as not reserved. if self.num_in >= self.max_in && !is_priority { @@ -315,6 +331,15 @@ impl PeersState { self.priority_nodes.get(group_id).cloned() } + /// Set whether to only allow connections to/from peers in a priority group. + /// Calling this method does not affect any existing connection, e.g. + /// enabling priority only will not disconnect from any non-priority peers + /// we are already connected to, only future incoming/outgoing connection + /// attempts will be affected. + pub fn set_priority_only(&mut self, priority: bool) { + self.priority_only = priority; + } + /// Check that node is any priority group. fn is_priority(&self, peer_id: &PeerId) -> bool { self.priority_nodes.iter().any(|(_, group)| group.contains(peer_id)) @@ -527,7 +552,7 @@ mod tests { #[test] fn full_slots_in() { - let mut peers_state = PeersState::new(1, 1); + let mut peers_state = PeersState::new(1, 1, false); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -542,7 +567,7 @@ mod tests { #[test] fn priority_node_doesnt_use_slot() { - let mut peers_state = PeersState::new(1, 1); + let mut peers_state = PeersState::new(1, 1, false); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -558,7 +583,7 @@ mod tests { #[test] fn disconnecting_frees_slot() { - let mut peers_state = PeersState::new(1, 1); + let mut peers_state = PeersState::new(1, 1, false); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -570,7 +595,7 @@ mod tests { #[test] fn priority_not_connected_peer() { - let mut peers_state = PeersState::new(25, 25); + let mut peers_state = PeersState::new(25, 25, false); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -589,7 +614,7 @@ mod tests { #[test] fn highest_not_connected_peer() { - let mut peers_state = PeersState::new(25, 25); + let mut peers_state = PeersState::new(25, 25, false); let id1 = PeerId::random(); let id2 = PeerId::random(); @@ -610,7 +635,7 @@ mod tests { #[test] fn disconnect_priority_doesnt_panic() { - let mut peers_state = PeersState::new(1, 1); + let mut peers_state = PeersState::new(1, 1, false); let id = PeerId::random(); peers_state.set_priority_group("test", vec![id.clone()].into_iter().collect()); let peer = peers_state.peer(&id).into_not_connected().unwrap().try_outgoing().unwrap(); @@ -619,7 +644,7 @@ mod tests { #[test] fn multiple_priority_groups_slot_count() { - let mut peers_state = PeersState::new(1, 1); + let mut peers_state = PeersState::new(1, 1, false); let id = PeerId::random(); if let Peer::Unknown(p) = peers_state.peer(&id) { @@ -636,4 +661,60 @@ mod tests { peers_state.set_priority_group("test2", vec![].into_iter().collect()); assert_eq!(peers_state.num_in, 1); } + + #[test] + fn priority_only_mode_ignores_drops_unknown_nodes() { + // test whether connection to/from given peer is allowed + let test_connection = |peers_state: &mut PeersState, id| { + if let Peer::Unknown(p) = peers_state.peer(id) { + p.discover(); + } + + let incoming = if let Peer::NotConnected(p) = peers_state.peer(id) { + p.try_accept_incoming().is_ok() + } else { + panic!() + }; + + if incoming { + peers_state.peer(id).into_connected().map(|p| p.disconnect()); + } + + let outgoing = if let Peer::NotConnected(p) = peers_state.peer(id) { + p.try_outgoing().is_ok() + } else { + panic!() + }; + + if outgoing { + peers_state.peer(id).into_connected().map(|p| p.disconnect()); + } + + incoming || outgoing + }; + + let mut peers_state = PeersState::new(1, 1, true); + let id = PeerId::random(); + + // this is an unknown peer and our peer state is set to only allow + // priority peers so any connection attempt should be denied. + assert!(!test_connection(&mut peers_state, &id)); + + // disabling priority only mode should allow the connection to go + // through. + peers_state.set_priority_only(false); + assert!(test_connection(&mut peers_state, &id)); + + // re-enabling it we should again deny connections from the peer. + peers_state.set_priority_only(true); + assert!(!test_connection(&mut peers_state, &id)); + + // but if we add the peer to a priority group it should be accepted. + peers_state.set_priority_group("TEST_GROUP", vec![id.clone()].into_iter().collect()); + assert!(test_connection(&mut peers_state, &id)); + + // and removing it will cause the connection to once again be denied. + peers_state.remove_from_priority_group("TEST_GROUP", &id); + assert!(!test_connection(&mut peers_state, &id)); + } } diff --git a/core/phragmen/Cargo.toml b/core/phragmen/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..5ee6d3b3c24bcaec7f6e3cdad090dbc02c48a7ee --- /dev/null +++ b/core/phragmen/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "substrate-phragmen" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +sr-primitives = { path = "../sr-primitives", default-features = false } + +[dev-dependencies] +runtime-io ={ package = "sr-io", path = "../sr-io" } +support = { package = "srml-support", path = "../../srml/support" } +rand = "0.7.2" + +[features] +default = ["std"] +std = [ + "serde", + "rstd/std", + "sr-primitives/std", +] diff --git a/core/phragmen/benches/phragmen.rs b/core/phragmen/benches/phragmen.rs new file mode 100644 index 0000000000000000000000000000000000000000..b73811b33fa55065e44e71a9a269e8db7d1b1088 --- /dev/null +++ b/core/phragmen/benches/phragmen.rs @@ -0,0 +1,212 @@ +// Copyright 2019 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Benchmarks of the phragmen election algorithm. +//! Note that execution times will not be accurate in an absolute scale, since +//! - Everything is executed in the context of `TestExternalities` +//! - Everything is executed in native environment. +#![cfg(feature = "bench")] +#![feature(test)] + +extern crate test; +use test::Bencher; + +use rand::{self, Rng}; +extern crate substrate_phragmen as phragmen; +use phragmen::{Support, SupportMap, PhragmenStakedAssignment}; + +use std::collections::BTreeMap; +use sr_primitives::traits::{Convert, SaturatedConversion}; + +const VALIDATORS: u64 = 1000; +const NOMINATORS: u64 = 10_000; +const EDGES: u64 = 2; +const TO_ELECT: usize = 100; +const STAKE: Balance = 1000; + +type Balance = u128; +type AccountId = u64; + +pub struct TestCurrencyToVote; +impl Convert for TestCurrencyToVote { + fn convert(x: Balance) -> u64 { x.saturated_into() } +} +impl Convert for TestCurrencyToVote { + fn convert(x: u128) -> Balance { x.saturated_into() } +} + +fn do_phragmen( + b: &mut Bencher, + num_vals: u64, + num_noms: u64, + count: usize, + votes_per: u64, + eq_iters: usize, + _eq_tolerance: u128, +) { + assert!(num_vals > votes_per); + let rr = |a, b| rand::thread_rng().gen_range(a as usize, b as usize) as Balance; + + // prefix to distinguish the validator and nominator account ranges. + let np = 10_000; + + let mut candidates = Vec::with_capacity(num_vals as usize); + let mut slashable_balance_of: BTreeMap = BTreeMap::new(); + + (1 ..= num_vals) + .for_each(|acc| { + candidates.push(acc); + slashable_balance_of.insert(acc, STAKE + rr(10, 50)); + }); + + let mut voters = Vec::with_capacity(num_noms as usize); + (np ..= (np + num_noms)) + .for_each(|acc| { + let mut stashes_to_vote = candidates.clone(); + let votes = (0 .. votes_per) + .map(|_| { + stashes_to_vote.remove(rr(0, stashes_to_vote.len()) as usize) + }) + .collect::>(); + voters.push((acc, votes)); + slashable_balance_of.insert(acc, STAKE + rr(10, 50)); + }); + + let slashable_balance = |who: &AccountId| -> Balance { + *slashable_balance_of.get(who).unwrap() + }; + + b.iter(|| { + let r = phragmen::elect::( + count, + 1_usize, + candidates.clone(), + voters.clone(), + slashable_balance, + true, + ).unwrap(); + + // Do the benchmarking with equalize. + if eq_iters > 0 { + let elected_stashes = r.winners; + let assignments = r.assignments; + + let to_votes = |b: Balance| + >::convert(b) as u128; + + // Initialize the support of each candidate. + let mut supports = >::new(); + elected_stashes + .iter() + .map(|(e, _)| (e, to_votes(slashable_balance(e)))) + .for_each(|(e, s)| { + let item = Support { own: s, total: s, ..Default::default() }; + supports.insert(e.clone(), item); + }); + + // build support struct. + for (n, assignment) in assignments.iter() { + for (c, per_thing) in assignment.iter() { + let nominator_stake = to_votes(slashable_balance(n)); + let other_stake = *per_thing * nominator_stake; + if let Some(support) = supports.get_mut(c) { + support.total = support.total.saturating_add(other_stake); + support.others.push((n.clone(), other_stake)); + } + } + } + + let mut staked_assignments + : Vec<(AccountId, Vec>)> + = Vec::with_capacity(assignments.len()); + for (n, assignment) in assignments.iter() { + let mut staked_assignment + : Vec> + = Vec::with_capacity(assignment.len()); + for (c, per_thing) in assignment.iter() { + let nominator_stake = to_votes(slashable_balance(n)); + let other_stake = *per_thing * nominator_stake; + staked_assignment.push((c.clone(), other_stake)); + } + staked_assignments.push((n.clone(), staked_assignment)); + } + + let tolerance = 0_u128; + let iterations = 2_usize; + phragmen::equalize::<_, _, TestCurrencyToVote, _>( + staked_assignments, + &mut supports, + tolerance, + iterations, + slashable_balance, + ); + } + }) +} + +macro_rules! phragmen_benches { + ($($name:ident: $tup:expr,)*) => { + $( + #[bench] + fn $name(b: &mut Bencher) { + let (v, n, t, e, eq_iter, eq_tol) = $tup; + println!("----------------------"); + println!( + "++ Benchmark: {} Validators // {} Nominators // {} Edges-per-nominator // {} \ + total edges // electing {} // Equalize: {} iterations -- {} tolerance", + v, n, e, e * n, t, eq_iter, eq_tol, + ); + do_phragmen(b, v, n, t, e, eq_iter, eq_tol); + } + )* + } +} + +phragmen_benches! { + bench_1_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0), + bench_1_2: (VALIDATORS*2, NOMINATORS, TO_ELECT, EDGES, 0, 0), + bench_1_3: (VALIDATORS*4, NOMINATORS, TO_ELECT, EDGES, 0, 0), + bench_1_4: (VALIDATORS*8, NOMINATORS, TO_ELECT, EDGES, 0, 0), + bench_1_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), + bench_1_2_eq: (VALIDATORS*2, NOMINATORS, TO_ELECT, EDGES, 2, 0), + bench_1_3_eq: (VALIDATORS*4, NOMINATORS, TO_ELECT, EDGES, 2, 0), + bench_1_4_eq: (VALIDATORS*8, NOMINATORS, TO_ELECT, EDGES, 2, 0), + + bench_0_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0), + bench_0_2: (VALIDATORS, NOMINATORS, TO_ELECT * 4, EDGES, 0, 0), + bench_0_3: (VALIDATORS, NOMINATORS, TO_ELECT * 8, EDGES, 0, 0), + bench_0_4: (VALIDATORS, NOMINATORS, TO_ELECT * 16, EDGES , 0, 0), + bench_0_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), + bench_0_2_eq: (VALIDATORS, NOMINATORS, TO_ELECT * 4, EDGES, 2, 0), + bench_0_3_eq: (VALIDATORS, NOMINATORS, TO_ELECT * 8, EDGES, 2, 0), + bench_0_4_eq: (VALIDATORS, NOMINATORS, TO_ELECT * 16, EDGES , 2, 0), + + bench_2_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0), + bench_2_2: (VALIDATORS, NOMINATORS*2, TO_ELECT, EDGES, 0, 0), + bench_2_3: (VALIDATORS, NOMINATORS*4, TO_ELECT, EDGES, 0, 0), + bench_2_4: (VALIDATORS, NOMINATORS*8, TO_ELECT, EDGES, 0, 0), + bench_2_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), + bench_2_2_eq: (VALIDATORS, NOMINATORS*2, TO_ELECT, EDGES, 2, 0), + bench_2_3_eq: (VALIDATORS, NOMINATORS*4, TO_ELECT, EDGES, 2, 0), + bench_2_4_eq: (VALIDATORS, NOMINATORS*8, TO_ELECT, EDGES, 2, 0), + + bench_3_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0 ), + bench_3_2: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*2, 0, 0), + bench_3_3: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*4, 0, 0), + bench_3_4: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*8, 0, 0), + bench_3_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), + bench_3_2_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*2, 2, 0), + bench_3_3_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*4, 2, 0), + bench_3_4_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*8, 2, 0), +} diff --git a/core/phragmen/src/lib.rs b/core/phragmen/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..a4287773b5aed57c407bf37525976900fa080d76 --- /dev/null +++ b/core/phragmen/src/lib.rs @@ -0,0 +1,553 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Rust implementation of the Phragmén election algorithm. This is used in several SRML modules to +//! optimally distribute the weight of a set of voters among an elected set of candidates. In the +//! context of staking this is mapped to validators and nominators. +//! +//! The algorithm has two phases: +//! - Sequential phragmen: performed in [`elect`] function which is first pass of the distribution +//! The results are not optimal but the execution time is less. +//! - Equalize post-processing: tries to further distribute the weight fairly among candidates. +//! Incurs more execution time. +//! +//! The main objective of the assignments done by phragmen is to maximize the minimum backed +//! candidate in the elected set. +//! +//! Reference implementation: https://github.com/w3f/consensus +//! Further details: +//! https://research.web3.foundation/en/latest/polkadot/NPoS/4.%20Sequential%20Phragm%C3%A9n%E2%80%99s%20method/ + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::{prelude::*, collections::btree_map::BTreeMap}; +use sr_primitives::RuntimeDebug; +use sr_primitives::{helpers_128bit::multiply_by_rational, Perbill, Rational128}; +use sr_primitives::traits::{Zero, Convert, Member, SimpleArithmetic, Saturating, Bounded}; + +mod mock; +mod tests; + +/// A type in which performing operations on balances and stakes of candidates and voters are safe. +/// +/// This module's functions expect a `Convert` type to convert all balances to u64. Hence, u128 is +/// a safe type for arithmetic operations over them. +/// +/// Balance types converted to `ExtendedBalance` are referred to as `Votes`. +pub type ExtendedBalance = u128; + +/// The denominator used for loads. Since votes are collected as u64, the smallest ratio that we +/// might collect is `1/approval_stake` where approval stake is the sum of votes. Hence, some number +/// bigger than u64::max_value() is needed. For maximum accuracy we simply use u128; +const DEN: u128 = u128::max_value(); + +/// A candidate entity for phragmen election. +#[derive(Clone, Default, RuntimeDebug)] +pub struct Candidate { + /// Identifier. + pub who: AccountId, + /// Intermediary value used to sort candidates. + pub score: Rational128, + /// Sum of the stake of this candidate based on received votes. + approval_stake: ExtendedBalance, + /// Flag for being elected. + elected: bool, +} + +/// A voter entity. +#[derive(Clone, Default, RuntimeDebug)] +pub struct Voter { + /// Identifier. + who: AccountId, + /// List of candidates proposed by this voter. + edges: Vec>, + /// The stake of this voter. + budget: ExtendedBalance, + /// Incremented each time a candidate that this voter voted for has been elected. + load: Rational128, +} + +/// A candidate being backed by a voter. +#[derive(Clone, Default, RuntimeDebug)] +pub struct Edge { + /// Identifier. + who: AccountId, + /// Load of this vote. + load: Rational128, + /// Index of the candidate stored in the 'candidates' vector. + candidate_index: usize, +} + +/// Means a particular `AccountId` was backed by `Perbill`th of a nominator's stake. +pub type PhragmenAssignment = (AccountId, Perbill); + +/// Means a particular `AccountId` was backed by `ExtendedBalance` of a nominator's stake. +pub type PhragmenStakedAssignment = (AccountId, ExtendedBalance); + +/// Final result of the phragmen election. +#[derive(RuntimeDebug)] +pub struct PhragmenResult { + /// Just winners zipped with their approval stake. Note that the approval stake is merely the + /// sub of their received stake and could be used for very basic sorting and approval voting. + pub winners: Vec<(AccountId, ExtendedBalance)>, + /// Individual assignments. for each tuple, the first elements is a voter and the second + /// is the list of candidates that it supports. + pub assignments: Vec<(AccountId, Vec>)> +} + +/// A structure to demonstrate the phragmen result from the perspective of the candidate, i.e. how +/// much support each candidate is receiving. +/// +/// This complements the [`PhragmenResult`] and is needed to run the equalize post-processing. +/// +/// This, at the current version, resembles the `Exposure` defined in the staking SRML module, yet +/// they do not necessarily have to be the same. +#[derive(Default, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Support { + /// The amount of support as the effect of self-vote. + pub own: ExtendedBalance, + /// Total support. + pub total: ExtendedBalance, + /// Support from voters. + pub others: Vec>, +} + +/// A linkage from a candidate and its [`Support`]. +pub type SupportMap = BTreeMap>; + +/// Perform election based on Phragmén algorithm. +/// +/// Returns an `Option` the set of winners and their detailed support ratio from each voter if +/// enough candidates are provided. Returns `None` otherwise. +/// +/// * `candidate_count`: number of candidates to elect. +/// * `minimum_candidate_count`: minimum number of candidates to elect. If less candidates exist, +/// `None` is returned. +/// * `initial_candidates`: candidates list to be elected from. +/// * `initial_voters`: voters list. +/// * `stake_of`: something that can return the stake stake of a particular candidate or voter. +/// * `self_vote`. If true, then each candidate will automatically vote for themselves with the a +/// weight indicated by their stake. Note that when this is `true` candidates are filtered by +/// having at least some backed stake from themselves. +pub fn elect( + candidate_count: usize, + minimum_candidate_count: usize, + initial_candidates: Vec, + initial_voters: Vec<(AccountId, Vec)>, + stake_of: FS, + self_vote: bool, +) -> Option> where + AccountId: Default + Ord + Member, + Balance: Default + Copy + SimpleArithmetic, + for<'r> FS: Fn(&'r AccountId) -> Balance, + C: Convert + Convert, +{ + let to_votes = |b: Balance| >::convert(b) as ExtendedBalance; + + // return structures + let mut elected_candidates: Vec<(AccountId, ExtendedBalance)>; + let mut assigned: Vec<(AccountId, Vec>)>; + + // used to cache and access candidates index. + let mut c_idx_cache = BTreeMap::::new(); + + // voters list. + let num_voters = initial_candidates.len() + initial_voters.len(); + let mut voters: Vec> = Vec::with_capacity(num_voters); + + // collect candidates. self vote or filter might apply + let mut candidates = if self_vote { + // self vote. filter. + initial_candidates.into_iter().map(|who| { + let stake = stake_of(&who); + Candidate { who, approval_stake: to_votes(stake), ..Default::default() } + }) + .filter(|c| !c.approval_stake.is_zero()) + .enumerate() + .map(|(i, c)| { + voters.push(Voter { + who: c.who.clone(), + edges: vec![Edge { who: c.who.clone(), candidate_index: i, ..Default::default() }], + budget: c.approval_stake, + load: Rational128::zero(), + }); + c_idx_cache.insert(c.who.clone(), i); + c + }) + .collect::>>() + } else { + // no self vote. just collect. + initial_candidates.into_iter() + .enumerate() + .map(|(idx, who)| { + c_idx_cache.insert(who.clone(), idx); + Candidate { who, ..Default::default() } + }) + .collect::>>() + }; + + // early return if we don't have enough candidates + if candidates.len() < minimum_candidate_count { return None; } + + // collect voters. use `c_idx_cache` for fast access and aggregate `approval_stake` of + // candidates. + voters.extend(initial_voters.into_iter().map(|(who, votes)| { + let voter_stake = stake_of(&who); + let mut edges: Vec> = Vec::with_capacity(votes.len()); + for v in votes { + if let Some(idx) = c_idx_cache.get(&v) { + // This candidate is valid + already cached. + candidates[*idx].approval_stake = candidates[*idx].approval_stake + .saturating_add(to_votes(voter_stake)); + edges.push(Edge { who: v.clone(), candidate_index: *idx, ..Default::default() }); + } // else {} would be wrong votes. We don't really care about it. + } + Voter { + who, + edges: edges, + budget: to_votes(voter_stake), + load: Rational128::zero(), + } + })); + + + // we have already checked that we have more candidates than minimum_candidate_count. + // run phragmen. + let to_elect = candidate_count.min(candidates.len()); + elected_candidates = Vec::with_capacity(candidate_count); + assigned = Vec::with_capacity(candidate_count); + + // main election loop + for _round in 0..to_elect { + // loop 1: initialize score + for c in &mut candidates { + if !c.elected { + // 1 / approval_stake == (DEN / approval_stake) / DEN. If approval_stake is zero, + // then the ratio should be as large as possible, essentially `infinity`. + if c.approval_stake.is_zero() { + c.score = Rational128::from_unchecked(DEN, 0); + } else { + c.score = Rational128::from(DEN / c.approval_stake, DEN); + } + } + } + + // loop 2: increment score + for n in &voters { + for e in &n.edges { + let c = &mut candidates[e.candidate_index]; + if !c.elected && !c.approval_stake.is_zero() { + let temp_n = multiply_by_rational( + n.load.n(), + n.budget, + c.approval_stake, + ).unwrap_or(Bounded::max_value()); + let temp_d = n.load.d(); + let temp = Rational128::from(temp_n, temp_d); + c.score = c.score.lazy_saturating_add(temp); + } + } + } + + // loop 3: find the best + if let Some(winner) = candidates + .iter_mut() + .filter(|c| !c.elected) + .min_by_key(|c| c.score) + { + // loop 3: update voter and edge load + winner.elected = true; + for n in &mut voters { + for e in &mut n.edges { + if e.who == winner.who { + e.load = winner.score.lazy_saturating_sub(n.load); + n.load = winner.score; + } + } + } + + elected_candidates.push((winner.who.clone(), winner.approval_stake)); + } else { + break + } + } // end of all rounds + + // update backing stake of candidates and voters + for n in &mut voters { + let mut assignment = (n.who.clone(), vec![]); + for e in &mut n.edges { + if let Some(c) = elected_candidates.iter().cloned().find(|(c, _)| *c == e.who) { + // if self_vote == false, this branch should always be executed as we want to + // collect all nominations + if c.0 != n.who || !self_vote { + let per_bill_parts = + { + if n.load == e.load { + // Full support. No need to calculate. + Perbill::accuracy().into() + } else { + if e.load.d() == n.load.d() { + // return e.load / n.load. + let desired_scale: u128 = Perbill::accuracy().into(); + multiply_by_rational( + desired_scale, + e.load.n(), + n.load.n(), + ).unwrap_or(Bounded::max_value()) + } else { + // defensive only. Both edge and nominator loads are built from + // scores, hence MUST have the same denominator. + Zero::zero() + } + } + }; + // safer to .min() inside as well to argue as u32 is safe. + let per_thing = Perbill::from_parts( + per_bill_parts.min(Perbill::accuracy().into()) as u32 + ); + assignment.1.push((e.who.clone(), per_thing)); + } + } + } + + if assignment.1.len() > 0 { + // To ensure an assertion indicating: no stake from the nominator going to waste, + // we add a minimal post-processing to equally assign all of the leftover stake ratios. + let vote_count = assignment.1.len() as u32; + let len = assignment.1.len(); + let sum = assignment.1.iter() + .map(|a| a.1.deconstruct()) + .sum::(); + let accuracy = Perbill::accuracy(); + let diff = accuracy.checked_sub(sum).unwrap_or(0); + let diff_per_vote = (diff / vote_count).min(accuracy); + + if diff_per_vote > 0 { + for i in 0..len { + let current_ratio = assignment.1[i % len].1; + let next_ratio = current_ratio + .saturating_add(Perbill::from_parts(diff_per_vote)); + assignment.1[i % len].1 = next_ratio; + } + } + + // `remainder` is set to be less than maximum votes of a nominator (currently 16). + // safe to cast it to usize. + let remainder = diff - diff_per_vote * vote_count; + for i in 0..remainder as usize { + let current_ratio = assignment.1[i % len].1; + let next_ratio = current_ratio.saturating_add(Perbill::from_parts(1)); + assignment.1[i % len].1 = next_ratio; + } + assigned.push(assignment); + } + } + + Some(PhragmenResult { + winners: elected_candidates, + assignments: assigned, + }) +} + +/// Build the support map from the given phragmen result. +pub fn build_support_map( + elected_stashes: &Vec, + assignments: &Vec<(AccountId, Vec>)>, + stake_of: FS, + assume_self_vote: bool, +) -> SupportMap where + AccountId: Default + Ord + Member, + Balance: Default + Copy + SimpleArithmetic, + C: Convert + Convert, + for<'r> FS: Fn(&'r AccountId) -> Balance, +{ + let to_votes = |b: Balance| >::convert(b) as ExtendedBalance; + // Initialize the support of each candidate. + let mut supports = >::new(); + elected_stashes + .iter() + .map(|e| (e, if assume_self_vote { to_votes(stake_of(e)) } else { Zero::zero() } )) + .for_each(|(e, s)| { + let item = Support { own: s, total: s, ..Default::default() }; + supports.insert(e.clone(), item); + }); + + // build support struct. + for (n, assignment) in assignments.iter() { + for (c, per_thing) in assignment.iter() { + let nominator_stake = to_votes(stake_of(n)); + // AUDIT: it is crucially important for the `Mul` implementation of all + // per-things to be sound. + let other_stake = *per_thing * nominator_stake; + if let Some(support) = supports.get_mut(c) { + // For an astronomically rich validator with more astronomically rich + // set of nominators, this might saturate. + support.total = support.total.saturating_add(other_stake); + support.others.push((n.clone(), other_stake)); + } + } + } + supports +} + +/// Performs equalize post-processing to the output of the election algorithm. This happens in +/// rounds. The number of rounds and the maximum diff-per-round tolerance can be tuned through input +/// parameters. +/// +/// No value is returned from the function and the `supports` parameter is updated. +/// +/// * `assignments`: exactly the same is the output of phragmen. +/// * `supports`: mutable reference to s `SupportMap`. This parameter is updated. +/// * `tolerance`: maximum difference that can occur before an early quite happens. +/// * `iterations`: maximum number of iterations that will be processed. +/// * `stake_of`: something that can return the stake stake of a particular candidate or voter. +pub fn equalize( + mut assignments: Vec<(AccountId, Vec>)>, + supports: &mut SupportMap, + tolerance: ExtendedBalance, + iterations: usize, + stake_of: FS, +) where + C: Convert + Convert, + for<'r> FS: Fn(&'r AccountId) -> Balance, + AccountId: Ord + Clone, +{ + // prepare the data for equalise + for _i in 0..iterations { + let mut max_diff = 0; + + for (voter, assignment) in assignments.iter_mut() { + let voter_budget = stake_of(&voter); + + let diff = do_equalize::<_, _, C>( + voter, + voter_budget, + assignment, + supports, + tolerance, + ); + if diff > max_diff { max_diff = diff; } + } + + if max_diff < tolerance { + break; + } + } +} + +/// actually perform equalize. same interface is `equalize`. Just called in loops with a check for +/// maximum difference. +fn do_equalize( + voter: &AccountId, + budget_balance: Balance, + elected_edges: &mut Vec>, + support_map: &mut SupportMap, + tolerance: ExtendedBalance +) -> ExtendedBalance where + C: Convert + Convert, + AccountId: Ord + Clone, +{ + let to_votes = |b: Balance| + >::convert(b) as ExtendedBalance; + let budget = to_votes(budget_balance); + + // Nothing to do. This voter had nothing useful. + // Defensive only. Assignment list should always be populated. + if elected_edges.is_empty() { return 0; } + + let stake_used = elected_edges + .iter() + .fold(0 as ExtendedBalance, |s, e| s.saturating_add(e.1)); + + let backed_stakes_iter = elected_edges + .iter() + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total); + + let backing_backed_stake = elected_edges + .iter() + .filter(|e| e.1 > 0) + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total) + .collect::>(); + + let mut difference; + if backing_backed_stake.len() > 0 { + let max_stake = backing_backed_stake + .iter() + .max() + .expect("vector with positive length will have a max; qed"); + let min_stake = backed_stakes_iter + .min() + .expect("iterator with positive length will have a min; qed"); + + difference = max_stake.saturating_sub(min_stake); + difference = difference.saturating_add(budget.saturating_sub(stake_used)); + if difference < tolerance { + return difference; + } + } else { + difference = budget; + } + + // Undo updates to support + elected_edges.iter_mut().for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + support.total = support.total.saturating_sub(e.1); + support.others.retain(|i_support| i_support.0 != *voter); + } + e.1 = 0; + }); + + elected_edges.sort_unstable_by_key(|e| + if let Some(e) = support_map.get(&e.0) { e.total } else { Zero::zero() } + ); + + let mut cumulative_stake: ExtendedBalance = 0; + let mut last_index = elected_edges.len() - 1; + let mut idx = 0usize; + for e in &mut elected_edges[..] { + if let Some(support) = support_map.get_mut(&e.0) { + let stake = support.total; + let stake_mul = stake.saturating_mul(idx as ExtendedBalance); + let stake_sub = stake_mul.saturating_sub(cumulative_stake); + if stake_sub > budget { + last_index = idx.checked_sub(1).unwrap_or(0); + break; + } + cumulative_stake = cumulative_stake.saturating_add(stake); + } + idx += 1; + } + + let last_stake = elected_edges[last_index].1; + let split_ways = last_index + 1; + let excess = budget + .saturating_add(cumulative_stake) + .saturating_sub(last_stake.saturating_mul(split_ways as ExtendedBalance)); + elected_edges.iter_mut().take(split_ways).for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + e.1 = (excess / split_ways as ExtendedBalance) + .saturating_add(last_stake) + .saturating_sub(support.total); + support.total = support.total.saturating_add(e.1); + support.others.push((voter.clone(), e.1)); + } + }); + + difference +} diff --git a/core/phragmen/src/mock.rs b/core/phragmen/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..ee4e1eb4bbb326552f51faf7b7e17d4b39bb5bc7 --- /dev/null +++ b/core/phragmen/src/mock.rs @@ -0,0 +1,434 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Mock file for phragmen. + +#![cfg(test)] + +use crate::{elect, PhragmenResult, PhragmenAssignment}; +use sr_primitives::{ + assert_eq_error_rate, Perbill, + traits::{Convert, Member, SaturatedConversion} +}; +use rstd::collections::btree_map::BTreeMap; + +pub(crate) struct TestCurrencyToVote; +impl Convert for TestCurrencyToVote { + fn convert(x: Balance) -> u64 { x.saturated_into() } +} +impl Convert for TestCurrencyToVote { + fn convert(x: u128) -> Balance { x } +} + +#[derive(Default, Debug)] +pub(crate) struct _Candidate { + who: A, + score: f64, + approval_stake: f64, + elected: bool, +} + +#[derive(Default, Debug)] +pub(crate) struct _Voter { + who: A, + edges: Vec<_Edge>, + budget: f64, + load: f64, +} + +#[derive(Default, Debug)] +pub(crate) struct _Edge { + who: A, + load: f64, + candidate_index: usize, +} + +#[derive(Default, Debug, PartialEq)] +pub(crate) struct _Support { + pub own: f64, + pub total: f64, + pub others: Vec<_PhragmenAssignment>, +} + +pub(crate) type _PhragmenAssignment = (A, f64); +pub(crate) type _SupportMap = BTreeMap>; + +pub(crate) type Balance = u128; +pub(crate) type AccountId = u64; + +#[derive(Debug, Clone)] +pub(crate) struct _PhragmenResult { + pub winners: Vec<(A, Balance)>, + pub assignments: Vec<(A, Vec<_PhragmenAssignment>)> +} + +pub(crate) fn elect_float( + candidate_count: usize, + minimum_candidate_count: usize, + initial_candidates: Vec, + initial_voters: Vec<(A, Vec)>, + stake_of: FS, + self_vote: bool, +) -> Option<_PhragmenResult> where + A: Default + Ord + Member + Copy, + for<'r> FS: Fn(&'r A) -> Balance, +{ + let mut elected_candidates: Vec<(A, Balance)>; + let mut assigned: Vec<(A, Vec<_PhragmenAssignment>)>; + let mut c_idx_cache = BTreeMap::::new(); + let num_voters = initial_candidates.len() + initial_voters.len(); + let mut voters: Vec<_Voter> = Vec::with_capacity(num_voters); + + let mut candidates = if self_vote { + initial_candidates.into_iter().map(|who| { + let stake = stake_of(&who) as f64; + _Candidate { who, approval_stake: stake, ..Default::default() } + }) + .filter(|c| c.approval_stake != 0f64) + .enumerate() + .map(|(i, c)| { + let who = c.who; + voters.push(_Voter { + who: who.clone(), + edges: vec![ + _Edge { who: who.clone(), candidate_index: i, ..Default::default() } + ], + budget: c.approval_stake, + load: 0f64, + }); + c_idx_cache.insert(c.who.clone(), i); + c + }) + .collect::>>() + } else { + initial_candidates.into_iter() + .enumerate() + .map(|(idx, who)| { + c_idx_cache.insert(who.clone(), idx); + _Candidate { who, ..Default::default() } + }) + .collect::>>() + }; + + if candidates.len() < minimum_candidate_count { + return None; + } + + voters.extend(initial_voters.into_iter().map(|(who, votes)| { + let voter_stake = stake_of(&who) as f64; + let mut edges: Vec<_Edge> = Vec::with_capacity(votes.len()); + for v in votes { + if let Some(idx) = c_idx_cache.get(&v) { + candidates[*idx].approval_stake = candidates[*idx].approval_stake + voter_stake; + edges.push( + _Edge { who: v.clone(), candidate_index: *idx, ..Default::default() } + ); + } + } + _Voter { + who, + edges: edges, + budget: voter_stake, + load: 0f64, + } + })); + + let to_elect = candidate_count.min(candidates.len()); + elected_candidates = Vec::with_capacity(candidate_count); + assigned = Vec::with_capacity(candidate_count); + + for _round in 0..to_elect { + for c in &mut candidates { + if !c.elected { + c.score = 1.0 / c.approval_stake; + } + } + for n in &voters { + for e in &n.edges { + let c = &mut candidates[e.candidate_index]; + if !c.elected && !(c.approval_stake == 0f64) { + c.score += n.budget * n.load / c.approval_stake; + } + } + } + + if let Some(winner) = candidates + .iter_mut() + .filter(|c| !c.elected) + .min_by(|x, y| x.score.partial_cmp(&y.score).unwrap_or(rstd::cmp::Ordering::Equal)) + { + winner.elected = true; + for n in &mut voters { + for e in &mut n.edges { + if e.who == winner.who { + e.load = winner.score - n.load; + n.load = winner.score; + } + } + } + + elected_candidates.push((winner.who.clone(), winner.approval_stake as Balance)); + } else { + break + } + } + + for n in &mut voters { + let mut assignment = (n.who.clone(), vec![]); + for e in &mut n.edges { + if let Some(c) = elected_candidates.iter().cloned().map(|(c, _)| c).find(|c| *c == e.who) { + if c != n.who { + let ratio = e.load / n.load; + assignment.1.push((e.who.clone(), ratio)); + } + } + } + if assignment.1.len() > 0 { + assigned.push(assignment); + } + } + + Some(_PhragmenResult { + winners: elected_candidates, + assignments: assigned, + }) +} + +pub(crate) fn equalize_float( + mut assignments: Vec<(A, Vec<_PhragmenAssignment>)>, + supports: &mut _SupportMap, + tolerance: f64, + iterations: usize, + stake_of: FS, +) where + for<'r> FS: Fn(&'r A) -> Balance, + A: Ord + Clone + std::fmt::Debug, +{ + for _i in 0..iterations { + let mut max_diff = 0.0; + for (voter, assignment) in assignments.iter_mut() { + let voter_budget = stake_of(&voter); + let diff = do_equalize_float( + voter, + voter_budget, + assignment, + supports, + tolerance, + ); + if diff > max_diff { max_diff = diff; } + } + + if max_diff < tolerance { + break; + } + } +} + +pub(crate) fn do_equalize_float( + voter: &A, + budget_balance: Balance, + elected_edges: &mut Vec<_PhragmenAssignment>, + support_map: &mut _SupportMap, + tolerance: f64 +) -> f64 where + A: Ord + Clone, +{ + let budget = budget_balance as f64; + if elected_edges.is_empty() { return 0.0; } + + let stake_used = elected_edges + .iter() + .fold(0.0, |s, e| s + e.1); + + let backed_stakes_iter = elected_edges + .iter() + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total); + + let backing_backed_stake = elected_edges + .iter() + .filter(|e| e.1 > 0.0) + .filter_map(|e| support_map.get(&e.0)) + .map(|e| e.total) + .collect::>(); + + let mut difference; + if backing_backed_stake.len() > 0 { + let max_stake = backing_backed_stake + .iter() + .max_by(|x, y| x.partial_cmp(&y).unwrap_or(rstd::cmp::Ordering::Equal)) + .expect("vector with positive length will have a max; qed"); + let min_stake = backed_stakes_iter + .min_by(|x, y| x.partial_cmp(&y).unwrap_or(rstd::cmp::Ordering::Equal)) + .expect("iterator with positive length will have a min; qed"); + + difference = max_stake - min_stake; + difference = difference + budget - stake_used; + if difference < tolerance { + return difference; + } + } else { + difference = budget; + } + + // Undo updates to support + elected_edges.iter_mut().for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + support.total = support.total - e.1; + support.others.retain(|i_support| i_support.0 != *voter); + } + e.1 = 0.0; + }); + + // todo: rewrite. + elected_edges.sort_unstable_by(|x, y| + if let Some(x) = support_map.get(&x.0) { + if let Some(y) = support_map.get(&y.0) { + x.total.partial_cmp(&y.total).unwrap_or(rstd::cmp::Ordering::Equal) + } else { + rstd::cmp::Ordering::Equal + } + } else { + rstd::cmp::Ordering::Equal + } + ); + + let mut cumulative_stake = 0.0; + let mut last_index = elected_edges.len() - 1; + elected_edges.iter_mut().enumerate().for_each(|(idx, e)| { + if let Some(support) = support_map.get_mut(&e.0) { + let stake = support.total; + let stake_mul = stake * (idx as f64); + let stake_sub = stake_mul - cumulative_stake; + if stake_sub > budget { + last_index = idx.checked_sub(1).unwrap_or(0); + return + } + cumulative_stake = cumulative_stake + stake; + } + }); + + let last_stake = elected_edges[last_index].1; + let split_ways = last_index + 1; + let excess = budget + cumulative_stake - last_stake * (split_ways as f64); + elected_edges.iter_mut().take(split_ways).for_each(|e| { + if let Some(support) = support_map.get_mut(&e.0) { + e.1 = excess / (split_ways as f64) + last_stake - support.total; + support.total = support.total + e.1; + support.others.push((voter.clone(), e.1)); + } + }); + + difference +} + + +pub(crate) fn create_stake_of(stakes: &[(AccountId, Balance)]) + -> Box Balance> +{ + let mut storage = BTreeMap::::new(); + stakes.iter().for_each(|s| { storage.insert(s.0, s.1); }); + let stake_of = move |who: &AccountId| -> Balance { storage.get(who).unwrap().to_owned() }; + Box::new(stake_of) +} + + +pub fn check_assignments(assignments: Vec<(AccountId, Vec>)>) { + for (_, a) in assignments { + let sum: u32 = a.iter().map(|(_, p)| p.deconstruct()).sum(); + assert_eq_error_rate!(sum, Perbill::accuracy(), 5); + } +} + +pub(crate) fn run_and_compare( + candidates: Vec, + voters: Vec<(AccountId, Vec)>, + stake_of: Box Balance>, + to_elect: usize, + min_to_elect: usize, + self_vote: bool, +) { + // run fixed point code. + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + to_elect, + min_to_elect, + candidates.clone(), + voters.clone(), + &stake_of, + self_vote, + ).unwrap(); + + // run float poc code. + let truth_value = elect_float( + to_elect, + min_to_elect, + candidates, + voters, + &stake_of, + self_vote, + ).unwrap(); + + assert_eq!(winners, truth_value.winners); + + for (nominator, assigned) in assignments.clone() { + if let Some(float_assignments) = truth_value.assignments.iter().find(|x| x.0 == nominator) { + for (candidate, per_thingy) in assigned { + if let Some(float_assignment) = float_assignments.1.iter().find(|x| x.0 == candidate ) { + assert_eq_error_rate!( + Perbill::from_fraction(float_assignment.1).deconstruct(), + per_thingy.deconstruct(), + 1, + ); + } else { + panic!("candidate mismatch. This should never happen.") + } + } + } else { + panic!("nominator mismatch. This should never happen.") + } + } + + check_assignments(assignments); +} + +pub(crate) fn build_support_map( + result: &mut _PhragmenResult, + stake_of: FS, +) -> _SupportMap + where for<'r> FS: Fn(&'r AccountId) -> Balance +{ + let mut supports = <_SupportMap>::new(); + result.winners + .iter() + .map(|(e, _)| (e, stake_of(e) as f64)) + .for_each(|(e, s)| { + let item = _Support { own: s, total: s, ..Default::default() }; + supports.insert(e.clone(), item); + }); + + for (n, assignment) in result.assignments.iter_mut() { + for (c, r) in assignment.iter_mut() { + let nominator_stake = stake_of(n) as f64; + let other_stake = nominator_stake * *r; + if let Some(support) = supports.get_mut(c) { + support.total = support.total + other_stake; + support.others.push((n.clone(), other_stake)); + } + *r = other_stake; + } + } + supports +} diff --git a/core/phragmen/src/tests.rs b/core/phragmen/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..d3c5b1168cc4ea9882f2ed9a6dd1b1bbcf4edd28 --- /dev/null +++ b/core/phragmen/src/tests.rs @@ -0,0 +1,351 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for phragmen. + +#![cfg(test)] + +use crate::mock::*; +use crate::{elect, PhragmenResult}; +use support::assert_eq_uvec; +use sr_primitives::Perbill; + +#[test] +fn float_phragmen_poc_works() { + let candidates = vec![1, 2, 3]; + let voters = vec![ + (10, vec![1, 2]), + (20, vec![1, 3]), + (30, vec![2, 3]), + ]; + let stake_of = create_stake_of(&[(10, 10), (20, 20), (30, 30), (1, 0), (2, 0), (3, 0)]); + let mut phragmen_result = elect_float(2, 2, candidates, voters, &stake_of, false).unwrap(); + let winners = phragmen_result.clone().winners; + let assignments = phragmen_result.clone().assignments; + + assert_eq_uvec!(winners, vec![(2, 40), (3, 50)]); + assert_eq_uvec!( + assignments, + vec![ + (10, vec![(2, 1.0)]), + (20, vec![(3, 1.0)]), + (30, vec![(2, 0.5), (3, 0.5)]), + ] + ); + + let mut support_map = build_support_map(&mut phragmen_result, &stake_of); + + assert_eq!( + support_map.get(&2).unwrap(), + &_Support { own: 0.0, total: 25.0, others: vec![(10u64, 10.0), (30u64, 15.0)]} + ); + assert_eq!( + support_map.get(&3).unwrap(), + &_Support { own: 0.0, total: 35.0, others: vec![(20u64, 20.0), (30u64, 15.0)]} + ); + + equalize_float(phragmen_result.assignments, &mut support_map, 0.0, 2, stake_of); + + assert_eq!( + support_map.get(&2).unwrap(), + &_Support { own: 0.0, total: 30.0, others: vec![(10u64, 10.0), (30u64, 20.0)]} + ); + assert_eq!( + support_map.get(&3).unwrap(), + &_Support { own: 0.0, total: 30.0, others: vec![(20u64, 20.0), (30u64, 10.0)]} + ); +} + +#[test] +fn phragmen_poc_works() { + let candidates = vec![1, 2, 3]; + let voters = vec![ + (10, vec![1, 2]), + (20, vec![1, 3]), + (30, vec![2, 3]), + ]; + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + create_stake_of(&[(10, 10), (20, 20), (30, 30)]), + false, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(2, 40), (3, 50)]); + assert_eq_uvec!( + assignments, + vec![ + (10, vec![(2, Perbill::from_percent(100))]), + (20, vec![(3, Perbill::from_percent(100))]), + (30, vec![(2, Perbill::from_percent(100/2)), (3, Perbill::from_percent(100/2))]), + ] + ); +} + +#[test] +fn phragmen_poc_2_works() { + let candidates = vec![10, 20, 30]; + let voters = vec![ + (2, vec![10, 20, 30]), + (4, vec![10, 20, 40]), + ]; + let stake_of = create_stake_of(&[ + (10, 1000), + (20, 1000), + (30, 1000), + (40, 1000), + (2, 500), + (4, 500), + ]); + + run_and_compare(candidates, voters, stake_of, 2, 2, true); +} + +#[test] +fn phragmen_poc_3_works() { + let candidates = vec![10, 20, 30]; + let voters = vec![ + (2, vec![10, 20, 30]), + (4, vec![10, 20, 40]), + ]; + let stake_of = create_stake_of(&[ + (10, 1000), + (20, 1000), + (30, 1000), + (2, 50), + (4, 1000), + ]); + + run_and_compare(candidates, voters, stake_of, 2, 2, true); +} + +#[test] +fn phragmen_accuracy_on_large_scale_only_validators() { + // because of this particular situation we had per_u128 and now rational128. In practice, a + // candidate can have the maximum amount of tokens, and also supported by the maximum. + let candidates = vec![1, 2, 3, 4, 5]; + let stake_of = create_stake_of(&[ + (1, (u64::max_value() - 1).into()), + (2, (u64::max_value() - 4).into()), + (3, (u64::max_value() - 5).into()), + (4, (u64::max_value() - 3).into()), + (5, (u64::max_value() - 2).into()), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + vec![], + stake_of, + true, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(1, 18446744073709551614u128), (5, 18446744073709551613u128)]); + assert_eq!(assignments.len(), 0); + check_assignments(assignments); +} + +#[test] +fn phragmen_accuracy_on_large_scale_validators_and_nominators() { + let candidates = vec![1, 2, 3, 4, 5]; + let voters = vec![ + (13, vec![1, 3, 5]), + (14, vec![2, 4]), + ]; + let stake_of = create_stake_of(&[ + (1, (u64::max_value() - 1).into()), + (2, (u64::max_value() - 4).into()), + (3, (u64::max_value() - 5).into()), + (4, (u64::max_value() - 3).into()), + (5, (u64::max_value() - 2).into()), + (13, (u64::max_value() - 10).into()), + (14, u64::max_value().into()), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + stake_of, + true, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(2, 36893488147419103226u128), (1, 36893488147419103219u128)]); + assert_eq!( + assignments, + vec![(13, vec![(1, Perbill::one())]), (14, vec![(2, Perbill::one())])] + ); + check_assignments(assignments); +} + +#[test] +fn phragmen_accuracy_on_small_scale_self_vote() { + let candidates = vec![40, 10, 20, 30]; + let voters = vec![]; + let stake_of = create_stake_of(&[ + (40, 0), + (10, 1), + (20, 2), + (30, 1), + ]); + + let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>( + 3, + 3, + candidates, + voters, + stake_of, + true, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]); +} + +#[test] +fn phragmen_accuracy_on_small_scale_no_self_vote() { + let candidates = vec![40, 10, 20, 30]; + let voters = vec![ + (1, vec![10]), + (2, vec![20]), + (3, vec![30]), + (4, vec![40]), + ]; + let stake_of = create_stake_of(&[ + (40, 1000), // don't care + (10, 1000), // don't care + (20, 1000), // don't care + (30, 1000), // don't care + (4, 0), + (1, 1), + (2, 2), + (3, 1), + ]); + + let PhragmenResult { winners, assignments: _ } = elect::<_, _, _, TestCurrencyToVote>( + 3, + 3, + candidates, + voters, + stake_of, + false, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(20, 2), (10, 1), (30, 1)]); +} + +#[test] +fn phragmen_large_scale_test() { + let candidates = vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24]; + let voters = vec![ + (50, vec![2, 4, 6, 8, 10, 12, 14, 16 ,18, 20, 22, 24]), + ]; + let stake_of = create_stake_of(&[ + (2, 1), + (4, 100), + (6, 1000000), + (8, 100000000001000), + (10, 100000000002000), + (12, 100000000003000), + (14, 400000000000000), + (16, 400000000001000), + (18, 18000000000000000), + (20, 20000000000000000), + (22, 500000000000100000), + (24, 500000000000200000), + (50, 990000000000000000), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + stake_of, + true, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(24, 1490000000000200000u128), (22, 1490000000000100000u128)]); + check_assignments(assignments); +} + +#[test] +fn phragmen_large_scale_test_2() { + let nom_budget: u64 = 1_000_000_000_000_000_000; + let c_budget: u64 = 4_000_000; + + let candidates = vec![2, 4]; + let voters = vec![(50, vec![2, 4])]; + + let stake_of = create_stake_of(&[ + (2, c_budget.into()), + (4, c_budget.into()), + (50, nom_budget.into()), + ]); + + let PhragmenResult { winners, assignments } = elect::<_, _, _, TestCurrencyToVote>( + 2, + 2, + candidates, + voters, + stake_of, + true, + ).unwrap(); + + assert_eq_uvec!(winners, vec![(2, 1000000000004000000u128), (4, 1000000000004000000u128)]); + assert_eq!( + assignments, + vec![(50, vec![(2, Perbill::from_parts(500000001)), (4, Perbill::from_parts(499999999))])], + ); + check_assignments(assignments); +} + +#[test] +fn phragmen_linear_equalize() { + let candidates = vec![11, 21, 31, 41, 51, 61, 71]; + let voters = vec![ + (2, vec![11]), + (4, vec![11, 21]), + (6, vec![21, 31]), + (8, vec![31, 41]), + (110, vec![41, 51]), + (120, vec![51, 61]), + (130, vec![61, 71]), + ]; + let stake_of = create_stake_of(&[ + (11, 1000), + (21, 1000), + (31, 1000), + (41, 1000), + (51, 1000), + (61, 1000), + (71, 1000), + + (2, 2000), + (4, 1000), + (6, 1000), + (8, 1000), + (110, 1000), + (120, 1000), + (130, 1000), + ]); + + run_and_compare(candidates, voters, stake_of, 2, 2, true); +} diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index 085b7f52c1dff5c1f26b56098f3a692764f96781..a74092a48e713500a436ffbc1c8c9f2fedafa20e 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -7,39 +7,45 @@ edition = "2018" [dependencies] rstd = { package = "sr-std", path = "../sr-std", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -rustc-hex = { version = "2.0", default-features = false } -serde = { version = "1.0", optional = true, features = ["derive"] } -twox-hash = { version = "1.2.0", optional = true } -byteorder = { version = "1.3.1", default-features = false } -primitive-types = { version = "0.5.0", default-features = false, features = ["codec"] } -impl-serde = { version = "0.1", optional = true } -wasmi = { version = "0.5.0", optional = true } -hash-db = { version = "0.15.0", default-features = false } -hash256-std-hasher = { version = "0.15.0", default-features = false } -ed25519-dalek = { version = "1.0.0-pre.1", optional = true } -base58 = { version = "0.1", optional = true } -blake2-rfc = { version = "0.2.18", optional = true } -schnorrkel = { version = "0.8.4", features = ["preaudit_deprecated"], optional = true } -rand = { version = "0.6", optional = true } -sha2 = { version = "0.8", optional = true } +rustc-hex = { version = "2.0.1", default-features = false } +log = { version = "0.4.8", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +twox-hash = { version = "1.5.0", default-features = false, optional = true } +byteorder = { version = "1.3.2", default-features = false } +primitive-types = { version = "0.6", default-features = false, features = ["codec"] } +impl-serde = { version = "0.2.3", optional = true } +wasmi = { version = "0.5.1", optional = true } +hash-db = { version = "0.15.2", default-features = false } +hash256-std-hasher = { version = "0.15.2", default-features = false } +ed25519-dalek = { version = "0.9.1", default-features = false, features = ["u64_backend"], optional = true } +base58 = { version = "0.1.0", optional = true } +blake2-rfc = { version = "0.2.18", default-features = false, optional = true } +schnorrkel = { version = "0.8.5", features = ["preaudit_deprecated"], default-features = false, optional = true } +rand = { version = "0.7.2", optional = true } +sha2 = { version = "0.8.0", default-features = false, optional = true } substrate-bip39 = { version = "0.3.1", optional = true } -tiny-bip39 = { version = "0.6.1", optional = true } -hex = { version = "0.3", optional = true } -regex = { version = "1.1", optional = true } -num-traits = { version = "0.2", default-features = false } -zeroize = { version = "0.9.2", default-features = false } -lazy_static = { version = "1.3", optional = true } +tiny-bip39 = { version = "0.6.2", optional = true } +hex = { version = "0.4", default-features = false, optional = true } +regex = { version = "1.3.1", optional = true } +num-traits = { version = "0.2.8", default-features = false } +zeroize = { version = "0.10.1", default-features = false } +lazy_static = { version = "1.4.0", default-features = false, optional = true } parking_lot = { version = "0.9.0", optional = true } +libsecp256k1 = { version = "0.3.0", default-features = false, optional = true } +tiny-keccak = { version = "1.5.0", optional = true } +substrate-debug-derive = { version = "2.0.0", path = "./debug-derive" } +externalities = { package = "substrate-externalities", path = "../externalities", optional = true } +primitives-storage = { package = "substrate-primitives-storage", path = "storage", default-features = false } [dev-dependencies] substrate-serializer = { path = "../serializer" } -pretty_assertions = "0.6" -hex-literal = "0.2" -rand = "0.6" -criterion = "0.2" +pretty_assertions = "0.6.1" +hex-literal = "0.2.1" +rand = "0.7.2" +criterion = "0.2.11" [[bench]] -name = "benches" +name = "bench" harness = false [lib] @@ -48,9 +54,11 @@ bench = false [features] default = ["std"] std = [ + "full_crypto", + "log/std", "wasmi", "lazy_static", - "parking_lot", + "parking_lot", "primitive-types/std", "primitive-types/serde", "primitive-types/byteorder", @@ -63,19 +71,36 @@ std = [ "rstd/std", "serde", "rustc-hex/std", - "twox-hash", - "blake2-rfc", - "ed25519-dalek", - "hex", + "twox-hash/std", + "blake2-rfc/std", + "ed25519-dalek/std", + "hex/std", "base58", "substrate-bip39", "tiny-bip39", "serde", "byteorder/std", "rand", - "sha2", - "schnorrkel", + "sha2/std", + "schnorrkel/std", "regex", "num-traits/std", - "zeroize/std" + "libsecp256k1", + "tiny-keccak", + "substrate-debug-derive/std", + "externalities", + "primitives-storage/std", +] + +# This feature enables all crypto primitives for `no_std` builds like microcontrollers +# or Intel SGX. +# For the regular wasm runtime builds this should not be used. +full_crypto = [ + "ed25519-dalek", + "blake2-rfc", + "schnorrkel", + "libsecp256k1", + "hex", + "sha2", + "twox-hash" ] diff --git a/core/primitives/benches/benches.rs b/core/primitives/benches/bench.rs similarity index 100% rename from core/primitives/benches/benches.rs rename to core/primitives/benches/bench.rs diff --git a/core/primitives/debug-derive/Cargo.toml b/core/primitives/debug-derive/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a7bf90695ab932e7fe2e5f44b3437f13bb3cd2ca --- /dev/null +++ b/core/primitives/debug-derive/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "substrate-debug-derive" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.2" +syn = "1.0.7" +proc-macro2 = "1.0" + +[features] +std = [] + +[dev-dependencies] + diff --git a/core/primitives/debug-derive/src/impls.rs b/core/primitives/debug-derive/src/impls.rs new file mode 100644 index 0000000000000000000000000000000000000000..decceca044c1b5ac9fda8d749b720db79ddd0382 --- /dev/null +++ b/core/primitives/debug-derive/src/impls.rs @@ -0,0 +1,217 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use quote::quote; +use proc_macro2::TokenStream; +use syn::{Data, DeriveInput, parse_quote}; + +pub fn debug_derive(ast: DeriveInput) -> proc_macro::TokenStream { + let name_str = ast.ident.to_string(); + let implementation = implementation::derive(&name_str, &ast.data); + let name = &ast.ident; + let mut generics = ast.generics.clone(); + let (impl_generics, ty_generics, where_clause) = { + let wh = generics.make_where_clause(); + for t in ast.generics.type_params() { + let name = &t.ident; + wh.predicates.push(parse_quote!{ #name : core::fmt::Debug }); + } + generics.split_for_impl() + }; + let gen = quote!{ + impl #impl_generics core::fmt::Debug for #name #ty_generics #where_clause { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { + #implementation + } + } + }; + + gen.into() +} + +#[cfg(not(feature = "std"))] +mod implementation { + use super::*; + + /// Derive the inner implementation of `Debug::fmt` function. + /// + /// Non-std environment. We do nothing to prevent bloating the size of runtime. + /// Implement `Printable` if you need to print the details. + pub fn derive(_name_str: &str, _data: &Data) -> TokenStream { + quote! { + fmt.write_str("") + } + } +} + +#[cfg(feature = "std")] +mod implementation { + use super::*; + use proc_macro2::Span; + use syn::{Ident, Index, token::SelfValue}; + + /// Derive the inner implementation of `Debug::fmt` function. + pub fn derive(name_str: &str, data: &Data) -> TokenStream { + match *data { + Data::Struct(ref s) => derive_struct(&name_str, &s.fields), + Data::Union(ref u) => derive_fields(&name_str, Fields::new(u.fields.named.iter(), None)), + Data::Enum(ref e) => derive_enum(&name_str, &e), + } + } + + enum Fields { + Indexed { + indices: Vec, + }, + Unnamed { + vars: Vec, + }, + Named { + names: Vec, + this: Option, + }, + } + + impl Fields { + fn new<'a>(fields: impl Iterator, this: Option) -> Self { + let mut indices = vec![]; + let mut names = vec![]; + + for (i, f) in fields.enumerate() { + if let Some(ident) = f.ident.clone() { + names.push(ident); + } else { + indices.push(Index::from(i)); + } + } + + if names.is_empty() { + Self::Indexed { + indices, + } + } else { + Self::Named { + names, + this, + } + } + } + } + + fn derive_fields<'a>( + name_str: &str, + fields: Fields, + ) -> TokenStream { + match fields { + Fields::Named { names, this } => { + let names_str: Vec<_> = names.iter() + .map(|x| x.to_string()) + .collect(); + + let fields = match this { + None => quote! { #( .field(#names_str, #names) )* }, + Some(this) => quote! { #( .field(#names_str, &#this.#names) )* }, + }; + + quote! { + fmt.debug_struct(#name_str) + #fields + .finish() + } + + }, + Fields::Indexed { indices } => { + quote! { + fmt.debug_tuple(#name_str) + #( .field(&self.#indices) )* + .finish() + } + }, + Fields::Unnamed { vars } => { + quote! { + fmt.debug_tuple(#name_str) + #( .field(#vars) )* + .finish() + } + }, + } + } + + fn derive_enum( + name: &str, + e: &syn::DataEnum, + ) -> TokenStream { + let v = e.variants + .iter() + .map(|v| { + let name = format!("{}::{}", name, v.ident); + let ident = &v.ident; + match v.fields { + syn::Fields::Named(ref f) => { + let names: Vec<_> = f.named.iter().flat_map(|f| f.ident.clone()).collect(); + let fields_impl = derive_fields(&name, Fields::Named { + names: names.clone(), + this: None, + }); + (ident, (quote!{ { #( ref #names ),* } }, fields_impl)) + }, + syn::Fields::Unnamed(ref f) => { + let names = f.unnamed.iter() + .enumerate() + .map(|(id, _)| Ident::new(&format!("a{}", id), Span::call_site())) + .collect::>(); + let fields_impl = derive_fields(&name, Fields::Unnamed { vars: names.clone() }); + (ident, (quote! { ( #( ref #names ),* ) }, fields_impl)) + }, + syn::Fields::Unit => { + let fields_impl = derive_fields(&name, Fields::Indexed { indices: vec![] }); + (ident, (quote! { }, fields_impl)) + }, + } + }); + + type Vecs = (Vec, Vec); + let (variants, others): Vecs<_, _> = v.unzip(); + let (match_fields, variants_impl): Vecs<_, _> = others.into_iter().unzip(); + + quote! { + match self { + #( Self::#variants #match_fields => #variants_impl, )* + _ => Ok(()), + } + } + } + + fn derive_struct( + name_str: &str, + fields: &syn::Fields, + ) -> TokenStream { + match *fields { + syn::Fields::Named(ref f) => derive_fields( + name_str, + Fields::new(f.named.iter(), Some(syn::Token!(self)(Span::call_site()))), + ), + syn::Fields::Unnamed(ref f) => derive_fields( + name_str, + Fields::new(f.unnamed.iter(), None), + ), + syn::Fields::Unit => derive_fields( + name_str, + Fields::Indexed { indices: vec![] }, + ), + } + } +} diff --git a/core/primitives/debug-derive/src/lib.rs b/core/primitives/debug-derive/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..5e6cf6098b30e4f0b69c7a3dd4c1a26b86e0832d --- /dev/null +++ b/core/primitives/debug-derive/src/lib.rs @@ -0,0 +1,44 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Macros to derive runtime debug implementation. +//! +//! This custom derive implements a `core::fmt::Debug` trait, +//! but in case the `std` feature is enabled the implementation +//! will actually print out the structure as regular `derive(Debug)` +//! would do. If `std` is disabled the implementation will be empty. +//! +//! This behaviour is useful to prevent bloating the runtime WASM +//! blob from unneeded code. +//! +//! ```rust +//! #[derive(substrate_debug_derive::RuntimeDebug)] +//! struct MyStruct; +//! +//! assert_eq!(format!("{:?}", MyStruct), "MyStruct"); +//! ``` + +extern crate proc_macro; + +mod impls; + +use proc_macro::TokenStream; + +#[proc_macro_derive(RuntimeDebug)] +pub fn debug_derive(input: TokenStream) -> TokenStream { + impls::debug_derive(syn::parse_macro_input!(input)) +} + diff --git a/core/primitives/debug-derive/tests/tests.rs b/core/primitives/debug-derive/tests/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..63ad6a3e8d49718f8db818ee9cb4cd3370a9a8c6 --- /dev/null +++ b/core/primitives/debug-derive/tests/tests.rs @@ -0,0 +1,63 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use substrate_debug_derive::RuntimeDebug; + +#[derive(RuntimeDebug)] +struct Unnamed(u64, String); + +#[derive(RuntimeDebug)] +struct Named { + a: u64, + b: String, +} + +#[derive(RuntimeDebug)] +enum EnumLongName { + A, + B(A, String), + VariantLongName { + a: A, + b: String, + }, +} + + +#[test] +fn should_display_proper_debug() { + use self::EnumLongName as Enum; + + assert_eq!( + format!("{:?}", Unnamed(1, "abc".into())), + "Unnamed(1, \"abc\")" + ); + assert_eq!( + format!("{:?}", Named { a: 1, b: "abc".into() }), + "Named { a: 1, b: \"abc\" }" + ); + assert_eq!( + format!("{:?}", Enum::::A), + "EnumLongName::A" + ); + assert_eq!( + format!("{:?}", Enum::B(1, "abc".into())), + "EnumLongName::B(1, \"abc\")" + ); + assert_eq!( + format!("{:?}", Enum::VariantLongName { a: 1, b: "abc".into() }), + "EnumLongName::VariantLongName { a: 1, b: \"abc\" }" + ); +} diff --git a/core/primitives/src/changes_trie.rs b/core/primitives/src/changes_trie.rs index bda993a0cdd8ee7aff388020bde8743107592954..4ad087c3811c91e4630021d49bf4c3596b823af6 100644 --- a/core/primitives/src/changes_trie.rs +++ b/core/primitives/src/changes_trie.rs @@ -85,7 +85,6 @@ impl ChangesTrieConfiguration { /// Returns max level digest block number that has been created at block <= passed block number. /// /// Returns None if digests are not created at all. - /// This could return Some(zero), even though changes trie isn't ever created at this block. pub fn prev_max_level_digest_block( &self, zero: Number, @@ -96,24 +95,30 @@ impl ChangesTrieConfiguration { ::rstd::ops::Add + ::rstd::ops::Sub + ::rstd::ops::Div + ::rstd::ops::Mul + Zero, { - if !self.is_digest_build_enabled() { + if block <= zero { return None; } - if block <= zero { - return None; + let (next_begin, next_end) = self.next_max_level_digest_range(zero.clone(), block.clone())?; + + // if 'next' digest includes our block, then it is a also a previous digest + if next_end == block { + return Some(block); } - let max_digest_interval: Number = self.max_digest_interval().into(); - let max_digests_since_zero = (block.clone() - zero.clone()) / max_digest_interval.clone(); - let last_max_digest_block = zero.clone() + max_digests_since_zero * max_digest_interval.clone(); - if last_max_digest_block == zero { + // if previous digest ends at zero block, then there are no previous digest + let prev_end = next_begin - 1.into(); + if prev_end == zero { None } else { - Some(last_max_digest_block) + Some(prev_end) } } - /// Returns max level digest block number that must be created at block >= passed block number. + + /// Returns max level digest blocks range (inclusive) which includes passed block. + /// + /// Returns None if digests are not created at all. + /// It will return the first max-level digest if block is <= zero. pub fn next_max_level_digest_range( &self, zero: Number, @@ -276,6 +281,11 @@ mod tests { assert_eq!(config(1, 1).prev_max_level_digest_block(0u64, 16), None); assert_eq!(config(2, 1).prev_max_level_digest_block(0u64, 16), Some(16)); assert_eq!(config(4, 1).prev_max_level_digest_block(0u64, 16), Some(16)); + + assert_eq!(config(4, 2).prev_max_level_digest_block(0u64, 16), Some(16)); + assert_eq!(config(4, 2).prev_max_level_digest_block(0u64, 17), Some(16)); + assert_eq!(config(4, 2).prev_max_level_digest_block(0u64, 33), Some(32)); + assert_eq!(config(32, 1).prev_max_level_digest_block(0u64, 16), None); assert_eq!(config(2, 3).prev_max_level_digest_block(0u64, 10), Some(8)); assert_eq!(config(2, 3).prev_max_level_digest_block(0u64, 8), Some(8)); diff --git a/core/primitives/src/crypto.rs b/core/primitives/src/crypto.rs index 0adf50e1602f3ca40e7b222c11c52125d614f38b..ad883c1dc3d8678d0cea4249ab66e459a767b318 100644 --- a/core/primitives/src/crypto.rs +++ b/core/primitives/src/crypto.rs @@ -18,6 +18,7 @@ //! Cryptographic utilities. // end::description[] +use rstd::{vec::Vec, hash::Hash}; #[cfg(feature = "std")] use rstd::convert::TryInto; use rstd::convert::TryFrom; @@ -30,8 +31,7 @@ use codec::{Encode, Decode}; use regex::Regex; #[cfg(feature = "std")] use base58::{FromBase58, ToBase58}; -#[cfg(feature = "std")] -use std::hash::Hash; + use zeroize::Zeroize; #[doc(hidden)] pub use rstd::ops::Deref; @@ -43,12 +43,12 @@ pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold r pub const DEV_ADDRESS: &str = "5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV"; /// The infallible type. -#[derive(Debug)] +#[derive(crate::RuntimeDebug)] pub enum Infallible {} /// The length of the junction identifier. Note that this is also referred to as the /// `CHAIN_CODE_LENGTH` in the context of Schnorrkel. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub const JUNCTION_ID_LEN: usize = 32; /// Similar to `From`, except that the onus is on the part of the caller to ensure @@ -120,7 +120,7 @@ impl Drop for Protected { /// An error with the interpretation of a secret. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub enum SecretStringError { /// The overall format was invalid (e.g. the seed phrase contained symbols). InvalidFormat, @@ -140,7 +140,7 @@ pub enum SecretStringError { /// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex` /// a new public key from an existing public key. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)] -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub enum DeriveJunction { /// Soft (vanilla) derivation. Public keys have a correspondent derivation. Soft([u8; JUNCTION_ID_LEN]), @@ -148,7 +148,7 @@ pub enum DeriveJunction { Hard([u8; JUNCTION_ID_LEN]), } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl DeriveJunction { /// Consume self to return a soft derive junction with the same chain code. pub fn soften(self) -> Self { DeriveJunction::Soft(self.unwrap_inner()) } @@ -209,7 +209,7 @@ impl DeriveJunction { } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl> From for DeriveJunction { fn from(j: T) -> DeriveJunction { let j = j.as_ref(); @@ -236,7 +236,7 @@ impl> From for DeriveJunction { } /// An error type for SS58 decoding. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum PublicError { /// Bad alphabet. @@ -254,36 +254,71 @@ pub enum PublicError { } /// Key that can be encoded to/from SS58. -#[cfg(feature = "std")] -pub trait Ss58Codec: Sized { +#[cfg(feature = "full_crypto")] +pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default { /// Some if the string is a properly encoded SS58Check address. + #[cfg(feature = "std")] fn from_ss58check(s: &str) -> Result { Self::from_ss58check_with_version(s) .and_then(|(r, v)| match v { Ss58AddressFormat::SubstrateAccountDirect => Ok(r), + Ss58AddressFormat::PolkadotAccountDirect => Ok(r), + Ss58AddressFormat::KusamaAccountDirect => Ok(r), + Ss58AddressFormat::DothereumAccountDirect => Ok(r), v if v == *DEFAULT_VERSION.lock() => Ok(r), _ => Err(PublicError::UnknownVersion), }) } /// Some if the string is a properly encoded SS58Check address. - fn from_ss58check_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError>; + #[cfg(feature = "std")] + fn from_ss58check_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> { + let mut res = Self::default(); + let len = res.as_mut().len(); + let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. + if d.len() != len + 3 { + // Invalid length. + return Err(PublicError::BadLength); + } + let ver = d[0].try_into().map_err(|_: ()| PublicError::UnknownVersion)?; + + if d[len + 1..len + 3] != ss58hash(&d[0..len + 1]).as_bytes()[0..2] { + // Invalid checksum. + return Err(PublicError::InvalidChecksum); + } + res.as_mut().copy_from_slice(&d[1..len + 1]); + Ok((res, ver)) + } /// Some if the string is a properly encoded SS58Check address, optionally with /// a derivation path following. + #[cfg(feature = "std")] fn from_string(s: &str) -> Result { Self::from_string_with_version(s) .and_then(|(r, v)| match v { Ss58AddressFormat::SubstrateAccountDirect => Ok(r), + Ss58AddressFormat::PolkadotAccountDirect => Ok(r), + Ss58AddressFormat::KusamaAccountDirect => Ok(r), + Ss58AddressFormat::DothereumAccountDirect => Ok(r), v if v == *DEFAULT_VERSION.lock() => Ok(r), _ => Err(PublicError::UnknownVersion), }) } /// Return the ss58-check string for this key. - fn to_ss58check_with_version(&self, version: Ss58AddressFormat) -> String; + + #[cfg(feature = "std")] + fn to_ss58check_with_version(&self, version: Ss58AddressFormat) -> String { + let mut v = vec![version.into()]; + v.extend(self.as_ref()); + let r = ss58hash(&v); + v.extend(&r.as_bytes()[0..2]); + v.to_base58() + } /// Return the ss58-check string for this key. + #[cfg(feature = "std")] fn to_ss58check(&self) -> String { self.to_ss58check_with_version(*DEFAULT_VERSION.lock()) } /// Some if the string is a properly encoded SS58Check address, optionally with /// a derivation path following. + #[cfg(feature = "std")] fn from_string_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> { Self::from_ss58check_with_version(s) } @@ -318,7 +353,7 @@ lazy_static::lazy_static! { } /// A known address (sub)format/network ID for SS58. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] #[derive(Copy, Clone, PartialEq, Eq)] pub enum Ss58AddressFormat { /// Any Substrate network, direct checksum, standard account (*25519). @@ -327,23 +362,26 @@ pub enum Ss58AddressFormat { PolkadotAccountDirect, /// Kusama Relay-chain, direct checksum, standard account (*25519). KusamaAccountDirect, + /// Dothereum Para-chain, direct checksum, standard account (*25519). + DothereumAccountDirect, /// Use a manually provided numeric value. Custom(u8), } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl From for u8 { fn from(x: Ss58AddressFormat) -> u8 { match x { Ss58AddressFormat::SubstrateAccountDirect => 42, Ss58AddressFormat::PolkadotAccountDirect => 0, Ss58AddressFormat::KusamaAccountDirect => 2, + Ss58AddressFormat::DothereumAccountDirect => 20, Ss58AddressFormat::Custom(n) => n, } } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl TryFrom for Ss58AddressFormat { type Error = (); fn try_from(x: u8) -> Result { @@ -351,12 +389,13 @@ impl TryFrom for Ss58AddressFormat { 42 => Ok(Ss58AddressFormat::SubstrateAccountDirect), 0 => Ok(Ss58AddressFormat::PolkadotAccountDirect), 2 => Ok(Ss58AddressFormat::KusamaAccountDirect), + 20 => Ok(Ss58AddressFormat::DothereumAccountDirect), _ => Err(()), } } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl<'a> TryFrom<&'a str> for Ss58AddressFormat { type Error = (); fn try_from(x: &'a str) -> Result { @@ -364,6 +403,7 @@ impl<'a> TryFrom<&'a str> for Ss58AddressFormat { "substrate" => Ok(Ss58AddressFormat::SubstrateAccountDirect), "polkadot" => Ok(Ss58AddressFormat::PolkadotAccountDirect), "kusama" => Ok(Ss58AddressFormat::KusamaAccountDirect), + "dothereum" => Ok(Ss58AddressFormat::DothereumAccountDirect), a => a.parse::().map(Ss58AddressFormat::Custom).map_err(|_| ()), } } @@ -376,6 +416,7 @@ impl From for String { Ss58AddressFormat::SubstrateAccountDirect => "substrate".into(), Ss58AddressFormat::PolkadotAccountDirect => "polkadot".into(), Ss58AddressFormat::KusamaAccountDirect => "kusama".into(), + Ss58AddressFormat::DothereumAccountDirect => "dothereum".into(), Ss58AddressFormat::Custom(x) => x.to_string(), } } @@ -387,7 +428,8 @@ impl From for String { /// /// Current known "versions" are: /// - 0 direct (payload) checksum for 32-byte *25519 Polkadot addresses. -/// - 2 direct (payload) checksum for 32-byte *25519 Polkadot Milestone 'K' addresses. +/// - 2 direct (payload) checksum for 32-byte *25519 Kusama addresses. +/// - 20 direct (payload) checksum for 32-byte *25519 Dothereum addresses. /// - 42 direct (payload) checksum for 32-byte *25519 addresses on any Substrate-based network. #[cfg(feature = "std")] pub fn set_default_ss58_version(version: Ss58AddressFormat) { @@ -395,44 +437,28 @@ pub fn set_default_ss58_version(version: Ss58AddressFormat) { } #[cfg(feature = "std")] -impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { - fn from_ss58check_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> { - let mut res = T::default(); - let len = res.as_mut().len(); - let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. - if d.len() != len + 3 { - // Invalid length. - return Err(PublicError::BadLength); - } - let ver = d[0].try_into().map_err(|_: ()| PublicError::UnknownVersion)?; - - if d[len+1..len+3] != ss58hash(&d[0..len+1]).as_bytes()[0..2] { - // Invalid checksum. - return Err(PublicError::InvalidChecksum); - } - res.as_mut().copy_from_slice(&d[1..len+1]); - Ok((res, ver)) - } - - fn to_ss58check_with_version(&self, version: Ss58AddressFormat) -> String { - let mut v = vec![version.into()]; - v.extend(self.as_ref()); - let r = ss58hash(&v); - v.extend(&r.as_bytes()[0..2]); - v.to_base58() - } - +impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { fn from_string(s: &str) -> Result { - let re = Regex::new(r"^(?P[\w\d]+)?(?P(//?[^/]+)*)$") + let re = Regex::new(r"^(?P[\w\d ]+)?(?P(//?[^/]+)*)$") .expect("constructed from known-good static value; qed"); let cap = re.captures(s).ok_or(PublicError::InvalidFormat)?; let re_junction = Regex::new(r"/(/?[^/]+)") .expect("constructed from known-good static value; qed"); - let addr = Self::from_ss58check( - cap.name("ss58") - .map(|r| r.as_str()) - .unwrap_or(DEV_ADDRESS) - )?; + let s = cap.name("ss58") + .map(|r| r.as_str()) + .unwrap_or(DEV_ADDRESS); + let addr = if s.starts_with("0x") { + let d = hex::decode(&s[2..]).map_err(|_| PublicError::InvalidFormat)?; + let mut r = Self::default(); + if d.len() == r.as_ref().len() { + r.as_mut().copy_from_slice(&d); + r + } else { + Err(PublicError::BadLength)? + } + } else { + Self::from_ss58check(s)? + }; if cap["path"].is_empty() { Ok(addr) } else { @@ -444,7 +470,7 @@ impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { } fn from_string_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> { - let re = Regex::new(r"^(?P[\w\d]+)?(?P(//?[^/]+)*)$") + let re = Regex::new(r"^(?P[\w\d ]+)?(?P(//?[^/]+)*)$") .expect("constructed from known-good static value; qed"); let cap = re.captures(s).ok_or(PublicError::InvalidFormat)?; let re_junction = Regex::new(r"/(/?[^/]+)") @@ -482,6 +508,103 @@ pub trait Public: AsRef<[u8]> + AsMut<[u8]> + Default + Derive + CryptoType + Pa fn as_slice(&self) -> &[u8] { self.as_ref() } } +/// An opaque 32-byte cryptographic identifier. +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode)] +pub struct AccountId32([u8; 32]); + +impl UncheckedFrom for AccountId32 { + fn unchecked_from(h: crate::hash::H256) -> Self { + AccountId32(h.into()) + } +} + +#[cfg(feature = "std")] +impl Ss58Codec for AccountId32 {} + +impl AsRef<[u8]> for AccountId32 { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for AccountId32 { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +impl AsRef<[u8; 32]> for AccountId32 { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} + +impl AsMut<[u8; 32]> for AccountId32 { + fn as_mut(&mut self) -> &mut [u8; 32] { + &mut self.0 + } +} + +impl From<[u8; 32]> for AccountId32 { + fn from(x: [u8; 32]) -> AccountId32 { + AccountId32(x) + } +} + +impl<'a> rstd::convert::TryFrom<&'a [u8]> for AccountId32 { + type Error = (); + fn try_from(x: &'a [u8]) -> Result { + if x.len() == 32 { + let mut r = AccountId32::default(); + r.0.copy_from_slice(x); + Ok(r) + } else { + Err(()) + } + } +} + +impl From for [u8; 32] { + fn from(x: AccountId32) -> [u8; 32] { + x.0 + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for AccountId32 { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +impl rstd::fmt::Debug for AccountId32 { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } +} + +#[cfg(feature = "std")] +impl serde::Serialize for AccountId32 { + fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> serde::Deserialize<'de> for AccountId32 { + fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { + Ss58Codec::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| serde::de::Error::custom(format!("{:?}", e))) + } +} + #[cfg(feature = "std")] pub use self::dummy::*; @@ -524,24 +647,19 @@ mod dummy { type Seed = Dummy; type Signature = Dummy; type DeriveError = (); + #[cfg(feature = "std")] fn generate_with_phrase(_: Option<&str>) -> (Self, String, Self::Seed) { Default::default() } + #[cfg(feature = "std")] fn from_phrase(_: &str, _: Option<&str>) -> Result<(Self, Self::Seed), SecretStringError> { Ok(Default::default()) } fn derive< - Iter: Iterator - >(&self, _: Iter) -> Result { Ok(Self) } + Iter: Iterator, + >(&self, _: Iter, _: Option) -> Result<(Self, Option), Self::DeriveError> { Ok((Self, None)) } fn from_seed(_: &Self::Seed) -> Self { Self } fn from_seed_slice(_: &[u8]) -> Result { Ok(Self) } - fn from_standard_components< - I: Iterator - >( - _: &str, - _: Option<&str>, - _: I - ) -> Result { Ok(Self) } fn sign(&self, _: &[u8]) -> Self::Signature { Self } fn verify>(_: &Self::Signature, _: M, _: &Self::Public) -> bool { true } fn verify_weak, M: AsRef<[u8]>>(_: &[u8], _: M, _: P) -> bool { true } @@ -553,7 +671,7 @@ mod dummy { /// Trait suitable for typical cryptographic PKI key pair type. /// /// For now it just specifies how to create a key from a phrase and derivation path. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// The type which is used to encode a public key. type Public: Public + Hash; @@ -573,10 +691,10 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// /// This is only for ephemeral keys really, since you won't have access to the secret key /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + #[cfg(feature = "std")] fn generate() -> (Self, Self::Seed) { - let mut csprng: OsRng = OsRng::new().expect("OS random generator works; qed"); let mut seed = Self::Seed::default(); - csprng.fill_bytes(seed.as_mut()); + OsRng.fill_bytes(seed.as_mut()); (Self::from_seed(&seed), seed) } @@ -586,13 +704,18 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// /// This is generally slower than `generate()`, so prefer that unless you need to persist /// the key from the current session. + #[cfg(feature = "std")] fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed); /// Returns the KeyPair from the English BIP39 seed `phrase`, or `None` if it's invalid. + #[cfg(feature = "std")] fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Self, Self::Seed), SecretStringError>; /// Derive a child key from a series of given junctions. - fn derive>(&self, path: Iter) -> Result; + fn derive>(&self, + path: Iter, + seed: Option, + ) -> Result<(Self, Option), Self::DeriveError>; /// Generate new key pair from the provided `seed`. /// @@ -607,11 +730,6 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// by an attacker then they can also derive your key. fn from_seed_slice(seed: &[u8]) -> Result; - /// Construct a key from a phrase, password and path. - fn from_standard_components< - I: Iterator - >(phrase: &str, password: Option<&str>, path: I) -> Result; - /// Sign a message. fn sign(&self, message: &[u8]) -> Self::Signature; @@ -624,7 +742,9 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// Get the public key. fn public(&self) -> Self::Public; - /// Interprets the string `s` in order to generate a key Pair. + /// Interprets the string `s` in order to generate a key Pair. Returns both the pair and an optional seed, in the + /// case that the pair can be expressed as a direct derivation from a seed (some cases, such as Sr25519 derivations + /// with path components, cannot). /// /// This takes a helper function to do the key generation from a phrase, password and /// junction iterator. @@ -650,31 +770,47 @@ pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static { /// be equivalent to no password at all. /// /// `None` is returned if no matches are found. - fn from_string(s: &str, password_override: Option<&str>) -> Result { - let hex_seed = if s.starts_with("0x") { - &s[2..] - } else { - s - }; - - if let Ok(d) = hex::decode(hex_seed) { - if let Ok(r) = Self::from_seed_slice(&d) { - return Ok(r) - } - } - - let re = Regex::new(r"^(?P\w+( \w+)*)?(?P(//?[^/]+)*)(///(?P.*))?$") + #[cfg(feature = "std")] + fn from_string_with_seed(s: &str, password_override: Option<&str>) + -> Result<(Self, Option), SecretStringError> + { + let re = Regex::new(r"^(?P[\d\w ]+)?(?P(//?[^/]+)*)(///(?P.*))?$") .expect("constructed from known-good static value; qed"); let cap = re.captures(s).ok_or(SecretStringError::InvalidFormat)?; + let re_junction = Regex::new(r"/(/?[^/]+)") .expect("constructed from known-good static value; qed"); let path = re_junction.captures_iter(&cap["path"]) .map(|f| DeriveJunction::from(&f[1])); - Self::from_standard_components( - cap.name("phrase").map(|r| r.as_str()).unwrap_or(DEV_PHRASE), - password_override.or_else(|| cap.name("password").map(|m| m.as_str())), - path, - ) + + let phrase = cap.name("phrase").map(|r| r.as_str()).unwrap_or(DEV_PHRASE); + let password = password_override.or_else(|| cap.name("password").map(|m| m.as_str())); + + let (root, seed) = if phrase.starts_with("0x") { + hex::decode(&phrase[2..]).ok() + .and_then(|seed_vec| { + let mut seed = Self::Seed::default(); + if seed.as_ref().len() == seed_vec.len() { + seed.as_mut().copy_from_slice(&seed_vec); + Some((Self::from_seed(&seed), seed)) + } else { + None + } + }) + .ok_or(SecretStringError::InvalidSeed)? + } else { + Self::from_phrase(phrase, password) + .map_err(|_| SecretStringError::InvalidPhrase)? + }; + root.derive(path, Some(seed)).map_err(|_| SecretStringError::InvalidPath) + } + + /// Interprets the string `s` in order to generate a key pair. + /// + /// See [`from_string_with_seed`](Self::from_string_with_seed) for more extensive documentation. + #[cfg(feature = "std")] + fn from_string(s: &str, password_override: Option<&str>) -> Result { + Self::from_string_with_seed(s, password_override).map(|x| x.0) } /// Return a vec filled with raw data. @@ -719,7 +855,7 @@ impl UncheckedFrom for Outer where /// Type which has a particular kind of crypto associated with it. pub trait CryptoType { /// The pair key type of this crypto. - #[cfg(feature="std")] + #[cfg(feature = "full_crypto")] type Pair: Pair; } @@ -731,7 +867,7 @@ pub trait CryptoType { /// Values whose first character is `_` are reserved for private use and won't conflict with any /// public modules. #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(crate::RuntimeDebug)] pub struct KeyTypeId(pub [u8; 4]); impl From for KeyTypeId { @@ -767,10 +903,6 @@ impl<'a> TryFrom<&'a str> for KeyTypeId { pub mod key_types { use super::KeyTypeId; - /// Key type for generic S/R 25519 key. - pub const SR25519: KeyTypeId = KeyTypeId(*b"sr25"); - /// Key type for generic Ed25519 key. - pub const ED25519: KeyTypeId = KeyTypeId(*b"ed25"); /// Key type for Babe module, build-in. pub const BABE: KeyTypeId = KeyTypeId(*b"babe"); /// Key type for Grandpa module, build-in. @@ -782,7 +914,6 @@ pub mod key_types { /// Key type for ImOnline module, built-in. pub const IM_ONLINE: KeyTypeId = KeyTypeId(*b"imon"); /// A key type ID useful for tests. - #[cfg(feature = "std")] pub const DUMMY: KeyTypeId = KeyTypeId(*b"dumy"); } @@ -838,13 +969,13 @@ mod tests { } impl Pair for TestPair { type Public = TestPublic; - type Seed = [u8; 0]; + type Seed = [u8; 8]; type Signature = [u8; 0]; type DeriveError = (); - fn generate() -> (Self, ::Seed) { (TestPair::Generated, []) } + fn generate() -> (Self, ::Seed) { (TestPair::Generated, [0u8; 8]) } fn generate_with_phrase(_password: Option<&str>) -> (Self, String, ::Seed) { - (TestPair::GeneratedWithPhrase, "".into(), []) + (TestPair::GeneratedWithPhrase, "".into(), [0u8; 8]) } fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Self, ::Seed), SecretStringError> @@ -852,14 +983,20 @@ mod tests { Ok((TestPair::GeneratedFromPhrase { phrase: phrase.to_owned(), password: password.map(Into::into) - }, [])) + }, [0u8; 8])) } - fn derive>(&self, _path: Iter) - -> Result + fn derive>(&self, path_iter: Iter, _: Option<[u8; 8]>) + -> Result<(Self, Option<[u8; 8]>), Self::DeriveError> { - Err(()) + Ok((match self.clone() { + TestPair::Standard {phrase, password, path} => + TestPair::Standard { phrase, password, path: path.into_iter().chain(path_iter).collect() }, + TestPair::GeneratedFromPhrase {phrase, password} => + TestPair::Standard { phrase, password, path: path_iter.collect() }, + x => if path_iter.count() == 0 { x } else { return Err(()) }, + }, None)) } - fn from_seed(_seed: &::Seed) -> Self { TestPair::Seed(vec![]) } + fn from_seed(_seed: &::Seed) -> Self { TestPair::Seed(_seed.as_ref().to_owned()) } fn sign(&self, _message: &[u8]) -> Self::Signature { [] } fn verify>(_: &Self::Signature, _: M, _: &Self::Public) -> bool { true } fn verify_weak, M: AsRef<[u8]>>( @@ -868,17 +1005,6 @@ mod tests { _pubkey: P ) -> bool { true } fn public(&self) -> Self::Public { TestPublic } - fn from_standard_components>( - phrase: &str, - password: Option<&str>, - path: I - ) -> Result { - Ok(TestPair::Standard { - phrase: phrase.to_owned(), - password: password.map(ToOwned::to_owned), - path: path.collect() - }) - } fn from_seed_slice(seed: &[u8]) -> Result { @@ -895,10 +1021,6 @@ mod tests { TestPair::from_string("0x0123456789abcdef", None), Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) ); - assert_eq!( - TestPair::from_string("0123456789abcdef", None), - Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) - ); } #[test] diff --git a/core/primitives/src/ecdsa.rs b/core/primitives/src/ecdsa.rs new file mode 100644 index 0000000000000000000000000000000000000000..691e9fba5e184389e3e0f9745330f7ef8587ec6c --- /dev/null +++ b/core/primitives/src/ecdsa.rs @@ -0,0 +1,615 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// tag::description[] +//! Simple ECDSA API. +// end::description[] + +use rstd::vec::Vec; + +use rstd::cmp::Ordering; +use codec::{Encode, Decode}; + +#[cfg(feature = "full_crypto")] +use core::convert::{TryFrom, TryInto}; +#[cfg(feature = "std")] +use substrate_bip39::seed_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "full_crypto")] +use crate::{hashing::blake2_256, crypto::{Pair as TraitPair, DeriveJunction, SecretStringError}}; +#[cfg(feature = "std")] +use crate::crypto::Ss58Codec; +#[cfg(feature = "std")] +use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; +use crate::crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}; +#[cfg(feature = "full_crypto")] +use secp256k1::{PublicKey, SecretKey}; + +/// A secret seed (which is bytewise essentially equivalent to a SecretKey). +/// +/// We need it as a different type because `Seed` is expected to be AsRef<[u8]>. +#[cfg(feature = "full_crypto")] +type Seed = [u8; 32]; + +/// The ECDSA 33-byte compressed public key. +#[derive(Clone, Encode, Decode)] +pub struct Public(pub [u8; 33]); + +impl PartialOrd for Public { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Public { + fn cmp(&self, other: &Self) -> Ordering { + self.0[..].cmp(&other.0[..]) + } +} + +impl PartialEq for Public { + fn eq(&self, other: &Self) -> bool { + &self.0[..] == &other.0[..] + } +} + +impl Eq for Public {} + +impl Default for Public { + fn default() -> Self { + Public([0u8; 33]) + } +} + +/// A key pair. +#[cfg(feature = "full_crypto")] +#[derive(Clone)] +pub struct Pair { + public: PublicKey, + secret: SecretKey, +} + +impl AsRef<[u8; 33]> for Public { + fn as_ref(&self) -> &[u8; 33] { + &self.0 + } +} + +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +impl rstd::convert::TryFrom<&[u8]> for Public { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 33 { + let mut inner = [0u8; 33]; + inner.copy_from_slice(data); + Ok(Public(inner)) + } else { + Err(()) + } + } +} + +impl From for [u8; 33] { + fn from(x: Public) -> Self { + x.0 + } +} + +#[cfg(feature = "full_crypto")] +impl From for Public { + fn from(x: Pair) -> Self { + x.public() + } +} + +impl UncheckedFrom<[u8; 33]> for Public { + fn unchecked_from(x: [u8; 33]) -> Self { + Public(x) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for Public { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for Public { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&&self.0[..]), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "full_crypto")] +impl rstd::hash::Hash for Public { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +/// A signature (a 512-bit value). +#[derive(Encode, Decode)] +pub struct Signature([u8; 65]); + +impl rstd::convert::TryFrom<&[u8]> for Signature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(Signature(inner)) + } else { + Err(()) + } + } +} + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 65]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 65]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + self.0[..] == b.0[..] + } +} + +impl Eq for Signature {} + +impl From for [u8; 65] { + fn from(v: Signature) -> [u8; 65] { + v.0 + } +} + +impl AsRef<[u8; 65]> for Signature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for Signature { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "full_crypto")] +impl rstd::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + rstd::hash::Hash::hash(&self.0[..], state); + } +} + +impl Signature { + /// A new instance from the given 65-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 65]) -> Signature { + Signature(data) + } + + /// Recover the public key from this signature and a message. + #[cfg(feature = "full_crypto")] + pub fn recover>(&self, message: M) -> Option { + let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); + let sig: (_, _) = self.try_into().ok()?; + secp256k1::recover(&message, &sig.0, &sig.1).ok() + .map(|recovered| Public(recovered.serialize_compressed())) + } +} + +#[cfg(feature = "full_crypto")] +impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature { + fn from(x: (secp256k1::Signature, secp256k1::RecoveryId)) -> Signature { + let mut r = Self::default(); + r.0[0..64].copy_from_slice(&x.0.serialize()[..]); + r.0[64] = x.1.serialize(); + r + } +} + +#[cfg(feature = "full_crypto")] +impl<'a> TryFrom<&'a Signature> for (secp256k1::Signature, secp256k1::RecoveryId) { + type Error = (); + fn try_from(x: &'a Signature) -> Result<(secp256k1::Signature, secp256k1::RecoveryId), Self::Error> { + Ok(( + secp256k1::Signature::parse_slice(&x.0[0..64]).expect("hardcoded to 64 bytes; qed"), + secp256k1::RecoveryId::parse(x.0[64]).map_err(|_| ())?, + )) + } +} + +/// An error type for SS58 decoding. +#[cfg(feature = "std")] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum PublicError { + /// Bad alphabet. + BadBase58, + /// Bad length. + BadLength, + /// Unknown version. + UnknownVersion, + /// Invalid checksum. + InvalidChecksum, +} + +impl Public { + /// A new instance from the given 33-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + pub fn from_raw(data: [u8; 33]) -> Self { + Public(data) + } + + /// Return a slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; 33] { + self.as_ref() + } +} + +impl TraitPublic for Public { + /// A new instance from the given slice that should be 33 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 33]; + r.copy_from_slice(data); + Public(r) + } +} + +impl Derive for Public {} + +/// Derive a single hard junction. +#[cfg(feature = "full_crypto")] +fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + ("Secp256k1HDKD", secret_seed, cc).using_encoded(|data| { + let mut res = [0u8; 32]; + res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); + res + }) +} + +/// An error when deriving a key. +#[cfg(feature = "full_crypto")] +pub enum DeriveError { + /// A soft key was found in the path (and is unsupported). + SoftKeyInPath, +} + +#[cfg(feature = "full_crypto")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = DeriveError; + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + #[cfg(feature = "std")] + fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + let (pair, seed) = Self::from_phrase(phrase, password) + .expect("All phrases generated by Mnemonic are valid; qed"); + ( + pair, + phrase.to_owned(), + seed, + ) + } + + /// Generate key pair from given recovery phrase and password. + #[cfg(feature = "std")] + fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { + let big_seed = seed_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), + password.unwrap_or(""), + ).map_err(|_| SecretStringError::InvalidSeed)?; + let mut seed = Seed::default(); + seed.copy_from_slice(&big_seed[0..32]); + Self::from_seed_slice(&big_seed[0..32]).map(|x| (x, seed)) + } + + /// Make a new key pair from secret seed material. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed(seed: &Seed) -> Pair { + Self::from_seed_slice(&seed[..]).expect("seed has valid length; qed") + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed_slice(seed_slice: &[u8]) -> Result { + let secret = SecretKey::parse_slice(seed_slice) + .map_err(|_| SecretStringError::InvalidSeedLength)?; + let public = PublicKey::from_secret_key(&secret); + Ok(Pair{ secret, public }) + } + + /// Derive a child key from a series of given junctions. + fn derive>(&self, + path: Iter, + _seed: Option + ) -> Result<(Pair, Option), DeriveError> { + let mut acc = self.secret.serialize(); + for j in path { + match j { + DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), + DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), + } + } + Ok((Self::from_seed(&acc), Some(acc))) + } + + /// Get the public key. + fn public(&self) -> Public { + Public(self.public.serialize_compressed()) + } + + /// Sign a message. + fn sign(&self, message: &[u8]) -> Signature { + let message = secp256k1::Message::parse(&blake2_256(message)); + secp256k1::sign(&message, &self.secret).into() + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { + let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); + let sig: (_, _) = match sig.try_into() { Ok(x) => x, _ => return false }; + match secp256k1::recover(&message, &sig.0, &sig.1) { + Ok(actual) => &pubkey.0[..] == &actual.serialize_compressed()[..], + _ => false, + } + } + + /// Verify a signature on a message. Returns true if the signature is good. + /// + /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct + /// size. Use it only if you're coming from byte buffers and need the speed. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let message = secp256k1::Message::parse(&blake2_256(message.as_ref())); + if sig.len() != 65 { return false } + let ri = match secp256k1::RecoveryId::parse(sig[64]) { Ok(x) => x, _ => return false }; + let sig = match secp256k1::Signature::parse_slice(&sig[0..64]) { Ok(x) => x, _ => return false }; + match secp256k1::recover(&message, &sig, &ri) { + Ok(actual) => pubkey.as_ref() == &actual.serialize_compressed()[..], + _ => false, + } + } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec { + self.seed().to_vec() + } +} + +#[cfg(feature = "full_crypto")] +impl Pair { + /// Get the seed for this key. + pub fn seed(&self) -> Seed { + self.secret.serialize() + } + + /// Exactly as `from_string` except that if no matches are found then, the the first 32 + /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. + #[cfg(feature = "std")] + pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { + Self::from_string(s, password_override).unwrap_or_else(|_| { + let mut padded_seed: Seed = [' ' as u8; 32]; + let len = s.len().min(32); + padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]); + Self::from_seed(&padded_seed) + }) + } +} + +impl CryptoType for Public { + #[cfg(feature="full_crypto")] + type Pair = Pair; +} + +impl CryptoType for Signature { + #[cfg(feature="full_crypto")] + type Pair = Pair; +} + +#[cfg(feature="full_crypto")] +impl CryptoType for Pair { + type Pair = Pair; +} + +#[cfg(test)] +mod test { + use super::*; + use hex_literal::hex; + use crate::crypto::DEV_PHRASE; + + #[test] + fn default_phrase_should_be_used() { + assert_eq!( + Pair::from_string("//Alice///password", None).unwrap().public(), + Pair::from_string(&format!("{}//Alice", DEV_PHRASE), Some("password")).unwrap().public(), + ); + } + + #[test] + fn seed_and_derive_should_work() { + let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); + let pair = Pair::from_seed(&seed); + assert_eq!(pair.seed(), seed); + let path = vec![DeriveJunction::Hard([0u8; 32])]; + let derived = pair.derive(path.into_iter(), None).ok().unwrap(); + assert_eq!( + derived.0.seed(), + hex!("b8eefc4937200a8382d00050e050ced2d4ab72cc2ef1b061477afb51564fdd61") + ); + } + + #[test] + fn test_vector_should_work() { + let pair = Pair::from_seed( + &hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60") + ); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91") + )); + let message = b""; + let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00"); + let signature = Signature::from_raw(signature); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn test_vector_by_string_should_work() { + let pair = Pair::from_string( + "0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + None + ).unwrap(); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("028db55b05db86c0b1786ca49f095d76344c9e6056b2f02701a7e7f3c20aabfd91") + )); + let message = b""; + let signature = hex!("3dde91174bd9359027be59a428b8146513df80a2a3c7eda2194f64de04a69ab97b753169e94db6ffd50921a2668a48b94ca11e3d32c1ff19cfe88890aa7e8f3c00"); + let signature = Signature::from_raw(signature); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let (pair, _) = Pair::generate(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, b"Something else", &public)); + } + + #[test] + fn seeded_pair_should_work() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + assert_eq!(public, Public::from_raw( + hex!("035676109c54b9a16d271abeb4954316a40a32bcce023ac14c8e26e958aa68fba9") + )); + let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); + let signature = pair.sign(&message[..]); + println!("Correct signature: {:?}", signature); + assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, "Other message", &public)); + } + + #[test] + fn generate_with_phrase_recovery_possible() { + let (pair1, phrase, _) = Pair::generate_with_phrase(None); + let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn generate_with_password_phrase_recovery_possible() { + let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); + let (pair2, _) = Pair::from_phrase(&phrase, Some("password")).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); + } + + #[test] + fn password_does_something() { + let (pair1, phrase, _) = Pair::generate_with_phrase(Some("password")); + let (pair2, _) = Pair::from_phrase(&phrase, None).unwrap(); + + assert_ne!(pair1.public(), pair2.public()); + } + + #[test] + fn ss58check_roundtrip_works() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + let s = public.to_ss58check(); + println!("Correct: {}", s); + let cmp = Public::from_ss58check(&s).unwrap(); + assert_eq!(cmp, public); + } +} diff --git a/core/primitives/src/ed25519.rs b/core/primitives/src/ed25519.rs index 810e86767d8e365ce9026e91c932134285ed830a..0a25b8c80664474b4bf7f8fd4f81c6ce6fae0527 100644 --- a/core/primitives/src/ed25519.rs +++ b/core/primitives/src/ed25519.rs @@ -18,18 +18,21 @@ //! Simple Ed25519 API. // end::description[] +use rstd::vec::Vec; use crate::{hash::H256, hash::H512}; use codec::{Encode, Decode}; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] use blake2_rfc; #[cfg(feature = "std")] use substrate_bip39::seed_from_entropy; #[cfg(feature = "std")] use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "full_crypto")] +use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError}; #[cfg(feature = "std")] -use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError, Ss58Codec}; +use crate::crypto::Ss58Codec; #[cfg(feature = "std")] use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}}; @@ -37,18 +40,19 @@ use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}}; /// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys /// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we /// will need it later (such as for HDKD). -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] type Seed = [u8; 32]; /// A public key. +#[cfg_attr(feature = "full_crypto", derive(Hash))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] pub struct Public(pub [u8; 32]); /// A key pair. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub struct Pair(ed25519_dalek::Keypair); -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl Clone for Pair { fn clone(&self) -> Self { Pair(ed25519_dalek::Keypair { @@ -97,7 +101,7 @@ impl From for [u8; 32] { } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl From for Public { fn from(x: Pair) -> Self { x.public() @@ -129,12 +133,17 @@ impl std::fmt::Display for Public { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl rstd::fmt::Debug for Public { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { let s = self.to_ss58check(); write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } } #[cfg(feature = "std")] @@ -152,13 +161,6 @@ impl<'de> Deserialize<'de> for Public { } } -#[cfg(feature = "std")] -impl std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - /// A signature (a 512-bit value). #[derive(Encode, Decode)] pub struct Signature(pub [u8; 64]); @@ -229,17 +231,22 @@ impl AsMut<[u8]> for Signature { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for Signature { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl rstd::fmt::Debug for Signature { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } } -#[cfg(feature = "std")] -impl std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - std::hash::Hash::hash(&self.0[..], state); +#[cfg(feature = "full_crypto")] +impl rstd::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + rstd::hash::Hash::hash(&self.0[..], state); } } @@ -333,7 +340,7 @@ impl TraitPublic for Public { impl Derive for Public {} /// Derive a single hard junction. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { ("Ed25519HDKD", secret_seed, cc).using_encoded(|data| { let mut res = [0u8; 32]; @@ -343,13 +350,13 @@ fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { } /// An error when deriving a key. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub enum DeriveError { /// A soft key was found in the path (and is unsupported). SoftKeyInPath, } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl TraitPair for Pair { type Public = Public; type Seed = Seed; @@ -359,6 +366,7 @@ impl TraitPair for Pair { /// Generate new secure (random) key pair and provide the recovery phrase. /// /// You can recover the same key later with `from_phrase`. + #[cfg(feature = "std")] fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); let phrase = mnemonic.phrase(); @@ -372,6 +380,7 @@ impl TraitPair for Pair { } /// Generate key pair from given recovery phrase and password. + #[cfg(feature = "std")] fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { let big_seed = seed_from_entropy( Mnemonic::from_phrase(phrase, Language::English) @@ -397,12 +406,15 @@ impl TraitPair for Pair { fn from_seed_slice(seed_slice: &[u8]) -> Result { let secret = ed25519_dalek::SecretKey::from_bytes(seed_slice) .map_err(|_| SecretStringError::InvalidSeedLength)?; - let public = ed25519_dalek::PublicKey::from(&secret); + let public = ed25519_dalek::PublicKey::from(secret.expand::()); Ok(Pair(ed25519_dalek::Keypair { secret, public })) } /// Derive a child key from a series of given junctions. - fn derive>(&self, path: Iter) -> Result { + fn derive>(&self, + path: Iter, + _seed: Option, + ) -> Result<(Pair, Option), DeriveError> { let mut acc = self.0.secret.to_bytes(); for j in path { match j { @@ -410,18 +422,7 @@ impl TraitPair for Pair { DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), } } - Ok(Self::from_seed(&acc)) - } - - /// Generate a key from the phrase, password and derivation path. - fn from_standard_components>( - phrase: &str, - password: Option<&str>, - path: I - ) -> Result { - Self::from_phrase(phrase, password)?.0 - .derive(path) - .map_err(|_| SecretStringError::InvalidPath) + Ok((Self::from_seed(&acc), Some(acc))) } /// Get the public key. @@ -434,7 +435,7 @@ impl TraitPair for Pair { /// Sign a message. fn sign(&self, message: &[u8]) -> Signature { - let r = self.0.sign(message).to_bytes(); + let r = self.0.sign::(message).to_bytes(); Signature::from_raw(r) } @@ -458,7 +459,7 @@ impl TraitPair for Pair { Err(_) => return false }; - match public_key.verify(message.as_ref(), &sig) { + match public_key.verify::(message.as_ref(), &sig) { Ok(_) => true, _ => false, } @@ -470,7 +471,7 @@ impl TraitPair for Pair { } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl Pair { /// Get the seed for this key. pub fn seed(&self) -> &Seed { @@ -479,6 +480,7 @@ impl Pair { /// Exactly as `from_string` except that if no matches are found then, the the first 32 /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. + #[cfg(feature = "std")] pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { Self::from_string(s, password_override).unwrap_or_else(|_| { let mut padded_seed: Seed = [' ' as u8; 32]; @@ -490,16 +492,16 @@ impl Pair { } impl CryptoType for Public { - #[cfg(feature="std")] + #[cfg(feature = "full_crypto")] type Pair = Pair; } impl CryptoType for Signature { - #[cfg(feature="std")] + #[cfg(feature = "full_crypto")] type Pair = Pair; } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl CryptoType for Pair { type Pair = Pair; } @@ -524,7 +526,7 @@ mod test { let pair = Pair::from_seed(&seed); assert_eq!(pair.seed(), &seed); let path = vec![DeriveJunction::Hard([0u8; 32])]; - let derived = pair.derive(path.into_iter()).ok().unwrap(); + let derived = pair.derive(path.into_iter(), None).ok().unwrap().0; assert_eq!( derived.seed(), &hex!("ede3354e133f9c8e337ddd6ee5415ed4b4ffe5fc7d21e933f4930a3730e5b21c") diff --git a/core/primitives/src/hexdisplay.rs b/core/primitives/src/hexdisplay.rs index cd2b6c18cb7fed04ecb08a2a6ac936c7853a1762..2c8533e25b5f88808d2e973bc2223fe3dc534ae4 100644 --- a/core/primitives/src/hexdisplay.rs +++ b/core/primitives/src/hexdisplay.rs @@ -21,28 +21,37 @@ pub struct HexDisplay<'a>(&'a [u8]); impl<'a> HexDisplay<'a> { /// Create new instance that will display `d` as a hex string when displayed. - pub fn from(d: &'a dyn AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } + pub fn from(d: &'a R) -> Self { HexDisplay(d.as_bytes_ref()) } } -impl<'a> ::core::fmt::Display for HexDisplay<'a> { - fn fmt(&self, fmtr: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> { +impl<'a> rstd::fmt::Display for HexDisplay<'a> { + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> Result<(), rstd::fmt::Error> { if self.0.len() < 1027 { for byte in self.0 { - fmtr.write_fmt(format_args!("{:02x}", byte))?; + f.write_fmt(format_args!("{:02x}", byte))?; } } else { for byte in &self.0[0..512] { - fmtr.write_fmt(format_args!("{:02x}", byte))?; + f.write_fmt(format_args!("{:02x}", byte))?; } - fmtr.write_str("...")?; + f.write_str("...")?; for byte in &self.0[self.0.len() - 512..] { - fmtr.write_fmt(format_args!("{:02x}", byte))?; + f.write_fmt(format_args!("{:02x}", byte))?; } } Ok(()) } } +impl<'a> rstd::fmt::Debug for HexDisplay<'a> { + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> Result<(), rstd::fmt::Error> { + for byte in self.0 { + f.write_fmt(format_args!("{:02x}", byte))?; + } + Ok(()) + } +} + /// Simple trait to transform various types to `&[u8]` pub trait AsBytesRef { /// Transform `self` into `&[u8]`. @@ -71,7 +80,7 @@ macro_rules! impl_non_endians { impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], - [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); + [u8; 48], [u8; 56], [u8; 64], [u8; 65], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); /// Format into ASCII + # + hex, suitable for storage key preimages. pub fn ascii_format(asciish: &[u8]) -> String { diff --git a/core/primitives/src/lib.rs b/core/primitives/src/lib.rs index 21e7c878082ad85f4aade22a8711b2633f2f89df..21483cbd5c52d08a61a2cd2e23c64c7d11f040c1 100644 --- a/core/primitives/src/lib.rs +++ b/core/primitives/src/lib.rs @@ -26,9 +26,9 @@ /// Can be used to create a `HashMap`. #[macro_export] macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( + ($( $name:expr => $value:expr ),* $(,)? ) => ( vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) + ); } use rstd::prelude::*; @@ -39,14 +39,17 @@ use std::borrow::Cow; use serde::{Serialize, Deserialize}; #[cfg(feature = "std")] pub use serde;// << for macro +#[doc(hidden)] pub use codec::{Encode, Decode};// << for macro +pub use substrate_debug_derive::RuntimeDebug; + #[cfg(feature = "std")] pub use impl_serde::serialize as bytes; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub mod hashing; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub use hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256}; #[cfg(feature = "std")] pub mod hexdisplay; @@ -56,13 +59,14 @@ pub mod u32_trait; pub mod ed25519; pub mod sr25519; +pub mod ecdsa; pub mod hash; mod hasher; pub mod offchain; pub mod sandbox; -pub mod storage; pub mod uint; mod changes_trie; +#[cfg(feature = "std")] pub mod traits; pub mod testing; @@ -72,7 +76,7 @@ mod tests; pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::uint::U256; pub use changes_trie::ChangesTrieConfiguration; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub use crypto::{DeriveJunction, Pair, Public}; pub use hash_db::Hasher; @@ -80,6 +84,11 @@ pub use hash_db::Hasher; // pub use self::hasher::blake::BlakeHasher; pub use self::hasher::blake2::Blake2Hasher; +pub use primitives_storage as storage; + +#[doc(hidden)] +pub use rstd; + /// Context for executing a call into the runtime. pub enum ExecutionContext { /// Context for general importing (including own blocks). @@ -88,26 +97,30 @@ pub enum ExecutionContext { Syncing, /// Context used for block construction. BlockConstruction, - /// Offchain worker context. - OffchainWorker(Box), - /// Context used for other calls. - Other, + /// Context used for offchain calls. + /// + /// This allows passing offchain extension and customizing available capabilities. + OffchainCall(Option<(Box, offchain::Capabilities)>), } impl ExecutionContext { - /// Returns if the keystore should be enabled for the current context. - pub fn enable_keystore(&self) -> bool { + /// Returns the capabilities of particular context. + pub fn capabilities(&self) -> offchain::Capabilities { use ExecutionContext::*; + match self { - Importing | Syncing | BlockConstruction => false, - OffchainWorker(_) | Other => true, + Importing | Syncing | BlockConstruction => + offchain::Capabilities::none(), + // Enable keystore by default for offchain calls. CC @bkchr + OffchainCall(None) => [offchain::Capability::Keystore][..].into(), + OffchainCall(Some((_, capabilities))) => *capabilities, } } } /// Hex-serialized shim for `Vec`. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord))] +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord))] pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); impl From> for Bytes { @@ -152,9 +165,9 @@ pub enum NativeOrEncoded { } #[cfg(feature = "std")] -impl ::std::fmt::Debug for NativeOrEncoded { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - self.as_encoded().as_ref().fmt(f) +impl rstd::fmt::Debug for NativeOrEncoded { + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + hexdisplay::HexDisplay::from(&self.as_encoded().as_ref()).fmt(f) } } @@ -214,3 +227,85 @@ impl codec::Decode for NeverNativeValue { } } +/// Provide a simple 4 byte identifier for a type. +pub trait TypeId { + /// Simple 4 byte identifier. + const TYPE_ID: [u8; 4]; +} + +/// A log level matching the one from `log` crate. +/// +/// Used internally by `runtime_io::log` method. +#[repr(u32)] +pub enum LogLevel { + /// `Error` log level. + Error = 1, + /// `Warn` log level. + Warn = 2, + /// `Info` log level. + Info = 3, + /// `Debug` log level. + Debug = 4, + /// `Trace` log level. + Trace = 5, +} + +impl From for LogLevel { + fn from(val: u32) -> Self { + match val { + x if x == LogLevel::Warn as u32 => LogLevel::Warn, + x if x == LogLevel::Info as u32 => LogLevel::Info, + x if x == LogLevel::Debug as u32 => LogLevel::Debug, + x if x == LogLevel::Trace as u32 => LogLevel::Trace, + _ => LogLevel::Error, + } + } +} + +impl From for LogLevel { + fn from(l: log::Level) -> Self { + use log::Level::*; + match l { + Error => Self::Error, + Warn => Self::Warn, + Info => Self::Info, + Debug => Self::Debug, + Trace => Self::Trace, + } + } +} + +impl From for log::Level { + fn from(l: LogLevel) -> Self { + use self::LogLevel::*; + match l { + Error => Self::Error, + Warn => Self::Warn, + Info => Self::Info, + Debug => Self::Debug, + Trace => Self::Trace, + } + } +} + +/// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`. +/// +/// When Substrate calls into Wasm it expects a fixed signature for functions exported +/// from the Wasm blob. The return value of this signature is always a `u64`. +/// This `u64` stores the pointer to the encoded return value and the length of this encoded value. +/// The low `32bits` are reserved for the pointer, followed by `32bit` for the length. +#[cfg(not(feature = "std"))] +pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 { + let encoded = value.encode(); + + let ptr = encoded.as_ptr() as u64; + let length = encoded.len() as u64; + let res = ptr | (length << 32); + + // Leak the output vector to avoid it being freed. + // This is fine in a WASM context since the heap + // will be discarded after the call. + rstd::mem::forget(encoded); + + res +} diff --git a/core/primitives/src/offchain.rs b/core/primitives/src/offchain.rs index 52dbf5fbee3566433f2664ea1ce790a641599fdb..c69c074b747b131ea0cd79fcdc4761d7a8a19f0d 100644 --- a/core/primitives/src/offchain.rs +++ b/core/primitives/src/offchain.rs @@ -17,14 +17,13 @@ //! Offchain workers types use codec::{Encode, Decode}; -use rstd::prelude::{Vec, Box}; -use rstd::convert::TryFrom; +use rstd::{prelude::{Vec, Box}, convert::TryFrom}; +use crate::RuntimeDebug; pub use crate::crypto::KeyTypeId; /// A type of supported crypto. -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, RuntimeDebug)] #[repr(C)] pub enum StorageKind { /// Persistent storage is non-revertible and not fork-aware. It means that any value @@ -60,8 +59,8 @@ impl From for u32 { } /// Opaque type for offchain http requests. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Hash))] pub struct HttpRequestId(pub u16); impl From for u32 { @@ -71,14 +70,15 @@ impl From for u32 { } /// An error enum returned by some http methods. -#[derive(Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug)] #[repr(C)] pub enum HttpError { /// The requested action couldn't been completed within a deadline. DeadlineReached = 1, /// There was an IO Error while processing the request. IoError = 2, + /// The ID of the request is invalid in this context. + Invalid = 3, } impl TryFrom for HttpError { @@ -88,6 +88,7 @@ impl TryFrom for HttpError { match error { e if e == HttpError::DeadlineReached as u8 as u32 => Ok(HttpError::DeadlineReached), e if e == HttpError::IoError as u8 as u32 => Ok(HttpError::IoError), + e if e == HttpError::Invalid as u8 as u32 => Ok(HttpError::Invalid), _ => Err(()) } } @@ -100,23 +101,21 @@ impl From for u32 { } /// Status of the HTTP request -#[derive(Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug)] pub enum HttpRequestStatus { /// Deadline was reached while we waited for this request to finish. /// - /// Note the deadline is controlled by the calling part, it not necessarily means - /// that the request has timed out. + /// Note the deadline is controlled by the calling part, it not necessarily + /// means that the request has timed out. DeadlineReached, - /// Request timed out. - /// - /// This means that the request couldn't be completed by the host environment - /// within a reasonable time (according to the host), has now been terminated - /// and is considered finished. - /// To retry the request you need to construct it again. - Timeout, - /// Request status of this ID is not known. - Unknown, + /// An error has occured during the request, for example a timeout or the + /// remote has closed our socket. + /// + /// The request is now considered destroyed. To retry the request you need + /// to construct it again. + IoError, + /// The passed ID is invalid in this context. + Invalid, /// The request has finished with given status code. Finished(u16), } @@ -124,9 +123,9 @@ pub enum HttpRequestStatus { impl From for u32 { fn from(status: HttpRequestStatus) -> Self { match status { - HttpRequestStatus::Unknown => 0, + HttpRequestStatus::Invalid => 0, HttpRequestStatus::DeadlineReached => 10, - HttpRequestStatus::Timeout => 20, + HttpRequestStatus::IoError => 20, HttpRequestStatus::Finished(code) => u32::from(code), } } @@ -137,9 +136,9 @@ impl TryFrom for HttpRequestStatus { fn try_from(status: u32) -> Result { match status { - 0 => Ok(HttpRequestStatus::Unknown), + 0 => Ok(HttpRequestStatus::Invalid), 10 => Ok(HttpRequestStatus::DeadlineReached), - 20 => Ok(HttpRequestStatus::Timeout), + 20 => Ok(HttpRequestStatus::IoError), 100..=999 => u16::try_from(status).map(HttpRequestStatus::Finished).map_err(|_| ()), _ => Err(()), } @@ -148,8 +147,7 @@ impl TryFrom for HttpRequestStatus { /// A blob to hold information about the local node's network state /// without committing to its format. -#[derive(Clone, Eq, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] pub struct OpaqueNetworkState { /// PeerId of the local node. pub peer_id: OpaquePeerId, @@ -158,8 +156,7 @@ pub struct OpaqueNetworkState { } /// Simple blob to hold a `PeerId` without committing to its format. -#[derive(Clone, Eq, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Default, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] pub struct OpaquePeerId(pub Vec); impl OpaquePeerId { @@ -170,8 +167,7 @@ impl OpaquePeerId { } /// Simple blob to hold a `Multiaddr` without committing to its format. -#[derive(Clone, Eq, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)] pub struct OpaqueMultiaddr(pub Vec); impl OpaqueMultiaddr { @@ -182,13 +178,11 @@ impl OpaqueMultiaddr { } /// Opaque timestamp type -#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug)] pub struct Timestamp(u64); /// Duration type -#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Default, RuntimeDebug)] pub struct Duration(u64); impl Duration { @@ -230,8 +224,72 @@ impl Timestamp { } } +/// Execution context extra capabilities. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[repr(u8)] +pub enum Capability { + /// Access to transaction pool. + TransactionPool = 1, + /// External http calls. + Http = 2, + /// Keystore access. + Keystore = 4, + /// Randomness source. + Randomness = 8, + /// Access to opaque network state. + NetworkState = 16, + /// Access to offchain worker DB (read only). + OffchainWorkerDbRead = 32, + /// Access to offchain worker DB (writes). + OffchainWorkerDbWrite = 64, +} + +/// A set of capabilities +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Capabilities(u8); + +impl Capabilities { + /// Return an object representing an empty set of capabilities. + pub fn none() -> Self { + Self(0) + } + + /// Return an object representing all capabilities enabled. + pub fn all() -> Self { + Self(u8::max_value()) + } + + /// Return capabilities for rich offchain calls. + /// + /// Those calls should be allowed to sign and submit transactions + /// and access offchain workers database (but read only!). + pub fn rich_offchain_call() -> Self { + [ + Capability::TransactionPool, + Capability::Keystore, + Capability::OffchainWorkerDbRead, + ][..].into() + } + + /// Check if particular capability is enabled. + pub fn has(&self, capability: Capability) -> bool { + self.0 & capability as u8 != 0 + } + + /// Check if this capability object represents all capabilities. + pub fn has_all(&self) -> bool { + self == &Capabilities::all() + } +} + +impl<'a> From<&'a [Capability]> for Capabilities { + fn from(list: &'a [Capability]) -> Self { + Capabilities(list.iter().fold(0_u8, |a, b| a | *b as u8)) + } +} + /// An extended externalities for offchain workers. -pub trait Externalities { +pub trait Externalities: Send { /// Returns if the local node is a potential validator. /// /// Even if this function returns `true`, it does not mean that any keys are configured @@ -291,6 +349,11 @@ pub trait Externalities { /// /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. /// Returns the id of newly started request. + /// + /// Returns an error if: + /// - No new request identifier could be allocated. + /// - The method or URI contain invalid characters. + /// fn http_request_start( &mut self, method: &str, @@ -299,6 +362,18 @@ pub trait Externalities { ) -> Result; /// Append header to the request. + /// + /// Calling this function multiple times with the same header name continues appending new + /// headers. In other words, headers are never replaced. + /// + /// Returns an error if: + /// - The request identifier is invalid. + /// - You have called `http_request_write_body` on that request. + /// - The name or value contain invalid characters. + /// + /// An error doesn't poison the request, and you can continue as if the call had never been + /// made. + /// fn http_request_add_header( &mut self, request_id: HttpRequestId, @@ -308,10 +383,19 @@ pub trait Externalities { /// Write a chunk of request body. /// - /// Writing an empty chunks finalises the request. + /// Calling this function with a non-empty slice may or may not start the + /// HTTP request. Calling this function with an empty chunks finalizes the + /// request and always starts it. It is no longer valid to write more data + /// afterwards. /// Passing `None` as deadline blocks forever. /// - /// Returns an error in case deadline is reached or the chunk couldn't be written. + /// Returns an error if: + /// - The request identifier is invalid. + /// - `http_response_wait` has already been called on this request. + /// - The deadline is reached. + /// - An I/O error has happened, for example the remote has closed our + /// request. The request is then considered invalid. + /// fn http_request_write_body( &mut self, request_id: HttpRequestId, @@ -325,6 +409,9 @@ pub trait Externalities { /// Note that if deadline is not provided the method will block indefinitely, /// otherwise unready responses will produce `DeadlineReached` status. /// + /// If a response returns an `IoError`, it is then considered destroyed. + /// Its id is then invalid. + /// /// Passing `None` as deadline blocks forever. fn http_response_wait( &mut self, @@ -335,6 +422,12 @@ pub trait Externalities { /// Read all response headers. /// /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. + /// + /// Dispatches the request if it hasn't been done yet. It is no longer + /// valid to modify the headers or write data to the request. + /// + /// Returns an empty list if the identifier is unknown/invalid, hasn't + /// received a response, or has finished. fn http_response_headers( &mut self, request_id: HttpRequestId @@ -342,9 +435,23 @@ pub trait Externalities { /// Read a chunk of body response to given buffer. /// + /// Dispatches the request if it hasn't been done yet. It is no longer + /// valid to modify the headers or write data to the request. + /// /// Returns the number of bytes written or an error in case a deadline /// is reached or server closed the connection. /// Passing `None` as a deadline blocks forever. + /// + /// If `Ok(0)` or `Err(IoError)` is returned, the request is considered + /// destroyed. Doing another read or getting the response's headers, for + /// example, is then invalid. + /// + /// Returns an error if: + /// - The request identifier is invalid. + /// - The deadline is reached. + /// - An I/O error has happened, for example the remote has closed our + /// request. The request is then considered invalid. + /// fn http_response_read_body( &mut self, request_id: HttpRequestId, @@ -430,7 +537,137 @@ impl Externalities for Box { (&mut **self).http_response_read_body(request_id, buffer, deadline) } } +/// An `OffchainExternalities` implementation with limited capabilities. +pub struct LimitedExternalities { + capabilities: Capabilities, + externalities: T, +} + +impl LimitedExternalities { + /// Create new externalities limited to given `capabilities`. + pub fn new(capabilities: Capabilities, externalities: T) -> Self { + Self { + capabilities, + externalities, + } + } + + /// Check if given capability is allowed. + /// + /// Panics in case it is not. + fn check(&self, capability: Capability, name: &'static str) { + if !self.capabilities.has(capability) { + panic!("Accessing a forbidden API: {}. No: {:?} capability.", name, capability); + } + } +} +impl Externalities for LimitedExternalities { + fn is_validator(&self) -> bool { + self.check(Capability::Keystore, "is_validator"); + self.externalities.is_validator() + } + + fn submit_transaction(&mut self, ex: Vec) -> Result<(), ()> { + self.check(Capability::TransactionPool, "submit_transaction"); + self.externalities.submit_transaction(ex) + } + + fn network_state(&self) -> Result { + self.check(Capability::NetworkState, "network_state"); + self.externalities.network_state() + } + + fn timestamp(&mut self) -> Timestamp { + self.check(Capability::Http, "timestamp"); + self.externalities.timestamp() + } + + fn sleep_until(&mut self, deadline: Timestamp) { + self.check(Capability::Http, "sleep_until"); + self.externalities.sleep_until(deadline) + } + + fn random_seed(&mut self) -> [u8; 32] { + self.check(Capability::Randomness, "random_seed"); + self.externalities.random_seed() + } + + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { + self.check(Capability::OffchainWorkerDbWrite, "local_storage_set"); + self.externalities.local_storage_set(kind, key, value) + } + + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option<&[u8]>, + new_value: &[u8], + ) -> bool { + self.check(Capability::OffchainWorkerDbWrite, "local_storage_compare_and_set"); + self.externalities.local_storage_compare_and_set(kind, key, old_value, new_value) + } + + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { + self.check(Capability::OffchainWorkerDbRead, "local_storage_get"); + self.externalities.local_storage_get(kind, key) + } + + fn http_request_start(&mut self, method: &str, uri: &str, meta: &[u8]) -> Result { + self.check(Capability::Http, "http_request_start"); + self.externalities.http_request_start(method, uri, meta) + } + + fn http_request_add_header(&mut self, request_id: HttpRequestId, name: &str, value: &str) -> Result<(), ()> { + self.check(Capability::Http, "http_request_add_header"); + self.externalities.http_request_add_header(request_id, name, value) + } + + fn http_request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option + ) -> Result<(), HttpError> { + self.check(Capability::Http, "http_request_write_body"); + self.externalities.http_request_write_body(request_id, chunk, deadline) + } + + fn http_response_wait(&mut self, ids: &[HttpRequestId], deadline: Option) -> Vec { + self.check(Capability::Http, "http_response_wait"); + self.externalities.http_response_wait(ids, deadline) + } + + fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { + self.check(Capability::Http, "http_response_headers"); + self.externalities.http_response_headers(request_id) + } + + fn http_response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option + ) -> Result { + self.check(Capability::Http, "http_response_read_body"); + self.externalities.http_response_read_body(request_id, buffer, deadline) + } +} + +#[cfg(feature = "std")] +externalities::decl_extension! { + /// The offchain extension that will be registered at the Substrate externalities. + pub struct OffchainExt(Box); +} + +#[cfg(feature = "std")] +impl OffchainExt { + /// Create a new instance of `Self`. + pub fn new(offchain: O) -> Self { + Self(Box::new(offchain)) + } +} #[cfg(test)] mod tests { @@ -443,4 +680,18 @@ mod tests { assert_eq!(t.sub(Duration::from_millis(10)), Timestamp(0)); assert_eq!(t.diff(&Timestamp(3)), Duration(2)); } + + #[test] + fn capabilities() { + let none = Capabilities::none(); + let all = Capabilities::all(); + let some = Capabilities::from(&[Capability::Keystore, Capability::Randomness][..]); + + assert!(!none.has(Capability::Keystore)); + assert!(all.has(Capability::Keystore)); + assert!(some.has(Capability::Keystore)); + assert!(!none.has(Capability::TransactionPool)); + assert!(all.has(Capability::TransactionPool)); + assert!(!some.has(Capability::TransactionPool)); + } } diff --git a/core/primitives/src/sandbox.rs b/core/primitives/src/sandbox.rs index e47a30ca5bbb7abb91c4901d9e05d0df33836b2d..dd91ad6a1f5c0ef00966c57b4a20ab93359118af 100644 --- a/core/primitives/src/sandbox.rs +++ b/core/primitives/src/sandbox.rs @@ -21,12 +21,12 @@ use rstd::vec::Vec; /// Error error that can be returned from host function. #[derive(Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(crate::RuntimeDebug)] pub struct HostError; /// Representation of a typed wasm value. #[derive(Clone, Copy, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(crate::RuntimeDebug)] pub enum TypedValue { /// Value of 32-bit signed or unsigned integer. #[codec(index = "1")] @@ -86,7 +86,7 @@ impl From for ::wasmi::RuntimeValue { /// /// Basically a `TypedValue` plus `Unit`, for functions which return nothing. #[derive(Clone, Copy, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(crate::RuntimeDebug)] pub enum ReturnValue { /// For returning nothing. Unit, @@ -119,7 +119,7 @@ fn return_value_encoded_max_size() { /// Describes an entity to define or import into the environment. #[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(crate::RuntimeDebug)] pub enum ExternEntity { /// Function that is specified by an index in a default table of /// a module that creates the sandbox. @@ -137,7 +137,7 @@ pub enum ExternEntity { /// Each entry has a two-level name and description of an entity /// being defined. #[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(crate::RuntimeDebug)] pub struct Entry { /// Module name of which corresponding entity being defined. pub module_name: Vec, @@ -149,7 +149,7 @@ pub struct Entry { /// Definition of runtime that could be used by sandboxed code. #[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(crate::RuntimeDebug)] pub struct EnvironmentDefinition { /// Vector of all entries in the environment definition. pub entries: Vec, diff --git a/core/primitives/src/sr25519.rs b/core/primitives/src/sr25519.rs index 0e573f49ce34c3de29565df0fc318b6214aae2d3..7bec910d730ca31788bbc49e734f14d90ae6f994 100644 --- a/core/primitives/src/sr25519.rs +++ b/core/primitives/src/sr25519.rs @@ -20,8 +20,8 @@ //! Note: `CHAIN_CODE_LENGTH` must be equal to `crate::crypto::JUNCTION_ID_LEN` //! for this to work. // end::description[] - -#[cfg(feature = "std")] +use rstd::vec::Vec; +#[cfg(feature = "full_crypto")] use schnorrkel::{signing_context, ExpansionMode, Keypair, SecretKey, MiniSecretKey, PublicKey, derive::{Derivation, ChainCode, CHAIN_CODE_LENGTH} }; @@ -29,32 +29,36 @@ use schnorrkel::{signing_context, ExpansionMode, Keypair, SecretKey, MiniSecretK use substrate_bip39::mini_secret_from_entropy; #[cfg(feature = "std")] use bip39::{Mnemonic, Language, MnemonicType}; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] use crate::crypto::{ - Pair as TraitPair, DeriveJunction, Infallible, SecretStringError, Ss58Codec + Pair as TraitPair, DeriveJunction, Infallible, SecretStringError }; +#[cfg(feature = "std")] +use crate::crypto::Ss58Codec; + use crate::{crypto::{Public as TraitPublic, UncheckedFrom, CryptoType, Derive}}; use crate::hash::{H256, H512}; use codec::{Encode, Decode}; #[cfg(feature = "std")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] use schnorrkel::keys::{MINI_SECRET_KEY_LENGTH, SECRET_KEY_LENGTH}; // signing context -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] const SIGNING_CTX: &[u8] = b"substrate"; /// An Schnorrkel/Ristretto x25519 ("sr25519") public key. +#[cfg_attr(feature = "full_crypto", derive(Hash))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] pub struct Public(pub [u8; 32]); /// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] pub struct Pair(Keypair); -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl Clone for Pair { fn clone(&self) -> Self { Pair(schnorrkel::Keypair { @@ -128,12 +132,17 @@ impl std::fmt::Display for Public { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for Public { - fn fmt(&self, f: &mut std::fmt::Formatter) -> ::std::fmt::Result { +impl rstd::fmt::Debug for Public { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { let s = self.to_ss58check(); write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } } #[cfg(feature = "std")] @@ -151,13 +160,6 @@ impl<'de> Deserialize<'de> for Public { } } -#[cfg(feature = "std")] -impl std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - /// An Schnorrkel/Ristretto x25519 ("sr25519") signature. /// /// Instead of importing it for the local module, alias it to be available as a public type @@ -230,24 +232,29 @@ impl AsMut<[u8]> for Signature { } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl From for Signature { fn from(s: schnorrkel::Signature) -> Signature { Signature(s.to_bytes()) } } -#[cfg(feature = "std")] -impl std::fmt::Debug for Signature { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { +impl rstd::fmt::Debug for Signature { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } } -#[cfg(feature = "std")] -impl std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - std::hash::Hash::hash(&self.0[..], state); +#[cfg(feature = "full_crypto")] +impl rstd::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + rstd::hash::Hash::hash(&self.0[..], state); } } @@ -358,21 +365,21 @@ impl From for Pair { } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl From for Pair { fn from(p: schnorrkel::Keypair) -> Pair { Pair(p) } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl From for schnorrkel::Keypair { fn from(p: Pair) -> schnorrkel::Keypair { p.0 } } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl AsRef for Pair { fn as_ref(&self) -> &schnorrkel::Keypair { &self.0 @@ -380,16 +387,16 @@ impl AsRef for Pair { } /// Derive a single hard junction. -#[cfg(feature = "std")] -fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> SecretKey { - secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0.expand(ExpansionMode::Ed25519) +#[cfg(feature = "full_crypto")] +fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> MiniSecretKey { + secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0 } /// The raw secret seed, which can be used to recreate the `Pair`. -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] type Seed = [u8; MINI_SECRET_KEY_LENGTH]; -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl TraitPair for Pair { type Public = Public; type Seed = Seed; @@ -436,18 +443,7 @@ impl TraitPair for Pair { _ => Err(SecretStringError::InvalidSeedLength) } } - - /// Generate a key from the phrase, password and derivation path. - fn from_standard_components>( - phrase: &str, - password: Option<&str>, - path: I - ) -> Result { - Self::from_phrase(phrase, password)?.0 - .derive(path) - .map_err(|_| SecretStringError::InvalidPath) - } - + #[cfg(feature = "std")] fn generate_with_phrase(password: Option<&str>) -> (Pair, String, Seed) { let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); let phrase = mnemonic.phrase(); @@ -459,20 +455,34 @@ impl TraitPair for Pair { seed, ) } - + #[cfg(feature = "std")] fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Pair, Seed), SecretStringError> { Mnemonic::from_phrase(phrase, Language::English) .map_err(|_| SecretStringError::InvalidPhrase) .map(|m| Self::from_entropy(m.entropy(), password)) } - fn derive>(&self, path: Iter) -> Result { + fn derive>(&self, + path: Iter, + seed: Option, + ) -> Result<(Pair, Option), Self::DeriveError> { + let seed = if let Some(s) = seed { + if let Ok(msk) = MiniSecretKey::from_bytes(&s) { + if msk.expand(ExpansionMode::Ed25519) == self.0.secret { + Some(msk) + } else { None } + } else { None } + } else { None }; let init = self.0.secret.clone(); - let result = path.fold(init, |acc, j| match j { - DeriveJunction::Soft(cc) => acc.derived_key_simple(ChainCode(cc), &[]).0, - DeriveJunction::Hard(cc) => derive_hard_junction(&acc, &cc), + let (result, seed) = path.fold((init, seed), |(acc, acc_seed), j| match (j, acc_seed) { + (DeriveJunction::Soft(cc), _) => + (acc.derived_key_simple(ChainCode(cc), &[]).0, None), + (DeriveJunction::Hard(cc), maybe_seed) => { + let seed = derive_hard_junction(&acc, &cc); + (seed.expand(ExpansionMode::Ed25519), maybe_seed.map(|_| seed)) + } }); - Ok(Self(result.into())) + Ok((Self(result.into()), seed.map(|s| MiniSecretKey::to_bytes(&s)))) } fn sign(&self, message: &[u8]) -> Signature { @@ -520,16 +530,16 @@ impl Pair { } impl CryptoType for Public { - #[cfg(feature="std")] + #[cfg(feature = "full_crypto")] type Pair = Pair; } impl CryptoType for Signature { - #[cfg(feature="std")] + #[cfg(feature = "full_crypto")] type Pair = Pair; } -#[cfg(feature = "std")] +#[cfg(feature = "full_crypto")] impl CryptoType for Pair { type Pair = Pair; } @@ -614,9 +624,9 @@ mod test { let pair = Pair::from_seed(&hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); - let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); - let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); - let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter()).unwrap(); + let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter(), None).unwrap().0; + let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter(), None).unwrap().0; + let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter(), None).unwrap().0; assert_eq!(derive_1.public(), derive_1b.public()); assert_ne!(derive_1.public(), derive_2.public()); } @@ -626,9 +636,9 @@ mod test { let pair = Pair::from_seed(&hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); - let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); - let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); - let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter()).unwrap(); + let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter(), None).unwrap().0; + let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter(), None).unwrap().0; + let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter(), None).unwrap().0; assert_eq!(derive_1.public(), derive_1b.public()); assert_ne!(derive_1.public(), derive_2.public()); } @@ -639,7 +649,7 @@ mod test { "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); let path = Some(DeriveJunction::soft(1)); - let pair_1 = pair.derive(path.clone().into_iter()).unwrap(); + let pair_1 = pair.derive(path.clone().into_iter(), None).unwrap().0; let public_1 = pair.public().derive(path.into_iter()).unwrap(); assert_eq!(pair_1.public(), public_1); } diff --git a/core/primitives/src/storage.rs b/core/primitives/src/storage.rs deleted file mode 100644 index 8fdb7bdcc40c03618ea1eb3f02f7356676452c1e..0000000000000000000000000000000000000000 --- a/core/primitives/src/storage.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Contract execution data. - -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -#[cfg(feature = "std")] -use crate::bytes; -use rstd::vec::Vec; - -/// Contract storage key. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord, Clone))] -pub struct StorageKey(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -/// Contract storage entry data. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord, Clone))] -pub struct StorageData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -/// Storage change set -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, PartialEq, Eq))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -pub struct StorageChangeSet { - /// Block hash - pub block: Hash, - /// A list of changes - pub changes: Vec<( - StorageKey, - Option, - )>, -} - -/// List of all well known keys and prefixes in storage. -pub mod well_known_keys { - - /// Wasm code of the runtime. - /// - /// Stored as a raw byte vector. Required by substrate. - pub const CODE: &'static [u8] = b":code"; - - /// Number of wasm linear memory pages required for execution of the runtime. - /// - /// The type of this value is encoded `u64`. - pub const HEAP_PAGES: &'static [u8] = b":heappages"; - - /// Current extrinsic index (u32) is stored under this key. - pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index"; - - /// Changes trie configuration is stored under this key. - pub const CHANGES_TRIE_CONFIG: &'static [u8] = b":changes_trie"; - - /// Prefix of child storage keys. - pub const CHILD_STORAGE_KEY_PREFIX: &'static [u8] = b":child_storage:"; - - /// Whether a key is a child storage key. - /// - /// This is convenience function which basically checks if the given `key` starts - /// with `CHILD_STORAGE_KEY_PREFIX` and doesn't do anything apart from that. - pub fn is_child_storage_key(key: &[u8]) -> bool { - // Other code might depend on this, so be careful changing this. - key.starts_with(CHILD_STORAGE_KEY_PREFIX) - } -} diff --git a/core/primitives/src/testing.rs b/core/primitives/src/testing.rs index 932c8b9cb1e75707b10beb5870d39486e3e2d722..e5d301008e3d4fb3344ad7306b797f9b70727964 100644 --- a/core/primitives/src/testing.rs +++ b/core/primitives/src/testing.rs @@ -17,7 +17,13 @@ //! Types that should only be used for testing! #[cfg(feature = "std")] -use crate::{ed25519, sr25519, crypto::{Public, Pair, KeyTypeId}}; +use crate::{ed25519, sr25519, crypto::{Public, Pair}}; +use crate::crypto::KeyTypeId; + +/// Key type for generic Ed25519 key. +pub const ED25519: KeyTypeId = KeyTypeId(*b"ed25"); +/// Key type for generic Sr 25519 key. +pub const SR25519: KeyTypeId = KeyTypeId(*b"sr25"); /// A keystore implementation usable in tests. #[cfg(feature = "std")] @@ -30,7 +36,7 @@ pub struct KeyStore { #[cfg(feature = "std")] impl KeyStore { /// Creates a new instance of `Self`. - pub fn new() -> std::sync::Arc> { + pub fn new() -> crate::traits::BareCryptoStorePtr { std::sync::Arc::new(parking_lot::RwLock::new(Self::default())) } } @@ -123,21 +129,122 @@ impl crate::traits::BareCryptoStore for KeyStore { } } +/// Macro for exporting functions from wasm in with the expected signature for using it with the +/// wasm executor. This is useful for tests where you need to call a function in wasm. +/// +/// The input parameters are expected to be SCALE encoded and will be automatically decoded for you. +/// The output value is also SCALE encoded when returned back to the host. +/// +/// The functions are feature-gated with `#[cfg(not(feature = "std"))]`, so they are only available +/// from within wasm. +/// +/// # Example +/// +/// ``` +/// # use substrate_primitives::wasm_export_functions; +/// +/// wasm_export_functions! { +/// fn test_in_wasm(value: bool, another_value: Vec) -> bool { +/// value && another_value.is_empty() +/// } +/// +/// fn without_return_value() { +/// // do something +/// } +/// } +/// ``` +#[macro_export] +macro_rules! wasm_export_functions { + ( + $( + fn $name:ident ( + $( $arg_name:ident: $arg_ty:ty ),* $(,)? + ) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* } + )* + ) => { + $( + $crate::wasm_export_functions! { + @IMPL + fn $name ( + $( $arg_name: $arg_ty ),* + ) $( -> $ret_ty )? { $( $fn_impl )* } + } + )* + }; + (@IMPL + fn $name:ident ( + $( $arg_name:ident: $arg_ty:ty ),* + ) { $( $fn_impl:tt )* } + ) => { + #[no_mangle] + #[allow(unreachable_code)] + #[cfg(not(feature = "std"))] + pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { + let input: &[u8] = if input_len == 0 { + &[0u8; 0] + } else { + unsafe { + $crate::rstd::slice::from_raw_parts(input_data, input_len) + } + }; + + { + let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode( + &mut &input[..], + ).expect("Input data is correctly encoded"); + + $( $fn_impl )* + } + + $crate::to_substrate_wasm_fn_return_value(&()) + } + }; + (@IMPL + fn $name:ident ( + $( $arg_name:ident: $arg_ty:ty ),* + ) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* } + ) => { + #[no_mangle] + #[allow(unreachable_code)] + #[cfg(not(feature = "std"))] + pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { + let input: &[u8] = if input_len == 0 { + &[0u8; 0] + } else { + unsafe { + $crate::rstd::slice::from_raw_parts(input_data, input_len) + } + }; + + let output $( : $ret_ty )? = { + let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode( + &mut &input[..], + ).expect("Input data is correctly encoded"); + + $( $fn_impl )* + }; + + $crate::to_substrate_wasm_fn_return_value(&output) + } + }; +} + #[cfg(test)] mod tests { use super::*; - use crate::{sr25519, crypto::key_types, traits::BareCryptoStore}; + use crate::sr25519; + use crate::testing::{ED25519, SR25519}; #[test] fn store_key_and_extract() { let store = KeyStore::new(); let public = store.write() - .ed25519_generate_new(key_types::ED25519, None) + .ed25519_generate_new(ED25519, None) .expect("Genrates key"); let store_key_pair = store.read() - .ed25519_key_pair(key_types::ED25519, &public) + .ed25519_key_pair(ED25519, &public) .expect("Key should exists in store"); assert_eq!(public, store_key_pair.public()); @@ -151,13 +258,13 @@ mod tests { let key_pair = sr25519::Pair::from_string(secret_uri, None).expect("Generates key pair"); store.write().insert_unknown( - key_types::SR25519, + SR25519, secret_uri, key_pair.public().as_ref(), ).expect("Inserts unknown key"); let store_key_pair = store.read().sr25519_key_pair( - key_types::SR25519, + SR25519, &key_pair.public(), ).expect("Gets key pair from keystore"); diff --git a/core/primitives/src/traits.rs b/core/primitives/src/traits.rs index 8e2f0c0213a13b26ed290b685ed014d3e99f32fd..1ef665032eed4cb9cba4787450035c4d36c5c752 100644 --- a/core/primitives/src/traits.rs +++ b/core/primitives/src/traits.rs @@ -16,11 +16,13 @@ //! Shareable Substrate traits. -#[cfg(feature = "std")] use crate::{crypto::KeyTypeId, ed25519, sr25519}; +use std::{fmt::{Debug, Display}, panic::UnwindSafe}; + +pub use externalities::{Externalities, ExternalitiesExt}; + /// Something that generates, stores and provides access to keys. -#[cfg(feature = "std")] pub trait BareCryptoStore: Send + Sync { /// Returns all sr25519 public keys for the given key type. fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec; @@ -66,5 +68,30 @@ pub trait BareCryptoStore: Send + Sync { } /// A pointer to the key store. -#[cfg(feature = "std")] pub type BareCryptoStorePtr = std::sync::Arc>; + +externalities::decl_extension! { + /// The keystore extension to register/retrieve from the externalities. + pub struct KeystoreExt(BareCryptoStorePtr); +} + +/// Code execution engine. +pub trait CodeExecutor: Sized + Send + Sync { + /// Externalities error type. + type Error: Display + Debug + Send + 'static; + + /// Call a given method in the runtime. Returns a tuple of the result (either the output data + /// or an execution error) together with a `bool`, which is true if native execution was used. + fn call< + E: Externalities, + R: codec::Codec + PartialEq, + NC: FnOnce() -> Result + UnwindSafe, + >( + &self, + ext: &mut E, + method: &str, + data: &[u8], + use_native: bool, + native_call: Option, + ) -> (Result, Self::Error>, bool); +} diff --git a/core/primitives/storage/Cargo.toml b/core/primitives/storage/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..1e5d7ee8b4548ff8641c75e220756f8d499287a2 --- /dev/null +++ b/core/primitives/storage/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "substrate-primitives-storage" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +description = "Storage related primitives" + +[dependencies] +rstd = { package = "sr-std", path = "../../sr-std", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +impl-serde = { version = "0.2.3", optional = true } +substrate-debug-derive = { version = "2.0.0", path = "../debug-derive" } + +[features] +default = [ "std" ] +std = [ "rstd/std", "serde", "impl-serde" ] diff --git a/core/primitives/storage/src/lib.rs b/core/primitives/storage/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..dcdc223994e269af7903df68e13830658e4d5e71 --- /dev/null +++ b/core/primitives/storage/src/lib.rs @@ -0,0 +1,150 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitive types for storage related stuff. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use substrate_debug_derive::RuntimeDebug; + +use rstd::{vec::Vec, borrow::Cow}; + +/// Storage key. +#[derive(PartialEq, Eq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] +pub struct StorageKey( + #[cfg_attr(feature = "std", serde(with="impl_serde::serialize"))] + pub Vec, +); + +/// Storage data associated to a [`StorageKey`]. +#[derive(PartialEq, Eq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] +pub struct StorageData( + #[cfg_attr(feature = "std", serde(with="impl_serde::serialize"))] + pub Vec, +); + +/// Storage change set +#[derive(RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, PartialEq, Eq))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +pub struct StorageChangeSet { + /// Block hash + pub block: Hash, + /// A list of changes + pub changes: Vec<(StorageKey, Option)>, +} + +/// List of all well known keys and prefixes in storage. +pub mod well_known_keys { + /// Wasm code of the runtime. + /// + /// Stored as a raw byte vector. Required by substrate. + pub const CODE: &'static [u8] = b":code"; + + /// Number of wasm linear memory pages required for execution of the runtime. + /// + /// The type of this value is encoded `u64`. + pub const HEAP_PAGES: &'static [u8] = b":heappages"; + + /// Current extrinsic index (u32) is stored under this key. + pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index"; + + /// Changes trie configuration is stored under this key. + pub const CHANGES_TRIE_CONFIG: &'static [u8] = b":changes_trie"; + + /// Prefix of child storage keys. + pub const CHILD_STORAGE_KEY_PREFIX: &'static [u8] = b":child_storage:"; + + /// Whether a key is a child storage key. + /// + /// This is convenience function which basically checks if the given `key` starts + /// with `CHILD_STORAGE_KEY_PREFIX` and doesn't do anything apart from that. + pub fn is_child_storage_key(key: &[u8]) -> bool { + // Other code might depend on this, so be careful changing this. + key.starts_with(CHILD_STORAGE_KEY_PREFIX) + } + + /// Determine whether a child trie key is valid. + /// + /// For now, the only valid child trie keys are those starting with `:child_storage:default:`. + /// + /// `child_trie_root` and `child_delta_trie_root` can panic if invalid value is provided to them. + pub fn is_child_trie_key_valid(storage_key: &[u8]) -> bool { + let has_right_prefix = storage_key.starts_with(b":child_storage:default:"); + if has_right_prefix { + // This is an attempt to catch a change of `is_child_storage_key`, which + // just checks if the key has prefix `:child_storage:` at the moment of writing. + debug_assert!( + is_child_storage_key(&storage_key), + "`is_child_trie_key_valid` is a subset of `is_child_storage_key`", + ); + } + has_right_prefix + } +} + +/// A wrapper around a child storage key. +/// +/// This wrapper ensures that the child storage key is correct and properly used. It is +/// impossible to create an instance of this struct without providing a correct `storage_key`. +pub struct ChildStorageKey<'a> { + storage_key: Cow<'a, [u8]>, +} + +impl<'a> ChildStorageKey<'a> { + /// Create new instance of `Self`. + fn new(storage_key: Cow<'a, [u8]>) -> Option { + if well_known_keys::is_child_trie_key_valid(&storage_key) { + Some(ChildStorageKey { storage_key }) + } else { + None + } + } + + /// Create a new `ChildStorageKey` from a vector. + /// + /// `storage_key` need to start with `:child_storage:default:` + /// See `is_child_trie_key_valid` for more details. + pub fn from_vec(key: Vec) -> Option { + Self::new(Cow::Owned(key)) + } + + /// Create a new `ChildStorageKey` from a slice. + /// + /// `storage_key` need to start with `:child_storage:default:` + /// See `is_child_trie_key_valid` for more details. + pub fn from_slice(key: &'a [u8]) -> Option { + Self::new(Cow::Borrowed(key)) + } + + /// Get access to the byte representation of the storage key. + /// + /// This key is guaranteed to be correct. + pub fn as_ref(&self) -> &[u8] { + &*self.storage_key + } + + /// Destruct this instance into an owned vector that represents the storage key. + /// + /// This key is guaranteed to be correct. + pub fn into_owned(self) -> Vec { + self.storage_key.into_owned() + } +} diff --git a/core/rpc-servers/Cargo.toml b/core/rpc-servers/Cargo.toml index 64a494f65ffe74b870720c2b0feb02de6e0ff46d..8fdf31db328d2b98789630c120dd1aab0f74c220 100644 --- a/core/rpc-servers/Cargo.toml +++ b/core/rpc-servers/Cargo.toml @@ -5,12 +5,13 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -pubsub = { package = "jsonrpc-pubsub", version = "12.0.0" } -log = "0.4" -serde = "1.0" -substrate-rpc = { path = "../rpc" } +jsonrpc-core = "14.0.3" +pubsub = { package = "jsonrpc-pubsub", version = "14.0.3" } +log = "0.4.8" +serde = "1.0.101" +serde_json = "1.0.41" sr-primitives = { path = "../sr-primitives" } [target.'cfg(not(target_os = "unknown"))'.dependencies] -http = { package = "jsonrpc-http-server", version = "12.0.0" } -ws = { package = "jsonrpc-ws-server", version = "12.0.0" } +http = { package = "jsonrpc-http-server", version = "14.0.3" } +ws = { package = "jsonrpc-ws-server", version = "14.0.3" } diff --git a/core/rpc-servers/src/lib.rs b/core/rpc-servers/src/lib.rs index a33f726747149414ebc8e90dd59e0f04791e332c..8d39386f93c4ae9c79c0504beb7397914a3477c8 100644 --- a/core/rpc-servers/src/lib.rs +++ b/core/rpc-servers/src/lib.rs @@ -16,13 +16,12 @@ //! Substrate RPC servers. -#[warn(missing_docs)] - -pub use substrate_rpc as apis; +#![warn(missing_docs)] use std::io; +use jsonrpc_core::IoHandlerExtension; use log::error; -use sr_primitives::{traits::{Block as BlockT, NumberFor}, generic::SignedBlock}; +use pubsub::PubSubMetadata; /// Maximal payload accepted by RPC servers. const MAX_PAYLOAD: usize = 15 * 1024 * 1024; @@ -30,30 +29,30 @@ const MAX_PAYLOAD: usize = 15 * 1024 * 1024; /// Default maximum number of connections for WS RPC servers. const WS_MAX_CONNECTIONS: usize = 100; -pub type Metadata = apis::metadata::Metadata; -pub type RpcHandler = pubsub::PubSubHandler; +/// The RPC IoHandler containing all requested APIs. +pub type RpcHandler = pubsub::PubSubHandler; pub use self::inner::*; /// Construct rpc `IoHandler` -pub fn rpc_handler( - state: S, - chain: C, - author: A, - system: Y, -) -> RpcHandler where - Block: BlockT + 'static, - ExHash: Send + Sync + 'static + sr_primitives::Serialize + sr_primitives::DeserializeOwned, - S: apis::state::StateApi, - C: apis::chain::ChainApi, Block::Hash, Block::Header, SignedBlock, Metadata=Metadata>, - A: apis::author::AuthorApi, - Y: apis::system::SystemApi>, -{ +pub fn rpc_handler( + extension: impl IoHandlerExtension +) -> RpcHandler { let mut io = pubsub::PubSubHandler::default(); - io.extend_with(state.to_delegate()); - io.extend_with(chain.to_delegate()); - io.extend_with(author.to_delegate()); - io.extend_with(system.to_delegate()); + extension.augment(&mut io); + + // add an endpoint to list all available methods. + let mut methods = io.iter().map(|x| x.0.clone()).collect::>(); + io.add_method("rpc_methods", { + methods.sort(); + let methods = serde_json::to_value(&methods) + .expect("Serialization of Vec is infallible; qed"); + + move |_| Ok(serde_json::json!({ + "version": 1, + "methods": methods.clone(), + })) + }); io } @@ -61,16 +60,18 @@ pub fn rpc_handler( mod inner { use super::*; + /// Type alias for http server pub type HttpServer = http::Server; + /// Type alias for ws server pub type WsServer = ws::Server; /// Start HTTP server listening on given address. /// /// **Note**: Only available if `not(target_os = "unknown")`. - pub fn start_http( + pub fn start_http( addr: &std::net::SocketAddr, cors: Option<&Vec>, - io: RpcHandler, + io: RpcHandler, ) -> io::Result { http::ServerBuilder::new(io) .threads(4) @@ -89,13 +90,13 @@ mod inner { /// Start WS server listening on given address. /// /// **Note**: Only available if `not(target_os = "unknown")`. - pub fn start_ws( + pub fn start_ws>> ( addr: &std::net::SocketAddr, max_connections: Option, cors: Option<&Vec>, - io: RpcHandler, + io: RpcHandler, ) -> io::Result { - ws::ServerBuilder::with_meta_extractor(io, |context: &ws::RequestContext| Metadata::new(context.sender())) + ws::ServerBuilder::with_meta_extractor(io, |context: &ws::RequestContext| context.sender().into()) .max_payload(MAX_PAYLOAD) .max_connections(max_connections.unwrap_or(WS_MAX_CONNECTIONS)) .allowed_origins(map_cors(cors)) diff --git a/core/rpc/Cargo.toml b/core/rpc/Cargo.toml index 957fe5be0b32703b4f1cb84003631fbb7eef8b6e..109db34240ccdc5d2e853041bf6aceb3e0172c3c 100644 --- a/core/rpc/Cargo.toml +++ b/core/rpc/Cargo.toml @@ -5,33 +5,31 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -derive_more = "0.14.0" -futures = "0.1" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.17", features = ["compat"] } -jsonrpc-core = "12.0.0" -jsonrpc-core-client = "12.0.0" -jsonrpc-pubsub = "12.0.0" -jsonrpc-derive = "12.0.0" -log = "0.4" -parking_lot = "0.9.0" -codec = { package = "parity-scale-codec", version = "1.0.0" } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +api = { package = "substrate-rpc-api", path = "./api" } client = { package = "substrate-client", path = "../client" } -substrate-executor = { path = "../executor" } -network = { package = "substrate-network", path = "../network" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } +jsonrpc-pubsub = "14.0.3" +log = "0.4.8" primitives = { package = "substrate-primitives", path = "../primitives" } +rpc = { package = "jsonrpc-core", version = "14.0.3" } +runtime_version = { package = "sr-version", path = "../sr-version" } +serde_json = "1.0.41" session = { package = "substrate-session", path = "../session" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } -transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" } sr-primitives = { path = "../sr-primitives" } -runtime_version = { package = "sr-version", path = "../sr-version" } +rpc-primitives = { package = "substrate-rpc-primitives", path = "primitives" } +state_machine = { package = "substrate-state-machine", path = "../state-machine" } +substrate-executor = { path = "../executor" } substrate-keystore = { path = "../keystore" } +transaction_pool = { package = "substrate-transaction-pool", path = "../transaction-pool" } +hash-db = { version = "0.15.2", default-features = false } +parking_lot = { version = "0.9.0" } [dev-dependencies] -assert_matches = "1.1" -futures = "0.1.17" +assert_matches = "1.3.0" +futures = "0.1.29" +network = { package = "substrate-network", path = "../network" } +rustc-hex = "2.0.1" sr-io = { path = "../sr-io" } test-client = { package = "substrate-test-runtime-client", path = "../test-runtime/client" } -rustc-hex = "2.0" -tokio = "0.1.17" +tokio = "0.1.22" diff --git a/core/rpc/api/Cargo.toml b/core/rpc/api/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..5fb0e4cbaec7158419adb33d6b9cd9d08a335aa9 --- /dev/null +++ b/core/rpc/api/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "substrate-rpc-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0" } +derive_more = "0.15.0" +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +jsonrpc-pubsub = "14.0.3" +log = "0.4.8" +parking_lot = "0.9.0" +primitives = { package = "substrate-primitives", path = "../../primitives" } +runtime_version = { package = "sr-version", path = "../../sr-version" } +serde = { version = "1.0.101", features = ["derive"] } +serde_json = "1.0.41" +txpool = { package = "substrate-transaction-graph", path = "../../transaction-pool/graph" } +rpc-primitives = { package = "substrate-rpc-primitives", path = "../../rpc/primitives" } diff --git a/core/rpc/src/author/error.rs b/core/rpc/api/src/author/error.rs similarity index 83% rename from core/rpc/src/author/error.rs rename to core/rpc/api/src/author/error.rs index 2fcc8c780dfdb59dac5b69d49a11b68852601ee5..8e4f8877682b37cc036c06b41a453ae6cb08960d 100644 --- a/core/rpc/src/author/error.rs +++ b/core/rpc/api/src/author/error.rs @@ -16,20 +16,23 @@ //! Authoring RPC module errors. -use client; -use transaction_pool::txpool; -use crate::rpc; use crate::errors; +use jsonrpc_core as rpc; /// Author RPC Result type. pub type Result = std::result::Result; +/// Author RPC future Result type. +pub type FutureResult = Box + Send>; + /// Author RPC errors. #[derive(Debug, derive_more::Display, derive_more::From)] pub enum Error { /// Client error. - Client(client::error::Error), + #[display(fmt="Client error: {}", _0)] + Client(Box), /// Transaction pool error, + #[display(fmt="Transaction pool error: {}", _0)] Pool(txpool::error::Error), /// Verification error #[display(fmt="Extrinsic verification error: {}", _0)] @@ -54,7 +57,7 @@ pub enum Error { impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - Error::Client(ref err) => Some(err), + Error::Client(ref err) => Some(&**err), Error::Pool(ref err) => Some(err), Error::Verification(ref err) => Some(&**err), _ => None, @@ -83,6 +86,8 @@ const POOL_TOO_LOW_PRIORITY: i64 = POOL_INVALID_TX + 4; const POOL_CYCLE_DETECTED: i64 = POOL_INVALID_TX + 5; /// The transaction was not included to the pool because of the limits. const POOL_IMMEDIATELY_DROPPED: i64 = POOL_INVALID_TX + 6; +/// The key type crypto is not known. +const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7; impl From for rpc::Error { fn from(e: Error) -> Self { @@ -99,15 +104,15 @@ impl From for rpc::Error { message: format!("Verification Error: {}", e).into(), data: Some(format!("{:?}", e).into()), }, - Error::Pool(PoolError::InvalidTransaction(code)) => rpc::Error { + Error::Pool(PoolError::InvalidTransaction(e)) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), message: "Invalid Transaction".into(), - data: Some(code.into()), + data: serde_json::to_value(e).ok(), }, - Error::Pool(PoolError::UnknownTransactionValidity(code)) => rpc::Error { + Error::Pool(PoolError::UnknownTransaction(e)) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), message: "Unknown Transaction Validity".into(), - data: Some(code.into()), + data: serde_json::to_value(e).ok(), }, Error::Pool(PoolError::TemporarilyBanned) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED), @@ -131,9 +136,17 @@ impl From for rpc::Error { }, Error::Pool(PoolError::ImmediatelyDropped) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_IMMEDIATELY_DROPPED), - message: "Immediately Dropped" .into(), + message: "Immediately Dropped".into(), data: Some("The transaction couldn't enter the pool because of the limit".into()), }, + Error::UnsupportedKeyType => rpc::Error { + code: rpc::ErrorCode::ServerError(UNSUPPORTED_KEY_TYPE), + message: "Unknown key type crypto" .into(), + data: Some( + "The crypto for the given key type is unknown, please add the public key to the \ + request to insert the key successfully.".into() + ), + }, e => errors::internal(e), } } diff --git a/core/rpc/src/author/hash.rs b/core/rpc/api/src/author/hash.rs similarity index 100% rename from core/rpc/src/author/hash.rs rename to core/rpc/api/src/author/hash.rs diff --git a/core/rpc/api/src/author/mod.rs b/core/rpc/api/src/author/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..4ea96cb3c6122be47da5dea671b78249ebb40b36 --- /dev/null +++ b/core/rpc/api/src/author/mod.rs @@ -0,0 +1,86 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate block-author/full-node API. + +pub mod error; +pub mod hash; + +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use primitives::{ + Bytes +}; +use self::error::{FutureResult, Result}; +use txpool::watcher::Status; + +pub use self::gen_client::Client as AuthorClient; + +/// Substrate authoring RPC API +#[rpc] +pub trait AuthorApi { + /// RPC metadata + type Metadata; + + /// Submit hex-encoded extrinsic for inclusion in block. + #[rpc(name = "author_submitExtrinsic")] + fn submit_extrinsic(&self, extrinsic: Bytes) -> FutureResult; + + /// Insert a key into the keystore. + #[rpc(name = "author_insertKey")] + fn insert_key(&self, + key_type: String, + suri: String, + public: Bytes, + ) -> Result<()>; + + /// Generate new session keys and returns the corresponding public keys. + #[rpc(name = "author_rotateKeys")] + fn rotate_keys(&self) -> Result; + + /// Returns all pending extrinsics, potentially grouped by sender. + #[rpc(name = "author_pendingExtrinsics")] + fn pending_extrinsics(&self) -> Result>; + + /// Remove given extrinsic from the pool and temporarily ban it to prevent reimporting. + #[rpc(name = "author_removeExtrinsic")] + fn remove_extrinsic(&self, + bytes_or_hash: Vec> + ) -> Result>; + + /// Submit an extrinsic to watch. + #[pubsub( + subscription = "author_extrinsicUpdate", + subscribe, + name = "author_submitAndWatchExtrinsic" + )] + fn watch_extrinsic(&self, + metadata: Self::Metadata, + subscriber: Subscriber>, + bytes: Bytes + ); + + /// Unsubscribe from extrinsic watching. + #[pubsub( + subscription = "author_extrinsicUpdate", + unsubscribe, + name = "author_unwatchExtrinsic" + )] + fn unwatch_extrinsic(&self, + metadata: Option, + id: SubscriptionId + ) -> Result; +} diff --git a/core/rpc/src/chain/error.rs b/core/rpc/api/src/chain/error.rs similarity index 84% rename from core/rpc/src/chain/error.rs rename to core/rpc/api/src/chain/error.rs index ad63af9add0510731df2083916551555b4df105a..454c0887abf820c284ce2eaa74da852cecb082b0 100644 --- a/core/rpc/src/chain/error.rs +++ b/core/rpc/api/src/chain/error.rs @@ -17,18 +17,21 @@ //! Error helpers for Chain RPC module. -use client; -use crate::rpc; use crate::errors; +use jsonrpc_core as rpc; /// Chain RPC Result type. pub type Result = std::result::Result; +/// Chain RPC future Result type. +pub type FutureResult = Box + Send>; + /// Chain RPC errors. #[derive(Debug, derive_more::Display, derive_more::From)] pub enum Error { /// Client error. - Client(client::error::Error), + #[display(fmt="Client error: {}", _0)] + Client(Box), /// Other error type. Other(String), } @@ -36,7 +39,7 @@ pub enum Error { impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - Error::Client(ref err) => Some(err), + Error::Client(ref err) => Some(&**err), _ => None, } } diff --git a/core/rpc/api/src/chain/mod.rs b/core/rpc/api/src/chain/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..73f4388236cc8bec6e58c61173f864be1ceaa944 --- /dev/null +++ b/core/rpc/api/src/chain/mod.rs @@ -0,0 +1,89 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate blockchain API. + +pub mod error; + +use jsonrpc_core::Result as RpcResult; +use jsonrpc_core::futures::Future; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use rpc_primitives::number; +use self::error::{FutureResult, Result}; + +pub use self::gen_client::Client as ChainClient; + +/// Substrate blockchain API +#[rpc] +pub trait ChainApi { + /// RPC metadata + type Metadata; + + /// Get header of a relay chain block. + #[rpc(name = "chain_getHeader")] + fn header(&self, hash: Option) -> FutureResult>; + + /// Get header and body of a relay chain block. + #[rpc(name = "chain_getBlock")] + fn block(&self, hash: Option) -> FutureResult>; + + /// Get hash of the n-th block in the canon chain. + /// + /// By default returns latest block hash. + #[rpc(name = "chain_getBlockHash", alias("chain_getHead"))] + fn block_hash(&self, hash: Option>) -> Result>; + + /// Get hash of the last finalized block in the canon chain. + #[rpc(name = "chain_getFinalizedHead", alias("chain_getFinalisedHead"))] + fn finalized_head(&self) -> Result; + + /// New head subscription + #[pubsub( + subscription = "chain_newHead", + subscribe, + name = "chain_subscribeNewHeads", + alias("subscribe_newHead", "chain_subscribeNewHead") + )] + fn subscribe_new_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); + + /// Unsubscribe from new head subscription. + #[pubsub( + subscription = "chain_newHead", + unsubscribe, + name = "chain_unsubscribeNewHeads", + alias("unsubscribe_newHead", "chain_unsubscribeNewHead") + )] + fn unsubscribe_new_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + + /// New head subscription + #[pubsub( + subscription = "chain_finalizedHead", + subscribe, + name = "chain_subscribeFinalizedHeads", + alias("chain_subscribeFinalisedHeads") + )] + fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); + + /// Unsubscribe from new head subscription. + #[pubsub( + subscription = "chain_finalizedHead", + unsubscribe, + name = "chain_unsubscribeFinalizedHeads", + alias("chain_unsubscribeFinalisedHeads") + )] + fn unsubscribe_finalized_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; +} diff --git a/core/rpc/src/errors.rs b/core/rpc/api/src/errors.rs similarity index 86% rename from core/rpc/src/errors.rs rename to core/rpc/api/src/errors.rs index da910de76215ae18339f942a40394b5cdbae7404..984a1cd712762c57957977ade8427604bf27f0ed 100644 --- a/core/rpc/src/errors.rs +++ b/core/rpc/api/src/errors.rs @@ -14,13 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use crate::rpc; use log::warn; -pub fn internal(e: E) -> rpc::Error { +pub fn internal(e: E) -> jsonrpc_core::Error { warn!("Unknown error: {:?}", e); - rpc::Error { - code: rpc::ErrorCode::InternalError, + jsonrpc_core::Error { + code: jsonrpc_core::ErrorCode::InternalError, message: "Unknown error occured".into(), data: Some(format!("{:?}", e).into()), } diff --git a/core/rpc/src/helpers.rs b/core/rpc/api/src/helpers.rs similarity index 80% rename from core/rpc/src/helpers.rs rename to core/rpc/api/src/helpers.rs index 2c69ead76caae134688da85c6a86e1551a3c7622..d500a50a869b49dac52745643c8240f0d2145c55 100644 --- a/core/rpc/src/helpers.rs +++ b/core/rpc/api/src/helpers.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use futures::prelude::*; +use jsonrpc_core::futures::prelude::*; use futures03::{channel::oneshot, compat::Compat}; /// Wraps around `oneshot::Receiver` and adjusts the error type to produce an internal error if the @@ -29,13 +29,3 @@ impl Future for Receiver { self.0.poll().map_err(|_| jsonrpc_core::Error::internal_error()) } } - -/// Unwraps the trailing parameter or falls back with the closure result. -pub fn unwrap_or_else(or_else: F, optional: Option) -> Result where - F: FnOnce() -> Result, -{ - match optional.into() { - None => or_else(), - Some(x) => Ok(x), - } -} diff --git a/core/rpc/api/src/lib.rs b/core/rpc/api/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..12db07633dcc42c3dd3b0e3bbdae279efe712c7f --- /dev/null +++ b/core/rpc/api/src/lib.rs @@ -0,0 +1,34 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate RPC interfaces. +//! +//! A collection of RPC methods and subscriptions supported by all substrate clients. + +#![warn(missing_docs)] + +mod errors; +mod helpers; +mod subscriptions; + +pub use jsonrpc_core::IoHandlerExtension as RpcExtension; +pub use subscriptions::{Subscriptions, TaskExecutor}; +pub use helpers::Receiver; + +pub mod author; +pub mod chain; +pub mod state; +pub mod system; diff --git a/core/rpc/src/state/error.rs b/core/rpc/api/src/state/error.rs similarity index 86% rename from core/rpc/src/state/error.rs rename to core/rpc/api/src/state/error.rs index 4b9d30b36b2043ef130492db91eb74004d12aba5..553a06e896f3d465c8d2d36872709a0d2f532c8a 100644 --- a/core/rpc/src/state/error.rs +++ b/core/rpc/api/src/state/error.rs @@ -16,18 +16,21 @@ //! State RPC errors. -use client; -use crate::rpc; use crate::errors; +use jsonrpc_core as rpc; /// State RPC Result type. pub type Result = std::result::Result; +/// State RPC future Result type. +pub type FutureResult = Box + Send>; + /// State RPC errors. #[derive(Debug, derive_more::Display, derive_more::From)] pub enum Error { /// Client error. - Client(client::error::Error), + #[display(fmt="Client error: {}", _0)] + Client(Box), /// Provided block range couldn't be resolved to a list of blocks. #[display(fmt = "Cannot resolve a block range ['{:?}' ... '{:?}]. {}", from, to, details)] InvalidBlockRange { @@ -43,7 +46,7 @@ pub enum Error { impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - Error::Client(ref err) => Some(err), + Error::Client(ref err) => Some(&**err), _ => None, } } diff --git a/core/rpc/api/src/state/mod.rs b/core/rpc/api/src/state/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..0d06092ca1659b988584536cf5af56ae24ab09ee --- /dev/null +++ b/core/rpc/api/src/state/mod.rs @@ -0,0 +1,143 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate state API. + +pub mod error; + +use jsonrpc_core::Result as RpcResult; +use jsonrpc_core::futures::Future; +use jsonrpc_derive::rpc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use primitives::Bytes; +use primitives::storage::{StorageKey, StorageData, StorageChangeSet}; +use runtime_version::RuntimeVersion; +use self::error::FutureResult; + +pub use self::gen_client::Client as StateClient; + +/// Substrate state API +#[rpc] +pub trait StateApi { + /// RPC Metadata + type Metadata; + + /// Call a contract at a block's state. + #[rpc(name = "state_call", alias("state_callAt"))] + fn call(&self, name: String, bytes: Bytes, hash: Option) -> FutureResult; + + /// Returns the keys with prefix, leave empty to get all the keys + #[rpc(name = "state_getKeys")] + fn storage_keys(&self, prefix: StorageKey, hash: Option) -> FutureResult>; + + /// Returns a storage entry at a specific block's state. + #[rpc(name = "state_getStorage", alias("state_getStorageAt"))] + fn storage(&self, key: StorageKey, hash: Option) -> FutureResult>; + + /// Returns the hash of a storage entry at a block's state. + #[rpc(name = "state_getStorageHash", alias("state_getStorageHashAt"))] + fn storage_hash(&self, key: StorageKey, hash: Option) -> FutureResult>; + + /// Returns the size of a storage entry at a block's state. + #[rpc(name = "state_getStorageSize", alias("state_getStorageSizeAt"))] + fn storage_size(&self, key: StorageKey, hash: Option) -> FutureResult>; + + /// Returns the keys with prefix from a child storage, leave empty to get all the keys + #[rpc(name = "state_getChildKeys")] + fn child_storage_keys( + &self, + child_storage_key: StorageKey, + prefix: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns a child storage entry at a specific block's state. + #[rpc(name = "state_getChildStorage")] + fn child_storage( + &self, + child_storage_key: StorageKey, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the hash of a child storage entry at a block's state. + #[rpc(name = "state_getChildStorageHash")] + fn child_storage_hash( + &self, + child_storage_key: StorageKey, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the size of a child storage entry at a block's state. + #[rpc(name = "state_getChildStorageSize")] + fn child_storage_size( + &self, + child_storage_key: StorageKey, + key: StorageKey, + hash: Option + ) -> FutureResult>; + + /// Returns the runtime metadata as an opaque blob. + #[rpc(name = "state_getMetadata")] + fn metadata(&self, hash: Option) -> FutureResult; + + /// Get the runtime version. + #[rpc(name = "state_getRuntimeVersion", alias("chain_getRuntimeVersion"))] + fn runtime_version(&self, hash: Option) -> FutureResult; + + /// Query historical storage entries (by key) starting from a block given as the second parameter. + /// + /// NOTE This first returned result contains the initial state of storage for all keys. + /// Subsequent values in the vector represent changes to the previous state (diffs). + #[rpc(name = "state_queryStorage")] + fn query_storage( + &self, + keys: Vec, + block: Hash, + hash: Option + ) -> FutureResult>>; + + /// New runtime version subscription + #[pubsub( + subscription = "state_runtimeVersion", + subscribe, + name = "state_subscribeRuntimeVersion", + alias("chain_subscribeRuntimeVersion") + )] + fn subscribe_runtime_version(&self, metadata: Self::Metadata, subscriber: Subscriber); + + /// Unsubscribe from runtime version subscription + #[pubsub( + subscription = "state_runtimeVersion", + unsubscribe, + name = "state_unsubscribeRuntimeVersion", + alias("chain_unsubscribeRuntimeVersion") + )] + fn unsubscribe_runtime_version(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + + /// New storage subscription + #[pubsub(subscription = "state_storage", subscribe, name = "state_subscribeStorage")] + fn subscribe_storage( + &self, metadata: Self::Metadata, subscriber: Subscriber>, keys: Option> + ); + + /// Unsubscribe from storage subscription + #[pubsub(subscription = "state_storage", unsubscribe, name = "state_unsubscribeStorage")] + fn unsubscribe_storage( + &self, metadata: Option, id: SubscriptionId + ) -> RpcResult; +} diff --git a/core/rpc/src/subscriptions.rs b/core/rpc/api/src/subscriptions.rs similarity index 78% rename from core/rpc/src/subscriptions.rs rename to core/rpc/api/src/subscriptions.rs index 77e1d958f683fed3f639f8093d048bd946984677..d5ca74fa60bc7e441b6f2645725b6babbba64528 100644 --- a/core/rpc/src/subscriptions.rs +++ b/core/rpc/api/src/subscriptions.rs @@ -20,11 +20,14 @@ use std::sync::{Arc, atomic::{self, AtomicUsize}}; use log::{error, warn}; use jsonrpc_pubsub::{SubscriptionId, typed::{Sink, Subscriber}}; use parking_lot::Mutex; -use crate::rpc::futures::sync::oneshot; -use crate::rpc::futures::{Future, future}; +use jsonrpc_core::futures::sync::oneshot; +use jsonrpc_core::futures::{Future, future}; type Id = u64; +/// Alias for a an implementation of `futures::future::Executor`. +pub type TaskExecutor = Arc + Send>> + Send + Sync>; + /// Generate unique ids for subscriptions. #[derive(Clone, Debug)] pub struct IdProvider { @@ -53,12 +56,12 @@ impl IdProvider { pub struct Subscriptions { next_id: IdProvider, active_subscriptions: Arc>>>, - executor: Arc + Send>> + Send + Sync>, + executor: TaskExecutor, } impl Subscriptions { /// Creates new `Subscriptions` object. - pub fn new(executor: Arc + Send>> + Send + Sync>) -> Self { + pub fn new(executor: TaskExecutor) -> Self { Subscriptions { next_id: Default::default(), active_subscriptions: Default::default(), @@ -66,18 +69,26 @@ impl Subscriptions { } } + /// Borrows the internal task executor. + /// + /// This can be used to spawn additional tasks on the underyling event loop. + pub fn executor(&self) -> &TaskExecutor { + &self.executor + } + /// Creates new subscription for given subscriber. /// /// Second parameter is a function that converts Subscriber sink into a future. - /// This future will be driven to completion bu underlying event loop + /// This future will be driven to completion by the underlying event loop /// or will be cancelled in case #cancel is invoked. - pub fn add(&self, subscriber: Subscriber, into_future: G) where + pub fn add(&self, subscriber: Subscriber, into_future: G) -> SubscriptionId where G: FnOnce(Sink) -> R, R: future::IntoFuture, F: future::Future + Send + 'static, { let id = self.next_id.next_id(); - if let Ok(sink) = subscriber.assign_id(id.into()) { + let subscription_id: SubscriptionId = id.into(); + if let Ok(sink) = subscriber.assign_id(subscription_id.clone()) { let (tx, rx) = oneshot::channel(); let future = into_future(sink) .into_future() @@ -89,6 +100,8 @@ impl Subscriptions { error!("Failed to spawn RPC subscription task"); } } + + subscription_id } /// Cancel subscription. diff --git a/core/rpc/src/system/error.rs b/core/rpc/api/src/system/error.rs similarity index 98% rename from core/rpc/src/system/error.rs rename to core/rpc/api/src/system/error.rs index bdd4cbe667e59a084d3b83f41b62e88f1518d5cd..32b694e3ac0088611bcd85edaae1e732cda650b9 100644 --- a/core/rpc/src/system/error.rs +++ b/core/rpc/api/src/system/error.rs @@ -16,8 +16,8 @@ //! System RPC module errors. -use crate::rpc; use crate::system::helpers::Health; +use jsonrpc_core as rpc; /// System RPC Result type. pub type Result = std::result::Result; diff --git a/core/rpc/src/system/helpers.rs b/core/rpc/api/src/system/helpers.rs similarity index 90% rename from core/rpc/src/system/helpers.rs rename to core/rpc/api/src/system/helpers.rs index 00e2ba9f408b7658ccb45a10d62642bbfed1209c..10319d57b693b0fb0e7847cb6b024c122b60b930 100644 --- a/core/rpc/src/system/helpers.rs +++ b/core/rpc/api/src/system/helpers.rs @@ -50,6 +50,14 @@ pub struct Health { pub should_have_peers: bool, } +impl fmt::Display for Health { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { + "syncing" + } else { "idle" }) + } +} + /// Network Peer information #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -66,12 +74,17 @@ pub struct PeerInfo { pub best_number: Number, } -impl fmt::Display for Health { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { - "syncing" - } else { "idle" }) - } +/// The role the node is running as +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub enum NodeRole { + /// The node is a full node + Full, + /// The node is a light client + LightClient, + /// The node is an authority + Authority, + /// An unknown role with a bit number + UnknownRole(u8) } #[cfg(test)] diff --git a/core/rpc/api/src/system/mod.rs b/core/rpc/api/src/system/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..f59fd84c7c027bc891cd664e5be386c44dbe2885 --- /dev/null +++ b/core/rpc/api/src/system/mod.rs @@ -0,0 +1,71 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate system API. + +pub mod error; +pub mod helpers; + +use crate::helpers::Receiver; +use jsonrpc_derive::rpc; + +use self::error::Result; + +pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; +pub use self::gen_client::Client as SystemClient; + +/// Substrate system RPC API +#[rpc] +pub trait SystemApi { + /// Get the node's implementation name. Plain old string. + #[rpc(name = "system_name")] + fn system_name(&self) -> Result; + + /// Get the node implementation's version. Should be a semver string. + #[rpc(name = "system_version")] + fn system_version(&self) -> Result; + + /// Get the chain's type. Given as a string identifier. + #[rpc(name = "system_chain")] + fn system_chain(&self) -> Result; + + /// Get a custom set of properties as a JSON object, defined in the chain spec. + #[rpc(name = "system_properties")] + fn system_properties(&self) -> Result; + + /// Return health status of the node. + /// + /// Node is considered healthy if it is: + /// - connected to some peers (unless running in dev mode) + /// - not performing a major sync + #[rpc(name = "system_health", returns = "Health")] + fn system_health(&self) -> Receiver; + + /// Returns currently connected peers + #[rpc(name = "system_peers", returns = "Vec>")] + fn system_peers(&self) -> Receiver>>; + + /// Returns current state of the network. + /// + /// **Warning**: This API is not stable. + // TODO: make this stable and move structs https://github.com/paritytech/substrate/issues/1890 + #[rpc(name = "system_networkState", returns = "jsonrpc_core::Value")] + fn system_network_state(&self) -> Receiver; + + /// Returns the roles the node is running as. + #[rpc(name = "system_nodeRoles", returns = "Vec")] + fn system_node_roles(&self) -> Receiver>; +} diff --git a/core/rpc/primitives/Cargo.toml b/core/rpc/primitives/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4044428112780949b6c1d469406b89b87d575c34 --- /dev/null +++ b/core/rpc/primitives/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "substrate-rpc-primitives" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", features = ["derive"] } +primitives = { package = "substrate-primitives", path = "../../primitives" } diff --git a/core/rpc/primitives/src/lib.rs b/core/rpc/primitives/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..667b1b1b4b4f9619b2a3823a9dca0cac92f73c61 --- /dev/null +++ b/core/rpc/primitives/src/lib.rs @@ -0,0 +1,21 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Substrate RPC primitives and utilities. + +#![warn(missing_docs)] + +pub mod number; diff --git a/core/rpc/src/chain/number.rs b/core/rpc/primitives/src/number.rs similarity index 98% rename from core/rpc/src/chain/number.rs rename to core/rpc/primitives/src/number.rs index df796d5e6d9911c2f952dc344cd69b23eef0a3b9..0637e3decf39645b3561a61d7d8881451ce142a3 100644 --- a/core/rpc/src/chain/number.rs +++ b/core/rpc/primitives/src/number.rs @@ -61,14 +61,12 @@ impl + From + Debug + PartialOrd> NumberOrHex } } -#[cfg(test)] impl From for NumberOrHex { fn from(n: u64) -> Self { NumberOrHex::Number(n) } } -#[cfg(test)] impl From for NumberOrHex { fn from(n: U256) -> Self { NumberOrHex::Hex(n) diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs index d797e87da57760dfff6bc5ba18b70f7a362c2cb8..82122dcf3d21f90041b890b90fc43ed2dd984a75 100644 --- a/core/rpc/src/author/mod.rs +++ b/core/rpc/src/author/mod.rs @@ -16,27 +16,24 @@ //! Substrate block-author/full-node API. -pub mod error; -pub mod hash; - #[cfg(test)] mod tests; use std::{sync::Arc, convert::TryInto}; +use futures03::future::{FutureExt, TryFutureExt}; +use log::warn; use client::{self, Client}; -use crate::rpc::futures::{Sink, Stream, Future}; -use crate::subscriptions::Subscriptions; -use jsonrpc_derive::rpc; +use rpc::futures::{ + Sink, Future, + future::result, +}; +use futures03::{StreamExt as _, compat::Compat, future::ready}; +use api::Subscriptions; use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use log::warn; use codec::{Encode, Decode}; -use primitives::{ - Bytes, Blake2Hasher, H256, ed25519, sr25519, crypto::{Pair, Public, key_types}, - traits::BareCryptoStorePtr, -}; +use primitives::{Bytes, Blake2Hasher, H256, traits::BareCryptoStorePtr}; use sr_primitives::{generic, traits::{self, ProvideRuntimeApi}}; -use self::error::{Error, Result}; use transaction_pool::{ txpool::{ ChainApi as PoolChainApi, @@ -49,63 +46,9 @@ use transaction_pool::{ }; use session::SessionKeys; -pub use self::gen_client::Client as AuthorClient; - -/// Substrate authoring RPC API -#[rpc] -pub trait AuthorApi { - /// RPC metadata - type Metadata; - - /// Submit hex-encoded extrinsic for inclusion in block. - #[rpc(name = "author_submitExtrinsic")] - fn submit_extrinsic(&self, extrinsic: Bytes) -> Result; - - /// Insert a key into the keystore. - #[rpc(name = "author_insertKey")] - fn insert_key(&self, - key_type: String, - suri: String, - maybe_public: Option - ) -> Result; - - /// Generate new session keys and returns the corresponding public keys. - #[rpc(name = "author_rotateKeys")] - fn rotate_keys(&self) -> Result; - - /// Returns all pending extrinsics, potentially grouped by sender. - #[rpc(name = "author_pendingExtrinsics")] - fn pending_extrinsics(&self) -> Result>; - - /// Remove given extrinsic from the pool and temporarily ban it to prevent reimporting. - #[rpc(name = "author_removeExtrinsic")] - fn remove_extrinsic(&self, - bytes_or_hash: Vec> - ) -> Result>; - - /// Submit an extrinsic to watch. - #[pubsub( - subscription = "author_extrinsicUpdate", - subscribe, - name = "author_submitAndWatchExtrinsic" - )] - fn watch_extrinsic(&self, - metadata: Self::Metadata, - subscriber: Subscriber>, - bytes: Bytes - ); - - /// Unsubscribe from extrinsic watching. - #[pubsub( - subscription = "author_extrinsicUpdate", - unsubscribe, - name = "author_unwatchExtrinsic" - )] - fn unwatch_extrinsic(&self, - metadata: Option, - id: SubscriptionId - ) -> Result; -} +/// Re-export the API for backward compatibility. +pub use api::author::*; +use self::error::{Error, FutureResult, Result}; /// Authoring API pub struct Author where P: PoolChainApi + Sync + Send + 'static { @@ -152,29 +95,13 @@ impl AuthorApi, BlockHash

> for Author whe &self, key_type: String, suri: String, - maybe_public: Option, - ) -> Result { + public: Bytes, + ) -> Result<()> { let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; let mut keystore = self.keystore.write(); - let maybe_password = keystore.password(); - let public = match maybe_public { - Some(public) => public.0, - None => { - let maybe_public = match key_type { - key_types::BABE | key_types::IM_ONLINE | key_types::SR25519 => - sr25519::Pair::from_string(&suri, maybe_password) - .map(|pair| pair.public().to_raw_vec()), - key_types::GRANDPA | key_types::ED25519 => - ed25519::Pair::from_string(&suri, maybe_password) - .map(|pair| pair.public().to_raw_vec()), - _ => Err(Error::UnsupportedKeyType)?, - }; - maybe_public.map_err(|_| Error::BadSeedPhrase)? - } - }; keystore.insert_unknown(key_type, &suri, &public[..]) .map_err(|_| Error::KeyStoreUnavailable)?; - Ok(public.into()) + Ok(()) } fn rotate_keys(&self) -> Result { @@ -182,18 +109,22 @@ impl AuthorApi, BlockHash

> for Author whe self.client.runtime_api().generate_session_keys( &generic::BlockId::Hash(best_block_hash), None, - ).map(Into::into).map_err(Into::into) + ).map(Into::into).map_err(|e| Error::Client(Box::new(e))) } - fn submit_extrinsic(&self, ext: Bytes) -> Result> { - let xt = Decode::decode(&mut &ext[..])?; + fn submit_extrinsic(&self, ext: Bytes) -> FutureResult> { + let xt = match Decode::decode(&mut &ext[..]) { + Ok(xt) => xt, + Err(err) => return Box::new(result(Err(err.into()))), + }; let best_block_hash = self.client.info().chain.best_hash; - self.pool + Box::new(self.pool .submit_one(&generic::BlockId::hash(best_block_hash), xt) + .compat() .map_err(|e| e.into_pool_error() .map(Into::into) - .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into()) - ) + .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into())) + ) } fn pending_extrinsics(&self) -> Result> { @@ -228,30 +159,46 @@ impl AuthorApi, BlockHash

> for Author whe ) { let submit = || -> Result<_> { let best_block_hash = self.client.info().chain.best_hash; - let dxt = <

::Block as traits::Block>::Extrinsic::decode(&mut &xt[..])?; - self.pool - .submit_and_watch(&generic::BlockId::hash(best_block_hash), dxt) - .map_err(|e| e.into_pool_error() - .map(Into::into) - .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into()) - ) + let dxt = <

::Block as traits::Block>::Extrinsic::decode(&mut &xt[..]) + .map_err(error::Error::from)?; + Ok( + self.pool + .submit_and_watch(&generic::BlockId::hash(best_block_hash), dxt) + .map_err(|e| e.into_pool_error() + .map(error::Error::from) + .unwrap_or_else(|e| error::Error::Verification(Box::new(e)).into()) + ) + ) }; - let watcher = match submit() { - Ok(watcher) => watcher, - Err(err) => { - // reject the subscriber (ignore errors - we don't care if subscriber is no longer there). - let _ = subscriber.reject(err.into()); - return; - }, - }; + let subscriptions = self.subscriptions.clone(); + let future = ready(submit()) + .and_then(|res| res) + // convert the watcher into a `Stream` + .map(|res| res.map(|watcher| watcher.into_stream().map(|v| Ok::<_, ()>(Ok(v))))) + // now handle the import result, + // start a new subscrition + .map(move |result| match result { + Ok(watcher) => { + subscriptions.add(subscriber, move |sink| { + sink + .sink_map_err(|_| unimplemented!()) + .send_all(Compat::new(watcher)) + .map(|_| ()) + }); + }, + Err(err) => { + warn!("Failed to submit extrinsic: {}", err); + // reject the subscriber (ignore errors - we don't care if subscriber is no longer there). + let _ = subscriber.reject(err.into()); + }, + }); - self.subscriptions.add(subscriber, move |sink| { - sink - .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all(watcher.into_stream().map(Ok)) - .map(|_| ()) - }) + let res = self.subscriptions.executor() + .execute(Box::new(Compat::new(future.map(|_| Ok(()))))); + if res.is_err() { + warn!("Error spawning subscription RPC task."); + } } fn unwatch_extrinsic(&self, _metadata: Option, id: SubscriptionId) -> Result { diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs index 0fdff9989b1cab11b74cfa18f73598842ac6b93e..5ae044ff49ede78ab20adca9d9c3da1b108fd489 100644 --- a/core/rpc/src/author/tests.rs +++ b/core/rpc/src/author/tests.rs @@ -19,17 +19,18 @@ use super::*; use std::sync::Arc; use assert_matches::assert_matches; use codec::Encode; -use transaction_pool::{ - txpool::Pool, - ChainApi, -}; use primitives::{ - H256, blake2_256, hexdisplay::HexDisplay, traits::BareCryptoStore, testing::KeyStore, - ed25519, crypto::key_types, + H256, blake2_256, hexdisplay::HexDisplay, testing::{ED25519, SR25519, KeyStore}, traits::BareCryptoStorePtr, ed25519, + crypto::Pair, }; +use rpc::futures::Stream as _; use test_client::{ - self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys}, DefaultTestClientBuilderExt, - TestClientBuilderExt, + self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys, RuntimeApi, Block}, DefaultTestClientBuilderExt, + TestClientBuilderExt, Backend, Client, Executor +}; +use transaction_pool::{ + txpool::Pool, + FullChainApi, }; use tokio::runtime; @@ -43,72 +44,81 @@ fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { tx.into_signed_tx() } +struct TestSetup { + pub runtime: runtime::Runtime, + pub client: Arc>, + pub keystore: BareCryptoStorePtr, + pub pool: Arc, Block>>>, +} + +impl Default for TestSetup { + fn default() -> Self { + let keystore = KeyStore::new(); + let client = Arc::new(test_client::TestClientBuilder::new().set_keystore(keystore.clone()).build()); + let pool = Arc::new(Pool::new(Default::default(), FullChainApi::new(client.clone()))); + TestSetup { + runtime: runtime::Runtime::new().expect("Failed to create runtime in test setup"), + client, + keystore, + pool, + } + } +} + +impl TestSetup { + fn author(&self) -> Author, Block>, RuntimeApi> { + Author { + client: self.client.clone(), + pool: self.pool.clone(), + subscriptions: Subscriptions::new(Arc::new(self.runtime.executor())), + keystore: self.keystore.clone(), + } + } +} + #[test] fn submit_transaction_should_not_cause_error() { - let runtime = runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let keystore = KeyStore::new(); - let p = Author { - client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client))), - subscriptions: Subscriptions::new(Arc::new(runtime.executor())), - keystore: keystore.clone(), - }; + let p = TestSetup::default().author(); let xt = uxt(AccountKeyring::Alice, 1).encode(); let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, xt.clone().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()).wait(), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, xt.into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).wait().is_err() ); } #[test] fn submit_rich_transaction_should_not_cause_error() { - let runtime = runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let keystore = KeyStore::new(); - let p = Author { - client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client.clone()))), - subscriptions: Subscriptions::new(Arc::new(runtime.executor())), - keystore: keystore.clone(), - }; + let p = TestSetup::default().author(); let xt = uxt(AccountKeyring::Alice, 0).encode(); let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, xt.clone().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()).wait(), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, xt.into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).wait().is_err() ); } #[test] fn should_watch_extrinsic() { //given - let mut runtime = runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), ChainApi::new(client.clone()))); - let keystore = KeyStore::new(); - let p = Author { - client, - pool: pool.clone(), - subscriptions: Subscriptions::new(Arc::new(runtime.executor())), - keystore: keystore.clone(), - }; - let (subscriber, id_rx, data) = ::jsonrpc_pubsub::typed::Subscriber::new_test("test"); + let mut setup = TestSetup::default(); + let p = setup.author(); + + let (subscriber, id_rx, data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); // when p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 0).encode().into()); // then - assert_eq!(runtime.block_on(id_rx), Ok(Ok(1.into()))); + assert_eq!(setup.runtime.block_on(id_rx), Ok(Ok(1.into()))); // check notifications let replacement = { let tx = Transfer { @@ -119,33 +129,41 @@ fn should_watch_extrinsic() { }; tx.into_signed_tx() }; - AuthorApi::submit_extrinsic(&p, replacement.encode().into()).unwrap(); - let (res, data) = runtime.block_on(data.into_future()).unwrap(); + AuthorApi::submit_extrinsic(&p, replacement.encode().into()).wait().unwrap(); + let (res, data) = setup.runtime.block_on(data.into_future()).unwrap(); assert_eq!( res, Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":"ready","subscription":1}}"#.into()) ); let h = blake2_256(&replacement.encode()); assert_eq!( - runtime.block_on(data.into_future()).unwrap().0, + setup.runtime.block_on(data.into_future()).unwrap().0, Some(format!(r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":1}}}}"#, HexDisplay::from(&h))) ); } +#[test] +fn should_return_watch_validation_error() { + //given + let mut setup = TestSetup::default(); + let p = setup.author(); + + let (subscriber, id_rx, _data) = jsonrpc_pubsub::typed::Subscriber::new_test("test"); + + // when + p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 179).encode().into()); + + // then + let res = setup.runtime.block_on(id_rx).unwrap(); + assert!(res.is_err(), "Expected the transaction to be rejected as invalid."); +} + #[test] fn should_return_pending_extrinsics() { - let runtime = runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), ChainApi::new(client.clone()))); - let keystore = KeyStore::new(); - let p = Author { - client, - pool: pool.clone(), - subscriptions: Subscriptions::new(Arc::new(runtime.executor())), - keystore: keystore.clone(), - }; + let p = TestSetup::default().author(); + let ex = uxt(AccountKeyring::Alice, 0); - AuthorApi::submit_extrinsic(&p, ex.encode().into()).unwrap(); + AuthorApi::submit_extrinsic(&p, ex.encode().into()).wait().unwrap(); assert_matches!( p.pending_extrinsics(), Ok(ref expected) if *expected == vec![Bytes(ex.encode())] @@ -154,23 +172,16 @@ fn should_return_pending_extrinsics() { #[test] fn should_remove_extrinsics() { - let runtime = runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let pool = Arc::new(Pool::new(Default::default(), ChainApi::new(client.clone()))); - let keystore = KeyStore::new(); - let p = Author { - client, - pool: pool.clone(), - subscriptions: Subscriptions::new(Arc::new(runtime.executor())), - keystore: keystore.clone(), - }; + let setup = TestSetup::default(); + let p = setup.author(); + let ex1 = uxt(AccountKeyring::Alice, 0); - p.submit_extrinsic(ex1.encode().into()).unwrap(); + p.submit_extrinsic(ex1.encode().into()).wait().unwrap(); let ex2 = uxt(AccountKeyring::Alice, 1); - p.submit_extrinsic(ex2.encode().into()).unwrap(); + p.submit_extrinsic(ex2.encode().into()).wait().unwrap(); let ex3 = uxt(AccountKeyring::Bob, 0); - let hash3 = p.submit_extrinsic(ex3.encode().into()).unwrap(); - assert_eq!(pool.status().ready, 3); + let hash3 = p.submit_extrinsic(ex3.encode().into()).wait().unwrap(); + assert_eq!(setup.pool.status().ready, 3); // now remove all 3 let removed = p.remove_extrinsic(vec![ @@ -184,57 +195,43 @@ fn should_remove_extrinsics() { #[test] fn should_insert_key() { - let runtime = runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); - let keystore = KeyStore::new(); - let p = Author { - client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client))), - subscriptions: Subscriptions::new(Arc::new(runtime.executor())), - keystore: keystore.clone(), - }; + let setup = TestSetup::default(); + let p = setup.author(); let suri = "//Alice"; let key_pair = ed25519::Pair::from_string(suri, None).expect("Generates keypair"); p.insert_key( - String::from_utf8(key_types::ED25519.0.to_vec()).expect("Keytype is a valid string"), + String::from_utf8(ED25519.0.to_vec()).expect("Keytype is a valid string"), suri.to_string(), - Some(key_pair.public().0.to_vec().into()), + key_pair.public().0.to_vec().into(), ).expect("Insert key"); - let store_key_pair = keystore.read() - .ed25519_key_pair(key_types::ED25519, &key_pair.public()).expect("Key exists in store"); + let store_key_pair = setup.keystore.read() + .ed25519_key_pair(ED25519, &key_pair.public()).expect("Key exists in store"); assert_eq!(key_pair.public(), store_key_pair.public()); } #[test] fn should_rotate_keys() { - let runtime = runtime::Runtime::new().unwrap(); - let keystore = KeyStore::new(); - let client = Arc::new(test_client::TestClientBuilder::new().set_keystore(keystore.clone()).build()); - let p = Author { - client: client.clone(), - pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client))), - subscriptions: Subscriptions::new(Arc::new(runtime.executor())), - keystore: keystore.clone(), - }; + let setup = TestSetup::default(); + let p = setup.author(); let new_public_keys = p.rotate_keys().expect("Rotates the keys"); let session_keys = SessionKeys::decode(&mut &new_public_keys[..]) .expect("SessionKeys decode successfully"); - let ed25519_key_pair = keystore.read().ed25519_key_pair( - key_types::ED25519, + let ed25519_key_pair = setup.keystore.read().ed25519_key_pair( + ED25519, &session_keys.ed25519.clone().into(), ).expect("ed25519 key exists in store"); - let sr25519_key_pair = keystore.read().sr25519_key_pair( - key_types::SR25519, + let sr25519_key_pair = setup.keystore.read().sr25519_key_pair( + SR25519, &session_keys.sr25519.clone().into(), ).expect("sr25519 key exists in store"); assert_eq!(session_keys.ed25519, ed25519_key_pair.public().into()); assert_eq!(session_keys.sr25519, sr25519_key_pair.public().into()); -} \ No newline at end of file +} diff --git a/core/rpc/src/chain/chain_full.rs b/core/rpc/src/chain/chain_full.rs new file mode 100644 index 0000000000000000000000000000000000000000..ad359a9300cdd63b4e513d3e428e3fecb799aebf --- /dev/null +++ b/core/rpc/src/chain/chain_full.rs @@ -0,0 +1,79 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Blockchain API backend for full nodes. + +use std::sync::Arc; +use rpc::futures::future::result; + +use api::Subscriptions; +use client::{backend::Backend, CallExecutor, Client}; +use primitives::{H256, Blake2Hasher}; +use sr_primitives::{ + generic::{BlockId, SignedBlock}, + traits::{Block as BlockT}, +}; + +use super::{ChainBackend, client_err, error::FutureResult}; + +/// Blockchain API backend for full nodes. Reads all the data from local database. +pub struct FullChain { + /// Substrate client. + client: Arc>, + /// Current subscriptions. + subscriptions: Subscriptions, +} + +impl FullChain { + /// Create new Chain API RPC handler. + pub fn new(client: Arc>, subscriptions: Subscriptions) -> Self { + Self { + client, + subscriptions, + } + } +} + +impl ChainBackend for FullChain where + Block: BlockT + 'static, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static, +{ + fn client(&self) -> &Arc> { + &self.client + } + + fn subscriptions(&self) -> &Subscriptions { + &self.subscriptions + } + + fn header(&self, hash: Option) -> FutureResult> { + Box::new(result(self.client + .header(&BlockId::Hash(self.unwrap_or_best(hash))) + .map_err(client_err) + )) + } + + fn block(&self, hash: Option) + -> FutureResult>> + { + Box::new(result(self.client + .block(&BlockId::Hash(self.unwrap_or_best(hash))) + .map_err(client_err) + )) + } +} diff --git a/core/rpc/src/chain/chain_light.rs b/core/rpc/src/chain/chain_light.rs new file mode 100644 index 0000000000000000000000000000000000000000..d969d6ca9370218df642fc2a1caa984c0e5ef09e --- /dev/null +++ b/core/rpc/src/chain/chain_light.rs @@ -0,0 +1,123 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Blockchain API backend for light nodes. + +use std::sync::Arc; +use futures03::{future::ready, FutureExt, TryFutureExt}; +use rpc::futures::future::{result, Future, Either}; + +use api::Subscriptions; +use client::{ + self, Client, + light::{ + fetcher::{Fetcher, RemoteBodyRequest}, + blockchain::RemoteBlockchain, + }, +}; +use primitives::{H256, Blake2Hasher}; +use sr_primitives::{ + generic::{BlockId, SignedBlock}, + traits::{Block as BlockT}, +}; + +use super::{ChainBackend, client_err, error::FutureResult}; + +/// Blockchain API backend for light nodes. Reads all the data from local +/// database, if available, or fetches it from remote node otherwise. +pub struct LightChain { + /// Substrate client. + client: Arc>, + /// Current subscriptions. + subscriptions: Subscriptions, + /// Remote blockchain reference + remote_blockchain: Arc>, + /// Remote fetcher reference. + fetcher: Arc, +} + +impl> LightChain { + /// Create new Chain API RPC handler. + pub fn new( + client: Arc>, + subscriptions: Subscriptions, + remote_blockchain: Arc>, + fetcher: Arc, + ) -> Self { + Self { + client, + subscriptions, + remote_blockchain, + fetcher, + } + } +} + +impl ChainBackend for LightChain where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static, + F: Fetcher + Send + Sync + 'static, +{ + fn client(&self) -> &Arc> { + &self.client + } + + fn subscriptions(&self) -> &Subscriptions { + &self.subscriptions + } + + fn header(&self, hash: Option) -> FutureResult> { + let hash = self.unwrap_or_best(hash); + + let fetcher = self.fetcher.clone(); + let maybe_header = client::light::blockchain::future_header( + &*self.remote_blockchain, + &*fetcher, + BlockId::Hash(hash), + ); + + Box::new(maybe_header.then(move |result| + ready(result.map_err(client_err)), + ).boxed().compat()) + } + + fn block(&self, hash: Option) + -> FutureResult>> + { + let fetcher = self.fetcher.clone(); + let block = self.header(hash) + .and_then(move |header| match header { + Some(header) => Either::A(fetcher + .remote_body(RemoteBodyRequest { + header: header.clone(), + retry_count: Default::default(), + }) + .boxed() + .compat() + .map(move |body| Some(SignedBlock { + block: Block::new(header, body), + justification: None, + })) + .map_err(client_err) + ), + None => Either::B(result(Ok(None))), + }); + + Box::new(block) + } +} diff --git a/core/rpc/src/chain/mod.rs b/core/rpc/src/chain/mod.rs index 9b8192e660e9be207c19c0b639ddccec88f5130a..61ecf967113832f456fc88231f2851618261352c 100644 --- a/core/rpc/src/chain/mod.rs +++ b/core/rpc/src/chain/mod.rs @@ -16,156 +16,182 @@ //! Substrate blockchain API. -pub mod error; -pub mod number; +mod chain_full; +mod chain_light; #[cfg(test)] mod tests; use std::sync::Arc; use futures03::{future, StreamExt as _, TryStreamExt as _}; - -use client::{self, Client, BlockchainEvents}; -use crate::rpc::Result as RpcResult; -use crate::rpc::futures::{stream, Future, Sink, Stream}; -use crate::subscriptions::Subscriptions; -use jsonrpc_derive::rpc; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use log::warn; +use rpc::{ + Result as RpcResult, + futures::{stream, Future, Sink, Stream}, +}; + +use api::Subscriptions; +use client::{ + self, Client, BlockchainEvents, + light::{fetcher::Fetcher, blockchain::RemoteBlockchain}, +}; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use primitives::{H256, Blake2Hasher}; -use sr_primitives::generic::{BlockId, SignedBlock}; -use sr_primitives::traits::{Block as BlockT, Header, NumberFor}; -use self::error::Result; +use rpc_primitives::number; +use sr_primitives::{ + generic::{BlockId, SignedBlock}, + traits::{Block as BlockT, Header, NumberFor}, +}; + +use self::error::{Result, Error, FutureResult}; + +pub use api::chain::*; + +/// Blockchain backend API +trait ChainBackend: Send + Sync + 'static + where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, +{ + /// Get client reference. + fn client(&self) -> &Arc>; -pub use self::gen_client::Client as ChainClient; + /// Get subscriptions reference. + fn subscriptions(&self) -> &Subscriptions; -/// Substrate blockchain API -#[rpc] -pub trait ChainApi { - /// RPC metadata - type Metadata; + /// Tries to unwrap passed block hash, or uses best block hash otherwise. + fn unwrap_or_best(&self, hash: Option) -> Block::Hash { + match hash.into() { + None => self.client().info().chain.best_hash, + Some(hash) => hash, + } + } /// Get header of a relay chain block. - #[rpc(name = "chain_getHeader")] - fn header(&self, hash: Option) -> Result>; + fn header(&self, hash: Option) -> FutureResult>; /// Get header and body of a relay chain block. - #[rpc(name = "chain_getBlock")] - fn block(&self, hash: Option) -> Result>; + fn block(&self, hash: Option) -> FutureResult>>; /// Get hash of the n-th block in the canon chain. /// /// By default returns latest block hash. - #[rpc(name = "chain_getBlockHash", alias("chain_getHead"))] - fn block_hash(&self, hash: Option>) -> Result>; + fn block_hash( + &self, + number: Option>>, + ) -> Result> { + Ok(match number { + None => Some(self.client().info().chain.best_hash), + Some(num_or_hex) => self.client() + .header(&BlockId::number(num_or_hex.to_number()?)) + .map_err(client_err)? + .map(|h| h.hash()), + }) + } /// Get hash of the last finalized block in the canon chain. - #[rpc(name = "chain_getFinalizedHead", alias("chain_getFinalisedHead"))] - fn finalized_head(&self) -> Result; + fn finalized_head(&self) -> Result { + Ok(self.client().info().chain.finalized_hash) + } /// New head subscription - #[pubsub( - subscription = "chain_newHead", - subscribe, - name = "chain_subscribeNewHead", - alias("subscribe_newHead") - )] - fn subscribe_new_head(&self, metadata: Self::Metadata, subscriber: Subscriber

); + fn subscribe_new_heads( + &self, + _metadata: crate::metadata::Metadata, + subscriber: Subscriber, + ) { + subscribe_headers( + self.client(), + self.subscriptions(), + subscriber, + || self.client().info().chain.best_hash, + || self.client().import_notification_stream() + .filter(|notification| future::ready(notification.is_new_best)) + .map(|notification| Ok::<_, ()>(notification.header)) + .compat(), + ) + } /// Unsubscribe from new head subscription. - #[pubsub( - subscription = "chain_newHead", - unsubscribe, - name = "chain_unsubscribeNewHead", - alias("unsubscribe_newHead") - )] - fn unsubscribe_new_head(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + fn unsubscribe_new_heads( + &self, + _metadata: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions().cancel(id)) + } /// New head subscription - #[pubsub( - subscription = "chain_finalizedHead", - subscribe, - name = "chain_subscribeFinalizedHeads", - alias("chain_subscribeFinalisedHeads") - )] - fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber
); + fn subscribe_finalized_heads( + &self, + _metadata: crate::metadata::Metadata, + subscriber: Subscriber, + ) { + subscribe_headers( + self.client(), + self.subscriptions(), + subscriber, + || self.client().info().chain.finalized_hash, + || self.client().finality_notification_stream() + .map(|notification| Ok::<_, ()>(notification.header)) + .compat(), + ) + } /// Unsubscribe from new head subscription. - #[pubsub( - subscription = "chain_finalizedHead", - unsubscribe, - name = "chain_unsubscribeFinalizedHeads", - alias("chain_unsubscribeFinalisedHeads") - )] - fn unsubscribe_finalized_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + fn unsubscribe_finalized_heads( + &self, + _metadata: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions().cancel(id)) + } } -/// Chain API with subscriptions support. -pub struct Chain { - /// Substrate client. +/// Create new state API that works on full node. +pub fn new_full( client: Arc>, - /// Current subscriptions. subscriptions: Subscriptions, +) -> Chain + where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, +{ + Chain { + backend: Box::new(self::chain_full::FullChain::new(client, subscriptions)), + } } -impl Chain { - /// Create new Chain API RPC handler. - pub fn new(client: Arc>, subscriptions: Subscriptions) -> Self { - Self { +/// Create new state API that works on light node. +pub fn new_light>( + client: Arc>, + subscriptions: Subscriptions, + remote_blockchain: Arc>, + fetcher: Arc, +) -> Chain + where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + F: Send + Sync + 'static, +{ + Chain { + backend: Box::new(self::chain_light::LightChain::new( client, subscriptions, - } + remote_blockchain, + fetcher, + )), } } -impl Chain where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: client::CallExecutor + Send + Sync + 'static, - RA: Send + Sync + 'static -{ - fn unwrap_or_best(&self, hash: Option) -> Result { - Ok(match hash.into() { - None => self.client.info().chain.best_hash, - Some(hash) => hash, - }) - } - - fn subscribe_headers( - &self, - subscriber: Subscriber, - best_block_hash: G, - stream: F, - ) where - F: FnOnce() -> S, - G: FnOnce() -> Result>, - ERR: ::std::fmt::Debug, - S: Stream + Send + 'static, - { - self.subscriptions.add(subscriber, |sink| { - // send current head right at the start. - let header = best_block_hash() - .and_then(|hash| self.header(hash.into())) - .and_then(|header| { - header.ok_or_else(|| "Best header missing.".to_owned().into()) - }) - .map_err(Into::into); - - // send further subscriptions - let stream = stream() - .map(|res| Ok(res)) - .map_err(|e| warn!("Block notification stream error: {:?}", e)); - - sink - .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all( - stream::iter_result(vec![Ok(header)]) - .chain(stream) - ) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }); - } +/// Chain API with subscriptions support. +pub struct Chain { + backend: Box>, } impl ChainApi, Block::Hash, Block::Header, SignedBlock> for Chain where @@ -176,55 +202,81 @@ impl ChainApi, Block::Hash, Block::Header, Sig { type Metadata = crate::metadata::Metadata; - fn header(&self, hash: Option) -> Result> { - let hash = self.unwrap_or_best(hash)?; - Ok(self.client.header(&BlockId::Hash(hash))?) + fn header(&self, hash: Option) -> FutureResult> { + self.backend.header(hash) } - fn block(&self, hash: Option) - -> Result>> + fn block(&self, hash: Option) -> FutureResult>> { - let hash = self.unwrap_or_best(hash)?; - Ok(self.client.block(&BlockId::Hash(hash))?) + self.backend.block(hash) } fn block_hash(&self, number: Option>>) -> Result> { - Ok(match number { - None => Some(self.client.info().chain.best_hash), - Some(num_or_hex) => self.client.header(&BlockId::number(num_or_hex.to_number()?))?.map(|h| h.hash()), - }) + self.backend.block_hash(number) } fn finalized_head(&self) -> Result { - Ok(self.client.info().chain.finalized_hash) + self.backend.finalized_head() } - fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: Subscriber) { - self.subscribe_headers( - subscriber, - || self.block_hash(None.into()), - || self.client.import_notification_stream() - .filter(|notification| future::ready(notification.is_new_best)) - .map(|notification| Ok::<_, ()>(notification.header)) - .compat(), - ) + fn subscribe_new_heads(&self, metadata: Self::Metadata, subscriber: Subscriber) { + self.backend.subscribe_new_heads(metadata, subscriber) } - fn unsubscribe_new_head(&self, _metadata: Option, id: SubscriptionId) -> RpcResult { - Ok(self.subscriptions.cancel(id)) + fn unsubscribe_new_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult { + self.backend.unsubscribe_new_heads(metadata, id) } - fn subscribe_finalized_heads(&self, _meta: Self::Metadata, subscriber: Subscriber) { - self.subscribe_headers( - subscriber, - || Ok(Some(self.client.info().chain.finalized_hash)), - || self.client.finality_notification_stream() - .map(|notification| Ok::<_, ()>(notification.header)) - .compat(), - ) + fn subscribe_finalized_heads(&self, metadata: Self::Metadata, subscriber: Subscriber) { + self.backend.subscribe_finalized_heads(metadata, subscriber) } - fn unsubscribe_finalized_heads(&self, _metadata: Option, id: SubscriptionId) -> RpcResult { - Ok(self.subscriptions.cancel(id)) + fn unsubscribe_finalized_heads(&self, metadata: Option, id: SubscriptionId) -> RpcResult { + self.backend.unsubscribe_finalized_heads(metadata, id) } } + +/// Subscribe to new headers. +fn subscribe_headers( + client: &Arc>, + subscriptions: &Subscriptions, + subscriber: Subscriber, + best_block_hash: G, + stream: F, +) where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, + F: FnOnce() -> S, + G: FnOnce() -> Block::Hash, + ERR: ::std::fmt::Debug, + S: Stream + Send + 'static, +{ + subscriptions.add(subscriber, |sink| { + // send current head right at the start. + let header = client.header(&BlockId::Hash(best_block_hash())) + .map_err(client_err) + .and_then(|header| { + header.ok_or_else(|| "Best header missing.".to_owned().into()) + }) + .map_err(Into::into); + + // send further subscriptions + let stream = stream() + .map(|res| Ok(res)) + .map_err(|e| warn!("Block notification stream error: {:?}", e)); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all( + stream::iter_result(vec![Ok(header)]) + .chain(stream) + ) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); +} + +fn client_err(err: client::error::Error) -> Error { + Error::Client(Box::new(err)) +} diff --git a/core/rpc/src/chain/tests.rs b/core/rpc/src/chain/tests.rs index e6fa4d94e5b0dfa96bfebc615eeb9aede6e40082..8b46befee65208b61da8ca10e350436d83ee8eec 100644 --- a/core/rpc/src/chain/tests.rs +++ b/core/rpc/src/chain/tests.rs @@ -27,13 +27,11 @@ fn should_return_header() { let core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let client = Chain { - client: Arc::new(test_client::new()), - subscriptions: Subscriptions::new(Arc::new(remote)), - }; + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); assert_matches!( - client.header(Some(client.client.genesis_hash()).into()), + api.header(Some(client.genesis_hash()).into()).wait(), Ok(Some(ref x)) if x == &Header { parent_hash: H256::from_low_u64_be(0), number: 0, @@ -44,7 +42,7 @@ fn should_return_header() { ); assert_matches!( - client.header(None.into()), + api.header(None.into()).wait(), Ok(Some(ref x)) if x == &Header { parent_hash: H256::from_low_u64_be(0), number: 0, @@ -55,7 +53,7 @@ fn should_return_header() { ); assert_matches!( - client.header(Some(H256::from_low_u64_be(5)).into()), + api.header(Some(H256::from_low_u64_be(5)).into()).wait(), Ok(None) ); } @@ -65,26 +63,24 @@ fn should_return_a_block() { let core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let api = Chain { - client: Arc::new(test_client::new()), - subscriptions: Subscriptions::new(Arc::new(remote)), - }; + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - let block = api.client.new_block(Default::default()).unwrap().bake().unwrap(); + let block = client.new_block(Default::default()).unwrap().bake().unwrap(); let block_hash = block.hash(); - api.client.import(BlockOrigin::Own, block).unwrap(); + client.import(BlockOrigin::Own, block).unwrap(); // Genesis block is not justified assert_matches!( - api.block(Some(api.client.genesis_hash()).into()), + api.block(Some(client.genesis_hash()).into()).wait(), Ok(Some(SignedBlock { justification: None, .. })) ); assert_matches!( - api.block(Some(block_hash).into()), + api.block(Some(block_hash).into()).wait(), Ok(Some(ref x)) if x.block == Block { header: Header { - parent_hash: api.client.genesis_hash(), + parent_hash: client.genesis_hash(), number: 1, state_root: x.block.header.state_root.clone(), extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), @@ -95,10 +91,10 @@ fn should_return_a_block() { ); assert_matches!( - api.block(None.into()), + api.block(None.into()).wait(), Ok(Some(ref x)) if x.block == Block { header: Header { - parent_hash: api.client.genesis_hash(), + parent_hash: client.genesis_hash(), number: 1, state_root: x.block.header.state_root.clone(), extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314".parse().unwrap(), @@ -109,7 +105,7 @@ fn should_return_a_block() { ); assert_matches!( - api.block(Some(H256::from_low_u64_be(5)).into()), + api.block(Some(H256::from_low_u64_be(5)).into()).wait(), Ok(None) ); } @@ -119,40 +115,38 @@ fn should_return_block_hash() { let core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let client = Chain { - client: Arc::new(test_client::new()), - subscriptions: Subscriptions::new(Arc::new(remote)), - }; + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); assert_matches!( - client.block_hash(None.into()), - Ok(Some(ref x)) if x == &client.client.genesis_hash() + api.block_hash(None.into()), + Ok(Some(ref x)) if x == &client.genesis_hash() ); assert_matches!( - client.block_hash(Some(0u64.into()).into()), - Ok(Some(ref x)) if x == &client.client.genesis_hash() + api.block_hash(Some(0u64.into()).into()), + Ok(Some(ref x)) if x == &client.genesis_hash() ); assert_matches!( - client.block_hash(Some(1u64.into()).into()), + api.block_hash(Some(1u64.into()).into()), Ok(None) ); - let block = client.client.new_block(Default::default()).unwrap().bake().unwrap(); - client.client.import(BlockOrigin::Own, block.clone()).unwrap(); + let block = client.new_block(Default::default()).unwrap().bake().unwrap(); + client.import(BlockOrigin::Own, block.clone()).unwrap(); assert_matches!( - client.block_hash(Some(0u64.into()).into()), - Ok(Some(ref x)) if x == &client.client.genesis_hash() + api.block_hash(Some(0u64.into()).into()), + Ok(Some(ref x)) if x == &client.genesis_hash() ); assert_matches!( - client.block_hash(Some(1u64.into()).into()), + api.block_hash(Some(1u64.into()).into()), Ok(Some(ref x)) if x == &block.hash() ); assert_matches!( - client.block_hash(Some(::primitives::U256::from(1u64).into()).into()), + api.block_hash(Some(::primitives::U256::from(1u64).into()).into()), Ok(Some(ref x)) if x == &block.hash() ); } @@ -163,30 +157,28 @@ fn should_return_finalized_hash() { let core = ::tokio::runtime::Runtime::new().unwrap(); let remote = core.executor(); - let client = Chain { - client: Arc::new(test_client::new()), - subscriptions: Subscriptions::new(Arc::new(remote)), - }; + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); assert_matches!( - client.finalized_head(), - Ok(ref x) if x == &client.client.genesis_hash() + api.finalized_head(), + Ok(ref x) if x == &client.genesis_hash() ); // import new block - let builder = client.client.new_block(Default::default()).unwrap(); - client.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); + let builder = client.new_block(Default::default()).unwrap(); + client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); // no finalization yet assert_matches!( - client.finalized_head(), - Ok(ref x) if x == &client.client.genesis_hash() + api.finalized_head(), + Ok(ref x) if x == &client.genesis_hash() ); // finalize - client.client.finalize_block(BlockId::number(1), None, true).unwrap(); + client.finalize_block(BlockId::number(1), None).unwrap(); assert_matches!( - client.finalized_head(), - Ok(ref x) if x == &client.client.block_hash(1).unwrap().unwrap() + api.finalized_head(), + Ok(ref x) if x == &client.block_hash(1).unwrap().unwrap() ); } @@ -197,18 +189,16 @@ fn should_notify_about_latest_block() { let (subscriber, id, transport) = Subscriber::new_test("test"); { - let api = Chain { - client: Arc::new(test_client::new()), - subscriptions: Subscriptions::new(Arc::new(remote)), - }; + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); - api.subscribe_new_head(Default::default(), subscriber); + api.subscribe_new_heads(Default::default(), subscriber); // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let builder = api.client.new_block(Default::default()).unwrap(); - api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); + let builder = client.new_block(Default::default()).unwrap(); + client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); } // assert initial head sent. @@ -228,19 +218,17 @@ fn should_notify_about_finalized_block() { let (subscriber, id, transport) = Subscriber::new_test("test"); { - let api = Chain { - client: Arc::new(test_client::new()), - subscriptions: Subscriptions::new(Arc::new(remote)), - }; + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); api.subscribe_finalized_heads(Default::default(), subscriber); // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let builder = api.client.new_block(Default::default()).unwrap(); - api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); - api.client.finalize_block(BlockId::number(1), None, true).unwrap(); + let builder = client.new_block(Default::default()).unwrap(); + client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); + client.finalize_block(BlockId::number(1), None).unwrap(); } // assert initial head sent. diff --git a/core/rpc/src/lib.rs b/core/rpc/src/lib.rs index 6488ea5f49c54120f5a77dbd1c23e8e16004b3d9..1341acb63d3537e49d48ace6b363172dc09da2f6 100644 --- a/core/rpc/src/lib.rs +++ b/core/rpc/src/lib.rs @@ -14,20 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Substrate RPC interfaces. +//! Substrate RPC implementation. +//! +//! A core implementation of Substrate RPC interfaces. #![warn(missing_docs)] -mod errors; -mod helpers; -mod subscriptions; +mod metadata; -pub use subscriptions::Subscriptions; +pub use api::Subscriptions; +pub use self::metadata::Metadata; +pub use rpc::IoHandlerExtension as RpcExtension; pub mod author; pub mod chain; -pub mod metadata; pub mod state; pub mod system; - -use jsonrpc_core as rpc; diff --git a/core/rpc/src/metadata.rs b/core/rpc/src/metadata.rs index e6af4ef94bc1adf6fee90eb520630da09ed18942..73bf583765b206ef3f1ecdcea51b5c977b26cd02 100644 --- a/core/rpc/src/metadata.rs +++ b/core/rpc/src/metadata.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use jsonrpc_pubsub::{Session, PubSubMetadata}; -use crate::rpc::futures::sync::mpsc; +use rpc::futures::sync::mpsc; /// RPC Metadata. /// @@ -30,7 +30,7 @@ pub struct Metadata { session: Option>, } -impl crate::rpc::Metadata for Metadata {} +impl rpc::Metadata for Metadata {} impl PubSubMetadata for Metadata { fn session(&self) -> Option> { self.session.clone() @@ -52,3 +52,9 @@ impl Metadata { (rx, Self::new(tx)) } } + +impl From> for Metadata { + fn from(sender: mpsc::Sender) -> Self { + Self::new(sender) + } +} diff --git a/core/rpc/src/state/mod.rs b/core/rpc/src/state/mod.rs index 0044ad77b8000a4f14e7b1fa45807c0c8096560c..b922601b0a5b213999e49bc2cc76c64e7714b93d 100644 --- a/core/rpc/src/state/mod.rs +++ b/core/rpc/src/state/mod.rs @@ -16,374 +16,245 @@ //! Substrate state API. -pub mod error; +mod state_full; +mod state_light; #[cfg(test)] mod tests; -use std::{ - collections::{BTreeMap, HashMap}, - ops::Range, - sync::Arc, +use std::sync::Arc; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use rpc::{ + Result as RpcResult, + futures::Future, }; -use futures03::{future, StreamExt as _, TryStreamExt as _}; -use client::{self, Client, CallExecutor, BlockchainEvents, runtime_api::Metadata}; -use crate::rpc::Result as RpcResult; -use crate::rpc::futures::{stream, Future, Sink, Stream}; -use crate::subscriptions::Subscriptions; -use jsonrpc_derive::rpc; -use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; -use log::{warn, trace}; -use primitives::hexdisplay::HexDisplay; -use primitives::storage::{self, StorageKey, StorageData, StorageChangeSet}; -use primitives::{H256, Blake2Hasher, Bytes}; -use sr_primitives::generic::BlockId; -use sr_primitives::traits::{ - Block as BlockT, Header, ProvideRuntimeApi, NumberFor, - SaturatedConversion +use api::Subscriptions; +use client::{ + Client, CallExecutor, + runtime_api::Metadata, + light::{blockchain::RemoteBlockchain, fetcher::Fetcher}, +}; +use primitives::{ + Blake2Hasher, Bytes, H256, + storage::{StorageKey, StorageData, StorageChangeSet}, }; use runtime_version::RuntimeVersion; -use self::error::Result; -use state_machine::{self, ExecutionStrategy}; +use sr_primitives::{ + traits::{Block as BlockT, ProvideRuntimeApi}, +}; -pub use self::gen_client::Client as StateClient; +use self::error::{Error, FutureResult}; -/// Substrate state API -#[rpc] -pub trait StateApi { - /// RPC Metadata - type Metadata; +pub use api::state::*; - /// Call a contract at a block's state. - #[rpc(name = "state_call", alias("state_callAt"))] - fn call(&self, name: String, bytes: Bytes, hash: Option) -> Result; +/// State backend API. +pub trait StateBackend: Send + Sync + 'static + where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, + RA: Send + Sync + 'static, +{ + /// Call runtime method at given block. + fn call( + &self, + block: Option, + method: String, + call_data: Bytes, + ) -> FutureResult; - /// Returns the keys with prefix, leave empty to get all the keys - #[rpc(name = "state_getKeys")] - fn storage_keys(&self, prefix: StorageKey, hash: Option) -> Result>; + /// Returns the keys with prefix, leave empty to get all the keys. + fn storage_keys( + &self, + block: Option, + prefix: StorageKey, + ) -> FutureResult>; /// Returns a storage entry at a specific block's state. - #[rpc(name = "state_getStorage", alias("state_getStorageAt"))] - fn storage(&self, key: StorageKey, hash: Option) -> Result>; + fn storage( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult>; /// Returns the hash of a storage entry at a block's state. - #[rpc(name = "state_getStorageHash", alias("state_getStorageHashAt"))] - fn storage_hash(&self, key: StorageKey, hash: Option) -> Result>; + fn storage_hash( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult>; /// Returns the size of a storage entry at a block's state. - #[rpc(name = "state_getStorageSize", alias("state_getStorageSizeAt"))] - fn storage_size(&self, key: StorageKey, hash: Option) -> Result>; + fn storage_size( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(self.storage(block, key) + .map(|x| x.map(|x| x.0.len() as u64))) + } /// Returns the keys with prefix from a child storage, leave empty to get all the keys - #[rpc(name = "state_getChildKeys")] fn child_storage_keys( &self, + block: Option, child_storage_key: StorageKey, prefix: StorageKey, - hash: Option - ) -> Result>; + ) -> FutureResult>; /// Returns a child storage entry at a specific block's state. - #[rpc(name = "state_getChildStorage")] fn child_storage( &self, + block: Option, child_storage_key: StorageKey, key: StorageKey, - hash: Option - ) -> Result>; + ) -> FutureResult>; /// Returns the hash of a child storage entry at a block's state. - #[rpc(name = "state_getChildStorageHash")] fn child_storage_hash( &self, + block: Option, child_storage_key: StorageKey, key: StorageKey, - hash: Option - ) -> Result>; + ) -> FutureResult>; /// Returns the size of a child storage entry at a block's state. - #[rpc(name = "state_getChildStorageSize")] fn child_storage_size( &self, + block: Option, child_storage_key: StorageKey, key: StorageKey, - hash: Option - ) -> Result>; + ) -> FutureResult> { + Box::new(self.child_storage(block, child_storage_key, key) + .map(|x| x.map(|x| x.0.len() as u64))) + } /// Returns the runtime metadata as an opaque blob. - #[rpc(name = "state_getMetadata")] - fn metadata(&self, hash: Option) -> Result; + fn metadata(&self, block: Option) -> FutureResult; /// Get the runtime version. - #[rpc(name = "state_getRuntimeVersion", alias("chain_getRuntimeVersion"))] - fn runtime_version(&self, hash: Option) -> Result; + fn runtime_version(&self, block: Option) -> FutureResult; /// Query historical storage entries (by key) starting from a block given as the second parameter. /// /// NOTE This first returned result contains the initial state of storage for all keys. /// Subsequent values in the vector represent changes to the previous state (diffs). - #[rpc(name = "state_queryStorage")] fn query_storage( &self, + from: Block::Hash, + to: Option, keys: Vec, - block: Hash, - hash: Option - ) -> Result>>; + ) -> FutureResult>>; /// New runtime version subscription - #[pubsub( - subscription = "state_runtimeVersion", - subscribe, - name = "state_subscribeRuntimeVersion", - alias("chain_subscribeRuntimeVersion") - )] - fn subscribe_runtime_version(&self, metadata: Self::Metadata, subscriber: Subscriber); + fn subscribe_runtime_version( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber, + ); /// Unsubscribe from runtime version subscription - #[pubsub( - subscription = "state_runtimeVersion", - unsubscribe, - name = "state_unsubscribeRuntimeVersion", - alias("chain_unsubscribeRuntimeVersion") - )] - fn unsubscribe_runtime_version(&self, metadata: Option, id: SubscriptionId) -> RpcResult; + fn unsubscribe_runtime_version( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult; /// New storage subscription - #[pubsub(subscription = "state_storage", subscribe, name = "state_subscribeStorage")] fn subscribe_storage( - &self, metadata: Self::Metadata, subscriber: Subscriber>, keys: Option> + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber>, + keys: Option>, ); /// Unsubscribe from storage subscription - #[pubsub(subscription = "state_storage", unsubscribe, name = "state_unsubscribeStorage")] fn unsubscribe_storage( - &self, metadata: Option, id: SubscriptionId + &self, + _meta: Option, + id: SubscriptionId, ) -> RpcResult; } -/// State API with subscriptions support. -pub struct State { - /// Substrate client. +/// Create new state API that works on full node. +pub fn new_full( client: Arc>, - /// Current subscriptions. subscriptions: Subscriptions, +) -> State + where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: Metadata, +{ + State { + backend: Box::new(self::state_full::FullState::new(client, subscriptions)), + } } -/// Ranges to query in state_queryStorage. -struct QueryStorageRange { - /// Hashes of all the blocks in the range. - pub hashes: Vec, - /// Number of the first block in the range. - pub first_number: NumberFor, - /// Blocks subrange ([begin; end) indices within `hashes`) where we should read keys at - /// each state to get changes. - pub unfiltered_range: Range, - /// Blocks subrange ([begin; end) indices within `hashes`) where we could pre-filter - /// blocks-with-changes by using changes tries. - pub filtered_range: Option>, -} - -impl State where - Block: BlockT, - B: client::backend::Backend, - E: CallExecutor, +/// Create new state API that works on light node. +pub fn new_light>( + client: Arc>, + subscriptions: Subscriptions, + remote_blockchain: Arc>, + fetcher: Arc, +) -> State + where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + F: Send + Sync + 'static, { - /// Create new State API RPC handler. - pub fn new(client: Arc>, subscriptions: Subscriptions) -> Self { - Self { + State { + backend: Box::new(self::state_light::LightState::new( client, subscriptions, - } - } - - /// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges. - /// Blocks that contain changes within filtered subrange could be filtered using changes tries. - /// Blocks that contain changes within unfiltered subrange must be filtered manually. - fn split_query_storage_range( - &self, - from: Block::Hash, - to: Option - ) -> Result> { - let to = self.unwrap_or_best(to)?; - let from_hdr = self.client.header(&BlockId::hash(from))?; - let to_hdr = self.client.header(&BlockId::hash(to))?; - match (from_hdr, to_hdr) { - (Some(ref from), Some(ref to)) if from.number() <= to.number() => { - // check if we can get from `to` to `from` by going through parent_hashes. - let from_number = *from.number(); - let blocks = { - let mut blocks = vec![to.hash()]; - let mut last = to.clone(); - while *last.number() > from_number { - if let Some(hdr) = self.client.header(&BlockId::hash(*last.parent_hash()))? { - blocks.push(hdr.hash()); - last = hdr; - } else { - return Err(invalid_block_range( - Some(from), - Some(to), - format!("Parent of {} ({}) not found", last.number(), last.hash()), - )) - } - } - if last.hash() != from.hash() { - return Err(invalid_block_range( - Some(from), - Some(to), - format!("Expected to reach `from`, got {} ({})", last.number(), last.hash()), - )) - } - blocks.reverse(); - blocks - }; - // check if we can filter blocks-with-changes from some (sub)range using changes tries - let changes_trie_range = self.client.max_key_changes_range(from_number, BlockId::Hash(to.hash()))?; - let filtered_range_begin = changes_trie_range.map(|(begin, _)| (begin - from_number).saturated_into::()); - let (unfiltered_range, filtered_range) = split_range(blocks.len(), filtered_range_begin); - Ok(QueryStorageRange { - hashes: blocks, - first_number: from_number, - unfiltered_range, - filtered_range, - }) - }, - (from, to) => Err( - invalid_block_range(from.as_ref(), to.as_ref(), "Invalid range or unknown block".into()) - ), - } - } - - /// Iterates through range.unfiltered_range and check each block for changes of keys' values. - fn query_storage_unfiltered( - &self, - range: &QueryStorageRange, - keys: &[StorageKey], - last_values: &mut HashMap>, - changes: &mut Vec>, - ) -> Result<()> { - for block in range.unfiltered_range.start..range.unfiltered_range.end { - let block_hash = range.hashes[block].clone(); - let mut block_changes = StorageChangeSet { block: block_hash.clone(), changes: Vec::new() }; - let id = BlockId::hash(block_hash); - for key in keys { - let (has_changed, data) = { - let curr_data = self.client.storage(&id, key)?; - match last_values.get(key) { - Some(prev_data) => (curr_data != *prev_data, curr_data), - None => (true, curr_data), - } - }; - if has_changed { - block_changes.changes.push((key.clone(), data.clone())); - } - last_values.insert(key.clone(), data); - } - if !block_changes.changes.is_empty() { - changes.push(block_changes); - } - } - Ok(()) - } - - /// Iterates through all blocks that are changing keys within range.filtered_range and collects these changes. - fn query_storage_filtered( - &self, - range: &QueryStorageRange, - keys: &[StorageKey], - last_values: &HashMap>, - changes: &mut Vec>, - ) -> Result<()> { - let (begin, end) = match range.filtered_range { - Some(ref filtered_range) => ( - range.first_number + filtered_range.start.saturated_into(), - BlockId::Hash(range.hashes[filtered_range.end - 1].clone()) - ), - None => return Ok(()), - }; - let mut changes_map: BTreeMap, StorageChangeSet> = BTreeMap::new(); - for key in keys { - let mut last_block = None; - let mut last_value = last_values.get(key).cloned().unwrap_or_default(); - for (block, _) in self.client.key_changes(begin, end, key)?.into_iter().rev() { - if last_block == Some(block) { - continue; - } - - let block_hash = range.hashes[(block - range.first_number).saturated_into::()].clone(); - let id = BlockId::Hash(block_hash); - let value_at_block = self.client.storage(&id, key)?; - if last_value == value_at_block { - continue; - } - - changes_map.entry(block) - .or_insert_with(|| StorageChangeSet { block: block_hash, changes: Vec::new() }) - .changes.push((key.clone(), value_at_block.clone())); - last_block = Some(block); - last_value = value_at_block; - } - } - if let Some(additional_capacity) = changes_map.len().checked_sub(changes.len()) { - changes.reserve(additional_capacity); - } - changes.extend(changes_map.into_iter().map(|(_, cs)| cs)); - Ok(()) + remote_blockchain, + fetcher, + )), } } -impl State where - Block: BlockT, - B: client::backend::Backend, - E: CallExecutor, -{ - fn unwrap_or_best(&self, hash: Option) -> Result { - crate::helpers::unwrap_or_else(|| Ok(self.client.info().chain.best_hash), hash) - } +/// State API with subscriptions support. +pub struct State { + backend: Box>, } -impl StateApi for State where - Block: BlockT + 'static, - B: client::backend::Backend + Send + Sync + 'static, - E: CallExecutor + Send + Sync + 'static + Clone, - RA: Send + Sync + 'static, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: Metadata +impl StateApi for State + where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, { type Metadata = crate::metadata::Metadata; - fn call(&self, method: String, data: Bytes, block: Option) -> Result { - let block = self.unwrap_or_best(block)?; - trace!(target: "rpc", "Calling runtime at {:?} for method {} ({})", block, method, HexDisplay::from(&data.0)); - let return_data = self.client - .executor() - .call( - &BlockId::Hash(block), - &method, &data.0, ExecutionStrategy::NativeElseWasm, state_machine::NeverOffchainExt::new(), - )?; - Ok(Bytes(return_data)) + fn call(&self, method: String, data: Bytes, block: Option) -> FutureResult { + self.backend.call(block, method, data) } - fn storage_keys(&self, key_prefix: StorageKey, block: Option) -> Result> { - let block = self.unwrap_or_best(block)?; - trace!(target: "rpc", "Querying storage keys at {:?}", block); - Ok(self.client.storage_keys(&BlockId::Hash(block), &key_prefix)?) + fn storage_keys( + &self, + key_prefix: StorageKey, + block: Option, + ) -> FutureResult> { + self.backend.storage_keys(block, key_prefix) } - fn storage(&self, key: StorageKey, block: Option) -> Result> { - let block = self.unwrap_or_best(block)?; - trace!(target: "rpc", "Querying storage at {:?} for key {}", block, HexDisplay::from(&key.0)); - Ok(self.client.storage(&BlockId::Hash(block), &key)?) + fn storage(&self, key: StorageKey, block: Option) -> FutureResult> { + self.backend.storage(block, key) } - fn storage_hash(&self, key: StorageKey, block: Option) -> Result> { - let block = self.unwrap_or_best(block)?; - trace!(target: "rpc", "Querying storage hash at {:?} for key {}", block, HexDisplay::from(&key.0)); - Ok(self.client.storage_hash(&BlockId::Hash(block), &key)?) + fn storage_hash(&self, key: StorageKey, block: Option) -> FutureResult> { + self.backend.storage_hash(block, key) } - fn storage_size(&self, key: StorageKey, block: Option) -> Result> { - Ok(self.storage(key, block)?.map(|x| x.0.len() as u64)) + fn storage_size(&self, key: StorageKey, block: Option) -> FutureResult> { + self.backend.storage_size(block, key) } fn child_storage( @@ -391,10 +262,8 @@ impl StateApi for State where child_storage_key: StorageKey, key: StorageKey, block: Option - ) -> Result> { - let block = self.unwrap_or_best(block)?; - trace!(target: "rpc", "Querying child storage at {:?} for key {}", block, HexDisplay::from(&key.0)); - Ok(self.client.child_storage(&BlockId::Hash(block), &child_storage_key, &key)?) + ) -> FutureResult> { + self.backend.child_storage(block, child_storage_key, key) } fn child_storage_keys( @@ -402,10 +271,8 @@ impl StateApi for State where child_storage_key: StorageKey, key_prefix: StorageKey, block: Option - ) -> Result> { - let block = self.unwrap_or_best(block)?; - trace!(target: "rpc", "Querying child storage keys at {:?}", block); - Ok(self.client.child_storage_keys(&BlockId::Hash(block), &child_storage_key, &key_prefix)?) + ) -> FutureResult> { + self.backend.child_storage_keys(block, child_storage_key, key_prefix) } fn child_storage_hash( @@ -413,14 +280,8 @@ impl StateApi for State where child_storage_key: StorageKey, key: StorageKey, block: Option - ) -> Result> { - let block = self.unwrap_or_best(block)?; - trace!( - target: "rpc", "Querying child storage hash at {:?} for key {}", - block, - HexDisplay::from(&key.0), - ); - Ok(self.client.child_storage_hash(&BlockId::Hash(block), &child_storage_key, &key)?) + ) -> FutureResult> { + self.backend.child_storage_hash(block, child_storage_key, key) } fn child_storage_size( @@ -428,13 +289,12 @@ impl StateApi for State where child_storage_key: StorageKey, key: StorageKey, block: Option - ) -> Result> { - Ok(self.child_storage(child_storage_key, key, block)?.map(|x| x.0.len() as u64)) + ) -> FutureResult> { + self.backend.child_storage_size(block, child_storage_key, key) } - fn metadata(&self, block: Option) -> Result { - let block = self.unwrap_or_best(block)?; - self.client.runtime_api().metadata(&BlockId::Hash(block)).map(Into::into).map_err(Into::into) + fn metadata(&self, block: Option) -> FutureResult { + self.backend.metadata(block) } fn query_storage( @@ -442,156 +302,40 @@ impl StateApi for State where keys: Vec, from: Block::Hash, to: Option - ) -> Result>> { - let range = self.split_query_storage_range(from, to)?; - let mut changes = Vec::new(); - let mut last_values = HashMap::new(); - self.query_storage_unfiltered(&range, &keys, &mut last_values, &mut changes)?; - self.query_storage_filtered(&range, &keys, &last_values, &mut changes)?; - Ok(changes) + ) -> FutureResult>> { + self.backend.query_storage(from, to, keys) } fn subscribe_storage( &self, - _meta: Self::Metadata, + meta: Self::Metadata, subscriber: Subscriber>, keys: Option> ) { - let keys = Into::>>::into(keys); - let stream = match self.client.storage_changes_notification_stream( - keys.as_ref().map(|x| &**x), - None - ) { - Ok(stream) => stream, - Err(err) => { - let _ = subscriber.reject(error::Error::from(err).into()); - return; - }, - }; - - // initial values - let initial = stream::iter_result(keys - .map(|keys| { - let block = self.client.info().chain.best_hash; - let changes = keys - .into_iter() - .map(|key| self.storage(key.clone(), Some(block.clone()).into()) - .map(|val| (key.clone(), val)) - .unwrap_or_else(|_| (key, None)) - ) - .collect(); - vec![Ok(Ok(StorageChangeSet { block, changes }))] - }).unwrap_or_default()); - - self.subscriptions.add(subscriber, |sink| { - let stream = stream - .map(|(block, changes)| Ok::<_, ()>(Ok(StorageChangeSet { - block, - changes: changes.iter() - .filter_map(|(o_sk, k, v)| if o_sk.is_none() { - Some((k.clone(),v.cloned())) - } else { None }).collect(), - }))) - .compat(); - - sink - .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all(initial.chain(stream)) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }) + self.backend.subscribe_storage(meta, subscriber, keys); } - fn unsubscribe_storage(&self, _meta: Option, id: SubscriptionId) -> RpcResult { - Ok(self.subscriptions.cancel(id)) + fn unsubscribe_storage(&self, meta: Option, id: SubscriptionId) -> RpcResult { + self.backend.unsubscribe_storage(meta, id) } - fn runtime_version(&self, at: Option) -> Result { - let at = self.unwrap_or_best(at)?; - Ok(self.client.runtime_version_at(&BlockId::Hash(at))?) + fn runtime_version(&self, at: Option) -> FutureResult { + self.backend.runtime_version(at) } - fn subscribe_runtime_version(&self, _meta: Self::Metadata, subscriber: Subscriber) { - let stream = match self.client.storage_changes_notification_stream( - Some(&[StorageKey(storage::well_known_keys::CODE.to_vec())]), - None, - ) { - Ok(stream) => stream, - Err(err) => { - let _ = subscriber.reject(error::Error::from(err).into()); - return; - } - }; - - self.subscriptions.add(subscriber, |sink| { - let version = self.runtime_version(None.into()) - .map_err(Into::into); - - let client = self.client.clone(); - let mut previous_version = version.clone(); - - let stream = stream - .filter_map(move |_| { - let info = client.info(); - let version = client - .runtime_version_at(&BlockId::hash(info.chain.best_hash)) - .map_err(error::Error::from) - .map_err(Into::into); - if previous_version != version { - previous_version = version.clone(); - future::ready(Some(Ok::<_, ()>(version))) - } else { - future::ready(None) - } - }) - .compat(); - - sink - .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all( - stream::iter_result(vec![Ok(version)]) - .chain(stream) - ) - // we ignore the resulting Stream (if the first stream is over we are unsubscribed) - .map(|_| ()) - }); + fn subscribe_runtime_version(&self, meta: Self::Metadata, subscriber: Subscriber) { + self.backend.subscribe_runtime_version(meta, subscriber); } - fn unsubscribe_runtime_version(&self, _meta: Option, id: SubscriptionId) -> RpcResult { - Ok(self.subscriptions.cancel(id)) + fn unsubscribe_runtime_version( + &self, + meta: Option, + id: SubscriptionId, + ) -> RpcResult { + self.backend.unsubscribe_runtime_version(meta, id) } } -/// Splits passed range into two subranges where: -/// - first range has at least one element in it; -/// - second range (optionally) starts at given `middle` element. -pub(crate) fn split_range(size: usize, middle: Option) -> (Range, Option>) { - // check if we can filter blocks-with-changes from some (sub)range using changes tries - let range2_begin = match middle { - // some of required changes tries are pruned => use available tries - Some(middle) if middle != 0 => Some(middle), - // all required changes tries are available, but we still want values at first block - // => do 'unfiltered' read for the first block and 'filtered' for the rest - Some(_) if size > 1 => Some(1), - // range contains single element => do not use changes tries - Some(_) => None, - // changes tries are not available => do 'unfiltered' read for the whole range - None => None, - }; - let range1 = 0..range2_begin.unwrap_or(size); - let range2 = range2_begin.map(|begin| begin..size); - (range1, range2) -} - -fn invalid_block_range(from: Option<&H>, to: Option<&H>, reason: String) -> error::Error { - let to_string = |x: Option<&H>| match x { - None => "unknown hash".into(), - Some(h) => format!("{} ({})", h.number(), h.hash()), - }; - - error::Error::InvalidBlockRange { - from: to_string(from), - to: to_string(to), - details: reason, - } +fn client_err(err: client::error::Error) -> Error { + Error::Client(Box::new(err)) } diff --git a/core/rpc/src/state/state_full.rs b/core/rpc/src/state/state_full.rs new file mode 100644 index 0000000000000000000000000000000000000000..ff4c5e5599a8a23af4cc9940f3ecc844d92620fd --- /dev/null +++ b/core/rpc/src/state/state_full.rs @@ -0,0 +1,509 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! State API backend for full nodes. + +use std::collections::{BTreeMap, HashMap}; +use std::sync::Arc; +use std::ops::Range; +use futures03::{future, StreamExt as _, TryStreamExt as _}; +use log::warn; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use rpc::{ + Result as RpcResult, + futures::{stream, Future, Sink, Stream, future::result}, +}; + +use api::Subscriptions; +use client::{ + Client, CallExecutor, BlockchainEvents, runtime_api::Metadata, + backend::Backend, error::Result as ClientResult, +}; +use primitives::{ + H256, Blake2Hasher, Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet}, +}; +use runtime_version::RuntimeVersion; +use state_machine::ExecutionStrategy; +use sr_primitives::{ + generic::BlockId, + traits::{Block as BlockT, Header, NumberFor, ProvideRuntimeApi, SaturatedConversion}, +}; + +use super::{StateBackend, error::{FutureResult, Error, Result}, client_err}; + +/// Ranges to query in state_queryStorage. +struct QueryStorageRange { + /// Hashes of all the blocks in the range. + pub hashes: Vec, + /// Number of the first block in the range. + pub first_number: NumberFor, + /// Blocks subrange ([begin; end) indices within `hashes`) where we should read keys at + /// each state to get changes. + pub unfiltered_range: Range, + /// Blocks subrange ([begin; end) indices within `hashes`) where we could pre-filter + /// blocks-with-changes by using changes tries. + pub filtered_range: Option>, +} + +/// State API backend for full nodes. +pub struct FullState { + client: Arc>, + subscriptions: Subscriptions, +} + +impl FullState + where + Block: BlockT + 'static, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, +{ + /// Create new state API backend for full nodes. + pub fn new(client: Arc>, subscriptions: Subscriptions) -> Self { + Self { client, subscriptions } + } + + /// Returns given block hash or best block hash if None is passed. + fn block_or_best(&self, hash: Option) -> ClientResult { + Ok(hash.unwrap_or_else(|| self.client.info().chain.best_hash)) + } + + /// Splits the `query_storage` block range into 'filtered' and 'unfiltered' subranges. + /// Blocks that contain changes within filtered subrange could be filtered using changes tries. + /// Blocks that contain changes within unfiltered subrange must be filtered manually. + fn split_query_storage_range( + &self, + from: Block::Hash, + to: Option + ) -> Result> { + let to = self.block_or_best(to).map_err(client_err)?; + let from_hdr = self.client.header(&BlockId::hash(from)).map_err(client_err)?; + let to_hdr = self.client.header(&BlockId::hash(to)).map_err(client_err)?; + match (from_hdr, to_hdr) { + (Some(ref from), Some(ref to)) if from.number() <= to.number() => { + // check if we can get from `to` to `from` by going through parent_hashes. + let from_number = *from.number(); + let blocks = { + let mut blocks = vec![to.hash()]; + let mut last = to.clone(); + while *last.number() > from_number { + let hdr = self.client + .header(&BlockId::hash(*last.parent_hash())) + .map_err(client_err)?; + if let Some(hdr) = hdr { + blocks.push(hdr.hash()); + last = hdr; + } else { + return Err(invalid_block_range( + Some(from), + Some(to), + format!("Parent of {} ({}) not found", last.number(), last.hash()), + )) + } + } + if last.hash() != from.hash() { + return Err(invalid_block_range( + Some(from), + Some(to), + format!("Expected to reach `from`, got {} ({})", last.number(), last.hash()), + )) + } + blocks.reverse(); + blocks + }; + // check if we can filter blocks-with-changes from some (sub)range using changes tries + let changes_trie_range = self.client + .max_key_changes_range(from_number, BlockId::Hash(to.hash())) + .map_err(client_err)?; + let filtered_range_begin = changes_trie_range + .map(|(begin, _)| (begin - from_number).saturated_into::()); + let (unfiltered_range, filtered_range) = split_range(blocks.len(), filtered_range_begin); + Ok(QueryStorageRange { + hashes: blocks, + first_number: from_number, + unfiltered_range, + filtered_range, + }) + }, + (from, to) => Err( + invalid_block_range(from.as_ref(), to.as_ref(), "Invalid range or unknown block".into()) + ), + } + } + + /// Iterates through range.unfiltered_range and check each block for changes of keys' values. + fn query_storage_unfiltered( + &self, + range: &QueryStorageRange, + keys: &[StorageKey], + last_values: &mut HashMap>, + changes: &mut Vec>, + ) -> Result<()> { + for block in range.unfiltered_range.start..range.unfiltered_range.end { + let block_hash = range.hashes[block].clone(); + let mut block_changes = StorageChangeSet { block: block_hash.clone(), changes: Vec::new() }; + let id = BlockId::hash(block_hash); + for key in keys { + let (has_changed, data) = { + let curr_data = self.client.storage(&id, key).map_err(client_err)?; + match last_values.get(key) { + Some(prev_data) => (curr_data != *prev_data, curr_data), + None => (true, curr_data), + } + }; + if has_changed { + block_changes.changes.push((key.clone(), data.clone())); + } + last_values.insert(key.clone(), data); + } + if !block_changes.changes.is_empty() { + changes.push(block_changes); + } + } + Ok(()) + } + + /// Iterates through all blocks that are changing keys within range.filtered_range and collects these changes. + fn query_storage_filtered( + &self, + range: &QueryStorageRange, + keys: &[StorageKey], + last_values: &HashMap>, + changes: &mut Vec>, + ) -> Result<()> { + let (begin, end) = match range.filtered_range { + Some(ref filtered_range) => ( + range.first_number + filtered_range.start.saturated_into(), + BlockId::Hash(range.hashes[filtered_range.end - 1].clone()) + ), + None => return Ok(()), + }; + let mut changes_map: BTreeMap, StorageChangeSet> = BTreeMap::new(); + for key in keys { + let mut last_block = None; + let mut last_value = last_values.get(key).cloned().unwrap_or_default(); + let key_changes = self.client.key_changes(begin, end, None, key).map_err(client_err)?; + for (block, _) in key_changes.into_iter().rev() { + if last_block == Some(block) { + continue; + } + + let block_hash = range.hashes[(block - range.first_number).saturated_into::()].clone(); + let id = BlockId::Hash(block_hash); + let value_at_block = self.client.storage(&id, key).map_err(client_err)?; + if last_value == value_at_block { + continue; + } + + changes_map.entry(block) + .or_insert_with(|| StorageChangeSet { block: block_hash, changes: Vec::new() }) + .changes.push((key.clone(), value_at_block.clone())); + last_block = Some(block); + last_value = value_at_block; + } + } + if let Some(additional_capacity) = changes_map.len().checked_sub(changes.len()) { + changes.reserve(additional_capacity); + } + changes.extend(changes_map.into_iter().map(|(_, cs)| cs)); + Ok(()) + } +} + +impl StateBackend for FullState + where + Block: BlockT + 'static, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: Metadata, +{ + fn call( + &self, + block: Option, + method: String, + call_data: Bytes, + ) -> FutureResult { + Box::new(result( + self.block_or_best(block) + .and_then(|block| + self + .client + .executor() + .call( + &BlockId::Hash(block), + &method, + &*call_data, + ExecutionStrategy::NativeElseWasm, + None, + ) + .map(Into::into)) + .map_err(client_err))) + } + + fn storage_keys( + &self, + block: Option, + prefix: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.storage_keys(&BlockId::Hash(block), &prefix)) + .map_err(client_err))) + } + + fn storage( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.storage(&BlockId::Hash(block), &key)) + .map_err(client_err))) + } + + fn storage_hash( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.storage_hash(&BlockId::Hash(block), &key)) + .map_err(client_err))) + } + + fn child_storage_keys( + &self, + block: Option, + child_storage_key: StorageKey, + prefix: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.child_storage_keys(&BlockId::Hash(block), &child_storage_key, &prefix)) + .map_err(client_err))) + } + + fn child_storage( + &self, + block: Option, + child_storage_key: StorageKey, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.child_storage(&BlockId::Hash(block), &child_storage_key, &key)) + .map_err(client_err))) + } + + fn child_storage_hash( + &self, + block: Option, + child_storage_key: StorageKey, + key: StorageKey, + ) -> FutureResult> { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.child_storage_hash(&BlockId::Hash(block), &child_storage_key, &key)) + .map_err(client_err))) + } + + fn metadata(&self, block: Option) -> FutureResult { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.runtime_api().metadata(&BlockId::Hash(block)).map(Into::into)) + .map_err(client_err))) + } + + fn runtime_version(&self, block: Option) -> FutureResult { + Box::new(result( + self.block_or_best(block) + .and_then(|block| self.client.runtime_version_at(&BlockId::Hash(block))) + .map_err(client_err))) + } + + fn query_storage( + &self, + from: Block::Hash, + to: Option, + keys: Vec, + ) -> FutureResult>> { + let call_fn = move || { + let range = self.split_query_storage_range(from, to)?; + let mut changes = Vec::new(); + let mut last_values = HashMap::new(); + self.query_storage_unfiltered(&range, &keys, &mut last_values, &mut changes)?; + self.query_storage_filtered(&range, &keys, &last_values, &mut changes)?; + Ok(changes) + }; + Box::new(result(call_fn())) + } + + fn subscribe_runtime_version( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber, + ) { + let stream = match self.client.storage_changes_notification_stream( + Some(&[StorageKey(well_known_keys::CODE.to_vec())]), + None, + ) { + Ok(stream) => stream, + Err(err) => { + let _ = subscriber.reject(Error::from(client_err(err)).into()); + return; + } + }; + + self.subscriptions.add(subscriber, |sink| { + let version = self.runtime_version(None.into()) + .map_err(Into::into) + .wait(); + + let client = self.client.clone(); + let mut previous_version = version.clone(); + + let stream = stream + .filter_map(move |_| { + let info = client.info(); + let version = client + .runtime_version_at(&BlockId::hash(info.chain.best_hash)) + .map_err(client_err) + .map_err(Into::into); + if previous_version != version { + previous_version = version.clone(); + future::ready(Some(Ok::<_, ()>(version))) + } else { + future::ready(None) + } + }) + .compat(); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all( + stream::iter_result(vec![Ok(version)]) + .chain(stream) + ) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); + } + + fn unsubscribe_runtime_version( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions.cancel(id)) + } + + fn subscribe_storage( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber>, + keys: Option>, + ) { + let keys = Into::>>::into(keys); + let stream = match self.client.storage_changes_notification_stream( + keys.as_ref().map(|x| &**x), + None + ) { + Ok(stream) => stream, + Err(err) => { + let _ = subscriber.reject(client_err(err).into()); + return; + }, + }; + + // initial values + let initial = stream::iter_result(keys + .map(|keys| { + let block = self.client.info().chain.best_hash; + let changes = keys + .into_iter() + .map(|key| self.storage(Some(block.clone()).into(), key.clone()) + .map(|val| (key.clone(), val)) + .wait() + .unwrap_or_else(|_| (key, None)) + ) + .collect(); + vec![Ok(Ok(StorageChangeSet { block, changes }))] + }).unwrap_or_default()); + + self.subscriptions.add(subscriber, |sink| { + let stream = stream + .map(|(block, changes)| Ok::<_, ()>(Ok(StorageChangeSet { + block, + changes: changes.iter() + .filter_map(|(o_sk, k, v)| if o_sk.is_none() { + Some((k.clone(),v.cloned())) + } else { None }).collect(), + }))) + .compat(); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all(initial.chain(stream)) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); + } + + fn unsubscribe_storage( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions.cancel(id)) + } +} + +/// Splits passed range into two subranges where: +/// - first range has at least one element in it; +/// - second range (optionally) starts at given `middle` element. +pub(crate) fn split_range(size: usize, middle: Option) -> (Range, Option>) { + // check if we can filter blocks-with-changes from some (sub)range using changes tries + let range2_begin = match middle { + // some of required changes tries are pruned => use available tries + Some(middle) if middle != 0 => Some(middle), + // all required changes tries are available, but we still want values at first block + // => do 'unfiltered' read for the first block and 'filtered' for the rest + Some(_) if size > 1 => Some(1), + // range contains single element => do not use changes tries + Some(_) => None, + // changes tries are not available => do 'unfiltered' read for the whole range + None => None, + }; + let range1 = 0..range2_begin.unwrap_or(size); + let range2 = range2_begin.map(|begin| begin..size); + (range1, range2) +} + +fn invalid_block_range(from: Option<&H>, to: Option<&H>, reason: String) -> Error { + let to_string = |x: Option<&H>| match x { + None => "unknown hash".into(), + Some(h) => format!("{} ({})", h.number(), h.hash()), + }; + + Error::InvalidBlockRange { + from: to_string(from), + to: to_string(to), + details: reason, + } +} diff --git a/core/rpc/src/state/state_light.rs b/core/rpc/src/state/state_light.rs new file mode 100644 index 0000000000000000000000000000000000000000..3d0c7979e39953a10c102dc729522ade010eb1c1 --- /dev/null +++ b/core/rpc/src/state/state_light.rs @@ -0,0 +1,784 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! State API backend for light nodes. + +use std::{ + sync::Arc, + collections::{HashSet, HashMap, hash_map::Entry}, +}; +use codec::Decode; +use futures03::{ + future::{ready, Either}, + channel::oneshot::{channel, Sender}, + FutureExt, TryFutureExt, + StreamExt as _, TryStreamExt as _, +}; +use hash_db::Hasher; +use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; +use log::warn; +use parking_lot::Mutex; +use rpc::{ + Result as RpcResult, + futures::Sink, + futures::future::{result, Future}, + futures::stream::Stream, +}; + +use api::Subscriptions; +use client::{ + BlockchainEvents, Client, CallExecutor, backend::Backend, + error::Error as ClientError, + light::{ + blockchain::{future_header, RemoteBlockchain}, + fetcher::{Fetcher, RemoteCallRequest, RemoteReadRequest, RemoteReadChildRequest}, + }, +}; +use primitives::{ + H256, Blake2Hasher, Bytes, OpaqueMetadata, + storage::{StorageKey, StorageData, StorageChangeSet}, +}; +use runtime_version::RuntimeVersion; +use sr_primitives::{ + generic::BlockId, + traits::Block as BlockT, +}; + +use super::{StateBackend, error::{FutureResult, Error}, client_err}; + +/// Storage data map of storage keys => (optional) storage value. +type StorageMap = HashMap>; + +/// State API backend for light nodes. +pub struct LightState, B, E, RA> { + client: Arc>, + subscriptions: Subscriptions, + version_subscriptions: SimpleSubscriptions, + storage_subscriptions: Arc>>, + remote_blockchain: Arc>, + fetcher: Arc, +} + +/// Shared requests container. +trait SharedRequests: Clone + Send + Sync { + /// Tries to listen for already issued request, or issues request. + /// + /// Returns true if requests has been issued. + fn listen_request( + &self, + block: Hash, + sender: Sender>, + ) -> bool; + + /// Returns (and forgets) all listeners for given request. + fn on_response_received(&self, block: Hash) -> Vec>>; +} + +/// Storage subscriptions data. +struct StorageSubscriptions { + /// Active storage requests. + active_requests: HashMap>>>, + /// Map of subscription => keys that this subscription watch for. + keys_by_subscription: HashMap>, + /// Map of key => set of subscriptions that watch this key. + subscriptions_by_key: HashMap>, +} + +impl SharedRequests for Arc>> { + fn listen_request( + &self, + block: Block::Hash, + sender: Sender>, + ) -> bool { + let mut subscriptions = self.lock(); + let active_requests_at = subscriptions.active_requests.entry(block).or_default(); + active_requests_at.push(sender); + active_requests_at.len() == 1 + } + + fn on_response_received(&self, block: Block::Hash) -> Vec>> { + self.lock().active_requests.remove(&block).unwrap_or_default() + } +} + +/// Simple, maybe shared, subscription data that shares per block requests. +type SimpleSubscriptions = Arc>>>>>; + +impl SharedRequests for SimpleSubscriptions where + Hash: Send + Eq + std::hash::Hash, + V: Send, +{ + fn listen_request( + &self, + block: Hash, + sender: Sender>, + ) -> bool { + let mut subscriptions = self.lock(); + let active_requests_at = subscriptions.entry(block).or_default(); + active_requests_at.push(sender); + active_requests_at.len() == 1 + } + + fn on_response_received(&self, block: Hash) -> Vec>> { + self.lock().remove(&block).unwrap_or_default() + } +} + +impl + 'static, B, E, RA> LightState + where + Block: BlockT, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, +{ + /// Create new state API backend for light nodes. + pub fn new( + client: Arc>, + subscriptions: Subscriptions, + remote_blockchain: Arc>, + fetcher: Arc, + ) -> Self { + Self { + client, + subscriptions, + version_subscriptions: Arc::new(Mutex::new(HashMap::new())), + storage_subscriptions: Arc::new(Mutex::new(StorageSubscriptions { + active_requests: HashMap::new(), + keys_by_subscription: HashMap::new(), + subscriptions_by_key: HashMap::new(), + })), + remote_blockchain, + fetcher, + } + } + + /// Returns given block hash or best block hash if None is passed. + fn block_or_best(&self, hash: Option) -> Block::Hash { + hash.unwrap_or_else(|| self.client.info().chain.best_hash) + } +} + +impl StateBackend for LightState + where + Block: BlockT, + B: Backend + Send + Sync + 'static, + E: CallExecutor + Send + Sync + 'static + Clone, + RA: Send + Sync + 'static, + F: Fetcher + 'static +{ + fn call( + &self, + block: Option, + method: String, + call_data: Bytes, + ) -> FutureResult { + Box::new(call( + &*self.remote_blockchain, + self.fetcher.clone(), + self.block_or_best(block), + method, + call_data, + ).boxed().compat()) + } + + fn storage_keys( + &self, + _block: Option, + _prefix: StorageKey, + ) -> FutureResult> { + Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient)))) + } + + fn storage( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(storage( + &*self.remote_blockchain, + self.fetcher.clone(), + self.block_or_best(block), + vec![key.0.clone()], + ).boxed().compat().map(move |mut values| values + .remove(&key) + .expect("successful request has entries for all requested keys; qed") + )) + } + + fn storage_hash( + &self, + block: Option, + key: StorageKey, + ) -> FutureResult> { + Box::new(self + .storage(block, key) + .and_then(|maybe_storage| + result(Ok(maybe_storage.map(|storage| Blake2Hasher::hash(&storage.0)))) + ) + ) + } + + fn child_storage_keys( + &self, + _block: Option, + _child_storage_key: StorageKey, + _prefix: StorageKey, + ) -> FutureResult> { + Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient)))) + } + + fn child_storage( + &self, + block: Option, + child_storage_key: StorageKey, + key: StorageKey, + ) -> FutureResult> { + let block = self.block_or_best(block); + let fetcher = self.fetcher.clone(); + let child_storage = resolve_header(&*self.remote_blockchain, &*self.fetcher, block) + .then(move |result| match result { + Ok(header) => Either::Left(fetcher.remote_read_child(RemoteReadChildRequest { + block, + header, + storage_key: child_storage_key.0, + keys: vec![key.0.clone()], + retry_count: Default::default(), + }).then(move |result| ready(result + .map(|mut data| data + .remove(&key.0) + .expect("successful result has entry for all keys; qed") + .map(StorageData) + ) + .map_err(client_err) + ))), + Err(error) => Either::Right(ready(Err(error))), + }); + + Box::new(child_storage.boxed().compat()) + } + + fn child_storage_hash( + &self, + block: Option, + child_storage_key: StorageKey, + key: StorageKey, + ) -> FutureResult> { + Box::new(self + .child_storage(block, child_storage_key, key) + .and_then(|maybe_storage| + result(Ok(maybe_storage.map(|storage| Blake2Hasher::hash(&storage.0)))) + ) + ) + } + + fn metadata(&self, block: Option) -> FutureResult { + let metadata = self.call(block, "Metadata_metadata".into(), Bytes(Vec::new())) + .and_then(|metadata| OpaqueMetadata::decode(&mut &metadata.0[..]) + .map(Into::into) + .map_err(|decode_err| client_err(ClientError::CallResultDecode( + "Unable to decode metadata", + decode_err, + )))); + + Box::new(metadata) + } + + fn runtime_version(&self, block: Option) -> FutureResult { + Box::new(runtime_version( + &*self.remote_blockchain, + self.fetcher.clone(), + self.block_or_best(block), + ).boxed().compat()) + } + + fn query_storage( + &self, + _from: Block::Hash, + _to: Option, + _keys: Vec, + ) -> FutureResult>> { + Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient)))) + } + + fn subscribe_storage( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber>, + keys: Option> + ) { + let keys = match keys { + Some(keys) => keys, + None => { + warn!("Cannot subscribe to all keys on light client. Subscription rejected."); + return; + } + }; + + let keys = keys.iter().cloned().collect::>(); + let keys_to_check = keys.iter().map(|k| k.0.clone()).collect::>(); + let subscription_id = self.subscriptions.add(subscriber, move |sink| { + let fetcher = self.fetcher.clone(); + let remote_blockchain = self.remote_blockchain.clone(); + let storage_subscriptions = self.storage_subscriptions.clone(); + let initial_block = self.block_or_best(None); + let initial_keys = keys_to_check.iter().cloned().collect::>(); + + let changes_stream = subscription_stream::( + storage_subscriptions.clone(), + self.client + .import_notification_stream() + .map(|notification| Ok::<_, ()>(notification.hash)) + .compat(), + display_error(storage( + &*remote_blockchain, + fetcher.clone(), + initial_block, + initial_keys, + ).map(move |r| r.map(|r| (initial_block, r)))), + move |block| { + // there'll be single request per block for all active subscriptions + // with all subscribed keys + let keys = storage_subscriptions + .lock() + .subscriptions_by_key + .keys() + .map(|k| k.0.clone()) + .collect(); + + storage( + &*remote_blockchain, + fetcher.clone(), + block, + keys, + ) + }, + move |block, old_value, new_value| { + // let's only select keys which are valid for this subscription + let new_value = new_value + .iter() + .filter(|(k, _)| keys_to_check.contains(&k.0)) + .map(|(k, v)| (k.clone(), v.clone())) + .collect::>(); + let value_differs = old_value + .as_ref() + .map(|old_value| **old_value != new_value) + .unwrap_or(true); + match value_differs { + true => Some(StorageChangeSet { + block, + changes: new_value + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(), + }), + false => None, + } + } + ); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all(changes_stream.map(|changes| Ok(changes))) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); + + // remember keys associated with this subscription + let mut storage_subscriptions = self.storage_subscriptions.lock(); + storage_subscriptions.keys_by_subscription.insert(subscription_id.clone(), keys.clone()); + for key in keys { + storage_subscriptions + .subscriptions_by_key + .entry(key) + .or_default() + .insert(subscription_id.clone()); + } + } + + fn unsubscribe_storage( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult { + if !self.subscriptions.cancel(id.clone()) { + return Ok(false); + } + + // forget subscription keys + let mut storage_subscriptions = self.storage_subscriptions.lock(); + let keys = storage_subscriptions.keys_by_subscription.remove(&id); + for key in keys.into_iter().flat_map(|keys| keys.into_iter()) { + match storage_subscriptions.subscriptions_by_key.entry(key) { + Entry::Vacant(_) => unreachable!("every key from keys_by_subscription has\ + corresponding entry in subscriptions_by_key; qed"), + Entry::Occupied(mut entry) => { + entry.get_mut().remove(&id); + if entry.get().is_empty() { + entry.remove(); + } + } + } + } + + Ok(true) + } + + fn subscribe_runtime_version( + &self, + _meta: crate::metadata::Metadata, + subscriber: Subscriber, + ) { + self.subscriptions.add(subscriber, move |sink| { + let fetcher = self.fetcher.clone(); + let remote_blockchain = self.remote_blockchain.clone(); + let version_subscriptions = self.version_subscriptions.clone(); + let initial_block = self.block_or_best(None); + + let versions_stream = subscription_stream::( + version_subscriptions, + self.client + .import_notification_stream() + .map(|notification| Ok::<_, ()>(notification.hash)) + .compat(), + display_error(runtime_version( + &*remote_blockchain, + fetcher.clone(), + initial_block, + ).map(move |r| r.map(|r| (initial_block, r)))), + move |block| runtime_version( + &*remote_blockchain, + fetcher.clone(), + block, + ), + |_, old_version, new_version| { + let version_differs = old_version + .as_ref() + .map(|old_version| *old_version != new_version) + .unwrap_or(true); + match version_differs { + true => Some(new_version.clone()), + false => None, + } + } + ); + + sink + .sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all(versions_stream.map(|version| Ok(version))) + // we ignore the resulting Stream (if the first stream is over we are unsubscribed) + .map(|_| ()) + }); + } + + fn unsubscribe_runtime_version( + &self, + _meta: Option, + id: SubscriptionId, + ) -> RpcResult { + Ok(self.subscriptions.cancel(id)) + } +} + +/// Resolve header by hash. +fn resolve_header>( + remote_blockchain: &dyn RemoteBlockchain, + fetcher: &F, + block: Block::Hash, +) -> impl std::future::Future> { + let maybe_header = future_header( + remote_blockchain, + fetcher, + BlockId::Hash(block), + ); + + maybe_header.then(move |result| + ready(result.and_then(|maybe_header| + maybe_header.ok_or(ClientError::UnknownBlock(format!("{}", block))) + ).map_err(client_err)), + ) +} + +/// Call runtime method at given block +fn call>( + remote_blockchain: &dyn RemoteBlockchain, + fetcher: Arc, + block: Block::Hash, + method: String, + call_data: Bytes, +) -> impl std::future::Future> { + resolve_header(remote_blockchain, &*fetcher, block) + .then(move |result| match result { + Ok(header) => Either::Left(fetcher.remote_call(RemoteCallRequest { + block, + header, + method, + call_data: call_data.0, + retry_count: Default::default(), + }).then(|result| ready(result.map(Bytes).map_err(client_err)))), + Err(error) => Either::Right(ready(Err(error))), + }) +} + +/// Get runtime version at given block. +fn runtime_version>( + remote_blockchain: &dyn RemoteBlockchain, + fetcher: Arc, + block: Block::Hash, +) -> impl std::future::Future> { + call( + remote_blockchain, + fetcher, + block, + "Core_version".into(), + Bytes(Vec::new()), + ) + .then(|version| ready(version.and_then(|version| + Decode::decode(&mut &version.0[..]).map_err(|_| client_err(ClientError::VersionInvalid)) + ))) +} + +/// Get storage value at given key at given block. +fn storage>( + remote_blockchain: &dyn RemoteBlockchain, + fetcher: Arc, + block: Block::Hash, + keys: Vec>, +) -> impl std::future::Future>, Error>> { + resolve_header(remote_blockchain, &*fetcher, block) + .then(move |result| match result { + Ok(header) => Either::Left(fetcher.remote_read(RemoteReadRequest { + block, + header, + keys, + retry_count: Default::default(), + }).then(|result| ready(result + .map(|result| result + .into_iter() + .map(|(key, value)| (StorageKey(key), value.map(StorageData))) + .collect() + ).map_err(client_err) + ))), + Err(error) => Either::Right(ready(Err(error))), + }) +} + +/// Returns subscription stream that issues request on every imported block and +/// if value has changed from previous block, emits (stream) item. +fn subscription_stream< + Block, + Requests, + FutureBlocksStream, + V, N, + InitialRequestFuture, + IssueRequest, IssueRequestFuture, + CompareValues, +>( + shared_requests: Requests, + future_blocks_stream: FutureBlocksStream, + initial_request: InitialRequestFuture, + issue_request: IssueRequest, + compare_values: CompareValues, +) -> impl Stream where + Block: BlockT, + Requests: 'static + SharedRequests, + FutureBlocksStream: Stream, + V: Send + 'static + Clone, + InitialRequestFuture: std::future::Future> + Send + 'static, + IssueRequest: 'static + Fn(Block::Hash) -> IssueRequestFuture, + IssueRequestFuture: std::future::Future> + Send + 'static, + CompareValues: Fn(Block::Hash, Option<&V>, &V) -> Option, +{ + // we need to send initial value first, then we'll only be sending if value has changed + let previous_value = Arc::new(Mutex::new(None)); + + // prepare 'stream' of initial values + let initial_value_stream = ignore_error(initial_request) + .boxed() + .compat() + .into_stream(); + + // prepare stream of future values + // + // we do not want to stop stream if single request fails + // (the warning should have been already issued by the request issuer) + let future_values_stream = future_blocks_stream + .and_then(move |block| ignore_error(maybe_share_remote_request::( + shared_requests.clone(), + block, + &issue_request, + ).map(move |r| r.map(|v| (block, v)))).boxed().compat()); + + // now let's return changed values for selected blocks + initial_value_stream + .chain(future_values_stream) + .filter_map(move |block_and_new_value| block_and_new_value.and_then(|(block, new_value)| { + let mut previous_value = previous_value.lock(); + compare_values(block, previous_value.as_ref(), &new_value) + .map(|notification_value| { + *previous_value = Some(new_value); + notification_value + }) + })) + .map_err(|_| ()) +} + +/// Request some data from remote node, probably reusing response from already +/// (in-progress) existing request. +fn maybe_share_remote_request( + shared_requests: Requests, + block: Block::Hash, + issue_request: &IssueRequest, +) -> impl std::future::Future> where + V: Clone, + Requests: SharedRequests, + IssueRequest: Fn(Block::Hash) -> IssueRequestFuture, + IssueRequestFuture: std::future::Future>, +{ + let (sender, receiver) = channel(); + let need_issue_request = shared_requests.listen_request(block, sender); + + // if that isn't the first request - just listen for existing request' response + if !need_issue_request { + return Either::Right(receiver.then(|r| ready(r.unwrap_or(Err(()))))); + } + + // that is the first request - issue remote request + notify all listeners on + // completion + Either::Left( + display_error(issue_request(block)) + .then(move |remote_result| { + let listeners = shared_requests.on_response_received(block); + // skip first element, because this future is the first element + for receiver in listeners.into_iter().skip(1) { + if let Err(_) = receiver.send(remote_result.clone()) { + // we don't care if receiver has been dropped already + } + } + + ready(remote_result) + }) + ) +} + +/// Convert successful future result into Ok(result) and error into Err(()), +/// displaying warning. +fn display_error(future: F) -> impl std::future::Future> where + F: std::future::Future> +{ + future.then(|result| ready(match result { + Ok(result) => Ok(result), + Err(err) => { + warn!("Remote request for subscription data has failed with: {:?}", err); + Err(()) + }, + })) +} + +/// Convert successful future result into Ok(Some(result)) and error into Ok(None), +/// displaying warning. +fn ignore_error(future: F) -> impl std::future::Future, ()>> where + F: std::future::Future> +{ + future.then(|result| ready(match result { + Ok(result) => Ok(Some(result)), + Err(()) => Ok(None), + })) +} + +#[cfg(test)] +mod tests { + use rpc::futures::stream::futures_ordered; + use test_client::runtime::Block; + use super::*; + + #[test] + fn subscription_stream_works() { + let stream = subscription_stream::( + SimpleSubscriptions::default(), + futures_ordered(vec![result(Ok(H256::from([2; 32]))), result(Ok(H256::from([3; 32])))]), + ready(Ok((H256::from([1; 32]), 100))), + |block| match block[0] { + 2 => ready(Ok(100)), + 3 => ready(Ok(200)), + _ => unreachable!("should not issue additional requests"), + }, + |_, old_value, new_value| match old_value == Some(new_value) { + true => None, + false => Some(new_value.clone()), + } + ); + + assert_eq!( + stream.collect().wait(), + Ok(vec![100, 200]) + ); + } + + #[test] + fn subscription_stream_ignores_failed_requests() { + let stream = subscription_stream::( + SimpleSubscriptions::default(), + futures_ordered(vec![result(Ok(H256::from([2; 32]))), result(Ok(H256::from([3; 32])))]), + ready(Ok((H256::from([1; 32]), 100))), + |block| match block[0] { + 2 => ready(Err(client_err(ClientError::NotAvailableOnLightClient))), + 3 => ready(Ok(200)), + _ => unreachable!("should not issue additional requests"), + }, + |_, old_value, new_value| match old_value == Some(new_value) { + true => None, + false => Some(new_value.clone()), + } + ); + + assert_eq!( + stream.collect().wait(), + Ok(vec![100, 200]) + ); + } + + #[test] + fn maybe_share_remote_request_shares_request() { + type UnreachableFuture = futures03::future::Ready>; + + let shared_requests = SimpleSubscriptions::default(); + + // let's 'issue' requests for B1 + shared_requests.lock().insert( + H256::from([1; 32]), + vec![channel().0], + ); + + // make sure that no additional requests are issued when we're asking for B1 + let _ = maybe_share_remote_request::( + shared_requests.clone(), + H256::from([1; 32]), + &|_| unreachable!("no duplicate requests issued"), + ); + + // make sure that additional requests is issued when we're asking for B2 + let request_issued = Arc::new(Mutex::new(false)); + let _ = maybe_share_remote_request::( + shared_requests.clone(), + H256::from([2; 32]), + &|_| { + *request_issued.lock() = true; + ready(Ok(Default::default())) + }, + ); + assert!(*request_issued.lock()); + } +} diff --git a/core/rpc/src/state/tests.rs b/core/rpc/src/state/tests.rs index ac7da729119a08ff5841275ada5c280492c6a153..b10571846c2a22ac773510823b8587fe546653c9 100644 --- a/core/rpc/src/state/tests.rs +++ b/core/rpc/src/state/tests.rs @@ -15,9 +15,12 @@ // along with Substrate. If not, see . use super::*; +use super::state_full::split_range; use self::error::Error; +use std::sync::Arc; use assert_matches::assert_matches; +use futures::stream::Stream; use primitives::{ChangesTrieConfiguration, storage::well_known_keys}; use sr_io::blake2_256; use test_client::{ @@ -25,29 +28,46 @@ use test_client::{ consensus::BlockOrigin, runtime, }; -use substrate_executor::NativeExecutionDispatch; #[test] fn should_return_storage() { - let core = tokio::runtime::Runtime::new().unwrap(); - let client = Arc::new(test_client::new()); + const KEY: &[u8] = b":mock"; + const VALUE: &[u8] = b"hello world"; + const STORAGE_KEY: &[u8] = b":child_storage:default:child"; + const CHILD_VALUE: &[u8] = b"hello world !"; + + let mut core = tokio::runtime::Runtime::new().unwrap(); + let client = TestClientBuilder::new() + .add_extra_storage(KEY.to_vec(), VALUE.to_vec()) + .add_extra_child_storage(STORAGE_KEY.to_vec(), KEY.to_vec(), CHILD_VALUE.to_vec()) + .build(); let genesis_hash = client.genesis_hash(); - let client = State::new(client, Subscriptions::new(Arc::new(core.executor()))); - let key = StorageKey(b":code".to_vec()); + let client = new_full(Arc::new(client), Subscriptions::new(Arc::new(core.executor()))); + let key = StorageKey(KEY.to_vec()); + let storage_key = StorageKey(STORAGE_KEY.to_vec()); assert_eq!( - client.storage(key.clone(), Some(genesis_hash).into()) + client.storage(key.clone(), Some(genesis_hash).into()).wait() .map(|x| x.map(|x| x.0.len())).unwrap().unwrap() as usize, - LocalExecutor::native_equivalent().len(), + VALUE.len(), ); assert_matches!( - client.storage_hash(key.clone(), Some(genesis_hash).into()).map(|x| x.is_some()), + client.storage_hash(key.clone(), Some(genesis_hash).into()).wait() + .map(|x| x.is_some()), Ok(true) ); assert_eq!( - client.storage_size(key.clone(), None).unwrap().unwrap() as usize, - LocalExecutor::native_equivalent().len(), + client.storage_size(key.clone(), None).wait().unwrap().unwrap() as usize, + VALUE.len(), ); + assert_eq!( + core.block_on( + client.child_storage(storage_key, key, Some(genesis_hash).into()) + .map(|x| x.map(|x| x.0.len())) + ).unwrap().unwrap() as usize, + CHILD_VALUE.len(), + ); + } #[test] @@ -57,22 +77,22 @@ fn should_return_child_storage() { .add_child_storage("test", "key", vec![42_u8]) .build()); let genesis_hash = client.genesis_hash(); - let client = State::new(client, Subscriptions::new(Arc::new(core.executor()))); + let client = new_full(client, Subscriptions::new(Arc::new(core.executor()))); let child_key = StorageKey(well_known_keys::CHILD_STORAGE_KEY_PREFIX.iter().chain(b"test").cloned().collect()); let key = StorageKey(b"key".to_vec()); assert_matches!( - client.child_storage(child_key.clone(), key.clone(), Some(genesis_hash).into()), + client.child_storage(child_key.clone(), key.clone(), Some(genesis_hash).into()).wait(), Ok(Some(StorageData(ref d))) if d[0] == 42 && d.len() == 1 ); assert_matches!( client.child_storage_hash(child_key.clone(), key.clone(), Some(genesis_hash).into()) - .map(|x| x.is_some()), + .wait().map(|x| x.is_some()), Ok(true) ); assert_matches!( - client.child_storage_size(child_key.clone(), key.clone(), None), + client.child_storage_size(child_key.clone(), key.clone(), None).wait(), Ok(Some(1)) ); } @@ -82,11 +102,11 @@ fn should_call_contract() { let core = tokio::runtime::Runtime::new().unwrap(); let client = Arc::new(test_client::new()); let genesis_hash = client.genesis_hash(); - let client = State::new(client, Subscriptions::new(Arc::new(core.executor()))); + let client = new_full(client, Subscriptions::new(Arc::new(core.executor()))); assert_matches!( - client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()), - Err(Error::Client(client::error::Error::Execution(_))) + client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()).wait(), + Err(Error::Client(_)) ) } @@ -97,21 +117,22 @@ fn should_notify_about_storage_changes() { let (subscriber, id, transport) = Subscriber::new_test("test"); { - let api = State::new(Arc::new(test_client::new()), Subscriptions::new(Arc::new(remote))); + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); api.subscribe_storage(Default::default(), subscriber, None.into()); // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let mut builder = api.client.new_block(Default::default()).unwrap(); + let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { from: AccountKeyring::Alice.into(), to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); - api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); + client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); } // assert notification sent to transport @@ -128,7 +149,8 @@ fn should_send_initial_storage_changes_and_notifications() { let (subscriber, id, transport) = Subscriber::new_test("test"); { - let api = State::new(Arc::new(test_client::new()), Subscriptions::new(Arc::new(remote))); + let client = Arc::new(test_client::new()); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote))); let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into())); @@ -139,14 +161,14 @@ fn should_send_initial_storage_changes_and_notifications() { // assert id assigned assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1)))); - let mut builder = api.client.new_block(Default::default()).unwrap(); + let mut builder = client.new_block(Default::default()).unwrap(); builder.push_transfer(runtime::Transfer { from: AccountKeyring::Alice.into(), to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); - api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); + client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap(); } // assert initial values sent to transport @@ -163,7 +185,7 @@ fn should_send_initial_storage_changes_and_notifications() { fn should_query_storage() { fn run_tests(client: Arc) { let core = tokio::runtime::Runtime::new().unwrap(); - let api = State::new(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); let add_block = |nonce| { let mut builder = client.new_block(Default::default()).unwrap(); @@ -215,7 +237,7 @@ fn should_query_storage() { Some(block1_hash).into(), ); - assert_eq!(result.unwrap(), expected); + assert_eq!(result.wait().unwrap(), expected); // Query all changes let result = api.query_storage( @@ -232,7 +254,7 @@ fn should_query_storage() { (StorageKey(vec![5]), Some(StorageData(vec![1]))), ], }); - assert_eq!(result.unwrap(), expected); + assert_eq!(result.wait().unwrap(), expected); } run_tests(Arc::new(test_client::new())); @@ -256,18 +278,20 @@ fn should_return_runtime_version() { let core = tokio::runtime::Runtime::new().unwrap(); let client = Arc::new(test_client::new()); - let api = State::new(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ \"specVersion\":1,\"implVersion\":1,\"apis\":[[\"0xdf6acb689907609b\",2],\ [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",3],\ [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ - [\"0xf78b278be53f454c\",1],[\"0xab3c0572291feb8b\",1]]}"; + [\"0xf78b278be53f454c\",1],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]]}"; - assert_eq!( - serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(), - result, - ); + let runtime_version = api.runtime_version(None.into()).wait().unwrap(); + let serialized = serde_json::to_string(&runtime_version).unwrap(); + assert_eq!(serialized, result); + + let deserialized: RuntimeVersion = serde_json::from_str(result).unwrap(); + assert_eq!(deserialized, runtime_version); } #[test] @@ -277,7 +301,7 @@ fn should_notify_on_runtime_version_initially() { { let client = Arc::new(test_client::new()); - let api = State::new(client.clone(), Subscriptions::new(Arc::new(core.executor()))); + let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor()))); api.subscribe_runtime_version(Default::default(), subscriber); @@ -291,3 +315,11 @@ fn should_notify_on_runtime_version_initially() { // no more notifications on this channel assert_eq!(core.block_on(next.into_future()).unwrap().0, None); } + +#[test] +fn should_deserialize_storage_key() { + let k = "\"0x7f864e18e3dd8b58386310d2fe0919eef27c6e558564b7f67f22d99d20f587b\""; + let k: StorageKey = serde_json::from_str(k).unwrap(); + + assert_eq!(k.0.len(), 32); +} diff --git a/core/rpc/src/system/mod.rs b/core/rpc/src/system/mod.rs index 59ed73b588a5da6d41897b8e1efa156986054044..8907151d9ac6984bb8396c3f7af263b1b9994ee3 100644 --- a/core/rpc/src/system/mod.rs +++ b/core/rpc/src/system/mod.rs @@ -16,62 +16,18 @@ //! Substrate system API. -pub mod error; -pub mod helpers; - #[cfg(test)] mod tests; -use crate::helpers::Receiver; use futures03::{channel::{mpsc, oneshot}, compat::Compat}; -use jsonrpc_derive::rpc; -use network; +use api::Receiver; use sr_primitives::traits::{self, Header as HeaderT}; - use self::error::Result; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo}; +pub use api::system::*; +pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; pub use self::gen_client::Client as SystemClient; -/// Substrate system RPC API -#[rpc] -pub trait SystemApi { - /// Get the node's implementation name. Plain old string. - #[rpc(name = "system_name")] - fn system_name(&self) -> Result; - - /// Get the node implementation's version. Should be a semver string. - #[rpc(name = "system_version")] - fn system_version(&self) -> Result; - - /// Get the chain's type. Given as a string identifier. - #[rpc(name = "system_chain")] - fn system_chain(&self) -> Result; - - /// Get a custom set of properties as a JSON object, defined in the chain spec. - #[rpc(name = "system_properties")] - fn system_properties(&self) -> Result; - - /// Return health status of the node. - /// - /// Node is considered healthy if it is: - /// - connected to some peers (unless running in dev mode) - /// - not performing a major sync - #[rpc(name = "system_health", returns = "Health")] - fn system_health(&self) -> Receiver; - - /// Returns currently connected peers - #[rpc(name = "system_peers", returns = "Vec>")] - fn system_peers(&self) -> Receiver>>; - - /// Returns current state of the network. - /// - /// **Warning**: This API is not stable. - // TODO: make this stable and move structs https://github.com/paritytech/substrate/issues/1890 - #[rpc(name = "system_networkState", returns = "network::NetworkState")] - fn system_network_state(&self) -> Receiver; -} - /// System API implementation pub struct System { info: SystemInfo, @@ -85,7 +41,9 @@ pub enum Request { /// Must return information about the peers we are connected to. Peers(oneshot::Sender::Number>>>), /// Must return the state of the network. - NetworkState(oneshot::Sender), + NetworkState(oneshot::Sender), + /// Must return the node role. + NodeRoles(oneshot::Sender>) } impl System { @@ -133,9 +91,15 @@ impl SystemApi::Number> for Sy Receiver(Compat::new(rx)) } - fn system_network_state(&self) -> Receiver { + fn system_network_state(&self) -> Receiver { let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NetworkState(tx)); Receiver(Compat::new(rx)) } + + fn system_node_roles(&self) -> Receiver> { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); + Receiver(Compat::new(rx)) + } } diff --git a/core/rpc/src/system/tests.rs b/core/rpc/src/system/tests.rs index 70e8b4b95b67608451d33cd35217b448852660f4..1c532be372660fbee4c8210a56c15842413e553e 100644 --- a/core/rpc/src/system/tests.rs +++ b/core/rpc/src/system/tests.rs @@ -69,7 +69,7 @@ fn api>>(sync: T) -> System { let _ = sender.send(peers); } Request::NetworkState(sender) => { - let _ = sender.send(network::NetworkState { + let _ = sender.send(serde_json::to_value(&network::NetworkState { peer_id: String::new(), listened_addresses: Default::default(), external_addresses: Default::default(), @@ -78,7 +78,10 @@ fn api>>(sync: T) -> System { average_download_per_sec: 0, average_upload_per_sec: 0, peerset: serde_json::Value::Null, - }); + }).unwrap()); + }, + Request::NodeRoles(sender) => { + let _ = sender.send(vec![NodeRole::Authority]); } }; @@ -206,8 +209,9 @@ fn system_peers() { #[test] fn system_network_state() { + let res = wait_receiver(api(None).system_network_state()); assert_eq!( - wait_receiver(api(None).system_network_state()), + serde_json::from_value::(res).unwrap(), network::NetworkState { peer_id: String::new(), listened_addresses: Default::default(), @@ -220,3 +224,11 @@ fn system_network_state() { } ); } + +#[test] +fn system_node_roles() { + assert_eq!( + wait_receiver(api(None).system_node_roles()), + vec![NodeRole::Authority] + ); +} \ No newline at end of file diff --git a/core/serializer/Cargo.toml b/core/serializer/Cargo.toml index ae320e4277bb5d54a492efc324b04d7796d70298..4e0e706e2fab232ff516ade2bfa22a2ed9ad598c 100644 --- a/core/serializer/Cargo.toml +++ b/core/serializer/Cargo.toml @@ -5,5 +5,5 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = "1.0" -serde_json = "1.0" +serde = "1.0.101" +serde_json = "1.0.41" diff --git a/core/service/Cargo.toml b/core/service/Cargo.toml index bd04cd670e5b2ad2c6a7f28eda42c9c4f78185a4..3d40550c8c5b5e6bee712b346871459434586c2d 100644 --- a/core/service/Cargo.toml +++ b/core/service/Cargo.toml @@ -4,21 +4,30 @@ version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" +[features] +default = ["rocksdb"] +# The RocksDB feature activates the RocksDB database backend. If it is not activated, and you pass +# a path to a database, an error will be produced at runtime. +rocksdb = ["client_db/kvdb-rocksdb"] +wasmtime = [ + "substrate-executor/wasmtime", +] + [dependencies] -derive_more = "0.14.0" -futures = "0.1.17" -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.17", features = ["compat"] } +derive_more = "0.15.0" +futures = "0.1.29" +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19", features = ["compat"] } parking_lot = "0.9.0" -lazy_static = "1.0" -log = "0.4" -slog = {version = "^2", features = ["nested-values"]} -tokio-executor = "0.1.7" -tokio-timer = "0.2" -exit-future = "0.1" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -sysinfo = "0.9.0" -target_info = "0.1" +lazy_static = "1.4.0" +log = "0.4.8" +slog = { version = "2.5.2", features = ["nested-values"] } +tokio-executor = "0.1.8" +tokio-timer = "0.2.11" +exit-future = "0.1.4" +serde = "1.0.101" +serde_json = "1.0.41" +sysinfo = "0.9.5" +target_info = "0.1.0" keystore = { package = "substrate-keystore", path = "../../core/keystore" } sr-io = { path = "../../core/sr-io" } sr-primitives = { path = "../../core/sr-primitives" } @@ -27,12 +36,14 @@ session = { package = "substrate-session", path = "../session" } app-crypto = { package = "substrate-application-crypto", path = "../application-crypto" } consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } network = { package = "substrate-network", path = "../../core/network" } +chain-spec = { package = "substrate-chain-spec", path = "../chain-spec" } client = { package = "substrate-client", path = "../../core/client" } -client_db = { package = "substrate-client-db", path = "../../core/client/db", features = ["kvdb-rocksdb"] } +client_db = { package = "substrate-client-db", path = "../../core/client/db" } codec = { package = "parity-scale-codec", version = "1.0.0" } substrate-executor = { path = "../../core/executor" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } -rpc = { package = "substrate-rpc-servers", path = "../../core/rpc-servers" } +rpc-servers = { package = "substrate-rpc-servers", path = "../../core/rpc-servers" } +rpc = { package = "substrate-rpc", path = "../../core/rpc" } tel = { package = "substrate-telemetry", path = "../../core/telemetry" } offchain = { package = "substrate-offchain", path = "../../core/offchain" } parity-multiaddr = { package = "parity-multiaddr", version = "0.5.0" } @@ -45,3 +56,4 @@ node-runtime = { path = "../../node/runtime" } babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives" } grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" } grandpa-primitives = { package = "substrate-finality-grandpa-primitives", path = "../../core/finality-grandpa/primitives" } +tokio = "0.1" diff --git a/core/service/src/builder.rs b/core/service/src/builder.rs new file mode 100644 index 0000000000000000000000000000000000000000..03db6e385b025daa296b77eda0629ddcf43e1eac --- /dev/null +++ b/core/service/src/builder.rs @@ -0,0 +1,1300 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::{Service, NetworkStatus, NetworkState, error::{self, Error}, DEFAULT_PROTOCOL_ID}; +use crate::{SpawnTaskHandle, start_rpc_servers, build_network_future, TransactionPoolAdapter}; +use crate::status_sinks; +use crate::config::{Configuration, DatabaseConfig}; +use client::{ + BlockchainEvents, Client, runtime_api, + backend::RemoteBackend, light::blockchain::RemoteBlockchain, +}; +use chain_spec::{RuntimeGenesis, Extension}; +use codec::{Decode, Encode, IoReader}; +use consensus_common::import_queue::ImportQueue; +use futures::{prelude::*, sync::mpsc}; +use futures03::{ + compat::Compat, + future::ready, + FutureExt as _, TryFutureExt as _, + StreamExt as _, TryStreamExt as _, +}; +use keystore::{Store as Keystore}; +use log::{info, warn}; +use network::{FinalityProofProvider, OnDemand, NetworkService, NetworkStateInfo, DhtEvent}; +use network::{config::BoxFinalityProofRequestBuilder, specialization::NetworkSpecialization}; +use parking_lot::{Mutex, RwLock}; +use primitives::{Blake2Hasher, H256, Hasher}; +use rpc; +use sr_primitives::generic::BlockId; +use sr_primitives::traits::{ + Block as BlockT, Extrinsic, ProvideRuntimeApi, NumberFor, One, Zero, Header, SaturatedConversion +}; +use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; +use std::{io::{Read, Write, Seek}, marker::PhantomData, sync::Arc, sync::atomic::AtomicBool}; +use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; +use tel::{telemetry, SUBSTRATE_INFO}; +use transaction_pool::txpool::{self, ChainApi, Pool as TransactionPool}; + +/// Aggregator for the components required to build a service. +/// +/// # Usage +/// +/// Call [`ServiceBuilder::new_full`] or [`ServiceBuilder::new_light`], then call the various +/// `with_` methods to add the required components that you built yourself: +/// +/// - [`with_select_chain`](ServiceBuilder::with_select_chain) +/// - [`with_import_queue`](ServiceBuilder::with_import_queue) +/// - [`with_network_protocol`](ServiceBuilder::with_network_protocol) +/// - [`with_finality_proof_provider`](ServiceBuilder::with_finality_proof_provider) +/// - [`with_transaction_pool`](ServiceBuilder::with_transaction_pool) +/// +/// After this is done, call [`build`](ServiceBuilder::build) to construct the service. +/// +/// The order in which the `with_*` methods are called doesn't matter, as the correct binding of +/// generics is done when you call `build`. +/// +pub struct ServiceBuilder +{ + config: Configuration, + client: Arc, + backend: Arc, + keystore: Arc>, + fetcher: Option, + select_chain: Option, + import_queue: TImpQu, + finality_proof_request_builder: Option, + finality_proof_provider: Option, + network_protocol: TNetP, + transaction_pool: Arc, + rpc_extensions: TRpc, + remote_backend: Option>>, + dht_event_tx: Option>, + marker: PhantomData<(TBl, TRtApi)>, +} + +/// Full client type. +type TFullClient = Client< + TFullBackend, + TFullCallExecutor, + TBl, + TRtApi, +>; + +/// Full client backend type. +type TFullBackend = client_db::Backend; + +/// Full client call executor type. +type TFullCallExecutor = client::LocalCallExecutor< + client_db::Backend, + NativeExecutor, +>; + +/// Light client type. +type TLightClient = Client< + TLightBackend, + TLightCallExecutor, + TBl, + TRtApi, +>; + +/// Light client backend type. +type TLightBackend = client::light::backend::Backend< + client_db::light::LightStorage, + Blake2Hasher, +>; + +/// Light call executor type. +type TLightCallExecutor = client::light::call_executor::GenesisCallExecutor< + client::light::backend::Backend< + client_db::light::LightStorage, + Blake2Hasher + >, + client::LocalCallExecutor< + client::light::backend::Backend< + client_db::light::LightStorage, + Blake2Hasher + >, + NativeExecutor + >, +>; + +impl ServiceBuilder<(), (), TCfg, TGen, TCSExt, (), (), (), (), (), (), (), (), (), ()> +where TGen: RuntimeGenesis, TCSExt: Extension { + /// Start the service builder with a configuration. + pub fn new_full, TRtApi, TExecDisp: NativeExecutionDispatch>( + config: Configuration + ) -> Result, + Arc>, + (), + (), + BoxFinalityProofRequestBuilder, + Arc>, + (), + (), + (), + TFullBackend, + >, Error> { + let keystore = Keystore::open( + config.keystore_path.clone().ok_or("No basepath configured")?, + config.keystore_password.clone() + )?; + + let executor = NativeExecutor::::new( + config.wasm_method, + config.default_heap_pages, + ); + + let fork_blocks = config.chain_spec + .extensions() + .get::>() + .cloned() + .unwrap_or_default(); + + let (client, backend) = { + let db_config = client_db::DatabaseSettings { + state_cache_size: config.state_cache_size, + state_cache_child_ratio: + config.state_cache_child_ratio.map(|v| (v, 100)), + pruning: config.pruning.clone(), + source: match &config.database { + DatabaseConfig::Path { path, cache_size } => + client_db::DatabaseSettingsSrc::Path { + path: path.clone(), + cache_size: cache_size.clone().map(|u| u as usize), + }, + DatabaseConfig::Custom(db) => + client_db::DatabaseSettingsSrc::Custom(db.clone()), + }, + }; + + client_db::new_client( + db_config, + executor, + &config.chain_spec, + fork_blocks, + config.execution_strategies.clone(), + Some(keystore.clone()), + )? + }; + + let client = Arc::new(client); + + Ok(ServiceBuilder { + config, + client, + backend, + keystore, + fetcher: None, + select_chain: None, + import_queue: (), + finality_proof_request_builder: None, + finality_proof_provider: None, + network_protocol: (), + transaction_pool: Arc::new(()), + rpc_extensions: Default::default(), + remote_backend: None, + dht_event_tx: None, + marker: PhantomData, + }) + } + + /// Start the service builder with a configuration. + pub fn new_light, TRtApi, TExecDisp: NativeExecutionDispatch + 'static>( + config: Configuration + ) -> Result, + Arc>, + (), + (), + BoxFinalityProofRequestBuilder, + Arc>, + (), + (), + (), + TLightBackend, + >, Error> { + let keystore = Keystore::open( + config.keystore_path.clone().ok_or("No basepath configured")?, + config.keystore_password.clone() + )?; + + let executor = NativeExecutor::::new( + config.wasm_method, + config.default_heap_pages, + ); + + let db_storage = { + let db_settings = client_db::DatabaseSettings { + state_cache_size: config.state_cache_size, + state_cache_child_ratio: + config.state_cache_child_ratio.map(|v| (v, 100)), + pruning: config.pruning.clone(), + source: match &config.database { + DatabaseConfig::Path { path, cache_size } => + client_db::DatabaseSettingsSrc::Path { + path: path.clone(), + cache_size: cache_size.clone().map(|u| u as usize), + }, + DatabaseConfig::Custom(db) => + client_db::DatabaseSettingsSrc::Custom(db.clone()), + }, + }; + client_db::light::LightStorage::new(db_settings)? + }; + let light_blockchain = client::light::new_light_blockchain(db_storage); + let fetch_checker = Arc::new(client::light::new_fetch_checker(light_blockchain.clone(), executor.clone())); + let fetcher = Arc::new(network::OnDemand::new(fetch_checker)); + let backend = client::light::new_light_backend(light_blockchain); + let remote_blockchain = backend.remote_blockchain(); + let client = Arc::new(client::light::new_light( + backend.clone(), + &config.chain_spec, + executor, + )?); + + Ok(ServiceBuilder { + config, + client, + backend, + keystore, + fetcher: Some(fetcher), + select_chain: None, + import_queue: (), + finality_proof_request_builder: None, + finality_proof_provider: None, + network_protocol: (), + transaction_pool: Arc::new(()), + rpc_extensions: Default::default(), + remote_backend: Some(remote_blockchain), + dht_event_tx: None, + marker: PhantomData, + }) + } +} + +impl + ServiceBuilder { + + /// Returns a reference to the client that was stored in this builder. + pub fn client(&self) -> &Arc { + &self.client + } + + /// Returns a reference to the backend that was used in this builder. + pub fn backend(&self) -> &Arc { + &self.backend + } + + /// Returns a reference to the select-chain that was stored in this builder. + pub fn select_chain(&self) -> Option<&TSc> { + self.select_chain.as_ref() + } + + /// Defines which head-of-chain strategy to use. + pub fn with_opt_select_chain( + self, + select_chain_builder: impl FnOnce( + &Configuration, &Arc + ) -> Result, Error> + ) -> Result, Error> { + let select_chain = select_chain_builder(&self.config, &self.backend)?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: self.dht_event_tx, + marker: self.marker, + }) + } + + /// Defines which head-of-chain strategy to use. + pub fn with_select_chain( + self, + builder: impl FnOnce(&Configuration, &Arc) -> Result + ) -> Result, Error> { + self.with_opt_select_chain(|cfg, b| builder(cfg, b).map(Option::Some)) + } + + /// Defines which import queue to use. + pub fn with_import_queue( + self, + builder: impl FnOnce(&Configuration, Arc, Option, Arc) + -> Result + ) -> Result, Error> + where TSc: Clone { + let import_queue = builder( + &self.config, + self.client.clone(), + self.select_chain.clone(), + self.transaction_pool.clone() + )?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: self.dht_event_tx, + marker: self.marker, + }) + } + + /// Defines which network specialization protocol to use. + pub fn with_network_protocol( + self, + network_protocol_builder: impl FnOnce(&Configuration) -> Result + ) -> Result, Error> { + let network_protocol = network_protocol_builder(&self.config)?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: self.dht_event_tx, + marker: self.marker, + }) + } + + /// Defines which strategy to use for providing finality proofs. + pub fn with_opt_finality_proof_provider( + self, + builder: impl FnOnce(Arc, Arc) -> Result>>, Error> + ) -> Result>, + TNetP, + TExPool, + TRpc, + Backend, + >, Error> { + let finality_proof_provider = builder(self.client.clone(), self.backend.clone())?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: self.dht_event_tx, + marker: self.marker, + }) + } + + /// Defines which strategy to use for providing finality proofs. + pub fn with_finality_proof_provider( + self, + build: impl FnOnce(Arc, Arc) -> Result>, Error> + ) -> Result>, + TNetP, + TExPool, + TRpc, + Backend, + >, Error> { + self.with_opt_finality_proof_provider(|client, backend| build(client, backend).map(Option::Some)) + } + + /// Defines which import queue to use. + pub fn with_import_queue_and_opt_fprb( + self, + builder: impl FnOnce( + &Configuration, + Arc, + Arc, + Option, + Option, + Arc, + ) -> Result<(UImpQu, Option), Error> + ) -> Result, Error> + where TSc: Clone, TFchr: Clone { + let (import_queue, fprb) = builder( + &self.config, + self.client.clone(), + self.backend.clone(), + self.fetcher.clone(), + self.select_chain.clone(), + self.transaction_pool.clone() + )?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue, + finality_proof_request_builder: fprb, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: self.dht_event_tx, + marker: self.marker, + }) + } + + /// Defines which import queue to use. + pub fn with_import_queue_and_fprb( + self, + builder: impl FnOnce( + &Configuration, + Arc, + Arc, + Option, + Option, + Arc, + ) -> Result<(UImpQu, UFprb), Error> + ) -> Result, Error> + where TSc: Clone, TFchr: Clone { + self.with_import_queue_and_opt_fprb(|cfg, cl, b, f, sc, tx| + builder(cfg, cl, b, f, sc, tx) + .map(|(q, f)| (q, Some(f))) + ) + } + + /// Defines which transaction pool to use. + pub fn with_transaction_pool( + self, + transaction_pool_builder: impl FnOnce(transaction_pool::txpool::Options, Arc) -> Result + ) -> Result, Error> { + let transaction_pool = transaction_pool_builder(self.config.transaction_pool.clone(), self.client.clone())?; + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: Arc::new(transaction_pool), + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: self.dht_event_tx, + marker: self.marker, + }) + } + + /// Defines the RPC extensions to use. + pub fn with_rpc_extensions( + self, + rpc_ext_builder: impl FnOnce(Arc, Arc, Arc) -> URpc + ) -> Result, Error> { + let rpc_extensions = rpc_ext_builder(self.client.clone(), self.transaction_pool.clone(), self.backend.clone()); + + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: self.dht_event_tx, + marker: self.marker, + }) + } + + /// Adds a dht event sender to builder to be used by the network to send dht events to the authority discovery + /// module. + pub fn with_dht_event_tx( + self, + dht_event_tx: mpsc::Sender, + ) -> Result, Error> { + Ok(ServiceBuilder { + config: self.config, + client: self.client, + backend: self.backend, + keystore: self.keystore, + fetcher: self.fetcher, + select_chain: self.select_chain, + import_queue: self.import_queue, + finality_proof_request_builder: self.finality_proof_request_builder, + finality_proof_provider: self.finality_proof_provider, + network_protocol: self.network_protocol, + transaction_pool: self.transaction_pool, + rpc_extensions: self.rpc_extensions, + remote_backend: self.remote_backend, + dht_event_tx: Some(dht_event_tx), + marker: self.marker, + }) + } +} + +/// Implemented on `ServiceBuilder`. Allows importing blocks once you have given all the required +/// components to the builder. +pub trait ServiceBuilderImport { + /// Starts the process of importing blocks. + fn import_blocks( + self, + exit: impl Future + Send + 'static, + input: impl Read + Seek, + ) -> Result + Send>, Error>; +} + +/// Implemented on `ServiceBuilder`. Allows exporting blocks once you have given all the required +/// components to the builder. +pub trait ServiceBuilderExport { + /// Type of block of the builder. + type Block: BlockT; + + /// Performs the blocks export. + fn export_blocks( + &self, + exit: impl Future + Send + 'static, + output: impl Write, + from: NumberFor, + to: Option>, + json: bool + ) -> Result<(), Error>; +} + +/// Implemented on `ServiceBuilder`. Allows reverting the chain once you have given all the +/// required components to the builder. +pub trait ServiceBuilderRevert { + /// Type of block of the builder. + type Block: BlockT; + + /// Performs a revert of `blocks` bocks. + fn revert_chain( + &self, + blocks: NumberFor + ) -> Result<(), Error>; +} + +impl< + TBl, TRtApi, TCfg, TGen, TCSExt, TBackend, + TExec, TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, + TExPool, TRpc, Backend +> ServiceBuilderImport for ServiceBuilder< + TBl, TRtApi, TCfg, TGen, TCSExt, Client, + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, Backend +> where + TBl: BlockT::Out>, + TBackend: 'static + client::backend::Backend + Send, + TExec: 'static + client::CallExecutor + Send + Sync + Clone, + TImpQu: 'static + ImportQueue, + TRtApi: 'static + Send + Sync, +{ + fn import_blocks( + self, + exit: impl Future + Send + 'static, + input: impl Read + Seek, + ) -> Result + Send>, Error> { + let client = self.client; + let mut queue = self.import_queue; + import_blocks!(TBl, client, queue, exit, input) + .map(|f| Box::new(f) as Box<_>) + } +} + +impl + ServiceBuilderExport for ServiceBuilder, + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TBackend> +where + TBl: BlockT::Out>, + TBackend: 'static + client::backend::Backend + Send, + TExec: 'static + client::CallExecutor + Send + Sync + Clone +{ + type Block = TBl; + + fn export_blocks( + &self, + exit: impl Future + Send + 'static, + mut output: impl Write, + from: NumberFor, + to: Option>, + json: bool + ) -> Result<(), Error> { + let client = &self.client; + export_blocks!(client, exit, output, from, to, json) + } +} + +impl + ServiceBuilderRevert for ServiceBuilder, + TFchr, TSc, TImpQu, TFprb, TFpp, TNetP, TExPool, TRpc, TBackend> +where + TBl: BlockT::Out>, + TBackend: 'static + client::backend::Backend + Send, + TExec: 'static + client::CallExecutor + Send + Sync + Clone +{ + type Block = TBl; + + fn revert_chain( + &self, + blocks: NumberFor + ) -> Result<(), Error> { + let client = &self.client; + revert_chain!(client, blocks) + } +} + +impl +ServiceBuilder< + TBl, + TRtApi, + TCfg, + TGen, + TCSExt, + Client, + Arc>, + TSc, + TImpQu, + BoxFinalityProofRequestBuilder, + Arc>, + TNetP, + TransactionPool, + TRpc, + TBackend, +> where + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: + runtime_api::Metadata + + offchain::OffchainWorkerApi + + runtime_api::TaggedTransactionQueue + + session::SessionKeys, + TBl: BlockT::Out>, + TRtApi: 'static + Send + Sync, + TCfg: Default, + TGen: RuntimeGenesis, + TCSExt: Extension, + TBackend: 'static + client::backend::Backend + Send, + TExec: 'static + client::CallExecutor + Send + Sync + Clone, + TSc: Clone, + TImpQu: 'static + ImportQueue, + TNetP: NetworkSpecialization, + TExPoolApi: 'static + ChainApi::Hash>, + TRpc: rpc::RpcExtension + Clone, +{ + /// Builds the service. + pub fn build(self) -> Result, + TSc, + NetworkStatus, + NetworkService::Hash>, + TransactionPool, + offchain::OffchainWorkers< + Client, + TBackend::OffchainStorage, + TBl + >, + >, Error> { + let ServiceBuilder { + marker: _, + mut config, + client, + fetcher: on_demand, + backend, + keystore, + select_chain, + import_queue, + finality_proof_request_builder, + finality_proof_provider, + network_protocol, + transaction_pool, + rpc_extensions, + remote_backend, + dht_event_tx, + } = self; + + session::generate_initial_session_keys( + client.clone(), + config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default() + )?; + + let (signal, exit) = exit_future::signal(); + + // List of asynchronous tasks to spawn. We collect them, then spawn them all at once. + let (to_spawn_tx, to_spawn_rx) = + mpsc::unbounded:: + Send>>(); + + let import_queue = Box::new(import_queue); + let chain_info = client.info().chain; + + let version = config.full_version(); + info!("Highest known block at #{}", chain_info.best_number); + telemetry!( + SUBSTRATE_INFO; + "node.start"; + "height" => chain_info.best_number.saturated_into::(), + "best" => ?chain_info.best_hash + ); + + let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { + imports_external_transactions: !config.roles.is_light(), + pool: transaction_pool.clone(), + client: client.clone(), + executor: Arc::new(SpawnTaskHandle { sender: to_spawn_tx.clone(), on_exit: exit.clone() }), + }); + + let protocol_id = { + let protocol_id_full = match config.chain_spec.protocol_id() { + Some(pid) => pid, + None => { + warn!("Using default protocol ID {:?} because none is configured in the \ + chain specs", DEFAULT_PROTOCOL_ID + ); + DEFAULT_PROTOCOL_ID + } + }.as_bytes(); + network::config::ProtocolId::from(protocol_id_full) + }; + + let block_announce_validator = + Box::new(consensus_common::block_validation::DefaultBlockAnnounceValidator::new(client.clone())); + + let network_params = network::config::Params { + roles: config.roles, + network_config: config.network.clone(), + chain: client.clone(), + finality_proof_provider, + finality_proof_request_builder, + on_demand: on_demand.clone(), + transaction_pool: transaction_pool_adapter.clone() as _, + import_queue, + protocol_id, + specialization: network_protocol, + block_announce_validator, + }; + + let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); + let network_mut = network::NetworkWorker::new(network_params)?; + let network = network_mut.service().clone(); + let network_status_sinks = Arc::new(Mutex::new(status_sinks::StatusSinks::new())); + + let offchain_storage = backend.offchain_storage(); + let offchain_workers = match (config.offchain_worker, offchain_storage) { + (true, Some(db)) => { + Some(Arc::new(offchain::OffchainWorkers::new(client.clone(), db))) + }, + (true, None) => { + log::warn!("Offchain workers disabled, due to lack of offchain storage support in backend."); + None + }, + _ => None, + }; + + { + // block notifications + let txpool = Arc::downgrade(&transaction_pool); + let wclient = Arc::downgrade(&client); + let offchain = offchain_workers.as_ref().map(Arc::downgrade); + let to_spawn_tx_ = to_spawn_tx.clone(); + let network_state_info: Arc = network.clone(); + let is_validator = config.roles.is_authority(); + + let events = client.import_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat() + .for_each(move |notification| { + let number = *notification.header.number(); + let txpool = txpool.upgrade(); + + if let (Some(txpool), Some(client)) = (txpool.as_ref(), wclient.upgrade()) { + let future = maintain_transaction_pool( + &BlockId::hash(notification.hash), + &client, + &*txpool, + ¬ification.retracted, + ).map_err(|e| warn!("Pool error processing new block: {:?}", e))?; + let _ = to_spawn_tx_.unbounded_send(future); + } + + let offchain = offchain.as_ref().and_then(|o| o.upgrade()); + if let (Some(txpool), Some(offchain)) = (txpool, offchain) { + let future = offchain.on_block_imported(&number, &txpool, network_state_info.clone(), is_validator) + .map(|()| Ok(())); + let _ = to_spawn_tx_.unbounded_send(Box::new(Compat::new(future))); + } + + Ok(()) + }) + .select(exit.clone()) + .then(|_| Ok(())); + let _ = to_spawn_tx.unbounded_send(Box::new(events)); + } + + { + // extrinsic notifications + let network = Arc::downgrade(&network); + let transaction_pool_ = transaction_pool.clone(); + let events = transaction_pool.import_notification_stream() + .map(|v| Ok::<_, ()>(v)).compat() + .for_each(move |_| { + if let Some(network) = network.upgrade() { + network.trigger_repropagate(); + } + let status = transaction_pool_.status(); + telemetry!(SUBSTRATE_INFO; "txpool.import"; + "ready" => status.ready, + "future" => status.future + ); + Ok(()) + }) + .select(exit.clone()) + .then(|_| Ok(())); + + let _ = to_spawn_tx.unbounded_send(Box::new(events)); + } + + // Periodically notify the telemetry. + let transaction_pool_ = transaction_pool.clone(); + let client_ = client.clone(); + let mut sys = System::new(); + let self_pid = get_current_pid().ok(); + let (state_tx, state_rx) = mpsc::unbounded::<(NetworkStatus<_>, NetworkState)>(); + network_status_sinks.lock().push(std::time::Duration::from_millis(5000), state_tx); + let tel_task = state_rx.for_each(move |(net_status, _)| { + let info = client_.info(); + let best_number = info.chain.best_number.saturated_into::(); + let best_hash = info.chain.best_hash; + let num_peers = net_status.num_connected_peers; + let txpool_status = transaction_pool_.status(); + let finalized_number: u64 = info.chain.finalized_number.saturated_into::(); + let bandwidth_download = net_status.average_download_per_sec; + let bandwidth_upload = net_status.average_upload_per_sec; + + let used_state_cache_size = match info.used_state_cache_size { + Some(size) => size, + None => 0, + }; + + // get cpu usage and memory usage of this process + let (cpu_usage, memory) = if let Some(self_pid) = self_pid { + if sys.refresh_process(self_pid) { + let proc = sys.get_process(self_pid) + .expect("Above refresh_process succeeds, this should be Some(), qed"); + (proc.cpu_usage(), proc.memory()) + } else { (0.0, 0) } + } else { (0.0, 0) }; + + telemetry!( + SUBSTRATE_INFO; + "system.interval"; + "peers" => num_peers, + "height" => best_number, + "best" => ?best_hash, + "txcount" => txpool_status.ready, + "cpu" => cpu_usage, + "memory" => memory, + "finalized_height" => finalized_number, + "finalized_hash" => ?info.chain.finalized_hash, + "bandwidth_download" => bandwidth_download, + "bandwidth_upload" => bandwidth_upload, + "used_state_cache_size" => used_state_cache_size, + ); + + Ok(()) + }).select(exit.clone()).then(|_| Ok(())); + let _ = to_spawn_tx.unbounded_send(Box::new(tel_task)); + + // Periodically send the network state to the telemetry. + let (netstat_tx, netstat_rx) = mpsc::unbounded::<(NetworkStatus<_>, NetworkState)>(); + network_status_sinks.lock().push(std::time::Duration::from_secs(30), netstat_tx); + let tel_task_2 = netstat_rx.for_each(move |(_, network_state)| { + telemetry!( + SUBSTRATE_INFO; + "system.network_state"; + "state" => network_state, + ); + Ok(()) + }).select(exit.clone()).then(|_| Ok(())); + let _ = to_spawn_tx.unbounded_send(Box::new(tel_task_2)); + + // RPC + let (system_rpc_tx, system_rpc_rx) = futures03::channel::mpsc::unbounded(); + let gen_handler = || { + use rpc::{chain, state, author, system}; + + let system_info = rpc::system::SystemInfo { + chain_name: config.chain_spec.name().into(), + impl_name: config.impl_name.into(), + impl_version: config.impl_version.into(), + properties: config.chain_spec.properties().clone(), + }; + + let subscriptions = rpc::Subscriptions::new(Arc::new(SpawnTaskHandle { + sender: to_spawn_tx.clone(), + on_exit: exit.clone() + })); + + let (chain, state) = if let (Some(remote_backend), Some(on_demand)) = + (remote_backend.as_ref(), on_demand.as_ref()) { + // Light clients + let chain = rpc::chain::new_light( + client.clone(), + subscriptions.clone(), + remote_backend.clone(), + on_demand.clone() + ); + let state = rpc::state::new_light( + client.clone(), + subscriptions.clone(), + remote_backend.clone(), + on_demand.clone() + ); + (chain, state) + + } else { + // Full nodes + let chain = rpc::chain::new_full(client.clone(), subscriptions.clone()); + let state = rpc::state::new_full(client.clone(), subscriptions.clone()); + (chain, state) + }; + + let author = rpc::author::Author::new( + client.clone(), + transaction_pool.clone(), + subscriptions, + keystore.clone(), + ); + let system = system::System::new(system_info, system_rpc_tx.clone()); + + rpc_servers::rpc_handler(( + state::StateApi::to_delegate(state), + chain::ChainApi::to_delegate(chain), + author::AuthorApi::to_delegate(author), + system::SystemApi::to_delegate(system), + rpc_extensions.clone(), + )) + }; + let rpc_handlers = gen_handler(); + let rpc = start_rpc_servers(&config, gen_handler)?; + + + let _ = to_spawn_tx.unbounded_send(Box::new(build_network_future( + config.roles, + network_mut, + client.clone(), + network_status_sinks.clone(), + system_rpc_rx, + has_bootnodes, + dht_event_tx, + ) + .map_err(|_| ()) + .select(exit.clone()) + .then(|_| Ok(())))); + + let telemetry_connection_sinks: Arc>>> = Default::default(); + + // Telemetry + let telemetry = config.telemetry_endpoints.clone().map(|endpoints| { + let is_authority = config.roles.is_authority(); + let network_id = network.local_peer_id().to_base58(); + let name = config.name.clone(); + let impl_name = config.impl_name.to_owned(); + let version = version.clone(); + let chain_name = config.chain_spec.name().to_owned(); + let telemetry_connection_sinks_ = telemetry_connection_sinks.clone(); + let telemetry = tel::init_telemetry(tel::TelemetryConfig { + endpoints, + wasm_external_transport: config.telemetry_external_transport.take(), + }); + let future = telemetry.clone() + .map(|ev| Ok::<_, ()>(ev)) + .compat() + .for_each(move |event| { + // Safe-guard in case we add more events in the future. + let tel::TelemetryEvent::Connected = event; + + telemetry!(SUBSTRATE_INFO; "system.connected"; + "name" => name.clone(), + "implementation" => impl_name.clone(), + "version" => version.clone(), + "config" => "", + "chain" => chain_name.clone(), + "authority" => is_authority, + "network_id" => network_id.clone() + ); + + telemetry_connection_sinks_.lock().retain(|sink| { + sink.unbounded_send(()).is_ok() + }); + Ok(()) + }); + let _ = to_spawn_tx.unbounded_send(Box::new(future + .select(exit.clone()) + .then(|_| Ok(())))); + telemetry + }); + + Ok(Service { + client, + network, + network_status_sinks, + select_chain, + transaction_pool, + exit, + signal: Some(signal), + essential_failed: Arc::new(AtomicBool::new(false)), + to_spawn_tx, + to_spawn_rx, + to_poll: Vec::new(), + rpc_handlers, + _rpc: rpc, + _telemetry: telemetry, + _offchain_workers: offchain_workers, + _telemetry_on_connect_sinks: telemetry_connection_sinks.clone(), + keystore, + marker: PhantomData::, + }) + } +} + +pub(crate) fn maintain_transaction_pool( + id: &BlockId, + client: &Arc>, + transaction_pool: &TransactionPool, + retracted: &[Block::Hash], +) -> error::Result + Send>> where + Block: BlockT::Out>, + Backend: 'static + client::backend::Backend, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, + Executor: 'static + client::CallExecutor, + PoolApi: 'static + txpool::ChainApi, + Api: 'static, +{ + // Put transactions from retracted blocks back into the pool. + let client_copy = client.clone(); + let retracted_transactions = retracted.to_vec().into_iter() + .filter_map(move |hash| client_copy.block(&BlockId::hash(hash)).ok().unwrap_or(None)) + .flat_map(|block| block.block.deconstruct().1.into_iter()) + .filter(|tx| tx.is_signed().unwrap_or(false)); + let resubmit_future = transaction_pool + .submit_at(id, retracted_transactions, true) + .then(|resubmit_result| ready(match resubmit_result { + Ok(_) => Ok(()), + Err(e) => { + warn!("Error re-submitting transactions: {:?}", e); + Ok(()) + } + })) + .compat(); + + // Avoid calling into runtime if there is nothing to prune from the pool anyway. + if transaction_pool.status().is_empty() { + return Ok(Box::new(resubmit_future)) + } + + let block = client.block(id)?; + Ok(match block { + Some(block) => { + let parent_id = BlockId::hash(*block.block.header().parent_hash()); + let prune_future = transaction_pool + .prune(id, &parent_id, block.block.extrinsics()) + .boxed() + .compat() + .map_err(|e| { format!("{:?}", e); }); + + Box::new(resubmit_future.and_then(|_| prune_future)) + }, + None => Box::new(resubmit_future), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use futures03::executor::block_on; + use consensus_common::{BlockOrigin, SelectChain}; + use substrate_test_runtime_client::{prelude::*, runtime::Transfer}; + + #[test] + fn should_remove_transactions_from_the_pool() { + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let best = longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // import the block + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push(transaction.clone()).unwrap(); + let block = builder.bake().unwrap(); + let id = BlockId::hash(block.header().hash()); + client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(pool.status().ready, 1); + maintain_transaction_pool( + &id, + &client, + &pool, + &[] + ).unwrap().wait().unwrap(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + } + + #[test] + fn should_add_reverted_transactions_to_the_pool() { + let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); + let client = Arc::new(client); + let pool = TransactionPool::new(Default::default(), ::transaction_pool::FullChainApi::new(client.clone())); + let transaction = Transfer { + amount: 5, + nonce: 0, + from: AccountKeyring::Alice.into(), + to: Default::default(), + }.into_signed_tx(); + let best = longest_chain.best_chain().unwrap(); + + // store the transaction in the pool + block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + + // import the block + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push(transaction.clone()).unwrap(); + let block = builder.bake().unwrap(); + let block1_hash = block.header().hash(); + let id = BlockId::hash(block1_hash.clone()); + client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should clean up the queue + assert_eq!(pool.status().ready, 1); + maintain_transaction_pool( + &id, + &client, + &pool, + &[] + ).unwrap().wait().unwrap(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + + // import second block + let builder = client.new_block_at(&BlockId::hash(best.hash()), Default::default()).unwrap(); + let block = builder.bake().unwrap(); + let id = BlockId::hash(block.header().hash()); + client.import(BlockOrigin::Own, block).unwrap(); + + // fire notification - this should add the transaction back to the pool. + maintain_transaction_pool( + &id, + &client, + &pool, + &[block1_hash] + ).unwrap().wait().unwrap(); + + // then + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 0); + } +} diff --git a/core/service/src/chain_ops.rs b/core/service/src/chain_ops.rs index c801b81186f18cda9495bd6466f13788263b0e10..e6d7df33c2a1d3b4994761722ee558397f5783d3 100644 --- a/core/service/src/chain_ops.rs +++ b/core/service/src/chain_ops.rs @@ -16,44 +16,20 @@ //! Chain utilities. -use std::{self, io::{Read, Write, Seek}}; -use futures::prelude::*; -use futures03::TryFutureExt as _; -use log::{info, warn}; - -use sr_primitives::generic::{SignedBlock, BlockId}; -use sr_primitives::traits::{SaturatedConversion, Zero, One, Block, Header, NumberFor}; -use consensus_common::import_queue::{ImportQueue, IncomingBlock, Link, BlockImportError, BlockImportResult}; -use network::message; - -use consensus_common::BlockOrigin; -use crate::components::{self, Components, ServiceFactory, FactoryFullConfiguration, FactoryBlockNumber, RuntimeGenesis}; -use crate::new_client; -use codec::{Decode, Encode, IoReader}; use crate::error; -use crate::chain_spec::ChainSpec; +use chain_spec::{ChainSpec, RuntimeGenesis, Extension}; -/// Export a range of blocks to a binary stream. -pub fn export_blocks( - config: FactoryFullConfiguration, - exit: E, - mut output: W, - from: FactoryBlockNumber, - to: Option>, - json: bool -) -> error::Result<()> - where - F: ServiceFactory, - E: Future + Send + 'static, - W: Write, -{ - let client = new_client::(&config)?; - let mut block = from; +/// Defines the logic for an operation exporting blocks within a range. +#[macro_export] +/// Export blocks +macro_rules! export_blocks { +($client:ident, $exit:ident, $output:ident, $from:ident, $to:ident, $json:ident) => {{ + let mut block = $from; - let last = match to { + let last = match $to { Some(v) if v.is_zero() => One::one(), Some(v) => v, - None => client.info().chain.best_number, + None => $client.info().chain.best_number, }; if last < block { @@ -61,29 +37,29 @@ pub fn export_blocks( } let (exit_send, exit_recv) = std::sync::mpsc::channel(); - ::std::thread::spawn(move || { - let _ = exit.wait(); + std::thread::spawn(move || { + let _ = $exit.wait(); let _ = exit_send.send(()); }); info!("Exporting blocks from #{} to #{}", block, last); - if !json { + if !$json { let last_: u64 = last.saturated_into::(); let block_: u64 = block.saturated_into::(); let len: u64 = last_ - block_ + 1; - output.write(&len.encode())?; + $output.write_all(&len.encode())?; } loop { if exit_recv.try_recv().is_ok() { break; } - match client.block(&BlockId::number(block))? { + match $client.block(&BlockId::number(block))? { Some(block) => { - if json { - serde_json::to_writer(&mut output, &block) + if $json { + serde_json::to_writer(&mut $output, &block) .map_err(|e| format!("Error writing JSON: {}", e))?; } else { - output.write(&block.encode())?; + $output.write_all(&block.encode())?; } }, None => break, @@ -97,66 +73,61 @@ pub fn export_blocks( block += One::one(); } Ok(()) +}} } -struct WaitLink { - imported_blocks: u64, - has_error: bool, -} +/// Defines the logic for an operation importing blocks from some known import. +#[macro_export] +/// Import blocks +macro_rules! import_blocks { +($block:ty, $client:ident, $queue:ident, $exit:ident, $input:ident) => {{ + use consensus_common::import_queue::{IncomingBlock, Link, BlockImportError, BlockImportResult}; + use consensus_common::BlockOrigin; + use network::message; + use sr_primitives::generic::SignedBlock; + use sr_primitives::traits::Block; + use futures03::TryFutureExt as _; + + struct WaitLink { + imported_blocks: u64, + has_error: bool, + } -impl WaitLink { - fn new() -> WaitLink { - WaitLink { - imported_blocks: 0, - has_error: false, + impl WaitLink { + fn new() -> WaitLink { + WaitLink { + imported_blocks: 0, + has_error: false, + } } } -} -impl Link for WaitLink { - fn blocks_processed( - &mut self, - imported: usize, - _count: usize, - results: Vec<(Result>, BlockImportError>, B::Hash)> - ) { - self.imported_blocks += imported as u64; - - for result in results { - if let (Err(err), hash) = result { - warn!("There was an error importing block with hash {:?}: {:?}", hash, err); - self.has_error = true; - break; + impl Link for WaitLink { + fn blocks_processed( + &mut self, + imported: usize, + _count: usize, + results: Vec<(Result>, BlockImportError>, B::Hash)> + ) { + self.imported_blocks += imported as u64; + + for result in results { + if let (Err(err), hash) = result { + warn!("There was an error importing block with hash {:?}: {:?}", hash, err); + self.has_error = true; + break; + } } } } -} - -/// Returns a future that import blocks from a binary stream. -pub fn import_blocks( - mut config: FactoryFullConfiguration, - exit: E, - input: R -) -> error::Result> - where F: ServiceFactory, E: Future + Send + 'static, R: Read + Seek, -{ - let client = new_client::(&config)?; - // FIXME #1134 this shouldn't need a mutable config. - let select_chain = components::FullComponents::::build_select_chain(&mut config, client.clone())?; - let (mut queue, _) = components::FullComponents::::build_import_queue( - &mut config, - client.clone(), - select_chain, - None, - )?; let (exit_send, exit_recv) = std::sync::mpsc::channel(); - ::std::thread::spawn(move || { - let _ = exit.wait(); + std::thread::spawn(move || { + let _ = $exit.wait(); let _ = exit_send.send(()); }); - let mut io_reader_input = IoReader(input); + let mut io_reader_input = IoReader($input); let count: u64 = Decode::decode(&mut io_reader_input) .map_err(|e| format!("Error reading file: {}", e))?; info!("Importing {} blocks", count); @@ -165,11 +136,11 @@ pub fn import_blocks( if exit_recv.try_recv().is_ok() { break; } - match SignedBlock::::decode(&mut io_reader_input) { + match SignedBlock::<$block>::decode(&mut io_reader_input) { Ok(signed) => { let (header, extrinsics) = signed.block.deconstruct(); let hash = header.hash(); - let block = message::BlockData:: { + let block = message::BlockData::<$block> { hash, justification: signed.justification, header: Some(header), @@ -178,8 +149,8 @@ pub fn import_blocks( message_queue: None }; // import queue handles verification and importing it into the client - queue.import_blocks(BlockOrigin::File, vec![ - IncomingBlock:: { + $queue.import_blocks(BlockOrigin::File, vec![ + IncomingBlock::<$block> { hash: block.hash, header: block.header, body: block.body, @@ -208,7 +179,7 @@ pub fn import_blocks( let blocks_before = link.imported_blocks; let _ = futures03::future::poll_fn(|cx| { - queue.poll_actions(cx, &mut link); + $queue.poll_actions(cx, &mut link); std::task::Poll::Pending::> }).compat().poll(); if link.has_error { @@ -226,24 +197,21 @@ pub fn import_blocks( ); } if link.imported_blocks >= count { - info!("Imported {} blocks. Best: #{}", block_count, client.info().chain.best_number); + info!("Imported {} blocks. Best: #{}", block_count, $client.info().chain.best_number); Ok(Async::Ready(())) } else { Ok(Async::NotReady) } })) +}} } -/// Revert the chain. -pub fn revert_chain( - config: FactoryFullConfiguration, - blocks: FactoryBlockNumber -) -> error::Result<()> - where F: ServiceFactory, -{ - let client = new_client::(&config)?; - let reverted = client.revert(blocks)?; - let info = client.info().chain; +/// Revert the chain some number of blocks. +#[macro_export] +macro_rules! revert_chain { +($client:ident, $blocks:ident) => {{ + let reverted = $client.revert($blocks)?; + let info = $client.info().chain; if reverted.is_zero() { info!("There aren't any non-finalized blocks to revert."); @@ -251,11 +219,13 @@ pub fn revert_chain( info!("Reverted {} blocks. Best: #{} ({})", reverted, info.best_number, info.best_hash); } Ok(()) +}} } /// Build a chain spec json -pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result - where G: RuntimeGenesis, +pub fn build_spec(spec: ChainSpec, raw: bool) -> error::Result where + G: RuntimeGenesis, + E: Extension, { Ok(spec.to_json(raw)?) } diff --git a/core/service/src/components.rs b/core/service/src/components.rs deleted file mode 100644 index b88abd4a98b03e6811edb8103af73abdc4c90423..0000000000000000000000000000000000000000 --- a/core/service/src/components.rs +++ /dev/null @@ -1,761 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Substrate service components. - -use std::{sync::Arc, ops::Deref, ops::DerefMut}; -use serde::{Serialize, de::DeserializeOwned}; -use crate::chain_spec::ChainSpec; -use keystore::KeyStorePtr; -use client_db; -use client::{self, Client, runtime_api}; -use crate::{error, Service}; -use consensus_common::{import_queue::ImportQueue, SelectChain}; -use network::{ - self, OnDemand, FinalityProofProvider, NetworkStateInfo, config::BoxFinalityProofRequestBuilder -}; -use substrate_executor::{NativeExecutor, NativeExecutionDispatch}; -use transaction_pool::txpool::{self, Options as TransactionPoolOptions, Pool as TransactionPool}; -use sr_primitives::{ - BuildStorage, traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi}, generic::BlockId -}; -use crate::config::Configuration; -use primitives::{Blake2Hasher, H256, traits::BareCryptoStorePtr}; -use rpc::{self, apis::system::SystemInfo}; -use futures::{prelude::*, future::Executor}; -use futures03::{FutureExt as _, channel::mpsc, compat::Compat}; - -// Type aliases. -// These exist mainly to avoid typing `::Foo` all over the code. - -/// Network service type for `Components`. -pub type NetworkService = network::NetworkService< - ComponentBlock, - <::Factory as ServiceFactory>::NetworkProtocol, - ComponentExHash ->; - -/// Code executor type for a factory. -pub type CodeExecutor = NativeExecutor<::RuntimeDispatch>; - -/// Full client backend type for a factory. -pub type FullBackend = client_db::Backend<::Block>; - -/// Full client executor type for a factory. -pub type FullExecutor = client::LocalCallExecutor< - client_db::Backend<::Block>, - CodeExecutor, ->; - -/// Light client backend type for a factory. -pub type LightBackend = client::light::backend::Backend< - client_db::light::LightStorage<::Block>, - network::OnDemand<::Block>, - Blake2Hasher, ->; - -/// Light client executor type for a factory. -pub type LightExecutor = client::light::call_executor::RemoteOrLocalCallExecutor< - ::Block, - client::light::backend::Backend< - client_db::light::LightStorage<::Block>, - network::OnDemand<::Block>, - Blake2Hasher - >, - client::light::call_executor::RemoteCallExecutor< - client::light::blockchain::Blockchain< - client_db::light::LightStorage<::Block>, - network::OnDemand<::Block> - >, - network::OnDemand<::Block>, - >, - client::LocalCallExecutor< - client::light::backend::Backend< - client_db::light::LightStorage<::Block>, - network::OnDemand<::Block>, - Blake2Hasher - >, - CodeExecutor - > ->; - -/// Full client type for a factory. -pub type FullClient = Client, FullExecutor, ::Block, ::RuntimeApi>; - -/// Light client type for a factory. -pub type LightClient = Client, LightExecutor, ::Block, ::RuntimeApi>; - -/// `ChainSpec` specialization for a factory. -pub type FactoryChainSpec = ChainSpec<::Genesis>; - -/// `Genesis` specialization for a factory. -pub type FactoryGenesis = ::Genesis; - -/// `Block` type for a factory. -pub type FactoryBlock = ::Block; - -/// `Extrinsic` type for a factory. -pub type FactoryExtrinsic = <::Block as BlockT>::Extrinsic; - -/// `Number` type for a factory. -pub type FactoryBlockNumber = < as BlockT>::Header as HeaderT>::Number; - -/// Full `Configuration` type for a factory. -pub type FactoryFullConfiguration = Configuration<::Configuration, FactoryGenesis>; - -/// Client type for `Components`. -pub type ComponentClient = Client< - ::Backend, - ::Executor, - FactoryBlock<::Factory>, - ::RuntimeApi, ->; - -/// A offchain workers storage backend type. -pub type ComponentOffchainStorage = < - ::Backend as client::backend::Backend, Blake2Hasher> ->::OffchainStorage; - -/// Block type for `Components` -pub type ComponentBlock = <::Factory as ServiceFactory>::Block; - -/// Extrinsic hash type for `Components` -pub type ComponentExHash = <::TransactionPoolApi as txpool::ChainApi>::Hash; - -/// Extrinsic type. -pub type ComponentExtrinsic = as BlockT>::Extrinsic; - -/// Extrinsic pool API type for `Components`. -pub type PoolApi = ::TransactionPoolApi; - -/// A set of traits for the runtime genesis config. -pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {} -impl RuntimeGenesis for T {} - -/// Something that can create and store initial session keys from given seeds. -pub trait InitialSessionKeys { - /// Generate the initial session keys for the given seeds and store them in - /// an internal keystore. - fn generate_initial_session_keys( - client: Arc>, - seeds: Vec, - ) -> error::Result<()>; -} - -impl InitialSessionKeys for C where - ComponentClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: session::SessionKeys>, -{ - fn generate_initial_session_keys( - client: Arc>, - seeds: Vec, - ) -> error::Result<()> { - session::generate_initial_session_keys(client, seeds).map_err(Into::into) - } -} - -/// Something that can start the RPC service. -pub trait StartRPC { - fn start_rpc( - client: Arc>, - system_send_back: mpsc::UnboundedSender>>, - system_info: SystemInfo, - task_executor: TaskExecutor, - transaction_pool: Arc>, - keystore: KeyStorePtr, - ) -> rpc::RpcHandler; -} - -impl StartRPC for C where - ComponentClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: - runtime_api::Metadata> + session::SessionKeys>, -{ - fn start_rpc( - client: Arc>, - system_send_back: mpsc::UnboundedSender>>, - rpc_system_info: SystemInfo, - task_executor: TaskExecutor, - transaction_pool: Arc>, - keystore: KeyStorePtr, - ) -> rpc::RpcHandler { - let subscriptions = rpc::apis::Subscriptions::new(task_executor.clone()); - let chain = rpc::apis::chain::Chain::new(client.clone(), subscriptions.clone()); - let state = rpc::apis::state::State::new(client.clone(), subscriptions.clone()); - let author = rpc::apis::author::Author::new( - client, - transaction_pool, - subscriptions, - keystore, - ); - let system = rpc::apis::system::System::new(rpc_system_info, system_send_back); - rpc::rpc_handler::, ComponentExHash, _, _, _, _>( - state, - chain, - author, - system, - ) - } -} - -/// Something that can maintain transaction pool on every imported block. -pub trait MaintainTransactionPool { - fn maintain_transaction_pool( - id: &BlockId>, - client: &ComponentClient, - transaction_pool: &TransactionPool, - ) -> error::Result<()>; -} - -fn maintain_transaction_pool( - id: &BlockId, - client: &Client, - transaction_pool: &TransactionPool, -) -> error::Result<()> where - Block: BlockT::Out>, - Backend: client::backend::Backend, - Client: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue, - Executor: client::CallExecutor, - PoolApi: txpool::ChainApi, -{ - // Avoid calling into runtime if there is nothing to prune from the pool anyway. - if transaction_pool.status().is_empty() { - return Ok(()) - } - - if let Some(block) = client.block(id)? { - let parent_id = BlockId::hash(*block.block.header().parent_hash()); - let extrinsics = block.block.extrinsics(); - transaction_pool.prune(id, &parent_id, extrinsics).map_err(|e| format!("{:?}", e))?; - } - - Ok(()) -} - -impl MaintainTransactionPool for C where - ComponentClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue>, -{ - fn maintain_transaction_pool( - id: &BlockId>, - client: &ComponentClient, - transaction_pool: &TransactionPool, - ) -> error::Result<()> { - maintain_transaction_pool(id, client, transaction_pool) - } -} - -pub trait OffchainWorker { - fn offchain_workers( - number: &FactoryBlockNumber, - offchain: &offchain::OffchainWorkers< - ComponentClient, - ComponentOffchainStorage, - ComponentBlock - >, - pool: &Arc>, - network_state: &Arc, - is_validator: bool, - ) -> error::Result + Send>>; -} - -impl OffchainWorker for C where - ComponentClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: offchain::OffchainWorkerApi>, -{ - fn offchain_workers( - number: &FactoryBlockNumber, - offchain: &offchain::OffchainWorkers< - ComponentClient, - ComponentOffchainStorage, - ComponentBlock - >, - pool: &Arc>, - network_state: &Arc, - is_validator: bool, - ) -> error::Result + Send>> { - let future = offchain.on_block_imported(number, pool, network_state.clone(), is_validator) - .map(|()| Ok(())); - Ok(Box::new(Compat::new(future))) - } -} - -/// The super trait that combines all required traits a `Service` needs to implement. -pub trait ServiceTrait: - Deref> - + Send - + 'static - + StartRPC - + MaintainTransactionPool - + OffchainWorker - + InitialSessionKeys -{} -impl ServiceTrait for T where - T: Deref> - + Send - + 'static - + StartRPC - + MaintainTransactionPool - + OffchainWorker - + InitialSessionKeys -{} - -/// Alias for a an implementation of `futures::future::Executor`. -pub type TaskExecutor = Arc + Send>> + Send + Sync>; - -/// A collection of types and methods to build a service on top of the substrate service. -pub trait ServiceFactory: 'static + Sized { - /// Block type. - type Block: BlockT; - /// The type that implements the runtime API. - type RuntimeApi: Send + Sync; - /// Network protocol extensions. - type NetworkProtocol: network::specialization::NetworkSpecialization; - /// Chain runtime. - type RuntimeDispatch: NativeExecutionDispatch + Send + Sync + 'static; - /// Extrinsic pool backend type for the full client. - type FullTransactionPoolApi: txpool::ChainApi::Hash, Block = Self::Block> + Send + 'static; - /// Extrinsic pool backend type for the light client. - type LightTransactionPoolApi: txpool::ChainApi::Hash, Block = Self::Block> + 'static; - /// Genesis configuration for the runtime. - type Genesis: RuntimeGenesis; - /// Other configuration for service members. - type Configuration: Default; - /// Extended full service type. - type FullService: ServiceTrait>; - /// Extended light service type. - type LightService: ServiceTrait>; - /// ImportQueue for full client - type FullImportQueue: ImportQueue + 'static; - /// ImportQueue for light clients - type LightImportQueue: ImportQueue + 'static; - /// The Fork Choice Strategy for the chain - type SelectChain: SelectChain + 'static; - - //TODO: replace these with a constructor trait. that TransactionPool implements. (#1242) - /// Extrinsic pool constructor for the full client. - fn build_full_transaction_pool(config: TransactionPoolOptions, client: Arc>) - -> Result, error::Error>; - /// Extrinsic pool constructor for the light client. - fn build_light_transaction_pool(config: TransactionPoolOptions, client: Arc>) - -> Result, error::Error>; - - /// Build network protocol. - fn build_network_protocol(config: &FactoryFullConfiguration) - -> Result; - - /// Build finality proof provider for serving network requests on full node. - fn build_finality_proof_provider( - client: Arc> - ) -> Result>>, error::Error>; - - /// Build the Fork Choice algorithm for full client - fn build_select_chain( - config: &mut FactoryFullConfiguration, - client: Arc>, - ) -> Result; - - /// Build full service. - fn new_full(config: FactoryFullConfiguration) - -> Result; - /// Build light service. - fn new_light(config: FactoryFullConfiguration) - -> Result; - - /// ImportQueue for a full client - fn build_full_import_queue( - config: &mut FactoryFullConfiguration, - _client: Arc>, - _select_chain: Self::SelectChain, - _transaction_pool: Option>>, - ) -> Result { - if let Some(name) = config.chain_spec.consensus_engine() { - match name { - _ => Err(format!("Chain Specification defines unknown consensus engine '{}'", name).into()) - } - - } else { - Err("Chain Specification doesn't contain any consensus_engine name".into()) - } - } - - /// ImportQueue for a light client - fn build_light_import_queue( - config: &mut FactoryFullConfiguration, - _client: Arc> - ) -> Result<(Self::LightImportQueue, BoxFinalityProofRequestBuilder), error::Error> { - if let Some(name) = config.chain_spec.consensus_engine() { - match name { - _ => Err(format!("Chain Specification defines unknown consensus engine '{}'", name).into()) - } - - } else { - Err("Chain Specification doesn't contain any consensus_engine name".into()) - } - } -} - -/// A collection of types and function to generalize over full / light client type. -pub trait Components: Sized + 'static { - /// Associated service factory. - type Factory: ServiceFactory; - /// Client backend. - type Backend: 'static + client::backend::Backend, Blake2Hasher>; - /// Client executor. - type Executor: 'static + client::CallExecutor, Blake2Hasher> + Send + Sync + Clone; - /// The type that implements the runtime API. - type RuntimeApi: Send + Sync; - /// A type that can start all runtime-dependent services. - type RuntimeServices: ServiceTrait; - // TODO: Traitify transaction pool and allow people to implement their own. (#1242) - /// Extrinsic pool type. - type TransactionPoolApi: 'static + txpool::ChainApi< - Hash = as BlockT>::Hash, - Block = FactoryBlock - >; - /// Our Import Queue - type ImportQueue: ImportQueue> + 'static; - /// The Fork Choice Strategy for the chain - type SelectChain: SelectChain>; - - /// Create client. - fn build_client( - config: &FactoryFullConfiguration, - executor: CodeExecutor, - keystore: Option, - ) -> Result< - ( - Arc>, - Option>>> - ), - error::Error - >; - - /// Create extrinsic pool. - fn build_transaction_pool(config: TransactionPoolOptions, client: Arc>) - -> Result, error::Error>; - - /// Build the queue that imports blocks from the network, and optionally a way for the network - /// to build requests for proofs of finality. - fn build_import_queue( - config: &mut FactoryFullConfiguration, - client: Arc>, - select_chain: Option, - _transaction_pool: Option>>, - ) -> Result<(Self::ImportQueue, Option>>), error::Error>; - - /// Finality proof provider for serving network requests. - fn build_finality_proof_provider( - client: Arc> - ) -> Result::Block>>>, error::Error>; - - /// Build fork choice selector - fn build_select_chain( - config: &mut FactoryFullConfiguration, - client: Arc> - ) -> Result, error::Error>; -} - -/// A struct that implement `Components` for the full client. -pub struct FullComponents { - service: Service>, -} - -impl FullComponents { - /// Create new `FullComponents` - pub fn new( - config: FactoryFullConfiguration - ) -> Result { - Ok( - Self { - service: Service::new(config)?, - } - ) - } -} - -impl Deref for FullComponents { - type Target = Service; - - fn deref(&self) -> &Self::Target { - &self.service - } -} - -impl DerefMut for FullComponents { - fn deref_mut(&mut self) -> &mut Service { - &mut self.service - } -} - -impl Future for FullComponents { - type Item = (); - type Error = super::Error; - - fn poll(&mut self) -> Poll { - self.service.poll() - } -} - -impl Executor + Send>> -for FullComponents { - fn execute( - &self, - future: Box + Send> - ) -> Result<(), futures::future::ExecuteError + Send>>> { - self.service.execute(future) - } -} - -impl Components for FullComponents { - type Factory = Factory; - type Executor = FullExecutor; - type Backend = FullBackend; - type TransactionPoolApi = ::FullTransactionPoolApi; - type ImportQueue = Factory::FullImportQueue; - type RuntimeApi = Factory::RuntimeApi; - type RuntimeServices = Factory::FullService; - type SelectChain = Factory::SelectChain; - - fn build_client( - config: &FactoryFullConfiguration, - executor: CodeExecutor, - keystore: Option, - ) -> Result< - (Arc>, Option>>>), - error::Error, - > - { - let db_settings = client_db::DatabaseSettings { - cache_size: config.database_cache_size.map(|u| u as usize), - state_cache_size: config.state_cache_size, - state_cache_child_ratio: - config.state_cache_child_ratio.map(|v| (v, 100)), - path: config.database_path.clone(), - pruning: config.pruning.clone(), - }; - - Ok(( - Arc::new( - client_db::new_client( - db_settings, - executor, - &config.chain_spec, - config.execution_strategies.clone(), - keystore, - )? - ), - None, - )) - } - - fn build_transaction_pool( - config: TransactionPoolOptions, - client: Arc> - ) -> Result, error::Error> { - Factory::build_full_transaction_pool(config, client) - } - - fn build_import_queue( - config: &mut FactoryFullConfiguration, - client: Arc>, - select_chain: Option, - transaction_pool: Option>>, - ) -> Result<(Self::ImportQueue, Option>>), error::Error> { - let select_chain = select_chain - .ok_or(error::Error::SelectChainRequired)?; - Factory::build_full_import_queue(config, client, select_chain, transaction_pool) - .map(|queue| (queue, None)) - } - - fn build_select_chain( - config: &mut FactoryFullConfiguration, - client: Arc> - ) -> Result, error::Error> { - Self::Factory::build_select_chain(config, client).map(Some) - } - - fn build_finality_proof_provider( - client: Arc> - ) -> Result::Block>>>, error::Error> { - Factory::build_finality_proof_provider(client) - } -} - -/// A struct that implement `Components` for the light client. -pub struct LightComponents { - service: Service>, -} - -impl LightComponents { - /// Create new `LightComponents` - pub fn new( - config: FactoryFullConfiguration, - ) -> Result { - Ok( - Self { - service: Service::new(config)?, - } - ) - } -} - -impl Deref for LightComponents { - type Target = Service; - - fn deref(&self) -> &Self::Target { - &self.service - } -} - -impl DerefMut for LightComponents { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.service - } -} - -impl Future for LightComponents { - type Item = (); - type Error = super::Error; - - fn poll(&mut self) -> Poll { - self.service.poll() - } -} - -impl Executor + Send>> -for LightComponents { - fn execute( - &self, - future: Box + Send> - ) -> Result<(), futures::future::ExecuteError + Send>>> { - self.service.execute(future) - } -} - -impl Components for LightComponents { - type Factory = Factory; - type Executor = LightExecutor; - type Backend = LightBackend; - type TransactionPoolApi = ::LightTransactionPoolApi; - type ImportQueue = ::LightImportQueue; - type RuntimeApi = Factory::RuntimeApi; - type RuntimeServices = Factory::LightService; - type SelectChain = Factory::SelectChain; - - fn build_client( - config: &FactoryFullConfiguration, - executor: CodeExecutor, - _: Option, - ) - -> Result< - ( - Arc>, - Option>>> - ), error::Error> - { - let db_settings = client_db::DatabaseSettings { - cache_size: None, - state_cache_size: config.state_cache_size, - state_cache_child_ratio: - config.state_cache_child_ratio.map(|v| (v, 100)), - path: config.database_path.clone(), - pruning: config.pruning.clone(), - }; - - let db_storage = client_db::light::LightStorage::new(db_settings)?; - let light_blockchain = client::light::new_light_blockchain(db_storage); - let fetch_checker = Arc::new( - client::light::new_fetch_checker(light_blockchain.clone(), executor.clone()) - ); - let fetcher = Arc::new(network::OnDemand::new(fetch_checker)); - let client_backend = client::light::new_light_backend(light_blockchain, fetcher.clone()); - let client = client::light::new_light(client_backend, fetcher.clone(), &config.chain_spec, executor)?; - Ok((Arc::new(client), Some(fetcher))) - } - - fn build_transaction_pool(config: TransactionPoolOptions, client: Arc>) - -> Result, error::Error> - { - Factory::build_light_transaction_pool(config, client) - } - - fn build_import_queue( - config: &mut FactoryFullConfiguration, - client: Arc>, - _select_chain: Option, - _transaction_pool: Option>>, - ) -> Result<(Self::ImportQueue, Option>>), error::Error> { - Factory::build_light_import_queue(config, client) - .map(|(queue, builder)| (queue, Some(builder))) - } - - fn build_finality_proof_provider( - _client: Arc> - ) -> Result::Block>>>, error::Error> { - Ok(None) - } - fn build_select_chain( - _config: &mut FactoryFullConfiguration, - _client: Arc> - ) -> Result, error::Error> { - Ok(None) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use consensus_common::BlockOrigin; - use substrate_test_runtime_client::{prelude::*, runtime::Transfer}; - - #[test] - fn should_remove_transactions_from_the_pool() { - let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); - let client = Arc::new(client); - let pool = TransactionPool::new(Default::default(), ::transaction_pool::ChainApi::new(client.clone())); - let transaction = Transfer { - amount: 5, - nonce: 0, - from: AccountKeyring::Alice.into(), - to: Default::default(), - }.into_signed_tx(); - let best = longest_chain.best_chain().unwrap(); - - // store the transaction in the pool - pool.submit_one(&BlockId::hash(best.hash()), transaction.clone()).unwrap(); - - // import the block - let mut builder = client.new_block(Default::default()).unwrap(); - builder.push(transaction.clone()).unwrap(); - let block = builder.bake().unwrap(); - let id = BlockId::hash(block.header().hash()); - client.import(BlockOrigin::Own, block).unwrap(); - - // fire notification - this should clean up the queue - assert_eq!(pool.status().ready, 1); - maintain_transaction_pool( - &id, - &client, - &pool, - ).unwrap(); - - // then - assert_eq!(pool.status().ready, 0); - assert_eq!(pool.status().future, 0); - } -} diff --git a/core/service/src/config.rs b/core/service/src/config.rs index 97eba357e3fead57a6fab1911bcffe192fb23094..e9f002c21f4423e8982c4a9286ac35432d380834 100644 --- a/core/service/src/config.rs +++ b/core/service/src/config.rs @@ -17,21 +17,20 @@ //! Service configuration. pub use client::ExecutionStrategies; -pub use client_db::PruningMode; +pub use client_db::{kvdb::KeyValueDB, PruningMode}; pub use network::config::{ExtTransport, NetworkConfiguration, Roles}; +pub use substrate_executor::WasmExecutionMethod; -use std::{path::PathBuf, net::SocketAddr}; +use std::{path::PathBuf, net::SocketAddr, sync::Arc}; use transaction_pool; -use crate::chain_spec::ChainSpec; +use chain_spec::{ChainSpec, RuntimeGenesis, Extension, NoExtension}; use primitives::crypto::Protected; -use sr_primitives::BuildStorage; -use serde::{Serialize, de::DeserializeOwned}; use target_info::Target; use tel::TelemetryEndpoints; /// Service configuration. #[derive(Clone)] -pub struct Configuration { +pub struct Configuration { /// Implementation name pub impl_name: &'static str, /// Implementation version @@ -44,12 +43,12 @@ pub struct Configuration { pub transaction_pool: transaction_pool::txpool::Options, /// Network configuration. pub network: NetworkConfiguration, + /// Path to the base configuration directory. + pub config_dir: Option, /// Path to key files. - pub keystore_path: PathBuf, - /// Path to the database. - pub database_path: PathBuf, - /// Cache Size for internal database in MiB - pub database_cache_size: Option, + pub keystore_path: Option, + /// Configuration for the database. + pub database: DatabaseConfig, /// Size of internal state cache in Bytes pub state_cache_size: usize, /// Size in percent of cache size dedicated to child tries @@ -57,11 +56,13 @@ pub struct Configuration { /// Pruning settings. pub pruning: PruningMode, /// Chain configuration. - pub chain_spec: ChainSpec, + pub chain_spec: ChainSpec, /// Custom configuration. pub custom: C, /// Node name. pub name: String, + /// Wasm execution method. + pub wasm_method: WasmExecutionMethod, /// Execution strategies. pub execution_strategies: ExecutionStrategies, /// RPC over HTTP binding address. `None` if disabled. @@ -81,6 +82,10 @@ pub struct Configuration { pub default_heap_pages: Option, /// Should offchain workers be executed. pub offchain_worker: bool, + /// Sentry mode is enabled, the node's role is AUTHORITY but it should not + /// actively participate in consensus (i.e. no keystores should be passed to + /// consensus modules). + pub sentry_mode: bool, /// Enable authoring even when offline. pub force_authoring: bool, /// Disable GRANDPA when running in validator mode @@ -95,25 +100,48 @@ pub struct Configuration { pub dev_key_seed: Option, } -impl Configuration { - /// Create default config for given chain spec. - pub fn default_with_spec(chain_spec: ChainSpec) -> Self { +/// Configuration of the database of the client. +#[derive(Clone)] +pub enum DatabaseConfig { + /// Database file at a specific path. Recommended for most uses. + Path { + /// Path to the database. + path: PathBuf, + /// Cache Size for internal database in MiB + cache_size: Option, + }, + + /// A custom implementation of an already-open database. + Custom(Arc), +} + +impl Configuration where + C: Default, + G: RuntimeGenesis, + E: Extension, +{ + /// Create a default config for given chain spec and path to configuration dir + pub fn default_with_spec_and_base_path(chain_spec: ChainSpec, config_dir: Option) -> Self { let mut configuration = Configuration { impl_name: "parity-substrate", impl_version: "0.0.0", impl_commit: "", chain_spec, + config_dir: config_dir.clone(), name: Default::default(), roles: Roles::FULL, transaction_pool: Default::default(), network: Default::default(), - keystore_path: Default::default(), - database_path: Default::default(), - database_cache_size: Default::default(), + keystore_path: config_dir.map(|c| c.join("keystore")), + database: DatabaseConfig::Path { + path: Default::default(), + cache_size: Default::default(), + }, state_cache_size: Default::default(), state_cache_child_ratio: Default::default(), custom: Default::default(), pruning: PruningMode::default(), + wasm_method: WasmExecutionMethod::Interpreted, execution_strategies: Default::default(), rpc_http: None, rpc_ws: None, @@ -123,6 +151,7 @@ impl Configuration Configuration Configuration { /// Returns full version string of this configuration. pub fn full_version(&self) -> String { full_version_from_strs(self.impl_version, self.impl_commit) @@ -144,6 +176,17 @@ impl Configuration String { format!("{}/v{}", self.impl_name, self.full_version()) } + + /// Generate a PathBuf to sub in the chain configuration directory + /// if given + pub fn in_chain_config_dir(&self, sub: &str) -> Option { + self.config_dir.clone().map(|mut path| { + path.push("chains"); + path.push(self.chain_spec.id()); + path.push(sub); + path + }) + } } /// Returns platform info diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index 3b5f438f4f745ac9581f1af6bcbbf14f104aba2e..299876a15b7bd2cfef08eb07fee9786876cc4fac 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -19,13 +19,16 @@ #![warn(missing_docs)] -mod components; -mod chain_spec; pub mod config; +#[macro_use] pub mod chain_ops; pub mod error; +mod builder; +mod status_sinks; + use std::io; +use std::marker::PhantomData; use std::net::SocketAddr; use std::collections::HashMap; use std::sync::atomic::{AtomicBool, Ordering}; @@ -33,37 +36,32 @@ use std::time::{Duration, Instant}; use futures::sync::mpsc; use parking_lot::Mutex; -use client::{BlockchainEvents, backend::Backend, runtime_api::BlockT}; +use client::{runtime_api::BlockT, Client}; use exit_future::Signal; use futures::prelude::*; -use futures03::stream::{StreamExt as _, TryStreamExt as _}; -use keystore::Store as Keystore; -use network::{NetworkState, NetworkStateInfo}; -use log::{log, info, warn, debug, error, Level}; +use futures03::{ + future::{ready, FutureExt as _, TryFutureExt as _}, + stream::{StreamExt as _, TryStreamExt as _}, +}; +use network::{ + NetworkService, NetworkState, specialization::NetworkSpecialization, + Event, DhtEvent, PeerId, ReportHandle, +}; +use log::{log, warn, debug, error, Level}; use codec::{Encode, Decode}; +use primitives::{Blake2Hasher, H256}; use sr_primitives::generic::BlockId; -use sr_primitives::traits::{Header, NumberFor, SaturatedConversion}; -use substrate_executor::NativeExecutor; -use sysinfo::{get_current_pid, ProcessExt, System, SystemExt}; -use tel::{telemetry, SUBSTRATE_INFO}; +use sr_primitives::traits::NumberFor; pub use self::error::Error; +pub use self::builder::{ServiceBuilder, ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert}; pub use config::{Configuration, Roles, PruningMode}; -pub use chain_spec::{ChainSpec, Properties}; +pub use chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension}; pub use transaction_pool::txpool::{ self, Pool as TransactionPool, Options as TransactionPoolOptions, ChainApi, IntoPoolError }; pub use client::FinalityNotifications; - -pub use components::{ - ServiceFactory, FullBackend, FullExecutor, LightBackend, - LightExecutor, Components, PoolApi, ComponentClient, ComponentOffchainStorage, - ComponentBlock, FullClient, LightClient, FullComponents, LightComponents, - CodeExecutor, NetworkService, FactoryChainSpec, FactoryBlock, - FactoryFullConfiguration, RuntimeGenesis, FactoryGenesis, - ComponentExHash, ComponentExtrinsic, FactoryExtrinsic, InitialSessionKeys, -}; -use components::{StartRPC, MaintainTransactionPool, OffchainWorker}; +pub use rpc::Metadata as RpcMetadata; #[doc(hidden)] pub use std::{ops::Deref, result::Result, sync::Arc}; #[doc(hidden)] @@ -74,15 +72,14 @@ pub use futures::future::Executor; const DEFAULT_PROTOCOL_ID: &str = "sup"; /// Substrate service. -pub struct Service { - client: Arc>, - select_chain: Option, - network: Arc>, +pub struct Service { + client: Arc, + select_chain: Option, + network: Arc, /// Sinks to propagate network status updates. - network_status_sinks: Arc>, NetworkState - )>>>>, - transaction_pool: Arc>, + /// For each element, every time the `Interval` fires we push an element on the sender. + network_status_sinks: Arc>>, + transaction_pool: Arc, /// A future that resolves when the service has exited, this is useful to /// make sure any internally spawned futures stop when the service does. exit: exit_future::Exit, @@ -99,44 +96,31 @@ pub struct Service { /// If spawning a background task is not possible, we instead push the task into this `Vec`. /// The elements must then be polled manually. to_poll: Vec + Send>>, - /// Configuration of this Service - config: FactoryFullConfiguration, - rpc_handlers: rpc::RpcHandler, + rpc_handlers: rpc_servers::RpcHandler, _rpc: Box, _telemetry: Option, _telemetry_on_connect_sinks: Arc>>>, - _offchain_workers: Option, - ComponentOffchainStorage, - ComponentBlock> - >>, + _offchain_workers: Option>, keystore: keystore::KeyStorePtr, + marker: PhantomData, } -/// Creates bare client without any networking. -pub fn new_client( - config: &FactoryFullConfiguration, -) -> Result>>, error::Error> { - let executor = NativeExecutor::new(config.default_heap_pages); - - components::FullComponents::::build_client( - config, - executor, - None, - ).map(|r| r.0) -} +/// Alias for a an implementation of `futures::future::Executor`. +pub type TaskExecutor = Arc + Send>> + Send + Sync>; /// An handle for spawning tasks in the service. #[derive(Clone)] pub struct SpawnTaskHandle { sender: mpsc::UnboundedSender + Send>>, + on_exit: exit_future::Exit, } impl Executor + Send>> for SpawnTaskHandle { fn execute( &self, - future: Box + Send> + future: Box + Send>, ) -> Result<(), futures::future::ExecuteError + Send>>> { + let future = Box::new(future.select(self.on_exit.clone()).then(|_| Ok(()))); if let Err(err) = self.sender.unbounded_send(future) { let kind = futures::future::ExecuteErrorKind::Shutdown; Err(futures::future::ExecuteError::new(kind, err.into_inner())) @@ -146,431 +130,166 @@ impl Executor + Send>> for SpawnTaskHandle } } -/// Stream of events for connection established to a telemetry server. -pub type TelemetryOnConnectNotifications = mpsc::UnboundedReceiver<()>; - -/// Used to hook on telemetry connection established events. -pub struct TelemetryOnConnect { - /// Event stream. - pub telemetry_connection_sinks: TelemetryOnConnectNotifications, -} - -impl Service { - /// Creates a new service. - pub fn new( - mut config: FactoryFullConfiguration, - ) -> Result { - let (signal, exit) = exit_future::signal(); - - // List of asynchronous tasks to spawn. We collect them, then spawn them all at once. - let (to_spawn_tx, to_spawn_rx) = - mpsc::unbounded:: + Send>>(); - - // Create client - let executor = NativeExecutor::new(config.default_heap_pages); - - let keystore = Keystore::open(config.keystore_path.clone(), config.keystore_password.clone())?; - - let (client, on_demand) = Components::build_client(&config, executor, Some(keystore.clone()))?; - let select_chain = Components::build_select_chain(&mut config, client.clone())?; - - let transaction_pool = Arc::new( - Components::build_transaction_pool(config.transaction_pool.clone(), client.clone())? - ); - let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { - imports_external_transactions: !config.roles.is_light(), - pool: transaction_pool.clone(), - client: client.clone(), - }); +/// Abstraction over a Substrate service. +pub trait AbstractService: 'static + Future + + Executor + Send>> + Send { + /// Type of block of this chain. + type Block: BlockT; + /// Backend storage for the client. + type Backend: 'static + client::backend::Backend; + /// How to execute calls towards the runtime. + type CallExecutor: 'static + client::CallExecutor + Send + Sync + Clone; + /// API that the runtime provides. + type RuntimeApi: Send + Sync; + /// Chain selection algorithm. + type SelectChain: consensus_common::SelectChain; + /// API of the transaction pool. + type TransactionPoolApi: ChainApi; + /// Network specialization. + type NetworkSpecialization: NetworkSpecialization; - let (import_queue, finality_proof_request_builder) = Components::build_import_queue( - &mut config, - client.clone(), - select_chain.clone(), - Some(transaction_pool.clone()), - )?; - let import_queue = Box::new(import_queue); - let finality_proof_provider = Components::build_finality_proof_provider(client.clone())?; - let chain_info = client.info().chain; - - Components::RuntimeServices::generate_initial_session_keys( - client.clone(), - config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), - )?; - - let version = config.full_version(); - info!("Highest known block at #{}", chain_info.best_number); - telemetry!( - SUBSTRATE_INFO; - "node.start"; - "height" => chain_info.best_number.saturated_into::(), - "best" => ?chain_info.best_hash - ); - - let network_protocol = ::build_network_protocol(&config)?; - - let protocol_id = { - let protocol_id_full = match config.chain_spec.protocol_id() { - Some(pid) => pid, - None => { - warn!("Using default protocol ID {:?} because none is configured in the \ - chain specs", DEFAULT_PROTOCOL_ID - ); - DEFAULT_PROTOCOL_ID - } - }.as_bytes(); - network::config::ProtocolId::from(protocol_id_full) - }; + /// Get event stream for telemetry connection established events. + fn telemetry_on_connect_stream(&self) -> mpsc::UnboundedReceiver<()>; - let network_params = network::config::Params { - roles: config.roles, - network_config: config.network.clone(), - chain: client.clone(), - finality_proof_provider, - finality_proof_request_builder, - on_demand, - transaction_pool: transaction_pool_adapter.clone() as _, - import_queue, - protocol_id, - specialization: network_protocol, - }; + /// return a shared instance of Telemetry (if enabled) + fn telemetry(&self) -> Option; - let has_bootnodes = !network_params.network_config.boot_nodes.is_empty(); - let network_mut = network::NetworkWorker::new(network_params)?; - let network = network_mut.service().clone(); - let network_status_sinks = Arc::new(Mutex::new(Vec::new())); - - #[allow(deprecated)] - let offchain_storage = client.backend().offchain_storage(); - let offchain_workers = match (config.offchain_worker, offchain_storage) { - (true, Some(db)) => { - Some(Arc::new(offchain::OffchainWorkers::new(client.clone(), db))) - }, - (true, None) => { - log::warn!("Offchain workers disabled, due to lack of offchain storage support in backend."); - None - }, - _ => None, - }; + /// Spawns a task in the background that runs the future passed as parameter. + fn spawn_task(&self, task: impl Future + Send + 'static); - { - // block notifications - let txpool = Arc::downgrade(&transaction_pool); - let wclient = Arc::downgrade(&client); - let offchain = offchain_workers.as_ref().map(Arc::downgrade); - let to_spawn_tx_ = to_spawn_tx.clone(); - let network_state_info: Arc = network.clone(); - let is_validator = config.roles.is_authority(); - - let events = client.import_notification_stream() - .map(|v| Ok::<_, ()>(v)).compat() - .for_each(move |notification| { - let number = *notification.header.number(); - - if let (Some(txpool), Some(client)) = (txpool.upgrade(), wclient.upgrade()) { - Components::RuntimeServices::maintain_transaction_pool( - &BlockId::hash(notification.hash), - &*client, - &*txpool, - ).map_err(|e| warn!("Pool error processing new block: {:?}", e))?; - } + /// Spawns a task in the background that runs the future passed as + /// parameter. The given task is considered essential, i.e. if it errors we + /// trigger a service exit. + fn spawn_essential_task(&self, task: impl Future + Send + 'static); - if let (Some(txpool), Some(offchain)) = (txpool.upgrade(), offchain.as_ref().and_then(|o| o.upgrade())) { - let future = Components::RuntimeServices::offchain_workers( - &number, - &offchain, - &txpool, - &network_state_info, - is_validator, - ).map_err(|e| warn!("Offchain workers error processing new block: {:?}", e))?; - let _ = to_spawn_tx_.unbounded_send(future); - } + /// Returns a handle for spawning tasks. + fn spawn_task_handle(&self) -> SpawnTaskHandle; - Ok(()) - }) - .select(exit.clone()) - .then(|_| Ok(())); - let _ = to_spawn_tx.unbounded_send(Box::new(events)); - } + /// Returns the keystore that stores keys. + fn keystore(&self) -> keystore::KeyStorePtr; - { - // extrinsic notifications - let network = Arc::downgrade(&network); - let transaction_pool_ = transaction_pool.clone(); - let events = transaction_pool.import_notification_stream() - .for_each(move |_| { - if let Some(network) = network.upgrade() { - network.trigger_repropagate(); - } - let status = transaction_pool_.status(); - telemetry!(SUBSTRATE_INFO; "txpool.import"; - "ready" => status.ready, - "future" => status.future - ); - Ok(()) - }) - .select(exit.clone()) - .then(|_| Ok(())); - - let _ = to_spawn_tx.unbounded_send(Box::new(events)); - } + /// Starts an RPC query. + /// + /// The query is passed as a string and must be a JSON text similar to what an HTTP client + /// would for example send. + /// + /// Returns a `Future` that contains the optional response. + /// + /// If the request subscribes you to events, the `Sender` in the `RpcSession` object is used to + /// send back spontaneous events. + fn rpc_query(&self, mem: &RpcSession, request: &str) -> Box, Error = ()> + Send>; - // Periodically notify the telemetry. - let transaction_pool_ = transaction_pool.clone(); - let client_ = client.clone(); - let mut sys = System::new(); - let self_pid = get_current_pid().ok(); - let (netstat_tx, netstat_rx) = mpsc::unbounded::<(NetworkStatus>, NetworkState)>(); - network_status_sinks.lock().push(netstat_tx); - let tel_task = netstat_rx.for_each(move |(net_status, network_state)| { - let info = client_.info(); - let best_number = info.chain.best_number.saturated_into::(); - let best_hash = info.chain.best_hash; - let num_peers = net_status.num_connected_peers; - let txpool_status = transaction_pool_.status(); - let finalized_number: u64 = info.chain.finalized_number.saturated_into::(); - let bandwidth_download = net_status.average_download_per_sec; - let bandwidth_upload = net_status.average_upload_per_sec; - - #[allow(deprecated)] - let backend = (*client_).backend(); - let used_state_cache_size = match backend.used_state_cache_size(){ - Some(size) => size, - None => 0, - }; + /// Get shared client instance. + fn client(&self) -> Arc>; - // get cpu usage and memory usage of this process - let (cpu_usage, memory) = if let Some(self_pid) = self_pid { - if sys.refresh_process(self_pid) { - let proc = sys.get_process(self_pid) - .expect("Above refresh_process succeeds, this should be Some(), qed"); - (proc.cpu_usage(), proc.memory()) - } else { (0.0, 0) } - } else { (0.0, 0) }; - - telemetry!( - SUBSTRATE_INFO; - "system.interval"; - "network_state" => network_state, - "peers" => num_peers, - "height" => best_number, - "best" => ?best_hash, - "txcount" => txpool_status.ready, - "cpu" => cpu_usage, - "memory" => memory, - "finalized_height" => finalized_number, - "finalized_hash" => ?info.chain.finalized_hash, - "bandwidth_download" => bandwidth_download, - "bandwidth_upload" => bandwidth_upload, - "used_state_cache_size" => used_state_cache_size, - ); + /// Get clone of select chain. + fn select_chain(&self) -> Option; - Ok(()) - }).select(exit.clone()).then(|_| Ok(())); - let _ = to_spawn_tx.unbounded_send(Box::new(tel_task)); - - // RPC - let (system_rpc_tx, system_rpc_rx) = futures03::channel::mpsc::unbounded(); - let gen_handler = || { - let system_info = rpc::apis::system::SystemInfo { - chain_name: config.chain_spec.name().into(), - impl_name: config.impl_name.into(), - impl_version: config.impl_version.into(), - properties: config.chain_spec.properties(), - }; - Components::RuntimeServices::start_rpc( - client.clone(), - system_rpc_tx.clone(), - system_info.clone(), - Arc::new(SpawnTaskHandle { sender: to_spawn_tx.clone() }), - transaction_pool.clone(), - keystore.clone(), - ) - }; - let rpc_handlers = gen_handler(); - let rpc = start_rpc_servers(&config, gen_handler)?; - - let _ = to_spawn_tx.unbounded_send(Box::new(build_network_future( - network_mut, - client.clone(), - network_status_sinks.clone(), - system_rpc_rx, - has_bootnodes - ) - .map_err(|_| ()) - .select(exit.clone()) - .then(|_| Ok(())))); - - let telemetry_connection_sinks: Arc>>> = Default::default(); - - // Telemetry - let telemetry = config.telemetry_endpoints.clone().map(|endpoints| { - let is_authority = config.roles.is_authority(); - let network_id = network.local_peer_id().to_base58(); - let name = config.name.clone(); - let impl_name = config.impl_name.to_owned(); - let version = version.clone(); - let chain_name = config.chain_spec.name().to_owned(); - let telemetry_connection_sinks_ = telemetry_connection_sinks.clone(); - let telemetry = tel::init_telemetry(tel::TelemetryConfig { - endpoints, - wasm_external_transport: config.telemetry_external_transport.take(), - }); - let future = telemetry.clone() - .map(|ev| Ok::<_, ()>(ev)) - .compat() - .for_each(move |event| { - // Safe-guard in case we add more events in the future. - let tel::TelemetryEvent::Connected = event; - - telemetry!(SUBSTRATE_INFO; "system.connected"; - "name" => name.clone(), - "implementation" => impl_name.clone(), - "version" => version.clone(), - "config" => "", - "chain" => chain_name.clone(), - "authority" => is_authority, - "network_id" => network_id.clone() - ); - - telemetry_connection_sinks_.lock().retain(|sink| { - sink.unbounded_send(()).is_ok() - }); - Ok(()) - }); - let _ = to_spawn_tx.unbounded_send(Box::new(future - .select(exit.clone()) - .then(|_| Ok(())))); - telemetry - }); + /// Get shared network instance. + fn network(&self) -> Arc>; - Ok(Service { - client, - network, - network_status_sinks, - select_chain, - transaction_pool, - exit, - signal: Some(signal), - essential_failed: Arc::new(AtomicBool::new(false)), - to_spawn_tx, - to_spawn_rx, - to_poll: Vec::new(), - config, - rpc_handlers, - _rpc: rpc, - _telemetry: telemetry, - _offchain_workers: offchain_workers, - _telemetry_on_connect_sinks: telemetry_connection_sinks.clone(), - keystore, - }) - } + /// Returns a receiver that periodically receives a status of the network. + fn network_status(&self, interval: Duration) -> mpsc::UnboundedReceiver<(NetworkStatus, NetworkState)>; - /// Returns a reference to the config passed at initialization. - pub fn config(&self) -> &FactoryFullConfiguration { - &self.config - } + /// Get shared transaction pool instance. + fn transaction_pool(&self) -> Arc>; - /// Returns a reference to the config passed at initialization. - /// - /// > **Note**: This method is currently necessary because we extract some elements from the - /// > configuration at the end of the service initialization. It is intended to be - /// > removed. - pub fn config_mut(&mut self) -> &mut FactoryFullConfiguration { - &mut self.config - } + /// Get a handle to a future that will resolve on exit. + fn on_exit(&self) -> ::exit_future::Exit; +} - /// Get event stream for telemetry connection established events. - pub fn telemetry_on_connect_stream(&self) -> TelemetryOnConnectNotifications { +impl AbstractService for + Service, TSc, NetworkStatus, + NetworkService, TransactionPool, TOc> +where + TBl: BlockT, + TBackend: 'static + client::backend::Backend, + TExec: 'static + client::CallExecutor + Send + Sync + Clone, + TRtApi: 'static + Send + Sync, + TSc: consensus_common::SelectChain + 'static + Clone + Send, + TExPoolApi: 'static + ChainApi, + TOc: 'static + Send + Sync, + TNetSpec: NetworkSpecialization, +{ + type Block = TBl; + type Backend = TBackend; + type CallExecutor = TExec; + type RuntimeApi = TRtApi; + type SelectChain = TSc; + type TransactionPoolApi = TExPoolApi; + type NetworkSpecialization = TNetSpec; + + fn telemetry_on_connect_stream(&self) -> mpsc::UnboundedReceiver<()> { let (sink, stream) = mpsc::unbounded(); self._telemetry_on_connect_sinks.lock().push(sink); stream } - /// Return a shared instance of Telemetry (if enabled) - pub fn telemetry(&self) -> Option { + fn telemetry(&self) -> Option { self._telemetry.as_ref().map(|t| t.clone()) } - /// Returns the keystore instance. - pub fn keystore(&self) -> keystore::KeyStorePtr { + fn keystore(&self) -> keystore::KeyStorePtr { self.keystore.clone() } - /// Spawns a task in the background that runs the future passed as parameter. - pub fn spawn_task(&self, task: impl Future + Send + 'static) { + fn spawn_task(&self, task: impl Future + Send + 'static) { + let task = task.select(self.on_exit()).then(|_| Ok(())); let _ = self.to_spawn_tx.unbounded_send(Box::new(task)); } - /// Spawns a task in the background that runs the future passed as - /// parameter. The given task is considered essential, i.e. if it errors we - /// trigger a service exit. - pub fn spawn_essential_task(&self, task: impl Future + Send + 'static) { + fn spawn_essential_task(&self, task: impl Future + Send + 'static) { let essential_failed = self.essential_failed.clone(); - let essential_task = Box::new(task.map_err(move |_| { + let essential_task = task.map_err(move |_| { error!("Essential task failed. Shutting down service."); essential_failed.store(true, Ordering::Relaxed); - })); + }); + let task = essential_task.select(self.on_exit()).then(|_| Ok(())); - let _ = self.to_spawn_tx.unbounded_send(essential_task); + let _ = self.to_spawn_tx.unbounded_send(Box::new(task)); } - /// Returns a handle for spawning tasks. - pub fn spawn_task_handle(&self) -> SpawnTaskHandle { + fn spawn_task_handle(&self) -> SpawnTaskHandle { SpawnTaskHandle { sender: self.to_spawn_tx.clone(), + on_exit: self.on_exit(), } } - /// Starts an RPC query. - /// - /// The query is passed as a string and must be a JSON text similar to what an HTTP client - /// would for example send. - /// - /// Returns a `Future` that contains the optional response. - /// - /// If the request subscribes you to events, the `Sender` in the `RpcSession` object is used to - /// send back spontaneous events. - pub fn rpc_query(&self, mem: &RpcSession, request: &str) - -> impl Future, Error = ()> - { - self.rpc_handlers.handle_request(request, mem.metadata.clone()) + fn rpc_query(&self, mem: &RpcSession, request: &str) -> Box, Error = ()> + Send> { + Box::new(self.rpc_handlers.handle_request(request, mem.metadata.clone())) } - /// Get shared client instance. - pub fn client(&self) -> Arc> { + fn client(&self) -> Arc> { self.client.clone() } - /// Get clone of select chain. - pub fn select_chain(&self) -> Option<::SelectChain> { + fn select_chain(&self) -> Option { self.select_chain.clone() } - /// Get shared network instance. - pub fn network(&self) -> Arc> { + fn network(&self) -> Arc> { self.network.clone() } - /// Returns a receiver that periodically receives a status of the network. - pub fn network_status(&self) -> mpsc::UnboundedReceiver<(NetworkStatus>, NetworkState)> { + fn network_status(&self, interval: Duration) -> mpsc::UnboundedReceiver<(NetworkStatus, NetworkState)> { let (sink, stream) = mpsc::unbounded(); - self.network_status_sinks.lock().push(sink); + self.network_status_sinks.lock().push(interval, sink); stream } - /// Get shared transaction pool instance. - pub fn transaction_pool(&self) -> Arc> { + fn transaction_pool(&self) -> Arc> { self.transaction_pool.clone() } - /// Get a handle to a future that will resolve on exit. - pub fn on_exit(&self) -> ::exit_future::Exit { + fn on_exit(&self) -> exit_future::Exit { self.exit.clone() } } -impl Future for Service where Components: components::Components { +impl Future for + Service +{ type Item = (); type Error = Error; @@ -593,7 +312,7 @@ impl Future for Service where Components: components::Co // Polling all the `to_poll` futures. while let Some(pos) = self.to_poll.iter_mut().position(|t| t.poll().map(|t| t.is_ready()).unwrap_or(true)) { - self.to_poll.remove(pos); + let _ = self.to_poll.remove(pos); } // The service future never ends. @@ -601,8 +320,8 @@ impl Future for Service where Components: components::Co } } -impl Executor + Send>> - for Service where Components: components::Components +impl Executor + Send>> for + Service { fn execute( &self, @@ -626,20 +345,18 @@ fn build_network_future< S: network::specialization::NetworkSpecialization, H: network::ExHashT > ( + roles: Roles, mut network: network::NetworkWorker, client: Arc, - status_sinks: Arc, NetworkState)>>>>, - rpc_rx: futures03::channel::mpsc::UnboundedReceiver>, + status_sinks: Arc, NetworkState)>>>, + rpc_rx: futures03::channel::mpsc::UnboundedReceiver>, should_have_peers: bool, + dht_event_tx: Option>, ) -> impl Future { - // Compatibility shim while we're transitionning to stable Futures. + // Compatibility shim while we're transitioning to stable Futures. // See https://github.com/paritytech/substrate/issues/3099 let mut rpc_rx = futures03::compat::Compat::new(rpc_rx.map(|v| Ok::<_, ()>(v))); - // Interval at which we send status updates on the status stream. - const STATUS_INTERVAL: Duration = Duration::from_millis(5000); - let mut status_interval = tokio_timer::Interval::new_interval(STATUS_INTERVAL); - let mut imported_blocks_stream = client.import_notification_stream().fuse() .map(|v| Ok::<_, ()>(v)).compat(); let mut finality_notification_stream = client.finality_notification_stream().fuse() @@ -650,7 +367,7 @@ fn build_network_future< // We poll `imported_blocks_stream`. while let Ok(Async::Ready(Some(notification))) = imported_blocks_stream.poll() { - network.on_block_imported(notification.hash, notification.header); + network.on_block_imported(notification.hash, notification.header, Vec::new(), notification.is_new_best); } // We poll `finality_notification_stream`, but we only take the last event. @@ -665,16 +382,16 @@ fn build_network_future< // Poll the RPC requests and answer them. while let Ok(Async::Ready(Some(request))) = rpc_rx.poll() { match request { - rpc::apis::system::Request::Health(sender) => { - let _ = sender.send(rpc::apis::system::Health { + rpc::system::Request::Health(sender) => { + let _ = sender.send(rpc::system::Health { peers: network.peers_debug_info().len(), is_syncing: network.service().is_major_syncing(), should_have_peers, }); }, - rpc::apis::system::Request::Peers(sender) => { + rpc::system::Request::Peers(sender) => { let _ = sender.send(network.peers_debug_info().into_iter().map(|(peer_id, p)| - rpc::apis::system::PeerInfo { + rpc::system::PeerInfo { peer_id: peer_id.to_base58(), roles: format!("{:?}", p.roles), protocol_version: p.protocol_version, @@ -683,14 +400,31 @@ fn build_network_future< } ).collect()); } - rpc::apis::system::Request::NetworkState(sender) => { - let _ = sender.send(network.network_state()); + rpc::system::Request::NetworkState(sender) => { + if let Some(network_state) = serde_json::to_value(&network.network_state()).ok() { + let _ = sender.send(network_state); + } + } + rpc::system::Request::NodeRoles(sender) => { + use rpc::system::NodeRole; + + let node_roles = (0 .. 8) + .filter(|&bit_number| (roles.bits() >> bit_number) & 1 == 1) + .map(|bit_number| match Roles::from_bits(1 << bit_number) { + Some(Roles::AUTHORITY) => NodeRole::Authority, + Some(Roles::LIGHT) => NodeRole::LightClient, + Some(Roles::FULL) => NodeRole::Full, + _ => NodeRole::UnknownRole(bit_number), + }) + .collect(); + + let _ = sender.send(node_roles); } }; } // Interval report for the external API. - while let Ok(Async::Ready(_)) = status_interval.poll() { + status_sinks.lock().poll(|| { let status = NetworkStatus { sync_state: network.sync_state(), best_seen_block: network.best_seen_block(), @@ -701,22 +435,31 @@ fn build_network_future< average_upload_per_sec: network.average_upload_per_sec(), }; let state = network.network_state(); - - status_sinks.lock().retain(|sink| sink.unbounded_send((status.clone(), state.clone())).is_ok()); - } + (status, state) + }); // Main network polling. - match network.poll() { - Ok(Async::NotReady) => {} - Err(err) => warn!(target: "service", "Error in network: {:?}", err), - Ok(Async::Ready(())) => warn!(target: "service", "Network service finished"), - } + while let Ok(Async::Ready(Some(Event::Dht(event)))) = network.poll().map_err(|err| { + warn!(target: "service", "Error in network: {:?}", err); + }) { + // Given that core/authority-discovery is the only upper stack consumer of Dht events at the moment, all Dht + // events are being passed on to the authority-discovery module. In the future there might be multiple + // consumers of these events. In that case this would need to be refactored to properly dispatch the events, + // e.g. via a subscriber model. + if let Some(Err(e)) = dht_event_tx.as_ref().map(|c| c.clone().try_send(event)) { + if e.is_full() { + warn!(target: "service", "Dht event channel to authority discovery is full, dropping event."); + } else if e.is_disconnected() { + warn!(target: "service", "Dht event channel to authority discovery is disconnected, dropping event."); + } + } + }; // Now some diagnostic for performances. let polling_dur = before_polling.elapsed(); log!( target: "service", - if polling_dur >= Duration::from_millis(50) { Level::Debug } else { Level::Trace }, + if polling_dur >= Duration::from_secs(1) { Level::Warn } else { Level::Trace }, "Polling the network future took {:?}", polling_dur ); @@ -744,7 +487,9 @@ pub struct NetworkStatus { pub average_upload_per_sec: u64, } -impl Drop for Service where Components: components::Components { +impl Drop for + Service +{ fn drop(&mut self) { debug!(target: "service", "Substrate service shutdown"); if let Some(signal) = self.signal.take() { @@ -755,8 +500,8 @@ impl Drop for Service where Components: components::Comp /// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. #[cfg(not(target_os = "unknown"))] -fn start_rpc_servers rpc::RpcHandler>( - config: &Configuration, +fn start_rpc_servers rpc_servers::RpcHandler>( + config: &Configuration, mut gen_handler: H ) -> Result, error::Error> { fn maybe_start_server(address: Option, mut start: F) -> Result, io::Error> @@ -780,11 +525,11 @@ fn start_rpc_servers rpc::RpcHandler>( Ok(Box::new(( maybe_start_server( config.rpc_http, - |address| rpc::start_http(address, config.rpc_cors.as_ref(), gen_handler()), + |address| rpc_servers::start_http(address, config.rpc_cors.as_ref(), gen_handler()), )?, maybe_start_server( config.rpc_ws, - |address| rpc::start_ws( + |address| rpc_servers::start_ws( address, config.rpc_ws_max_connections, config.rpc_cors.as_ref(), @@ -796,15 +541,16 @@ fn start_rpc_servers rpc::RpcHandler>( /// Starts RPC servers that run in their own thread, and returns an opaque object that keeps them alive. #[cfg(target_os = "unknown")] -fn start_rpc_servers rpc::RpcHandler>( - _: &Configuration, +fn start_rpc_servers rpc_servers::RpcHandler>( + _: &Configuration, _: H -) -> Result, error::Error> { +) -> Result, error::Error> { Ok(Box::new(())) } /// An RPC session. Used to perform in-memory RPC queries (ie. RPC queries that don't go through /// the HTTP or WebSockets server). +#[derive(Clone)] pub struct RpcSession { metadata: rpc::Metadata, } @@ -818,7 +564,7 @@ impl RpcSession { /// The `RpcSession` must be kept alive in order to receive messages on the sender. pub fn new(sender: mpsc::Sender) -> RpcSession { RpcSession { - metadata: rpc::Metadata::new(sender), + metadata: sender.into(), } } } @@ -828,6 +574,7 @@ pub struct TransactionPoolAdapter { imports_external_transactions: bool, pool: Arc

, client: Arc, + executor: TaskExecutor, } /// Get transactions for propagation. @@ -838,7 +585,7 @@ fn transactions_to_propagate(pool: &TransactionPool) where PoolApi: ChainApi, B: BlockT, - H: std::hash::Hash + Eq + sr_primitives::traits::Member + serde::Serialize, + H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, E: txpool::error::IntoPoolError + From, { pool.ready() @@ -855,47 +602,59 @@ impl network::TransactionPool for TransactionPoolAdapter> where C: network::ClientHandle + Send + Sync, - PoolApi: ChainApi, + PoolApi: 'static + ChainApi, B: BlockT, - H: std::hash::Hash + Eq + sr_primitives::traits::Member + serde::Serialize, + H: std::hash::Hash + Eq + sr_primitives::traits::Member + sr_primitives::traits::MaybeSerialize, E: txpool::error::IntoPoolError + From, { fn transactions(&self) -> Vec<(H, ::Extrinsic)> { transactions_to_propagate(&self.pool) } - fn import(&self, transaction: &::Extrinsic) -> Option { + fn hash_of(&self, transaction: &B::Extrinsic) -> H { + self.pool.hash_of(transaction) + } + + fn import( + &self, + report_handle: ReportHandle, + who: PeerId, + reputation_change_good: i32, + reputation_change_bad: i32, + transaction: B::Extrinsic + ) { if !self.imports_external_transactions { debug!("Transaction rejected"); - return None; + return; } let encoded = transaction.encode(); match Decode::decode(&mut &encoded[..]) { Ok(uxt) => { let best_block_id = BlockId::hash(self.client.info().chain.best_hash); - match self.pool.submit_one(&best_block_id, uxt) { - Ok(hash) => Some(hash), - Err(e) => match e.into_pool_error() { - Ok(txpool::error::Error::AlreadyImported(hash)) => { - hash.downcast::().ok() - .map(|x| x.as_ref().clone()) - }, - Ok(e) => { - debug!("Error adding transaction to the pool: {:?}", e); - None - }, - Err(e) => { - debug!("Error converting pool error: {:?}", e); - None - }, - } + let import_future = self.pool.submit_one(&best_block_id, uxt); + let import_future = import_future + .then(move |import_result| { + match import_result { + Ok(_) => report_handle.report_peer(who, reputation_change_good), + Err(e) => match e.into_pool_error() { + Ok(txpool::error::Error::AlreadyImported(_)) => (), + Ok(e) => { + report_handle.report_peer(who, reputation_change_bad); + debug!("Error adding transaction to the pool: {:?}", e) + } + Err(e) => debug!("Error converting pool error: {:?}", e), + } + } + ready(Ok(())) + }) + .compat(); + + if let Err(e) = self.executor.execute(Box::new(import_future)) { + warn!("Error scheduling extrinsic import: {:?}", e); } } - Err(e) => { - debug!("Error decoding transaction {}", e); - None - } + Err(e) => debug!("Error decoding transaction {}", e), } } @@ -991,123 +750,10 @@ where /// } /// } /// ``` -#[macro_export] -macro_rules! construct_service_factory { - ( - $(#[$attr:meta])* - struct $name:ident { - Block = $block:ty, - RuntimeApi = $runtime_api:ty, - NetworkProtocol = $protocol:ty { $( $protocol_init:tt )* }, - RuntimeDispatch = $dispatch:ty, - FullTransactionPoolApi = $full_transaction:ty { $( $full_transaction_init:tt )* }, - LightTransactionPoolApi = $light_transaction:ty { $( $light_transaction_init:tt )* }, - Genesis = $genesis:ty, - Configuration = $config:ty, - FullService = $full_service:ty { $( $full_service_init:tt )* }, - AuthoritySetup = { $( $authority_setup:tt )* }, - LightService = $light_service:ty { $( $light_service_init:tt )* }, - FullImportQueue = $full_import_queue:ty - { $( $full_import_queue_init:tt )* }, - LightImportQueue = $light_import_queue:ty - { $( $light_import_queue_init:tt )* }, - SelectChain = $select_chain:ty - { $( $select_chain_init:tt )* }, - FinalityProofProvider = { $( $finality_proof_provider_init:tt )* }, - } - ) => { - $( #[$attr] )* - pub struct $name {} - - #[allow(unused_variables)] - impl $crate::ServiceFactory for $name { - type Block = $block; - type RuntimeApi = $runtime_api; - type NetworkProtocol = $protocol; - type RuntimeDispatch = $dispatch; - type FullTransactionPoolApi = $full_transaction; - type LightTransactionPoolApi = $light_transaction; - type Genesis = $genesis; - type Configuration = $config; - type FullService = $full_service; - type LightService = $light_service; - type FullImportQueue = $full_import_queue; - type LightImportQueue = $light_import_queue; - type SelectChain = $select_chain; - - fn build_full_transaction_pool( - config: $crate::TransactionPoolOptions, - client: $crate::Arc<$crate::FullClient> - ) -> $crate::Result<$crate::TransactionPool, $crate::Error> - { - ( $( $full_transaction_init )* ) (config, client) - } - - fn build_light_transaction_pool( - config: $crate::TransactionPoolOptions, - client: $crate::Arc<$crate::LightClient> - ) -> $crate::Result<$crate::TransactionPool, $crate::Error> - { - ( $( $light_transaction_init )* ) (config, client) - } - - fn build_network_protocol(config: &$crate::FactoryFullConfiguration) - -> $crate::Result - { - ( $( $protocol_init )* ) (config) - } - - fn build_select_chain( - config: &mut $crate::FactoryFullConfiguration, - client: Arc<$crate::FullClient> - ) -> $crate::Result { - ( $( $select_chain_init )* ) (config, client) - } - - fn build_full_import_queue( - config: &mut $crate::FactoryFullConfiguration, - client: $crate::Arc<$crate::FullClient>, - select_chain: Self::SelectChain, - transaction_pool: Option>>, - ) -> $crate::Result { - ( $( $full_import_queue_init )* ) (config, client, select_chain, transaction_pool) - } - - fn build_light_import_queue( - config: &mut FactoryFullConfiguration, - client: Arc<$crate::LightClient>, - ) -> Result<(Self::LightImportQueue, $crate::BoxFinalityProofRequestBuilder<$block>), $crate::Error> { - ( $( $light_import_queue_init )* ) (config, client) - } - - fn build_finality_proof_provider( - client: Arc<$crate::FullClient> - ) -> Result>>, $crate::Error> { - ( $( $finality_proof_provider_init )* ) (client) - } - - fn new_light( - config: $crate::FactoryFullConfiguration - ) -> $crate::Result - { - ( $( $light_service_init )* ) (config) - } - - fn new_full( - config: $crate::FactoryFullConfiguration - ) -> Result - { - ( $( $full_service_init )* ) (config).and_then(|service| { - ($( $authority_setup )*)(service) - }) - } - } - } -} - #[cfg(test)] mod tests { use super::*; + use futures03::executor::block_on; use consensus_common::SelectChain; use sr_primitives::traits::BlindCheckable; use substrate_test_runtime_client::{prelude::*, runtime::{Extrinsic, Transfer}}; @@ -1119,7 +765,7 @@ mod tests { let client = Arc::new(client); let pool = Arc::new(TransactionPool::new( Default::default(), - transaction_pool::ChainApi::new(client.clone()) + transaction_pool::FullChainApi::new(client.clone()) )); let best = longest_chain.best_chain().unwrap(); let transaction = Transfer { @@ -1128,8 +774,8 @@ mod tests { from: AccountKeyring::Alice.into(), to: Default::default(), }.into_signed_tx(); - pool.submit_one(&BlockId::hash(best.hash()), transaction.clone()).unwrap(); - pool.submit_one(&BlockId::hash(best.hash()), Extrinsic::IncludeData(vec![1])).unwrap(); + block_on(pool.submit_one(&BlockId::hash(best.hash()), transaction.clone())).unwrap(); + block_on(pool.submit_one(&BlockId::hash(best.hash()), Extrinsic::IncludeData(vec![1]))).unwrap(); assert_eq!(pool.status().ready, 2); // when diff --git a/core/service/src/status_sinks.rs b/core/service/src/status_sinks.rs new file mode 100644 index 0000000000000000000000000000000000000000..079ecf6353b1fe125028e91dc13aabb0e7729f6f --- /dev/null +++ b/core/service/src/status_sinks.rs @@ -0,0 +1,149 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use futures::prelude::*; +use futures::sync::mpsc; +use futures::stream::futures_unordered::FuturesUnordered; +use std::time::{Duration, Instant}; +use tokio_timer::Delay; + +/// Holds a list of `UnboundedSender`s, each associated with a certain time period. Every time the +/// period elapses, we push an element on the sender. +/// +/// Senders are removed only when they are closed. +pub struct StatusSinks { + entries: FuturesUnordered>, +} + +struct YieldAfter { + delay: tokio_timer::Delay, + interval: Duration, + sender: Option>, +} + +impl StatusSinks { + /// Builds a new empty collection. + pub fn new() -> StatusSinks { + StatusSinks { + entries: FuturesUnordered::new(), + } + } + + /// Adds a sender to the collection. + /// + /// The `interval` is the time period between two pushes on the sender. + pub fn push(&mut self, interval: Duration, sender: mpsc::UnboundedSender) { + self.entries.push(YieldAfter { + delay: Delay::new(Instant::now() + interval), + interval, + sender: Some(sender), + }) + } + + /// Processes all the senders. If any sender is ready, calls the `status_grab` function and + /// pushes what it returns to the sender. + /// + /// This function doesn't return anything, but it should be treated as if it implicitly + /// returns `Ok(Async::NotReady)`. In particular, it should be called again when the task + /// is waken up. + /// + /// # Panic + /// + /// Panics if not called within the context of a task. + pub fn poll(&mut self, mut status_grab: impl FnMut() -> T) { + loop { + match self.entries.poll() { + Ok(Async::Ready(Some((sender, interval)))) => { + let status = status_grab(); + if sender.unbounded_send(status).is_ok() { + self.entries.push(YieldAfter { + // Note that since there's a small delay between the moment a task is + // waken up and the moment it is polled, the period is actually not + // `interval` but `interval + `. We ignore this problem in + // practice. + delay: Delay::new(Instant::now() + interval), + interval, + sender: Some(sender), + }); + } + } + Err(()) | + Ok(Async::Ready(None)) | + Ok(Async::NotReady) => break, + } + } + } +} + +impl Future for YieldAfter { + type Item = (mpsc::UnboundedSender, Duration); + type Error = (); + + fn poll(&mut self) -> Poll { + match self.delay.poll() { + Ok(Async::NotReady) => Ok(Async::NotReady), + Ok(Async::Ready(())) => { + let sender = self.sender.take() + .expect("sender is always Some unless the future is finished; qed"); + Ok(Async::Ready((sender, self.interval))) + }, + Err(_) => Err(()), + } + } +} + +#[cfg(test)] +mod tests { + use super::StatusSinks; + use futures::prelude::*; + use futures::sync::mpsc; + use std::time::Duration; + + #[test] + fn basic_usage() { + let mut status_sinks = StatusSinks::new(); + + let (tx1, rx1) = mpsc::unbounded(); + status_sinks.push(Duration::from_millis(200), tx1); + + let (tx2, rx2) = mpsc::unbounded(); + status_sinks.push(Duration::from_millis(500), tx2); + + let mut runtime = tokio::runtime::Runtime::new().unwrap(); + + let mut val_order = 5; + runtime.spawn(futures::future::poll_fn(move || { + status_sinks.poll(|| { val_order += 1; val_order }); + Ok(Async::NotReady) + })); + + let done = rx1 + .into_future() + .and_then(|(item, rest)| { + assert_eq!(item, Some(6)); + rest.into_future() + }) + .and_then(|(item, _)| { + assert_eq!(item, Some(7)); + rx2.into_future() + }) + .map(|(item, _)| { + assert_eq!(item, Some(8)); + }); + + runtime.block_on(done).unwrap(); + } +} diff --git a/core/service/test/Cargo.toml b/core/service/test/Cargo.toml index aa3dddfc1851e77580fad547ee561d404c0c65d1..4415369a6a1d3f69d5c42a8332408d3fa390a05f 100644 --- a/core/service/test/Cargo.toml +++ b/core/service/test/Cargo.toml @@ -5,13 +5,14 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -tempdir = "0.3" -tokio = "0.1.7" -futures = "0.1" -log = "0.4" -env_logger = "0.6" -fdlimit = "0.1" -service = { package = "substrate-service", path = "../../../core/service" } +tempdir = "0.3.7" +tokio = "0.1.22" +futures = "0.1.29" +log = "0.4.8" +env_logger = "0.7.0" +fdlimit = "0.1.1" +futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19", features = ["compat"] } +service = { package = "substrate-service", path = "../../../core/service", default-features = false } network = { package = "substrate-network", path = "../../../core/network" } consensus = { package = "substrate-consensus-common", path = "../../../core/consensus/common" } client = { package = "substrate-client", path = "../../../core/client" } diff --git a/core/service/test/src/lib.rs b/core/service/test/src/lib.rs index 1b3c43dae74bbfd446e64f5470b9c4b271d06064..c147f8051065ea2c4435f8132ca9eb3896f5e256 100644 --- a/core/service/test/src/lib.rs +++ b/core/service/test/src/lib.rs @@ -20,39 +20,37 @@ use std::iter; use std::sync::{Arc, Mutex, MutexGuard}; use std::net::Ipv4Addr; use std::time::Duration; -use std::collections::HashMap; use log::info; use futures::{Future, Stream, Poll}; use tempdir::TempDir; use tokio::{runtime::Runtime, prelude::FutureExt}; use tokio::timer::Interval; use service::{ - ServiceFactory, + AbstractService, + ChainSpec, Configuration, - FactoryFullConfiguration, - FactoryChainSpec, + config::DatabaseConfig, Roles, - FactoryExtrinsic, + Error, }; use network::{multiaddr, Multiaddr}; use network::config::{NetworkConfiguration, TransportConfig, NodeKeyConfig, Secret, NonReservedPeerMode}; -use sr_primitives::generic::BlockId; -use consensus::{BlockImportParams, BlockImport}; +use sr_primitives::{generic::BlockId, traits::Block as BlockT}; /// Maximum duration of single wait call. const MAX_WAIT_TIME: Duration = Duration::from_secs(60 * 3); -struct TestNet { +struct TestNet { runtime: Runtime, - authority_nodes: Vec<(usize, SyncService, Multiaddr)>, - full_nodes: Vec<(usize, SyncService, Multiaddr)>, - light_nodes: Vec<(usize, SyncService, Multiaddr)>, - chain_spec: FactoryChainSpec, + authority_nodes: Vec<(usize, SyncService, U, Multiaddr)>, + full_nodes: Vec<(usize, SyncService, U, Multiaddr)>, + light_nodes: Vec<(usize, SyncService, Multiaddr)>, + chain_spec: ChainSpec, base_port: u16, nodes: usize, } -/// Wraps around an `Arc>` and implements `Future`. +/// Wraps around an `Arc` and implements `Future`. pub struct SyncService(Arc>); impl SyncService { @@ -82,22 +80,24 @@ impl> Future for SyncService { } } -impl TestNet { +impl TestNet +where F: Send + 'static, L: Send +'static, U: Clone + Send + 'static +{ pub fn run_until_all_full( &mut self, full_predicate: FP, light_predicate: LP, ) where - FP: Send + Fn(usize, &SyncService) -> bool + 'static, - LP: Send + Fn(usize, &SyncService) -> bool + 'static, + FP: Send + Fn(usize, &SyncService) -> bool + 'static, + LP: Send + Fn(usize, &SyncService) -> bool + 'static, { let full_nodes = self.full_nodes.clone(); let light_nodes = self.light_nodes.clone(); let interval = Interval::new_interval(Duration::from_millis(100)) .map_err(|_| ()) .for_each(move |_| { - let full_ready = full_nodes.iter().all(|&(ref id, ref service, _)| + let full_ready = full_nodes.iter().all(|&(ref id, ref service, _, _)| full_predicate(*id, service) ); @@ -125,14 +125,14 @@ impl TestNet { } } -fn node_config ( +fn node_config ( index: usize, - spec: &FactoryChainSpec, + spec: &ChainSpec, role: Roles, key_seed: Option, base_port: u16, root: &TempDir, -) -> FactoryFullConfiguration +) -> Configuration<(), G, E> { let root = root.path().join(format!("node-{}", index)); @@ -169,16 +169,20 @@ fn node_config ( roles: role, transaction_pool: Default::default(), network: network_config, - keystore_path: root.join("key"), + keystore_path: Some(root.join("key")), keystore_password: None, - database_path: root.join("db"), - database_cache_size: None, + config_dir: Some(root.clone()), + database: DatabaseConfig::Path { + path: root.join("db"), + cache_size: None + }, state_cache_size: 16777216, state_cache_child_ratio: None, pruning: Default::default(), chain_spec: (*spec).clone(), custom: Default::default(), name: format!("Node {}", index), + wasm_method: service::config::WasmExecutionMethod::Interpreted, execution_strategies: Default::default(), rpc_http: None, rpc_ws: None, @@ -188,24 +192,29 @@ fn node_config ( telemetry_external_transport: None, default_heap_pages: None, offchain_worker: false, + sentry_mode: false, force_authoring: false, disable_grandpa: false, dev_key_seed: key_seed, } } -impl TestNet where - F::FullService: Future, - F::LightService: Future, +impl TestNet where + F: AbstractService, + L: AbstractService, + E: Clone, { fn new( temp: &TempDir, - spec: FactoryChainSpec, - full: usize, - light: usize, - authorities: Vec, + spec: ChainSpec, + full: impl Iterator) -> Result<(F, U), Error>>, + light: impl Iterator) -> Result>, + authorities: impl Iterator) -> Result<(F, U), Error> + )>, base_port: u16 - ) -> TestNet { + ) -> TestNet { let _ = env_logger::try_init(); fdlimit::raise_fd_limit(); let runtime = Runtime::new().expect("Error creating tokio runtime"); @@ -222,85 +231,113 @@ impl TestNet where net } - fn insert_nodes(&mut self, temp: &TempDir, full: usize, light: usize, authorities: Vec) { - let mut nodes = self.nodes; - let base_port = self.base_port; - let spec = &self.chain_spec; + fn insert_nodes( + &mut self, + temp: &TempDir, + full: impl Iterator) -> Result<(F, U), Error>>, + light: impl Iterator) -> Result>, + authorities: impl Iterator) -> Result<(F, U), Error>)> + ) { let executor = self.runtime.executor(); - self.authority_nodes.extend(authorities.iter().enumerate().map(|(index, key)| { - let node_config = node_config::( - index, - &spec, + + for (key, authority) in authorities { + let node_config = node_config( + self.nodes, + &self.chain_spec, Roles::AUTHORITY, - Some(key.clone()), - base_port, + Some(key), + self.base_port, &temp, ); let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let service = SyncService::from(F::new_full(node_config).expect("Error creating test node service")); + let (service, user_data) = authority(node_config).expect("Error creating test node service"); + let service = SyncService::from(service); executor.spawn(service.clone().map_err(|_| ())); let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); - ((index + nodes), service, addr) - })); - nodes += authorities.len(); + self.authority_nodes.push((self.nodes, service, user_data, addr)); + self.nodes += 1; + } - self.full_nodes.extend((nodes..nodes + full).map(|index| { - let node_config = node_config::(index, &spec, Roles::FULL, None, base_port, &temp); + for full in full { + let node_config = node_config(self.nodes, &self.chain_spec, Roles::FULL, None, self.base_port, &temp); let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let service = SyncService::from(F::new_full(node_config).expect("Error creating test node service")); + let (service, user_data) = full(node_config).expect("Error creating test node service"); + let service = SyncService::from(service); executor.spawn(service.clone().map_err(|_| ())); let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); - (index, service, addr) - })); - nodes += full; + self.full_nodes.push((self.nodes, service, user_data, addr)); + self.nodes += 1; + } - self.light_nodes.extend((nodes..nodes + light).map(|index| { - let node_config = node_config::(index, &spec, Roles::LIGHT, None, base_port, &temp); + for light in light { + let node_config = node_config(self.nodes, &self.chain_spec, Roles::LIGHT, None, self.base_port, &temp); let addr = node_config.network.listen_addresses.iter().next().unwrap().clone(); - let service = SyncService::from(F::new_light(node_config).expect("Error creating test node service")); + let service = SyncService::from(light(node_config).expect("Error creating test node service")); executor.spawn(service.clone().map_err(|_| ())); let addr = addr.with(multiaddr::Protocol::P2p(service.get().network().local_peer_id().into())); - (index, service, addr) - })); - nodes += light; - - self.nodes = nodes; + self.light_nodes.push((self.nodes, service, addr)); + self.nodes += 1; + } } } -pub fn connectivity(spec: FactoryChainSpec) where - F::FullService: Future, - F::LightService: Future, +pub fn connectivity( + spec: ChainSpec, + full_builder: Fb, + light_builder: Lb, + light_node_interconnectivity: bool, // should normally be false, unless the light nodes + // aren't actually light. +) where + E: Clone, + Fb: Fn(Configuration<(), G, E>) -> Result, + F: AbstractService, + Lb: Fn(Configuration<(), G, E>) -> Result, + L: AbstractService, { const NUM_FULL_NODES: usize = 5; const NUM_LIGHT_NODES: usize = 5; + + let expected_full_connections = NUM_FULL_NODES - 1 + NUM_LIGHT_NODES; + let expected_light_connections = if light_node_interconnectivity { + expected_full_connections + } else { + NUM_FULL_NODES + }; + { let temp = TempDir::new("substrate-connectivity-test").expect("Error creating test dir"); let runtime = { - let mut network = TestNet::::new( + let mut network = TestNet::new( &temp, spec.clone(), - NUM_FULL_NODES, - NUM_LIGHT_NODES, - vec![], + (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), 30400, ); info!("Checking star topology"); - let first_address = network.full_nodes[0].2.clone(); - for (_, service, _) in network.full_nodes.iter().skip(1) { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + let first_address = network.full_nodes[0].3.clone(); + for (_, service, _, _) in network.full_nodes.iter().skip(1) { + service.get().network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); } for (_, service, _) in network.light_nodes.iter() { - service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); + service.get().network().add_reserved_peer(first_address.to_string()) + .expect("Error adding reserved peer"); } + network.run_until_all_full( - |_index, service| service.get().network().num_connected() == NUM_FULL_NODES - 1 - + NUM_LIGHT_NODES, - |_index, service| service.get().network().num_connected() == NUM_FULL_NODES, + move |_index, service| service.get().network().num_connected() + == expected_full_connections, + move |_index, service| service.get().network().num_connected() + == expected_light_connections, ); + network.runtime }; @@ -311,76 +348,92 @@ pub fn connectivity(spec: FactoryChainSpec) where { let temp = TempDir::new("substrate-connectivity-test").expect("Error creating test dir"); { - let mut network = TestNet::::new( + let mut network = TestNet::new( &temp, spec, - NUM_FULL_NODES, - NUM_LIGHT_NODES, - vec![], + (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), 30400, ); info!("Checking linked topology"); - let mut address = network.full_nodes[0].2.clone(); + let mut address = network.full_nodes[0].3.clone(); let max_nodes = std::cmp::max(NUM_FULL_NODES, NUM_LIGHT_NODES); for i in 0..max_nodes { if i != 0 { - if let Some((_, service, node_id)) = network.full_nodes.get(i) { - service.get().network().add_reserved_peer(address.to_string()).expect("Error adding reserved peer"); + if let Some((_, service, _, node_id)) = network.full_nodes.get(i) { + service.get().network().add_reserved_peer(address.to_string()) + .expect("Error adding reserved peer"); address = node_id.clone(); } } if let Some((_, service, node_id)) = network.light_nodes.get(i) { - service.get().network().add_reserved_peer(address.to_string()).expect("Error adding reserved peer"); + service.get().network().add_reserved_peer(address.to_string()) + .expect("Error adding reserved peer"); address = node_id.clone(); } } + network.run_until_all_full( - |_index, service| service.get().network().num_connected() == NUM_FULL_NODES - 1 - + NUM_LIGHT_NODES, - |_index, service| service.get().network().num_connected() == NUM_FULL_NODES, + move |_index, service| service.get().network().num_connected() + == expected_full_connections, + move |_index, service| service.get().network().num_connected() + == expected_light_connections, ); } temp.close().expect("Error removing temp dir"); } } -pub fn sync(spec: FactoryChainSpec, mut block_factory: B, mut extrinsic_factory: E) where - F: ServiceFactory, - F::FullService: Future, - F::LightService: Future, - B: FnMut(&SyncService) -> BlockImportParams, - E: FnMut(&SyncService) -> FactoryExtrinsic, +pub fn sync( + spec: ChainSpec, + full_builder: Fb, + light_builder: Lb, + mut make_block_and_import: B, + mut extrinsic_factory: ExF +) where + Fb: Fn(Configuration<(), G, E>) -> Result<(F, U), Error>, + F: AbstractService, + Lb: Fn(Configuration<(), G, E>) -> Result, + L: AbstractService, + B: FnMut(&F, &mut U), + ExF: FnMut(&F, &U) -> ::Extrinsic, + U: Clone + Send + 'static, + E: Clone, { const NUM_FULL_NODES: usize = 10; // FIXME: BABE light client support is currently not working. - const NUM_LIGHT_NODES: usize = 0; + const NUM_LIGHT_NODES: usize = 10; const NUM_BLOCKS: usize = 512; let temp = TempDir::new("substrate-sync-test").expect("Error creating test dir"); - let mut network = TestNet::::new( + let mut network = TestNet::new( &temp, spec.clone(), - NUM_FULL_NODES, - NUM_LIGHT_NODES, - vec![], + (0..NUM_FULL_NODES).map(|_| { |cfg| full_builder(cfg) }), + (0..NUM_LIGHT_NODES).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg) })), 30500, ); info!("Checking block sync"); let first_address = { - let first_service = &network.full_nodes[0].1; - let mut client = first_service.get().client(); + let &mut (_, ref first_service, ref mut first_user_data, _) = &mut network.full_nodes[0]; for i in 0 .. NUM_BLOCKS { if i % 128 == 0 { - info!("Generating #{}", i); + info!("Generating #{}", i + 1); } - let import_data = block_factory(&first_service); - client.import_block(import_data, HashMap::new()).expect("Error importing test block"); + + make_block_and_import(&first_service.get(), first_user_data); } - network.full_nodes[0].2.clone() + network.full_nodes[0].3.clone() }; info!("Running sync"); - for (_, service, _) in network.full_nodes.iter().skip(1) { + for (_, service, _, _) in network.full_nodes.iter().skip(1) { service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); } for (_, service, _) in network.light_nodes.iter() { @@ -395,42 +448,50 @@ pub fn sync(spec: FactoryChainSpec, mut block_factory: B, mut extrin info!("Checking extrinsic propagation"); let first_service = network.full_nodes[0].1.clone(); + let first_user_data = &network.full_nodes[0].2; let best_block = BlockId::number(first_service.get().client().info().chain.best_number); - let extrinsic = extrinsic_factory(&first_service); - first_service.get().transaction_pool().submit_one(&best_block, extrinsic).unwrap(); + let extrinsic = extrinsic_factory(&first_service.get(), first_user_data); + futures03::executor::block_on(first_service.get().transaction_pool().submit_one(&best_block, extrinsic)).unwrap(); network.run_until_all_full( |_index, service| service.get().transaction_pool().ready().count() == 1, |_index, _service| true, ); } -pub fn consensus(spec: FactoryChainSpec, authorities: Vec) where - F: ServiceFactory, - F::FullService: Future, - F::LightService: Future, +pub fn consensus( + spec: ChainSpec, + full_builder: Fb, + light_builder: Lb, + authorities: impl IntoIterator +) where + Fb: Fn(Configuration<(), G, E>) -> Result, + F: AbstractService, + Lb: Fn(Configuration<(), G, E>) -> Result, + L: AbstractService, + E: Clone, { const NUM_FULL_NODES: usize = 10; - const NUM_LIGHT_NODES: usize = 0; + const NUM_LIGHT_NODES: usize = 10; const NUM_BLOCKS: usize = 10; // 10 * 2 sec block production time = ~20 seconds let temp = TempDir::new("substrate-conensus-test").expect("Error creating test dir"); - let mut network = TestNet::::new( + let mut network = TestNet::new( &temp, spec.clone(), - NUM_FULL_NODES / 2, - NUM_LIGHT_NODES / 2, - authorities, + (0..NUM_FULL_NODES / 2).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES / 2).map(|_| { |cfg| light_builder(cfg) }), + authorities.into_iter().map(|key| (key, { |cfg| full_builder(cfg).map(|s| (s, ())) })), 30600, ); info!("Checking consensus"); - let first_address = network.authority_nodes[0].2.clone(); - for (_, service, _) in network.full_nodes.iter() { + let first_address = network.authority_nodes[0].3.clone(); + for (_, service, _, _) in network.full_nodes.iter() { service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); } for (_, service, _) in network.light_nodes.iter() { service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); } - for (_, service, _) in network.authority_nodes.iter().skip(1) { + for (_, service, _, _) in network.authority_nodes.iter().skip(1) { service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); } network.run_until_all_full( @@ -441,8 +502,15 @@ pub fn consensus(spec: FactoryChainSpec, authorities: Vec) where ); info!("Adding more peers"); - network.insert_nodes(&temp, NUM_FULL_NODES / 2, NUM_LIGHT_NODES / 2, vec![]); - for (_, service, _) in network.full_nodes.iter() { + network.insert_nodes( + &temp, + (0..NUM_FULL_NODES / 2).map(|_| { |cfg| full_builder(cfg).map(|s| (s, ())) }), + (0..NUM_LIGHT_NODES / 2).map(|_| { |cfg| light_builder(cfg) }), + // Note: this iterator is empty but we can't just use `iter::empty()`, otherwise + // the type of the closure cannot be inferred. + (0..0).map(|_| (String::new(), { |cfg| full_builder(cfg).map(|s| (s, ())) })), + ); + for (_, service, _, _) in network.full_nodes.iter() { service.get().network().add_reserved_peer(first_address.to_string()).expect("Error adding reserved peer"); } for (_, service, _) in network.light_nodes.iter() { diff --git a/core/sr-api-macros/Cargo.toml b/core/sr-api-macros/Cargo.toml index 3301b2fdc7ab3d6f505f477ce86d5401a736be5b..ad258fcf67c66e8035151e178fc30b55a3c60999 100644 --- a/core/sr-api-macros/Cargo.toml +++ b/core/sr-api-macros/Cargo.toml @@ -8,11 +8,11 @@ edition = "2018" proc-macro = true [dependencies] -quote = "0.6.12" -syn = { version = "^0.15.30", features = [ "full", "fold", "extra-traits", "visit" ] } -proc-macro2 = "0.4" -blake2-rfc = "0.2" -proc-macro-crate = "0.1.3" +quote = "1.0.2" +syn = { version = "1.0.7", features = [ "full", "fold", "extra-traits", "visit" ] } +proc-macro2 = "1.0.6" +blake2-rfc = "0.2.18" +proc-macro-crate = "0.1.4" [dev-dependencies] client = { package = "substrate-client", path = "../client" } @@ -21,11 +21,17 @@ state_machine = { package = "substrate-state-machine", path = "../state-machine" sr-primitives = { path = "../sr-primitives" } sr-version = { path = "../sr-version" } primitives = { package = "substrate-primitives", path = "../primitives" } -criterion = "0.2" +criterion = "0.3.0" consensus_common = { package = "substrate-consensus-common", path = "../consensus/common" } codec = { package = "parity-scale-codec", version = "1.0.0" } -trybuild = "1.0" +trybuild = "1.0.17" +rustversion = "1.0.0" [[bench]] name = "bench" harness = false + +# We actually don't need the `std` feature in this crate, but the tests require it. +[features] +default = [ "std" ] +std = [] diff --git a/core/sr-api-macros/src/decl_runtime_apis.rs b/core/sr-api-macros/src/decl_runtime_apis.rs index 27f102740b83b650aa6affb84d17d50ee8f6b0ec..778ac910cd93f796eac8c1f49f0f9c38ad56f765 100644 --- a/core/sr-api-macros/src/decl_runtime_apis.rs +++ b/core/sr-api-macros/src/decl_runtime_apis.rs @@ -19,6 +19,7 @@ use crate::utils::{ fold_fn_decl_for_client_side, unwrap_or_error, extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name, return_type_extract_type, generate_method_runtime_api_impl_name, generate_call_api_at_fn_name, prefix_function_with_trait, + replace_wild_card_parameter_names, }; use proc_macro2::{TokenStream, Span}; @@ -27,9 +28,8 @@ use quote::quote; use syn::{ spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error}, ReturnType, - fold::{self, Fold}, parse_quote, ItemTrait, Generics, GenericParam, Attribute, FnArg, - visit::{Visit, self}, Pat, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, Type, - TraitItemMethod + fold::{self, Fold}, parse_quote, ItemTrait, Generics, GenericParam, Attribute, FnArg, Type, + visit::{Visit, self}, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, TraitItemMethod, }; use std::collections::HashMap; @@ -95,9 +95,9 @@ impl Parse for RuntimeApiDecls { fn extend_generics_with_block(generics: &mut Generics) { let c = generate_crate_access(HIDDEN_INCLUDES_ID); - generics.lt_token = Some(parse_quote!(<)); + generics.lt_token = Some(Default::default()); generics.params.insert(0, parse_quote!( Block: #c::runtime_api::BlockT )); - generics.gt_token = Some(parse_quote!(>)); + generics.gt_token = Some(Default::default()); } /// Remove all attributes from the vector that are supported by us in the declaration of a runtime @@ -182,34 +182,34 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); // Auxiliary function that is used to convert between types that use different block types. - // The function expects that both a convertable by encoding the one and decoding the other. + // The function expects that both are convertible by encoding the one and decoding the other. result.push(quote!( #[cfg(any(feature = "std", test))] fn convert_between_block_types ( input: &I, error_desc: &'static str, - ) -> ::std::result::Result + ) -> std::result::Result { ::decode( - &mut &#crate_::runtime_api::Encode::encode(input)[..] - ).map_err(|_| error_desc) + &mut &#crate_::runtime_api::Encode::encode(input)[..], + ).map_err(|e| format!("{} {}", error_desc, e.what())) } )); // Generate a native call generator for each function of the given trait. for fn_ in fns { - let params = extract_parameter_names_types_and_borrows(&fn_.decl)?; + let params = extract_parameter_names_types_and_borrows(&fn_)?; let trait_fn_name = &fn_.ident; let fn_name = generate_native_call_generator_fn_name(&fn_.ident); - let output = return_type_replace_block_with_node_block(fn_.decl.output.clone()); + let output = return_type_replace_block_with_node_block(fn_.output.clone()); let output_ty = return_type_extract_type(&output); - let output = quote!( ::std::result::Result<#output_ty, &'static str> ); + let output = quote!( std::result::Result<#output_ty, String> ); // Every type that is using the `Block` generic parameter, we need to encode/decode, // to make it compatible between the runtime/node. let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| { let name_str = format!( - "Could not convert parameter `{}` between node and runtime!", quote!(#n) + "Could not convert parameter `{}` between node and runtime:", quote!(#n) ); quote!( let #n: #t = convert_between_block_types(&#n, #name_str)?; @@ -217,7 +217,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { }); // Same as for the input types, we need to check if we also need to convert the output, // before returning it. - let output_conversion = if return_type_is_using_block(&fn_.decl.output) { + let output_conversion = if return_type_is_using_block(&fn_.output) { quote!( convert_between_block_types( &res, @@ -234,22 +234,21 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result { // the user. Otherwise if it is not using the block, we don't need to add anything. let input_borrows = params .iter() - .map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { quote!() }); + .map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { None }); // Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect // all the function inputs. let fn_inputs = fn_ - .decl .inputs .iter() .map(|v| fn_arg_replace_block_with_node_block(v.clone())) .map(|v| match v { - FnArg::Captured(ref arg) => { + FnArg::Typed(ref arg) => { let mut arg = arg.clone(); - if let Type::Reference(ref mut r) = arg.ty { + if let Type::Reference(ref mut r) = *arg.ty { r.lifetime = Some(parse_quote!( 'a )); } - FnArg::Captured(arg) + FnArg::Typed(arg) }, r => r.clone(), }); @@ -310,15 +309,15 @@ fn parse_renamed_attribute(renamed: &Attribute) -> Result<(String, u32)> { } else { let mut itr = list.nested.iter(); let old_name = match itr.next() { - Some(NestedMeta::Literal(Lit::Str(i))) => { + Some(NestedMeta::Lit(Lit::Str(i))) => { i.value() }, _ => return err, }; let version = match itr.next() { - Some(NestedMeta::Literal(Lit::Int(i))) => { - i.value() as u32 + Some(NestedMeta::Lit(Lit::Int(i))) => { + i.base10_parse()? }, _ => return err, }; @@ -398,7 +397,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result { #[cfg(any(feature = "std", test))] pub fn #fn_name< R: #crate_::runtime_api::Encode + #crate_::runtime_api::Decode + PartialEq, - NC: FnOnce() -> ::std::result::Result + ::std::panic::UnwindSafe, + NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe, Block: #crate_::runtime_api::BlockT, T: #crate_::runtime_api::CallRuntimeAt, C: #crate_::runtime_api::Core, @@ -488,6 +487,8 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { if remove_supported_attributes(&mut method.attrs).contains_key(CHANGED_IN_ATTRIBUTE) { None } else { + // Make sure we replace all the wild card parameter names. + replace_wild_card_parameter_names(&mut method.sig); Some(TraitItem::Method(method.clone())) } } @@ -552,9 +553,9 @@ impl<'a> ToClientSideDecl<'a> { fn fold_trait_item_method(&mut self, method: TraitItemMethod) -> (TraitItemMethod, Option, TraitItemMethod) { let crate_ = self.crate_; - let context_other = quote!( #crate_::runtime_api::ExecutionContext::Other ); + let context = quote!( #crate_::runtime_api::ExecutionContext::OffchainCall(None) ); let fn_impl = self.create_method_runtime_api_impl(method.clone()); - let fn_decl = self.create_method_decl(method.clone(), context_other); + let fn_decl = self.create_method_decl(method.clone(), context); let fn_decl_ctx = self.create_method_decl_with_context(method); (fn_decl, fn_impl, fn_decl_ctx) @@ -565,7 +566,7 @@ impl<'a> ToClientSideDecl<'a> { let context_arg: syn::FnArg = parse_quote!( context: #crate_::runtime_api::ExecutionContext ); let mut fn_decl_ctx = self.create_method_decl(method, quote!( context )); fn_decl_ctx.sig.ident = Ident::new(&format!("{}_with_context", &fn_decl_ctx.sig.ident), Span::call_site()); - fn_decl_ctx.sig.decl.inputs.insert(2, context_arg); + fn_decl_ctx.sig.inputs.insert(2, context_arg); fn_decl_ctx } @@ -577,12 +578,12 @@ impl<'a> ToClientSideDecl<'a> { return None; } - let fn_decl = &method.sig.decl; - let ret_type = return_type_extract_type(&fn_decl.output); + let fn_sig = &method.sig; + let ret_type = return_type_extract_type(&fn_sig.output); // Get types and if the value is borrowed from all parameters. // If there is an error, we push it as the block to the user. - let param_types = match extract_parameter_names_types_and_borrows(fn_decl) { + let param_types = match extract_parameter_names_types_and_borrows(fn_sig) { Ok(res) => res.into_iter().map(|v| { let ty = v.1; let borrow = v.2; @@ -614,8 +615,12 @@ impl<'a> ToClientSideDecl<'a> { /// Takes the method declared by the user and creates the declaration we require for the runtime /// api client side. This method will call by default the `method_runtime_api_impl` for doing /// the actual call into the runtime. - fn create_method_decl(&mut self, mut method: TraitItemMethod, context: TokenStream) -> TraitItemMethod { - let params = match extract_parameter_names_types_and_borrows(&method.sig.decl) { + fn create_method_decl( + &mut self, + mut method: TraitItemMethod, + context: TokenStream, + ) -> TraitItemMethod { + let params = match extract_parameter_names_types_and_borrows(&method.sig) { Ok(res) => res.into_iter().map(|v| v.0).collect::>(), Err(e) => { self.errors.push(e.to_compile_error()); @@ -623,13 +628,10 @@ impl<'a> ToClientSideDecl<'a> { } }; let params2 = params.clone(); - let ret_type = return_type_extract_type(&method.sig.decl.output); + let ret_type = return_type_extract_type(&method.sig.output); + + fold_fn_decl_for_client_side(&mut method.sig, &self.block_id, &self.crate_); - method.sig.decl = fold_fn_decl_for_client_side( - method.sig.decl.clone(), - &self.block_id, - &self.crate_ - ); let name_impl = generate_method_runtime_api_impl_name(&self.trait_, &method.sig.ident); let crate_ = self.crate_; @@ -650,7 +652,7 @@ impl<'a> ToClientSideDecl<'a> { let ident = Ident::new( &format!("{}_before_version_{}", method.sig.ident, version), - method.sig.ident.span() + method.sig.ident.span(), ); method.sig.ident = ident; method.attrs.push(parse_quote!( #[deprecated] )); @@ -674,22 +676,26 @@ impl<'a> ToClientSideDecl<'a> { let runtime_api_impl_params_encoded = #crate_::runtime_api::Encode::encode(&( #( &#params ),* )); - self.#name_impl(at, #context, #param_tuple, runtime_api_impl_params_encoded) - .and_then(|r| - match r { - #crate_::runtime_api::NativeOrEncoded::Native(n) => { - #native_handling - }, - #crate_::runtime_api::NativeOrEncoded::Encoded(r) => { - <#ret_type as #crate_::runtime_api::Decode>::decode(&mut &r[..]) - .map_err(|err| - #crate_::error::Error::CallResultDecode( - #function_name, err - ).into() - ) - } + self.#name_impl( + __runtime_api_at_param__, + #context, + #param_tuple, + runtime_api_impl_params_encoded, + ).and_then(|r| + match r { + #crate_::runtime_api::NativeOrEncoded::Native(n) => { + #native_handling + }, + #crate_::runtime_api::NativeOrEncoded::Encoded(r) => { + <#ret_type as #crate_::runtime_api::Decode>::decode(&mut &r[..]) + .map_err(|err| + #crate_::error::Error::CallResultDecode( + #function_name, err + ).into() + ) } - ) + } + ) } } ); @@ -745,15 +751,12 @@ fn parse_runtime_api_version(version: &Attribute) -> Result { match meta { Meta::List(list) => { - if list.nested.len() > 1 && list.nested.is_empty() { + if list.nested.len() != 1 { err + } else if let Some(NestedMeta::Lit(Lit::Int(i))) = list.nested.first() { + i.base10_parse() } else { - match list.nested.first().as_ref().map(|v| v.value()) { - Some(NestedMeta::Literal(Lit::Int(i))) => { - Ok(i.value()) - }, - _ => err, - } + err } }, _ => err, @@ -848,32 +851,8 @@ struct CheckTraitDecl { impl<'ast> Visit<'ast> for CheckTraitDecl { fn visit_fn_arg(&mut self, input: &'ast FnArg) { - match input { - FnArg::Captured(ref arg) => { - match arg.pat { - Pat::Ident(ref pat) if pat.ident == "at" => { - self.errors.push( - Error::new( - pat.span(), - "`decl_runtime_apis!` adds automatically a parameter \ - `at: &BlockId`. Please rename/remove your parameter." - ) - ) - }, - _ => {} - } - }, - FnArg::SelfRef(_) | FnArg::SelfValue(_) => { - self.errors.push(Error::new(input.span(), "Self values are not supported.")) - } - _ => { - self.errors.push( - Error::new( - input.span(), - "Only function arguments in the form `pat: type` are supported." - ) - ) - } + if let FnArg::Receiver(_) = input { + self.errors.push(Error::new(input.span(), "`self` as argument not supported.")) } visit::visit_fn_arg(self, input); @@ -897,7 +876,7 @@ impl<'ast> Visit<'ast> for CheckTraitDecl { } fn visit_trait_bound(&mut self, input: &'ast TraitBound) { - if let Some(last_ident) = input.path.segments.last().map(|v| &v.value().ident) { + if let Some(last_ident) = input.path.segments.last().map(|v| &v.ident) { if last_ident == "BlockT" || last_ident == BLOCK_GENERIC_IDENT { self.errors.push( Error::new( diff --git a/core/sr-api-macros/src/impl_runtime_apis.rs b/core/sr-api-macros/src/impl_runtime_apis.rs index 973fa0558a85cd1eaf29fe450b27142c9c28fd26..d77d46a43cd44fe2f6b12e06b4417ac11890364b 100644 --- a/core/sr-api-macros/src/impl_runtime_apis.rs +++ b/core/sr-api-macros/src/impl_runtime_apis.rs @@ -26,7 +26,7 @@ use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{ - spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, Path, + spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, Path, Signature, ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath, fold::{self, Fold}, parse_quote }; @@ -56,12 +56,12 @@ impl Parse for RuntimeApiImpls { /// Generates the call to the implementation of the requested function. /// The generated code includes decoding of the input arguments and encoding of the output. fn generate_impl_call( - signature: &MethodSig, + signature: &Signature, runtime: &Type, input: &Ident, impl_trait: &Path ) -> Result { - let params = extract_parameter_names_types_and_borrows(&signature.decl)?; + let params = extract_parameter_names_types_and_borrows(signature)?; let c = generate_crate_access(HIDDEN_INCLUDES_ID); let c_iter = iter::repeat(&c); @@ -83,8 +83,7 @@ fn generate_impl_call( )* #[allow(deprecated)] - let output = <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*); - #c::runtime_api::Encode::encode(&output) + <#runtime as #impl_trait>::#fn_name(#( #pborrow #pnames2 ),*) ) ) } @@ -111,23 +110,20 @@ fn extract_impl_trait<'a>(impl_: &'a ItemImpl) -> Result<&'a Path> { /// Extracts the runtime block identifier. fn extract_runtime_block_ident(trait_: &Path) -> Result<&TypePath> { let span = trait_.span(); - let segment = trait_ + let generics = trait_ .segments .last() - .ok_or_else( - || Error::new(span, "Empty path not supported") - )?; - let generics = segment.value(); + .ok_or_else(|| Error::new(span, "Empty path not supported"))?; match &generics.arguments { PathArguments::AngleBracketed(ref args) => { - args.args.first().and_then(|v| match v.value() { - GenericArgument::Type(Type::Path(block)) => Some(block), + args.args.first().and_then(|v| match v { + GenericArgument::Type(Type::Path(ref block)) => Some(block), _ => None }).ok_or_else(|| Error::new(args.span(), "Missing `Block` generic parameter.")) }, PathArguments::None => { - let span = trait_.segments.last().as_ref().unwrap().value().span(); + let span = trait_.segments.last().as_ref().unwrap().span(); Err(Error::new(span, "Missing `Block` generic parameter.")) }, PathArguments::Parenthesized(_) => { @@ -150,7 +146,6 @@ fn generate_impl_calls( .segments .last() .ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))? - .value() .ident; for item in &impl_.items { @@ -175,11 +170,12 @@ fn generate_impl_calls( /// Generate the dispatch function that is used in native to call into the runtime. fn generate_dispatch_function(impls: &[ItemImpl]) -> Result { let data = Ident::new("data", Span::call_site()); + let c = generate_crate_access(HIDDEN_INCLUDES_ID); let impl_calls = generate_impl_calls(impls, &data)? .into_iter() .map(|(trait_, fn_name, impl_)| { let name = prefix_function_with_trait(&trait_, &fn_name); - quote!( #name => Some({ #impl_ }), ) + quote!( #name => Some(#c::runtime_api::Encode::encode(&{ #impl_ })), ) }); Ok(quote!( @@ -218,13 +214,7 @@ fn generate_wasm_interface(impls: &[ItemImpl]) -> Result { }; let output = { #impl_ }; - let res = output.as_ptr() as u64 + ((output.len() as u64) << 32); - - // Leak the output vector to avoid it being freed. - // This is fine in a WASM context since the heap - // will be discarded after the call. - #c::runtime_api::mem::forget(output); - res + #c::runtime_api::to_substrate_wasm_fn_return_value(&output) } ) }); @@ -282,7 +272,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result> #crate_::runtime_api::ApiExt<#block> for RuntimeApiImpl { - fn map_api_result ::std::result::Result, R, E>( + fn map_api_result std::result::Result, R, E>( &self, map_call: F ) -> ::std::result::Result where Self: Sized { @@ -306,15 +296,17 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result Option>> { + fn extract_proof(&mut self) -> Option<#crate_::runtime_api::StorageProof> { self.recorder .take() - .map(|r| { - r.borrow_mut() + .map(|recorder| { + let trie_nodes = recorder + .borrow_mut() .drain() .into_iter() - .map(|n| n.data.to_vec()) - .collect() + .map(|record| record.data) + .collect(); + #crate_::runtime_api::StorageProof::new(trie_nodes) }) } } @@ -367,7 +359,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result(&self, res: &::std::result::Result) { + fn commit_on_ok(&self, res: &std::result::Result) { if *self.commit_on_success.borrow() { if res.is_err() { self.changes.borrow_mut().discard_prospective(); @@ -389,7 +381,6 @@ fn extend_with_runtime_decl_path(mut trait_: Path) -> Path { .last() .as_ref() .expect("Trait path should always contain at least one item; qed") - .value() .ident; generate_runtime_mod_name_for_trait(trait_name) @@ -459,16 +450,16 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { let block_id = self.node_block_id; // Generate the access to the native parameters - let param_tuple_access = if input.sig.decl.inputs.len() == 1 { + let param_tuple_access = if input.sig.inputs.len() == 1 { vec![ quote!( p ) ] } else { - input.sig.decl.inputs.iter().enumerate().map(|(i, _)| { + input.sig.inputs.iter().enumerate().map(|(i, _)| { let i = syn::Index::from(i); quote!( p.#i ) }).collect::>() }; - let (param_types, error) = match extract_parameter_names_types_and_borrows(&input.sig.decl) { + let (param_types, error) = match extract_parameter_names_types_and_borrows(&input.sig) { Ok(res) => ( res.into_iter().map(|v| { let ty = v.1; @@ -480,18 +471,23 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { Err(e) => (Vec::new(), Some(e.to_compile_error())), }; - let context_arg: syn::FnArg = parse_quote!( context: #crate_::runtime_api::ExecutionContext ); - // Rewrite the input parameters. - input.sig.decl.inputs = parse_quote! { - &self, at: &#block_id, #context_arg, params: Option<( #( #param_types ),* )>, params_encoded: Vec + input.sig.inputs = parse_quote! { + &self, + at: &#block_id, + context: #crate_::runtime_api::ExecutionContext, + params: Option<( #( #param_types ),* )>, + params_encoded: Vec, }; - input.sig.ident = generate_method_runtime_api_impl_name(&self.impl_trait, &input.sig.ident); - let ret_type = return_type_extract_type(&input.sig.decl.output); + input.sig.ident = generate_method_runtime_api_impl_name( + &self.impl_trait, + &input.sig.ident, + ); + let ret_type = return_type_extract_type(&input.sig.output); // Generate the correct return type. - input.sig.decl.output = parse_quote!( + input.sig.output = parse_quote!( -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>> ); @@ -499,7 +495,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { parse_quote!( { // Get the error to the user (if we have one). - #( #error )* + #error self.call_api_at( |call_runtime_at, core_api, changes, initialized_block, recorder| { @@ -560,7 +556,7 @@ fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result .segments .last() .ok_or_else(|| Error::new(impl_trait_path.span(), "Empty trait path not possible!"))? - .into_value(); + .clone(); let runtime_block = extract_runtime_block_ident(impl_trait_path)?; let (node_block, node_block_id) = generate_node_block_and_block_id_ty(&impl_.self_ty); let runtime_type = &impl_.self_ty; diff --git a/core/sr-api-macros/src/utils.rs b/core/sr-api-macros/src/utils.rs index 21000f431b81505979f6c158a694fcd44aa2f98b..c627cdacfa982017ee17ed37775b6219ddaaae56 100644 --- a/core/sr-api-macros/src/utils.rs +++ b/core/sr-api-macros/src/utils.rs @@ -15,9 +15,15 @@ // along with Substrate. If not, see . use proc_macro2::{TokenStream, Span}; -use syn::{Result, Ident, FnDecl, parse_quote, Type, Pat, spanned::Spanned, FnArg, Error}; + +use syn::{ + Result, Ident, Signature, parse_quote, Type, Pat, spanned::Spanned, FnArg, Error, token::And, +}; + use quote::quote; + use std::env; + use proc_macro_crate::crate_name; /// Unwrap the given result, if it is an error, `compile_error!` will be generated. @@ -82,23 +88,33 @@ pub fn return_type_extract_type(rt: &syn::ReturnType) -> Type { } } -/// Fold the given `FnDecl` to make it usable on the client side. +/// Replace the `_` (wild card) parameter names in the given signature with unique identifiers. +pub fn replace_wild_card_parameter_names(input: &mut Signature) { + let mut generated_pattern_counter = 0; + input.inputs.iter_mut().for_each(|arg| if let FnArg::Typed(arg) = arg { + arg.pat = Box::new( + generate_unique_pattern((*arg.pat).clone(), &mut generated_pattern_counter), + ); + }); +} + +/// Fold the given `Signature` to make it usable on the client side. pub fn fold_fn_decl_for_client_side( - mut input: FnDecl, + input: &mut Signature, block_id: &TokenStream, - crate_: &TokenStream -) -> FnDecl { + crate_: &TokenStream, +) { + replace_wild_card_parameter_names(input); + // Add `&self, at:& BlockId` as parameters to each function at the beginning. - input.inputs.insert(0, parse_quote!( at: &#block_id )); + input.inputs.insert(0, parse_quote!( __runtime_api_at_param__: &#block_id )); input.inputs.insert(0, parse_quote!( &self )); // Wrap the output in a `Result` input.output = { let ty = return_type_extract_type(&input.output); - parse_quote!( -> ::std::result::Result<#ty, #crate_::error::Error> ) + parse_quote!( -> std::result::Result<#ty, #crate_::error::Error> ) }; - - input } /// Generate an unique pattern based on the given counter, if the given pattern is a `_`. @@ -106,8 +122,8 @@ pub fn generate_unique_pattern(pat: Pat, counter: &mut u32) -> Pat { match pat { Pat::Wild(_) => { let generated_name = Ident::new( - &format!("runtime_api_generated_name_{}", counter), - pat.span() + &format!("__runtime_api_generated_name_{}__", counter), + pat.span(), ); *counter += 1; @@ -115,38 +131,31 @@ pub fn generate_unique_pattern(pat: Pat, counter: &mut u32) -> Pat { }, _ => pat, } -} + } /// Extracts the name, the type and `&` or ``(if it is a reference or not) -/// for each parameter in the given function declaration. -pub fn extract_parameter_names_types_and_borrows(fn_decl: &FnDecl) - -> Result> +/// for each parameter in the given function signature. +pub fn extract_parameter_names_types_and_borrows(sig: &Signature) + -> Result)>> { let mut result = Vec::new(); let mut generated_pattern_counter = 0; - for input in fn_decl.inputs.iter() { + for input in sig.inputs.iter() { match input { - FnArg::Captured(arg) => { - let (ty, borrow) = match &arg.ty { + FnArg::Typed(arg) => { + let (ty, borrow) = match &*arg.ty { Type::Reference(t) => { - let ty = &t.elem; - (parse_quote!( #ty ), quote!( & )) + ((*t.elem).clone(), Some(t.and_token)) }, - t => { (t.clone(), quote!()) }, + t => { (t.clone(), None) }, }; let name = - generate_unique_pattern(arg.pat.clone(), &mut generated_pattern_counter); + generate_unique_pattern((*arg.pat).clone(), &mut generated_pattern_counter); result.push((name, ty, borrow)); }, - _ => { - return Err( - Error::new( - input.span(), - "Only function arguments with the following \ - pattern are accepted: `name: type`!" - ) - ) + FnArg::Receiver(_) => { + return Err(Error::new(input.span(), "`self` parameter not supported!")) } } } diff --git a/core/sr-api-macros/tests/decl_and_impl.rs b/core/sr-api-macros/tests/decl_and_impl.rs index 36091d1f85062e6c693e0780383d0d9680b1d258..314c92e28d02e57573c54e80af6ca745a6edc455 100644 --- a/core/sr-api-macros/tests/decl_and_impl.rs +++ b/core/sr-api-macros/tests/decl_and_impl.rs @@ -33,6 +33,7 @@ decl_runtime_apis! { fn something_with_block(block: Block) -> Block; fn function_with_two_args(data: u64, block: Block); fn same_name(); + fn wild_card(_: u32); } #[api_version(2)] @@ -58,6 +59,8 @@ impl_runtime_apis! { } fn same_name() {} + + fn wild_card(_: u32) {} } impl self::ApiWithCustomVersion for Runtime { @@ -93,13 +96,6 @@ fn test_client_side_function_signature() { RuntimeApiImpl::::same_name_before_version_2; } -#[test] -fn test_runtime_side_function_signature() { - let _api_same_name: fn(input_data: *mut u8, input_len: usize) -> u64 = api::Api_same_name; - let _api_with_version_same_name: fn(input_data: *mut u8, input_len: usize) -> u64 = - api::ApiWithCustomVersion_same_name; -} - #[test] fn check_runtime_api_info() { assert_eq!(&Api::::ID, &runtime_decl_for_Api::ID); diff --git a/core/sr-api-macros/tests/runtime_calls.rs b/core/sr-api-macros/tests/runtime_calls.rs index 6b79e52ee21d01e46c71c8dabe8e53f722ce4353..77dd9efa783e6daacdcec0b618c0f838f91b272e 100644 --- a/core/sr-api-macros/tests/runtime_calls.rs +++ b/core/sr-api-macros/tests/runtime_calls.rs @@ -50,7 +50,10 @@ fn calling_wasm_runtime_function() { } #[test] -#[should_panic(expected = "Could not convert parameter `param` between node and runtime!")] +#[should_panic( + expected = + "Could not convert parameter `param` between node and runtime: DecodeFails always fails" +)] fn calling_native_runtime_function_with_non_decodable_parameter() { let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build(); let runtime_api = client.runtime_api(); @@ -183,8 +186,8 @@ fn record_proof_works() { // Use the proof backend to execute `execute_block`. let mut overlay = Default::default(); - let executor = NativeExecutor::::new(None); - execution_proof_check_on_trie_backend( + let executor = NativeExecutor::::new(WasmExecutionMethod::Interpreted, None); + execution_proof_check_on_trie_backend::<_, u64, _>( &backend, &mut overlay, &executor, diff --git a/core/sr-api-macros/tests/trybuild.rs b/core/sr-api-macros/tests/trybuild.rs index 302dd7c0878e3dfb6c9b364c2004ee6f8fed2e80..9baea83196e9bf728e1aea8229f109f0d978ac41 100644 --- a/core/sr-api-macros/tests/trybuild.rs +++ b/core/sr-api-macros/tests/trybuild.rs @@ -1,5 +1,6 @@ use std::env; +#[rustversion::attr(not(stable), ignore)] #[test] fn ui() { // As trybuild is using `cargo check`, we don't need the real WASM binaries. diff --git a/core/sr-api-macros/tests/ui/adding_at_parameter.rs b/core/sr-api-macros/tests/ui/adding_at_parameter.rs deleted file mode 100644 index d4757e256f024514613090300169440258d70ee3..0000000000000000000000000000000000000000 --- a/core/sr-api-macros/tests/ui/adding_at_parameter.rs +++ /dev/null @@ -1,9 +0,0 @@ -use client::decl_runtime_apis; - -decl_runtime_apis! { - pub trait Api { - fn test(at: u64); - } -} - -fn main() {} diff --git a/core/sr-api-macros/tests/ui/adding_at_parameter.stderr b/core/sr-api-macros/tests/ui/adding_at_parameter.stderr deleted file mode 100644 index 1c7e07a418c0a250b57e5a758b8ec4678d415f34..0000000000000000000000000000000000000000 --- a/core/sr-api-macros/tests/ui/adding_at_parameter.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: `decl_runtime_apis!` adds automatically a parameter `at: &BlockId`. Please rename/remove your parameter. - --> $DIR/adding_at_parameter.rs:5:11 - | -5 | fn test(at: u64); - | ^^ diff --git a/core/sr-api-macros/tests/ui/adding_self_parameter.stderr b/core/sr-api-macros/tests/ui/adding_self_parameter.stderr index e7249e9f732f55fe84707266da3eac32d3835141..34ba4d4a5112fc00ff0a4a36367a0b389cac3aee 100644 --- a/core/sr-api-macros/tests/ui/adding_self_parameter.stderr +++ b/core/sr-api-macros/tests/ui/adding_self_parameter.stderr @@ -1,4 +1,4 @@ -error: Self values are not supported. +error: `self` as argument not supported. --> $DIR/adding_self_parameter.rs:5:11 | 5 | fn test(&self); diff --git a/core/sr-api-macros/tests/ui/declaring_old_block.stderr b/core/sr-api-macros/tests/ui/declaring_old_block.stderr index 181aa2a3ca7834eebc40cbb0b6b6f83a7380dcbc..999a50cc9697759f3e94a3e84a2f202399fc937b 100644 --- a/core/sr-api-macros/tests/ui/declaring_old_block.stderr +++ b/core/sr-api-macros/tests/ui/declaring_old_block.stderr @@ -16,4 +16,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr index a591d0448c50d7c03bc48b46fe071ea4c6b13ccd..ec033f2e09d23fe63309796c3b75e4b049015c16 100644 --- a/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr +++ b/core/sr-api-macros/tests/ui/declaring_own_block_with_different_name.stderr @@ -10,4 +10,4 @@ warning: unused import: `sr_primitives::traits::Block as BlockT` 1 | use sr_primitives::traits::Block as BlockT; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[warn(unused_imports)] on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.rs b/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.rs index 774d017c190e926e1a4e4d55e6ab9aa6ab46214e..b85431f3ba049b0a55e7e9ddd6a6c0d80e89cb27 100644 --- a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.rs +++ b/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.rs @@ -1,6 +1,6 @@ -use sr_primitives::traits::GetNodeBlockType; +use sr_primitives::traits::{GetNodeBlockType, Block as BlockT}; use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis}; +use client::{decl_runtime_apis, impl_runtime_apis, runtime_api}; /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` /// trait are done by the `construct_runtime!` macro in a real runtime. @@ -19,6 +19,18 @@ impl_runtime_apis! { impl self::Api for Runtime { fn test(data: String) {} } + + impl runtime_api::Core for Runtime { + fn version() -> runtime_api::RuntimeVersion { + unimplemented!() + } + fn execute_block(_: Block) { + unimplemented!() + } + fn initialize_block(_: &::Header) { + unimplemented!() + } + } } fn main() {} diff --git a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.stderr b/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.stderr index 15434a52ba8b78ae6876b17e34f72ff9c7e85779..025ca60c48095365e706871c1ec4a2fe3a50d10e 100644 --- a/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.stderr +++ b/core/sr-api-macros/tests/ui/impl_incorrect_method_signature.stderr @@ -10,6 +10,37 @@ error[E0053]: method `test` has an incompatible type for trait = note: expected type `fn(u64)` found type `fn(std::string::String)` +error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for trait + --> $DIR/impl_incorrect_method_signature.rs:18:1 + | +12 | / decl_runtime_apis! { +13 | | pub trait Api { +14 | | fn test(data: u64); +15 | | } +16 | | } + | |_- type in trait +17 | +18 | impl_runtime_apis! { + | ^^^^^^^^^^^^^^^^^^ expected u64, found struct `std::string::String` + | + = note: expected type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` + found type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` + +error[E0308]: mismatched types + --> $DIR/impl_incorrect_method_signature.rs:18:1 + | +18 | / impl_runtime_apis! { +19 | | impl self::Api for Runtime { +20 | | fn test(data: String) {} +21 | | } +... | +33 | | } +34 | | } + | |_^ expected u64, found struct `std::string::String` + | + = note: expected type `u64` + found type `std::string::String` + error[E0308]: mismatched types --> $DIR/impl_incorrect_method_signature.rs:20:11 | @@ -18,6 +49,3 @@ error[E0308]: mismatched types | = note: expected type `u64` found type `std::string::String` - -Some errors have detailed explanations: E0053, E0308. -For more information about an error, try `rustc --explain E0053`. diff --git a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.rs b/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.rs index acca97a73df5bd2464fb736c733d84116b07c994..1664bec577b57a53715fc65b0f3234e12bd78503 100644 --- a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.rs +++ b/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.rs @@ -16,6 +16,8 @@ decl_runtime_apis! { } mod second { + use super::*; + decl_runtime_apis! { pub trait Api { fn test2(data: u64); diff --git a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.stderr b/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.stderr index 355db2864bb784a7011b5c0b8376a713371f88b2..4c37b6b716a0a97cd19bca6a5f469adc56e58ed4 100644 --- a/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.stderr +++ b/core/sr-api-macros/tests/ui/impl_two_traits_with_same_name.stderr @@ -1,25 +1,17 @@ error: Two traits with the same name detected! The trait name is used to generate its ID. Please rename one trait at the declaration! - --> $DIR/impl_two_traits_with_same_name.rs:31:15 + --> $DIR/impl_two_traits_with_same_name.rs:33:15 | -31 | impl second::Api for Runtime { +33 | impl second::Api for Runtime { | ^^^ -error: cannot find macro `decl_runtime_apis!` in this scope - --> $DIR/impl_two_traits_with_same_name.rs:19:2 +error[E0277]: the trait bound `RuntimeApiImpl: sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not satisfied + --> $DIR/impl_two_traits_with_same_name.rs:29:7 | -19 | decl_runtime_apis! { - | ^^^^^^^^^^^^^^^^^ +29 | impl self::Api for Runtime { + | ^^^^^^^^^^^^^^^^ the trait `sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not implemented for `RuntimeApiImpl` -error[E0433]: failed to resolve: could not find `runtime_decl_for_Api` in `second` - --> $DIR/impl_two_traits_with_same_name.rs:26:1 +error[E0277]: the trait bound `RuntimeApiImpl: sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not satisfied + --> $DIR/impl_two_traits_with_same_name.rs:33:7 | -26 | / impl_runtime_apis! { -27 | | impl self::Api for Runtime { -28 | | fn test(data: u64) {} -29 | | } -... | -33 | | } -34 | | } - | |_^ could not find `runtime_decl_for_Api` in `second` - -For more information about this error, try `rustc --explain E0433`. +33 | impl second::Api for Runtime { + | ^^^^^^^^^^^^^^^^^^ the trait `sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::Core, substrate_test_runtime::Extrinsic>>` is not implemented for `RuntimeApiImpl` diff --git a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.rs index 0e7dc56951647264d532ee41c4a917883e9f5b22..20f114c6bb29e597f7c093c72be7c9ebd9501b7b 100644 --- a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.rs +++ b/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.rs @@ -1,6 +1,6 @@ -use sr_primitives::traits::GetNodeBlockType; +use sr_primitives::traits::{GetNodeBlockType, Block as BlockT}; use test_client::runtime::Block; -use client::{decl_runtime_apis, impl_runtime_apis}; +use client::{decl_runtime_apis, impl_runtime_apis, runtime_api}; /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` /// trait are done by the `construct_runtime!` macro in a real runtime. @@ -21,6 +21,18 @@ impl_runtime_apis! { unimplemented!() } } + + impl runtime_api::Core for Runtime { + fn version() -> runtime_api::RuntimeVersion { + unimplemented!() + } + fn execute_block(_: Block) { + unimplemented!() + } + fn initialize_block(_: &::Header) { + unimplemented!() + } + } } fn main() {} diff --git a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.stderr index 9bfc04c8db046ecba4f42d2140143a7ade6b3886..b2b024ee7fe1e9ca319a0d9a8a70586812e1e518 100644 --- a/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ b/core/sr-api-macros/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -10,6 +10,22 @@ error[E0053]: method `test` has an incompatible type for trait = note: expected type `fn(u64)` found type `fn(&u64)` +error[E0053]: method `Api_test_runtime_api_impl` has an incompatible type for trait + --> $DIR/type_reference_in_impl_runtime_apis_call.rs:18:1 + | +12 | / decl_runtime_apis! { +13 | | pub trait Api { +14 | | fn test(data: u64); +15 | | } +16 | | } + | |_- type in trait +17 | +18 | impl_runtime_apis! { + | ^^^^^^^^^^^^^^^^^^ expected u64, found &u64 + | + = note: expected type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` + found type `fn(&RuntimeApiImpl, &sr_primitives::generic::block::BlockId, substrate_test_runtime::Extrinsic>>, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::runtime_api::ExecutionContext, std::option::Option<&u64>, std::vec::Vec) -> std::result::Result, sr_api_hidden_includes_DECL_RUNTIME_APIS::sr_api_client::error::Error>` + error[E0308]: mismatched types --> $DIR/type_reference_in_impl_runtime_apis_call.rs:18:1 | @@ -17,13 +33,22 @@ error[E0308]: mismatched types 19 | | impl self::Api for Runtime { 20 | | fn test(data: &u64) { 21 | | unimplemented!() -22 | | } -23 | | } -24 | | } +... | +35 | | } +36 | | } | |_^ expected u64, found &u64 | = note: expected type `u64` found type `&u64` -Some errors have detailed explanations: E0053, E0308. -For more information about an error, try `rustc --explain E0053`. +error[E0308]: mismatched types + --> $DIR/type_reference_in_impl_runtime_apis_call.rs:20:11 + | +20 | fn test(data: &u64) { + | ^^^^^^^ + | | + | expected u64, found &u64 + | help: consider removing the borrow: `data` + | + = note: expected type `u64` + found type `&u64` diff --git a/core/sr-arithmetic/Cargo.toml b/core/sr-arithmetic/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..fd484671dd84896f97d4daf0db343633899b2beb --- /dev/null +++ b/core/sr-arithmetic/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "sr-arithmetic" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +integer-sqrt = "0.1.2" +num-traits = { version = "0.2.8", default-features = false } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +substrate-debug-derive = { path = "../primitives/debug-derive", default-features = false } + +[dev-dependencies] +primitive-types = "0.6.0" +rand = "0.7.2" +criterion = "0.3" + +[features] +default = ["std"] +std = [ + "codec/std", + "num-traits/std", + "rstd/std", + "serde", + "substrate-debug-derive/std", +] + +[[bench]] +name = "bench" +harness = false diff --git a/core/sr-arithmetic/benches/bench.rs b/core/sr-arithmetic/benches/bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..22c0ce6f566e965b1fc8885b6427753fec2ad74a --- /dev/null +++ b/core/sr-arithmetic/benches/bench.rs @@ -0,0 +1,80 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use criterion::{Criterion, Throughput, BenchmarkId, criterion_group, criterion_main}; +use sr_arithmetic::biguint::{BigUint, Single}; +use rand::Rng; + +fn random_big_uint(size: usize) -> BigUint { + let mut rng = rand::thread_rng(); + let digits: Vec<_> = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); + BigUint::from_limbs(&digits) +} + +fn bench_op(c: &mut Criterion, name: &str, op: F) { + let mut group = c.benchmark_group(name); + + for size in [2, 4, 6, 8, 10].iter() { + group.throughput(Throughput::Elements(*size)); + group.bench_with_input(BenchmarkId::from_parameter(size), size, |bencher, &size| { + let a = random_big_uint(size as usize); + let b = random_big_uint(size as usize); + + bencher.iter(|| op(&a, &b)); + }); + } +} + +fn bench_addition(c: &mut Criterion) { + bench_op(c, "addition", |a, b| { + let _ = a.clone().add(&b); + }); +} + +fn bench_subtraction(c: &mut Criterion) { + bench_op(c, "subtraction", |a, b| { + let _ = a.clone().sub(&b); + }); +} + +fn bench_multiplication(c: &mut Criterion) { + bench_op(c, "multiplication", |a, b| { + let _ = a.clone().mul(&b); + }); +} + +fn bench_division(c: &mut Criterion) { + let mut group = c.benchmark_group("division"); + + for size in [4, 6, 8, 10].iter() { + group.throughput(Throughput::Elements(*size)); + group.bench_with_input(BenchmarkId::from_parameter(size), size, |bencher, &size| { + let a = random_big_uint(size as usize); + let b = random_big_uint(rand::thread_rng().gen_range(2, size as usize)); + + bencher.iter(|| { + let _ = a.clone().div(&b, true); + }); + }); + } +} + +criterion_group!{ + name = benches; + config = Criterion::default(); + targets = bench_addition, bench_subtraction, bench_multiplication, bench_division +} +criterion_main!(benches); diff --git a/core/sr-arithmetic/fuzzer/.gitignore b/core/sr-arithmetic/fuzzer/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3ebcb104d4a50a19959dc7ff2bc06ee6bb48b31f --- /dev/null +++ b/core/sr-arithmetic/fuzzer/.gitignore @@ -0,0 +1,2 @@ +hfuzz_target +hfuzz_workspace diff --git a/core/sr-arithmetic/fuzzer/Cargo.lock b/core/sr-arithmetic/fuzzer/Cargo.lock new file mode 100644 index 0000000000000000000000000000000000000000..f6ce6f1d4797dca029231bbe726851badf3e9ddb --- /dev/null +++ b/core/sr-arithmetic/fuzzer/Cargo.lock @@ -0,0 +1,465 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "arbitrary" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitvec" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-slice-cast" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fixed-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "honggfuzz" +version = "0.5.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.65" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-scale-codec" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "primitive-types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-hex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sr-arithmetic" +version = "2.0.0" +dependencies = [ + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", +] + +[[package]] +name = "sr-arithmetic-fuzzer" +version = "2.0.0" +dependencies = [ + "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-arithmetic 2.0.0", +] + +[[package]] +name = "sr-std" +version = "2.0.0" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "static_assertions" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "uint" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9633b74910e1870f50f5af189b08487195cdb83c0e27a71d6f64d5e09dd0538b" +"checksum byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbcbf18128ec71d8d4a0d054461ec59fff5b75b7d10a4c9b7c7cb1a379c3e77" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +"checksum fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6357b15872f8126e4ea7cf79d579473f132ccd2de239494ad1bf4aa892faea68" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)" = "24c27b4aa3049d6d10d8e33d52c9d03ca9aec18f8a449b246f8c4a5b0c10fb34" +"checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" +"checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "001fbbb956d8593f321c7a784f64d16b2c99b2657823976eea729006ad2c3668" +"checksum parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42af752f59119656fa3cb31e8852ed24e895b968c0bdb41847da7f0cea6d155f" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +"checksum primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97b5a08dda18910f056e5c2060c034e77cab18e0bd7d895e44f03207af4c71d5" +"checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" +"checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..482905c4350106cffa386455c487c030fab16829 --- /dev/null +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sr-arithmetic-fuzzer" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +sr-arithmetic = { path = ".." } +honggfuzz = "0.5" +primitive-types = "0.6" +num-bigint = "0.2" +num-traits = "0.2" + +[workspace] + +[[bin]] +name = "biguint" +path = "src/biguint.rs" + +[[bin]] +name = "rational128" +path = "src/rational128.rs" diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs new file mode 100644 index 0000000000000000000000000000000000000000..bd270a97cac7102b37d3bd400f7c02c080e6cdaf --- /dev/null +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -0,0 +1,181 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run biguint`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug biguint hfuzz_workspace/biguint/*.fuzz`. +//! +//! # More infomation +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/). + +use honggfuzz::fuzz; +use sr_arithmetic::biguint::{BigUint, Single}; +use std::convert::TryFrom; + +fn main() { + loop { + fuzz!(|data: (Vec, Vec, bool)| { + let (mut digits_u, mut digits_v, return_remainder) = data; + + let mut u = BigUint::from_limbs(&digits_u); + let mut v = BigUint::from_limbs(&digits_v); + + u.lstrip(); + v.lstrip(); + + let ue = u128::try_from(u.clone()); + let ve = u128::try_from(v.clone()); + + digits_u.reverse(); + digits_v.reverse(); + + let num_u = num_bigint::BigUint::new(digits_u.clone()); + let num_v = num_bigint::BigUint::new(digits_v.clone()); + + if check_digit_lengths(&u, &v, 4) { + assert_eq!(u.cmp(&v), ue.cmp(&ve)); + assert_eq!(u.eq(&v), ue.eq(&ve)); + } + + if check_digit_lengths(&u, &v, 3) { + let expected = ue.unwrap() + ve.unwrap(); + let t = u.clone().add(&v); + assert_eq!( + u128::try_from(t.clone()).unwrap(), expected, + "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + + if check_digit_lengths(&u, &v, 4) { + let expected = ue.unwrap().checked_sub(ve.unwrap()); + let t = u.clone().sub(&v); + if expected.is_none() { + assert!(t.is_err()) + } else { + let t = t.unwrap(); + let expected = expected.unwrap(); + assert_eq!( + u128::try_from(t.clone()).unwrap(), expected, + "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + } + + if check_digit_lengths(&u, &v, 2) { + let expected = ue.unwrap() * ve.unwrap(); + let t = u.clone().mul(&v); + assert_eq!( + u128::try_from(t.clone()).unwrap(), expected, + "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + + if check_digit_lengths(&u, &v, 4) { + let (ue, ve) = (ue.unwrap(), ve.unwrap()); + if ve == 0 { + return; + } + let (q, r) = (ue / ve, ue % ve); + if let Some((qq, rr)) = u.clone().div(&v, true) { + assert_eq!( + u128::try_from(qq.clone()).unwrap(), q, + "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + assert_eq!( + u128::try_from(rr.clone()).unwrap(), r, + "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, + ); + } else if v.len() == 1 { + let qq = u.clone().div_unit(ve as Single); + assert_eq!( + u128::try_from(qq.clone()).unwrap(), q, + "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + } else if v.msb() != 0 && u.msb() != 0 && u.len() > v.len() { + panic!("div returned none for an unexpected reason"); + } + } + + // Test against num_bigint + + // Equality + + assert_eq!(u.cmp(&v), num_u.cmp(&num_v)); + + // Addition + + let w = u.clone().add(&v); + let num_w = num_u.clone() + &num_v; + + assert_biguints_eq(&w, &num_w); + + // Subtraction + + if let Ok(w) = u.clone().sub(&v) { + let num_w = num_u.clone() - &num_v; + + assert_biguints_eq(&w, &num_w); + } + + // Multiplication + + let w = u.clone().mul(&v); + let num_w = num_u.clone() * &num_v; + + assert_biguints_eq(&w, &num_w); + + // Division + + if v.len() == 1 && v.get(0) != 0 { + let w = u.clone().div_unit(v.get(0)); + let num_w = num_u.clone() / &num_v; + assert_biguints_eq(&w, &num_w); + } else if u.len() > v.len() && v.len() > 0 { + let num_remainder = num_u.clone() % num_v.clone(); + + let (w, remainder) = u.clone().div(&v, return_remainder).unwrap(); + let num_w = num_u.clone() / &num_v; + + assert_biguints_eq(&w, &num_w); + + if return_remainder { + assert_biguints_eq(&remainder, &num_remainder); + } + } + }); + } +} + +fn check_digit_lengths(u: &BigUint, v: &BigUint, max_limbs: usize) -> bool { + 1 <= u.len() && u.len() <= max_limbs && 1 <= v.len() && v.len() <= max_limbs +} + +fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { + let mut a = a.clone(); + a.lstrip(); + + // `num_bigint::BigUint` doesn't expose it's internals, so we need to convert into that to + // compare. + let limbs = (0 .. a.len()).map(|i| a.get(i)).collect(); + let num_a = num_bigint::BigUint::new(limbs); + + assert!(&num_a == b, "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); +} diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs new file mode 100644 index 0000000000000000000000000000000000000000..b2a00d754527f042cec53f4f6986d8571ad7530e --- /dev/null +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -0,0 +1,77 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run rational128`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug rational128 hfuzz_workspace/rational128/*.fuzz`. +//! +//! # More infomation +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/). + +use honggfuzz::fuzz; +use sr_arithmetic::{helpers_128bit::multiply_by_rational, traits::Zero}; + +fn main() { + loop { + fuzz!(|data: ([u8; 16], [u8; 16], [u8; 16])| { + let (a_bytes, b_bytes, c_bytes) = data; + let (a, b, c) = ( + u128::from_be_bytes(a_bytes), + u128::from_be_bytes(b_bytes), + u128::from_be_bytes(c_bytes), + ); + + println!("++ Equation: {} * {} / {}", a, b, c); + + // The point of this fuzzing is to make sure that `multiply_by_rational` is 100% + // accurate as long as the value fits in a u128. + if let Ok(result) = multiply_by_rational(a, b, c) { + let truth = mul_div(a, b, c); + + if result != truth && result != truth + 1 { + println!("++ Expected {}", truth); + println!("+++++++ Got {}", result); + panic!(); + } + } + }) + } +} + +fn mul_div(a: u128, b: u128, c: u128) -> u128 { + use primitive_types::U256; + if a.is_zero() { + return Zero::zero(); + } + let c = c.max(1); + + // e for extended + let ae: U256 = a.into(); + let be: U256 = b.into(); + let ce: U256 = c.into(); + + let r = ae * be / ce; + if r > u128::max_value().into() { + a + } else { + r.as_u128() + } +} diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs new file mode 100644 index 0000000000000000000000000000000000000000..1a701a5ebd460cd950e312a11fbc3ca2e6c15769 --- /dev/null +++ b/core/sr-arithmetic/src/biguint.rs @@ -0,0 +1,735 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Infinite precision unsigned integer for substrate runtime. + +use num_traits::Zero; +use rstd::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom}; + +// A sensible value for this would be half of the dword size of the host machine. Since the +// runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively +// should yield the most performance. +/// Representation of a single limb. +pub type Single = u32; +/// Representation of two limbs. +pub type Double = u64; +/// Difference in the number of bits of [`Single`] and [`Double`]. +const SHIFT: usize = 32; +/// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers. +const B: Double = Single::max_value() as Double + 1; + +/// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers. +pub fn split(a: Double) -> (Single, Single) { + let al = a as Single; + let ah = (a >> SHIFT) as Single; + (ah, al) +} + +/// Assumed as a given primitive. +/// +/// Multiplication of two singles, which at most yields 1 double. +pub fn mul_single(a: Single, b: Single) -> Double { + let a: Double = a.into(); + let b: Double = b.into(); + a * b +} + +/// Assumed as a given primitive. +/// +/// Addition of two singles, which at most takes a single limb of result and a carry, +/// returned as a tuple respectively. +pub fn add_single(a: Single, b: Single) -> (Single, Single) { + let a: Double = a.into(); + let b: Double = b.into(); + let q = a + b; + let (carry, r) = split(q); + (r, carry) +} + +/// Assumed as a given primitive. +/// +/// Division of double by a single limb. Always returns a double limb of quotient and a single +/// limb of remainder. +fn div_single(a: Double, b: Single) -> (Double, Single) { + let b: Double = b.into(); + let q = a / b; + let r = a % b; + // both conversions are trivially safe. + (q, r as Single) +} + +/// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`]. +#[derive(Clone, Default)] +pub struct BigUint { + /// digits (limbs) of this number (sorted as msb -> lsd). + pub(crate) digits: Vec, +} + +impl BigUint { + /// Create a new instance with `size` limbs. This prevents any number with zero limbs to be + /// created. + /// + /// The behavior of the type is undefined with zero limbs. + pub fn with_capacity(size: usize) -> Self { + Self { digits: vec![0; size.max(1)] } + } + + /// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is + /// used. + pub fn from_limbs(limbs: &[Single]) -> Self { + if !limbs.is_empty() { + Self { digits: limbs.to_vec() } + } else { + Zero::zero() + } + } + + /// Number of limbs. + pub fn len(&self) -> usize { self.digits.len() } + + /// A naive getter for limb at `index`. Note that the order is lsb -> msb. + /// + /// #### Panics + /// + /// This panics if index is out of range. + pub fn get(&self, index: usize) -> Single { + self.digits[self.len() - 1 - index] + } + + /// A naive getter for limb at `index`. Note that the order is lsb -> msb. + pub fn checked_get(&self, index: usize) -> Option { + let i = self.len().checked_sub(1)?; + let j = i.checked_sub(index)?; + self.digits.get(j).cloned() + } + + /// A naive setter for limb at `index`. Note that the order is lsb -> msb. + /// + /// #### Panics + /// + /// This panics if index is out of range. + pub fn set(&mut self, index: usize, value: Single) { + let len = self.digits.len(); + self.digits[len - 1 - index] = value; + } + + /// returns the least significant limb of the number. + /// + /// #### Panics + /// + /// While the constructor of the type prevents this, this can panic if `self` has no digits. + pub fn lsb(&self) -> Single { + self.digits[self.len() - 1] + } + + /// returns the most significant limb of the number. + /// + /// #### Panics + /// + /// While the constructor of the type prevents this, this can panic if `self` has no digits. + pub fn msb(&self) -> Single { + self.digits[0] + } + + /// Strips zeros from the left side (the most significant limbs) of `self`, if any. + pub fn lstrip(&mut self) { + // by definition, a big-int number should never have leading zero limbs. This function + // has the ability to cause this. There is nothing to do if the number already has 1 + // limb only. call it a day and return. + if self.len().is_zero() { return; } + let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(0); + + if index > 0 { + self.digits = self.digits[index..].to_vec() + } + } + + /// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self` + /// is already bigger than `size` limbs. + pub fn lpad(&mut self, size: usize) { + let n = self.len(); + if n >= size { return; } + let pad = size - n; + let mut new_digits = (0..pad).map(|_| 0).collect::>(); + new_digits.extend(self.digits.iter()); + self.digits = new_digits; + } + + /// Adds `self` with `other`. self and other do not have to have any particular size. Given + /// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1` + /// limbs. + /// + /// This function does not strip the output and returns the original allocated `n + 1` + /// limbs. The caller may strip the output if desired. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn add(self, other: &Self) -> Self { + let n = self.len().max(other.len()); + let mut k: Double = 0; + let mut w = Self::with_capacity(n + 1); + + for j in 0..n { + let u = Double::from(self.checked_get(j).unwrap_or(0)); + let v = Double::from(other.checked_get(j).unwrap_or(0)); + let s = u + v + k; + w.set(j, (s % B) as Single); + k = s / B; + } + // k is always 0 or 1. + w.set(n, k as Single); + w + } + + /// Subtracts `other` from `self`. self and other do not have to have any particular size. + /// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`. + /// + /// If `other` is bigger than `self`, `Err(B - borrow)` is returned. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn sub(self, other: &Self) -> Result { + let n = self.len().max(other.len()); + let mut k = 0; + let mut w = Self::with_capacity(n); + for j in 0..n { + let s = { + let u = Double::from(self.checked_get(j).unwrap_or(0)); + let v = Double::from(other.checked_get(j).unwrap_or(0)); + let mut needs_borrow = false; + let mut t = 0; + + if let Some(v) = u.checked_sub(v) { + if let Some(v2) = v.checked_sub(k) { + t = v2 % B; + k = 0; + } else { + needs_borrow = true; + } + } else { + needs_borrow = true; + } + if needs_borrow { + t = u + B - v - k; + k = 1; + } + t + }; + // PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is + // trivial. The latter will not overflow this branch will only happen if the sum of + // `u - v - k` part has been negative, hence `u + B - v - k < b`. + w.set(j, s as Single); + } + + if k.is_zero() { + Ok(w) + } else { + Err(w) + } + } + + /// Multiplies n-limb number `self` with m-limb number `other`. + /// + /// The resulting number will always have `n + m` limbs. + /// + /// This function does not strip the output and returns the original allocated `n + m` + /// limbs. The caller may strip the output if desired. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn mul(self, other: &Self) -> Self { + let n = self.len(); + let m = other.len(); + let mut w = Self::with_capacity(m + n); + + for j in 0..n { + if self.get(j) == 0 { + // Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if + // otherwise. + continue; + } + + let mut k = 0; + for i in 0..m { + // PROOF: (B−1) × (B−1) + (B−1) + (B−1) = B^2 −1 < B^2. addition is safe. + let t = + mul_single(self.get(j), other.get(i)) + + Double::from(w.get(i + j)) + + Double::from(k); + w.set(i + j, (t % B) as Single); + // PROOF: (B^2 - 1) / B < B. conversion is safe. + k = (t / B) as Single; + } + w.set(j + m, k); + } + w + } + + /// Divides `self` by a single limb `other`. This can be used in cases where the original + /// division cannot work due to the divisor (`other`) being just one limb. + /// + /// Invariant: `other` cannot be zero. + pub fn div_unit(self, mut other: Single) -> Self { + other = other.max(1); + let n = self.len(); + let mut out = Self::with_capacity(n); + let mut r: Single = 0; + // PROOF: (B-1) * B + (B-1) still fits in double + let with_r = |x: Double, r: Single| { Double::from(r) * B + x }; + for d in (0..n).rev() { + let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ; + out.set(d, q as Single); + r = rr; + } + out + } + + /// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb + /// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both + /// in the form of an option's `Ok`. + /// + /// - requires `other` to be stripped and have no leading zeros. + /// - requires `self` to be stripped and have no leading zeros. + /// - requires `other` to have at least two limbs. + /// - requires `self` to have a greater length compared to `other`. + /// + /// All arguments are examined without being stripped for the above conditions. If any of + /// the above fails, `None` is returned.` + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> { + if other.len() <= 1 + || other.msb() == 0 + || self.msb() == 0 + || self.len() <= other.len() + { + return None + } + let n = other.len(); + let m = self.len() - n; + + let mut q = Self::with_capacity(m + 1); + let mut r = Self::with_capacity(n); + + // PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are + // safe. + let normalizer_bits = other.msb().leading_zeros() as Single; + let normalizer = (2 as Single).pow(normalizer_bits as u32) as Single; + + // step D1. + let mut self_norm = self.mul(&Self::from(normalizer)); + let mut other_norm = other.clone().mul(&Self::from(normalizer)); + + // defensive only; the mul implementation should always create this. + self_norm.lpad(n + m + 1); + other_norm.lstrip(); + + // step D2. + for j in (0..=m).rev() { + // step D3.0 Find an estimate of q[j], named qhat. + let (qhat, rhat) = { + // PROOF: this always fits into `Double`. In the context of Single = u8, and + // Double = u16, think of 255 * 256 + 255 which is just u16::max_value(). + let dividend = + Double::from(self_norm.get(j + n)) + * B + + Double::from(self_norm.get(j + n - 1)); + let divisor = other_norm.get(n - 1); + div_single(dividend, divisor) + }; + + // D3.1 test qhat + // replace qhat and rhat with RefCells. This helps share state with the closure + let qhat = RefCell::new(qhat); + let rhat = RefCell::new(Double::from(rhat)); + + let test = || { + // decrease qhat if it is bigger than the base (B) + let qhat_local = *qhat.borrow(); + let rhat_local = *rhat.borrow(); + let predicate_1 = qhat_local >= B; + let predicate_2 = { + let lhs = qhat_local * Double::from(other_norm.get(n - 2)); + let rhs = B * rhat_local + Double::from(self_norm.get(j + n - 2)); + lhs > rhs + }; + if predicate_1 || predicate_2 { + *qhat.borrow_mut() -= 1; + *rhat.borrow_mut() += Double::from(other_norm.get(n - 1)); + true + } else { + false + } + }; + + test(); + while (*rhat.borrow() as Double) < B { + if !test() { break; } + } + + let qhat = qhat.into_inner(); + // we don't need rhat anymore. just let it go out of scope when it does. + + // step D4 + let lhs = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; + let rhs = other_norm.clone().mul(&Self::from(qhat)); + + let maybe_sub = lhs.sub(&rhs); + let mut negative = false; + let sub = match maybe_sub { + Ok(t) => t, + Err(t) => { negative = true; t } + }; + (j..=j+n).for_each(|d| { self_norm.set(d, sub.get(d - j)); }); + + // step D5 + // PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion + // is safe. + q.set(j, qhat as Single); + + // step D6: add back if negative happened. + if negative { + q.set(j, q.get(j) - 1); + let u = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; + let r = other_norm.clone().add(&u); + (j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); }) + } + } + + // if requested, calculate remainder. + if rem { + // undo the normalization. + if normalizer_bits > 0 { + let s = SHIFT as u32; + let nb = normalizer_bits; + for d in 0..n-1 { + let v = self_norm.get(d) >> nb + | self_norm.get(d + 1).overflowing_shl(s - nb).0; + r.set(d, v); + } + r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits); + } else { + r = self_norm; + } + } + + Some((q, r)) + } +} + +impl rstd::fmt::Debug for BigUint { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { + write!( + f, + "BigUint {{ {:?} ({:?})}}", + self.digits, + u128::try_from(self.clone()).unwrap_or(0), + ) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { + Ok(()) + } + +} + +impl PartialEq for BigUint { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for BigUint {} + +impl Ord for BigUint { + fn cmp(&self, other: &Self) -> Ordering { + let lhs_first = self.digits.iter().position(|&e| e != 0); + let rhs_first = other.digits.iter().position(|&e| e != 0); + + match (lhs_first, rhs_first) { + // edge cases that should not happen. This basically means that one or both were + // zero. + (None, None) => Ordering::Equal, + (Some(_), None) => Ordering::Greater, + (None, Some(_)) => Ordering::Less, + (Some(lhs_idx), Some(rhs_idx)) => { + let lhs = &self.digits[lhs_idx..]; + let rhs = &other.digits[rhs_idx..]; + let len_cmp = lhs.len().cmp(&rhs.len()); + match len_cmp { + Ordering::Equal => lhs.cmp(rhs), + _ => len_cmp, + } + } + } + } +} + +impl PartialOrd for BigUint { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl ops::Add for BigUint { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + self.add(&rhs) + } +} + +impl ops::Sub for BigUint { + type Output = Self; + fn sub(self, rhs: Self) -> Self::Output { + self.sub(&rhs).unwrap_or_else(|e| e) + } +} + +impl ops::Mul for BigUint { + type Output = Self; + fn mul(self, rhs: Self) -> Self::Output { + self.mul(&rhs) + } +} + +impl Zero for BigUint { + fn zero() -> Self { + Self { digits: vec![Zero::zero()] } + } + + fn is_zero(&self) -> bool { + self.digits.iter().all(|d| d.is_zero()) + } +} + +macro_rules! impl_try_from_number_for { + ($([$type:ty, $len:expr]),+) => { + $( + impl TryFrom for $type { + type Error = &'static str; + fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { + value.lstrip(); + let error_message = concat!("cannot fit a number into ", stringify!($type)); + if value.len() * SHIFT > $len { + Err(error_message) + } else { + let mut acc: $type = Zero::zero(); + for (i, d) in value.digits.iter().rev().cloned().enumerate() { + let d: $type = d.into(); + acc += d << (SHIFT * i); + } + Ok(acc) + } + } + } + )* + }; +} +// can only be implemented for sizes bigger than two limb. +impl_try_from_number_for!([u128, 128], [u64, 64]); + +macro_rules! impl_from_for_smaller_than_word { + ($($type:ty),+) => { + $(impl From<$type> for BigUint { + fn from(a: $type) -> Self { + Self { digits: vec! [a.into()] } + } + })* + } +} +impl_from_for_smaller_than_word!(u8, u16, Single); + +impl From for BigUint { + fn from(a: Double) -> Self { + let (ah, al) = split(a); + Self { digits: vec![ah, al] } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + + fn with_limbs(n: usize) -> BigUint { + BigUint { digits: vec![1; n] } + } + + #[test] + fn split_works() { + let a = SHIFT / 2; + let b = SHIFT * 3 / 2; + let num: Double = 1 << a | 1 << b; + // example when `Single = u8` + // assert_eq!(num, 0b_0001_0000_0001_0000) + assert_eq!(split(num), (1 << a, 1 << a)); + } + + #[test] + fn strip_works() { + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![1, 0] }); + + let mut a = BigUint::from_limbs(&[0, 0, 1]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![1] }); + + let mut a = BigUint::from_limbs(&[0, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![0] }); + + let mut a = BigUint::from_limbs(&[0, 0, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![0] }); + } + + #[test] + fn lpad_works() { + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(2); + assert_eq!(a.digits, vec![0, 1, 0]); + + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(3); + assert_eq!(a.digits, vec![0, 1, 0]); + + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(4); + assert_eq!(a.digits, vec![0, 0, 1, 0]); + } + + #[test] + fn equality_works() { + assert_eq!( + BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + true, + ); + assert_eq!( + BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + false, + ); + assert_eq!( + BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + true, + ); + } + + #[test] + fn ordering_works() { + assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] }); + assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] }); + assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] }); + assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] }); + assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] }); + + assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); + + assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] }); + + assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] }); + } + + #[test] + fn can_try_build_numbers_from_types() { + use rstd::convert::TryFrom; + assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1); + assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::max_value() as u64 + 2); + assert_eq!( + u64::try_from(with_limbs(3)).unwrap_err(), + "cannot fit a number into u64", + ); + assert_eq!( + u128::try_from(with_limbs(3)).unwrap(), + u32::max_value() as u128 + u64::max_value() as u128 + 3 + ); + } + + #[test] + fn zero_works() { + assert_eq!(BigUint::zero(), BigUint { digits: vec![0] }); + assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false); + assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true); + + let a = BigUint::zero(); + let b = BigUint::zero(); + let c = a * b; + assert_eq!(c.digits, vec![0, 0]); + } + + #[test] + fn sub_negative_works() { + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(), + BigUint::from(5 as Single) + ); + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(), + BigUint::from(0 as Single) + ); + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(), + BigUint::from((B - 3) as Single), + ); + } + + #[test] + fn mul_always_appends_one_digit() { + let a = BigUint::from(10 as Single); + let b = BigUint::from(4 as Single); + assert_eq!(a.len(), 1); + assert_eq!(b.len(), 1); + + let n = a.mul(&b); + + assert_eq!(n.len(), 2); + assert_eq!(n.digits, vec![0, 40]); + } + + #[test] + fn div_conditions_work() { + let a = BigUint { digits: vec![2] }; + let b = BigUint { digits: vec![1, 2] }; + let c = BigUint { digits: vec![1, 1, 2] }; + let d = BigUint { digits: vec![0, 2] }; + let e = BigUint { digits: vec![0, 1, 1, 2] }; + + assert!(a.clone().div(&b, true).is_none()); + assert!(c.clone().div(&a, true).is_none()); + assert!(c.clone().div(&d, true).is_none()); + assert!(e.clone().div(&a, true).is_none()); + + assert!(c.clone().div(&b, true).is_some()); + } + + #[test] + fn div_unit_works() { + let a = BigUint { digits: vec![100] }; + let b = BigUint { digits: vec![1, 100] }; + + assert_eq!(a.clone().div_unit(1), a); + assert_eq!(a.clone().div_unit(0), a); + assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single)); + assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single)); + + assert_eq!(b.clone().div_unit(1), b); + assert_eq!(b.clone().div_unit(0), b); + assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single)); + assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single)); + + } +} diff --git a/core/sr-arithmetic/src/fixed64.rs b/core/sr-arithmetic/src/fixed64.rs new file mode 100644 index 0000000000000000000000000000000000000000..bd58e36940ae6c1887302fd0ded53ba56232e244 --- /dev/null +++ b/core/sr-arithmetic/src/fixed64.rs @@ -0,0 +1,244 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use rstd::{ + ops, prelude::*, + convert::{TryFrom, TryInto}, +}; +use codec::{Encode, Decode}; +use crate::{ + Perbill, + traits::{ + SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating + } +}; + +/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] +/// with fixed point accuracy of one billion. +#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Fixed64(i64); + +/// The accuracy of the `Fixed64` type. +const DIV: i64 = 1_000_000_000; + +impl Fixed64 { + /// creates self from a natural number. + /// + /// Note that this might be lossy. + pub fn from_natural(int: i64) -> Self { + Self(int.saturating_mul(DIV)) + } + + /// Return the accuracy of the type. Given that this function returns the value `X`, it means + /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. + pub fn accuracy() -> i64 { + DIV + } + + /// Consume self and return the inner value. + /// + /// This should only be used for testing. + #[cfg(any(feature = "std", test))] + pub fn into_inner(self) -> i64 { self.0 } + + /// Raw constructor. Equal to `parts / 1_000_000_000`. + pub fn from_parts(parts: i64) -> Self { + Self(parts) + } + + /// creates self from a rational number. Equal to `n/d`. + /// + /// Note that this might be lossy. + pub fn from_rational(n: i64, d: u64) -> Self { + Self( + (i128::from(n).saturating_mul(i128::from(DIV)) / i128::from(d).max(1)) + .try_into() + .unwrap_or_else(|_| Bounded::max_value()) + ) + } + + /// Performs a saturated multiply and accumulate by unsigned number. + /// + /// Returns a saturated `int + (self * int)`. + pub fn saturated_multiply_accumulate(self, int: N) -> N + where + N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + + ops::Rem + ops::Div + ops::Mul + + ops::Add, + { + let div = DIV as u64; + let positive = self.0 > 0; + // safe to convert as absolute value. + let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1); + + + // will always fit. + let natural_parts = parts / div; + // might saturate. + let natural_parts: N = natural_parts.saturated_into(); + // fractional parts can always fit into u32. + let perbill_parts = (parts % div) as u32; + + let n = int.clone().saturating_mul(natural_parts); + let p = Perbill::from_parts(perbill_parts) * int.clone(); + + // everything that needs to be either added or subtracted from the original weight. + let excess = n.saturating_add(p); + + if positive { + int.saturating_add(excess) + } else { + int.saturating_sub(excess) + } + } +} + +impl Saturating for Fixed64 { + fn saturating_add(self, rhs: Self) -> Self { + Self(self.0.saturating_add(rhs.0)) + } + fn saturating_mul(self, rhs: Self) -> Self { + Self(self.0.saturating_mul(rhs.0) / DIV) + } + fn saturating_sub(self, rhs: Self) -> Self { + Self(self.0.saturating_sub(rhs.0)) + } +} + +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe addition. +impl ops::Add for Fixed64 { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe subtraction. +impl ops::Sub for Fixed64 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +impl CheckedSub for Fixed64 { + fn checked_sub(&self, rhs: &Self) -> Option { + self.0.checked_sub(rhs.0).map(Self) + } +} + +impl CheckedAdd for Fixed64 { + fn checked_add(&self, rhs: &Self) -> Option { + self.0.checked_add(rhs.0).map(Self) + } +} + +impl rstd::fmt::Debug for Fixed64 { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + write!(f, "Fixed64({},{})", self.0 / DIV, (self.0 % DIV) / 1000) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn max() -> Fixed64 { + Fixed64::from_parts(i64::max_value()) + } + + #[test] + fn fixed64_semantics() { + assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2); + assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4)); + assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1)); + + // biggest value that can be created. + assert_ne!(max(), Fixed64::from_natural(9_223_372_036)); + assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); + } + + #[test] + fn fixed_64_growth_decrease_curve() { + let test_set = vec![0u32, 1, 10, 1000, 1_000_000_000]; + + // negative (1/2) + let mut fm = Fixed64::from_rational(-1, 2); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i) as i32, i as i32 - i as i32 / 2); + }); + + // unit (1) multiplier + fm = Fixed64::from_parts(0); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i); + }); + + // i.5 multiplier + fm = Fixed64::from_rational(1, 2); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i * 3 / 2); + }); + + // dual multiplier + fm = Fixed64::from_rational(1, 1); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i * 2); + }); + } + + macro_rules! saturating_mul_acc_test { + ($num_type:tt) => { + assert_eq!( + Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type), + 1010, + ); + assert_eq!( + Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type), + 510, + ); + assert_eq!( + Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type), + 0, + ); + assert_eq!( + Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()), + $num_type::max_value() + ); + assert_eq!( + max().saturated_multiply_accumulate($num_type::max_value()), + $num_type::max_value() + ); + } + } + + #[test] + fn fixed64_multiply_accumulate_works() { + saturating_mul_acc_test!(u32); + saturating_mul_acc_test!(u64); + saturating_mul_acc_test!(u128); + } +} diff --git a/core/sr-arithmetic/src/helpers_128bit.rs b/core/sr-arithmetic/src/helpers_128bit.rs new file mode 100644 index 0000000000000000000000000000000000000000..10cc94ae777e66d2f802a464947f7bce4385301e --- /dev/null +++ b/core/sr-arithmetic/src/helpers_128bit.rs @@ -0,0 +1,112 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Some helper functions to work with 128bit numbers. Note that the functionality provided here is +//! only sensible to use with 128bit numbers because for smaller sizes, you can always rely on +//! assumptions of a bigger type (u128) being available, or simply create a per-thing and use the +//! multiplication implementation provided there. + +use crate::biguint; +use num_traits::Zero; +use rstd::{cmp::{min, max}, convert::TryInto, mem}; + +/// Helper gcd function used in Rational128 implementation. +pub fn gcd(a: u128, b: u128) -> u128 { + match ((a, b), (a & 1, b & 1)) { + ((x, y), _) if x == y => y, + ((0, x), _) | ((x, 0), _) => x, + ((x, y), (0, 1)) | ((y, x), (1, 0)) => gcd(x >> 1, y), + ((x, y), (0, 0)) => gcd(x >> 1, y >> 1) << 1, + ((x, y), (1, 1)) => { + let (x, y) = (min(x, y), max(x, y)); + gcd((y - x) >> 1, x) + }, + _ => unreachable!(), + } +} + +/// split a u128 into two u64 limbs +pub fn split(a: u128) -> (u64, u64) { + let al = a as u64; + let ah = (a >> 64) as u64; + (ah, al) +} + +/// Convert a u128 to a u32 based biguint. +pub fn to_big_uint(x: u128) -> biguint::BigUint { + let (xh, xl) = split(x); + let (xhh, xhl) = biguint::split(xh); + let (xlh, xll) = biguint::split(xl); + let mut n = biguint::BigUint::from_limbs(&[xhh, xhl, xlh, xll]); + n.lstrip(); + n +} + +/// Safely and accurately compute `a * b / c`. The approach is: +/// - Simply try `a * b / c`. +/// - Else, convert them both into big numbers and re-try. `Err` is returned if the result +/// cannot be safely casted back to u128. +/// +/// Invariant: c must be greater than or equal to 1. +pub fn multiply_by_rational(mut a: u128, mut b: u128, mut c: u128) -> Result { + if a.is_zero() || b.is_zero() { return Ok(Zero::zero()); } + c = c.max(1); + + // a and b are interchangeable by definition in this function. It always helps to assume the + // bigger of which is being multiplied by a `0 < b/c < 1`. Hence, a should be the bigger and + // b the smaller one. + if b > a { + mem::swap(&mut a, &mut b); + } + + // Attempt to perform the division first + if a % c == 0 { + a /= c; + c = 1; + } else if b % c == 0 { + b /= c; + c = 1; + } + + if let Some(x) = a.checked_mul(b) { + // This is the safest way to go. Try it. + Ok(x / c) + } else { + let a_num = to_big_uint(a); + let b_num = to_big_uint(b); + let c_num = to_big_uint(c); + + let mut ab = a_num * b_num; + ab.lstrip(); + let mut q = if c_num.len() == 1 { + // PROOF: if `c_num.len() == 1` then `c` fits in one limb. + ab.div_unit(c as biguint::Single) + } else { + // PROOF: both `ab` and `c` cannot have leading zero limbs; if length of `c` is 1, + // the previous branch would handle. Also, if ab for sure has a bigger size than + // c, because `a.checked_mul(b)` has failed, hence ab must be at least one limb + // bigger than c. In this case, returning zero is defensive-only and div should + // always return Some. + let (mut q, r) = ab.div(&c_num, true).unwrap_or((Zero::zero(), Zero::zero())); + let r: u128 = r.try_into() + .expect("reminder of div by c is always less than c; qed"); + if r > (c / 2) { q = q.add(&to_big_uint(1)); } + q + }; + q.lstrip(); + q.try_into().map_err(|_| "result cannot fit in u128") + } +} diff --git a/core/sr-arithmetic/src/lib.rs b/core/sr-arithmetic/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7b285002e54001ced6f9fcdeccfbd246f4a47519 --- /dev/null +++ b/core/sr-arithmetic/src/lib.rs @@ -0,0 +1,44 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Minimal fixed point arithmetic primitives and types for runtime. + +#![cfg_attr(not(feature = "std"), no_std)] + +/// Copied from `sr-primitives` and documented there. +#[cfg(test)] +macro_rules! assert_eq_error_rate { + ($x:expr, $y:expr, $error:expr $(,)?) => { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} + +pub mod biguint; +pub mod helpers_128bit; +pub mod traits; +mod per_things; +mod fixed64; +mod rational128; + +pub use fixed64::Fixed64; +pub use per_things::{Percent, Permill, Perbill, Perquintill}; +pub use rational128::Rational128; diff --git a/core/sr-arithmetic/src/per_things.rs b/core/sr-arithmetic/src/per_things.rs new file mode 100644 index 0000000000000000000000000000000000000000..2dd1e62d0b4db7aa45cd39b5ed3088fb84167013 --- /dev/null +++ b/core/sr-arithmetic/src/per_things.rs @@ -0,0 +1,520 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; + +use rstd::{ops, prelude::*, convert::TryInto}; +use codec::{Encode, Decode, CompactAs}; +use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; +use substrate_debug_derive::RuntimeDebug; + +macro_rules! implement_per_thing { + ($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => { + /// A fixed point representation of a number between in the range [0, 1]. + /// + #[doc = $title] + #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Ord, PartialOrd))] + #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, RuntimeDebug, CompactAs)] + pub struct $name($type); + + impl $name { + /// Nothing. + pub fn zero() -> Self { Self(0) } + + /// `true` if this is nothing. + pub fn is_zero(&self) -> bool { self.0 == 0 } + + /// Everything. + pub fn one() -> Self { Self($max) } + + /// Consume self and deconstruct into a raw numeric type. + pub fn deconstruct(self) -> $type { self.0 } + + /// Return the scale at which this per-thing is working. + pub const fn accuracy() -> $type { $max } + + /// From an explicitly defined number of parts per maximum of the type. + /// + /// This can be called at compile time. + pub const fn from_parts(parts: $type) -> Self { + Self([parts, $max][(parts > $max) as usize]) + } + + /// Converts from a percent. Equal to `x / 100`. + /// + /// This can be created at compile time. + pub const fn from_percent(x: $type) -> Self { + Self([x, 100][(x > 100) as usize] * ($max / 100)) + } + + /// Return the product of multiplication of this value by itself. + pub fn square(self) -> Self { + // both can be safely casted and multiplied. + let p: $upper_type = self.0 as $upper_type * self.0 as $upper_type; + let q: $upper_type = <$upper_type>::from($max) * <$upper_type>::from($max); + Self::from_rational_approximation(p, q) + } + + /// Converts a fraction into `Permill`. + #[cfg(feature = "std")] + pub fn from_fraction(x: f64) -> Self { Self((x * ($max as f64)) as $type) } + + /// Approximate the fraction `p/q` into a per-thing fraction. This will never overflow. + /// + /// The computation of this approximation is performed in the generic type `N`. Given + /// `M` as the data type that can hold the maximum value of this per-thing (e.g. u32 for + /// perbill), this can only work if `N == M` or `N: From + TryInto`. + pub fn from_rational_approximation(p: N, q: N) -> Self + where N: Clone + Ord + From<$type> + TryInto<$type> + ops::Div + { + // q cannot be zero. + let q = q.max((1 as $type).into()); + // p should not be bigger than q. + let p = p.min(q.clone()); + + let factor = (q.clone() / $max.into()).max((1 as $type).into()); + + // q cannot overflow: (q / (q/$max)) < 2 * $max. p < q hence p also cannot overflow. + // this implies that $type must be able to fit 2 * $max. + let q_reduce: $type = (q / factor.clone()) + .try_into() + .map_err(|_| "Failed to convert") + .expect( + "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ + does not satisfy this; qed" + ); + let p_reduce: $type = (p / factor.clone()) + .try_into() + .map_err(|_| "Failed to convert") + .expect( + "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ + does not satisfy this; qed" + ); + + // `p_reduced` and `q_reduced` are withing $type. Mul by another $max will always + // fit in $upper_type. This is guaranteed by the macro tests. + let part = + p_reduce as $upper_type + * <$upper_type>::from($max) + / q_reduce as $upper_type; + + $name(part as $type) + } + } + + impl Saturating for $name { + fn saturating_add(self, rhs: Self) -> Self { + // defensive-only: since `$max * 2 < $type::max_value()`, this can never overflow. + Self::from_parts(self.0.saturating_add(rhs.0)) + } + fn saturating_sub(self, rhs: Self) -> Self { + Self::from_parts(self.0.saturating_sub(rhs.0)) + } + fn saturating_mul(self, rhs: Self) -> Self { + let a = self.0 as $upper_type; + let b = rhs.0 as $upper_type; + let m = <$upper_type>::from($max); + let parts = a * b / m; + // This will always fit into $type. + Self::from_parts(parts as $type) + } + } + + impl ops::Div for $name { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + let p = self.0; + let q = rhs.0; + Self::from_rational_approximation(p, q) + } + } + + /// Overflow-prune multiplication. + /// + /// tailored to be used with a balance type. + impl ops::Mul for $name + where + N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem + + ops::Div + ops::Mul + ops::Add, + { + type Output = N; + fn mul(self, b: N) -> Self::Output { + let maximum: N = $max.into(); + let upper_max: $upper_type = $max.into(); + let part: N = self.0.into(); + + let rem_multiplied_divided = { + let rem = b.clone().rem(maximum.clone()); + + // `rem_sized` is inferior to $max, thus it fits into $type. This is assured by + // a test. + let rem_sized = rem.saturated_into::<$type>(); + + // `self` and `rem_sized` are inferior to $max, thus the product is less than + // $max^2 and fits into $upper_type. This is assured by a test. + let rem_multiplied_upper = rem_sized as $upper_type * self.0 as $upper_type; + + // `rem_multiplied_upper` is less than $max^2 therefore divided by $max it fits + // in $type. remember that $type always fits $max. + let mut rem_multiplied_divided_sized = + (rem_multiplied_upper / upper_max) as $type; + // fix a tiny rounding error + if rem_multiplied_upper % upper_max > upper_max / 2 { + rem_multiplied_divided_sized += 1; + } + + // `rem_multiplied_divided_sized` is inferior to b, thus it can be converted + // back to N type + rem_multiplied_divided_sized.into() + }; + + (b / maximum) * part + rem_multiplied_divided + } + } + + #[cfg(test)] + mod $test_mod { + use codec::{Encode, Decode}; + use super::{$name, Saturating, RuntimeDebug}; + use crate::traits::Zero; + + + #[test] + fn macro_expanded_correctly() { + // needed for the `from_percent` to work. + assert!($max >= 100); + assert!($max % 100 == 0); + + // needed for `from_rational_approximation` + assert!(2 * $max < <$type>::max_value()); + assert!(<$upper_type>::from($max) < <$upper_type>::max_value()); + + // for something like percent they can be the same. + assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value()); + assert!(<$upper_type>::from($max).checked_mul($max.into()).is_some()); + } + + #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)] + struct WithCompact { + data: T, + } + + #[test] + fn has_compact() { + let data = WithCompact { data: $name(1) }; + let encoded = data.encode(); + assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap()); + } + + #[test] + fn compact_encoding() { + let tests = [ + // assume all per_things have the size u8 at least. + (0 as $type, 1usize), + (1 as $type, 1usize), + (63, 1), + (64, 2), + (65, 2), + (<$type>::max_value(), <$type>::max_value().encode().len() + 1) + ]; + for &(n, l) in &tests { + let compact: codec::Compact<$name> = $name(n).into(); + let encoded = compact.encode(); + assert_eq!(encoded.len(), l); + let decoded = >::decode(&mut & encoded[..]) + .unwrap(); + let per_thingy: $name = decoded.into(); + assert_eq!(per_thingy, $name(n)); + } + } + + #[test] + fn per_thing_api_works() { + // some really basic stuff + assert_eq!($name::zero(), $name::from_parts(Zero::zero())); + assert_eq!($name::one(), $name::from_parts($max)); + assert_eq!($name::accuracy(), $max); + assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero())); + assert_eq!($name::from_percent(10), $name::from_parts($max / 10)); + assert_eq!($name::from_percent(100), $name::from_parts($max)); + } + + macro_rules! per_thing_mul_test { + ($num_type:tt) => { + // multiplication from all sort of from_percent + assert_eq!( + $name::from_percent(100) * $num_type::max_value(), + $num_type::max_value() + ); + assert_eq_error_rate!( + $name::from_percent(99) * $num_type::max_value(), + ((Into::::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type, + 1, + ); + assert_eq!( + $name::from_percent(50) * $num_type::max_value(), + $num_type::max_value() / 2, + ); + assert_eq_error_rate!( + $name::from_percent(1) * $num_type::max_value(), + $num_type::max_value() / 100, + 1, + ); + assert_eq!($name::from_percent(0) * $num_type::max_value(), 0); + + // // multiplication with bounds + assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value()); + assert_eq!($name::zero() * $num_type::max_value(), 0); + } + } + + #[test] + fn per_thing_mul_works() { + use primitive_types::U256; + + // accuracy test + assert_eq!($name::from_rational_approximation(1 as $type, 3) * 30 as $type, 10); + + $(per_thing_mul_test!($test_units);)* + } + + #[test] + fn per_thing_mul_rounds_to_nearest_number() { + assert_eq!($name::from_percent(33) * 10u64, 3); + assert_eq!($name::from_percent(34) * 10u64, 3); + assert_eq!($name::from_percent(35) * 10u64, 3); + assert_eq!($name::from_percent(36) * 10u64, 4); + assert_eq!($name::from_percent(36) * 10u64, 4); + } + + #[test] + fn per_thing_multiplication_with_large_number() { + use primitive_types::U256; + let max_minus_one = $max - 1; + assert_eq_error_rate!( + $name::from_parts(max_minus_one) * std::u128::MAX, + ((Into::::into(std::u128::MAX) * max_minus_one) / $max).as_u128(), + 1, + ); + } + + macro_rules! per_thing_from_rationale_approx_test { + ($num_type:tt) => { + // within accuracy boundary + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 0), + $name::one(), + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 1), + $name::one(), + ); + assert_eq_error_rate!( + $name::from_rational_approximation(1 as $num_type, 3).0, + $name::from_parts($max / 3).0, + 2 + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 10), + $name::from_percent(10), + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 4), + $name::from_percent(25), + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 4), + $name::from_rational_approximation(2 as $num_type, 8), + ); + // no accurate anymore but won't overflow. + assert_eq!( + $name::from_rational_approximation( + $num_type::max_value() - 1, + $num_type::max_value() + ), + $name::one(), + ); + assert_eq_error_rate!( + $name::from_rational_approximation( + $num_type::max_value() / 3, + $num_type::max_value() + ).0, + $name::from_parts($max / 3).0, + 2 + ); + assert_eq!( + $name::from_rational_approximation(1, $num_type::max_value()), + $name::zero(), + ); + }; + } + + #[test] + fn per_thing_from_rationale_approx_works() { + // This is just to make sure something like Percent which _might_ get built from a + // u8 does not overflow in the context of this test. + let max_value = <$upper_type>::from($max); + // almost at the edge + assert_eq!( + $name::from_rational_approximation($max - 1, $max + 1), + $name::from_parts($max - 2), + ); + assert_eq!( + $name::from_rational_approximation(1, $max-1), + $name::from_parts(1), + ); + assert_eq!( + $name::from_rational_approximation(1, $max), + $name::from_parts(1), + ); + assert_eq!( + $name::from_rational_approximation(2, 2 * $max - 1), + $name::from_parts(1), + ); + assert_eq!( + $name::from_rational_approximation(1, $max+1), + $name::zero(), + ); + assert_eq!( + $name::from_rational_approximation(3 * max_value / 2, 3 * max_value), + $name::from_percent(50), + ); + $(per_thing_from_rationale_approx_test!($test_units);)* + } + + #[test] + fn per_things_mul_operates_in_output_type() { + // assert_eq!($name::from_percent(50) * 100u32, 50u32); + assert_eq!($name::from_percent(50) * 100u64, 50u64); + assert_eq!($name::from_percent(50) * 100u128, 50u128); + } + + #[test] + fn per_thing_saturating_op_works() { + assert_eq!( + $name::from_percent(50).saturating_add($name::from_percent(40)), + $name::from_percent(90) + ); + assert_eq!( + $name::from_percent(50).saturating_add($name::from_percent(50)), + $name::from_percent(100) + ); + assert_eq!( + $name::from_percent(60).saturating_add($name::from_percent(50)), + $name::from_percent(100) + ); + + assert_eq!( + $name::from_percent(60).saturating_sub($name::from_percent(50)), + $name::from_percent(10) + ); + assert_eq!( + $name::from_percent(60).saturating_sub($name::from_percent(60)), + $name::from_percent(0) + ); + assert_eq!( + $name::from_percent(60).saturating_sub($name::from_percent(70)), + $name::from_percent(0) + ); + + assert_eq!( + $name::from_percent(50).saturating_mul($name::from_percent(50)), + $name::from_percent(25) + ); + assert_eq!( + $name::from_percent(20).saturating_mul($name::from_percent(20)), + $name::from_percent(4) + ); + assert_eq!( + $name::from_percent(10).saturating_mul($name::from_percent(10)), + $name::from_percent(1) + ); + } + + #[test] + fn per_thing_square_works() { + assert_eq!($name::from_percent(100).square(), $name::from_percent(100)); + assert_eq!($name::from_percent(50).square(), $name::from_percent(25)); + assert_eq!($name::from_percent(10).square(), $name::from_percent(1)); + assert_eq!( + $name::from_percent(2).square(), + $name::from_parts((4 * <$upper_type>::from($max) / 100 / 100) as $type) + ); + } + + #[test] + fn per_things_div_works() { + // normal + assert_eq!($name::from_percent(10) / $name::from_percent(20), + $name::from_percent(50) + ); + assert_eq!($name::from_percent(10) / $name::from_percent(10), + $name::from_percent(100) + ); + assert_eq!($name::from_percent(10) / $name::from_percent(0), + $name::from_percent(100) + ); + + // will not overflow + assert_eq!($name::from_percent(10) / $name::from_percent(5), + $name::from_percent(100) + ); + assert_eq!($name::from_percent(100) / $name::from_percent(50), + $name::from_percent(100) + ); + } + } + }; +} + +implement_per_thing!( + Percent, + test_per_cent, + [u32, u64, u128], + 100u8, + u8, + u16, + "_Percent_", +); +implement_per_thing!( + Permill, + test_permill, + [u32, u64, u128], + 1_000_000u32, + u32, + u64, + "_Parts per Million_", +); +implement_per_thing!( + Perbill, + test_perbill, + [u32, u64, u128], + 1_000_000_000u32, + u32, + u64, + "_Parts per Billion_", +); +implement_per_thing!( + Perquintill, + test_perquintill, + [u64, u128], + 1_000_000_000_000_000_000u64, + u64, + u128, + "_Parts per Quintillion_", +); diff --git a/core/sr-arithmetic/src/rational128.rs b/core/sr-arithmetic/src/rational128.rs new file mode 100644 index 0000000000000000000000000000000000000000..3247321199d6142e05fd8a11befcaad3e3e16186 --- /dev/null +++ b/core/sr-arithmetic/src/rational128.rs @@ -0,0 +1,384 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use rstd::{cmp::Ordering, prelude::*}; +use crate::helpers_128bit; +use num_traits::Zero; +use substrate_debug_derive::RuntimeDebug; + +/// A wrapper for any rational number with a 128 bit numerator and denominator. +#[derive(Clone, Copy, Default, Eq, RuntimeDebug)] +pub struct Rational128(u128, u128); + +impl Rational128 { + /// Nothing. + pub fn zero() -> Self { + Self(0, 1) + } + + /// If it is zero or not + pub fn is_zero(&self) -> bool { + self.0.is_zero() + } + + /// Build from a raw `n/d`. + pub fn from(n: u128, d: u128) -> Self { + Self(n, d.max(1)) + } + + /// Build from a raw `n/d`. This could lead to / 0 if not properly handled. + pub fn from_unchecked(n: u128, d: u128) -> Self { + Self(n, d) + } + + /// Return the numerator. + pub fn n(&self) -> u128 { + self.0 + } + + /// Return the denominator. + pub fn d(&self) -> u128 { + self.1 + } + + /// Convert `self` to a similar rational number where denominator is the given `den`. + // + /// This only returns if the result is accurate. `Err` is returned if the result cannot be + /// accurately calculated. + pub fn to_den(self, den: u128) -> Result { + if den == self.1 { + Ok(self) + } else { + helpers_128bit::multiply_by_rational(self.0, den, self.1).map(|n| Self(n, den)) + } + } + + /// Get the least common divisor of `self` and `other`. + /// + /// This only returns if the result is accurate. `Err` is returned if the result cannot be + /// accurately calculated. + pub fn lcm(&self, other: &Self) -> Result { + // this should be tested better: two large numbers that are almost the same. + if self.1 == other.1 { return Ok(self.1) } + let g = helpers_128bit::gcd(self.1, other.1); + helpers_128bit::multiply_by_rational(self.1 , other.1, g) + } + + /// A saturating add that assumes `self` and `other` have the same denominator. + pub fn lazy_saturating_add(self, other: Self) -> Self { + if other.is_zero() { + self + } else { + Self(self.0.saturating_add(other.0) ,self.1) + } + } + + /// A saturating subtraction that assumes `self` and `other` have the same denominator. + pub fn lazy_saturating_sub(self, other: Self) -> Self { + if other.is_zero() { + self + } else { + Self(self.0.saturating_sub(other.0) ,self.1) + } + } + + /// Addition. Simply tries to unify the denominators and add the numerators. + /// + /// Overflow might happen during any of the steps. Error is returned in such cases. + pub fn checked_add(self, other: Self) -> Result { + let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; + let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let n = self_scaled.0.checked_add(other_scaled.0) + .ok_or("overflow while adding numerators")?; + Ok(Self(n, self_scaled.1)) + } + + /// Subtraction. Simply tries to unify the denominators and subtract the numerators. + /// + /// Overflow might happen during any of the steps. None is returned in such cases. + pub fn checked_sub(self, other: Self) -> Result { + let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; + let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + + let n = self_scaled.0.checked_sub(other_scaled.0) + .ok_or("overflow while subtracting numerators")?; + Ok(Self(n, self_scaled.1)) + } +} + +impl PartialOrd for Rational128 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Rational128 { + fn cmp(&self, other: &Self) -> Ordering { + // handle some edge cases. + if self.1 == other.1 { + self.0.cmp(&other.0) + } else if self.1.is_zero() { + Ordering::Greater + } else if other.1.is_zero() { + Ordering::Less + } else { + // Don't even compute gcd. + let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); + let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); + self_n.cmp(&other_n) + } + } +} + +impl PartialEq for Rational128 { + fn eq(&self, other: &Self) -> bool { + // handle some edge cases. + if self.1 == other.1 { + self.0.eq(&other.0) + } else { + let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); + let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); + self_n.eq(&other_n) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::helpers_128bit::*; + + const MAX128: u128 = u128::max_value(); + const MAX64: u128 = u64::max_value() as u128; + const MAX64_2: u128 = 2 * u64::max_value() as u128; + + fn r(p: u128, q: u128) -> Rational128 { + Rational128(p, q) + } + + fn mul_div(a: u128, b: u128, c: u128) -> u128 { + use primitive_types::U256; + if a.is_zero() { return Zero::zero(); } + let c = c.max(1); + + // e for extended + let ae: U256 = a.into(); + let be: U256 = b.into(); + let ce: U256 = c.into(); + + let r = ae * be / ce; + if r > u128::max_value().into() { + a + } else { + r.as_u128() + } + } + + #[test] + fn truth_value_function_works() { + assert_eq!( + mul_div(2u128.pow(100), 8, 4), + 2u128.pow(101) + ); + assert_eq!( + mul_div(2u128.pow(100), 4, 8), + 2u128.pow(99) + ); + + // and it returns a if result cannot fit + assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10); + } + + #[test] + fn to_denom_works() { + // simple up and down + assert_eq!(r(1, 5).to_den(10), Ok(r(2, 10))); + assert_eq!(r(4, 10).to_den(5), Ok(r(2, 5))); + + // up and down with large numbers + assert_eq!(r(MAX128 - 10, MAX128).to_den(10), Ok(r(10, 10))); + assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10))); + + // large to perbill. This is very well needed for phragmen. + assert_eq!( + r(MAX128 / 2, MAX128).to_den(1000_000_000), + Ok(r(500_000_000, 1000_000_000)) + ); + + // large to large + assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128/2), Ok(r(MAX128/4, MAX128/2))); + } + + #[test] + fn gdc_works() { + assert_eq!(gcd(10, 5), 5); + assert_eq!(gcd(7, 22), 1); + } + + #[test] + fn lcm_works() { + // simple stuff + assert_eq!(r(3, 10).lcm(&r(4, 15)).unwrap(), 30); + assert_eq!(r(5, 30).lcm(&r(1, 7)).unwrap(), 210); + assert_eq!(r(5, 30).lcm(&r(1, 10)).unwrap(), 30); + + // large numbers + assert_eq!( + r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128-1)), + Err("result cannot fit in u128"), + ); + assert_eq!( + r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64-1)), + Ok(340282366920938463408034375210639556610), + ); + assert!(340282366920938463408034375210639556610 < MAX128); + assert!(340282366920938463408034375210639556610 == MAX64 * (MAX64 - 1)); + } + + #[test] + fn add_works() { + // works + assert_eq!(r(3, 10).checked_add(r(1, 10)).unwrap(), r(2, 5)); + assert_eq!(r(3, 10).checked_add(r(3, 7)).unwrap(), r(51, 70)); + + // errors + assert_eq!( + r(1, MAX128).checked_add(r(1, MAX128-1)), + Err("failed to scale to denominator"), + ); + assert_eq!( + r(7, MAX128).checked_add(r(MAX128, MAX128)), + Err("overflow while adding numerators"), + ); + assert_eq!( + r(MAX128, MAX128).checked_add(r(MAX128, MAX128)), + Err("overflow while adding numerators"), + ); + } + + #[test] + fn sub_works() { + // works + assert_eq!(r(3, 10).checked_sub(r(1, 10)).unwrap(), r(1, 5)); + assert_eq!(r(6, 10).checked_sub(r(3, 7)).unwrap(), r(12, 70)); + + // errors + assert_eq!( + r(2, MAX128).checked_sub(r(1, MAX128-1)), + Err("failed to scale to denominator"), + ); + assert_eq!( + r(7, MAX128).checked_sub(r(MAX128, MAX128)), + Err("overflow while subtracting numerators"), + ); + assert_eq!( + r(1, 10).checked_sub(r(2,10)), + Err("overflow while subtracting numerators"), + ); + } + + #[test] + fn ordering_and_eq_works() { + assert!(r(1, 2) > r(1, 3)); + assert!(r(1, 2) > r(2, 6)); + + assert!(r(1, 2) < r(6, 6)); + assert!(r(2, 1) > r(2, 6)); + + assert!(r(5, 10) == r(1, 2)); + assert!(r(1, 2) == r(1, 2)); + + assert!(r(1, 1490000000000200000) > r(1, 1490000000000200001)); + } + + #[test] + fn multiply_by_rational_works() { + assert_eq!(multiply_by_rational(7, 2, 3).unwrap(), 7 * 2 / 3); + assert_eq!(multiply_by_rational(7, 20, 30).unwrap(), 7 * 2 / 3); + assert_eq!(multiply_by_rational(20, 7, 30).unwrap(), 7 * 2 / 3); + + assert_eq!( + // MAX128 % 3 == 0 + multiply_by_rational(MAX128, 2, 3).unwrap(), + MAX128 / 3 * 2, + ); + assert_eq!( + // MAX128 % 7 == 3 + multiply_by_rational(MAX128, 5, 7).unwrap(), + (MAX128 / 7 * 5) + (3 * 5 / 7), + ); + assert_eq!( + // MAX128 % 7 == 3 + multiply_by_rational(MAX128, 11 , 13).unwrap(), + (MAX128 / 13 * 11) + (8 * 11 / 13), + ); + assert_eq!( + // MAX128 % 1000 == 455 + multiply_by_rational(MAX128, 555, 1000).unwrap(), + (MAX128 / 1000 * 555) + (455 * 555 / 1000), + ); + + assert_eq!( + multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(), + 2 * MAX64 - 1, + ); + assert_eq!( + multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(), + 2 * MAX64 - 3, + ); + + assert_eq!( + multiply_by_rational(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(), + (MAX64 + 100) * 2, + ); + assert_eq!( + multiply_by_rational(MAX64 + 100, MAX64_2 / 100, MAX64_2 / 200).unwrap(), + (MAX64 + 100) * 2, + ); + + assert_eq!( + multiply_by_rational(2u128.pow(66) - 1, 2u128.pow(65) - 1, 2u128.pow(65)).unwrap(), + 73786976294838206461, + ); + assert_eq!( + multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), + 250000000, + ); + } + + #[test] + fn multiply_by_rational_a_b_are_interchangeable() { + assert_eq!( + multiply_by_rational(10, MAX128, MAX128 / 2), + Ok(20), + ); + assert_eq!( + multiply_by_rational(MAX128, 10, MAX128 / 2), + Ok(20), + ); + } + + #[test] + #[ignore] + fn multiply_by_rational_fuzzed_equation() { + assert_eq!( + multiply_by_rational(154742576605164960401588224, 9223376310179529214, 549756068598), + Ok(2596149632101417846585204209223679) + ); + } +} diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs new file mode 100644 index 0000000000000000000000000000000000000000..d02425066ff9d7f8e34efe6e73b94262ba197b64 --- /dev/null +++ b/core/sr-arithmetic/src/traits.rs @@ -0,0 +1,143 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for the runtime modules. + +use rstd::{self, convert::{TryFrom, TryInto}}; +use codec::HasCompact; +pub use integer_sqrt::IntegerSquareRoot; +pub use num_traits::{ + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, + CheckedShl, CheckedShr +}; +use rstd::ops::{ + Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, + RemAssign, Shl, Shr +}; + +/// A meta trait for arithmetic. +/// +/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to +/// be able to represent at least `u32` values without loss, hence the trait implies `From` +/// and smaller ints. All other conversions are fallible. +pub trait SimpleArithmetic: + Zero + One + IntegerSquareRoot + + From + From + From + TryInto + TryInto + TryInto + + TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + + UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + + UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + Shl + Shr + + CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + + Saturating + PartialOrd + Ord + Bounded + + HasCompact + Sized +{} +impl + From + From + TryInto + TryInto + TryInto + + TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + + UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + + UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + Shl + Shr + + CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + + Saturating + PartialOrd + Ord + Bounded + + HasCompact + Sized +> SimpleArithmetic for T {} + +/// Just like `From` except that if the source value is too big to fit into the destination type +/// then it'll saturate the destination. +pub trait UniqueSaturatedFrom: Sized { + /// Convert from a value of `T` into an equivalent instance of `Self`. + fn unique_saturated_from(t: T) -> Self; +} + +/// Just like `Into` except that if the source value is too big to fit into the destination type +/// then it'll saturate the destination. +pub trait UniqueSaturatedInto: Sized { + /// Consume self to return an equivalent value of `T`. + fn unique_saturated_into(self) -> T; +} + +impl + Bounded + Sized> UniqueSaturatedFrom for S { + fn unique_saturated_from(t: T) -> Self { + S::try_from(t).unwrap_or_else(|_| Bounded::max_value()) + } +} + +impl + Sized> UniqueSaturatedInto for S { + fn unique_saturated_into(self) -> T { + self.try_into().unwrap_or_else(|_| Bounded::max_value()) + } +} + +/// Simple trait to use checked mul and max value to give a saturated mul operation over +/// supported types. +pub trait Saturating { + /// Saturated addition - if the product can't fit in the type then just use max-value. + fn saturating_add(self, o: Self) -> Self; + + /// Saturated subtraction - if the product can't fit in the type then just use max-value. + fn saturating_sub(self, o: Self) -> Self; + + /// Saturated multiply - if the product can't fit in the type then just use max-value. + fn saturating_mul(self, o: Self) -> Self; +} + +impl Saturating for T { + fn saturating_add(self, o: Self) -> Self { + ::saturating_add(self, o) + } + fn saturating_sub(self, o: Self) -> Self { + ::saturating_sub(self, o) + } + fn saturating_mul(self, o: Self) -> Self { + self.checked_mul(&o).unwrap_or_else(Bounded::max_value) + } +} + +/// Convenience type to work around the highly unergonomic syntax needed +/// to invoke the functions of overloaded generic traits, in this case +/// `SaturatedFrom` and `SaturatedInto`. +pub trait SaturatedConversion { + /// Convert from a value of `T` into an equivalent instance of `Self`. + /// + /// This just uses `UniqueSaturatedFrom` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn saturated_from(t: T) -> Self where Self: UniqueSaturatedFrom { + >::unique_saturated_from(t) + } + + /// Consume self to return an equivalent value of `T`. + /// + /// This just uses `UniqueSaturatedInto` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn saturated_into(self) -> T where Self: UniqueSaturatedInto { + >::unique_saturated_into(self) + } +} +impl SaturatedConversion for T {} diff --git a/core/sr-io/Cargo.toml b/core/sr-io/Cargo.toml index 0e6fba5bd73d2c960244c30e9da5e07b5c50dc9e..4d140d289dafe3d1033243f59f7fcc09bd8e5fe2 100644 --- a/core/sr-io/Cargo.toml +++ b/core/sr-io/Cargo.toml @@ -6,21 +6,19 @@ build = "build.rs" edition = "2018" [build-dependencies] -rustc_version = "0.2" +rustc_version = "0.2.3" [dependencies] -rstd = { package = "sr-std", path = "../sr-std", default-features = false } -primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -hash-db = { version = "0.15.0", default-features = false } -libsecp256k1 = { version = "0.2.1", optional = true } -tiny-keccak = { version = "1.4.2", optional = true } -environmental = { version = "1.0.1", optional = true } +hash-db = { version = "0.15.2", default-features = false } +primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +libsecp256k1 = { version = "0.3.0", optional = true } +tiny-keccak = { version = "1.5.0", optional = true } substrate-state-machine = { path = "../state-machine", optional = true } trie = { package = "substrate-trie", path = "../trie", optional = true } - -[dev-dependencies] -substrate-offchain = { path = "../offchain" } +externalities = { package = "substrate-externalities", path = "../externalities", optional = true } +log = { version = "0.4.8", optional = true } [features] default = ["std"] @@ -30,13 +28,18 @@ std = [ "rstd/std", "hash-db/std", "trie", - "environmental", "substrate-state-machine", "libsecp256k1", - "tiny-keccak" + "tiny-keccak", + "externalities", + "log", ] nightly = [] strict = [] -wasm-nice-panic-message = [] + +# These two features are used for `no_std` builds for the environments which already provides +# `#[panic_handler]` and `#[alloc_error_handler]`. +# +# For the regular wasm runtime builds those are not used. no_panic_handler = [] no_oom = [] diff --git a/core/sr-io/src/lib.rs b/core/sr-io/src/lib.rs index 91b27efba03045cd24054998ac8cd07832c66462..fe5e50b3eda3e8defce026001755e199dcea1b53 100644 --- a/core/sr-io/src/lib.rs +++ b/core/sr-io/src/lib.rs @@ -26,18 +26,14 @@ #![cfg_attr(feature = "std", doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] -use hash_db::Hasher; use rstd::vec::Vec; -#[doc(hidden)] -pub use codec; - -pub use primitives::Blake2Hasher; use primitives::{ - crypto::KeyTypeId, ed25519, sr25519, + crypto::KeyTypeId, ed25519, sr25519, H256, offchain::{ Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, }, + LogLevel, }; /// Error verifying ECDSA signature @@ -50,14 +46,6 @@ pub enum EcdsaVerifyError { BadSignature, } -pub mod offchain; - -/// Trait for things which can be printed. -pub trait Printable { - /// Print the object. - fn print(self); -} - /// Converts a public trait definition into a private trait and set of public functions /// that assume the trait is implemented for `()` for ease of calling. macro_rules! export_api { @@ -67,7 +55,6 @@ macro_rules! export_api { $( $( #[$attr:meta] )* fn $name:ident - $(< $( $g_name:ident $( : $g_ty:path )? ),+ >)? ( $( $arg:ident : $arg_ty:ty ),* $(,)? ) $( -> $ret:ty )? $( where $( $w_name:path : $w_ty:path ),+ )?; @@ -78,18 +65,18 @@ macro_rules! export_api { pub(crate) trait $trait_name { $( $( #[$attr] )* - fn $name $(< $( $g_name $( : $g_ty )? ),+ >)? ( $($arg : $arg_ty ),* ) $( -> $ret )? + fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )? $( where $( $w_name : $w_ty ),+ )?; )* } $( $( #[$attr] )* - pub fn $name $(< $( $g_name $( : $g_ty )? ),+ >)? ( $($arg : $arg_ty ),* ) $( -> $ret )? + pub fn $name ( $($arg : $arg_ty ),* ) $( -> $ret )? $( where $( $w_name : $w_ty ),+ )? { #[allow(deprecated)] - <()>:: $name $(::< $( $g_name ),+ > )? ( $( $arg ),* ) + <()>:: $name ( $( $arg ),* ) } )* } @@ -154,26 +141,10 @@ export_api! { fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]>; /// A trie root formed from the iterated items. - fn trie_root(input: I) -> H::Out - where - I: IntoIterator, - A: AsRef<[u8]>, - A: Ord, - B: AsRef<[u8]>, - H: Hasher, - H: self::imp::HasherBounds, - H::Out: Ord - ; + fn blake2_256_trie_root(input: Vec<(Vec, Vec)>) -> H256; /// A trie root formed from the enumerated items. - fn ordered_trie_root(input: I) -> H::Out - where - I: IntoIterator, - A: AsRef<[u8]>, - H: Hasher, - H: self::imp::HasherBounds, - H::Out: Ord - ; + fn blake2_256_ordered_trie_root(input: Vec>) -> H256; } } @@ -182,12 +153,26 @@ export_api! { /// The current relay chain identifier. fn chain_id() -> u64; - /// Print a printable value. - fn print(value: T) - where - T: Printable, - T: Sized - ; + /// Print a number. + fn print_num(val: u64); + /// Print any valid `utf8` buffer. + fn print_utf8(utf8: &[u8]); + /// Print any `u8` slice as hex. + fn print_hex(data: &[u8]); + + /// Request to print a log message (stderr) on the host. + /// + /// Note that this will be only displayed if the host + /// is enabed to display log messages with given + /// level and target. + /// + /// Instead of using directly, prefer setting up `RuntimeLogger` + /// and using `log` macros. + fn log( + level: LogLevel, + target: &[u8], + message: &[u8] + ); } } @@ -203,10 +188,10 @@ export_api! { /// key type in the keystore. /// /// Returns the raw signature. - fn ed25519_sign>( + fn ed25519_sign( id: KeyTypeId, pubkey: &ed25519::Public, - msg: &M, + msg: &[u8], ) -> Option; /// Verify an ed25519 signature. /// @@ -223,10 +208,10 @@ export_api! { /// key type in the keystore. /// /// Returns the raw signature. - fn sr25519_sign>( + fn sr25519_sign( id: KeyTypeId, pubkey: &sr25519::Public, - msg: &M, + msg: &[u8], ) -> Option; /// Verify an sr25519 signature. /// @@ -235,15 +220,20 @@ export_api! { /// Verify and recover a SECP256k1 ECDSA signature. /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. - /// - returns `Err` if the signature is bad, otherwise the 64-byte pubkey (doesn't include the 0x04 prefix). + /// - returns `Err` if the signature is bad, otherwise the 64-byte raw pubkey (doesn't include the 0x04 prefix). fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError>; + + /// Verify and recover a SECP256k1 ECDSA signature. + /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. + /// - returns `Err` if the signature is bad, otherwise the 33-byte compressed pubkey. + fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError>; } } export_api! { pub(crate) trait HashingApi { /// Conduct a 256-bit Keccak hash. - fn keccak_256(data: &[u8]) -> [u8; 32] ; + fn keccak_256(data: &[u8]) -> [u8; 32]; /// Conduct a 128-bit Blake2 hash. fn blake2_128(data: &[u8]) -> [u8; 16]; @@ -269,10 +259,11 @@ export_api! { /// Even if this function returns `true`, it does not mean that any keys are configured /// and that the validator is registered in the chain. fn is_validator() -> bool; + /// Submit transaction to the pool. /// /// The transaction will end up in the pool. - fn submit_transaction(data: &T) -> Result<(), ()>; + fn submit_transaction(data: Vec) -> Result<(), ()>; /// Returns information about the local node's network state. fn network_state() -> Result; @@ -308,7 +299,7 @@ export_api! { kind: StorageKind, key: &[u8], old_value: Option<&[u8]>, - new_value: &[u8] + new_value: &[u8], ) -> bool; /// Gets a value from the local storage. @@ -325,14 +316,14 @@ export_api! { fn http_request_start( method: &str, uri: &str, - meta: &[u8] + meta: &[u8], ) -> Result; /// Append header to the request. fn http_request_add_header( request_id: HttpRequestId, name: &str, - value: &str + value: &str, ) -> Result<(), ()>; /// Write a chunk of request body. @@ -344,7 +335,7 @@ export_api! { fn http_request_write_body( request_id: HttpRequestId, chunk: &[u8], - deadline: Option + deadline: Option, ) -> Result<(), HttpError>; /// Block and wait for the responses for given requests. @@ -356,16 +347,14 @@ export_api! { /// Passing `None` as deadline blocks forever. fn http_response_wait( ids: &[HttpRequestId], - deadline: Option + deadline: Option, ) -> Vec; /// Read all response headers. /// /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. /// NOTE response headers have to be read before response body. - fn http_response_headers( - request_id: HttpRequestId - ) -> Vec<(Vec, Vec)>; + fn http_response_headers(request_id: HttpRequestId) -> Vec<(Vec, Vec)>; /// Read a chunk of body response to given buffer. /// @@ -378,7 +367,7 @@ export_api! { fn http_response_read_body( request_id: HttpRequestId, buffer: &mut [u8], - deadline: Option + deadline: Option, ) -> Result; } } @@ -399,13 +388,10 @@ mod imp { } #[cfg(feature = "std")] -pub use self::imp::{ - StorageOverlay, ChildrenStorageOverlay, with_storage, - with_externalities -}; +pub use self::imp::{StorageOverlay, ChildrenStorageOverlay, with_storage}; #[cfg(not(feature = "std"))] pub use self::imp::ext::*; /// Type alias for Externalities implementation used in tests. #[cfg(feature = "std")] -pub type TestExternalities = self::imp::TestExternalities; +pub type TestExternalities = self::imp::TestExternalities; diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs index 167011608fd34c78d73254e8001ab7d7a89cbc84..7e0504c37aafcbce5f62f45666374bdae82703d5 100644 --- a/core/sr-io/with_std.rs +++ b/core/sr-io/with_std.rs @@ -15,21 +15,19 @@ // along with Substrate. If not, see . use primitives::{ - blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair, + blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair, H256, + traits::KeystoreExt, storage::ChildStorageKey, hexdisplay::HexDisplay, Hasher, + offchain::{self, OffchainExt}, }; // Switch to this after PoC-3 // pub use primitives::BlakeHasher; -pub use substrate_state_machine::{ - Externalities, BasicExternalities, TestExternalities, ChildStorageKey, -}; +pub use substrate_state_machine::{BasicExternalities, TestExternalities}; -use environmental::environmental; -use primitives::{offchain, hexdisplay::HexDisplay, H256}; use trie::{TrieConfiguration, trie_types::Layout}; use std::{collections::HashMap, convert::TryFrom}; -environmental!(ext: trait Externalities); +use externalities::{with_externalities, set_and_run_with_externalities, ExternalitiesExt}; /// Additional bounds for `Hasher` trait for with_std. pub trait HasherBounds {} @@ -40,7 +38,7 @@ impl HasherBounds for T {} /// /// Panicking here is aligned with what the `without_std` environment would do /// in the case of an invalid child storage key. -fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { +fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { match ChildStorageKey::from_slice(storage_key) { Some(storage_key) => storage_key, None => panic!("child storage key is invalid"), @@ -49,21 +47,21 @@ fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey Option> { - ext::with(|ext| ext.storage(key).map(|s| s.to_vec())) + with_externalities(|ext| ext.storage(key).map(|s| s.to_vec())) .expect("storage cannot be called outside of an Externalities-provided environment.") } fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> Option { - ext::with(|ext| ext.storage(key).map(|value| { - let value = &value[value_offset..]; - let written = std::cmp::min(value.len(), value_out.len()); - value_out[..written].copy_from_slice(&value[..written]); + with_externalities(|ext| ext.storage(key).map(|value| { + let data = &value[value_offset.min(value.len())..]; + let written = std::cmp::min(data.len(), value_out.len()); + value_out[..written].copy_from_slice(&data[..written]); value.len() })).expect("read_storage cannot be called outside of an Externalities-provided environment.") } fn child_storage(storage_key: &[u8], key: &[u8]) -> Option> { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.child_storage(storage_key, key).map(|s| s.to_vec()) }) @@ -71,7 +69,7 @@ impl StorageApi for () { } fn set_storage(key: &[u8], value: &[u8]) { - ext::with(|ext| + with_externalities(|ext| ext.set_storage(key.to_vec(), value.to_vec()) ); } @@ -82,13 +80,13 @@ impl StorageApi for () { value_out: &mut [u8], value_offset: usize, ) -> Option { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.child_storage(storage_key, key) .map(|value| { - let value = &value[value_offset..]; - let written = std::cmp::min(value.len(), value_out.len()); - value_out[..written].copy_from_slice(&value[..written]); + let data = &value[value_offset.min(value.len())..]; + let written = std::cmp::min(data.len(), value_out.len()); + value_out[..written].copy_from_slice(&data[..written]); value.len() }) }) @@ -96,124 +94,135 @@ impl StorageApi for () { } fn set_child_storage(storage_key: &[u8], key: &[u8], value: &[u8]) { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.set_child_storage(storage_key, key.to_vec(), value.to_vec()) }); } fn clear_storage(key: &[u8]) { - ext::with(|ext| + with_externalities(|ext| ext.clear_storage(key) ); } fn clear_child_storage(storage_key: &[u8], key: &[u8]) { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.clear_child_storage(storage_key, key) }); } fn kill_child_storage(storage_key: &[u8]) { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.kill_child_storage(storage_key) }); } fn exists_storage(key: &[u8]) -> bool { - ext::with(|ext| + with_externalities(|ext| ext.exists_storage(key) ).unwrap_or(false) } fn exists_child_storage(storage_key: &[u8], key: &[u8]) -> bool { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.exists_child_storage(storage_key, key) }).unwrap_or(false) } fn clear_prefix(prefix: &[u8]) { - ext::with(|ext| - ext.clear_prefix(prefix) - ); + with_externalities(|ext| ext.clear_prefix(prefix)); } fn clear_child_prefix(storage_key: &[u8], prefix: &[u8]) { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.clear_child_prefix(storage_key, prefix) }); } fn storage_root() -> [u8; 32] { - ext::with(|ext| + with_externalities(|ext| ext.storage_root() ).unwrap_or(H256::zero()).into() } fn child_storage_root(storage_key: &[u8]) -> Vec { - ext::with(|ext| { + with_externalities(|ext| { let storage_key = child_storage_key_or_panic(storage_key); ext.child_storage_root(storage_key) }).expect("child_storage_root cannot be called outside of an Externalities-provided environment.") } fn storage_changes_root(parent_hash: [u8; 32]) -> Option<[u8; 32]> { - ext::with(|ext| + with_externalities(|ext| ext.storage_changes_root(parent_hash.into()).map(|h| h.map(|h| h.into())) ).unwrap_or(Ok(None)).expect("Invalid parent hash passed to storage_changes_root") } - fn trie_root(input: I) -> H::Out - where - I: IntoIterator, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, - H: Hasher, - H::Out: Ord, - { - Layout::::trie_root(input) + fn blake2_256_trie_root(input: Vec<(Vec, Vec)>) -> H256 { + Layout::::trie_root(input) } - fn ordered_trie_root(input: I) -> H::Out - where - I: IntoIterator, - A: AsRef<[u8]>, - H: Hasher, - H::Out: Ord, - { - Layout::::ordered_trie_root(input) + fn blake2_256_ordered_trie_root(input: Vec>) -> H256 { + Layout::::ordered_trie_root(input) } } impl OtherApi for () { fn chain_id() -> u64 { - ext::with(|ext| + with_externalities(|ext| ext.chain_id() ).unwrap_or(0) } - fn print(value: T) { - value.print() + fn print_num(val: u64) { + log::debug!(target: "runtime", "{}", val); + } + + fn print_utf8(utf8: &[u8]) { + if let Ok(data) = std::str::from_utf8(utf8) { + log::debug!(target: "runtime", "{}", data) + } + } + + fn print_hex(data: &[u8]) { + log::debug!(target: "runtime", "{}", HexDisplay::from(&data)); + } + + fn log( + level: LogLevel, + target: &[u8], + message: &[u8], + ) { + let target = std::str::from_utf8(target).unwrap_or("invalid utf8"); + let msg = std::str::from_utf8(message).unwrap_or("invalid utf8"); + + log::log!( + target: target, + log::Level::from(level), + "{}", + msg, + ) } } impl CryptoApi for () { fn ed25519_public_keys(id: KeyTypeId) -> Vec { - ext::with(|ext| { - ext.keystore() + with_externalities(|ext| { + ext.extension::() .expect("No `keystore` associated for the current context!") - .write() + .read() .ed25519_public_keys(id) }).expect("`ed25519_public_keys` cannot be called outside of an Externalities-provided environment.") } fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public { - ext::with(|ext| { - ext.keystore() + with_externalities(|ext| { + ext.extension::() .expect("No `keystore` associated for the current context!") .write() .ed25519_generate_new(id, seed) @@ -221,19 +230,19 @@ impl CryptoApi for () { }).expect("`ed25519_generate` cannot be called outside of an Externalities-provided environment.") } - fn ed25519_sign>( + fn ed25519_sign( id: KeyTypeId, pubkey: &ed25519::Public, - msg: &M, + msg: &[u8], ) -> Option { let pub_key = ed25519::Public::try_from(pubkey.as_ref()).ok()?; - ext::with(|ext| { - ext.keystore() + with_externalities(|ext| { + ext.extension::() .expect("No `keystore` associated for the current context!") .read() .ed25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg.as_ref()).into()) + .map(|k| k.sign(msg)) }).expect("`ed25519_sign` cannot be called outside of an Externalities-provided environment.") } @@ -242,17 +251,17 @@ impl CryptoApi for () { } fn sr25519_public_keys(id: KeyTypeId) -> Vec { - ext::with(|ext| { - ext.keystore() + with_externalities(|ext| { + ext.extension::() .expect("No `keystore` associated for the current context!") - .write() + .read() .sr25519_public_keys(id) }).expect("`sr25519_public_keys` cannot be called outside of an Externalities-provided environment.") } fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public { - ext::with(|ext| { - ext.keystore() + with_externalities(|ext| { + ext.extension::() .expect("No `keystore` associated for the current context!") .write() .sr25519_generate_new(id, seed) @@ -260,19 +269,19 @@ impl CryptoApi for () { }).expect("`sr25519_generate` cannot be called outside of an Externalities-provided environment.") } - fn sr25519_sign>( + fn sr25519_sign( id: KeyTypeId, pubkey: &sr25519::Public, - msg: &M, + msg: &[u8], ) -> Option { let pub_key = sr25519::Public::try_from(pubkey.as_ref()).ok()?; - ext::with(|ext| { - ext.keystore() + with_externalities(|ext| { + ext.extension::() .expect("No `keystore` associated for the current context!") .read() .sr25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg.as_ref()).into()) + .map(|k| k.sign(msg)) }).expect("`sr25519_sign` cannot be called outside of an Externalities-provided environment.") } @@ -291,6 +300,16 @@ impl CryptoApi for () { res.copy_from_slice(&pubkey.serialize()[1..65]); Ok(res) } + + fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError> { + let rs = secp256k1::Signature::parse_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + Ok(pubkey.serialize_compressed()) + } } impl HashingApi for () { @@ -320,9 +339,9 @@ impl HashingApi for () { } fn with_offchain(f: impl FnOnce(&mut dyn offchain::Externalities) -> R, msg: &'static str) -> R { - ext::with(|ext| ext - .offchain() - .map(|ext| f(ext)) + with_externalities(|ext| ext + .extension::() + .map(|ext| f(&mut **ext)) .expect(msg) ).expect("offchain-worker functions cannot be called outside of an Externalities-provided environment.") } @@ -334,9 +353,9 @@ impl OffchainApi for () { }, "is_validator can be called only in the offchain worker context") } - fn submit_transaction(data: &T) -> Result<(), ()> { + fn submit_transaction(data: Vec) -> Result<(), ()> { with_offchain(|ext| { - ext.submit_transaction(codec::Encode::encode(data)) + ext.submit_transaction(data) }, "submit_transaction can be called only in the offchain worker context") } @@ -390,7 +409,7 @@ impl OffchainApi for () { fn http_request_start( method: &str, uri: &str, - meta: &[u8] + meta: &[u8], ) -> Result { with_offchain(|ext| { ext.http_request_start(method, uri, meta) @@ -400,7 +419,7 @@ impl OffchainApi for () { fn http_request_add_header( request_id: offchain::HttpRequestId, name: &str, - value: &str + value: &str, ) -> Result<(), ()> { with_offchain(|ext| { ext.http_request_add_header(request_id, name, value) @@ -410,7 +429,7 @@ impl OffchainApi for () { fn http_request_write_body( request_id: offchain::HttpRequestId, chunk: &[u8], - deadline: Option + deadline: Option, ) -> Result<(), offchain::HttpError> { with_offchain(|ext| { ext.http_request_write_body(request_id, chunk, deadline) @@ -419,7 +438,7 @@ impl OffchainApi for () { fn http_response_wait( ids: &[offchain::HttpRequestId], - deadline: Option + deadline: Option, ) -> Vec { with_offchain(|ext| { ext.http_response_wait(ids, deadline) @@ -427,7 +446,7 @@ impl OffchainApi for () { } fn http_response_headers( - request_id: offchain::HttpRequestId + request_id: offchain::HttpRequestId, ) -> Vec<(Vec, Vec)> { with_offchain(|ext| { ext.http_response_headers(request_id) @@ -437,7 +456,7 @@ impl OffchainApi for () { fn http_response_read_body( request_id: offchain::HttpRequestId, buffer: &mut [u8], - deadline: Option + deadline: Option, ) -> Result { with_offchain(|ext| { ext.http_response_read_body(request_id, buffer, deadline) @@ -447,13 +466,6 @@ impl OffchainApi for () { impl Api for () {} -/// Execute the given closure with global function available whose functionality routes into the -/// externalities `ext`. Forwards the value that the closure returns. -// NOTE: need a concrete hasher here due to limitations of the `environmental!` macro, otherwise a type param would have been fine I think. -pub fn with_externalities R>(ext: &mut dyn Externalities, f: F) -> R { - ext::using(ext, f) -} - /// A set of key value pairs for storage. pub type StorageOverlay = HashMap, Vec>; @@ -471,31 +483,13 @@ pub fn with_storage R>( rstd::mem::swap(&mut alt_storage, storage); let mut ext = BasicExternalities::new(alt_storage.0, alt_storage.1); - let r = ext::using(&mut ext, f); + let r = set_and_run_with_externalities(&mut ext, f); *storage = ext.into_storages(); r } -impl<'a> Printable for &'a [u8] { - fn print(self) { - println!("Runtime: {}", HexDisplay::from(&self)); - } -} - -impl<'a> Printable for &'a str { - fn print(self) { - println!("Runtime: {}", self); - } -} - -impl Printable for u64 { - fn print(self) { - println!("Runtime: {}", self); - } -} - #[cfg(test)] mod std_tests { use super::*; @@ -504,7 +498,7 @@ mod std_tests { #[test] fn storage_works() { let mut t = BasicExternalities::default(); - assert!(with_externalities(&mut t, || { + assert!(set_and_run_with_externalities(&mut t, || { assert_eq!(storage(b"hello"), None); set_storage(b"hello", b"world"); assert_eq!(storage(b"hello"), Some(b"world".to_vec())); @@ -515,7 +509,7 @@ mod std_tests { t = BasicExternalities::new(map![b"foo".to_vec() => b"bar".to_vec()], map![]); - assert!(!with_externalities(&mut t, || { + assert!(!set_and_run_with_externalities(&mut t, || { assert_eq!(storage(b"hello"), None); assert_eq!(storage(b"foo"), Some(b"bar".to_vec())); false @@ -528,7 +522,7 @@ mod std_tests { b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec() ], map![]); - with_externalities(&mut t, || { + set_and_run_with_externalities(&mut t, || { let mut v = [0u8; 4]; assert!(read_storage(b":test", &mut v[..], 0).unwrap() >= 4); assert_eq!(v, [11u8, 0, 0, 0]); @@ -547,7 +541,7 @@ mod std_tests { b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() ], map![]); - with_externalities(&mut t, || { + set_and_run_with_externalities(&mut t, || { clear_prefix(b":abc"); assert!(storage(b":a").is_some()); diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs index 954eccc9cfafd6ccb7f46f2e0c454c4277f56c1f..c3f7d62031b931dba928f240015f1a9475e8fdc3 100644 --- a/core/sr-io/without_std.rs +++ b/core/sr-io/without_std.rs @@ -20,7 +20,7 @@ pub use rstd::{mem, slice}; use core::{intrinsics, panic::PanicInfo}; use rstd::{vec::Vec, cell::Cell, convert::TryInto}; -use primitives::{offchain, Blake2Hasher}; +use primitives::offchain; use codec::Decode; #[cfg(not(feature = "no_panic_handler"))] @@ -28,26 +28,15 @@ use codec::Decode; #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { unsafe { - #[cfg(feature = "wasm-nice-panic-message")] - { - let message = rstd::alloc::format!("{}", info); - extern_functions_host_impl::ext_print_utf8(message.as_ptr() as *const u8, message.len() as u32); - } - #[cfg(not(feature = "wasm-nice-panic-message"))] - { - if let Some(loc) = info.location() { - extern_functions_host_impl::ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32); - extern_functions_host_impl::ext_print_num(loc.line() as u64); - extern_functions_host_impl::ext_print_num(loc.column() as u64); - } - } + let message = rstd::alloc::format!("{}", info); + extern_functions_host_impl::ext_print_utf8(message.as_ptr() as *const u8, message.len() as u32); intrinsics::abort() } } #[cfg(not(feature = "no_oom"))] #[alloc_error_handler] -pub extern fn oom(_: ::core::alloc::Layout) -> ! { +pub extern fn oom(_: core::alloc::Layout) -> ! { static OOM_MSG: &str = "Runtime memory exhausted. Aborting"; unsafe { @@ -126,44 +115,6 @@ pub mod ext { } } - /// Ensures we use the right crypto when calling into native - pub trait ExternTrieCrypto: Hasher { - /// A trie root formed from the enumerated items. - fn ordered_trie_root< - A: AsRef<[u8]>, - I: IntoIterator - >(values: I) -> Self::Out; - } - - /// Additional bounds for Hasher trait for without_std. - pub trait HasherBounds: ExternTrieCrypto {} - impl HasherBounds for T {} - - // Ensures we use a Blake2_256-flavored Hasher when calling into native - impl ExternTrieCrypto for Blake2Hasher { - fn ordered_trie_root< - A: AsRef<[u8]>, - I: IntoIterator - >(items: I) -> Self::Out { - let mut values = Vec::new(); - let mut lengths = Vec::new(); - for v in items.into_iter() { - values.extend_from_slice(v.as_ref()); - lengths.push((v.as_ref().len() as u32).to_le()); - } - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_blake2_256_enumerated_trie_root.get()( - values.as_ptr(), - lengths.as_ptr(), - lengths.len() as u32, - result.as_mut_ptr() - ); - } - result.into() - } - } - /// Declare extern functions macro_rules! extern_functions { ( @@ -209,6 +160,14 @@ pub mod ext { fn ext_print_hex(data: *const u8, len: u32); /// Print a number fn ext_print_num(value: u64); + /// Print a log line if logging for given level and target is enabled. + fn ext_log( + level: u32, + target_data: *const u8, + target_len: u32, + message_data: *const u8, + message_len: u32, + ); /// Set value for key in storage. fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); @@ -228,7 +187,7 @@ pub mod ext { storage_key_data: *const u8, storage_key_len: u32, prefix_data: *const u8, - prefix_len: u32 + prefix_len: u32, ); /// Gets the value of the given key from storage. /// @@ -255,7 +214,7 @@ pub mod ext { key_len: u32, value_data: *mut u8, value_len: u32, - value_offset: u32 + value_offset: u32, ) -> u32; /// Gets the trie root of the storage. fn ext_storage_root(result: *mut u8); @@ -266,7 +225,10 @@ pub mod ext { /// - `1` if the change trie root was found. /// - `0` if the change trie root was not found. fn ext_storage_changes_root( - parent_hash_data: *const u8, parent_hash_len: u32, result: *mut u8) -> u32; + parent_hash_data: *const u8, + parent_hash_len: u32, + result: *mut u8, + ) -> u32; /// A child storage function. /// @@ -279,7 +241,7 @@ pub mod ext { key_data: *const u8, key_len: u32, value_data: *const u8, - value_len: u32 + value_len: u32, ); /// A child storage function. /// @@ -290,7 +252,7 @@ pub mod ext { storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, - key_len: u32 + key_len: u32, ); /// A child storage function. /// @@ -301,7 +263,7 @@ pub mod ext { storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, - key_len: u32 + key_len: u32, ) -> u32; /// A child storage function. /// @@ -319,7 +281,7 @@ pub mod ext { storage_key_len: u32, key_data: *const u8, key_len: u32, - written_out: *mut u32 + written_out: *mut u32, ) -> *mut u8; /// A child storage function. /// @@ -333,7 +295,7 @@ pub mod ext { key_len: u32, value_data: *mut u8, value_len: u32, - value_offset: u32 + value_offset: u32, ) -> u32; /// Commits all changes and calculates the child-storage root. /// @@ -432,12 +394,23 @@ pub mod ext { ) -> u32; /// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise. + /// + /// pubkey_data must point to 64 bytes. fn ext_secp256k1_ecdsa_recover( msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8, ) -> u32; + /// Note: ext_secp256k1_ecdsa_recover_compressed returns 0 if the signature is correct, nonzero otherwise. + /// + /// pubkey_data must point to 33 bytes. + fn ext_secp256k1_ecdsa_recover_compressed( + msg_data: *const u8, + sig_data: *const u8, + pubkey_data: *mut u8, + ) -> u32; + //================================ // Offchain-worker Context //================================ @@ -498,7 +471,7 @@ pub mod ext { old_value: *const u8, old_value_len: u32, new_value: *const u8, - new_value_len: u32 + new_value_len: u32, ) -> u32; /// Read a value from local storage. @@ -526,7 +499,7 @@ pub mod ext { url: *const u8, url_len: u32, meta: *const u8, - meta_len: u32 + meta_len: u32, ) -> u32; /// Add a header to the request. @@ -540,7 +513,7 @@ pub mod ext { name: *const u8, name_len: u32, value: *const u8, - value_len: u32 + value_len: u32, ) -> u32; /// Write a chunk of request body. @@ -556,7 +529,7 @@ pub mod ext { request_id: u32, chunk: *const u8, chunk_len: u32, - deadline: u64 + deadline: u64, ) -> u32; /// Block and wait for the responses for given requests. @@ -570,7 +543,7 @@ pub mod ext { ids: *const u32, ids_len: u32, statuses: *mut u32, - deadline: u64 + deadline: u64, ); /// Read all response headers. @@ -583,7 +556,7 @@ pub mod ext { /// - In case invalid `id` is passed it returns a pointer to parity-encoded empty vector. fn ext_http_response_headers( id: u32, - written_out: *mut u32 + written_out: *mut u32, ) -> *mut u8; /// Read a chunk of body response to given buffer. @@ -605,7 +578,7 @@ pub mod ext { id: u32, buffer: *mut u8, buffer_len: u32, - deadline: u64 + deadline: u64, ) -> u32; } } @@ -777,21 +750,28 @@ impl StorageApi for () { } } - fn trie_root< - H: Hasher + ExternTrieCrypto, - I: IntoIterator, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]>, - >(_input: I) -> H::Out { + + fn blake2_256_trie_root(_input: Vec<(Vec, Vec)>) -> H256 { unimplemented!() } - fn ordered_trie_root< - H: Hasher + ExternTrieCrypto, - I: IntoIterator, - A: AsRef<[u8]> - >(values: I) -> H::Out { - H::ordered_trie_root(values) + fn blake2_256_ordered_trie_root(input: Vec>) -> H256 { + let mut values = Vec::with_capacity(input.len()); + let mut lengths = Vec::with_capacity(input.len()); + for v in input { + values.extend_from_slice(&v); + lengths.push((v.len() as u32).to_le()); + } + let mut result: [u8; 32] = Default::default(); + unsafe { + ext_blake2_256_enumerated_trie_root.get()( + values.as_ptr(), + lengths.as_ptr(), + lengths.len() as u32, + result.as_mut_ptr(), + ); + } + result.into() } } @@ -802,10 +782,39 @@ impl OtherApi for () { } } - fn print(value: T) { - value.print() + fn print_num(val: u64) { + unsafe { + ext_print_num.get()(val); + } } + fn print_utf8(utf8: &[u8]) { + unsafe { + ext_print_utf8.get()(utf8.as_ptr(), utf8.len() as u32); + } + } + + fn print_hex(data: &[u8]) { + unsafe { + ext_print_hex.get()(data.as_ptr(), data.len() as u32); + } + } + + fn log( + level: LogLevel, + target: &[u8], + message: &[u8] + ) { + unsafe { + ext_log.get()( + level as u32, + target.as_ptr(), + target.len() as u32, + message.as_ptr(), + message.len() as u32, + ) + } + } } impl HashingApi for () { @@ -876,18 +885,18 @@ impl CryptoApi for () { ed25519::Public(res) } - fn ed25519_sign>( + fn ed25519_sign( id: KeyTypeId, pubkey: &ed25519::Public, - msg: &M, + msg: &[u8], ) -> Option { let mut res = [0u8; 64]; let success = unsafe { ext_ed25519_sign.get()( id.0.as_ptr(), pubkey.0.as_ptr(), - msg.as_ref().as_ptr(), - msg.as_ref().len() as u32, + msg.as_ptr(), + msg.len() as u32, res.as_mut_ptr(), ) == 0 }; @@ -927,18 +936,18 @@ impl CryptoApi for () { sr25519::Public(res) } - fn sr25519_sign>( + fn sr25519_sign( id: KeyTypeId, pubkey: &sr25519::Public, - msg: &M, + msg: &[u8], ) -> Option { let mut res = [0u8; 64]; let success = unsafe { ext_sr25519_sign.get()( id.0.as_ptr(), pubkey.0.as_ptr(), - msg.as_ref().as_ptr(), - msg.as_ref().len() as u32, + msg.as_ptr(), + msg.len() as u32, res.as_mut_ptr(), ) == 0 }; @@ -973,6 +982,19 @@ impl CryptoApi for () { _ => unreachable!("`ext_secp256k1_ecdsa_recover` only returns 0, 1, 2 or 3; qed"), } } + + fn secp256k1_ecdsa_recover_compressed(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 33], EcdsaVerifyError> { + let mut pubkey = [0u8; 33]; + match unsafe { + ext_secp256k1_ecdsa_recover_compressed.get()(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr()) + } { + 0 => Ok(pubkey), + 1 => Err(EcdsaVerifyError::BadRS), + 2 => Err(EcdsaVerifyError::BadV), + 3 => Err(EcdsaVerifyError::BadSignature), + _ => unreachable!("`ext_secp256k1_ecdsa_recover_compressed` only returns 0, 1, 2 or 3; qed"), + } + } } impl OffchainApi for () { @@ -980,10 +1002,9 @@ impl OffchainApi for () { unsafe { ext_is_validator.get()() == 1 } } - fn submit_transaction(data: &T) -> Result<(), ()> { - let encoded_data = codec::Encode::encode(data); + fn submit_transaction(data: Vec) -> Result<(), ()> { let ret = unsafe { - ext_submit_transaction.get()(encoded_data.as_ptr(), encoded_data.len() as u32) + ext_submit_transaction.get()(data.as_ptr(), data.len() as u32) }; if ret == 0 { @@ -1163,7 +1184,7 @@ impl OffchainApi for () { statuses .into_iter() - .map(|status| status.try_into().unwrap_or(offchain::HttpRequestStatus::Unknown)) + .map(|status| status.try_into().unwrap_or(offchain::HttpRequestStatus::Invalid)) .collect() } @@ -1218,25 +1239,3 @@ unsafe fn from_raw_parts(ptr: *mut u8, len: u32) -> Option> { } impl Api for () {} - -impl<'a> Printable for &'a [u8] { - fn print(self) { - unsafe { - ext_print_hex.get()(self.as_ptr(), self.len() as u32); - } - } -} - -impl<'a> Printable for &'a str { - fn print(self) { - unsafe { - ext_print_utf8.get()(self.as_ptr() as *const u8, self.len() as u32); - } - } -} - -impl Printable for u64 { - fn print(self) { - unsafe { ext_print_num.get()(self); } - } -} diff --git a/core/sr-primitives/Cargo.toml b/core/sr-primitives/Cargo.toml index d3510e6baa8340a5ed89d09534de7cfa43b61746..1b1434b91930d19186504fe6f563fa873a71dc1c 100644 --- a/core/sr-primitives/Cargo.toml +++ b/core/sr-primitives/Cargo.toml @@ -5,32 +5,34 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -num-traits = { version = "0.2", default-features = false } -integer-sqrt = { version = "0.1.2" } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } app-crypto = { package = "substrate-application-crypto", path = "../application-crypto", default-features = false } +arithmetic = { package = "sr-arithmetic", path = "../sr-arithmetic", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } -log = { version = "0.4", optional = true } -paste = { version = "0.1"} -rand = { version = "0.7.0", optional = true } +log = { version = "0.4.8", optional = true } +paste = "0.1.6" +rand = { version = "0.7.2", optional = true } +impl-trait-for-tuples = "0.1.3" [dev-dependencies] -serde_json = "1.0" -primitive-types = "0.5.0" +serde_json = "1.0.41" +rand = "0.7.2" +substrate-offchain = { path = "../offchain" } [features] +bench = [] default = ["std"] std = [ - "num-traits/std", - "serde", - "log", - "rstd/std", - "runtime_io/std", + "app-crypto/std", + "arithmetic/std", "codec/std", + "log", "primitives/std", - "app-crypto/std", "rand", + "rstd/std", + "runtime_io/std", + "serde", ] diff --git a/core/sr-primitives/src/curve.rs b/core/sr-primitives/src/curve.rs new file mode 100644 index 0000000000000000000000000000000000000000..6f25af3e10b6e3e96073cd07f19359b40a4a9a08 --- /dev/null +++ b/core/sr-primitives/src/curve.rs @@ -0,0 +1,163 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Provides some utilities to define a piecewise linear function. + +use crate::{Perbill, traits::{SimpleArithmetic, SaturatedConversion}}; +use core::ops::Sub; + +/// Piecewise Linear function in [0, 1] -> [0, 1]. +#[derive(PartialEq, Eq, primitives::RuntimeDebug)] +pub struct PiecewiseLinear<'a> { + /// Array of points. Must be in order from the lowest abscissas to the highest. + pub points: &'a [(Perbill, Perbill)] +} + +fn abs_sub + Clone>(a: N, b: N) -> N where { + a.clone().max(b.clone()) - a.min(b) +} + +impl<'a> PiecewiseLinear<'a> { + /// Compute `f(n/d)*d` with `n <= d`. This is useful to avoid loss of precision. + pub fn calculate_for_fraction_times_denominator(&self, n: N, d: N) -> N where + N: SimpleArithmetic + Clone + { + let n = n.min(d.clone()); + + if self.points.len() == 0 { + return N::zero() + } + + let next_point_index = self.points.iter() + .position(|p| n < p.0 * d.clone()); + + let (prev, next) = if let Some(next_point_index) = next_point_index { + if let Some(previous_point_index) = next_point_index.checked_sub(1) { + (self.points[previous_point_index], self.points[next_point_index]) + } else { + // There is no previous points, take first point ordinate + return self.points.first().map(|p| p.1).unwrap_or_else(Perbill::zero) * d + } + } else { + // There is no next points, take last point ordinate + return self.points.last().map(|p| p.1).unwrap_or_else(Perbill::zero) * d + }; + + let delta_y = multiply_by_rational_saturating( + abs_sub(n.clone(), prev.0 * d.clone()), + abs_sub(next.1.deconstruct(), prev.1.deconstruct()), + // Must not saturate as prev abscissa > next abscissa + next.0.deconstruct().saturating_sub(prev.0.deconstruct()), + ); + + // If both substration are same sign then result is positive + if (n > prev.0 * d.clone()) == (next.1.deconstruct() > prev.1.deconstruct()) { + (prev.1 * d).saturating_add(delta_y) + // Otherwise result is negative + } else { + (prev.1 * d).saturating_sub(delta_y) + } + } +} + +// Compute value * p / q. +// This is guaranteed not to overflow on whatever values nor lose precision. +// `q` must be superior to zero. +fn multiply_by_rational_saturating(value: N, p: u32, q: u32) -> N + where N: SimpleArithmetic + Clone +{ + let q = q.max(1); + + // Mul can saturate if p > q + let result_divisor_part = (value.clone() / q.into()).saturating_mul(p.into()); + + let result_remainder_part = { + let rem = value % q.into(); + + // Fits into u32 because q is u32 and remainder < q + let rem_u32 = rem.saturated_into::(); + + // Multiplication fits into u64 as both term are u32 + let rem_part = rem_u32 as u64 * p as u64 / q as u64; + + // Can saturate if p > q + rem_part.saturated_into::() + }; + + // Can saturate if p > q + result_divisor_part.saturating_add(result_remainder_part) +} + +#[test] +fn test_multiply_by_rational_saturating() { + use std::convert::TryInto; + + let div = 100u32; + for value in 0..=div { + for p in 0..=div { + for q in 1..=div { + let value: u64 = (value as u128 * u64::max_value() as u128 / div as u128) + .try_into().unwrap(); + let p = (p as u64 * u32::max_value() as u64 / div as u64) + .try_into().unwrap(); + let q = (q as u64 * u32::max_value() as u64 / div as u64) + .try_into().unwrap(); + + assert_eq!( + multiply_by_rational_saturating(value, p, q), + (value as u128 * p as u128 / q as u128) + .try_into().unwrap_or(u64::max_value()) + ); + } + } + } +} + +#[test] +fn test_calculate_for_fraction_times_denominator() { + use std::convert::TryInto; + + let curve = PiecewiseLinear { + points: &[ + (Perbill::from_parts(0_000_000_000), Perbill::from_parts(0_500_000_000)), + (Perbill::from_parts(0_500_000_000), Perbill::from_parts(1_000_000_000)), + (Perbill::from_parts(1_000_000_000), Perbill::from_parts(0_000_000_000)), + ] + }; + + pub fn formal_calculate_for_fraction_times_denominator(n: u64, d: u64) -> u64 { + if n <= Perbill::from_parts(0_500_000_000) * d.clone() { + n + d / 2 + } else { + (d as u128 * 2 - n as u128 * 2).try_into().unwrap() + } + } + + let div = 100u32; + for d in 0..=div { + for n in 0..=d { + let d: u64 = (d as u128 * u64::max_value() as u128 / div as u128) + .try_into().unwrap(); + let n: u64 = (n as u128 * u64::max_value() as u128 / div as u128) + .try_into().unwrap(); + + let res = curve.calculate_for_fraction_times_denominator(n, d); + let expected = formal_calculate_for_fraction_times_denominator(n, d); + + assert!(abs_sub(res, expected) <= 1); + } + } +} diff --git a/core/sr-primitives/src/generic/block.rs b/core/sr-primitives/src/generic/block.rs index 736ad0cbbb6368199ce4fa046c253bdddf66f0a3..3383e257605aa7498f35b39384c59bf86a3c50a1 100644 --- a/core/sr-primitives/src/generic/block.rs +++ b/core/sr-primitives/src/generic/block.rs @@ -23,13 +23,14 @@ use std::fmt; use serde::{Deserialize, Serialize}; use rstd::prelude::*; +use primitives::RuntimeDebug; use crate::codec::{Codec, Encode, Decode}; use crate::traits::{self, Member, Block as BlockT, Header as HeaderT, MaybeSerialize}; use crate::Justification; /// Something to identify a block. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub enum BlockId { @@ -61,8 +62,8 @@ impl fmt::Display for BlockId { } /// Abstraction over a substrate block. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Block { @@ -93,11 +94,14 @@ where fn new(header: Self::Header, extrinsics: Vec) -> Self { Block { header, extrinsics } } + fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec { + (header, extrinsics).encode() + } } /// Abstraction over a substrate block and justification. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct SignedBlock { diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index 08d7b10386721764ca2bad5cf627961b723a6b6a..3fc7711ccc451455a67877dd56c7c7db6542820a 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -17,19 +17,18 @@ //! Generic implementation of an extrinsic that has passed the verification //! stage. -use rstd::result::Result; use crate::traits::{ - self, Member, MaybeDisplay, SignedExtension, DispatchError, Dispatchable, DispatchResult, - ValidateUnsigned + self, Member, MaybeDisplay, SignedExtension, Dispatchable, }; +#[allow(deprecated)] +use crate::traits::ValidateUnsigned; use crate::weights::{GetDispatchInfo, DispatchInfo}; use crate::transaction_validity::TransactionValidity; /// Definition of something that the external world might want to say; its /// existence implies that it has been checked and is good, particularly with /// regards to the signature. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)] pub struct CheckedExtrinsic { /// Who this purports to be from and the number of extrinsics have come before /// from the same signer, if anyone (note this is not a signature). @@ -39,8 +38,7 @@ pub struct CheckedExtrinsic { pub function: Call, } -impl traits::Applyable -for +impl traits::Applyable for CheckedExtrinsic where AccountId: Member + MaybeDisplay, @@ -55,38 +53,38 @@ where self.signed.as_ref().map(|x| &x.0) } - fn validate>(&self, + #[allow(deprecated)] // Allow ValidateUnsigned + fn validate>( + &self, info: DispatchInfo, len: usize, ) -> TransactionValidity { if let Some((ref id, ref extra)) = self.signed { - Extra::validate(extra, id, &self.function, info, len).into() + Extra::validate(extra, id, &self.function, info, len) } else { - match Extra::validate_unsigned(&self.function, info, len) { - Ok(extra) => match U::validate_unsigned(&self.function) { - TransactionValidity::Valid(v) => - TransactionValidity::Valid(v.combine_with(extra)), - x => x, - }, - x => x.into(), - } + let valid = Extra::validate_unsigned(&self.function, info, len)?; + let unsigned_validation = U::validate_unsigned(&self.function)?; + Ok(valid.combine_with(unsigned_validation)) } } - fn dispatch(self, + #[allow(deprecated)] // Allow ValidateUnsigned + fn apply>( + self, info: DispatchInfo, len: usize, - ) -> Result { + ) -> crate::ApplyResult { let (maybe_who, pre) = if let Some((id, extra)) = self.signed { let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; (Some(id), pre) } else { let pre = Extra::pre_dispatch_unsigned(&self.function, info, len)?; + U::pre_dispatch(&self.function)?; (None, pre) }; let res = self.function.dispatch(Origin::from(maybe_who)); Extra::post_dispatch(pre, info, len); - Ok(res) + Ok(res.map_err(Into::into)) } } diff --git a/core/sr-primitives/src/generic/digest.rs b/core/sr-primitives/src/generic/digest.rs index 8e47a72183e8d22fa9783abc6adbbd447e5302c2..b507b7dba5c7167372d151f46f8e7212ec848d8f 100644 --- a/core/sr-primitives/src/generic/digest.rs +++ b/core/sr-primitives/src/generic/digest.rs @@ -24,10 +24,11 @@ use rstd::prelude::*; use primitives::ChangesTrieConfiguration; use crate::ConsensusEngineId; use crate::codec::{Decode, Encode, Input, Error}; +use primitives::RuntimeDebug; /// Generic header digest. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Digest { /// A list of logs in the digest. pub logs: Vec>, @@ -73,8 +74,7 @@ impl Digest { /// Digest item that is able to encode/decode 'system' digest items and /// provide opaque access to other items. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] pub enum DigestItem { /// System digest item that contains the root of changes trie at given /// block. It is created for every block iff runtime supports changes @@ -146,8 +146,7 @@ impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem { /// A 'referencing view' for digest item. Does not own its contents. Used by /// final runtime implementations for encoding/decoding its log items. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] pub enum DigestItemRef<'a, Hash: 'a> { /// Reference to `DigestItem::ChangesTrieRoot`. ChangesTrieRoot(&'a Hash), diff --git a/core/sr-primitives/src/generic/era.rs b/core/sr-primitives/src/generic/era.rs index 7308a8adc5cd5d97a43adfc10869008be7c8285b..305951b1ee3914e3ae2fc93839dd155090d12db3 100644 --- a/core/sr-primitives/src/generic/era.rs +++ b/core/sr-primitives/src/generic/era.rs @@ -28,8 +28,8 @@ pub type Period = u64; pub type Phase = u64; /// An era to describe the longevity of a transaction. -#[derive(PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[derive(PartialEq, Eq, Clone, Copy, primitives::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Era { /// The transaction is valid forever. The genesis hash must be present in the signed content. Immortal, diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index e9a8405fe21b0a45d62f9bcc341b14ee1712982b..75994749c572e3a5c144ce738608902dde91e2a0 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -18,20 +18,21 @@ #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -#[cfg(feature = "std")] -use log::debug; use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error}; use crate::traits::{ - self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug, - MaybeSerializeDebugButNotDeserialize + self, Member, SimpleArithmetic, SimpleBitOps, Hash as HashT, + MaybeSerializeDeserialize, MaybeSerialize, MaybeDisplay, }; use crate::generic::Digest; use primitives::U256; -use core::convert::TryFrom; +use rstd::{ + convert::TryFrom, + fmt::Debug, +}; /// Abstraction over a block header for a substrate chain. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Header + TryFrom, Hash: HashT> { @@ -103,11 +104,11 @@ impl codec::EncodeLike for Header where {} impl traits::Header for Header where - Number: Member + MaybeSerializeDebug + rstd::hash::Hash + MaybeDisplay + + Number: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash + MaybeDisplay + SimpleArithmetic + Codec + Copy + Into + TryFrom, Hash: HashT, Hash::Output: Default + rstd::hash::Hash + Copy + Member + - MaybeSerializeDebugButNotDeserialize + MaybeDisplay + SimpleBitOps + Codec, + MaybeSerialize + Debug + MaybeDisplay + SimpleBitOps + Codec, { type Number = Number; type Hash = ::Output; @@ -127,15 +128,12 @@ impl traits::Header for Header where fn digest(&self) -> &Digest { &self.digest } - #[cfg(feature = "std")] fn digest_mut(&mut self) -> &mut Digest { - debug!(target: "header", "Retrieving mutable reference to digest"); + #[cfg(feature = "std")] + log::debug!(target: "header", "Retrieving mutable reference to digest"); &mut self.digest } - #[cfg(not(feature = "std"))] - fn digest_mut(&mut self) -> &mut Digest { &mut self.digest } - fn new( number: Self::Number, extrinsics_root: Self::Hash, diff --git a/core/sr-primitives/src/generic/mod.rs b/core/sr-primitives/src/generic/mod.rs index a1d0cb052ecb14c6eaba8d16818268a6f6f84322..4aaf700bcd64d48c7fe604471f0922e8cd81c218 100644 --- a/core/sr-primitives/src/generic/mod.rs +++ b/core/sr-primitives/src/generic/mod.rs @@ -27,7 +27,7 @@ mod digest; #[cfg(test)] mod tests; -pub use self::unchecked_extrinsic::UncheckedExtrinsic; +pub use self::unchecked_extrinsic::{UncheckedExtrinsic, SignedPayload}; pub use self::era::{Era, Phase}; pub use self::checked_extrinsic::CheckedExtrinsic; pub use self::header::Header; diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index cb9330cfaaff0dad15939ebd9cc42575f7cb70e6..befa857dffd64d1ac13a90f7571e60ad8ca4050a 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -16,16 +16,17 @@ //! Generic implementation of an unchecked (pre-verification) extrinsic. -#[cfg(feature = "std")] -use std::fmt; - use rstd::prelude::*; +use rstd::fmt; use runtime_io::blake2_256; -use crate::codec::{Decode, Encode, Input, Error}; -use crate::traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic}; -use super::CheckedExtrinsic; +use codec::{Decode, Encode, EncodeLike, Input, Error}; +use crate::{ + traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic, IdentifyAccount}, + generic::CheckedExtrinsic, transaction_validity::{TransactionValidityError, InvalidTransaction}, + weights::{GetDispatchInfo, DispatchInfo}, +}; -const TRANSACTION_VERSION: u8 = 3; +const TRANSACTION_VERSION: u8 = 4; /// A extrinsic right from the external world. This is unchecked and so /// can contain a signature. @@ -72,12 +73,22 @@ impl Extrinsic { type Call = Call; + type SignaturePayload = ( + Address, + Signature, + Extra, + ); + fn is_signed(&self) -> Option { Some(self.signature.is_some()) } - fn new_unsigned(function: Call) -> Option { - Some(UncheckedExtrinsic::new_unsigned(function)) + fn new(function: Call, signed_data: Option) -> Option { + Some(if let Some((address, signature, extra)) = signed_data { + UncheckedExtrinsic::new_signed(function, address, signature, extra) + } else { + UncheckedExtrinsic::new_unsigned(function) + }) } } @@ -88,31 +99,29 @@ for where Address: Member + MaybeDisplay, Call: Encode + Member, - Signature: Member + traits::Verify, + Signature: Member + traits::Verify, + ::Signer: IdentifyAccount, Extra: SignedExtension, AccountId: Member + MaybeDisplay, - Lookup: traits::Lookup + Lookup: traits::Lookup, { type Checked = CheckedExtrinsic; - fn check(self, lookup: &Lookup) -> Result { + fn check(self, lookup: &Lookup) -> Result { Ok(match self.signature { Some((signed, signature, extra)) => { - let additional_signed = extra.additional_signed()?; - let raw_payload = (self.function, extra, additional_signed); let signed = lookup.lookup(signed)?; + let raw_payload = SignedPayload::new(self.function, extra)?; if !raw_payload.using_encoded(|payload| { - if payload.len() > 256 { - signature.verify(&blake2_256(payload)[..], &signed) - } else { - signature.verify(payload, &signed) - } + signature.verify(payload, &signed) }) { - return Err(crate::BAD_SIGNATURE) + return Err(InvalidTransaction::BadProof.into()) } + + let (function, extra, _) = raw_payload.deconstruct(); CheckedExtrinsic { - signed: Some((signed, raw_payload.1)), - function: raw_payload.0, + signed: Some((signed, extra)), + function, } } None => CheckedExtrinsic { @@ -123,6 +132,65 @@ where } } +/// A payload that has been signed for an unchecked extrinsics. +/// +/// Note that the payload that we sign to produce unchecked extrinsic signature +/// is going to be different than the `SignaturePayload` - so the thing the extrinsic +/// actually contains. +pub struct SignedPayload(( + Call, + Extra, + Extra::AdditionalSigned, +)); + +impl SignedPayload where + Call: Encode, + Extra: SignedExtension, +{ + /// Create new `SignedPayload`. + /// + /// This function may fail if `additional_signed` of `Extra` is not available. + pub fn new(call: Call, extra: Extra) -> Result { + let additional_signed = extra.additional_signed()?; + let raw_payload = (call, extra, additional_signed); + Ok(Self(raw_payload)) + } + + /// Create new `SignedPayload` from raw components. + pub fn from_raw(call: Call, extra: Extra, additional_signed: Extra::AdditionalSigned) -> Self { + Self((call, extra, additional_signed)) + } + + /// Deconstruct the payload into it's components. + pub fn deconstruct(self) -> (Call, Extra, Extra::AdditionalSigned) { + self.0 + } +} + +impl Encode for SignedPayload where + Call: Encode, + Extra: SignedExtension, +{ + /// Get an encoded version of this payload. + /// + /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. + fn using_encoded R>(&self, f: F) -> R { + self.0.using_encoded(|payload| { + if payload.len() > 256 { + f(&blake2_256(payload)[..]) + } else { + f(payload) + } + }) + } +} + +impl EncodeLike for SignedPayload +where + Call: Encode, + Extra: SignedExtension, +{} + impl Decode for UncheckedExtrinsic where @@ -178,6 +246,15 @@ where } } +impl EncodeLike + for UncheckedExtrinsic +where + Address: Encode, + Signature: Encode, + Call: Encode, + Extra: SignedExtension, +{} + #[cfg(feature = "std")] impl serde::Serialize for UncheckedExtrinsic @@ -187,7 +264,6 @@ impl s } } -#[cfg(feature = "std")] impl fmt::Debug for UncheckedExtrinsic where @@ -196,7 +272,23 @@ where Extra: SignedExtension, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedExtrinsic({:?}, {:?})", self.signature.as_ref().map(|x| (&x.0, &x.2)), self.function) + write!( + f, + "UncheckedExtrinsic({:?}, {:?})", + self.signature.as_ref().map(|x| (&x.0, &x.2)), + self.function, + ) + } +} + +impl GetDispatchInfo + for UncheckedExtrinsic +where + Call: GetDispatchInfo, + Extra: SignedExtension, +{ + fn get_dispatch_info(&self) -> DispatchInfo { + self.function.get_dispatch_info() } } @@ -205,22 +297,26 @@ mod tests { use super::*; use runtime_io::blake2_256; use crate::codec::{Encode, Decode}; - use crate::traits::{SignedExtension, Lookup}; + use crate::traits::{SignedExtension, IdentifyAccount, IdentityLookup}; use serde::{Serialize, Deserialize}; - struct TestContext; - impl Lookup for TestContext { - type Source = u64; - type Target = u64; - fn lookup(&self, s: u64) -> Result { Ok(s) } + type TestContext = IdentityLookup; + + #[derive(Eq, PartialEq, Clone, Copy, Debug, Serialize, Deserialize, Encode, Decode)] + pub struct TestSigner(pub u64); + impl From for TestSigner { fn from(x: u64) -> Self { Self(x) } } + impl From for u64 { fn from(x: TestSigner) -> Self { x.0 } } + impl IdentifyAccount for TestSigner { + type AccountId = u64; + fn into_account(self) -> u64 { self.into() } } #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Encode, Decode)] struct TestSig(u64, Vec); impl traits::Verify for TestSig { - type Signer = u64; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { - *signer == self.0 && msg.get() == &self.1[..] + type Signer = TestSigner; + fn verify>(&self, mut msg: L, signer: &u64) -> bool { + signer == &self.0 && msg.get() == &self.1[..] } } @@ -238,7 +334,7 @@ mod tests { type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } } type Ex = UncheckedExtrinsic; @@ -280,7 +376,7 @@ mod tests { fn unsigned_check_should_work() { let ux = Ex::new_unsigned(vec![0u8; 0]); assert!(!ux.is_signed().unwrap_or(false)); - assert!(>::check(ux, &TestContext).is_ok()); + assert!(>::check(ux, &Default::default()).is_ok()); } #[test] @@ -289,10 +385,13 @@ mod tests { vec![0u8; 0], TEST_ACCOUNT, TestSig(TEST_ACCOUNT, vec![0u8; 0]), - TestExtra + TestExtra, ); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!( + >::check(ux, &Default::default()), + Err(InvalidTransaction::BadProof.into()), + ); } #[test] @@ -301,12 +400,12 @@ mod tests { vec![0u8; 0], TEST_ACCOUNT, TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()), - TestExtra + TestExtra, ); assert!(ux.is_signed().unwrap_or(false)); assert_eq!( - >::check(ux, &TestContext), - Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }) + >::check(ux, &Default::default()), + Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }), ); } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 636a97ce9200b917a874118b94e4f7b619a162c6..fce9f7def05b36df85d5f4470fcf81d3006688e5 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -17,9 +17,12 @@ //! Runtime Modules shared primitive types. #![warn(missing_docs)] - #![cfg_attr(not(feature = "std"), no_std)] +// to allow benchmarking +#![cfg_attr(feature = "bench", feature(test))] +#[cfg(feature = "bench")] extern crate test; + #[doc(hidden)] pub use codec; #[cfg(feature = "std")] @@ -37,41 +40,48 @@ pub use app_crypto; #[cfg(feature = "std")] pub use runtime_io::{StorageOverlay, ChildrenStorageOverlay}; -use rstd::{prelude::*, ops, convert::{TryInto, TryFrom}}; -use primitives::{crypto, ed25519, sr25519, hash::{H256, H512}}; -use codec::{Encode, Decode, CompactAs}; +use rstd::prelude::*; +use rstd::convert::TryFrom; +use primitives::{crypto, ed25519, sr25519, ecdsa, hash::{H256, H512}}; +use codec::{Encode, Decode}; #[cfg(feature = "std")] pub mod testing; -pub mod weights; -pub mod traits; -use traits::{SaturatedConversion, UniqueSaturatedInto, Saturating, Bounded, CheckedSub, CheckedAdd}; - +pub mod curve; pub mod generic; +pub mod offchain; +pub mod traits; pub mod transaction_validity; +pub mod weights; /// Re-export these since they're only "kind of" generic. pub use generic::{DigestItem, Digest}; /// Re-export this since it's part of the API of this crate. -pub use primitives::crypto::{key_types, KeyTypeId, CryptoType}; -pub use app_crypto::AppKey; - -/// A message indicating an invalid signature in extrinsic. -pub const BAD_SIGNATURE: &str = "bad signature in extrinsic"; - -/// Full block error message. +pub use primitives::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, AccountId32}}; +pub use app_crypto::{RuntimeAppPublic, BoundToRuntimeAppPublic}; + +/// Re-export `RuntimeDebug`, to avoid dependency clutter. +pub use primitives::RuntimeDebug; + +/// Re-export top-level arithmetic stuff. +pub use arithmetic::{ + Perquintill, Perbill, Permill, Percent, + Rational128, Fixed64 +}; +/// Re-export 128 bit helpers. +pub use arithmetic::helpers_128bit; +/// Re-export big_uint stuff. +pub use arithmetic::biguint; + +/// An abstraction over justification for a block's validity under a consensus algorithm. /// -/// This allows modules to indicate that given transaction is potentially valid -/// in the future, but can't be executed in the current state. -/// Note this error should be returned early in the execution to prevent DoS, -/// cause the fees are not being paid if this error is returned. -/// -/// Example: block gas limit is reached (the transaction can be retried in the next block though). -pub const BLOCK_FULL: &str = "block size limit is reached"; - -/// Justification type. +/// Essentially a finality proof. The exact formulation will vary between consensus +/// algorithms. In the case where there are multiple valid proofs, inclusion within +/// the block itself would allow swapping justifications to change the block's hash +/// (and thus fork the chain). Sending a `Justification` alongside a block instead +/// bypasses this problem. pub type Justification = Vec; use traits::{Verify, Lazy}; @@ -80,7 +90,7 @@ use traits::{Verify, Lazy}; #[derive(Clone, Copy, Eq, PartialEq, Encode, Decode)] pub struct ModuleId(pub [u8; 8]); -impl traits::TypeId for ModuleId { +impl TypeId for ModuleId { const TYPE_ID: [u8; 4] = *b"modl"; } @@ -107,19 +117,20 @@ macro_rules! create_runtime_str { #[cfg(feature = "std")] pub use serde::{Serialize, Deserialize, de::DeserializeOwned}; +use crate::traits::IdentifyAccount; /// Complex storage builder stuff. #[cfg(feature = "std")] pub trait BuildStorage: Sized { /// Build the storage out of this builder. - fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { + fn build_storage(&self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { let mut storage = (Default::default(), Default::default()); self.assimilate_storage(&mut storage)?; Ok(storage) } /// Assimilate the storage for this module into pre-existing overlays. fn assimilate_storage( - self, + &self, storage: &mut (StorageOverlay, ChildrenStorageOverlay), ) -> Result<(), String>; } @@ -129,26 +140,24 @@ pub trait BuildStorage: Sized { pub trait BuildModuleGenesisStorage: Sized { /// Create the module genesis storage into the given `storage` and `child_storage`. fn build_module_genesis_storage( - self, + &self, storage: &mut (StorageOverlay, ChildrenStorageOverlay), ) -> Result<(), String>; } #[cfg(feature = "std")] impl BuildStorage for (StorageOverlay, ChildrenStorageOverlay) { - fn build_storage(self) -> Result<(StorageOverlay, ChildrenStorageOverlay), String> { - Ok(self) - } fn assimilate_storage( - self, + &self, storage: &mut (StorageOverlay, ChildrenStorageOverlay), )-> Result<(), String> { - storage.0.extend(self.0); - for (k, other_map) in self.1.into_iter() { + storage.0.extend(self.0.iter().map(|(k, v)| (k.clone(), v.clone()))); + for (k, other_map) in self.1.iter() { + let k = k.clone(); if let Some(map) = storage.1.get_mut(&k) { - map.extend(other_map); + map.extend(other_map.iter().map(|(k, v)| (k.clone(), v.clone()))); } else { - storage.1.insert(k, other_map); + storage.1.insert(k, other_map.clone()); } } Ok(()) @@ -158,356 +167,15 @@ impl BuildStorage for (StorageOverlay, ChildrenStorageOverlay) { /// Consensus engine unique ID. pub type ConsensusEngineId = [u8; 4]; -/// Permill is parts-per-million (i.e. after multiplying by this, divide by 1000000). -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Ord, PartialOrd))] -#[derive(Encode, Decode, CompactAs, Default, Copy, Clone, PartialEq, Eq)] -pub struct Permill(u32); - -impl Permill { - /// Nothing. - pub fn zero() -> Self { Self(0) } - - /// `true` if this is nothing. - pub fn is_zero(&self) -> bool { self.0 == 0 } - - /// Everything. - pub fn one() -> Self { Self(1_000_000) } - - /// create a new raw instance. This can be called at compile time. - pub const fn from_const_parts(parts: u32) -> Self { - Self([parts, 1_000_000][(parts > 1_000_000) as usize]) - } - - /// From an explicitly defined number of parts per maximum of the type. - pub fn from_parts(parts: u32) -> Self { Self::from_const_parts(parts) } - - /// Converts from a percent. Equal to `x / 100`. - pub const fn from_percent(x: u32) -> Self { Self([x, 100][(x > 100) as usize] * 10_000) } - - /// Converts a fraction into `Permill`. - #[cfg(feature = "std")] - pub fn from_fraction(x: f64) -> Self { Self((x * 1_000_000.0) as u32) } - - /// Approximate the fraction `p/q` into a per million fraction - pub fn from_rational_approximation(p: N, q: N) -> Self - where N: traits::SimpleArithmetic + Clone - { - let p = p.min(q.clone()); - let factor = (q.clone() / 1_000_000u32.into()).max(1u32.into()); - - // Conversion can't overflow as p < q so ( p / (q/million)) < million - let p_reduce: u32 = (p / factor.clone()).try_into().unwrap_or_else(|_| panic!()); - let q_reduce: u32 = (q / factor.clone()).try_into().unwrap_or_else(|_| panic!()); - let part = p_reduce as u64 * 1_000_000u64 / q_reduce as u64; - - Permill(part as u32) - } -} - -impl ops::Mul for Permill -where - N: Clone + From + UniqueSaturatedInto + ops::Rem - + ops::Div + ops::Mul + ops::Add, -{ - type Output = N; - fn mul(self, b: N) -> Self::Output { - let million: N = 1_000_000.into(); - let part: N = self.0.into(); - - let rem_multiplied_divided = { - let rem = b.clone().rem(million.clone()); - - // `rem` is inferior to one million, thus it fits into u32 - let rem_u32 = rem.saturated_into::(); - - // `self` and `rem` are inferior to one million, thus the product is less than 10^12 - // and fits into u64 - let rem_multiplied_u64 = rem_u32 as u64 * self.0 as u64; - - // `rem_multiplied_u64` is less than 10^12 therefore divided by a million it fits into - // u32 - let rem_multiplied_divided_u32 = (rem_multiplied_u64 / 1_000_000) as u32; - - // `rem_multiplied_divided` is inferior to b, thus it can be converted back to N type - rem_multiplied_divided_u32.into() - }; - - (b / million) * part + rem_multiplied_divided - } -} - -#[cfg(feature = "std")] -impl From for Permill { - fn from(x: f64) -> Permill { - Permill::from_fraction(x) - } -} - -#[cfg(feature = "std")] -impl From for Permill { - fn from(x: f32) -> Permill { - Permill::from_fraction(x as f64) - } -} - -/// Perbill is parts-per-billion. It stores a value between 0 and 1 in fixed point and -/// provides a means to multiply some other value by that. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, CompactAs, Default, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] -pub struct Perbill(u32); - -impl Perbill { - /// Nothing. - pub fn zero() -> Self { Self(0) } - - /// `true` if this is nothing. - pub fn is_zero(&self) -> bool { self.0 == 0 } - - /// Everything. - pub fn one() -> Self { Self(1_000_000_000) } - - /// create a new raw instance. This can be called at compile time. - pub const fn from_const_parts(parts: u32) -> Self { - Self([parts, 1_000_000_000][(parts > 1_000_000_000) as usize]) - } - - /// From an explicitly defined number of parts per maximum of the type. - pub fn from_parts(parts: u32) -> Self { Self::from_const_parts(parts) } - - /// Converts from a percent. Equal to `x / 100`. - pub const fn from_percent(x: u32) -> Self { Self([x, 100][(x > 100) as usize] * 10_000_000) } - - /// Construct new instance where `x` is in millionths. Value equivalent to `x / 1,000,000`. - pub fn from_millionths(x: u32) -> Self { Self(x.min(1_000_000) * 1000) } - - #[cfg(feature = "std")] - /// Construct new instance whose value is equal to `x` (between 0 and 1). - pub fn from_fraction(x: f64) -> Self { Self((x.max(0.0).min(1.0) * 1_000_000_000.0) as u32) } - - /// Approximate the fraction `p/q` into a per billion fraction - pub fn from_rational_approximation(p: N, q: N) -> Self - where N: traits::SimpleArithmetic + Clone - { - let p = p.min(q.clone()); - let factor = (q.clone() / 1_000_000_000u32.into()).max(1u32.into()); - - // Conversion can't overflow as p < q so ( p / (q/billion)) < billion - let p_reduce: u32 = (p / factor.clone()).try_into().unwrap_or_else(|_| panic!()); - let q_reduce: u32 = (q / factor.clone()).try_into().unwrap_or_else(|_| panic!()); - let part = p_reduce as u64 * 1_000_000_000u64 / q_reduce as u64; - - Perbill(part as u32) - } -} - -impl ops::Mul for Perbill -where - N: Clone + From + UniqueSaturatedInto + ops::Rem - + ops::Div + ops::Mul + ops::Add, -{ - type Output = N; - fn mul(self, b: N) -> Self::Output { - let billion: N = 1_000_000_000.into(); - let part: N = self.0.into(); - - let rem_multiplied_divided = { - let rem = b.clone().rem(billion.clone()); - - // `rem` is inferior to one billion, thus it fits into u32 - let rem_u32 = rem.saturated_into::(); - - // `self` and `rem` are inferior to one billion, thus the product is less than 10^18 - // and fits into u64 - let rem_multiplied_u64 = rem_u32 as u64 * self.0 as u64; - - // `rem_multiplied_u64` is less than 10^18 therefore divided by a billion it fits into - // u32 - let rem_multiplied_divided_u32 = (rem_multiplied_u64 / 1_000_000_000) as u32; - - // `rem_multiplied_divided` is inferior to b, thus it can be converted back to N type - rem_multiplied_divided_u32.into() - }; - - (b / billion) * part + rem_multiplied_divided - } -} - -#[cfg(feature = "std")] -impl From for Perbill { - fn from(x: f64) -> Perbill { - Perbill::from_fraction(x) - } -} - -#[cfg(feature = "std")] -impl From for Perbill { - fn from(x: f32) -> Perbill { - Perbill::from_fraction(x as f64) - } -} - -/// A fixed point number by the scale of 1 billion. -/// -/// cannot hold a value larger than +-`9223372036854775807 / 1_000_000_000` (~9 billion). -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Fixed64(i64); - -/// The maximum value of the `Fixed64` type -const DIV: i64 = 1_000_000_000; - -impl Fixed64 { - /// creates self from a natural number. - /// - /// Note that this might be lossy. - pub fn from_natural(int: i64) -> Self { - Self(int.saturating_mul(DIV)) - } - - /// Return the accuracy of the type. Given that this function returns the value `X`, it means - /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. - pub fn accuracy() -> i64 { - DIV - } - - /// creates self from a rational number. Equal to `n/d`. - /// - /// Note that this might be lossy. - pub fn from_rational(n: i64, d: u64) -> Self { - Self((n as i128 * DIV as i128 / (d as i128).max(1)).try_into().unwrap_or(Bounded::max_value())) - } - - /// Performs a saturated multiply and accumulate. - /// - /// Returns a saturated `n + (self * n)`. - /// TODO: generalize this to any weight type. #3189 - pub fn saturated_multiply_accumulate(&self, int: u32) -> u32 { - let parts = self.0; - let positive = parts > 0; - - // natural parts might overflow. - let natural_parts = self.clone().saturated_into::(); - // fractional parts can always fit into u32. - let perbill_parts = (parts.abs() % DIV) as u32; - - let n = int.saturating_mul(natural_parts); - let p = Perbill::from_parts(perbill_parts) * int; - // everything that needs to be either added or subtracted from the original weight. - let excess = n.saturating_add(p); - - if positive { - int.saturating_add(excess) - } else { - int.saturating_sub(excess) - } - } - - /// Raw constructor. Equal to `parts / 1_000_000_000`. - pub fn from_parts(parts: i64) -> Self { - Self(parts) - } -} - -impl UniqueSaturatedInto for Fixed64 { - /// Note that the maximum value of Fixed64 might be more than what can fit in u32. This is hence, - /// expected to be lossy. - fn unique_saturated_into(self) -> u32 { - (self.0.abs() / DIV).try_into().unwrap_or(Bounded::max_value()) - } -} - -impl Saturating for Fixed64 { - fn saturating_add(self, rhs: Self) -> Self { - Self(self.0.saturating_add(rhs.0)) - } - fn saturating_mul(self, rhs: Self) -> Self { - Self(self.0.saturating_mul(rhs.0) / DIV) - } - fn saturating_sub(self, rhs: Self) -> Self { - Self(self.0.saturating_sub(rhs.0)) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe addition. -impl ops::Add for Fixed64 { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe subtraction. -impl ops::Sub for Fixed64 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) - } -} - -impl CheckedSub for Fixed64 { - fn checked_sub(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_sub(rhs.0) { - Some(Self(v)) - } else { - None - } - } -} - -impl CheckedAdd for Fixed64 { - fn checked_add(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_add(rhs.0) { - Some(Self(v)) - } else { - None - } - } -} - -/// PerU128 is parts-per-u128-max-value. It stores a value between 0 and 1 in fixed point. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, CompactAs, Default, Copy, Clone, PartialEq, Eq)] -pub struct PerU128(u128); - -const U128: u128 = u128::max_value(); - -impl PerU128 { - /// Nothing. - pub fn zero() -> Self { Self(0) } - - /// `true` if this is nothing. - pub fn is_zero(&self) -> bool { self.0 == 0 } - - /// Everything. - pub fn one() -> Self { Self(U128) } - - /// From an explicitly defined number of parts per maximum of the type. - pub fn from_parts(x: u128) -> Self { Self(x) } - - /// Construct new instance where `x` is denominator and the nominator is 1. - pub fn from_xth(x: u128) -> Self { Self(U128/x.max(1)) } -} - -impl ::rstd::ops::Deref for PerU128 { - type Target = u128; - - fn deref(&self) -> &u128 { - &self.0 - } -} - /// Signature verify that can work with any known signature types.. -#[derive(Eq, PartialEq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, RuntimeDebug)] pub enum MultiSignature { /// An Ed25519 signature. Ed25519(ed25519::Signature), /// An Sr25519 signature. Sr25519(sr25519::Signature), + /// An ECDSA/SECP256k1 signature. + Ecdsa(ecdsa::Signature), } impl From for MultiSignature { @@ -522,6 +190,12 @@ impl From for MultiSignature { } } +impl From for MultiSignature { + fn from(x: ecdsa::Signature) -> Self { + MultiSignature::Ecdsa(x) + } +} + impl Default for MultiSignature { fn default() -> Self { MultiSignature::Ed25519(Default::default()) @@ -529,13 +203,15 @@ impl Default for MultiSignature { } /// Public key for any known crypto algorithm. -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum MultiSigner { /// An Ed25519 identity. Ed25519(ed25519::Public), /// An Sr25519 identity. Sr25519(sr25519::Public), + /// An SECP256k1/ECDSA identity (actually, the Blake2 hash of the pub key). + Ecdsa(ecdsa::Public), } impl Default for MultiSigner { @@ -557,6 +233,18 @@ impl AsRef<[u8]> for MultiSigner { match *self { MultiSigner::Ed25519(ref who) => who.as_ref(), MultiSigner::Sr25519(ref who) => who.as_ref(), + MultiSigner::Ecdsa(ref who) => who.as_ref(), + } + } +} + +impl traits::IdentifyAccount for MultiSigner { + type AccountId = AccountId32; + fn into_account(self) -> AccountId32 { + match self { + MultiSigner::Ed25519(who) => <[u8; 32]>::from(who).into(), + MultiSigner::Sr25519(who) => <[u8; 32]>::from(who).into(), + MultiSigner::Ecdsa(who) => runtime_io::blake2_256(who.as_ref()).into(), } } } @@ -567,47 +255,83 @@ impl From for MultiSigner { } } +impl TryFrom for ed25519::Public { + type Error = (); + fn try_from(m: MultiSigner) -> Result { + if let MultiSigner::Ed25519(x) = m { Ok(x) } else { Err(()) } + } +} + impl From for MultiSigner { fn from(x: sr25519::Public) -> Self { MultiSigner::Sr25519(x) } } - #[cfg(feature = "std")] +impl TryFrom for sr25519::Public { + type Error = (); + fn try_from(m: MultiSigner) -> Result { + if let MultiSigner::Sr25519(x) = m { Ok(x) } else { Err(()) } + } +} + +impl From for MultiSigner { + fn from(x: ecdsa::Public) -> Self { + MultiSigner::Ecdsa(x) + } +} + +impl TryFrom for ecdsa::Public { + type Error = (); + fn try_from(m: MultiSigner) -> Result { + if let MultiSigner::Ecdsa(x) = m { Ok(x) } else { Err(()) } + } +} + +#[cfg(feature = "std")] impl std::fmt::Display for MultiSigner { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { match *self { MultiSigner::Ed25519(ref who) => write!(fmt, "ed25519: {}", who), MultiSigner::Sr25519(ref who) => write!(fmt, "sr25519: {}", who), + MultiSigner::Ecdsa(ref who) => write!(fmt, "ecdsa: {}", who), } } } impl Verify for MultiSignature { type Signer = MultiSigner; - fn verify>(&self, msg: L, signer: &Self::Signer) -> bool { + fn verify>(&self, mut msg: L, signer: &AccountId32) -> bool { + use primitives::crypto::Public; match (self, signer) { - (MultiSignature::Ed25519(ref sig), &MultiSigner::Ed25519(ref who)) => sig.verify(msg, who), - (MultiSignature::Sr25519(ref sig), &MultiSigner::Sr25519(ref who)) => sig.verify(msg, who), - _ => false, + (MultiSignature::Ed25519(ref sig), who) => sig.verify(msg, &ed25519::Public::from_slice(who.as_ref())), + (MultiSignature::Sr25519(ref sig), who) => sig.verify(msg, &sr25519::Public::from_slice(who.as_ref())), + (MultiSignature::Ecdsa(ref sig), who) => { + let m = runtime_io::blake2_256(msg.get()); + match runtime_io::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { + Ok(pubkey) => &runtime_io::blake2_256(pubkey.as_ref()) == >::as_ref(who), + _ => false, + } + } } } } /// Signature verify that can work with any known signature types.. -#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Default, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct AnySignature(H512); impl Verify for AnySignature { type Signer = sr25519::Public; fn verify>(&self, mut msg: L, signer: &sr25519::Public) -> bool { + use primitives::crypto::Public; + let msg = msg.get(); sr25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) - .map(|s| runtime_io::sr25519_verify(&s, msg.get(), &signer)) + .map(|s| s.verify(msg, signer)) .unwrap_or(false) || ed25519::Signature::try_from(self.0.as_fixed_bytes().as_ref()) - .and_then(|s| ed25519::Public::try_from(signer.0.as_ref()).map(|p| (s, p))) - .map(|(s, p)| runtime_io::ed25519_verify(&s, msg.get(), &p)) + .map(|s| s.verify(msg, &ed25519::Public::from_slice(signer.as_ref()))) .unwrap_or(false) } } @@ -624,56 +348,114 @@ impl From for AnySignature { } } -#[derive(Eq, PartialEq, Clone, Copy, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[repr(u8)] -/// Outcome of a valid extrinsic application. Capable of being sliced. -pub enum ApplyOutcome { - /// Successful application (extrinsic reported no issue). - Success = 0, - /// Failed application (extrinsic was probably a no-op other than fees). - Fail = 1, +#[derive(Eq, PartialEq, Clone, Copy, Decode, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize))] +/// Reason why an extrinsic couldn't be applied (i.e. invalid extrinsic). +pub enum ApplyError { + /// General error to do with the permissions of the sender. + NoPermission, + + /// General error to do with the state of the system in general. + BadState, + + /// Any error to do with the transaction validity. + Validity(transaction_validity::TransactionValidityError), } -impl codec::Encode for ApplyOutcome { - fn using_encoded R>(&self, f: F) -> R { - f(&[*self as u8]) +impl ApplyError { + /// Returns if the reason for the error was block resource exhaustion. + pub fn exhausted_resources(&self) -> bool { + match self { + Self::Validity(e) => e.exhausted_resources(), + _ => false, + } } } -impl codec::EncodeLike for ApplyOutcome {} - -#[derive(Eq, PartialEq, Clone, Copy, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[repr(u8)] -/// Reason why an extrinsic couldn't be applied (i.e. invalid extrinsic). -pub enum ApplyError { - /// Bad signature. - BadSignature = 0, - /// Nonce too low. - Stale = 1, - /// Nonce too high. - Future = 2, - /// Sending account had too low a balance. - CantPay = 3, - /// Block is full, no more extrinsics can be applied. - FullBlock = 255, +impl From for &'static str { + fn from(err: ApplyError) -> &'static str { + match err { + ApplyError::NoPermission => "Transaction does not have required permissions", + ApplyError::BadState => "System state currently prevents this transaction", + ApplyError::Validity(v) => v.into(), + } + } } -impl codec::Encode for ApplyError { - fn using_encoded R>(&self, f: F) -> R { - f(&[*self as u8]) +impl From for ApplyError { + fn from(err: transaction_validity::TransactionValidityError) -> Self { + ApplyError::Validity(err) } } -impl codec::EncodeLike for ApplyError {} +/// The outcome of applying a transaction. +pub type ApplyOutcome = Result<(), DispatchError>; + +impl From for ApplyOutcome { + fn from(err: DispatchError) -> Self { + Err(err) + } +} /// Result from attempt to apply an extrinsic. pub type ApplyResult = Result; +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize))] +/// Reason why a dispatch call failed +pub struct DispatchError { + /// Module index, matching the metadata module index + pub module: Option, + /// Module specific error value + pub error: u8, + /// Optional error message. + #[codec(skip)] + pub message: Option<&'static str>, +} + +impl DispatchError { + /// Create a new instance of `DispatchError`. + pub fn new(module: Option, error: u8, message: Option<&'static str>) -> Self { + Self { + module, + error, + message, + } + } +} + +impl traits::Printable for DispatchError { + fn print(&self) { + "DispatchError".print(); + if let Some(module) = self.module { + module.print(); + } + self.error.print(); + if let Some(msg) = self.message { + msg.print(); + } + } +} + +impl traits::ModuleDispatchError for &'static str { + fn as_u8(&self) -> u8 { + 0 + } + + fn as_str(&self) -> &'static str { + self + } +} + +impl From<&'static str> for DispatchError { + fn from(err: &'static str) -> DispatchError { + DispatchError::new(None, 0, Some(err)) + } +} + /// Verify a signature on an encoded value in a lazy manner. This can be /// an optimization if the signature scheme has an "unsigned" escape hash. -pub fn verify_encoded_lazy(sig: &V, item: &T, signer: &V::Signer) -> bool { +pub fn verify_encoded_lazy(sig: &V, item: &T, signer: &::AccountId) -> bool { // The `Lazy` trait expresses something like `X: FnMut &'a T>`. // unfortunately this is a lifetime relationship that can't // be expressed without generic associated types, better unification of HRTBs in type position, @@ -759,11 +541,11 @@ macro_rules! impl_outer_config { #[cfg(any(feature = "std", test))] impl $crate::BuildStorage for $main { fn assimilate_storage( - self, + &self, storage: &mut ($crate::StorageOverlay, $crate::ChildrenStorageOverlay), ) -> std::result::Result<(), String> { $( - if let Some(extra) = self.[< $snake $(_ $instance )? >] { + if let Some(ref extra) = self.[< $snake $(_ $instance )? >] { $crate::impl_outer_config! { @CALL_FN $concrete; @@ -805,18 +587,55 @@ macro_rules! impl_outer_config { } } +/// Checks that `$x` is equal to `$y` with an error rate of `$error`. +/// +/// # Example +/// +/// ```rust +/// # fn main() { +/// sr_primitives::assert_eq_error_rate!(10, 10, 0); +/// sr_primitives::assert_eq_error_rate!(10, 11, 1); +/// sr_primitives::assert_eq_error_rate!(12, 10, 2); +/// # } +/// ``` +/// +/// ```rust,should_panic +/// # fn main() { +/// sr_primitives::assert_eq_error_rate!(12, 10, 1); +/// # } +/// ``` +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_eq_error_rate { + ($x:expr, $y:expr, $error:expr $(,)?) => { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} + /// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized /// correctly. #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] pub struct OpaqueExtrinsic(pub Vec); -#[cfg(feature = "std")] -impl std::fmt::Debug for OpaqueExtrinsic { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { +impl rstd::fmt::Debug for OpaqueExtrinsic { + #[cfg(feature = "std")] + fn fmt(&self, fmt: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { write!(fmt, "{}", primitives::hexdisplay::HexDisplay::from(&self.0)) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _fmt: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } } + #[cfg(feature = "std")] impl ::serde::Serialize for OpaqueExtrinsic { fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { @@ -835,50 +654,18 @@ impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic { impl traits::Extrinsic for OpaqueExtrinsic { type Call = (); + type SignaturePayload = (); +} - fn is_signed(&self) -> Option { - None - } - - fn new_unsigned(_call: Self::Call) -> Option { None } +/// Print something that implements `Printable` from the runtime. +pub fn print(print: impl traits::Printable) { + print.print(); } #[cfg(test)] mod tests { - use crate::codec::{Encode, Decode}; - use super::{Perbill, Permill}; - - macro_rules! per_thing_upper_test { - ($num_type:tt, $per:tt) => { - // multiplication from all sort of from_percent - assert_eq!($per::from_percent(100) * $num_type::max_value(), $num_type::max_value()); - assert_eq!( - $per::from_percent(99) * $num_type::max_value(), - ((Into::::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type - ); - assert_eq!($per::from_percent(50) * $num_type::max_value(), $num_type::max_value() / 2); - assert_eq!($per::from_percent(1) * $num_type::max_value(), $num_type::max_value() / 100); - assert_eq!($per::from_percent(0) * $num_type::max_value(), 0); - - // multiplication with bounds - assert_eq!($per::one() * $num_type::max_value(), $num_type::max_value()); - assert_eq!($per::zero() * $num_type::max_value(), 0); - - // from_rational_approximation - assert_eq!( - $per::from_rational_approximation(u128::max_value() - 1, u128::max_value()), - $per::one(), - ); - assert_eq!( - $per::from_rational_approximation(u128::max_value()/3, u128::max_value()), - $per::from_parts($per::one().0/3), - ); - assert_eq!( - $per::from_rational_approximation(1, u128::max_value()), - $per::zero(), - ); - } - } + use crate::DispatchError; + use codec::{Encode, Decode}; #[test] fn opaque_extrinsic_serialization() { @@ -887,76 +674,22 @@ mod tests { } #[test] - fn compact_permill_perbill_encoding() { - let tests = [(0u32, 1usize), (63, 1), (64, 2), (16383, 2), (16384, 4), (1073741823, 4), (1073741824, 5), (u32::max_value(), 5)]; - for &(n, l) in &tests { - let compact: crate::codec::Compact = Permill(n).into(); - let encoded = compact.encode(); - assert_eq!(encoded.len(), l); - let decoded = >::decode(&mut & encoded[..]).unwrap(); - let permill: Permill = decoded.into(); - assert_eq!(permill, Permill(n)); - - let compact: crate::codec::Compact = Perbill(n).into(); - let encoded = compact.encode(); - assert_eq!(encoded.len(), l); - let decoded = >::decode(&mut & encoded[..]).unwrap(); - let perbill: Perbill = decoded.into(); - assert_eq!(perbill, Perbill(n)); - } - } - - #[derive(Encode, Decode, PartialEq, Eq, Debug)] - struct WithCompact { - data: T, - } - - #[test] - fn test_has_compact_permill() { - let data = WithCompact { data: Permill(1) }; - let encoded = data.encode(); - assert_eq!(data, WithCompact::::decode(&mut &encoded[..]).unwrap()); - } - - #[test] - fn test_has_compact_perbill() { - let data = WithCompact { data: Perbill(1) }; - let encoded = data.encode(); - assert_eq!(data, WithCompact::::decode(&mut &encoded[..]).unwrap()); - } - - #[test] - fn per_things_should_work() { - use super::{Perbill, Permill}; - use primitive_types::U256; - - per_thing_upper_test!(u32, Perbill); - per_thing_upper_test!(u64, Perbill); - per_thing_upper_test!(u128, Perbill); - - per_thing_upper_test!(u32, Permill); - per_thing_upper_test!(u64, Permill); - per_thing_upper_test!(u128, Permill); - - } - - #[test] - fn per_things_operate_in_output_type() { - assert_eq!(Perbill::one() * 255_u64, 255); - } - - #[test] - fn per_things_one_minus_one_part() { - use primitive_types::U256; - - assert_eq!( - Perbill::from_parts(999_999_999) * std::u128::MAX, - ((Into::::into(std::u128::MAX) * 999_999_999u32) / 1_000_000_000u32).as_u128() - ); - + fn dispatch_error_encoding() { + let error = DispatchError { + module: Some(1), + error: 2, + message: Some("error message"), + }; + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![1, 1, 2]); assert_eq!( - Permill::from_parts(999_999) * std::u128::MAX, - ((Into::::into(std::u128::MAX) * 999_999u32) / 1_000_000u32).as_u128() + decoded, + DispatchError { + module: Some(1), + error: 2, + message: None, + }, ); } } diff --git a/core/sr-io/src/offchain/http.rs b/core/sr-primitives/src/offchain/http.rs similarity index 84% rename from core/sr-io/src/offchain/http.rs rename to core/sr-primitives/src/offchain/http.rs index 6685dd023f469e607b59cfcf7509b629c58bde94..77e514d65342bb605f030cf7b8f86e95a9d34d40 100644 --- a/core/sr-io/src/offchain/http.rs +++ b/core/sr-primitives/src/offchain/http.rs @@ -14,12 +14,44 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! A non-std set of HTTP types. +//! A high-level helpers for making HTTP requests from Offchain Workers. +//! +//! `sr-io` crate exposes a low level methods to make and control HTTP requests +//! available only for Offchain Workers. Those might be hard to use +//! and usually that level of control is not really necessary. +//! This module aims to provide high-level wrappers for those APIs +//! to simplify making HTTP requests. +//! +//! +//! Example: +//! ```rust,no_run +//! use sr_primitives::offchain::http::Request; +//! +//! // initiate a GET request to localhost:1234 +//! let request: Request = Request::get("http://localhost:1234"); +//! let pending = request +//! .add_header("X-Auth", "hunter2") +//! .send() +//! .unwrap(); +//! +//! // wait for the response indefinitely +//! let mut response = pending.wait().unwrap(); +//! +//! // then check the headers +//! let mut headers = response.headers().into_iter(); +//! assert_eq!(headers.current(), None); +//! +//! // and collect the body +//! let body = response.body(); +//! assert_eq!(body.clone().collect::>(), b"1234".to_vec()); +//! assert_eq!(body.error(), &None); +//! ``` use rstd::str; use rstd::prelude::Vec; #[cfg(not(feature = "std"))] use rstd::prelude::vec; +use primitives::RuntimeDebug; use primitives::offchain::{ Timestamp, HttpRequestId as RequestId, @@ -28,8 +60,7 @@ use primitives::offchain::{ }; /// Request method (HTTP verb) -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] pub enum Method { /// GET request Get, @@ -62,8 +93,7 @@ mod header { use super::*; /// A header type. - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive(Clone, PartialEq, Eq, RuntimeDebug)] pub struct Header { name: Vec, value: Vec, @@ -97,8 +127,7 @@ mod header { } /// An HTTP request builder. -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] pub struct Request<'a, T = Vec<&'static [u8]>> { /// Request method pub method: Method, @@ -192,11 +221,11 @@ impl<'a, I: AsRef<[u8]>, T: IntoIterator> Request<'a, T> { let meta = &[]; // start an http request. - let id = crate::http_request_start(self.method.as_ref(), self.url, meta).map_err(|_| HttpError::IoError)?; + let id = runtime_io::http_request_start(self.method.as_ref(), self.url, meta).map_err(|_| HttpError::IoError)?; // add custom headers for header in &self.headers { - crate::http_request_add_header( + runtime_io::http_request_add_header( id, header.name(), header.value(), @@ -205,11 +234,11 @@ impl<'a, I: AsRef<[u8]>, T: IntoIterator> Request<'a, T> { // write body for chunk in self.body { - crate::http_request_write_body(id, chunk.as_ref(), self.deadline)?; + runtime_io::http_request_write_body(id, chunk.as_ref(), self.deadline)?; } // finalise the request - crate::http_request_write_body(id, &[], self.deadline)?; + runtime_io::http_request_write_body(id, &[], self.deadline)?; Ok(PendingRequest { id, @@ -218,20 +247,18 @@ impl<'a, I: AsRef<[u8]>, T: IntoIterator> Request<'a, T> { } /// A request error -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] pub enum Error { /// Deadline has been reached. DeadlineReached, /// Request had timed out. - Timeout, + IoError, /// Unknown error has been ecountered. Unknown, } /// A struct representing an uncompleted http request. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, RuntimeDebug)] pub struct PendingRequest { /// Request ID pub id: RequestId, @@ -276,15 +303,15 @@ impl PendingRequest { deadline: impl Into> ) -> Vec> { let ids = requests.iter().map(|r| r.id).collect::>(); - let statuses = crate::http_response_wait(&ids, deadline.into()); + let statuses = runtime_io::http_response_wait(&ids, deadline.into()); statuses .into_iter() .zip(requests.into_iter()) .map(|(status, req)| match status { RequestStatus::DeadlineReached => Err(req), - RequestStatus::Timeout => Ok(Err(Error::Timeout)), - RequestStatus::Unknown => Ok(Err(Error::Unknown)), + RequestStatus::IoError => Ok(Err(Error::IoError)), + RequestStatus::Invalid => Ok(Err(Error::Unknown)), RequestStatus::Finished(code) => Ok(Ok(Response::new(req.id, code))), }) .collect() @@ -292,7 +319,7 @@ impl PendingRequest { } /// A HTTP response. -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(RuntimeDebug)] pub struct Response { /// Request id pub id: RequestId, @@ -314,7 +341,7 @@ impl Response { /// Retrieve the headers for this response. pub fn headers(&mut self) -> &Headers { if self.headers.is_none() { - self.headers = Some(Headers { raw: crate::http_response_headers(self.id) }); + self.headers = Some(Headers { raw: runtime_io::http_response_headers(self.id) }); } self.headers.as_ref().expect("Headers were just set; qed") } @@ -393,7 +420,7 @@ impl Iterator for ResponseBody { } if self.filled_up_to.is_none() { - let result = crate::http_response_read_body(self.id, &mut self.buffer, self.deadline); + let result = runtime_io::http_response_read_body(self.id, &mut self.buffer, self.deadline); match result { Err(e) => { self.error = Some(e); @@ -421,8 +448,7 @@ impl Iterator for ResponseBody { } /// A collection of Headers in the response. -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] pub struct Headers { /// Raw headers pub raw: Vec<(Vec, Vec)>, @@ -452,8 +478,7 @@ impl Headers { } /// A custom iterator traversing all the headers. -#[derive(Clone)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, RuntimeDebug)] pub struct HeadersIterator<'a> { collection: &'a [(Vec, Vec)], index: Option, @@ -481,16 +506,17 @@ impl<'a> HeadersIterator<'a> { #[cfg(test)] mod tests { use super::*; - use crate::{TestExternalities, with_externalities}; + use runtime_io::TestExternalities; use substrate_offchain::testing; + use primitives::offchain::OffchainExt; #[test] fn should_send_a_basic_request_and_get_response() { let (offchain, state) = testing::TestOffchainExt::new(); let mut t = TestExternalities::default(); - t.set_offchain_externalities(offchain); + t.register_extension(OffchainExt::new(offchain)); - with_externalities(&mut t, || { + t.execute_with(|| { let request: Request = Request::get("http://localhost:1234"); let pending = request .add_header("X-Auth", "hunter2") @@ -529,9 +555,9 @@ mod tests { fn should_send_a_post_request() { let (offchain, state) = testing::TestOffchainExt::new(); let mut t = TestExternalities::default(); - t.set_offchain_externalities(offchain); + t.register_extension(OffchainExt::new(offchain)); - with_externalities(&mut t, || { + t.execute_with(|| { let pending = Request::default() .method(Method::Post) .url("http://localhost:1234") diff --git a/core/sr-io/src/offchain/mod.rs b/core/sr-primitives/src/offchain/mod.rs similarity index 100% rename from core/sr-io/src/offchain/mod.rs rename to core/sr-primitives/src/offchain/mod.rs diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index c91c8366c1123587a98e1f4a5a7542963489dd89..b1bd94a5461b195a37d798e1966231b09687e643 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -17,22 +17,36 @@ //! Testing utilities. use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer}; -use std::{fmt::Debug, ops::Deref, fmt}; +use std::{fmt::Debug, ops::Deref, fmt, cell::RefCell}; use crate::codec::{Codec, Encode, Decode}; use crate::traits::{ - self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, DispatchError, DispatchResult, - ValidateUnsigned, SignedExtension, Dispatchable, + self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, + SignedExtension, Dispatchable, }; -use crate::{generic, KeyTypeId}; +#[allow(deprecated)] +use crate::traits::ValidateUnsigned; +use crate::{generic, KeyTypeId, ApplyResult}; use crate::weights::{GetDispatchInfo, DispatchInfo}; -pub use primitives::H256; +pub use primitives::{H256, sr25519}; use primitives::{crypto::{CryptoType, Dummy, key_types, Public}, U256}; -use crate::transaction_validity::TransactionValidity; +use crate::transaction_validity::{TransactionValidity, TransactionValidityError}; /// Authority Id -#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize)] +#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize, PartialOrd, Ord)] pub struct UintAuthorityId(pub u64); +impl From for UintAuthorityId { + fn from(id: u64) -> Self { + UintAuthorityId(id) + } +} + +impl From for u64 { + fn from(id: UintAuthorityId) -> u64 { + id.0 + } +} + impl UintAuthorityId { /// Convert this authority id into a public key. pub fn to_public_key(&self) -> T { @@ -47,34 +61,44 @@ impl CryptoType for UintAuthorityId { impl AsRef<[u8]> for UintAuthorityId { fn as_ref(&self) -> &[u8] { + // Unsafe, i know, but it's test code and it's just there because it's really convenient to + // keep `UintAuthorityId` as a u64 under the hood. unsafe { std::slice::from_raw_parts(&self.0 as *const u64 as *const _, std::mem::size_of::()) } } } +thread_local! { + /// A list of all UintAuthorityId keys returned to the runtime. + static ALL_KEYS: RefCell> = RefCell::new(vec![]); +} + +impl UintAuthorityId { + /// Set the list of keys returned by the runtime call for all keys of that type. + pub fn set_all_keys>(keys: impl IntoIterator) { + ALL_KEYS.with(|l| *l.borrow_mut() = keys.into_iter().map(Into::into).collect()) + } +} + impl app_crypto::RuntimeAppPublic for UintAuthorityId { + const ID: KeyTypeId = key_types::DUMMY; + type Signature = u64; fn all() -> Vec { - unimplemented!("`all()` not available for `UintAuthorityId`.") + ALL_KEYS.with(|l| l.borrow().clone()) } - #[cfg(feature = "std")] fn generate_pair(_: Option<&str>) -> Self { use rand::RngCore; UintAuthorityId(rand::thread_rng().next_u64()) } - #[cfg(not(feature = "std"))] - fn generate_pair(_: Option<&str>) -> Self { - unimplemented!("`generate_pair` not implemented for `UIntAuthorityId` on `no_std`.") - } - fn sign>(&self, msg: &M) -> Option { let mut signature = [0u8; 8]; msg.as_ref().iter() - .chain(rstd::iter::repeat(&42u8)) + .chain(std::iter::repeat(&42u8)) .take(8) .enumerate() .for_each(|(i, v)| { signature[i] = *v; }); @@ -85,7 +109,7 @@ impl app_crypto::RuntimeAppPublic for UintAuthorityId { fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool { let mut msg_signature = [0u8; 8]; msg.as_ref().iter() - .chain(rstd::iter::repeat(&42)) + .chain(std::iter::repeat(&42)) .take(8) .enumerate() .for_each(|(i, v)| { msg_signature[i] = *v; }); @@ -95,24 +119,25 @@ impl app_crypto::RuntimeAppPublic for UintAuthorityId { } impl OpaqueKeys for UintAuthorityId { - type KeyTypeIds = std::iter::Cloned>; + type KeyTypeIdProviders = (); + + fn key_ids() -> &'static [KeyTypeId] { + &[key_types::DUMMY] + } - fn key_ids() -> Self::KeyTypeIds { [key_types::DUMMY].iter().cloned() } - // Unsafe, i know, but it's test code and it's just there because it's really convenient to - // keep `UintAuthorityId` as a u64 under the hood. fn get_raw(&self, _: KeyTypeId) -> &[u8] { - unsafe { - std::slice::from_raw_parts( - &self.0 as *const _ as *const u8, - std::mem::size_of::(), - ) - } + self.as_ref() } + fn get(&self, _: KeyTypeId) -> Option { - self.0.using_encoded(|mut x| T::decode(&mut x)).ok() + self.using_encoded(|mut x| T::decode(&mut x)).ok() } } +impl crate::BoundToRuntimeAppPublic for UintAuthorityId { + type Public = Self; +} + /// Digest item pub type DigestItem = generic::DigestItem; @@ -187,6 +212,7 @@ pub struct ExtrinsicWrapper(Xt); impl traits::Extrinsic for ExtrinsicWrapper { type Call = (); + type SignaturePayload = (); fn is_signed(&self) -> Option { None @@ -239,6 +265,9 @@ impl) -> Self { Block { header, extrinsics } } + fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec { + (header, extrinsics).encode() + } } impl<'a, Xt> Deserialize<'a> for Block where Block: Decode { @@ -270,24 +299,25 @@ impl Debug for TestXt { impl Checkable for TestXt { type Checked = Self; - fn check(self, _: &Context) -> Result { Ok(self) } + fn check(self, _: &Context) -> Result { Ok(self) } } impl traits::Extrinsic for TestXt { type Call = Call; + type SignaturePayload = (u64, Extra); fn is_signed(&self) -> Option { Some(self.0.is_some()) } - fn new_unsigned(_c: Call) -> Option { - None + fn new(c: Call, sig: Option) -> Option { + Some(TestXt(sig, c)) } } impl Applyable for TestXt where Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Dispatchable, Extra: SignedExtension, - Origin: From> + Origin: From>, { type AccountId = u64; type Call = Call; @@ -295,19 +325,23 @@ impl Applyable for TestXt where fn sender(&self) -> Option<&Self::AccountId> { self.0.as_ref().map(|x| &x.0) } /// Checks to see if this is a valid *transaction*. It returns information on it if so. - fn validate>(&self, + #[allow(deprecated)] // Allow ValidateUnsigned + fn validate>( + &self, _info: DispatchInfo, _len: usize, ) -> TransactionValidity { - TransactionValidity::Valid(Default::default()) + Ok(Default::default()) } /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, /// index and sender. - fn dispatch(self, + #[allow(deprecated)] // Allow ValidateUnsigned + fn apply>( + self, info: DispatchInfo, len: usize, - ) -> Result { + ) -> ApplyResult { let maybe_who = if let Some((who, extra)) = self.0 { Extra::pre_dispatch(extra, &who, &self.1, info, len)?; Some(who) @@ -315,7 +349,8 @@ impl Applyable for TestXt where Extra::pre_dispatch_unsigned(&self.1, info, len)?; None }; - Ok(self.1.dispatch(maybe_who.into())) + + Ok(self.1.dispatch(maybe_who.into()).map_err(Into::into)) } } diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 5fc0cb5c5761bf916af38b5aba5743bc31b768b4..195fca26fad190430ad472a720f3f46aae5e753c 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -17,25 +17,26 @@ //! Primitives for the runtime modules. use rstd::prelude::*; -use rstd::{self, result, marker::PhantomData, convert::{TryFrom, TryInto}}; +use rstd::{self, result, marker::PhantomData, convert::{TryFrom, TryInto}, fmt::Debug}; use runtime_io; -#[cfg(feature = "std")] use std::fmt::{Debug, Display}; -#[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned}; -use primitives::{self, Hasher, Blake2Hasher}; -use crate::codec::{Codec, Encode, Decode, HasCompact}; -use crate::transaction_validity::{ValidTransaction, TransactionValidity}; +#[cfg(feature = "std")] +use std::fmt::Display; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize, de::DeserializeOwned}; +use primitives::{self, Hasher, Blake2Hasher, TypeId}; +use crate::codec::{Codec, Encode, Decode}; +use crate::transaction_validity::{ + ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, +}; use crate::generic::{Digest, DigestItem}; use crate::weights::DispatchInfo; -pub use integer_sqrt::IntegerSquareRoot; -pub use num_traits::{ +pub use arithmetic::traits::{ + SimpleArithmetic, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating, SaturatedConversion, Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, - CheckedShl, CheckedShr + CheckedShl, CheckedShr, IntegerSquareRoot }; -use rstd::ops::{ - Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, - RemAssign, Shl, Shr -}; -use crate::AppKey; +use app_crypto::AppKey; +use impl_trait_for_tuples::impl_for_tuples; /// A lazy value. pub trait Lazy { @@ -49,62 +50,126 @@ impl<'a> Lazy<[u8]> for &'a [u8] { fn get(&mut self) -> &[u8] { &**self } } +/// Some type that is able to be collapsed into an account ID. It is not possible to recreate the original value from +/// the account ID. +pub trait IdentifyAccount { + /// The account ID that this can be transformed into. + type AccountId; + /// Transform into an account. + fn into_account(self) -> Self::AccountId; +} + +impl IdentifyAccount for primitives::ed25519::Public { + type AccountId = Self; + fn into_account(self) -> Self { self } +} + +impl IdentifyAccount for primitives::sr25519::Public { + type AccountId = Self; + fn into_account(self) -> Self { self } +} + +impl IdentifyAccount for primitives::ecdsa::Public { + type AccountId = Self; + fn into_account(self) -> Self { self } +} + /// Means of signature verification. pub trait Verify { /// Type of the signer. - type Signer; + type Signer: IdentifyAccount; /// Verify a signature. Return `true` if signature is valid for the value. - fn verify>(&self, msg: L, signer: &Self::Signer) -> bool; + fn verify>(&self, msg: L, signer: &::AccountId) -> bool; } impl Verify for primitives::ed25519::Signature { type Signer = primitives::ed25519::Public; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + fn verify>(&self, mut msg: L, signer: &primitives::ed25519::Public) -> bool { runtime_io::ed25519_verify(self, msg.get(), signer) } } impl Verify for primitives::sr25519::Signature { type Signer = primitives::sr25519::Public; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + fn verify>(&self, mut msg: L, signer: &primitives::sr25519::Public) -> bool { runtime_io::sr25519_verify(self, msg.get(), signer) } } +impl Verify for primitives::ecdsa::Signature { + type Signer = primitives::ecdsa::Public; + fn verify>(&self, mut msg: L, signer: &primitives::ecdsa::Public) -> bool { + match runtime_io::secp256k1_ecdsa_recover_compressed(self.as_ref(), &runtime_io::blake2_256(msg.get())) { + Ok(pubkey) => >::as_ref(signer) == &pubkey[..], + _ => false, + } + } +} + /// Means of signature verification of an application key. pub trait AppVerify { /// Type of the signer. - type Signer; + type AccountId; /// Verify a signature. Return `true` if signature is valid for the value. - fn verify>(&self, msg: L, signer: &Self::Signer) -> bool; + fn verify>(&self, msg: L, signer: &Self::AccountId) -> bool; } impl< S: Verify::Public as app_crypto::AppPublic>::Generic> + From, T: app_crypto::Wraps + app_crypto::AppKey + app_crypto::AppSignature + AsRef + AsMut + From, -> AppVerify for T { - type Signer = ::Public; - fn verify>(&self, msg: L, signer: &Self::Signer) -> bool { +> AppVerify for T where + ::Signer: IdentifyAccount::Signer>, + <::Public as app_crypto::AppPublic>::Generic: + IdentifyAccount::Public as app_crypto::AppPublic>::Generic>, +{ + type AccountId = ::Public; + fn verify>(&self, msg: L, signer: &::Public) -> bool { use app_crypto::IsWrappedBy; let inner: &S = self.as_ref(); - let inner_pubkey = ::Generic::from_ref(&signer); + let inner_pubkey = <::Public as app_crypto::AppPublic>::Generic::from_ref(&signer); Verify::verify(inner, msg, inner_pubkey) } } +/// An error type that indicates that the origin is invalid. +#[derive(Encode, Decode)] +pub struct InvalidOrigin; + +impl From for &'static str { + fn from(_: InvalidOrigin) -> &'static str { + "Invalid origin" + } +} + /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { /// A return type. type Success; /// Perform the origin check. - fn ensure_origin(o: OuterOrigin) -> result::Result { - Self::try_origin(o).map_err(|_| "Invalid origin") + fn ensure_origin(o: OuterOrigin) -> result::Result { + Self::try_origin(o).map_err(|_| InvalidOrigin) } /// Perform the origin check. fn try_origin(o: OuterOrigin) -> result::Result; } +/// An error that indicates that a lookup failed. +#[derive(Encode, Decode)] +pub struct LookupError; + +impl From for &'static str { + fn from(_: LookupError) -> &'static str { + "Can not lookup" + } +} + +impl From for TransactionValidityError { + fn from(_: LookupError) -> Self { + UnknownTransaction::CannotLookup.into() + } +} + /// Means of changing one type into another in a manner dependent on the source type. pub trait Lookup { /// Type to lookup from. @@ -112,7 +177,7 @@ pub trait Lookup { /// Type to lookup into. type Target; /// Attempt a lookup. - fn lookup(&self, s: Self::Source) -> result::Result; + fn lookup(&self, s: Self::Source) -> Result; } /// Means of changing one type into another in a manner dependent on the source type. @@ -120,11 +185,11 @@ pub trait Lookup { /// context. pub trait StaticLookup { /// Type to lookup from. - type Source: Codec + Clone + PartialEq + MaybeDebug; + type Source: Codec + Clone + PartialEq + Debug; /// Type to lookup into. type Target; /// Attempt a lookup. - fn lookup(s: Self::Source) -> result::Result; + fn lookup(s: Self::Source) -> Result; /// Convert from Target back to Source. fn unlookup(t: Self::Target) -> Self::Source; } @@ -132,16 +197,17 @@ pub trait StaticLookup { /// A lookup implementation returning the input value. #[derive(Default)] pub struct IdentityLookup(PhantomData); -impl StaticLookup for IdentityLookup { +impl StaticLookup for IdentityLookup { type Source = T; type Target = T; - fn lookup(x: T) -> result::Result { Ok(x) } + fn lookup(x: T) -> Result { Ok(x) } fn unlookup(x: T) -> T { x } } + impl Lookup for IdentityLookup { type Source = T; type Target = T; - fn lookup(&self, x: T) -> result::Result { Ok(x) } + fn lookup(&self, x: T) -> Result { Ok(x) } } /// Extensible conversion trait. Generic over both source and destination types. @@ -166,120 +232,6 @@ impl> Convert for ConvertInto { fn convert(a: A) -> B { a.into() } } -/// A meta trait for arithmetic. -/// -/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to -/// be able to represent at least `u32` values without loss, hence the trait implies `From` -/// and smaller ints. All other conversions are fallible. -pub trait SimpleArithmetic: - Zero + One + IntegerSquareRoot + - From + From + From + TryInto + TryInto + TryInto + - TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + - UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + - UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + - Add + AddAssign + - Sub + SubAssign + - Mul + MulAssign + - Div + DivAssign + - Rem + RemAssign + - Shl + Shr + - CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + - Saturating + PartialOrd + Ord + Bounded + - HasCompact + Sized -{} -impl + From + From + TryInto + TryInto + TryInto + - TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + - UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + - UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + - UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + - Add + AddAssign + - Sub + SubAssign + - Mul + MulAssign + - Div + DivAssign + - Rem + RemAssign + - Shl + Shr + - CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + - Saturating + PartialOrd + Ord + Bounded + - HasCompact + Sized -> SimpleArithmetic for T {} - -/// Just like `From` except that if the source value is too big to fit into the destination type -/// then it'll saturate the destination. -pub trait UniqueSaturatedFrom: Sized { - /// Convert from a value of `T` into an equivalent instance of `Self`. - fn unique_saturated_from(t: T) -> Self; -} - -/// Just like `Into` except that if the source value is too big to fit into the destination type -/// then it'll saturate the destination. -pub trait UniqueSaturatedInto: Sized { - /// Consume self to return an equivalent value of `T`. - fn unique_saturated_into(self) -> T; -} - -impl + Bounded + Sized> UniqueSaturatedFrom for S { - fn unique_saturated_from(t: T) -> Self { - S::try_from(t).unwrap_or_else(|_| Bounded::max_value()) - } -} - -impl + Sized> UniqueSaturatedInto for S { - fn unique_saturated_into(self) -> T { - self.try_into().unwrap_or_else(|_| Bounded::max_value()) - } -} - -/// Simple trait to use checked mul and max value to give a saturated mul operation over -/// supported types. -pub trait Saturating { - /// Saturated addition - if the product can't fit in the type then just use max-value. - fn saturating_add(self, o: Self) -> Self; - - /// Saturated subtraction - if the product can't fit in the type then just use max-value. - fn saturating_sub(self, o: Self) -> Self; - - /// Saturated multiply - if the product can't fit in the type then just use max-value. - fn saturating_mul(self, o: Self) -> Self; -} - -impl Saturating for T { - fn saturating_add(self, o: Self) -> Self { - ::saturating_add(self, o) - } - fn saturating_sub(self, o: Self) -> Self { - ::saturating_sub(self, o) - } - fn saturating_mul(self, o: Self) -> Self { - self.checked_mul(&o).unwrap_or_else(Bounded::max_value) - } -} - -/// Convenience type to work around the highly unergonomic syntax needed -/// to invoke the functions of overloaded generic traits, in this case -/// `SaturatedFrom` and `SaturatedInto`. -pub trait SaturatedConversion { - /// Convert from a value of `T` into an equivalent instance of `Self`. - /// - /// This just uses `UniqueSaturatedFrom` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn saturated_from(t: T) -> Self where Self: UniqueSaturatedFrom { - >::unique_saturated_from(t) - } - - /// Consume self to return an equivalent value of `T`. - /// - /// This just uses `UniqueSaturatedInto` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn saturated_into(self) -> T where Self: UniqueSaturatedInto { - >::unique_saturated_into(self) - } -} -impl SaturatedConversion for T {} - /// Convenience type to work around the highly unergonomic syntax needed /// to invoke the functions of overloaded generic traits, in this case /// `TryFrom` and `TryInto`. @@ -375,22 +327,20 @@ impl { /// The block is being finalized. Implement to have something happen. fn on_finalize(_n: BlockNumber) {} } -impl OnFinalize for () {} - /// The block initialization trait. Implementing this lets you express what should happen /// for your module when the block is beginning (right before the first extrinsic is executed). +#[impl_for_tuples(30)] pub trait OnInitialize { /// The block is being initialized. Implement to have something happen. fn on_initialize(_n: BlockNumber) {} } -impl OnInitialize for () {} - /// Off-chain computation trait. /// /// Implementing this trait on a module allows you to perform long-running tasks @@ -399,6 +349,7 @@ impl OnInitialize for () {} /// /// NOTE: This function runs off-chain, so it can access the block state, /// but cannot preform any alterations. +#[impl_for_tuples(30)] pub trait OffchainWorker { /// This function is being called on every block. /// @@ -407,53 +358,13 @@ pub trait OffchainWorker { fn generate_extrinsics(_n: BlockNumber) {} } -impl OffchainWorker for () {} - -macro_rules! tuple_impl { - ($first:ident, $($rest:ident,)+) => { - tuple_impl!([$first] [$first] [$($rest)+]); - }; - ([$($direct:ident)+] [$($reverse:ident)+] []) => { - impl< - Number: Copy, - $($direct: OnFinalize),+ - > OnFinalize for ($($direct),+,) { - fn on_finalize(n: Number) { - $($reverse::on_finalize(n);)+ - } - } - impl< - Number: Copy, - $($direct: OnInitialize),+ - > OnInitialize for ($($direct),+,) { - fn on_initialize(n: Number) { - $($direct::on_initialize(n);)+ - } - } - impl< - Number: Copy, - $($direct: OffchainWorker),+ - > OffchainWorker for ($($direct),+,) { - fn generate_extrinsics(n: Number) { - $($direct::generate_extrinsics(n);)+ - } - } - }; - ([$($direct:ident)+] [$($reverse:ident)+] [$first:ident $($rest:ident)*]) => { - tuple_impl!([$($direct)+] [$($reverse)+] []); - tuple_impl!([$($direct)+ $first] [$first $($reverse)+] [$($rest)*]); - }; -} - -#[allow(non_snake_case)] -tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,); - /// Abstraction around hashing -pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stupid bug in the Rust compiler believes derived - // traits must be fulfilled by all type parameters. +// Stupid bug in the Rust compiler believes derived +// traits must be fulfilled by all type parameters. +pub trait Hash: 'static + MaybeSerializeDeserialize + Debug + Clone + Eq + PartialEq { /// The hash type produced. - type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy - + Default + Encode + Decode; + type Output: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash + + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + Encode + Decode; /// The associated hash_db Hasher type. type Hasher: Hasher; @@ -466,18 +377,11 @@ pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stup Encode::using_encoded(s, Self::hash) } - /// Iterator-based version of `ordered_trie_root`. - fn ordered_trie_root< - I: IntoIterator, - A: AsRef<[u8]> - >(input: I) -> Self::Output; + /// The ordered Patricia tree root of the given `input`. + fn ordered_trie_root(input: Vec>) -> Self::Output; - /// The Patricia tree root of the given mapping as an iterator. - fn trie_root< - I: IntoIterator, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]> - >(input: I) -> Self::Output; + /// The Patricia tree root of the given mapping. + fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output; /// Acquire the global storage root. fn storage_root() -> Self::Output; @@ -487,8 +391,8 @@ pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stup } /// Blake2-256 Hash implementation. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(PartialEq, Eq, Clone, primitives::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct BlakeTwo256; impl Hash for BlakeTwo256 { @@ -497,22 +401,19 @@ impl Hash for BlakeTwo256 { fn hash(s: &[u8]) -> Self::Output { runtime_io::blake2_256(s).into() } - fn trie_root< - I: IntoIterator, - A: AsRef<[u8]> + Ord, - B: AsRef<[u8]> - >(input: I) -> Self::Output { - runtime_io::trie_root::(input).into() + + fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { + runtime_io::blake2_256_trie_root(input) } - fn ordered_trie_root< - I: IntoIterator, - A: AsRef<[u8]> - >(input: I) -> Self::Output { - runtime_io::ordered_trie_root::(input).into() + + fn ordered_trie_root(input: Vec>) -> Self::Output { + runtime_io::blake2_256_ordered_trie_root(input) } + fn storage_root() -> Self::Output { runtime_io::storage_root().into() } + fn storage_changes_root(parent_hash: Self::Output) -> Option { runtime_io::storage_changes_root(parent_hash.into()).map(Into::into) } @@ -529,21 +430,25 @@ impl CheckEqual for primitives::H256 { fn check_equal(&self, other: &Self) { use primitives::hexdisplay::HexDisplay; if self != other { - println!("Hash: given={}, expected={}", HexDisplay::from(self.as_fixed_bytes()), HexDisplay::from(other.as_fixed_bytes())); + println!( + "Hash: given={}, expected={}", + HexDisplay::from(self.as_fixed_bytes()), + HexDisplay::from(other.as_fixed_bytes()), + ); } } #[cfg(not(feature = "std"))] fn check_equal(&self, other: &Self) { if self != other { - runtime_io::print("Hash not equal"); - runtime_io::print(self.as_bytes()); - runtime_io::print(other.as_bytes()); + "Hash not equal".print(); + self.as_bytes().print(); + other.as_bytes().print(); } } } -impl CheckEqual for super::generic::DigestItem where H: Encode { +impl CheckEqual for super::generic::DigestItem where H: Encode { #[cfg(feature = "std")] fn check_equal(&self, other: &Self) { if self != other { @@ -554,84 +459,44 @@ impl CheckEqual for super::generic::DigestItem MaybeSerializeDebugButNotDeserialize for T {} - -/// A type that implements Serialize and Debug when in std environment. -#[cfg(not(feature = "std"))] -pub trait MaybeSerializeDebugButNotDeserialize {} -#[cfg(not(feature = "std"))] -impl MaybeSerializeDebugButNotDeserialize for T {} - -/// A type that implements Serialize when in std environment. -#[cfg(feature = "std")] -pub trait MaybeSerialize: Serialize {} -#[cfg(feature = "std")] -impl MaybeSerialize for T {} - -/// A type that implements Serialize when in std environment. -#[cfg(not(feature = "std"))] -pub trait MaybeSerialize {} -#[cfg(not(feature = "std"))] -impl MaybeSerialize for T {} - -/// A type that implements Serialize, DeserializeOwned and Debug when in std environment. -#[cfg(feature = "std")] -pub trait MaybeSerializeDebug: Serialize + DeserializeOwned + Debug {} -#[cfg(feature = "std")] -impl MaybeSerializeDebug for T {} - -/// A type that implements Serialize, DeserializeOwned and Debug when in std environment. -#[cfg(not(feature = "std"))] -pub trait MaybeSerializeDebug {} -#[cfg(not(feature = "std"))] -impl MaybeSerializeDebug for T {} - -/// A type that implements Debug when in std environment. -#[cfg(feature = "std")] -pub trait MaybeDebug: Debug {} -#[cfg(feature = "std")] -impl MaybeDebug for T {} - -/// A type that implements Debug when in std environment. -#[cfg(not(feature = "std"))] -pub trait MaybeDebug {} -#[cfg(not(feature = "std"))] -impl MaybeDebug for T {} +macro_rules! impl_maybe_marker { + ( $( $(#[$doc:meta])+ $trait_name:ident: $($trait_bound:path),+ );+ ) => { + $( + $(#[$doc])+ + #[cfg(feature = "std")] + pub trait $trait_name: $($trait_bound +)+ {} + #[cfg(feature = "std")] + impl $trait_name for T {} + + $(#[$doc])+ + #[cfg(not(feature = "std"))] + pub trait $trait_name {} + #[cfg(not(feature = "std"))] + impl $trait_name for T {} + )+ + } +} -/// A type that implements Display when in std environment. -#[cfg(feature = "std")] -pub trait MaybeDisplay: Display {} -#[cfg(feature = "std")] -impl MaybeDisplay for T {} +impl_maybe_marker!( + /// A type that implements Display when in std environment. + MaybeDisplay: Display; -/// A type that implements Display when in std environment. -#[cfg(not(feature = "std"))] -pub trait MaybeDisplay {} -#[cfg(not(feature = "std"))] -impl MaybeDisplay for T {} + /// A type that implements Hash when in std environment. + MaybeHash: rstd::hash::Hash; -/// A type that implements Hash when in std environment. -#[cfg(feature = "std")] -pub trait MaybeHash: ::rstd::hash::Hash {} -#[cfg(feature = "std")] -impl MaybeHash for T {} + /// A type that implements Serialize when in std environment. + MaybeSerialize: Serialize; -/// A type that implements Hash when in std environment. -#[cfg(not(feature = "std"))] -pub trait MaybeHash {} -#[cfg(not(feature = "std"))] -impl MaybeHash for T {} + /// A type that implements Serialize, DeserializeOwned and Debug when in std environment. + MaybeSerializeDeserialize: DeserializeOwned, Serialize +); /// A type that provides a randomness beacon. pub trait RandomnessBeacon { @@ -650,8 +515,8 @@ pub trait RandomnessBeacon { } /// A type that can be used in runtime structures. -pub trait Member: Send + Sync + Sized + MaybeDebug + Eq + PartialEq + Clone + 'static {} -impl Member for T {} +pub trait Member: Send + Sync + Sized + Debug + Eq + PartialEq + Clone + 'static {} +impl Member for T {} /// Determine if a `MemberId` is a valid member. pub trait IsMember { @@ -660,15 +525,17 @@ pub trait IsMember { } /// Something which fulfills the abstract idea of a Substrate header. It has types for a `Number`, -/// a `Hash` and a `Digest`. It provides access to an `extrinsics_root`, `state_root` and +/// a `Hash` and a `Hashing`. It provides access to an `extrinsics_root`, `state_root` and /// `parent_hash`, as well as a `digest` and a block `number`. /// /// You can also create a `new` one from those fields. -pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDeserialize + 'static { +pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerialize + Debug + 'static { /// Header number. - type Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec; + type Number: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash + + Copy + MaybeDisplay + SimpleArithmetic + Codec; /// Header hash type - type Hash: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; + type Hash: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash + + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; /// Hashing algorithm type Hashing: Hash; @@ -716,13 +583,14 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe /// `Extrinsic` piece of information as well as a `Header`. /// /// You can get an iterator over each of the `extrinsics` and retrieve the `header`. -pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDeserialize + 'static { +pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerialize + Debug + 'static { /// Type of extrinsics. type Extrinsic: Member + Codec + Extrinsic + MaybeSerialize; /// Header type. type Header: Header; /// Block hash type. - type Hash: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; + type Hash: Member + MaybeSerializeDeserialize + Debug + rstd::hash::Hash + + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; /// Returns a reference to the header. fn header(&self) -> &Self::Header; @@ -736,6 +604,8 @@ pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDes fn hash(&self) -> Self::Hash { <::Hashing as Hash>::hash_of(self.header()) } + /// Create an encoded block from the given `header` and `extrinsics` without requiring to create an instance. + fn encode_from(header: &Self::Header, extrinsics: &[Self::Extrinsic]) -> Vec; } /// Something that acts like an `Extrinsic`. @@ -743,13 +613,24 @@ pub trait Extrinsic: Sized { /// The function call. type Call; + /// The payload we carry for signed extrinsics. + /// + /// Usually it will contain a `Signature` and + /// may include some additional data that are specific to signed + /// extrinsics. + type SignaturePayload; + /// Is this `Extrinsic` signed? /// If no information are available about signed/unsigned, `None` should be returned. fn is_signed(&self) -> Option { None } - /// New instance of an unsigned extrinsic aka "inherent". `None` if this is an opaque - /// extrinsic type. - fn new_unsigned(_call: Self::Call) -> Option { None } + /// Create new instance of the extrinsic. + /// + /// Extrinsics can be split into: + /// 1. Inherents (no signature; created by validators during block production) + /// 2. Unsigned Transactions (no signature; represent "system calls" or other special kinds of calls) + /// 3. Signed Transactions (with signature; a regular transactions with known origin) + fn new(_call: Self::Call, _signed_data: Option) -> Option { None } } /// Extract the hashing type for a block. @@ -770,7 +651,7 @@ pub trait Checkable: Sized { type Checked; /// Check self, given an instance of Context. - fn check(self, c: &Context) -> Result; + fn check(self, c: &Context) -> Result; } /// A "checkable" piece of information, used by the standard Substrate Executive in order to @@ -782,61 +663,21 @@ pub trait BlindCheckable: Sized { type Checked; /// Check self. - fn check(self) -> Result; + fn check(self) -> Result; } // Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`. impl Checkable for T { type Checked = ::Checked; - fn check(self, _c: &Context) -> Result { - BlindCheckable::check(self) - } -} - -/// An abstract error concerning an attempt to verify, check or dispatch the transaction. This -/// cannot be more concrete because it's designed to work reasonably well over a broad range of -/// possible transaction types. -#[cfg_attr(feature = "std", derive(Debug))] -pub enum DispatchError { - /// General error to do with the inability to pay some fees (e.g. account balance too low). - Payment, - - /// General error to do with the exhaustion of block resources. - Exhausted, - - /// General error to do with the permissions of the sender. - NoPermission, - - /// General error to do with the state of the system in general. - BadState, - - /// General error to do with the transaction being outdated (e.g. nonce too low). - Stale, - /// General error to do with the transaction not yet being valid (e.g. nonce too high). - Future, - - /// General error to do with the transaction's proofs (e.g. signature). - BadProof, -} - -impl From for i8 { - fn from(e: DispatchError) -> i8 { - match e { - DispatchError::Payment => -64, - DispatchError::Exhausted => -65, - DispatchError::NoPermission => -66, - DispatchError::BadState => -67, - DispatchError::Stale => -68, - DispatchError::Future => -69, - DispatchError::BadProof => -70, - } + fn check(self, _c: &Context) -> Result { + BlindCheckable::check(self) } } /// Result of a module function call; either nothing (functions are only called for "side effects") /// or an error message. -pub type DispatchResult = result::Result<(), &'static str>; +pub type DispatchResult = result::Result<(), Error>; /// A lazy call (module function and argument values) that can be executed via its `dispatch` /// method. @@ -847,15 +688,15 @@ pub trait Dispatchable { type Origin; /// ... type Trait; + /// The error type returned by this dispatchable. + type Error: Into; /// Actually dispatch this call and result the result of it. - fn dispatch(self, origin: Self::Origin) -> DispatchResult; + fn dispatch(self, origin: Self::Origin) -> DispatchResult; } /// Means by which a transaction may be extended. This type embodies both the data and the logic /// that should be additionally associated with the transaction. It should be plain old data. -pub trait SignedExtension: - Codec + MaybeDebug + Sync + Send + Clone + Eq + PartialEq -{ +pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq { /// The type which encodes the sender identity. type AccountId; @@ -871,133 +712,152 @@ pub trait SignedExtension: /// Construct any additional data that should be in the signed payload of the transaction. Can /// also perform any pre-signature-verification checks and return an error if needed. - fn additional_signed(&self) -> Result; + fn additional_signed(&self) -> Result; /// Validate a signed transaction for the transaction queue. + /// + /// This function can be called frequently by the transaction queue, + /// to obtain transaction validity against current state. + /// It should perform all checks that determine a valid transaction, + /// that can pay for it's execution and quickly eliminate ones + /// that are stale or incorrect. + /// + /// Make sure to perform the same checks in `pre_dispatch` function. fn validate( &self, _who: &Self::AccountId, _call: &Self::Call, _info: DispatchInfo, _len: usize, - ) -> Result { - Ok(Default::default()) + ) -> TransactionValidity { + Ok(ValidTransaction::default()) } /// Do any pre-flight stuff for a signed transaction. + /// + /// Note this function by default delegates to `validate`, so that + /// all checks performed for the transaction queue are also performed during + /// the dispatch phase (applying the extrinsic). + /// + /// If you ever override this function, you need to make sure to always + /// perform the same validation as in `validate`. fn pre_dispatch( self, who: &Self::AccountId, call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| Self::Pre::default()) + ) -> Result { + self.validate(who, call, info, len) + .map(|_| Self::Pre::default()) + .map_err(Into::into) } - /// Validate an unsigned transaction for the transaction queue. Normally the default - /// implementation is fine since `ValidateUnsigned` is a better way of recognising and - /// validating unsigned transactions. + /// Validate an unsigned transaction for the transaction queue. + /// + /// This function can be called frequently by the transaction queue, + /// to obtain transaction validity against current state. + /// It should perform all checks that determine a valid unsigned transaction, + /// and quickly eliminate ones that are stale or incorrect. + /// + /// Make sure to perform the same checks in `pre_dispatch_unsigned` function. fn validate_unsigned( _call: &Self::Call, _info: DispatchInfo, _len: usize, - ) -> Result { Ok(Default::default()) } + ) -> TransactionValidity { + Ok(ValidTransaction::default()) + } /// Do any pre-flight stuff for a unsigned transaction. + /// + /// Note this function by default delegates to `validate_unsigned`, so that + /// all checks performed for the transaction queue are also performed during + /// the dispatch phase (applying the extrinsic). + /// + /// If you ever override this function, you need to make sure to always + /// perform the same validation as in `validate_unsigned`. fn pre_dispatch_unsigned( call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { - Self::validate_unsigned(call, info, len).map(|_| Self::Pre::default()) + ) -> Result { + Self::validate_unsigned(call, info, len) + .map(|_| Self::Pre::default()) + .map_err(Into::into) } /// Do any post-flight stuff for a transaction. - fn post_dispatch( - _pre: Self::Pre, - _info: DispatchInfo, - _len: usize, - ) { } + fn post_dispatch(_pre: Self::Pre, _info: DispatchInfo, _len: usize) { } } -macro_rules! tuple_impl_indexed { - ($first:ident, $($rest:ident,)+ ; $first_index:tt, $($rest_index:tt,)+) => { - tuple_impl_indexed!([$first] [$($rest)+] ; [$first_index,] [$($rest_index,)+]); - }; - ([$($direct:ident)+] ; [$($index:tt,)+]) => { - impl< - AccountId, - Call, - $($direct: SignedExtension),+ - > SignedExtension for ($($direct),+,) { - type AccountId = AccountId; - type Call = Call; - type AdditionalSigned = ($($direct::AdditionalSigned,)+); - type Pre = ($($direct::Pre,)+); - fn additional_signed(&self) -> Result { - Ok(( $(self.$index.additional_signed()?,)+ )) - } - fn validate( - &self, - who: &Self::AccountId, - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result { - let aggregator = vec![$(<$direct as SignedExtension>::validate(&self.$index, who, call, info, len)?),+]; - Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a))) - } - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result { - Ok(($(self.$index.pre_dispatch(who, call, info, len)?,)+)) - } - fn validate_unsigned( - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result { - let aggregator = vec![$($direct::validate_unsigned(call, info, len)?),+]; - Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a))) - } - fn pre_dispatch_unsigned( - call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> Result { - Ok(($($direct::pre_dispatch_unsigned(call, info, len)?,)+)) - } - fn post_dispatch( - pre: Self::Pre, - info: DispatchInfo, - len: usize, - ) { - $($direct::post_dispatch(pre.$index, info, len);)+ - } - } +/// An error that is returned by a dispatchable function of a module. +pub trait ModuleDispatchError { + /// Convert this error to an `u8`. + /// + /// The `u8` corresponds to the index of the variant in the error enum. + fn as_u8(&self) -> u8; - }; - ([$($direct:ident)+] [] ; [$($index:tt,)+] []) => { - tuple_impl_indexed!([$($direct)+] ; [$($index,)+]); - }; - ( - [$($direct:ident)+] [$first:ident $($rest:ident)*] - ; - [$($index:tt,)+] [$first_index:tt, $($rest_index:tt,)*] - ) => { - tuple_impl_indexed!([$($direct)+] ; [$($index,)+]); - tuple_impl_indexed!([$($direct)+ $first] [$($rest)*] ; [$($index,)+ $first_index,] [$($rest_index,)*]); - }; + /// Convert the error to a `&'static str`. + fn as_str(&self) -> &'static str; } -// TODO: merge this into `tuple_impl` once codec supports `trait Codec` for longer tuple lengths. #3152 -#[allow(non_snake_case)] -tuple_impl_indexed!(A, B, C, D, E, F, G, H, I, J, ; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,); +#[impl_for_tuples(1, 12)] +impl SignedExtension for Tuple { + for_tuples!( where #( Tuple: SignedExtension )* ); + type AccountId = AccountId; + type Call = Call; + for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); + for_tuples!( type Pre = ( #( Tuple::Pre ),* ); ); + + fn additional_signed(&self) -> Result { + Ok(for_tuples!( ( #( Tuple.additional_signed()? ),* ) )) + } + + fn validate( + &self, + who: &Self::AccountId, + call: &Self::Call, + info: DispatchInfo, + len: usize, + ) -> TransactionValidity { + let valid = ValidTransaction::default(); + for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info, len)?); )* ); + Ok(valid) + } + + fn pre_dispatch(self, who: &Self::AccountId, call: &Self::Call, info: DispatchInfo, len: usize) + -> Result + { + Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info, len)? ),* ) )) + } + + fn validate_unsigned( + call: &Self::Call, + info: DispatchInfo, + len: usize, + ) -> TransactionValidity { + let valid = ValidTransaction::default(); + for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info, len)?); )* ); + Ok(valid) + } + + fn pre_dispatch_unsigned( + call: &Self::Call, + info: DispatchInfo, + len: usize, + ) -> Result { + Ok(for_tuples!( ( #( Tuple::pre_dispatch_unsigned(call, info, len)? ),* ) )) + } + + fn post_dispatch( + pre: Self::Pre, + info: DispatchInfo, + len: usize, + ) { + for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, len); )* ) + } +} /// Only for bare bone testing when you don't care about signed extensions at all. #[cfg(feature = "std")] @@ -1006,7 +866,7 @@ impl SignedExtension for () { type AdditionalSigned = (); type Call = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } } /// An "executable" piece of information, used by the standard Substrate Executive in order to @@ -1026,17 +886,21 @@ pub trait Applyable: Sized + Send + Sync { fn sender(&self) -> Option<&Self::AccountId>; /// Checks to see if this is a valid *transaction*. It returns information on it if so. - fn validate>(&self, + #[allow(deprecated)] // Allow ValidateUnsigned + fn validate>( + &self, info: DispatchInfo, len: usize, ) -> TransactionValidity; /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, /// index and sender. - fn dispatch(self, + #[allow(deprecated)] // Allow ValidateUnsigned + fn apply>( + self, info: DispatchInfo, len: usize, - ) -> Result; + ) -> crate::ApplyResult; } /// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. @@ -1095,11 +959,33 @@ pub trait RuntimeApiInfo { const VERSION: u32; } -/// Something that can validate unsigned extrinsics. +/// Something that can validate unsigned extrinsics for the transaction pool. +/// +/// Note that any checks done here are only used for determining the validity of +/// the transaction for the transaction pool. +/// During block execution phase one need to perform the same checks anyway, +/// since this function is not being called. +#[deprecated(note = "Use SignedExtensions instead.")] pub trait ValidateUnsigned { /// The call to validate type Call; + /// Validate the call right before dispatch. + /// + /// This method should be used to prevent transactions already in the pool + /// (i.e. passing `validate_unsigned`) from being included in blocks + /// in case we know they now became invalid. + /// + /// By default it's a good idea to call `validate_unsigned` from within + /// this function again to make sure we never include an invalid transaction. + /// + /// Changes made to storage WILL be persisted if the call returns `Ok`. + fn pre_dispatch(call: &Self::Call) -> Result<(), crate::ApplyError> { + Self::validate_unsigned(call) + .map(|_| ()) + .map_err(Into::into) + } + /// Return the validity of the call /// /// This doesn't execute any side-effects; it merely checks @@ -1112,11 +998,11 @@ pub trait ValidateUnsigned { /// Opaque datatype that may be destructured into a series of raw byte slices (which represent /// individual keys). pub trait OpaqueKeys: Clone { - /// An iterator over the type IDs of keys that this holds. - type KeyTypeIds: IntoIterator; + /// Types bound to this opaque keys that provide the key type ids returned. + type KeyTypeIdProviders; - /// Return an iterator over the key-type IDs supported by this set. - fn key_ids() -> Self::KeyTypeIds; + /// Return the key-type IDs supported by this set. + fn key_ids() -> &'static [crate::KeyTypeId]; /// Get the raw bytes of key with key-type ID `i`. fn get_raw(&self, i: super::KeyTypeId) -> &[u8]; /// Get the decoded key with index `i`. @@ -1172,12 +1058,6 @@ pub trait AccountIdConversion: Sized { fn try_from_sub_account(x: &AccountId) -> Option<(Self, S)>; } -/// Provide a simple 4 byte identifier for a type. -pub trait TypeId { - /// Simple 4 byte identifier. - const TYPE_ID: [u8; 4]; -} - /// Format is TYPE_ID ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing zeroes to /// fill AccountId. impl AccountIdConversion for Id { @@ -1201,76 +1081,6 @@ impl AccountIdConver } } -#[cfg(test)] -mod tests { - use super::AccountIdConversion; - use crate::codec::{Encode, Decode, Input}; - - #[derive(Encode, Decode, Default, PartialEq, Debug)] - struct U32Value(u32); - impl super::TypeId for U32Value { - const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca]; - } - // cafef00d - - #[derive(Encode, Decode, Default, PartialEq, Debug)] - struct U16Value(u16); - impl super::TypeId for U16Value { - const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0]; - } - // f00dcafe - - type AccountId = u64; - - #[test] - fn into_account_should_work() { - let r: AccountId = U32Value::into_account(&U32Value(0xdeadbeef)); - assert_eq!(r, 0x_deadbeef_cafef00d); - } - - #[test] - fn try_from_account_should_work() { - let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64); - assert_eq!(r.unwrap(), U32Value(0xdeadbeef)); - } - - #[test] - fn into_account_with_fill_should_work() { - let r: AccountId = U16Value::into_account(&U16Value(0xc0da)); - assert_eq!(r, 0x_0000_c0da_f00dcafe); - } - - #[test] - fn try_from_account_with_fill_should_work() { - let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64); - assert_eq!(r.unwrap(), U16Value(0xc0da)); - } - - #[test] - fn bad_try_from_account_should_fail() { - let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64); - assert!(r.is_none()); - let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64); - assert!(r.is_none()); - } - - #[test] - fn trailing_zero_should_work() { - let mut t = super::TrailingZeroInput(&[1, 2, 3]); - assert_eq!(t.remaining_len(), Ok(None)); - let mut buffer = [0u8; 2]; - assert_eq!(t.read(&mut buffer), Ok(())); - assert_eq!(t.remaining_len(), Ok(None)); - assert_eq!(buffer, [1, 2]); - assert_eq!(t.read(&mut buffer), Ok(())); - assert_eq!(t.remaining_len(), Ok(None)); - assert_eq!(buffer, [3, 0]); - assert_eq!(t.read(&mut buffer), Ok(())); - assert_eq!(t.remaining_len(), Ok(None)); - assert_eq!(buffer, [0, 0]); - } -} - /// Calls a given macro a number of times with a set of fixed params and an incrementing numeral. /// e.g. /// ```nocompile @@ -1292,21 +1102,25 @@ macro_rules! count { } /// Implement `OpaqueKeys` for a described struct. -/// Would be much nicer for this to be converted to `derive` code. /// -/// Every field type must be equivalent implement `as_ref()`, which is expected -/// to hold the standard SCALE-encoded form of that key. This is typically -/// just the bytes of the key. +/// Every field type must implement [`BoundToRuntimeAppPublic`](crate::BoundToRuntimeAppPublic). +/// `KeyTypeIdProviders` is set to the types given as fields. /// /// ```rust -/// use sr_primitives::{impl_opaque_keys, key_types, KeyTypeId, app_crypto::{sr25519, ed25519}}; +/// use sr_primitives::{ +/// impl_opaque_keys, KeyTypeId, BoundToRuntimeAppPublic, app_crypto::{sr25519, ed25519} +/// }; +/// +/// pub struct KeyModule; +/// impl BoundToRuntimeAppPublic for KeyModule { type Public = ed25519::AppPublic; } +/// +/// pub struct KeyModule2; +/// impl BoundToRuntimeAppPublic for KeyModule2 { type Public = sr25519::AppPublic; } /// /// impl_opaque_keys! { /// pub struct Keys { -/// #[id(key_types::ED25519)] -/// pub ed25519: ed25519::AppPublic, -/// #[id(key_types::SR25519)] -/// pub sr25519: sr25519::AppPublic, +/// pub key_module: KeyModule, +/// pub key_module2: KeyModule2, /// } /// } /// ``` @@ -1315,16 +1129,20 @@ macro_rules! impl_opaque_keys { ( pub struct $name:ident { $( - #[id($key_id:expr)] pub $field:ident: $type:ty, )* } ) => { - #[derive(Default, Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug, $crate::serde::Serialize, $crate::serde::Deserialize))] + #[derive( + Default, Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + #[cfg_attr(feature = "std", derive($crate::serde::Serialize, $crate::serde::Deserialize))] pub struct $name { $( - pub $field: $type, + pub $field: <$type as $crate::BoundToRuntimeAppPublic>::Public, )* } @@ -1337,7 +1155,11 @@ macro_rules! impl_opaque_keys { pub fn generate(seed: Option<&str>) -> $crate::rstd::vec::Vec { let keys = Self{ $( - $field: <$type as $crate::app_crypto::RuntimeAppPublic>::generate_pair(seed), + $field: < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::generate_pair(seed), )* }; $crate::codec::Encode::encode(&keys) @@ -1345,20 +1167,167 @@ macro_rules! impl_opaque_keys { } impl $crate::traits::OpaqueKeys for $name { - type KeyTypeIds = $crate::rstd::iter::Cloned< - $crate::rstd::slice::Iter<'static, $crate::KeyTypeId> - >; + type KeyTypeIdProviders = ( $( $type, )* ); - fn key_ids() -> Self::KeyTypeIds { - [ $($key_id),* ].iter().cloned() + fn key_ids() -> &'static [$crate::KeyTypeId] { + &[ + $( + < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::ID + ),* + ] } fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] { match i { - $( i if i == $key_id => self.$field.as_ref(), )* + $( + i if i == < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::ID => + self.$field.as_ref(), + )* _ => &[], } } } }; } + +/// Trait for things which can be printed from the runtime. +pub trait Printable { + /// Print the object. + fn print(&self); +} + +impl Printable for u8 { + fn print(&self) { + (*self as u64).print() + } +} + +impl Printable for u32 { + fn print(&self) { + (*self as u64).print() + } +} + +impl Printable for usize { + fn print(&self) { + (*self as u64).print() + } +} + +impl Printable for u64 { + fn print(&self) { + runtime_io::print_num(*self); + } +} + +impl Printable for &[u8] { + fn print(&self) { + runtime_io::print_hex(self); + } +} + +impl Printable for &str { + fn print(&self) { + runtime_io::print_utf8(self.as_bytes()); + } +} + +#[impl_for_tuples(1, 12)] +impl Printable for Tuple { + fn print(&self) { + for_tuples!( #( Tuple.print(); )* ) + } +} + +#[cfg(test)] +mod tests { + use super::AccountIdConversion; + use crate::codec::{Encode, Decode, Input}; + + mod t { + use primitives::crypto::KeyTypeId; + use app_crypto::{app_crypto, sr25519}; + app_crypto!(sr25519, KeyTypeId(*b"test")); + } + + #[test] + fn app_verify_works() { + use t::*; + use super::AppVerify; + + let s = Signature::default(); + let _ = s.verify(&[0u8; 100][..], &Public::default()); + } + + #[derive(Encode, Decode, Default, PartialEq, Debug)] + struct U32Value(u32); + impl super::TypeId for U32Value { + const TYPE_ID: [u8; 4] = [0x0d, 0xf0, 0xfe, 0xca]; + } + // cafef00d + + #[derive(Encode, Decode, Default, PartialEq, Debug)] + struct U16Value(u16); + impl super::TypeId for U16Value { + const TYPE_ID: [u8; 4] = [0xfe, 0xca, 0x0d, 0xf0]; + } + // f00dcafe + + type AccountId = u64; + + #[test] + fn into_account_should_work() { + let r: AccountId = U32Value::into_account(&U32Value(0xdeadbeef)); + assert_eq!(r, 0x_deadbeef_cafef00d); + } + + #[test] + fn try_from_account_should_work() { + let r = U32Value::try_from_account(&0x_deadbeef_cafef00d_u64); + assert_eq!(r.unwrap(), U32Value(0xdeadbeef)); + } + + #[test] + fn into_account_with_fill_should_work() { + let r: AccountId = U16Value::into_account(&U16Value(0xc0da)); + assert_eq!(r, 0x_0000_c0da_f00dcafe); + } + + #[test] + fn try_from_account_with_fill_should_work() { + let r = U16Value::try_from_account(&0x0000_c0da_f00dcafe_u64); + assert_eq!(r.unwrap(), U16Value(0xc0da)); + } + + #[test] + fn bad_try_from_account_should_fail() { + let r = U16Value::try_from_account(&0x0000_c0de_baadcafe_u64); + assert!(r.is_none()); + let r = U16Value::try_from_account(&0x0100_c0da_f00dcafe_u64); + assert!(r.is_none()); + } + + #[test] + fn trailing_zero_should_work() { + let mut t = super::TrailingZeroInput(&[1, 2, 3]); + assert_eq!(t.remaining_len(), Ok(None)); + let mut buffer = [0u8; 2]; + assert_eq!(t.read(&mut buffer), Ok(())); + assert_eq!(t.remaining_len(), Ok(None)); + assert_eq!(buffer, [1, 2]); + assert_eq!(t.read(&mut buffer), Ok(())); + assert_eq!(t.remaining_len(), Ok(None)); + assert_eq!(buffer, [3, 0]); + assert_eq!(t.read(&mut buffer), Ok(())); + assert_eq!(t.remaining_len(), Ok(None)); + assert_eq!(buffer, [0, 0]); + } +} diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 4d5d53baf199f103a877198b824dbe94a42634d4..3e765215b979a950d9b37a083415b24f56c09766 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -17,8 +17,8 @@ //! Transaction validity interface. use rstd::prelude::*; -use crate::codec::{Encode, Decode, Error}; -use crate::traits::DispatchError; +use crate::codec::{Encode, Decode}; +use crate::RuntimeDebug; /// Priority for a transaction. Additive. Higher is better. pub type TransactionPriority = u64; @@ -30,30 +30,151 @@ pub type TransactionLongevity = u64; /// Tag for a transaction. No two transactions with the same tag should be placed on-chain. pub type TransactionTag = Vec; -/// Information on a transaction's validity and, if valid, on how it relates to other transactions. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Debug))] -pub enum TransactionValidity { - /// Transaction is invalid. Details are described by the error code. - Invalid(i8), - /// Transaction is valid. - Valid(ValidTransaction), +/// An invalid transaction validity. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize))] +pub enum InvalidTransaction { + /// The call of the transaction is not expected. + Call, + /// General error to do with the inability to pay some fees (e.g. account balance too low). + Payment, + /// General error to do with the transaction not yet being valid (e.g. nonce too high). + Future, + /// General error to do with the transaction being outdated (e.g. nonce too low). + Stale, + /// General error to do with the transaction's proofs (e.g. signature). + BadProof, + /// The transaction birth block is ancient. + AncientBirthBlock, + /// The transaction would exhaust the resources of current block. + /// + /// The transaction might be valid, but there are not enough resources left in the current block. + ExhaustsResources, + /// Any other custom invalid validity that is not covered by this enum. + Custom(u8), +} + +impl InvalidTransaction { + /// Returns if the reason for the invalidity was block resource exhaustion. + pub fn exhausted_resources(&self) -> bool { + match self { + Self::ExhaustsResources => true, + _ => false, + } + } +} + +impl From for &'static str { + fn from(invalid: InvalidTransaction) -> &'static str { + match invalid { + InvalidTransaction::Call => "Transaction call is not expected", + InvalidTransaction::Future => "Transaction will be valid in the future", + InvalidTransaction::Stale => "Transaction is outdated", + InvalidTransaction::BadProof => "Transaction has a bad signature", + InvalidTransaction::AncientBirthBlock => "Transaction has an ancient birth block", + InvalidTransaction::ExhaustsResources => + "Transaction would exhausts the block limits", + InvalidTransaction::Payment => + "Inability to pay some fees (e.g. account balance too low)", + InvalidTransaction::Custom(_) => "InvalidTransaction custom error", + } + } +} + +/// An unknown transaction validity. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize))] +pub enum UnknownTransaction { + /// Could not lookup some information that is required to validate the transaction. + CannotLookup, + /// No validator found for the given unsigned transaction. + NoUnsignedValidator, + /// Any other custom unknown validity that is not covered by this enum. + Custom(u8), +} + +impl From for &'static str { + fn from(unknown: UnknownTransaction) -> &'static str { + match unknown { + UnknownTransaction::CannotLookup => + "Could not lookup information required to validate the transaction", + UnknownTransaction::NoUnsignedValidator => + "Could not find an unsigned validator for the unsigned transaction", + UnknownTransaction::Custom(_) => "UnknownTransaction custom error", + } + } +} + +/// Errors that can occur while checking the validity of a transaction. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize))] +pub enum TransactionValidityError { + /// The transaction is invalid. + Invalid(InvalidTransaction), /// Transaction validity can't be determined. - Unknown(i8), + Unknown(UnknownTransaction), +} + +impl TransactionValidityError { + /// Returns `true` if the reason for the error was block resource exhaustion. + pub fn exhausted_resources(&self) -> bool { + match self { + Self::Invalid(e) => e.exhausted_resources(), + Self::Unknown(_) => false, + } + } } -impl From> for TransactionValidity { - fn from(r: Result) -> Self { - match r { - Ok(v) => TransactionValidity::Valid(v), - Err(e) => TransactionValidity::Invalid(e.into()), +impl From for &'static str { + fn from(err: TransactionValidityError) -> &'static str { + match err { + TransactionValidityError::Invalid(invalid) => invalid.into(), + TransactionValidityError::Unknown(unknown) => unknown.into(), } } } +impl From for TransactionValidityError { + fn from(err: InvalidTransaction) -> Self { + TransactionValidityError::Invalid(err) + } +} + +impl From for TransactionValidityError { + fn from(err: UnknownTransaction) -> Self { + TransactionValidityError::Unknown(err) + } +} + +impl From for crate::ApplyError { + fn from(invalid: InvalidTransaction) -> crate::ApplyError { + TransactionValidityError::from(invalid).into() + } +} + +impl From for crate::ApplyError { + fn from(unknown: UnknownTransaction) -> crate::ApplyError { + TransactionValidityError::from(unknown).into() + } +} + +/// Information on a transaction's validity and, if valid, on how it relates to other transactions. +pub type TransactionValidity = Result; + +impl Into for InvalidTransaction { + fn into(self) -> TransactionValidity { + Err(self.into()) + } +} + +impl Into for UnknownTransaction { + fn into(self) -> TransactionValidity { + Err(self.into()) + } +} + /// Information concerning a valid transaction. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] pub struct ValidTransaction { /// Priority of the transaction. /// @@ -112,49 +233,13 @@ impl ValidTransaction { } } -impl Decode for TransactionValidity { - fn decode(value: &mut I) -> Result { - match value.read_byte()? { - 0 => Ok(TransactionValidity::Invalid(i8::decode(value)?)), - 1 => { - let priority = TransactionPriority::decode(value)?; - let requires = Vec::decode(value)?; - let provides = Vec::decode(value)?; - let longevity = TransactionLongevity::decode(value)?; - let propagate = bool::decode(value).unwrap_or(true); - - Ok(TransactionValidity::Valid(ValidTransaction { - priority, requires, provides, longevity, propagate, - })) - }, - 2 => Ok(TransactionValidity::Unknown(i8::decode(value)?)), - _ => Err("Invalid transaction validity variant".into()), - } - } -} - #[cfg(test)] mod tests { use super::*; - #[test] - fn should_decode_with_backward_compat() { - let old_encoding = vec![ - 1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0 - ]; - - assert_eq!(TransactionValidity::decode(&mut &*old_encoding), Ok(TransactionValidity::Valid(ValidTransaction { - priority: 5, - requires: vec![vec![1, 2, 3, 4]], - provides: vec![vec![4, 5, 6]], - longevity: 42, - propagate: true, - }))); - } - #[test] fn should_encode_and_decode() { - let v = TransactionValidity::Valid(ValidTransaction { + let v: TransactionValidity = Ok(ValidTransaction { priority: 5, requires: vec![vec![1, 2, 3, 4]], provides: vec![vec![4, 5, 6]], @@ -165,7 +250,7 @@ mod tests { let encoded = v.encode(); assert_eq!( encoded, - vec![1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, 0] + vec![0, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, 0] ); // decode back diff --git a/core/sr-primitives/src/weights.rs b/core/sr-primitives/src/weights.rs index 45ac59e0d5489c5ded68bd14c1344e8a9e7f19ff..088f13244eb31d3943719f82a8f58492b8db834c 100644 --- a/core/sr-primitives/src/weights.rs +++ b/core/sr-primitives/src/weights.rs @@ -14,28 +14,58 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Primitives for transaction weighting. +//! # Primitives for transaction weighting. //! -//! Each dispatch function within `decl_module!` can have an optional `#[weight = $x]` attribute. -//! `$x` can be any type that implements the `ClassifyDispatch` and `WeighData` traits. By -//! default, All transactions are annotated with `#[weight = SimpleDispatchInfo::default()]`. +//! All dispatchable functions defined in `decl_module!` must provide two trait implementations: +//! - [`WeightData`]: To determine the weight of the dispatch. +//! - [`ClassifyDispatch`]: To determine the class of the dispatch. See the enum definition for +//! more information on dispatch classes. +//! +//! Every dispatchable function is responsible for providing this data via an optional `#[weight = +//! $x]` attribute. In this snipped, `$x` can be any user provided struct that implements the +//! two aforementioned traits. +//! +//! Substrate then bundles then output information of the two traits into [`DispatchInfo`] struct +//! and provides it by implementing the [`GetDispatchInfo`] for all `Call` variants, and opaque +//! extrinsic types. +//! +//! If no `#[weight]` is defined, the macro automatically injects the `Default` implementation of +//! the [`SimpleDispatchInfo`]. //! //! Note that the decl_module macro _cannot_ enforce this and will simply fail if an invalid struct //! (something that does not implement `Weighable`) is passed in. -use crate::{Fixed64, traits::Saturating}; -use crate::codec::{Encode, Decode}; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use codec::{Encode, Decode}; +use arithmetic::traits::Bounded; +use crate::RuntimeDebug; +/// Re-export priority as type pub use crate::transaction_validity::TransactionPriority; -use crate::traits::Bounded; /// Numeric range of a transaction weight. pub type Weight = u32; +/// Means of weighing some particular kind of data (`T`). +pub trait WeighData { + /// Weigh the data `T` given by `target`. When implementing this for a dispatchable, `T` will be + /// a tuple of all arguments given to the function (except origin). + fn weigh_data(&self, target: T) -> Weight; +} + +/// Means of classifying a dispatchable function. +pub trait ClassifyDispatch { + /// Classify the dispatch function based on input data `target` of type `T`. When implementing + /// this for a dispatchable, `T` will be a tuple of all arguments given to the function (except + /// origin). + fn classify_dispatch(&self, target: T) -> DispatchClass; +} + /// A generalized group of dispatch types. This is only distinguishing normal, user-triggered transactions /// (`Normal`) and anything beyond which serves a higher purpose to the system (`Operational`). -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)] pub enum DispatchClass { /// A normal dispatch. Normal, @@ -64,8 +94,8 @@ impl From for DispatchClass { } /// A bundle of static information collected from the `#[weight = $x]` attributes. -#[cfg_attr(feature = "std", derive(PartialEq, Eq, Debug))] -#[derive(Clone, Copy, Default)] +#[cfg_attr(feature = "std", derive(PartialEq, Eq))] +#[derive(Clone, Copy, Default, RuntimeDebug)] pub struct DispatchInfo { /// Weight of this transaction. pub weight: Weight, @@ -84,8 +114,8 @@ impl DispatchInfo { } } -/// A `Dispatchable` function (aka transaction) that can carry some static information along with it, using the -/// `#[weight]` attribute. +/// A `Dispatchable` function (aka transaction) that can carry some static information along with +/// it, using the `#[weight]` attribute. pub trait GetDispatchInfo { /// Return a `DispatchInfo`, containing relevant information of this dispatch. /// @@ -93,18 +123,6 @@ pub trait GetDispatchInfo { fn get_dispatch_info(&self) -> DispatchInfo; } -/// Means of weighing some particular kind of data (`T`). -pub trait WeighData { - /// Weigh the data `T` given by `target`. - fn weigh_data(&self, target: T) -> Weight; -} - -/// Means of classifying a dispatchable function. -pub trait ClassifyDispatch { - /// Classify the dispatch function based on input data `target` of type `T`. - fn classify_dispatch(&self, target: T) -> DispatchClass; -} - /// Default type used with the `#[weight = x]` attribute in a substrate chain. /// /// A user may pass in any other type that implements the correct traits. If not, the `Default` @@ -116,13 +134,9 @@ pub trait ClassifyDispatch { /// - A `Free` variant is equal to `::Fixed(0)`. Note that this does not guarantee inclusion. /// - A `Max` variant is equal to `::Fixed(Weight::max_value())`. /// -/// Based on the final weight value, based on the above variants: -/// - A _weight-fee_ is deducted. -/// - The block weight is consumed proportionally. -/// /// As for the generalized groups themselves: /// - `Normal` variants will be assigned a priority proportional to their weight. They can only -/// consume a portion (1/4) of the maximum block resource limits. +/// consume a portion (defined in the system module) of the maximum block resource limits. /// - `Operational` variants will be assigned the maximum priority. They can potentially consume /// the entire block resource limit. #[derive(Clone, Copy)] @@ -167,76 +181,3 @@ impl Default for SimpleDispatchInfo { SimpleDispatchInfo::FixedNormal(10_000) } } - -/// Representation of a weight multiplier. This represents how a fee value can be computed from a -/// weighted transaction. -/// -/// This is basically a wrapper for the `Fixed64` type a slightly tailored multiplication to u32 -/// in the form of the `apply_to` method. -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct WeightMultiplier(Fixed64); - -impl WeightMultiplier { - /// Apply the inner Fixed64 as a weight multiplier to a weight value. - /// - /// This will perform a saturated `weight + weight * self.0`. - pub fn apply_to(&self, weight: Weight) -> Weight { - self.0.saturated_multiply_accumulate(weight) - } - - /// build self from raw parts per billion. - #[cfg(feature = "std")] - pub fn from_parts(parts: i64) -> Self { - Self(Fixed64(parts)) - } - - /// build self from a fixed64 value. - pub fn from_fixed(f: Fixed64) -> Self { - Self(f) - } - - /// Approximate the fraction `n/d`. - pub fn from_rational(n: i64, d: u64) -> Self { - Self(Fixed64::from_rational(n, d)) - } -} - -impl Saturating for WeightMultiplier { - fn saturating_add(self, rhs: Self) -> Self { - Self(self.0.saturating_add(rhs.0)) - } - fn saturating_mul(self, rhs: Self) -> Self { - Self(self.0.saturating_mul(rhs.0)) - - } - fn saturating_sub(self, rhs: Self) -> Self { - Self(self.0.saturating_sub(rhs.0)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn multiplier_apply_to_works() { - let test_set = vec![0, 1, 10, 1000, 1_000_000_000]; - - // negative (1/2) - let mut fm = WeightMultiplier::from_rational(-1, 2); - test_set.clone().into_iter().for_each(|i| { assert_eq!(fm.apply_to(i) as i32, i as i32 - i as i32 / 2); }); - - // unit (1) multiplier - fm = WeightMultiplier::from_parts(0); - test_set.clone().into_iter().for_each(|i| { assert_eq!(fm.apply_to(i), i); }); - - // i.5 multiplier - fm = WeightMultiplier::from_rational(1, 2); - test_set.clone().into_iter().for_each(|i| { assert_eq!(fm.apply_to(i), i * 3 / 2); }); - - // dual multiplier - fm = WeightMultiplier::from_rational(1, 1); - test_set.clone().into_iter().for_each(|i| { assert_eq!(fm.apply_to(i), i * 2); }); - } -} diff --git a/core/sr-sandbox/Cargo.toml b/core/sr-sandbox/Cargo.toml index da80b2f213c7ef53074a2f34884ef9b4813946f6..87b4e742a04131aaaa6a0122685b528cab9b875b 100755 --- a/core/sr-sandbox/Cargo.toml +++ b/core/sr-sandbox/Cargo.toml @@ -6,17 +6,17 @@ build = "build.rs" edition = "2018" [build-dependencies] -rustc_version = "0.2" +rustc_version = "0.2.3" [dependencies] -wasmi = { version = "0.5.0", optional = true } +wasmi = { version = "0.5.1", optional = true } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } [dev-dependencies] -wabt = "~0.7.4" -assert_matches = "1.1" +wabt = "0.9.2" +assert_matches = "1.3.0" [features] default = ["std"] diff --git a/core/sr-sandbox/src/lib.rs b/core/sr-sandbox/src/lib.rs index e814a51acedf692b5df4082db9fce73408d5308e..c9f9135661586d034f1722ad30e822ac2eebc1c0 100755 --- a/core/sr-sandbox/src/lib.rs +++ b/core/sr-sandbox/src/lib.rs @@ -51,7 +51,7 @@ mod imp { } /// Error that can occur while using this crate. -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(primitives::RuntimeDebug)] pub enum Error { /// Module is not valid, couldn't be instantiated. Module, @@ -171,7 +171,7 @@ pub struct Instance { impl Instance { /// Instantiate a module with the given [`EnvironmentDefinitionBuilder`]. It will - /// run the `start` function with the given `state`. + /// run the `start` function (if it is present in the module) with the given `state`. /// /// Returns `Err(Error::Module)` if this module can't be instantiated with the given /// environment. If execution of `start` function generated a trap, then `Err(Error::Execution)` will diff --git a/core/sr-staking-primitives/Cargo.toml b/core/sr-staking-primitives/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..25e8f4ccf1529576e5d34111445d57b947f04f37 --- /dev/null +++ b/core/sr-staking-primitives/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "sr-staking-primitives" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sr-primitives = { path = "../sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "sr-primitives/std", + "rstd/std", +] diff --git a/core/sr-staking-primitives/src/lib.rs b/core/sr-staking-primitives/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..182307cb4712fa1a17668f348b70bf89f4dbfda3 --- /dev/null +++ b/core/sr-staking-primitives/src/lib.rs @@ -0,0 +1,23 @@ + +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +#![cfg_attr(not(feature = "std"), no_std)] + +//! A crate which contains primitives that are useful for implementation that uses staking +//! approaches in general. Definitions related to sessions, slashing, etc go here. + +pub mod offence; + +/// Simple index type with which we can count sessions. +pub type SessionIndex = u32; diff --git a/core/sr-staking-primitives/src/offence.rs b/core/sr-staking-primitives/src/offence.rs new file mode 100644 index 0000000000000000000000000000000000000000..db51f75df1bf3c973c8989446404b0fb8178182e --- /dev/null +++ b/core/sr-staking-primitives/src/offence.rs @@ -0,0 +1,141 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Common traits and types that are useful for describing offences for usage in environments +//! that use staking. + +use rstd::vec::Vec; + +use codec::{Encode, Decode}; +use sr_primitives::Perbill; + +use crate::SessionIndex; + +/// The kind of an offence, is a byte string representing some kind identifier +/// e.g. `b"im-online:offlin"`, `b"babe:equivocatio"` +// TODO [slashing]: Is there something better we can have here that is more natural but still +// flexible? as you see in examples, they get cut off with long names. +pub type Kind = [u8; 16]; + +/// Number of times the offence of this authority was already reported in the past. +/// +/// Note that we don't buffer offence reporting, so every time we see a new offence +/// of the same kind, we will report past authorities again. +/// This counter keeps track of how many times the authority was already reported in the past, +/// so that we can slash it accordingly. +pub type OffenceCount = u32; + +/// A trait implemented by an offence report. +/// +/// This trait assumes that the offence is legitimate and was validated already. +/// +/// Examples of offences include: a BABE equivocation or a GRANDPA unjustified vote. +pub trait Offence { + /// Identifier which is unique for this kind of an offence. + const ID: Kind; + + /// A type that represents a point in time on an abstract timescale. + /// + /// See `Offence::time_slot` for details. The only requirement is that such timescale could be + /// represented by a single `u128` value. + type TimeSlot: Clone + codec::Codec + Ord; + + /// The list of all offenders involved in this incident. + /// + /// The list has no duplicates, so it is rather a set. + fn offenders(&self) -> Vec; + + /// The session index that is used for querying the validator set for the `slash_fraction` + /// function. + /// + /// This is used for filtering historical sessions. + fn session_index(&self) -> SessionIndex; + + /// Return a validator set count at the time when the offence took place. + fn validator_set_count(&self) -> u32; + + /// A point in time when this offence happened. + /// + /// This is used for looking up offences that happened at the "same time". + /// + /// The timescale is abstract and doesn't have to be the same across different implementations + /// of this trait. The value doesn't represent absolute timescale though since it is interpreted + /// along with the `session_index`. Two offences are considered to happen at the same time iff + /// both `session_index` and `time_slot` are equal. + /// + /// As an example, for GRANDPA timescale could be a round number and for BABE it could be a slot + /// number. Note that for GRANDPA the round number is reset each epoch. + fn time_slot(&self) -> Self::TimeSlot; + + /// A slash fraction of the total exposure that should be slashed for this + /// particular offence kind for the given parameters that happened at a singular `TimeSlot`. + /// + /// `offenders_count` - the count of unique offending authorities. It is >0. + /// `validator_set_count` - the cardinality of the validator set at the time of offence. + fn slash_fraction( + offenders_count: u32, + validator_set_count: u32, + ) -> Perbill; +} + +/// A trait for decoupling offence reporters from the actual handling of offence reports. +pub trait ReportOffence> { + /// Report an `offence` and reward given `reporters`. + fn report_offence(reporters: Vec, offence: O); +} + +impl> ReportOffence for () { + fn report_offence(_reporters: Vec, _offence: O) {} +} + +/// A trait to take action on an offence. +/// +/// Used to decouple the module that handles offences and +/// the one that should punish for those offences. +pub trait OnOffenceHandler { + /// A handler for an offence of a particular kind. + /// + /// Note that this contains a list of all previous offenders + /// as well. The implementer should cater for a case, where + /// the same authorities were reported for the same offence + /// in the past (see `OffenceCount`). + /// + /// The vector of `slash_fraction` contains `Perbill`s + /// the authorities should be slashed and is computed + /// according to the `OffenceCount` already. This is of the same length as `offenders.` + /// Zero is a valid value for a fraction. + fn on_offence( + offenders: &[OffenceDetails], + slash_fraction: &[Perbill], + ); +} + +impl OnOffenceHandler for () { + fn on_offence( + _offenders: &[OffenceDetails], + _slash_fraction: &[Perbill], + ) {} +} + +/// A details about an offending authority for a particular kind of offence. +#[derive(Clone, PartialEq, Eq, Encode, Decode, sr_primitives::RuntimeDebug)] +pub struct OffenceDetails { + /// The offending authority id + pub offender: Offender, + /// A list of reporters of offences of this authority ID. Possibly empty where there are no + /// particular reporters. + pub reporters: Vec, +} diff --git a/core/sr-std/src/lib.rs b/core/sr-std/src/lib.rs index 24c137c285f41096e94b71a43eaa967fc7f16cc9..f369d3908ba83233ecebb645c278f1318c491e28 100644 --- a/core/sr-std/src/lib.rs +++ b/core/sr-std/src/lib.rs @@ -68,7 +68,7 @@ include!("../without_std.rs"); pub mod prelude { pub use crate::vec::Vec; pub use crate::boxed::Box; - pub use crate::cmp::{Eq, PartialEq}; + pub use crate::cmp::{Eq, PartialEq, Reverse}; pub use crate::clone::Clone; // Re-export `vec!` macro here, but not in `std` mode, since diff --git a/core/sr-std/without_std.rs b/core/sr-std/without_std.rs index 327e271049d586f7f35b6292ca52a5352634d703..9762c74367198fba65520e9a5b37ce0c9a192134 100755 --- a/core/sr-std/without_std.rs +++ b/core/sr-std/without_std.rs @@ -14,12 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -#[cfg(feature = "nightly")] #[doc(hidden)] pub extern crate alloc; extern "C" { - fn ext_malloc(size: usize) -> *mut u8; + fn ext_malloc(size: u32) -> *mut u8; fn ext_free(ptr: *mut u8); } @@ -37,7 +36,7 @@ mod __impl { unsafe impl GlobalAlloc for WasmAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - super::ext_malloc(layout.size()) as *mut u8 + super::ext_malloc(layout.size() as u32) as *mut u8 } unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { @@ -49,12 +48,12 @@ mod __impl { pub use alloc::boxed; pub use alloc::rc; pub use alloc::vec; -pub use core::borrow; pub use core::cell; pub use core::clone; pub use core::cmp; pub use core::convert; pub use core::default; +pub use core::fmt; pub use core::hash; pub use core::intrinsics; pub use core::iter; @@ -76,3 +75,8 @@ pub mod collections { pub use alloc::collections::btree_set; pub use alloc::collections::vec_deque; } + +pub mod borrow { + pub use core::borrow::*; + pub use alloc::borrow::*; +} diff --git a/core/sr-version/Cargo.toml b/core/sr-version/Cargo.toml index a83d1f6415dd072ef6093b60e61675ce3ce06cd3..5be3048f827b4351d7fbc1b091d0851aef7d7ac2 100644 --- a/core/sr-version/Cargo.toml +++ b/core/sr-version/Cargo.toml @@ -5,9 +5,9 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -impl-serde = { version = "0.1", optional = true } -serde = { version = "1.0", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +impl-serde = { version = "0.2.3", optional = true } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.5", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../sr-std", default-features = false } sr-primitives = { path = "../sr-primitives", default-features = false } diff --git a/core/sr-version/src/lib.rs b/core/sr-version/src/lib.rs index cf96fe70e219faaed1e98ef5ae5a6e12445b768e..24c54a739a2e0489a17aff64f84281fc280ebf1f 100644 --- a/core/sr-version/src/lib.rs +++ b/core/sr-version/src/lib.rs @@ -62,8 +62,8 @@ macro_rules! create_apis_vec { /// This triplet have different semantics and mis-interpretation could cause problems. /// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, /// absolutely not `impl_version` since they change the semantics of the runtime. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize, Decode))] +#[derive(Clone, PartialEq, Eq, Encode, Default, sr_primitives::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Decode))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] pub struct RuntimeVersion { /// Identifies the different Substrate runtimes. There'll be at least polkadot and node. @@ -96,7 +96,13 @@ pub struct RuntimeVersion { pub impl_version: u32, /// List of supported API "features" along with their versions. - #[cfg_attr(feature = "std", serde(serialize_with = "apis_serialize::serialize"))] + #[cfg_attr( + feature = "std", + serde( + serialize_with = "apis_serialize::serialize", + deserialize_with = "apis_serialize::deserialize", + ) + )] pub apis: ApisVec, } @@ -141,7 +147,7 @@ impl RuntimeVersion { } #[cfg(feature = "std")] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Debug)] pub struct NativeVersion { /// Basic runtime version info. pub runtime_version: RuntimeVersion, @@ -163,7 +169,7 @@ impl NativeVersion { mod apis_serialize { use super::*; use impl_serde::serialize as bytes; - use serde::{Serializer, ser::SerializeTuple}; + use serde::{Serializer, de, ser::SerializeTuple}; #[derive(Serialize)] struct ApiId<'a>( @@ -182,9 +188,48 @@ mod apis_serialize { seq.end() } - pub fn serialize_bytesref(apis: &&super::ApiId, ser: S) -> Result where + pub fn serialize_bytesref(&apis: &&super::ApiId, ser: S) -> Result where S: Serializer, { - bytes::serialize(*apis, ser) + bytes::serialize(apis, ser) + } + + #[derive(Deserialize)] + struct ApiIdOwned( + #[serde(deserialize_with="deserialize_bytes")] + super::ApiId, + u32, + ); + + pub fn deserialize<'de, D>(deserializer: D) -> Result where + D: de::Deserializer<'de>, + { + struct Visitor; + impl<'de> de::Visitor<'de> for Visitor { + type Value = ApisVec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence of api id and version tuples") + } + + fn visit_seq(self, mut visitor: V) -> Result where + V: de::SeqAccess<'de>, + { + let mut apis = Vec::new(); + while let Some(value) = visitor.next_element::()? { + apis.push((value.0, value.1)); + } + Ok(apis.into()) + } + } + deserializer.deserialize_seq(Visitor) + } + + pub fn deserialize_bytes<'de, D>(d: D) -> Result where + D: de::Deserializer<'de> + { + let mut arr = [0; 8]; + bytes::deserialize_check_len(d, bytes::ExpectedLen::Exact(&mut arr[..]))?; + Ok(arr) } } diff --git a/core/state-db/Cargo.toml b/core/state-db/Cargo.toml index 332751c927f5d1ca65398def6578fe4489c5f877..d271a0e179d6d3eee5994b13ac1de5bd9ed4038c 100644 --- a/core/state-db/Cargo.toml +++ b/core/state-db/Cargo.toml @@ -6,9 +6,9 @@ edition = "2018" [dependencies] parking_lot = "0.9.0" -log = "0.4" +log = "0.4.8" primitives = { package = "substrate-primitives", path = "../../core/primitives" } codec = { package = "parity-scale-codec", version = "1.0.0", features = ["derive"] } [dev-dependencies] -env_logger = "0.6" +env_logger = "0.7.0" diff --git a/core/state-db/src/lib.rs b/core/state-db/src/lib.rs index 81772e554bc572849a79d257a1e9a420b4b2644d..e561d9ce9617cb4c4edf92270160805bd151e1b8 100644 --- a/core/state-db/src/lib.rs +++ b/core/state-db/src/lib.rs @@ -41,6 +41,11 @@ use noncanonical::NonCanonicalOverlay; use pruning::RefWindow; use log::trace; +const PRUNING_MODE: &[u8] = b"mode"; +const PRUNING_MODE_ARCHIVE: &[u8] = b"archive"; +const PRUNING_MODE_ARCHIVE_CANON: &[u8] = b"archive_canonical"; +const PRUNING_MODE_CONSTRAINED: &[u8] = b"constrained"; + /// Database value type. pub type DBValue = Vec; @@ -77,6 +82,8 @@ pub enum Error { InvalidBlockNumber, /// Trying to insert block with unknown parent. InvalidParent, + /// Invalid pruning mode specified. Contains expected mode. + InvalidPruningMode(String), } /// Pinning error type. @@ -99,6 +106,7 @@ impl fmt::Debug for Error { Error::InvalidBlock => write!(f, "Trying to canonicalize invalid block"), Error::InvalidBlockNumber => write!(f, "Trying to insert block with invalid number"), Error::InvalidParent => write!(f, "Trying to insert block with unknown parent"), + Error::InvalidPruningMode(e) => write!(f, "Expected pruning mode: {}", e), } } } @@ -159,6 +167,14 @@ impl PruningMode { } } + /// Is this an archive (either ArchiveAll or ArchiveCanonical) pruning mode? + pub fn id(&self) -> &[u8] { + match self { + PruningMode::ArchiveAll => PRUNING_MODE_ARCHIVE, + PruningMode::ArchiveCanonical => PRUNING_MODE_ARCHIVE_CANON, + PruningMode::Constrained(_) => PRUNING_MODE_CONSTRAINED, + } + } } impl Default for PruningMode { @@ -183,6 +199,10 @@ struct StateDbSync { impl StateDbSync { pub fn new(mode: PruningMode, db: &D) -> Result, Error> { trace!(target: "state-db", "StateDb settings: {:?}", mode); + + // Check that settings match + Self::check_meta(&mode, db)?; + let non_canonical: NonCanonicalOverlay = NonCanonicalOverlay::new(db)?; let pruning: Option> = match mode { PruningMode::Constrained(Constraints { @@ -192,6 +212,7 @@ impl StateDbSync { PruningMode::Constrained(_) => Some(RefWindow::new(db)?), PruningMode::ArchiveAll | PruningMode::ArchiveCanonical => None, }; + Ok(StateDbSync { mode, non_canonical, @@ -200,18 +221,41 @@ impl StateDbSync { }) } + fn check_meta(mode: &PruningMode, db: &D) -> Result<(), Error> { + let db_mode = db.get_meta(&to_meta_key(PRUNING_MODE, &())).map_err(Error::Db)?; + trace!(target: "state-db", + "DB pruning mode: {:?}", + db_mode.as_ref().map(|v| std::str::from_utf8(&v)) + ); + match &db_mode { + Some(v) if v.as_slice() == mode.id() => Ok(()), + Some(v) => Err(Error::InvalidPruningMode(String::from_utf8_lossy(v).into())), + None => Ok(()), + } + } + pub fn insert_block(&mut self, hash: &BlockHash, number: u64, parent_hash: &BlockHash, mut changeset: ChangeSet) -> Result, Error> { + let mut meta = ChangeSet::default(); + if number == 0 { + // Save pruning mode when writing first block. + meta.inserted.push((to_meta_key(PRUNING_MODE, &()), self.mode.id().into())); + } + match self.mode { PruningMode::ArchiveAll => { changeset.deleted.clear(); // write changes immediately Ok(CommitSet { data: changeset, - meta: Default::default(), + meta: meta, }) }, PruningMode::Constrained(_) | PruningMode::ArchiveCanonical => { - self.non_canonical.insert(hash, number, parent_hash, changeset) + let commit = self.non_canonical.insert(hash, number, parent_hash, changeset); + commit.map(|mut c| { + c.meta.inserted.extend(meta.inserted); + c + }) } } } @@ -544,4 +588,23 @@ mod tests { assert!(sdb.is_pruned(&H256::from_low_u64_be(22), 2)); assert!(db.data_eq(&make_db(&[1, 21, 3, 921, 922, 93, 94]))); } + + #[test] + fn detects_incompatible_mode() { + let mut db = make_db(&[]); + let state_db = StateDb::new(PruningMode::ArchiveAll, &db).unwrap(); + db.commit( + &state_db + .insert_block::( + &H256::from_low_u64_be(0), + 0, + &H256::from_low_u64_be(0), + make_changeset(&[], &[]), + ) + .unwrap(), + ); + let new_mode = PruningMode::Constrained(Constraints { max_blocks: Some(2), max_mem: None }); + let state_db: Result, _> = StateDb::new(new_mode, &db); + assert!(state_db.is_err()); + } } diff --git a/core/state-machine/Cargo.toml b/core/state-machine/Cargo.toml index bf5b96e43675a70ed12ce00f53b314dfb0b8d71e..7cd8601a3b636b281309b2ae0256fb1def3ddfcb 100644 --- a/core/state-machine/Cargo.toml +++ b/core/state-machine/Cargo.toml @@ -6,19 +6,21 @@ description = "Substrate State Machine" edition = "2018" [dependencies] -log = "0.4" +log = "0.4.8" parking_lot = "0.9.0" -hash-db = "0.15.0" -trie-db = "0.15.0" -trie-root = "0.15.0" +hash-db = "0.15.2" +trie-db = "0.15.2" +trie-root = "0.15.2" trie = { package = "substrate-trie", path = "../trie" } primitives = { package = "substrate-primitives", path = "../primitives" } panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } codec = { package = "parity-scale-codec", version = "1.0.0" } -num-traits = "0.2" +num-traits = "0.2.8" +rand = "0.7.2" +externalities = { package = "substrate-externalities", path = "../externalities" } [dev-dependencies] -hex-literal = "0.2.0" +hex-literal = "0.2.1" [features] default = [] diff --git a/core/state-machine/src/backend.rs b/core/state-machine/src/backend.rs index 0feb6e84d039e2102ac278c46fec09c2153647ac..e2f398ef7ccaef0af7c1b69a287c1aa01682d3d7 100644 --- a/core/state-machine/src/backend.rs +++ b/core/state-machine/src/backend.rs @@ -16,22 +16,21 @@ //! State machine backends. These manage the code and storage of contracts. -use std::{error, fmt}; -use std::cmp::Ord; -use std::collections::HashMap; -use std::marker::PhantomData; +use std::{error, fmt, cmp::Ord, collections::HashMap, marker::PhantomData}; use log::warn; use hash_db::Hasher; use crate::trie_backend::TrieBackend; use crate::trie_backend_essence::TrieBackendStorage; -use trie::{TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration}; -use trie::trie_types::{TrieDBMut, Layout}; +use trie::{ + TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration, + trie_types::{TrieDBMut, Layout}, +}; /// A state backend is used to read state data and can have changes committed /// to it. /// /// The clone operation (if implemented) should be cheap. -pub trait Backend { +pub trait Backend: std::fmt::Debug { /// An error type when fetching data is not possible. type Error: super::Error; @@ -72,7 +71,14 @@ pub trait Backend { /// Retrieve all entries keys which start with the given prefix and /// call `f` for each of those keys. - fn for_keys_with_prefix(&self, prefix: &[u8], f: F); + fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { + self.for_key_values_with_prefix(prefix, |k, _v| f(k)) + } + + /// Retrieve all entries keys and values of which start with the given prefix and + /// call `f` for each of those keys. + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F); + /// Retrieve all child entries keys which start with the given prefix and /// call `f` for each of those keys. @@ -112,7 +118,9 @@ pub trait Backend { } /// Try convert into trie backend. - fn as_trie_backend(&mut self) -> Option<&TrieBackend>; + fn as_trie_backend(&mut self) -> Option<&TrieBackend> { + None + } /// Calculate the storage root, with given delta over what is already stored /// in the backend, and produce a "transaction" that can be used to commit. @@ -147,7 +155,56 @@ pub trait Backend { txs.consolidate(parent_txs); (root, txs) } +} + +impl<'a, T: Backend, H: Hasher> Backend for &'a T { + type Error = T::Error; + type Transaction = T::Transaction; + type TrieBackendStorage = T::TrieBackendStorage; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + (*self).storage(key) + } + + fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { + (*self).child_storage(storage_key, key) + } + + fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { + (*self).for_keys_in_child_storage(storage_key, f) + } + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + (*self).for_keys_with_prefix(prefix, f) + } + + fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { + (*self).for_child_keys_with_prefix(storage_key, prefix, f) + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord, + { + (*self).storage_root(delta) + } + + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord, + { + (*self).child_storage_root(storage_key, delta) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + (*self).pairs() + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + (*self).for_key_values_with_prefix(prefix, f); + } } /// Trait that allows consolidate two transactions together. @@ -197,6 +254,12 @@ pub struct InMemory { _hasher: PhantomData, } +impl std::fmt::Debug for InMemory { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "InMemory ({} values)", self.inner.len()) + } +} + impl Default for InMemory { fn default() -> Self { InMemory { @@ -291,8 +354,6 @@ impl From>, Vec, Option>)>> for InMem } } -impl super::Error for Void {} - impl InMemory { /// child storage key iterator pub fn child_storage_keys(&self) -> impl Iterator { @@ -321,6 +382,11 @@ impl Backend for InMemory { self.inner.get(&None).map(|map| map.keys().filter(|key| key.starts_with(prefix)).map(|k| &**k).for_each(f)); } + fn for_key_values_with_prefix(&self, prefix: &[u8], mut f: F) { + self.inner.get(&None).map(|map| map.iter().filter(|(key, _val)| key.starts_with(prefix)) + .for_each(|(k, v)| f(k, v))); + } + fn for_keys_in_child_storage(&self, storage_key: &[u8], mut f: F) { self.inner.get(&Some(storage_key.to_vec())).map(|map| map.keys().for_each(|k| f(&k))); } diff --git a/core/state-machine/src/basic.rs b/core/state-machine/src/basic.rs index 1d36a0ddad51d1afe6d87cee6594031dc6c53a1d..c2d1a0e3950d035a6de4bea3cc6c71b6985dff09 100644 --- a/core/state-machine/src/basic.rs +++ b/core/state-machine/src/basic.rs @@ -16,15 +16,15 @@ //! Basic implementation for Externalities. -use std::collections::HashMap; -use std::iter::FromIterator; +use std::{collections::HashMap, any::{TypeId, Any}, iter::FromIterator}; use crate::backend::{Backend, InMemory}; use hash_db::Hasher; use trie::{TrieConfiguration, default_child_trie_root}; use trie::trie_types::Layout; -use primitives::offchain; -use primitives::storage::well_known_keys::is_child_storage_key; -use super::{ChildStorageKey, Externalities}; +use primitives::{ + storage::{well_known_keys::is_child_storage_key, ChildStorageKey}, + traits::Externalities, Blake2Hasher, hash::H256, +}; use log::warn; /// Simple HashMap-based Externalities impl. @@ -35,7 +35,6 @@ pub struct BasicExternalities { } impl BasicExternalities { - /// Create a new instance of `BasicExternalities` pub fn new( top: HashMap, Vec>, @@ -88,21 +87,37 @@ impl From, Vec>> for BasicExternalities { } } -impl Externalities for BasicExternalities where H::Out: Ord { +impl Externalities for BasicExternalities { fn storage(&self, key: &[u8]) -> Option> { self.top.get(key).cloned() } + fn storage_hash(&self, key: &[u8]) -> Option { + self.storage(key).map(|v| Blake2Hasher::hash(&v)) + } + fn original_storage(&self, key: &[u8]) -> Option> { - Externalities::::storage(self, key) + self.storage(key) + } + + fn original_storage_hash(&self, key: &[u8]) -> Option { + self.storage_hash(key) } - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { self.children.get(storage_key.as_ref()).and_then(|child| child.get(key)).cloned() } - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { - Externalities::::child_storage(self, storage_key, key) + fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v)) + } + + fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + self.child_storage_hash(storage_key, key) + } + + fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + Externalities::child_storage(self, storage_key, key) } fn place_storage(&mut self, key: Vec, maybe_value: Option>) { @@ -119,9 +134,9 @@ impl Externalities for BasicExternalities where H::Out: Ord { fn place_child_storage( &mut self, - storage_key: ChildStorageKey, + storage_key: ChildStorageKey, key: Vec, - value: Option> + value: Option>, ) { let child_map = self.children.entry(storage_key.into_owned()).or_default(); if let Some(value) = value { @@ -131,7 +146,7 @@ impl Externalities for BasicExternalities where H::Out: Ord { } } - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { + fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { self.children.remove(storage_key.as_ref()); } @@ -147,7 +162,7 @@ impl Externalities for BasicExternalities where H::Out: Ord { self.top.retain(|key, _| !key.starts_with(prefix)); } - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { + fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { if let Some(child) = self.children.get_mut(storage_key.as_ref()) { child.retain(|key, _| !key.starts_with(prefix)); } @@ -155,17 +170,17 @@ impl Externalities for BasicExternalities where H::Out: Ord { fn chain_id(&self) -> u64 { 42 } - fn storage_root(&mut self) -> H::Out { + fn storage_root(&mut self) -> H256 { let mut top = self.top.clone(); let keys: Vec<_> = self.children.keys().map(|k| k.to_vec()).collect(); // Single child trie implementation currently allows using the same child // empty root for all child trie. Using null storage key until multiple // type of child trie support. - let empty_hash = default_child_trie_root::>(&[]); + let empty_hash = default_child_trie_root::>(&[]); for storage_key in keys { let child_root = self.child_storage_root( - ChildStorageKey::::from_slice(storage_key.as_slice()) - .expect("Map only feed by valid keys; qed") + ChildStorageKey::from_slice(storage_key.as_slice()) + .expect("Map only feed by valid keys; qed"), ); if &empty_hash[..] == &child_root[..] { top.remove(&storage_key); @@ -173,30 +188,28 @@ impl Externalities for BasicExternalities where H::Out: Ord { top.insert(storage_key, child_root); } } - Layout::::trie_root(self.top.clone()) + + Layout::::trie_root(self.top.clone()) } - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { + fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { if let Some(child) = self.children.get(storage_key.as_ref()) { let delta = child.clone().into_iter().map(|(k, v)| (k, Some(v))); - InMemory::::default().child_storage_root(storage_key.as_ref(), delta).0 + InMemory::::default().child_storage_root(storage_key.as_ref(), delta).0 } else { - default_child_trie_root::>(storage_key.as_ref()) + default_child_trie_root::>(storage_key.as_ref()) } } - fn storage_changes_root(&mut self, _parent: H::Out) -> Result, ()> { + fn storage_changes_root(&mut self, _parent: H256) -> Result, ()> { Ok(None) } +} - fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities> { - warn!("Call to non-existent offchain externalities set."); - None - } - - fn keystore(&self) -> Option { - warn!("Call to non-existent keystore."); +impl externalities::ExtensionStore for BasicExternalities { + fn extension_by_type_id(&mut self, _: TypeId) -> Option<&mut dyn Any> { + warn!("Extensions are not supported by `BasicExternalities`."); None } } @@ -204,14 +217,13 @@ impl Externalities for BasicExternalities where H::Out: Ord { #[cfg(test)] mod tests { use super::*; - use primitives::{Blake2Hasher, H256, map}; + use primitives::{H256, map}; use primitives::storage::well_known_keys::CODE; use hex_literal::hex; #[test] fn commit_should_work() { let mut ext = BasicExternalities::default(); - let ext = &mut ext as &mut dyn Externalities; ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); @@ -223,7 +235,6 @@ mod tests { #[test] fn set_and_retrieve_code() { let mut ext = BasicExternalities::default(); - let ext = &mut ext as &mut dyn Externalities; let code = vec![1, 2, 3]; ext.set_storage(CODE.to_vec(), code.clone()); @@ -244,8 +255,6 @@ mod tests { ] ); - let ext = &mut ext as &mut dyn Externalities; - let child = || ChildStorageKey::from_vec(child_storage.clone()).unwrap(); assert_eq!(ext.child_storage(child(), b"doe"), Some(b"reindeer".to_vec())); diff --git a/core/state-machine/src/changes_trie/build.rs b/core/state-machine/src/changes_trie/build.rs index dd10a3cb80da0b36266f3a191af306bf4ecfd30b..34e77bd91436a4f5eaf9dc80b171877d73f2e60c 100644 --- a/core/state-machine/src/changes_trie/build.rs +++ b/core/state-machine/src/changes_trie/build.rs @@ -16,7 +16,7 @@ //! Structures and functions required to build changes trie for given block. -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use std::collections::btree_map::Entry; use codec::Decode; use hash_db::Hasher; @@ -27,62 +27,137 @@ use crate::trie_backend_essence::TrieBackendEssence; use crate::changes_trie::build_iterator::digest_build_iterator; use crate::changes_trie::input::{InputKey, InputPair, DigestIndex, ExtrinsicIndex}; use crate::changes_trie::{AnchorBlockId, ConfigurationRange, Storage, BlockNumber}; +use crate::changes_trie::input::ChildIndex; /// Prepare input pairs for building a changes trie of given block. /// /// Returns Err if storage error has occurred OR if storage haven't returned /// required data. -/// Returns Ok(None) data required to prepare input pairs is not collected -/// or storage is not provided. -pub fn prepare_input<'a, B, H, Number>( +pub(crate) fn prepare_input<'a, B, H, Number>( backend: &'a B, - storage: &'a Storage, + storage: &'a dyn Storage, config: ConfigurationRange<'a, Number>, changes: &'a OverlayedChanges, parent: &'a AnchorBlockId, -) -> Result> + 'a, String> +) -> Result<( + impl Iterator> + 'a, + Vec<(ChildIndex, impl Iterator> + 'a)>, + Vec, + ), String> where B: Backend, H: Hasher + 'a, Number: BlockNumber, { let number = parent.number.clone() + One::one(); - let extrinsics_input = prepare_extrinsics_input( + let (extrinsics_input, children_extrinsics_input) = prepare_extrinsics_input( backend, &number, - changes)?; - let digest_input = prepare_digest_input::( + changes, + )?; + let (digest_input, mut children_digest_input, digest_input_blocks) = prepare_digest_input::( parent, config, number, - storage)?; - Ok(extrinsics_input.chain(digest_input)) -} + storage, + )?; + + let mut children_digest = Vec::with_capacity(children_extrinsics_input.len()); + for (child_index, ext_iter) in children_extrinsics_input.into_iter() { + let dig_iter = children_digest_input.remove(&child_index); + children_digest.push(( + child_index, + Some(ext_iter).into_iter().flatten() + .chain(dig_iter.into_iter().flatten()), + )); + } + for (child_index, dig_iter) in children_digest_input.into_iter() { + children_digest.push(( + child_index, + None.into_iter().flatten() + .chain(Some(dig_iter).into_iter().flatten()), + )); + } + Ok(( + extrinsics_input.chain(digest_input), + children_digest, + digest_input_blocks, + )) +} /// Prepare ExtrinsicIndex input pairs. fn prepare_extrinsics_input<'a, B, H, Number>( backend: &'a B, block: &Number, changes: &'a OverlayedChanges, +) -> Result<( + impl Iterator> + 'a, + BTreeMap, impl Iterator> + 'a>, + ), String> + where + B: Backend, + H: Hasher + 'a, + Number: BlockNumber, +{ + + let mut children_keys = BTreeSet::>::new(); + let mut children_result = BTreeMap::new(); + for (storage_key, _) in changes.prospective.children.iter() + .chain(changes.committed.children.iter()) { + children_keys.insert(storage_key.clone()); + } + for storage_key in children_keys { + let child_index = ChildIndex:: { + block: block.clone(), + storage_key: storage_key.clone(), + }; + + let iter = prepare_extrinsics_input_inner(backend, block, changes, Some(storage_key))?; + children_result.insert(child_index, iter); + } + + let top = prepare_extrinsics_input_inner(backend, block, changes, None)?; + + Ok((top, children_result)) +} + +fn prepare_extrinsics_input_inner<'a, B, H, Number>( + backend: &'a B, + block: &Number, + changes: &'a OverlayedChanges, + storage_key: Option>, ) -> Result> + 'a, String> where B: Backend, H: Hasher, Number: BlockNumber, { - changes.committed.top.iter() - .chain(changes.prospective.top.iter()) + let (committed, prospective) = if let Some(sk) = storage_key.as_ref() { + (changes.committed.children.get(sk), changes.prospective.children.get(sk)) + } else { + (Some(&changes.committed.top), Some(&changes.prospective.top)) + }; + committed.iter().flat_map(|c| c.iter()) + .chain(prospective.iter().flat_map(|c| c.iter())) .filter(|( _, v)| v.extrinsics.is_some()) .try_fold(BTreeMap::new(), |mut map: BTreeMap<&[u8], (ExtrinsicIndex, Vec)>, (k, v)| { match map.entry(k) { Entry::Vacant(entry) => { // ignore temporary values (values that have null value at the end of operation // AND are not in storage at the beginning of operation - if !changes.storage(k).map(|v| v.is_some()).unwrap_or_default() { - if !backend.exists_storage(k).map_err(|e| format!("{}", e))? { - return Ok(map); + if let Some(sk) = storage_key.as_ref() { + if !changes.child_storage(sk, k).map(|v| v.is_some()).unwrap_or_default() { + if !backend.exists_child_storage(sk, k).map_err(|e| format!("{}", e))? { + return Ok(map); + } } - } + } else { + if !changes.storage(k).map(|v| v.is_some()).unwrap_or_default() { + if !backend.exists_storage(k).map_err(|e| format!("{}", e))? { + return Ok(map); + } + } + }; let extrinsics = v.extrinsics.as_ref() .expect("filtered by filter() call above; qed") @@ -111,13 +186,18 @@ fn prepare_extrinsics_input<'a, B, H, Number>( .map(|pairs| pairs.into_iter().map(|(_, (k, v))| InputPair::ExtrinsicIndex(k, v))) } + /// Prepare DigestIndex input pairs. fn prepare_digest_input<'a, H, Number>( parent: &'a AnchorBlockId, - config: ConfigurationRange<'a, Number>, + config: ConfigurationRange, block: Number, - storage: &'a Storage, -) -> Result> + 'a, String> + storage: &'a dyn Storage, +) -> Result<( + impl Iterator> + 'a, + BTreeMap, impl Iterator> + 'a>, + Vec, + ), String> where H: Hasher, H::Out: 'a, @@ -132,16 +212,17 @@ fn prepare_digest_input<'a, H, Number>( block.clone() }; - digest_build_iterator(config, block_for_digest) - .try_fold(BTreeMap::new(), move |mut map, digest_build_block| { + let digest_input_blocks = digest_build_iterator(config, block_for_digest).collect::>(); + digest_input_blocks.clone().into_iter() + .try_fold( + (BTreeMap::new(), BTreeMap::new()), move |(mut map, mut child_map), digest_build_block| { + let extrinsic_prefix = ExtrinsicIndex::key_neutral_prefix(digest_build_block.clone()); + let digest_prefix = DigestIndex::key_neutral_prefix(digest_build_block.clone()); + let child_prefix = ChildIndex::key_neutral_prefix(digest_build_block.clone()); let trie_root = storage.root(parent, digest_build_block.clone())?; let trie_root = trie_root.ok_or_else(|| format!("No changes trie root for block {}", digest_build_block.clone()))?; - let trie_storage = TrieBackendEssence::<_, H>::new( - crate::changes_trie::TrieBackendStorageAdapter(storage), - trie_root, - ); - let mut insert_to_map = |key: Vec| { + let insert_to_map = |map: &mut BTreeMap<_,_>, key: Vec| { match map.entry(key.clone()) { Entry::Vacant(entry) => { entry.insert((DigestIndex { @@ -163,32 +244,97 @@ fn prepare_digest_input<'a, H, Number>( } }; - let extrinsic_prefix = ExtrinsicIndex::key_neutral_prefix(digest_build_block.clone()); - trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key| - if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = Decode::decode(&mut &key[..]) { - insert_to_map(trie_key.key); - }); + // try to get all updated keys from cache + let populated_from_cache = storage.with_cached_changed_keys( + &trie_root, + &mut |changed_keys| { + for (storage_key, changed_keys) in changed_keys { + let map = match storage_key { + Some(storage_key) => child_map + .entry(ChildIndex:: { + block: block.clone(), + storage_key: storage_key.clone(), + }) + .or_default(), + None => &mut map, + }; + for changed_key in changed_keys.iter().cloned() { + insert_to_map(map, changed_key); + } + } + } + ); + if populated_from_cache { + return Ok((map, child_map)); + } - let digest_prefix = DigestIndex::key_neutral_prefix(digest_build_block.clone()); - trie_storage.for_keys_with_prefix(&digest_prefix, |key| - if let Ok(InputKey::DigestIndex::(trie_key)) = Decode::decode(&mut &key[..]) { - insert_to_map(trie_key.key); - }); + let mut children_roots = BTreeMap::, _>::new(); + { + let trie_storage = TrieBackendEssence::<_, H>::new( + crate::changes_trie::TrieBackendStorageAdapter(storage), + trie_root, + ); + + trie_storage.for_key_values_with_prefix(&child_prefix, |key, value| + if let Ok(InputKey::ChildIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + if let Ok(value) = >::decode(&mut &value[..]) { + let mut trie_root = ::Out::default(); + trie_root.as_mut().copy_from_slice(&value[..]); + children_roots.insert(trie_key.storage_key, trie_root); + } + }); - Ok(map) + trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key| + if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + + trie_storage.for_keys_with_prefix(&digest_prefix, |key| + if let Ok(InputKey::DigestIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + } + + for (storage_key, trie_root) in children_roots.into_iter() { + let child_index = ChildIndex:: { + block: block.clone(), + storage_key, + }; + + let mut map = child_map.entry(child_index).or_default(); + let trie_storage = TrieBackendEssence::<_, H>::new( + crate::changes_trie::TrieBackendStorageAdapter(storage), + trie_root, + ); + trie_storage.for_keys_with_prefix(&extrinsic_prefix, |key| + if let Ok(InputKey::ExtrinsicIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + + trie_storage.for_keys_with_prefix(&digest_prefix, |key| + if let Ok(InputKey::DigestIndex::(trie_key)) = Decode::decode(&mut &key[..]) { + insert_to_map(&mut map, trie_key.key); + }); + } + Ok((map, child_map)) }) - .map(|pairs| pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v))) + .map(|(pairs, child_pairs)| ( + pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)), + child_pairs.into_iter().map(|(sk, pairs)| + (sk, pairs.into_iter().map(|(_, (k, v))| InputPair::DigestIndex(k, v)))).collect(), + digest_input_blocks, + )) } #[cfg(test)] mod test { use codec::Encode; use primitives::Blake2Hasher; - use primitives::storage::well_known_keys::EXTRINSIC_INDEX; + use primitives::storage::well_known_keys::{EXTRINSIC_INDEX}; use crate::backend::InMemory; - use crate::changes_trie::Configuration; - use crate::changes_trie::storage::InMemoryStorage; - use crate::overlayed_changes::OverlayedValue; + use crate::changes_trie::{RootsStorage, Configuration, storage::InMemoryStorage}; + use crate::changes_trie::build_cache::{IncompleteCacheAction, IncompleteCachedBuildData}; + use crate::overlayed_changes::{OverlayedValue, OverlayedChangeSet}; use super::*; fn prepare_for_build(zero: u64) -> ( @@ -205,6 +351,8 @@ mod test { (vec![104], vec![255]), (vec![105], vec![255]), ].into_iter().collect::<::std::collections::HashMap<_, _>>().into(); + let child_trie_key1 = b"1".to_vec(); + let child_trie_key2 = b"2".to_vec(); let storage = InMemoryStorage::with_inputs(vec![ (zero + 1, vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![100] }, vec![1, 3]), @@ -238,9 +386,24 @@ mod test { ]), (zero + 9, Vec::new()), (zero + 10, Vec::new()), (zero + 11, Vec::new()), (zero + 12, Vec::new()), (zero + 13, Vec::new()), (zero + 14, Vec::new()), (zero + 15, Vec::new()), + ], vec![(child_trie_key1.clone(), vec![ + (zero + 1, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![100] }, vec![1, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![101] }, vec![0, 2]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 1, key: vec![105] }, vec![0, 2, 4]), + ]), + (zero + 2, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0]), + ]), + (zero + 4, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 2, key: vec![102] }, vec![0, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + ]), + ]), ]); let changes = OverlayedChanges { - prospective: vec![ + prospective: OverlayedChangeSet { top: vec![ (vec![100], OverlayedValue { value: Some(vec![200]), extrinsics: Some(vec![0, 2].into_iter().collect()) @@ -250,7 +413,22 @@ mod test { extrinsics: Some(vec![0, 1].into_iter().collect()) }), ].into_iter().collect(), - committed: vec![ + children: vec![ + (child_trie_key1.clone(), vec![ + (vec![100], OverlayedValue { + value: Some(vec![200]), + extrinsics: Some(vec![0, 2].into_iter().collect()) + }) + ].into_iter().collect()), + (child_trie_key2, vec![ + (vec![100], OverlayedValue { + value: Some(vec![200]), + extrinsics: Some(vec![0, 2].into_iter().collect()) + }) + ].into_iter().collect()), + ].into_iter().collect() + }, + committed: OverlayedChangeSet { top: vec![ (EXTRINSIC_INDEX.to_vec(), OverlayedValue { value: Some(3u32.encode()), extrinsics: None, @@ -264,6 +442,15 @@ mod test { extrinsics: Some(vec![1].into_iter().collect()) }), ].into_iter().collect(), + children: vec![ + (child_trie_key1, vec![ + (vec![100], OverlayedValue { + value: Some(vec![202]), + extrinsics: Some(vec![3].into_iter().collect()) + }) + ].into_iter().collect()), + ].into_iter().collect(), + }, collect_extrinsics: true, }; let config = Configuration { digest_interval: 4, digest_levels: 2 }; @@ -291,11 +478,23 @@ mod test { &changes, &parent, ).unwrap(); - assert_eq!(changes_trie_nodes.collect::>>(), vec![ + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![100] }, vec![0, 2, 3]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![101] }, vec![1]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![103] }, vec![0, 1]), ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 5u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5u64, key: vec![100] }, vec![0, 2, 3]), + ]), + (ChildIndex { block: zero + 5, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 5, key: vec![100] }, vec![0, 2]), + ]), + ]); + } test_with_zero(0); @@ -315,7 +514,7 @@ mod test { &changes, &parent, ).unwrap(); - assert_eq!(changes_trie_nodes.collect::>>(), vec![ + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), @@ -325,6 +524,22 @@ mod test { InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 4u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1]), + ]), + (ChildIndex { block: zero + 4, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2]), + ]), + ]); } test_with_zero(0); @@ -344,7 +559,7 @@ mod test { &changes, &parent, ).unwrap(); - assert_eq!(changes_trie_nodes.collect::>>(), vec![ + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![100] }, vec![0, 2, 3]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![101] }, vec![1]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![103] }, vec![0, 1]), @@ -355,6 +570,19 @@ mod test { InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![103] }, vec![zero + 4]), InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![105] }, vec![zero + 4, zero + 8]), ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 16u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 16, key: vec![102] }, vec![zero + 4]), + ]), + (ChildIndex { block: zero + 16, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 16, key: vec![100] }, vec![0, 2]), + ]), + ]); } test_with_zero(0); @@ -376,7 +604,7 @@ mod test { &changes, &parent, ).unwrap(); - assert_eq!(changes_trie_nodes.collect::>>(), vec![ + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![100] }, vec![0, 2, 3]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![101] }, vec![1]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![103] }, vec![0, 1]), @@ -390,7 +618,7 @@ mod test { &changes, &parent, ).unwrap(); - assert_eq!(changes_trie_nodes.collect::>>(), vec![ + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![100] }, vec![0, 2, 3]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![101] }, vec![1]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 11, key: vec![103] }, vec![0, 1]), @@ -427,7 +655,7 @@ mod test { &changes, &parent, ).unwrap(); - assert_eq!(changes_trie_nodes.collect::>>(), vec![ + assert_eq!(changes_trie_nodes.0.collect::>>(), vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2, 3]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![101] }, vec![1]), InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![103] }, vec![0, 1]), @@ -437,10 +665,94 @@ mod test { InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1, zero + 3]), ]); + assert_eq!(changes_trie_nodes.1.into_iter() + .map(|(k,v)| (k, v.collect::>())).collect::>(), vec![ + (ChildIndex { block: zero + 4u64, storage_key: b"1".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![100] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![101] }, vec![zero + 1]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![102] }, vec![zero + 2]), + InputPair::DigestIndex(DigestIndex { block: zero + 4, key: vec![105] }, vec![zero + 1]), + ]), + (ChildIndex { block: zero + 4, storage_key: b"2".to_vec() }, + vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: zero + 4, key: vec![100] }, vec![0, 2]), + ]), + ]); + } test_with_zero(0); test_with_zero(16); test_with_zero(17); } + + #[test] + fn cache_is_used_when_changes_trie_is_built() { + let (backend, mut storage, changes, config) = prepare_for_build(0); + let parent = AnchorBlockId { hash: Default::default(), number: 15 }; + + // override some actual values from storage with values from the cache + // + // top-level storage: + // (keys 100, 101, 103, 105 are now missing from block#4 => they do not appear + // in l2 digest at block 16) + // + // "1" child storage: + // key 102 is now missing from block#4 => it doesn't appear in l2 digest at block 16 + // (keys 103, 104) are now added to block#4 => they appear in l2 digest at block 16 + // + // "2" child storage: + // (keys 105, 106) are now added to block#4 => they appear in l2 digest at block 16 + let trie_root4 = storage.root(&parent, 4).unwrap().unwrap(); + let cached_data4 = IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()) + .set_digest_input_blocks(vec![1, 2, 3]) + .insert(None, vec![vec![100], vec![102]].into_iter().collect()) + .insert(Some(b"1".to_vec()), vec![vec![103], vec![104]].into_iter().collect()) + .insert(Some(b"2".to_vec()), vec![vec![105], vec![106]].into_iter().collect()) + .complete(4, &trie_root4); + storage.cache_mut().perform(cached_data4); + + let (root_changes_trie_nodes, child_changes_tries_nodes, _) = prepare_input( + &backend, + &storage, + configuration_range(&config, 0), + &changes, + &parent, + ).unwrap(); + assert_eq!(root_changes_trie_nodes.collect::>>(), vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![100] }, vec![0, 2, 3]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![101] }, vec![1]), + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![103] }, vec![0, 1]), + + InputPair::DigestIndex(DigestIndex { block: 16, key: vec![100] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16, key: vec![102] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16, key: vec![105] }, vec![8]), + ]); + + let child_changes_tries_nodes = child_changes_tries_nodes + .into_iter() + .map(|(k, i)| (k, i.collect::>())) + .collect::>(); + assert_eq!( + child_changes_tries_nodes.get(&ChildIndex { block: 16u64, storage_key: b"1".to_vec() }).unwrap(), + &vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16u64, key: vec![100] }, vec![0, 2, 3]), + + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![103] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![104] }, vec![4]), + ], + ); + assert_eq!( + child_changes_tries_nodes.get(&ChildIndex { block: 16u64, storage_key: b"2".to_vec() }).unwrap(), + &vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16u64, key: vec![100] }, vec![0, 2]), + + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![105] }, vec![4]), + InputPair::DigestIndex(DigestIndex { block: 16u64, key: vec![106] }, vec![4]), + ], + ); + } } diff --git a/core/state-machine/src/changes_trie/build_cache.rs b/core/state-machine/src/changes_trie/build_cache.rs new file mode 100644 index 0000000000000000000000000000000000000000..f5c7c28b6b8016dec445bc252c432795a9be91d5 --- /dev/null +++ b/core/state-machine/src/changes_trie/build_cache.rs @@ -0,0 +1,262 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Changes tries build cache. + +use std::collections::{HashMap, HashSet}; + +/// Changes trie build cache. +/// +/// Helps to avoid read of changes tries from the database when digest trie +/// is built. It holds changed keys for every block (indexed by changes trie +/// root) that could be referenced by future digest items. For digest entries +/// it also holds keys covered by this digest. Entries for top level digests +/// are never created, because they'll never be used to build other digests. +/// +/// Entries are pruned from the cache once digest block that is using this entry +/// is inserted (because digest block will includes all keys from this entry). +/// When there's a fork, entries are pruned when first changes trie is inserted. +pub struct BuildCache { + /// Map of block (implies changes true) number => changes trie root. + roots_by_number: HashMap, + /// Map of changes trie root => set of storage keys that are in this trie. + /// The `Option>` in inner `HashMap` stands for the child storage key. + /// If it is `None`, then the `HashSet` contains keys changed in top-level storage. + /// If it is `Some`, then the `HashSet` contains keys changed in child storage, identified by the key. + changed_keys: HashMap>, HashSet>>>, +} + +/// The action to perform when block-with-changes-trie is imported. +#[derive(Debug, PartialEq)] +pub enum CacheAction { + /// Cache data that has been collected when CT has been built. + CacheBuildData(CachedBuildData), + /// Clear cache from all existing entries. + Clear, +} + +/// The data that has been cached during changes trie building. +#[derive(Debug, PartialEq)] +pub struct CachedBuildData { + block: N, + trie_root: H, + digest_input_blocks: Vec, + changed_keys: HashMap>, HashSet>>, +} + +/// The action to perform when block-with-changes-trie is imported. +#[derive(Debug, PartialEq)] +pub(crate) enum IncompleteCacheAction { + /// Cache data that has been collected when CT has been built. + CacheBuildData(IncompleteCachedBuildData), + /// Clear cache from all existing entries. + Clear, +} + +/// The data (without changes trie root) that has been cached during changes trie building. +#[derive(Debug, PartialEq)] +pub(crate) struct IncompleteCachedBuildData { + digest_input_blocks: Vec, + changed_keys: HashMap>, HashSet>>, +} + +impl BuildCache + where + N: Eq + ::std::hash::Hash, + H: Eq + ::std::hash::Hash + Clone, +{ + /// Create new changes trie build cache. + pub fn new() -> Self { + BuildCache { + roots_by_number: HashMap::new(), + changed_keys: HashMap::new(), + } + } + + /// Get cached changed keys for changes trie with given root. + pub fn get(&self, root: &H) -> Option<&HashMap>, HashSet>>> { + self.changed_keys.get(&root) + } + + /// Execute given functor with cached entry for given block. + /// Returns true if the functor has been called and false otherwise. + pub fn with_changed_keys( + &self, + root: &H, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool { + match self.changed_keys.get(&root) { + Some(changed_keys) => { + functor(changed_keys); + true + }, + None => false, + } + } + + /// Insert data into cache. + pub fn perform(&mut self, action: CacheAction) { + match action { + CacheAction::CacheBuildData(data) => { + self.roots_by_number.insert(data.block, data.trie_root.clone()); + self.changed_keys.insert(data.trie_root, data.changed_keys); + + for digest_input_block in data.digest_input_blocks { + let digest_input_block_hash = self.roots_by_number.remove(&digest_input_block); + if let Some(digest_input_block_hash) = digest_input_block_hash { + self.changed_keys.remove(&digest_input_block_hash); + } + } + }, + CacheAction::Clear => { + self.roots_by_number.clear(); + self.changed_keys.clear(); + }, + } + } +} + +impl IncompleteCacheAction { + /// Returns true if we need to collect changed keys for this action. + pub fn collects_changed_keys(&self) -> bool { + match *self { + IncompleteCacheAction::CacheBuildData(_) => true, + IncompleteCacheAction::Clear => false, + } + } + + /// Complete cache action with computed changes trie root. + pub(crate) fn complete(self, block: N, trie_root: &H) -> CacheAction { + match self { + IncompleteCacheAction::CacheBuildData(build_data) => + CacheAction::CacheBuildData(build_data.complete(block, trie_root.clone())), + IncompleteCacheAction::Clear => CacheAction::Clear, + } + } + + /// Set numbers of blocks that are superseded by this new entry. + /// + /// If/when this build data is committed to the cache, entries for these blocks + /// will be removed from the cache. + pub(crate) fn set_digest_input_blocks(self, digest_input_blocks: Vec) -> Self { + match self { + IncompleteCacheAction::CacheBuildData(build_data) => + IncompleteCacheAction::CacheBuildData(build_data.set_digest_input_blocks(digest_input_blocks)), + IncompleteCacheAction::Clear => IncompleteCacheAction::Clear, + } + } + + /// Insert changed keys of given storage into cached data. + pub(crate) fn insert( + self, + storage_key: Option>, + changed_keys: HashSet>, + ) -> Self { + match self { + IncompleteCacheAction::CacheBuildData(build_data) => + IncompleteCacheAction::CacheBuildData(build_data.insert(storage_key, changed_keys)), + IncompleteCacheAction::Clear => IncompleteCacheAction::Clear, + } + } +} + +impl IncompleteCachedBuildData { + /// Create new cached data. + pub(crate) fn new() -> Self { + IncompleteCachedBuildData { + digest_input_blocks: Vec::new(), + changed_keys: HashMap::new(), + } + } + + fn complete(self, block: N, trie_root: H) -> CachedBuildData { + CachedBuildData { + block, + trie_root, + digest_input_blocks: self.digest_input_blocks, + changed_keys: self.changed_keys, + } + } + + fn set_digest_input_blocks(mut self, digest_input_blocks: Vec) -> Self { + self.digest_input_blocks = digest_input_blocks; + self + } + + fn insert( + mut self, + storage_key: Option>, + changed_keys: HashSet>, + ) -> Self { + self.changed_keys.insert(storage_key, changed_keys); + self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn updated_keys_are_stored_when_non_top_level_digest_is_built() { + let mut data = IncompleteCachedBuildData::::new(); + data = data.insert(None, vec![vec![1]].into_iter().collect()); + assert_eq!(data.changed_keys.len(), 1); + + let mut cache = BuildCache::new(); + cache.perform(CacheAction::CacheBuildData(data.complete(1, 1))); + assert_eq!(cache.changed_keys.len(), 1); + assert_eq!( + cache.get(&1).unwrap().clone(), + vec![(None, vec![vec![1]].into_iter().collect())].into_iter().collect(), + ); + } + + #[test] + fn obsolete_entries_are_purged_when_new_ct_is_built() { + let mut cache = BuildCache::::new(); + cache.perform(CacheAction::CacheBuildData(IncompleteCachedBuildData::new() + .insert(None, vec![vec![1]].into_iter().collect()) + .complete(1, 1))); + cache.perform(CacheAction::CacheBuildData(IncompleteCachedBuildData::new() + .insert(None, vec![vec![2]].into_iter().collect()) + .complete(2, 2))); + cache.perform(CacheAction::CacheBuildData(IncompleteCachedBuildData::new() + .insert(None, vec![vec![3]].into_iter().collect()) + .complete(3, 3))); + + assert_eq!(cache.changed_keys.len(), 3); + + cache.perform(CacheAction::CacheBuildData(IncompleteCachedBuildData::new() + .set_digest_input_blocks(vec![1, 2, 3]) + .complete(4, 4))); + + assert_eq!(cache.changed_keys.len(), 1); + + cache.perform(CacheAction::CacheBuildData(IncompleteCachedBuildData::new() + .insert(None, vec![vec![8]].into_iter().collect()) + .complete(8, 8))); + cache.perform(CacheAction::CacheBuildData(IncompleteCachedBuildData::new() + .insert(None, vec![vec![12]].into_iter().collect()) + .complete(12, 12))); + + assert_eq!(cache.changed_keys.len(), 3); + + cache.perform(CacheAction::Clear); + + assert_eq!(cache.changed_keys.len(), 0); + } +} \ No newline at end of file diff --git a/core/state-machine/src/changes_trie/build_iterator.rs b/core/state-machine/src/changes_trie/build_iterator.rs index 3a1ed738c18bc71dfab30004963d897eae7b52ba..36b6dd198316d769af467e3c0e93243680b22487 100644 --- a/core/state-machine/src/changes_trie/build_iterator.rs +++ b/core/state-machine/src/changes_trie/build_iterator.rs @@ -91,6 +91,8 @@ impl Iterator for DigestBuildIterator { type Item = Number; fn next(&mut self) -> Option { + // when we're building skewed digest, we might want to skip some blocks if + // they're not covered by current configuration loop { if let Some(next) = self.current_range.as_mut().and_then(|iter| iter.next()) { if next < self.end { diff --git a/core/state-machine/src/changes_trie/changes_iterator.rs b/core/state-machine/src/changes_trie/changes_iterator.rs index 397bc89857c7ce5a4c132f7bbe723bb652310ef6..e8730a1bddedb7a631a8159a5fcf3b36809ff3a3 100644 --- a/core/state-machine/src/changes_trie/changes_iterator.rs +++ b/core/state-machine/src/changes_trie/changes_iterator.rs @@ -26,6 +26,7 @@ use trie::Recorder; use crate::changes_trie::{AnchorBlockId, ConfigurationRange, RootsStorage, Storage, BlockNumber}; use crate::changes_trie::input::{DigestIndex, ExtrinsicIndex, DigestIndexValue, ExtrinsicIndexValue}; use crate::changes_trie::storage::{TrieBackendAdapter, InMemoryStorage}; +use crate::changes_trie::input::ChildIndex; use crate::changes_trie::surface_iterator::{surface_iterator, SurfaceIterator}; use crate::proving_backend::ProvingBackendEssence; use crate::trie_backend_essence::{TrieBackendEssence}; @@ -39,6 +40,7 @@ pub fn key_changes<'a, H: Hasher, Number: BlockNumber>( begin: Number, end: &'a AnchorBlockId, max: Number, + storage_key: Option<&'a [u8]>, key: &'a [u8], ) -> Result, String> { // we can't query any roots before root @@ -46,6 +48,7 @@ pub fn key_changes<'a, H: Hasher, Number: BlockNumber>( Ok(DrilldownIterator { essence: DrilldownIteratorEssence { + storage_key, key, roots_storage: storage.as_roots_storage(), storage, @@ -67,6 +70,7 @@ pub fn key_changes<'a, H: Hasher, Number: BlockNumber>( }) } + /// Returns proof of changes of given key at given blocks range. /// `max` is the number of best known block. pub fn key_changes_proof<'a, H: Hasher, Number: BlockNumber>( @@ -75,6 +79,7 @@ pub fn key_changes_proof<'a, H: Hasher, Number: BlockNumber>( begin: Number, end: &AnchorBlockId, max: Number, + storage_key: Option<&[u8]>, key: &[u8], ) -> Result>, String> { // we can't query any roots before root @@ -82,6 +87,7 @@ pub fn key_changes_proof<'a, H: Hasher, Number: BlockNumber>( let mut iter = ProvingDrilldownIterator { essence: DrilldownIteratorEssence { + storage_key, key, roots_storage: storage.as_roots_storage(), storage, @@ -121,6 +127,7 @@ pub fn key_changes_proof_check<'a, H: Hasher, Number: BlockNumber>( begin: Number, end: &AnchorBlockId, max: Number, + storage_key: Option<&[u8]>, key: &[u8] ) -> Result, String> { key_changes_proof_check_with_db( @@ -130,6 +137,7 @@ pub fn key_changes_proof_check<'a, H: Hasher, Number: BlockNumber>( begin, end, max, + storage_key, key, ) } @@ -142,6 +150,7 @@ pub fn key_changes_proof_check_with_db<'a, H: Hasher, Number: BlockNumber>( begin: Number, end: &AnchorBlockId, max: Number, + storage_key: Option<&[u8]>, key: &[u8] ) -> Result, String> { // we can't query any roots before root @@ -149,6 +158,7 @@ pub fn key_changes_proof_check_with_db<'a, H: Hasher, Number: BlockNumber>( DrilldownIterator { essence: DrilldownIteratorEssence { + storage_key, key, roots_storage, storage: proof_db, @@ -178,6 +188,7 @@ pub struct DrilldownIteratorEssence<'a, H, Number> Number: BlockNumber, H::Out: 'a, { + storage_key: Option<&'a [u8]>, key: &'a [u8], roots_storage: &'a dyn RootsStorage, storage: &'a dyn Storage, @@ -224,6 +235,25 @@ impl<'a, H, Number> DrilldownIteratorEssence<'a, H, Number> // AND trie roots for old blocks are known (both on full + light node) let trie_root = self.roots_storage.root(&self.end, block.clone())? .ok_or_else(|| format!("Changes trie root for block {} is not found", block.clone()))?; + let trie_root = if let Some(storage_key) = self.storage_key { + let child_key = ChildIndex { + block: block.clone(), + storage_key: storage_key.to_vec(), + }.encode(); + if let Some(trie_root) = trie_reader(self.storage, trie_root, &child_key)? + .and_then(|v| >::decode(&mut &v[..]).ok()) + .map(|v| { + let mut hash = H::Out::default(); + hash.as_mut().copy_from_slice(&v[..]); + hash + }) { + trie_root + } else { + continue; + } + } else { + trie_root + }; // only return extrinsics for blocks before self.max // most of blocks will be filtered out before pushing to `self.blocks` @@ -356,8 +386,10 @@ mod tests { let config = Configuration { digest_interval: 4, digest_levels: 2 }; let backend = InMemoryStorage::with_inputs(vec![ // digest: 1..4 => [(3, 0)] - (1, vec![]), - (2, vec![]), + (1, vec![ + ]), + (2, vec![ + ]), (3, vec![ InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 3, key: vec![42] }, vec![0]), ]), @@ -386,6 +418,19 @@ mod tests { (16, vec![ InputPair::DigestIndex(DigestIndex { block: 16, key: vec![42] }, vec![4, 8]), ]), + ], vec![(b"1".to_vec(), vec![ + (1, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 1, key: vec![42] }, vec![0]), + ]), + (2, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 2, key: vec![42] }, vec![3]), + ]), + (16, vec![ + InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 16, key: vec![42] }, vec![5]), + + InputPair::DigestIndex(DigestIndex { block: 16, key: vec![42] }, vec![2]), + ]), + ]), ]); (config, backend) @@ -408,6 +453,7 @@ mod tests { 1, &AnchorBlockId { hash: Default::default(), number: 16 }, 16, + None, &[42], ).and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1), (6, 3), (3, 0)])); @@ -418,6 +464,7 @@ mod tests { 1, &AnchorBlockId { hash: Default::default(), number: 2 }, 4, + None, &[42], ).and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![])); @@ -428,6 +475,7 @@ mod tests { 1, &AnchorBlockId { hash: Default::default(), number: 3 }, 4, + None, &[42], ).and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(3, 0)])); @@ -438,6 +486,7 @@ mod tests { 1, &AnchorBlockId { hash: Default::default(), number: 7 }, 7, + None, &[42], ).and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(6, 3), (3, 0)])); @@ -448,6 +497,7 @@ mod tests { 7, &AnchorBlockId { hash: Default::default(), number: 8 }, 8, + None, &[42], ).and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1)])); @@ -458,6 +508,7 @@ mod tests { 5, &AnchorBlockId { hash: Default::default(), number: 7 }, 8, + None, &[42], ).and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(6, 3)])); @@ -474,6 +525,17 @@ mod tests { 1, &AnchorBlockId { hash: Default::default(), number: 100 }, 1000, + None, + &[42], + ).and_then(|i| i.collect::, _>>()).is_err()); + + assert!(key_changes::( + configuration_range(&config, 0), + &storage, + 1, + &AnchorBlockId { hash: Default::default(), number: 100 }, + 1000, + Some(&b"1"[..]), &[42], ).and_then(|i| i.collect::, _>>()).is_err()); } @@ -487,6 +549,7 @@ mod tests { 1, &AnchorBlockId { hash: Default::default(), number: 100 }, 50, + None, &[42], ).is_err()); assert!(key_changes::( @@ -495,6 +558,7 @@ mod tests { 20, &AnchorBlockId { hash: Default::default(), number: 10 }, 100, + None, &[42], ).is_err()); } @@ -507,8 +571,13 @@ mod tests { // create drilldown iterator that records all trie nodes during drilldown let (remote_config, remote_storage) = prepare_for_drilldown(); let remote_proof = key_changes_proof::( - configuration_range(&remote_config, 0), &remote_storage, - 1, &AnchorBlockId { hash: Default::default(), number: 16 }, 16, &[42]).unwrap(); + configuration_range(&remote_config, 0), &remote_storage, 1, + &AnchorBlockId { hash: Default::default(), number: 16 }, 16, None, &[42]).unwrap(); + + let (remote_config, remote_storage) = prepare_for_drilldown(); + let remote_proof_child = key_changes_proof::( + configuration_range(&remote_config, 0), &remote_storage, 1, + &AnchorBlockId { hash: Default::default(), number: 16 }, 16, Some(&b"1"[..]), &[42]).unwrap(); // happens on local light node: @@ -516,11 +585,18 @@ mod tests { let (local_config, local_storage) = prepare_for_drilldown(); local_storage.clear_storage(); let local_result = key_changes_proof_check::( - configuration_range(&local_config, 0), &local_storage, remote_proof, - 1, &AnchorBlockId { hash: Default::default(), number: 16 }, 16, &[42]); + configuration_range(&local_config, 0), &local_storage, remote_proof, 1, + &AnchorBlockId { hash: Default::default(), number: 16 }, 16, None, &[42]); + + let (local_config, local_storage) = prepare_for_drilldown(); + local_storage.clear_storage(); + let local_result_child = key_changes_proof_check::( + configuration_range(&local_config, 0), &local_storage, remote_proof_child, 1, + &AnchorBlockId { hash: Default::default(), number: 16 }, 16, Some(&b"1"[..]), &[42]); // check that drilldown result is the same as if it was happening at the full node assert_eq!(local_result, Ok(vec![(8, 2), (8, 1), (6, 3), (3, 0)])); + assert_eq!(local_result_child, Ok(vec![(16, 5), (2, 3)])); } #[test] @@ -543,11 +619,17 @@ mod tests { input[79 - 1].1.push(InputPair::ExtrinsicIndex(ExtrinsicIndex { block: 79, key: vec![42] }, vec![1])); input[80 - 1].1.push(InputPair::DigestIndex(DigestIndex { block: 80, key: vec![42] }, vec![79])); input[91 - 1].1.push(InputPair::DigestIndex(DigestIndex { block: 91, key: vec![42] }, vec![80])); - let storage = InMemoryStorage::with_inputs(input); + let storage = InMemoryStorage::with_inputs(input, vec![]); let drilldown_result = key_changes::( - config_range, &storage, 1, &AnchorBlockId { hash: Default::default(), number: 91 }, 100_000u64, &[42]) - .and_then(Result::from_iter); + config_range, + &storage, + 1, + &AnchorBlockId { hash: Default::default(), number: 91 }, + 100_000u64, + None, + &[42], + ).and_then(Result::from_iter); assert_eq!(drilldown_result, Ok(vec![(79, 1), (63, 0)])); } } diff --git a/core/state-machine/src/changes_trie/input.rs b/core/state-machine/src/changes_trie/input.rs index 8da4f1a3862cb0cb813cf36287ce122cfa0c3d71..e0bcad18be114fe58ed55cfbf2cb0123ac612ec3 100644 --- a/core/state-machine/src/changes_trie/input.rs +++ b/core/state-machine/src/changes_trie/input.rs @@ -40,9 +40,22 @@ pub struct DigestIndex { pub key: Vec, } +/// Key of { childtrie key => Childchange trie } mapping. +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct ChildIndex { + /// Block at which this key has been inserted in the trie. + pub block: Number, + /// Storage key this node is responsible for. + pub storage_key: Vec, +} + /// Value of { changed key => block/digest block numbers } mapping. pub type DigestIndexValue = Vec; +/// Value of { changed key => block/digest block numbers } mapping. +/// That is the root of the child change trie. +pub type ChildIndexValue = Vec; + /// Single input pair of changes trie. #[derive(Clone, Debug, PartialEq, Eq)] pub enum InputPair { @@ -50,6 +63,8 @@ pub enum InputPair { ExtrinsicIndex(ExtrinsicIndex, ExtrinsicIndexValue), /// Element of { key => set of blocks/digest blocks where key has been changed } element mapping. DigestIndex(DigestIndex, DigestIndexValue), + /// Element of { childtrie key => Childchange trie } where key has been changed } element mapping. + ChildIndex(ChildIndex, ChildIndexValue), } /// Single input key of changes trie. @@ -59,6 +74,19 @@ pub enum InputKey { ExtrinsicIndex(ExtrinsicIndex), /// Key of { key => set of blocks/digest blocks where key has been changed } element mapping. DigestIndex(DigestIndex), + /// Key of { childtrie key => Childchange trie } where key has been changed } element mapping. + ChildIndex(ChildIndex), +} + +impl InputPair { + /// Extract storage key that this pair corresponds to. + pub fn key(&self) -> Option<&[u8]> { + match *self { + InputPair::ExtrinsicIndex(ref key, _) => Some(&key.key), + InputPair::DigestIndex(ref key, _) => Some(&key.key), + InputPair::ChildIndex(_, _) => None, + } + } } impl Into<(Vec, Vec)> for InputPair { @@ -66,6 +94,7 @@ impl Into<(Vec, Vec)> for InputPair { match self { InputPair::ExtrinsicIndex(key, value) => (key.encode(), value.encode()), InputPair::DigestIndex(key, value) => (key.encode(), value.encode()), + InputPair::ChildIndex(key, value) => (key.encode(), value.encode()), } } } @@ -75,6 +104,7 @@ impl Into> for InputPair { match self { InputPair::ExtrinsicIndex(key, _) => InputKey::ExtrinsicIndex(key), InputPair::DigestIndex(key, _) => InputKey::DigestIndex(key), + InputPair::ChildIndex(key, _) => InputKey::ChildIndex(key), } } } @@ -114,6 +144,22 @@ impl Encode for DigestIndex { } } +impl ChildIndex { + pub fn key_neutral_prefix(block: Number) -> Vec { + let mut prefix = vec![3]; + prefix.extend(block.encode()); + prefix + } +} + +impl Encode for ChildIndex { + fn encode_to(&self, dest: &mut W) { + dest.push_byte(3); + self.block.encode_to(dest); + self.storage_key.encode_to(dest); + } +} + impl codec::EncodeLike for DigestIndex {} impl Decode for InputKey { @@ -127,6 +173,10 @@ impl Decode for InputKey { block: Decode::decode(input)?, key: Decode::decode(input)?, })), + 3 => Ok(InputKey::ChildIndex(ChildIndex { + block: Decode::decode(input)?, + storage_key: Decode::decode(input)?, + })), _ => Err("Invalid input key variant".into()), } } diff --git a/core/state-machine/src/changes_trie/mod.rs b/core/state-machine/src/changes_trie/mod.rs index c03346d776756c79f44667870b5bb8244a37a152..9d88352cb74654397714ab58c0c0614269636665 100644 --- a/core/state-machine/src/changes_trie/mod.rs +++ b/core/state-machine/src/changes_trie/mod.rs @@ -32,10 +32,24 @@ //! the last N*digest_level-1 blocks (except for genesis block), mapping these keys //! to the set of lower-level digest blocks. //! +//! Changes trie configuration could change within a time. The range of blocks, where +//! configuration has been active, is given by two blocks: zero and end. Zero block is +//! the block where configuration has been set. But the first changes trie that uses +//! this configuration will be built at the block zero+1. If configuration deactivates +//! at some block, this will be the end block of the configuration. It is also the +//! zero block of the next configuration. +//! +//! If configuration has the end block, it also means that 'skewed digest' has/should +//! been built at that block. If this is the block where max-level digest should have +//! been created, than it is simply max-level digest of this configuration. Otherwise, +//! it is the digest that covers all blocks since last max-level digest block was +//! created. +//! //! Changes trie only contains the top level storage changes. Sub-level changes //! are propagated through its storage root on the top level storage. mod build; +mod build_cache; mod build_iterator; mod changes_iterator; mod input; @@ -43,6 +57,7 @@ mod prune; mod storage; mod surface_iterator; +pub use self::build_cache::{BuildCache, CachedBuildData, CacheAction}; pub use self::storage::InMemoryStorage; pub use self::changes_iterator::{ key_changes, key_changes_proof, @@ -50,6 +65,7 @@ pub use self::changes_iterator::{ }; pub use self::prune::prune; +use std::collections::{HashMap, HashSet}; use std::convert::TryInto; use hash_db::{Hasher, Prefix}; use crate::backend::Backend; @@ -57,6 +73,7 @@ use num_traits::{One, Zero}; use codec::{Decode, Encode}; use primitives; use crate::changes_trie::build::prepare_input; +use crate::changes_trie::build_cache::{IncompleteCachedBuildData, IncompleteCacheAction}; use crate::overlayed_changes::OverlayedChanges; use trie::{MemoryDB, DBValue, TrieMut}; use trie::trie_types::TrieDBMut; @@ -71,6 +88,7 @@ pub trait BlockNumber: Clone + From + TryInto + One + Zero + PartialEq + Ord + + ::std::hash::Hash + ::std::ops::Add + ::std::ops::Sub + ::std::ops::Mul + ::std::ops::Div + ::std::ops::Rem + @@ -85,6 +103,7 @@ impl BlockNumber for T where T: Clone + From + TryInto + One + Zero + PartialEq + Ord + + ::std::hash::Hash + ::std::ops::Add + ::std::ops::Sub + ::std::ops::Mul + ::std::ops::Div + ::std::ops::Rem + @@ -127,6 +146,13 @@ pub trait RootsStorage: Send + Sync { pub trait Storage: RootsStorage { /// Casts from self reference to RootsStorage reference. fn as_roots_storage(&self) -> &dyn RootsStorage; + /// Execute given functor with cached entry for given trie root. + /// Returns true if the functor has been called (cache entry exists) and false otherwise. + fn with_cached_changed_keys( + &self, + root: &H::Out, + functor: &mut dyn FnMut(&HashMap>, HashSet>>), + ) -> bool; /// Get a trie node. fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String>; } @@ -185,7 +211,7 @@ pub fn build_changes_trie<'a, B: Backend, H: Hasher, Number: BlockNumber>( state: Option<&'a State<'a, H, Number>>, changes: &OverlayedChanges, parent_hash: H::Out, -) -> Result, H::Out)>, ()> +) -> Result, H::Out, CacheAction)>, ()> where H::Out: Ord + 'static, { @@ -195,8 +221,9 @@ pub fn build_changes_trie<'a, B: Backend, H: Hasher, Number: BlockNumber>( None => return Ok(None), }; - // build_anchor error should not be considered fatal (passed parent_hash may be incorrect) + // build_anchor error should not be considered fatal let parent = state.storage.build_anchor(parent_hash).map_err(|_| ())?; + let block = parent.number.clone() + One::one(); // prepare configuration range - we already know zero block. Current block may be the end block if configuration // has been changed in this block @@ -212,22 +239,137 @@ pub fn build_changes_trie<'a, B: Backend, H: Hasher, Number: BlockNumber>( }; // storage errors are considered fatal (similar to situations when runtime fetches values from storage) - let input_pairs = prepare_input::( + let (input_pairs, child_input_pairs, digest_input_blocks) = prepare_input::( backend, state.storage, - config_range, + config_range.clone(), changes, &parent, ).expect("changes trie: storage access is not allowed to fail within runtime"); - let mut root = Default::default(); + + // prepare cached data + let mut cache_action = prepare_cached_build_data(config_range, block.clone()); + let needs_changed_keys = cache_action.collects_changed_keys(); + cache_action = cache_action.set_digest_input_blocks(digest_input_blocks); + let mut mdb = MemoryDB::default(); + let mut child_roots = Vec::with_capacity(child_input_pairs.len()); + for (child_index, input_pairs) in child_input_pairs { + let mut not_empty = false; + let mut root = Default::default(); + { + let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + let mut storage_changed_keys = HashSet::new(); + for input_pair in input_pairs { + if needs_changed_keys { + if let Some(key) = input_pair.key() { + storage_changed_keys.insert(key.to_vec()); + } + } + + let (key, value) = input_pair.into(); + not_empty = true; + trie.insert(&key, &value) + .expect("changes trie: insertion to trie is not allowed to fail within runtime"); + } + + cache_action = cache_action.insert( + Some(child_index.storage_key.clone()), + storage_changed_keys, + ); + } + if not_empty { + child_roots.push(input::InputPair::ChildIndex(child_index, root.as_ref().to_vec())); + } + } + let mut root = Default::default(); { let mut trie = TrieDBMut::::new(&mut mdb, &mut root); - for (key, value) in input_pairs.map(Into::into) { + for (key, value) in child_roots.into_iter().map(Into::into) { + trie.insert(&key, &value) + .expect("changes trie: insertion to trie is not allowed to fail within runtime"); + } + + let mut storage_changed_keys = HashSet::new(); + for input_pair in input_pairs { + if needs_changed_keys { + if let Some(key) = input_pair.key() { + storage_changed_keys.insert(key.to_vec()); + } + } + + let (key, value) = input_pair.into(); trie.insert(&key, &value) .expect("changes trie: insertion to trie is not allowed to fail within runtime"); } + cache_action = cache_action.insert( + None, + storage_changed_keys, + ); } - Ok(Some((mdb, root))) + let cache_action = cache_action.complete(block, &root); + Ok(Some((mdb, root, cache_action))) +} + +/// Prepare empty cached build data for given block. +fn prepare_cached_build_data( + config: ConfigurationRange, + block: Number, +) -> IncompleteCacheAction { + // when digests are not enabled in configuration, we do not need to cache anything + // because it'll never be used again for building other tries + // => let's clear the cache + if !config.config.is_digest_build_enabled() { + return IncompleteCacheAction::Clear; + } + + // when this is the last block where current configuration is active + // => let's clear the cache + if config.end.as_ref() == Some(&block) { + return IncompleteCacheAction::Clear; + } + + // we do not need to cache anything when top-level digest trie is created, because + // it'll never be used again for building other tries + // => let's clear the cache + match config.config.digest_level_at_block(config.zero.clone(), block) { + Some((digest_level, _, _)) if digest_level == config.config.digest_levels => IncompleteCacheAction::Clear, + _ => IncompleteCacheAction::CacheBuildData(IncompleteCachedBuildData::new()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cache_is_cleared_when_digests_are_disabled() { + let config = Configuration { digest_interval: 0, digest_levels: 0 }; + let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; + assert_eq!(prepare_cached_build_data(config_range, 8u32), IncompleteCacheAction::Clear); + } + + #[test] + fn build_data_is_cached_when_digests_are_enabled() { + let config = Configuration { digest_interval: 8, digest_levels: 2 }; + let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; + assert!(prepare_cached_build_data(config_range.clone(), 4u32).collects_changed_keys()); + assert!(prepare_cached_build_data(config_range.clone(), 7u32).collects_changed_keys()); + assert!(prepare_cached_build_data(config_range, 8u32).collects_changed_keys()); + } + + #[test] + fn cache_is_cleared_when_digests_are_enabled_and_top_level_digest_is_built() { + let config = Configuration { digest_interval: 8, digest_levels: 2 }; + let config_range = ConfigurationRange { zero: 0, end: None, config: &config }; + assert_eq!(prepare_cached_build_data(config_range, 64u32), IncompleteCacheAction::Clear); + } + + #[test] + fn cache_is_cleared_when_end_block_of_configuration_is_built() { + let config = Configuration { digest_interval: 8, digest_levels: 2 }; + let config_range = ConfigurationRange { zero: 0, end: Some(4u32), config: &config }; + assert_eq!(prepare_cached_build_data(config_range.clone(), 4u32), IncompleteCacheAction::Clear); + } } diff --git a/core/state-machine/src/changes_trie/prune.rs b/core/state-machine/src/changes_trie/prune.rs index fab0f6ac7f9758659b7df014206278d4ce24032d..aa3be9ce52773c29ce238aec94f2e9b61304d4fb 100644 --- a/core/state-machine/src/changes_trie/prune.rs +++ b/core/state-machine/src/changes_trie/prune.rs @@ -24,13 +24,15 @@ use crate::proving_backend::ProvingBackendEssence; use crate::trie_backend_essence::TrieBackendEssence; use crate::changes_trie::{AnchorBlockId, Storage, BlockNumber}; use crate::changes_trie::storage::TrieBackendAdapter; +use crate::changes_trie::input::{ChildIndex, InputKey}; +use codec::Decode; /// Prune obsolete changes tries. Pruning happens at the same block, where highest /// level digest is created. Pruning guarantees to save changes tries for last /// `min_blocks_to_keep` blocks. We only prune changes tries at `max_digest_interval` /// ranges. pub fn prune( - storage: &Storage, + storage: &dyn Storage, first: Number, last: Number, current_block: &AnchorBlockId, @@ -56,23 +58,55 @@ pub fn prune( continue; }, }; - - // enumerate all changes trie' keys, recording all nodes that have been 'touched' - // (effectively - all changes trie nodes) - let mut proof_recorder: Recorder = Default::default(); - { - let mut trie = ProvingBackendEssence::<_, H> { - backend: &TrieBackendEssence::new(TrieBackendAdapter::new(storage), root), - proof_recorder: &mut proof_recorder, - }; - trie.record_all_keys(); + let children_roots = { + let trie_storage = TrieBackendEssence::<_, H>::new( + crate::changes_trie::TrieBackendStorageAdapter(storage), + root, + ); + let child_prefix = ChildIndex::key_neutral_prefix(block.clone()); + let mut children_roots = Vec::new(); + trie_storage.for_key_values_with_prefix(&child_prefix, |key, value| { + if let Ok(InputKey::ChildIndex::(_trie_key)) = Decode::decode(&mut &key[..]) { + if let Ok(value) = >::decode(&mut &value[..]) { + let mut trie_root = ::Out::default(); + trie_root.as_mut().copy_from_slice(&value[..]); + children_roots.push(trie_root); + } + } + }); + + children_roots + }; + for root in children_roots.into_iter() { + prune_trie(storage, root, &mut remove_trie_node); } - // all nodes of this changes trie should be pruned - remove_trie_node(root); - for node in proof_recorder.drain().into_iter().map(|n| n.hash) { - remove_trie_node(node); - } + prune_trie(storage, root, &mut remove_trie_node); + } +} + +// Prune a trie. +fn prune_trie( + storage: &dyn Storage, + root: H::Out, + remove_trie_node: &mut F, +) { + + // enumerate all changes trie' keys, recording all nodes that have been 'touched' + // (effectively - all changes trie nodes) + let mut proof_recorder: Recorder = Default::default(); + { + let mut trie = ProvingBackendEssence::<_, H> { + backend: &TrieBackendEssence::new(TrieBackendAdapter::new(storage), root), + proof_recorder: &mut proof_recorder, + }; + trie.record_all_keys(); + } + + // all nodes of this changes trie should be pruned + remove_trie_node(root); + for node in proof_recorder.drain().into_iter().map(|n| n.hash) { + remove_trie_node(node); } } @@ -83,10 +117,11 @@ mod tests { use primitives::{H256, Blake2Hasher}; use crate::backend::insert_into_memory_db; use crate::changes_trie::storage::InMemoryStorage; + use codec::Encode; use super::*; fn prune_by_collect( - storage: &Storage, + storage: &dyn Storage, first: u64, last: u64, current_block: u64, @@ -101,6 +136,8 @@ mod tests { #[test] fn prune_works() { fn prepare_storage() -> InMemoryStorage { + + let child_key = ChildIndex { block: 67u64, storage_key: b"1".to_vec() }.encode(); let mut mdb1 = MemoryDB::::default(); let root1 = insert_into_memory_db::(&mut mdb1, vec![(vec![10], vec![20])]).unwrap(); let mut mdb2 = MemoryDB::::default(); @@ -109,10 +146,12 @@ mod tests { vec![(vec![11], vec![21]), (vec![12], vec![22])], ).unwrap(); let mut mdb3 = MemoryDB::::default(); - let root3 = insert_into_memory_db::( - &mut mdb3, - vec![(vec![13], vec![23]), (vec![14], vec![24])], - ).unwrap(); + let ch_root3 = insert_into_memory_db::(&mut mdb3, vec![(vec![110], vec![120])]).unwrap(); + let root3 = insert_into_memory_db::(&mut mdb3, vec![ + (vec![13], vec![23]), + (vec![14], vec![24]), + (child_key, ch_root3.as_ref().encode()), + ]).unwrap(); let mut mdb4 = MemoryDB::::default(); let root4 = insert_into_memory_db::( &mut mdb4, diff --git a/core/state-machine/src/changes_trie/storage.rs b/core/state-machine/src/changes_trie/storage.rs index 10d5c9701e1999bea3a19a268cb9af4fb0345488..a82477bdc393310089329b070af3d7c0d1603f02 100644 --- a/core/state-machine/src/changes_trie/storage.rs +++ b/core/state-machine/src/changes_trie/storage.rs @@ -16,29 +16,28 @@ //! Changes trie storage utilities. -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashSet, HashMap}; use hash_db::{Hasher, Prefix, EMPTY_PREFIX}; use trie::DBValue; use trie::MemoryDB; use parking_lot::RwLock; -use crate::changes_trie::{RootsStorage, Storage, AnchorBlockId, BlockNumber}; +use crate::changes_trie::{BuildCache, RootsStorage, Storage, AnchorBlockId, BlockNumber}; use crate::trie_backend_essence::TrieBackendStorage; -#[cfg(test)] -use std::collections::HashSet; #[cfg(test)] use crate::backend::insert_into_memory_db; #[cfg(test)] -use crate::changes_trie::input::InputPair; +use crate::changes_trie::input::{InputPair, ChildIndex}; /// In-memory implementation of changes trie storage. pub struct InMemoryStorage { data: RwLock>, + cache: BuildCache, } /// Adapter for using changes trie storage as a TrieBackendEssence' storage. pub struct TrieBackendAdapter<'a, H: Hasher, Number: BlockNumber> { - storage: &'a Storage, + storage: &'a dyn Storage, _hasher: ::std::marker::PhantomData<(H, Number)>, } @@ -55,6 +54,7 @@ impl InMemoryStorage { roots: BTreeMap::new(), mdb, }), + cache: BuildCache::new(), } } @@ -67,28 +67,56 @@ impl InMemoryStorage { pub fn with_proof(proof: Vec>) -> Self { use hash_db::HashDB; - let mut proof_db = MemoryDB::::default(); + let mut proof_db = MemoryDB::::default(); for item in proof { proof_db.insert(EMPTY_PREFIX, &item); } Self::with_db(proof_db) } - /// Creates storage with given blocks. + /// Get mutable cache reference. + pub fn cache_mut(&mut self) -> &mut BuildCache { + &mut self.cache + } + + /// Create the storage with given blocks. pub fn with_blocks(blocks: Vec<(Number, H::Out)>) -> Self { Self { data: RwLock::new(InMemoryStorageData { roots: blocks.into_iter().collect(), mdb: MemoryDB::default(), }), + cache: BuildCache::new(), } } #[cfg(test)] - pub fn with_inputs(inputs: Vec<(Number, Vec>)>) -> Self { + pub fn with_inputs( + mut top_inputs: Vec<(Number, Vec>)>, + children_inputs: Vec<(Vec, Vec<(Number, Vec>)>)>, + ) -> Self { let mut mdb = MemoryDB::default(); let mut roots = BTreeMap::new(); - for (block, pairs) in inputs { + for (storage_key, child_input) in children_inputs { + for (block, pairs) in child_input { + let root = insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); + + if let Some(root) = root { + let ix = if let Some(ix) = top_inputs.iter().position(|v| v.0 == block) { + ix + } else { + top_inputs.push((block.clone(), Default::default())); + top_inputs.len() - 1 + }; + top_inputs[ix].1.push(InputPair::ChildIndex( + ChildIndex { block: block.clone(), storage_key: storage_key.clone() }, + root.as_ref().to_vec(), + )); + } + } + } + + for (block, pairs) in top_inputs { let root = insert_into_memory_db::(&mut mdb, pairs.into_iter().map(Into::into)); if let Some(root) = root { roots.insert(block, root); @@ -100,6 +128,7 @@ impl InMemoryStorage { roots, mdb, }), + cache: BuildCache::new(), } } @@ -147,13 +176,21 @@ impl Storage for InMemoryStorage>, HashSet>>), + ) -> bool { + self.cache.with_changed_keys(root, functor) + } + fn get(&self, key: &H::Out, prefix: Prefix) -> Result, String> { MemoryDB::::get(&self.data.read().mdb, key, prefix) } } impl<'a, H: Hasher, Number: BlockNumber> TrieBackendAdapter<'a, H, Number> { - pub fn new(storage: &'a Storage) -> Self { + pub fn new(storage: &'a dyn Storage) -> Self { Self { storage, _hasher: Default::default() } } } diff --git a/core/state-machine/src/changes_trie/surface_iterator.rs b/core/state-machine/src/changes_trie/surface_iterator.rs index 3711fac569770af163f4cdc231db8d28811a525d..f3583e2f57e6b7536217a341e32c394a60ff865f 100644 --- a/core/state-machine/src/changes_trie/surface_iterator.rs +++ b/core/state-machine/src/changes_trie/surface_iterator.rs @@ -17,13 +17,16 @@ //! The best way to understand how this iterator works is to imagine some 2D terrain that have some mountains //! (digest changes tries) and valleys (changes tries for regular blocks). There are gems (blocks) beneath the //! terrain. Given the request to find all gems in the range [X1; X2] this iterator will return **minimal set** -//! of points at the terrain (mountains and valleys() inside this range that have to be drilled down to +//! of points at the terrain (mountains and valleys) inside this range that have to be drilled down to //! search for gems. use num_traits::One; use crate::changes_trie::{ConfigurationRange, BlockNumber}; /// Returns surface iterator for given range of blocks. +/// +/// `max` is the number of best block, known to caller. We can't access any changes tries +/// that are built after this block, even though we may have them built already. pub fn surface_iterator<'a, Number: BlockNumber>( config: ConfigurationRange<'a, Number>, max: Number, @@ -226,7 +229,12 @@ mod tests { // when config activates at 0 assert_eq!( - surface_iterator(configuration_range(&config, 0u64), 100_000u64, 40u64, 180u64).unwrap().collect::>(), + surface_iterator( + configuration_range(&config, 0u64), + 100_000u64, + 40u64, + 180u64, + ).unwrap().collect::>(), vec![ Ok((192, Some(2))), Ok((176, Some(2))), Ok((160, Some(2))), Ok((144, Some(2))), Ok((128, Some(2))), Ok((112, Some(2))), Ok((96, Some(2))), Ok((80, Some(2))), @@ -236,7 +244,12 @@ mod tests { // when config activates at 30 assert_eq!( - surface_iterator(configuration_range(&config, 30u64), 100_000u64, 40u64, 180u64).unwrap().collect::>(), + surface_iterator( + configuration_range(&config, 30u64), + 100_000u64, + 40u64, + 180u64, + ).unwrap().collect::>(), vec![ Ok((190, Some(2))), Ok((174, Some(2))), Ok((158, Some(2))), Ok((142, Some(2))), Ok((126, Some(2))), Ok((110, Some(2))), Ok((94, Some(2))), Ok((78, Some(2))), Ok((62, Some(2))), Ok((46, Some(2))), diff --git a/core/state-machine/src/error.rs b/core/state-machine/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..6e6ce995858ea409dcbe3e309cb195e44eba4feb --- /dev/null +++ b/core/state-machine/src/error.rs @@ -0,0 +1,47 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +/// State Machine Errors + +use std::fmt; + +/// State Machine Error bound. +/// +/// This should reflect Wasm error type bound for future compatibility. +pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} + +impl Error for T {} + +/// Externalities Error. +/// +/// Externalities are not really allowed to have errors, since it's assumed that dependent code +/// would not be executed unless externalities were available. This is included for completeness, +/// and as a transition away from the pre-existing framework. +#[derive(Debug, Eq, PartialEq)] +pub enum ExecutionError { + /// Backend error. + Backend(String), + /// The entry `:code` doesn't exist in storage so there's no way we can execute anything. + CodeEntryDoesNotExist, + /// Backend is incompatible with execution proof generation process. + UnableToGenerateProof, + /// Invalid execution proof. + InvalidProof, +} + +impl fmt::Display for ExecutionError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } +} diff --git a/core/state-machine/src/ext.rs b/core/state-machine/src/ext.rs index 054b358aece23f3d4ab5871278c30fd74709a0ae..ac8fece23b3ace84877bd4bf51d6cedaf5fc7bd1 100644 --- a/core/state-machine/src/ext.rs +++ b/core/state-machine/src/ext.rs @@ -16,15 +16,24 @@ //! Concrete externalities implementation. -use std::{error, fmt, cmp::Ord}; -use log::warn; -use crate::backend::Backend; -use crate::changes_trie::{State as ChangesTrieState, build_changes_trie}; -use crate::{Externalities, OverlayedChanges, ChildStorageKey}; +use crate::{ + backend::Backend, OverlayedChanges, + changes_trie::{ + State as ChangesTrieState, CacheAction as ChangesTrieCacheAction, + build_changes_trie, + }, +}; + use hash_db::Hasher; -use primitives::{offchain, storage::well_known_keys::is_child_storage_key, traits::BareCryptoStorePtr}; -use trie::{MemoryDB, default_child_trie_root}; -use trie::trie_types::Layout; +use primitives::{ + storage::{ChildStorageKey, well_known_keys::is_child_storage_key}, + traits::Externalities, hexdisplay::HexDisplay, hash::H256, +}; +use trie::{trie_types::Layout, MemoryDB, default_child_trie_root}; +use externalities::Extensions; + +use std::{error, fmt, any::{Any, TypeId}}; +use log::{warn, trace}; const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; @@ -58,11 +67,7 @@ impl error::Error for Error { } /// Wraps a read-only backend, call executor, and current overlayed changes. -pub struct Ext<'a, H, N, B, O> -where - H: Hasher, - B: 'a + Backend, -{ +pub struct Ext<'a, H, N, B> where H: Hasher, B: 'a + Backend { /// The overlayed changes to write to. overlay: &'a mut OverlayedChanges, /// The storage backend to read from. @@ -76,33 +81,30 @@ where /// Set to Some when `storage_changes_root` is called. Could be replaced later /// by calling `storage_changes_root` again => never used as cache. /// This differs from `storage_transaction` behavior, because the moment when - /// `storage_changes_root` is called matters. - changes_trie_transaction: Option<(MemoryDB, H::Out)>, - /// Additional externalities for offchain workers. - /// - /// If None, some methods from the trait might not be supported. - offchain_externalities: Option<&'a mut O>, - /// The keystore that manages the keys of the node. - keystore: Option, + /// `storage_changes_root` is called matters + we need to remember additional + /// data at this moment (block number). + changes_trie_transaction: Option<(MemoryDB, H::Out, ChangesTrieCacheAction)>, + /// Pseudo-unique id used for tracing. + pub id: u16, /// Dummy usage of N arg. - _phantom: ::std::marker::PhantomData, + _phantom: std::marker::PhantomData, + /// Extensions registered with this instance. + extensions: Option<&'a mut Extensions>, } -impl<'a, H, N, B, O> Ext<'a, H, N, B, O> +impl<'a, H, N, B> Ext<'a, H, N, B> where - H: Hasher, + H: Hasher, B: 'a + Backend, - O: 'a + offchain::Externalities, - H::Out: Ord + 'static, N: crate::changes_trie::BlockNumber, { + /// Create a new `Ext` from overlayed changes and read-only backend pub fn new( overlay: &'a mut OverlayedChanges, backend: &'a B, changes_trie_state: Option<&'a ChangesTrieState<'a, H, N>>, - offchain_externalities: Option<&'a mut O>, - keystore: Option, + extensions: Option<&'a mut Extensions>, ) -> Self { Ext { overlay, @@ -110,21 +112,26 @@ where storage_transaction: None, changes_trie_state, changes_trie_transaction: None, - offchain_externalities, - keystore, + id: rand::random(), _phantom: Default::default(), + extensions, } } /// Get the transaction necessary to update the backend. - pub fn transaction(mut self) -> ((B::Transaction, H::Out), Option>) { + pub fn transaction(&mut self) -> ( + (B::Transaction, H256), + Option>, + ) { let _ = self.storage_root(); let (storage_transaction, changes_trie_transaction) = ( self.storage_transaction + .take() .expect("storage_transaction always set after calling storage root; qed"), self.changes_trie_transaction - .map(|(tx, _)| tx), + .take() + .map(|(tx, _, cache)| (tx, cache)), ); ( @@ -139,15 +146,13 @@ where fn mark_dirty(&mut self) { self.storage_transaction = None; } - } #[cfg(test)] -impl<'a, H, N, B, O> Ext<'a, H, N, B, O> +impl<'a, H, N, B> Ext<'a, H, N, B> where - H: Hasher, + H: Hasher, B: 'a + Backend, - O: 'a + offchain::Externalities, N: crate::changes_trie::BlockNumber, { pub fn storage_pairs(&self) -> Vec<(Vec, Vec)> { @@ -164,76 +169,171 @@ where } } -impl<'a, B, H, N, O> Externalities for Ext<'a, H, N, B, O> +impl<'a, H, B, N> Externalities for Ext<'a, H, N, B> where - H: Hasher, + H: Hasher, B: 'a + Backend, - O: 'a + offchain::Externalities, - H::Out: Ord + 'static, N: crate::changes_trie::BlockNumber, { fn storage(&self, key: &[u8]) -> Option> { let _guard = panic_handler::AbortGuard::force_abort(); - self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| - self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL)) + let result = self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| + self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL)); + trace!(target: "state-trace", "{:04x}: Get {}={:?}", + self.id, + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from) + ); + result } - fn storage_hash(&self, key: &[u8]) -> Option { + fn storage_hash(&self, key: &[u8]) -> Option { let _guard = panic_handler::AbortGuard::force_abort(); - self.overlay.storage(key).map(|x| x.map(|x| H::hash(x))).unwrap_or_else(|| - self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)) + let result = self.overlay + .storage(key) + .map(|x| x.map(|x| H::hash(x))) + .unwrap_or_else(|| + self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL) + ); + trace!(target: "state-trace", "{:04x}: Hash {}={:?}", + self.id, + HexDisplay::from(&key), + result, + ); + result } fn original_storage(&self, key: &[u8]) -> Option> { let _guard = panic_handler::AbortGuard::force_abort(); - self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL) + let result = self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL); + trace!(target: "state-trace", "{:04x}: GetOriginal {}={:?}", + self.id, + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from) + ); + result } - fn original_storage_hash(&self, key: &[u8]) -> Option { + fn original_storage_hash(&self, key: &[u8]) -> Option { let _guard = panic_handler::AbortGuard::force_abort(); - self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL) + let result = self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL); + trace!(target: "state-trace", "{:04x}: GetOriginalHash {}={:?}", + self.id, + HexDisplay::from(&key), + result, + ); + result } - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { let _guard = panic_handler::AbortGuard::force_abort(); - self.overlay.child_storage(storage_key.as_ref(), key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| - self.backend.child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL)) + let result = self.overlay + .child_storage(storage_key.as_ref(), key) + .map(|x| x.map(|x| x.to_vec())) + .unwrap_or_else(|| + self.backend.child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL) + ); + + trace!(target: "state-trace", "{:04x}: GetChild({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from) + ); + + result } - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { let _guard = panic_handler::AbortGuard::force_abort(); - self.overlay.child_storage(storage_key.as_ref(), key).map(|x| x.map(|x| H::hash(x))).unwrap_or_else(|| - self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)) + let result = self.overlay + .child_storage(storage_key.as_ref(), key) + .map(|x| x.map(|x| H::hash(x))) + .unwrap_or_else(|| + self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL) + ); + + trace!(target: "state-trace", "{:04x}: ChildHash({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result, + ); + + result } - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { let _guard = panic_handler::AbortGuard::force_abort(); - self.backend.child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL) + let result = self.backend + .child_storage(storage_key.as_ref(), key) + .expect(EXT_NOT_ALLOWED_TO_FAIL); + + trace!(target: "state-trace", "{:04x}: ChildOriginal({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result.as_ref().map(HexDisplay::from), + ); + result } - fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { let _guard = panic_handler::AbortGuard::force_abort(); - self.backend.child_storage_hash(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL) + let result = self.backend + .child_storage_hash(storage_key.as_ref(), key) + .expect(EXT_NOT_ALLOWED_TO_FAIL); + + trace!(target: "state-trace", "{}: ChildHashOriginal({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result, + ); + result } fn exists_storage(&self, key: &[u8]) -> bool { let _guard = panic_handler::AbortGuard::force_abort(); - match self.overlay.storage(key) { + let result = match self.overlay.storage(key) { Some(x) => x.is_some(), _ => self.backend.exists_storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL), - } + }; + + trace!(target: "state-trace", "{:04x}: Exists {}={:?}", + self.id, + HexDisplay::from(&key), + result, + ); + result + } - fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { + fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { let _guard = panic_handler::AbortGuard::force_abort(); - match self.overlay.child_storage(storage_key.as_ref(), key) { + let result = match self.overlay.child_storage(storage_key.as_ref(), key) { Some(x) => x.is_some(), - _ => self.backend.exists_child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL), - } + _ => self.backend + .exists_child_storage(storage_key.as_ref(), key) + .expect(EXT_NOT_ALLOWED_TO_FAIL), + }; + + trace!(target: "state-trace", "{:04x}: ChildExists({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + result, + ); + result } fn place_storage(&mut self, key: Vec, value: Option>) { + trace!(target: "state-trace", "{:04x}: Put {}={:?}", + self.id, + HexDisplay::from(&key), + value.as_ref().map(HexDisplay::from) + ); let _guard = panic_handler::AbortGuard::force_abort(); if is_child_storage_key(&key) { warn!(target: "trie", "Refuse to directly set child storage key"); @@ -244,14 +344,29 @@ where self.overlay.set_storage(key, value); } - fn place_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Option>) { + fn place_child_storage( + &mut self, + storage_key: ChildStorageKey, + key: Vec, + value: Option>, + ) { + trace!(target: "state-trace", "{:04x}: PutChild({}) {}={:?}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&key), + value.as_ref().map(HexDisplay::from) + ); let _guard = panic_handler::AbortGuard::force_abort(); self.mark_dirty(); self.overlay.set_child_storage(storage_key.into_owned(), key, value); } - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { + fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { + trace!(target: "state-trace", "{:04x}: KillChild({})", + self.id, + HexDisplay::from(&storage_key.as_ref()), + ); let _guard = panic_handler::AbortGuard::force_abort(); self.mark_dirty(); @@ -262,6 +377,10 @@ where } fn clear_prefix(&mut self, prefix: &[u8]) { + trace!(target: "state-trace", "{:04x}: ClearPrefix {}", + self.id, + HexDisplay::from(&prefix), + ); let _guard = panic_handler::AbortGuard::force_abort(); if is_child_storage_key(prefix) { warn!(target: "trie", "Refuse to directly clear prefix that is part of child storage key"); @@ -275,7 +394,12 @@ where }); } - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { + fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { + trace!(target: "state-trace", "{:04x}: ClearChildPrefix({}) {}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&prefix), + ); let _guard = panic_handler::AbortGuard::force_abort(); self.mark_dirty(); @@ -289,9 +413,13 @@ where 42 } - fn storage_root(&mut self) -> H::Out { + fn storage_root(&mut self) -> H256 { let _guard = panic_handler::AbortGuard::force_abort(); if let Some((_, ref root)) = self.storage_transaction { + trace!(target: "state-trace", "{:04x}: Root (cached) {}", + self.id, + HexDisplay::from(&root.as_ref()), + ); return root.clone(); } @@ -301,10 +429,10 @@ where let child_delta_iter = child_storage_keys.map(|storage_key| (storage_key.clone(), self.overlay.committed.children.get(storage_key) .into_iter() - .flat_map(|map| map.1.iter().map(|(k, v)| (k.clone(), v.clone()))) + .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.value.clone()))) .chain(self.overlay.prospective.children.get(storage_key) .into_iter() - .flat_map(|map| map.1.iter().map(|(k, v)| (k.clone(), v.clone())))))); + .flat_map(|map| map.iter().map(|(k, v)| (k.clone(), v.value.clone())))))); // compute and memoize @@ -313,37 +441,58 @@ where let (root, transaction) = self.backend.full_storage_root(delta, child_delta_iter); self.storage_transaction = Some((transaction, root)); + trace!(target: "state-trace", "{:04x}: Root {}", + self.id, + HexDisplay::from(&root.as_ref()), + ); root } - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { + fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { let _guard = panic_handler::AbortGuard::force_abort(); if self.storage_transaction.is_some() { - self + let root = self .storage(storage_key.as_ref()) .unwrap_or( default_child_trie_root::>(storage_key.as_ref()) - ) + ); + trace!(target: "state-trace", "{:04x}: ChildRoot({}) (cached) {}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&root.as_ref()), + ); + root } else { let storage_key = storage_key.as_ref(); - let delta = self.overlay.committed.children.get(storage_key) - .into_iter() - .flat_map(|map| map.1.iter().map(|(k, v)| (k.clone(), v.clone()))) - .chain(self.overlay.prospective.children.get(storage_key) - .into_iter() - .flat_map(|map| map.1.clone().into_iter())); - - let root = self.backend.child_storage_root(storage_key, delta).0; - - self.overlay.set_storage(storage_key.to_vec(), Some(root.to_vec())); - + let (root, is_empty, _) = { + let delta = self.overlay.committed.children.get(storage_key) + .into_iter() + .flat_map(|map| map.clone().into_iter().map(|(k, v)| (k, v.value))) + .chain(self.overlay.prospective.children.get(storage_key) + .into_iter() + .flat_map(|map| map.clone().into_iter().map(|(k, v)| (k, v.value)))); + + self.backend.child_storage_root(storage_key, delta) + }; + + if is_empty { + self.overlay.set_storage(storage_key.into(), None); + } else { + self.overlay.set_storage(storage_key.into(), Some(root.clone())); + } + + trace!(target: "state-trace", "{:04x}: ChildRoot({}) {}", + self.id, + HexDisplay::from(&storage_key.as_ref()), + HexDisplay::from(&root.as_ref()), + ); root } } - fn storage_changes_root(&mut self, parent_hash: H::Out) -> Result, ()> { + fn storage_changes_root(&mut self, parent_hash: H256) -> Result, ()> { let _guard = panic_handler::AbortGuard::force_abort(); self.changes_trie_transaction = build_changes_trie::<_, H, N>( self.backend, @@ -351,35 +500,43 @@ where self.overlay, parent_hash, )?; - Ok(self.changes_trie_transaction.as_ref().map(|(_, root)| root.clone())) - } - - fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities> { - self.offchain_externalities.as_mut().map(|x| &mut **x as _) + let result = Ok(self.changes_trie_transaction.as_ref().map(|(_, root, _)| root.clone())); + trace!(target: "state-trace", "{:04x}: ChangesRoot({}) {:?}", + self.id, + HexDisplay::from(&parent_hash.as_ref()), + result, + ); + result } +} - fn keystore(&self) -> Option { - self.keystore.clone() +impl<'a, H, B, N> externalities::ExtensionStore for Ext<'a, H, N, B> +where + H: Hasher, + B: 'a + Backend, + N: crate::changes_trie::BlockNumber, +{ + fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { + self.extensions.as_mut().and_then(|exts| exts.get_mut(type_id)) } } #[cfg(test)] mod tests { + use super::*; use hex_literal::hex; use num_traits::Zero; use codec::Encode; - use primitives::{Blake2Hasher}; - use primitives::storage::well_known_keys::EXTRINSIC_INDEX; - use crate::backend::InMemory; - use crate::changes_trie::{ - Configuration as ChangesTrieConfiguration, - InMemoryStorage as TestChangesTrieStorage, + use primitives::{Blake2Hasher, storage::well_known_keys::EXTRINSIC_INDEX}; + use crate::{ + changes_trie::{ + Configuration as ChangesTrieConfiguration, + InMemoryStorage as TestChangesTrieStorage, + }, backend::InMemory, overlayed_changes::OverlayedValue, }; - use crate::overlayed_changes::OverlayedValue; - use super::*; type TestBackend = InMemory; - type TestExt<'a> = Ext<'a, Blake2Hasher, u64, TestBackend, crate::NeverOffchainExt>; + type TestExt<'a> = Ext<'a, Blake2Hasher, u64, TestBackend>; fn prepare_overlay_with_changes() -> OverlayedChanges { OverlayedChanges { @@ -409,7 +566,7 @@ mod tests { fn storage_changes_root_is_none_when_storage_is_not_provided() { let mut overlay = prepare_overlay_with_changes(); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, None, None, None); + let mut ext = TestExt::new(&mut overlay, &backend, None, None); assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None); } @@ -417,7 +574,7 @@ mod tests { fn storage_changes_root_is_none_when_state_is_not_provided() { let mut overlay = prepare_overlay_with_changes(); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, None, None, None); + let mut ext = TestExt::new(&mut overlay, &backend, None, None); assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None); } @@ -427,9 +584,8 @@ mod tests { let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); let state = Some(ChangesTrieState::new(changes_trie_config(), Zero::zero(), &storage)); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, state.as_ref(), None, None); + let mut ext = TestExt::new(&mut overlay, &backend, state.as_ref(), None); let root = hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").into(); - assert_eq!( ext.storage_changes_root(Default::default()).unwrap(), Some(root), @@ -443,9 +599,8 @@ mod tests { let storage = TestChangesTrieStorage::with_blocks(vec![(99, Default::default())]); let state = Some(ChangesTrieState::new(changes_trie_config(), Zero::zero(), &storage)); let backend = TestBackend::default(); - let mut ext = TestExt::new(&mut overlay, &backend, state.as_ref(), None, None); + let mut ext = TestExt::new(&mut overlay, &backend, state.as_ref(), None); let root = hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").into(); - assert_eq!( ext.storage_changes_root(Default::default()).unwrap(), Some(root), diff --git a/core/state-machine/src/lib.rs b/core/state-machine/src/lib.rs index fd0d5177ade7f829464cb4e8e5101bc142b0b679..41f3f806389f44a8271390021d4434da84ad9db6 100644 --- a/core/state-machine/src/lib.rs +++ b/core/state-machine/src/lib.rs @@ -18,18 +18,20 @@ #![warn(missing_docs)] -use std::{fmt, panic::UnwindSafe, result, marker::PhantomData}; -use std::borrow::Cow; -use log::warn; +use std::{fmt, result, collections::HashMap, panic::UnwindSafe, marker::PhantomData}; +use log::{warn, trace}; use hash_db::Hasher; use codec::{Decode, Encode}; use primitives::{ - NativeOrEncoded, NeverNativeValue, offchain, - traits::BareCryptoStorePtr, + NativeOrEncoded, NeverNativeValue, offchain::OffchainExt, + traits::{KeystoreExt, CodeExecutor}, hexdisplay::HexDisplay, hash::H256, }; +use overlayed_changes::OverlayedChangeSet; +use externalities::Extensions; pub mod backend; mod changes_trie; +mod error; mod ext; mod testing; mod basic; @@ -38,9 +40,7 @@ mod proving_backend; mod trie_backend; mod trie_backend_essence; -use overlayed_changes::OverlayedChangeSet; -pub use trie::{TrieMut, DBValue, MemoryDB}; -pub use trie::trie_types::{Layout, TrieDBMut}; +pub use trie::{trie_types::{Layout, TrieDBMut}, TrieMut, DBValue, MemoryDB}; pub use testing::TestExternalities; pub use basic::BasicExternalities; pub use ext::Ext; @@ -51,6 +51,8 @@ pub use changes_trie::{ Storage as ChangesTrieStorage, RootsStorage as ChangesTrieRootsStorage, InMemoryStorage as InMemoryChangesTrieStorage, + BuildCache as ChangesTrieBuildCache, + CacheAction as ChangesTrieCacheAction, ConfigurationRange as ChangesTrieConfigurationRange, key_changes, key_changes_proof, key_changes_proof_check, key_changes_proof_check_with_db, @@ -59,327 +61,22 @@ pub use changes_trie::{ }; pub use overlayed_changes::OverlayedChanges; pub use proving_backend::{ - create_proof_check_backend, create_proof_check_backend_storage, - Recorder as ProofRecorder, ProvingBackend, + create_proof_check_backend, create_proof_check_backend_storage, merge_storage_proofs, + Recorder as ProofRecorder, ProvingBackend, StorageProof, }; pub use trie_backend_essence::{TrieBackendStorage, Storage}; pub use trie_backend::TrieBackend; - - -/// A wrapper around a child storage key. -/// -/// This wrapper ensures that the child storage key is correct and properly used. It is -/// impossible to create an instance of this struct without providing a correct `storage_key`. -pub struct ChildStorageKey<'a, H: Hasher> { - storage_key: Cow<'a, [u8]>, - _hasher: PhantomData, -} - -impl<'a, H: Hasher> ChildStorageKey<'a, H> { - fn new(storage_key: Cow<'a, [u8]>) -> Option { - if !trie::is_child_trie_key_valid::>(&storage_key) { - return None; - } - - Some(ChildStorageKey { - storage_key, - _hasher: PhantomData, - }) - } - - /// Create a new `ChildStorageKey` from a vector. - /// - /// `storage_key` has should start with `:child_storage:default:` - /// See `is_child_trie_key_valid` for more details. - pub fn from_vec(key: Vec) -> Option { - Self::new(Cow::Owned(key)) - } - - /// Create a new `ChildStorageKey` from a slice. - /// - /// `storage_key` has should start with `:child_storage:default:` - /// See `is_child_trie_key_valid` for more details. - pub fn from_slice(key: &'a [u8]) -> Option { - Self::new(Cow::Borrowed(key)) - } - - /// Get access to the byte representation of the storage key. - /// - /// This key is guaranteed to be correct. - pub fn as_ref(&self) -> &[u8] { - &*self.storage_key - } - - /// Destruct this instance into an owned vector that represents the storage key. - /// - /// This key is guaranteed to be correct. - pub fn into_owned(self) -> Vec { - self.storage_key.into_owned() - } -} - -/// State Machine Error bound. -/// -/// This should reflect WASM error type bound for future compatibility. -pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} - -impl Error for ExecutionError {} - -/// Externalities Error. -/// -/// Externalities are not really allowed to have errors, since it's assumed that dependent code -/// would not be executed unless externalities were available. This is included for completeness, -/// and as a transition away from the pre-existing framework. -#[derive(Debug, Eq, PartialEq)] -pub enum ExecutionError { - /// Backend error. - Backend(String), - /// The entry `:code` doesn't exist in storage so there's no way we can execute anything. - CodeEntryDoesNotExist, - /// Backend is incompatible with execution proof generation process. - UnableToGenerateProof, - /// Invalid execution proof. - InvalidProof, -} - -impl fmt::Display for ExecutionError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } -} +pub use error::{Error, ExecutionError}; type CallResult = Result, E>; -/// Externalities: pinned to specific active address. -pub trait Externalities { - /// Read runtime storage. - fn storage(&self, key: &[u8]) -> Option>; - - /// Get storage value hash. This may be optimized for large values. - fn storage_hash(&self, key: &[u8]) -> Option { - self.storage(key).map(|v| H::hash(&v)) - } - - /// Get child storage value hash. This may be optimized for large values. - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { - self.child_storage(storage_key, key).map(|v| H::hash(&v)) - } - - /// Read original runtime storage, ignoring any overlayed changes. - fn original_storage(&self, key: &[u8]) -> Option>; - - /// Read original runtime child storage, ignoring any overlayed changes. - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; - - /// Get original storage value hash, ignoring any overlayed changes. - /// This may be optimized for large values. - fn original_storage_hash(&self, key: &[u8]) -> Option { - self.original_storage(key).map(|v| H::hash(&v)) - } - - /// Get original child storage value hash, ignoring any overlayed changes. - /// This may be optimized for large values. - fn original_child_storage_hash( - &self, - storage_key: ChildStorageKey, - key: &[u8], - ) -> Option { - self.original_child_storage(storage_key, key).map(|v| H::hash(&v)) - } - - /// Read child runtime storage. - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; - - /// Set storage entry `key` of current contract being called (effective immediately). - fn set_storage(&mut self, key: Vec, value: Vec) { - self.place_storage(key, Some(value)); - } - - /// Set child storage entry `key` of current contract being called (effective immediately). - fn set_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Vec) { - self.place_child_storage(storage_key, key, Some(value)) - } - - /// Clear a storage entry (`key`) of current contract being called (effective immediately). - fn clear_storage(&mut self, key: &[u8]) { - self.place_storage(key.to_vec(), None); - } - - /// Clear a child storage entry (`key`) of current contract being called (effective immediately). - fn clear_child_storage(&mut self, storage_key: ChildStorageKey, key: &[u8]) { - self.place_child_storage(storage_key, key.to_vec(), None) - } - - /// Whether a storage entry exists. - fn exists_storage(&self, key: &[u8]) -> bool { - self.storage(key).is_some() - } - - /// Whether a child storage entry exists. - fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { - self.child_storage(storage_key, key).is_some() - } - - /// Clear an entire child storage. - fn kill_child_storage(&mut self, storage_key: ChildStorageKey); +type DefaultHandler = fn(CallResult, CallResult) -> CallResult; - /// Clear storage entries which keys are start with the given prefix. - fn clear_prefix(&mut self, prefix: &[u8]); - - /// Clear child storage entries which keys are start with the given prefix. - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]); - - /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). - fn place_storage(&mut self, key: Vec, value: Option>); - - /// Set or clear a child storage entry. Return whether the operation succeeds. - fn place_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Option>); - - /// Get the identity of the chain. - fn chain_id(&self) -> u64; - - /// Get the trie root of the current storage map. This will also update all child storage keys in the top-level storage map. - fn storage_root(&mut self) -> H::Out where H::Out: Ord; - - /// Get the trie root of a child storage map. This will also update the value of the child - /// storage keys in the top-level storage map. - /// If the storage root equals the default hash as defined by the trie, the key in the top-level - /// storage map will be removed. - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec; - - /// Get the change trie root of the current storage overlay at a block with given parent. - fn storage_changes_root(&mut self, parent: H::Out) -> Result, ()> where H::Out: Ord; - - /// Returns offchain externalities extension if present. - fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities>; - - /// Returns the keystore. - fn keystore(&self) -> Option; -} - -/// An implementation of offchain extensions that should never be triggered. -pub enum NeverOffchainExt {} - -impl NeverOffchainExt { - /// Create new offchain extensions. - pub fn new<'a>() -> Option<&'a mut Self> { - None - } -} - -impl offchain::Externalities for NeverOffchainExt { - fn is_validator(&self) -> bool { - unreachable!() - } - - fn submit_transaction(&mut self, _extrinsic: Vec) -> Result<(), ()> { - unreachable!() - } - - fn network_state( - &self, - ) -> Result { - unreachable!() - } - - fn timestamp(&mut self) -> offchain::Timestamp { - unreachable!() - } - - fn sleep_until(&mut self, _deadline: offchain::Timestamp) { - unreachable!() - } - - fn random_seed(&mut self) -> [u8; 32] { - unreachable!() - } - - fn local_storage_set(&mut self, _kind: offchain::StorageKind, _key: &[u8], _value: &[u8]) { - unreachable!() - } - - fn local_storage_compare_and_set( - &mut self, - _kind: offchain::StorageKind, - _key: &[u8], - _old_value: Option<&[u8]>, - _new_value: &[u8], - ) -> bool { - unreachable!() - } - - fn local_storage_get(&mut self, _kind: offchain::StorageKind, _key: &[u8]) -> Option> { - unreachable!() - } - - fn http_request_start( - &mut self, - _method: &str, - _uri: &str, - _meta: &[u8] - ) -> Result { - unreachable!() - } - - fn http_request_add_header( - &mut self, - _request_id: offchain::HttpRequestId, - _name: &str, - _value: &str - ) -> Result<(), ()> { - unreachable!() - } - - fn http_request_write_body( - &mut self, - _request_id: offchain::HttpRequestId, - _chunk: &[u8], - _deadline: Option - ) -> Result<(), offchain::HttpError> { - unreachable!() - } - - fn http_response_wait( - &mut self, - _ids: &[offchain::HttpRequestId], - _deadline: Option - ) -> Vec { - unreachable!() - } - - fn http_response_headers( - &mut self, - _request_id: offchain::HttpRequestId - ) -> Vec<(Vec, Vec)> { - unreachable!() - } - - fn http_response_read_body( - &mut self, - _request_id: offchain::HttpRequestId, - _buffer: &mut [u8], - _deadline: Option - ) -> Result { - unreachable!() - } -} - -/// Code execution engine. -pub trait CodeExecutor: Sized + Send + Sync { - /// Externalities error type. - type Error: Error; - - /// Call a given method in the runtime. Returns a tuple of the result (either the output data - /// or an execution error) together with a `bool`, which is true if native execution was used. - fn call< - E: Externalities, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe - >( - &self, - ext: &mut E, - method: &str, - data: &[u8], - use_native: bool, - native_call: Option, - ) -> (CallResult, bool); -} +/// Type of changes trie transaction. +pub type ChangesTrieTransaction = ( + MemoryDB, + ChangesTrieCacheAction<::Out, N>, +); /// Strategy for executing a call into the runtime. #[derive(Copy, Clone, Eq, PartialEq, Debug)] @@ -394,18 +91,26 @@ pub enum ExecutionStrategy { NativeElseWasm, } -type DefaultHandler = fn( - CallResult, - CallResult, -) -> CallResult; +/// Storage backend trust level. +#[derive(Debug, Clone)] +pub enum BackendTrustLevel { + /// Panics from trusted backends are considered justified, and never caught. + Trusted, + /// Panics from untrusted backend are caught and interpreted as runtime error. + /// Untrusted backend may be missing some parts of the trie, so panics are not considered + /// fatal. + Untrusted, +} /// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure. #[derive(Clone)] pub enum ExecutionManager { /// Execute with the native equivalent if it is compatible with the given wasm module; otherwise fall back to the wasm. NativeWhenPossible, - /// Use the given wasm module. - AlwaysWasm, + /// Use the given wasm module. The backend on which code is executed code could be + /// trusted to provide all storage or not (i.e. the light client cannot be trusted to provide + /// for all storage queries since the storage entries it has come from an external node). + AlwaysWasm(BackendTrustLevel), /// Run with both the wasm and the native variant (if compatible). Call `F` in the case of any discrepency. Both(F), /// First native, then if that fails or is not possible, wasm. @@ -416,7 +121,7 @@ impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { fn from(s: &'a ExecutionManager) -> Self { match *s { ExecutionManager::NativeWhenPossible => ExecutionStrategy::NativeWhenPossible, - ExecutionManager::AlwaysWasm => ExecutionStrategy::AlwaysWasm, + ExecutionManager::AlwaysWasm(_) => ExecutionStrategy::AlwaysWasm, ExecutionManager::NativeElseWasm => ExecutionStrategy::NativeElseWasm, ExecutionManager::Both(_) => ExecutionStrategy::Both, } @@ -425,9 +130,11 @@ impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { impl ExecutionStrategy { /// Gets the corresponding manager for the execution strategy. - pub fn get_manager(self) -> ExecutionManager> { + pub fn get_manager( + self, + ) -> ExecutionManager> { match self { - ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, + ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted), ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, ExecutionStrategy::NativeElseWasm => ExecutionManager::NativeElseWasm, ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| { @@ -442,67 +149,72 @@ impl ExecutionStrategy { } } - -/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. -pub fn native_when_possible() -> ExecutionManager> { - ExecutionManager::NativeWhenPossible -} - /// Evaluate to ExecutionManager::NativeElseWasm, without having to figure out the type. pub fn native_else_wasm() -> ExecutionManager> { ExecutionManager::NativeElseWasm } -/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. -pub fn always_wasm() -> ExecutionManager> { - ExecutionManager::AlwaysWasm +/// Evaluate to ExecutionManager::AlwaysWasm with trusted backend, without having to figure out the type. +fn always_wasm() -> ExecutionManager> { + ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted) } -/// Creates new substrate state machine. -pub fn new<'a, H, N, B, O, Exec>( - backend: &'a B, - changes_trie_state: Option>, - offchain_ext: Option<&'a mut O>, - overlay: &'a mut OverlayedChanges, - exec: &'a Exec, - method: &'a str, - call_data: &'a [u8], - keystore: Option, -) -> StateMachine<'a, H, N, B, O, Exec> { - StateMachine { - backend, - changes_trie_state, - offchain_ext, - overlay, - exec, - method, - call_data, - keystore, - _hasher: PhantomData, - } +/// Evaluate ExecutionManager::AlwaysWasm with untrusted backend, without having to figure out the type. +fn always_untrusted_wasm() -> ExecutionManager> { + ExecutionManager::AlwaysWasm(BackendTrustLevel::Untrusted) } /// The substrate state machine. -pub struct StateMachine<'a, H, N, B, O, Exec> { +pub struct StateMachine<'a, B, H, N, Exec> where H: Hasher, B: Backend { backend: &'a B, - changes_trie_state: Option>, - offchain_ext: Option<&'a mut O>, - overlay: &'a mut OverlayedChanges, exec: &'a Exec, method: &'a str, call_data: &'a [u8], - keystore: Option, - _hasher: PhantomData<(H, N)>, + overlay: &'a mut OverlayedChanges, + extensions: Extensions, + changes_trie_state: Option>, + _marker: PhantomData<(H, N)>, } -impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where - H: Hasher, - Exec: CodeExecutor, +impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> where + H: Hasher, + Exec: CodeExecutor, B: Backend, - O: offchain::Externalities, - H::Out: Ord + 'static, N: crate::changes_trie::BlockNumber, { + /// Creates new substrate state machine. + pub fn new( + backend: &'a B, + changes_trie_state: Option>, + offchain_ext: Option, + overlay: &'a mut OverlayedChanges, + exec: &'a Exec, + method: &'a str, + call_data: &'a [u8], + keystore: Option, + ) -> Self { + let mut extensions = Extensions::new(); + + if let Some(keystore) = keystore { + extensions.register(keystore); + } + + if let Some(offchain) = offchain_ext { + extensions.register(offchain); + } + + Self { + backend, + exec, + method, + call_data, + extensions, + overlay, + changes_trie_state, + _marker: PhantomData, + } + } + /// Execute a call using the given state backend, overlayed changes, and call executor. /// Produces a state-backend-specific "transaction" which can be used to apply the changes /// to the backing store, such as the disk. @@ -511,10 +223,10 @@ impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where /// /// Note: changes to code will be in place if this call is made again. For running partial /// blocks (e.g. a transaction at a time), ensure a different method is used. - pub fn execute( - &mut self, - strategy: ExecutionStrategy, - ) -> Result<(Vec, (B::Transaction, H::Out), Option>), Box> { + pub fn execute(&mut self, strategy: ExecutionStrategy) -> Result< + (Vec, (B::Transaction, H::Out), Option>), + Box, + > { // We are not giving a native call and thus we are sure that the result can never be a native // value. self.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( @@ -538,31 +250,49 @@ impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where CallResult, bool, Option<(B::Transaction, H::Out)>, - Option>, + Option>, ) where R: Decode + Encode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, { - let mut externalities = ext::Ext::new( + let mut ext = Ext::new( self.overlay, self.backend, self.changes_trie_state.as_ref(), - self.offchain_ext.as_mut().map(|x| &mut **x), - self.keystore.clone(), + Some(&mut self.extensions), ); + + let id = ext.id; + trace!( + target: "state-trace", "{:04x}: Call {} at {:?}. Input={:?}", + id, + self.method, + self.backend, + HexDisplay::from(&self.call_data), + ); + let (result, was_native) = self.exec.call( - &mut externalities, + &mut ext, self.method, self.call_data, use_native, native_call, ); + let (storage_delta, changes_delta) = if compute_tx { - let (storage_delta, changes_delta) = externalities.transaction(); + let (storage_delta, changes_delta) = ext.transaction(); (Some(storage_delta), changes_delta) } else { (None, None) }; + + trace!( + target: "state-trace", "{:04x}: Return. Native={:?}, Result={:?}", + id, + was_native, + result, + ); + (result, was_native, storage_delta, changes_delta) } @@ -572,23 +302,36 @@ impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where mut native_call: Option, orig_prospective: OverlayedChangeSet, on_consensus_failure: Handler, - ) -> (CallResult, Option<(B::Transaction, H::Out)>, Option>) where + ) -> ( + CallResult, + Option<(B::Transaction, H::Out)>, + Option>, + ) where R: Decode + Encode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, Handler: FnOnce( CallResult, - CallResult + CallResult, ) -> CallResult { - let (result, was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call.take()); + let (result, was_native, storage_delta, changes_delta) = self.execute_aux( + compute_tx, + true, + native_call.take(), + ); if was_native { self.overlay.prospective = orig_prospective.clone(); - let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux(compute_tx, false, native_call); + let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux( + compute_tx, + false, + native_call, + ); if (result.is_ok() && wasm_result.is_ok() && result.as_ref().ok() == wasm_result.as_ref().ok()) - || result.is_err() && wasm_result.is_err() { + || result.is_err() && wasm_result.is_err() + { (result, storage_delta, changes_delta) } else { (on_consensus_failure(wasm_result, result), wasm_storage_delta, wasm_changes_delta) @@ -603,17 +346,29 @@ impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where compute_tx: bool, mut native_call: Option, orig_prospective: OverlayedChangeSet, - ) -> (CallResult, Option<(B::Transaction, H::Out)>, Option>) where + ) -> ( + CallResult, + Option<(B::Transaction, H::Out)>, + Option>, + ) where R: Decode + Encode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, { - let (result, was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call.take()); + let (result, was_native, storage_delta, changes_delta) = self.execute_aux( + compute_tx, + true, + native_call.take(), + ); if !was_native || result.is_ok() { (result, storage_delta, changes_delta) } else { self.overlay.prospective = orig_prospective.clone(); - let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux(compute_tx, false, native_call); + let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux( + compute_tx, + false, + native_call, + ); (wasm_result, wasm_storage_delta, wasm_changes_delta) } } @@ -634,13 +389,13 @@ impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where ) -> Result<( NativeOrEncoded, Option<(B::Transaction, H::Out)>, - Option> + Option>, ), Box> where R: Decode + Encode + PartialEq, - NC: FnOnce() -> result::Result + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, Handler: FnOnce( CallResult, - CallResult + CallResult, ) -> CallResult { let changes_tries_enabled = self.changes_trie_state.is_some(); @@ -651,18 +406,31 @@ impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where let (result, storage_delta, changes_delta) = match manager { ExecutionManager::Both(on_consensus_failure) => { - self.execute_call_with_both_strategy(compute_tx, native_call.take(), orig_prospective, on_consensus_failure) + self.execute_call_with_both_strategy( + compute_tx, + native_call.take(), + orig_prospective, + on_consensus_failure, + ) }, ExecutionManager::NativeElseWasm => { - self.execute_call_with_native_else_wasm_strategy(compute_tx, native_call.take(), orig_prospective) + self.execute_call_with_native_else_wasm_strategy( + compute_tx, + native_call.take(), + orig_prospective, + ) }, - ExecutionManager::AlwaysWasm => { - let (result, _, storage_delta, changes_delta) = self.execute_aux(compute_tx, false, native_call); - (result, storage_delta, changes_delta) + ExecutionManager::AlwaysWasm(trust_level) => { + let _abort_guard = match trust_level { + BackendTrustLevel::Trusted => None, + BackendTrustLevel::Untrusted => Some(panic_handler::AbortGuard::never_abort()), + }; + let res = self.execute_aux(compute_tx, false, native_call); + (res.0, res.2, res.3) }, ExecutionManager::NativeWhenPossible => { - let (result, _was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call); - (result, storage_delta, changes_delta) + let res = self.execute_aux(compute_tx, true, native_call); + (res.0, res.2, res.3) }, }; result.map(move |out| (out, storage_delta, changes_delta)) @@ -673,23 +441,23 @@ impl<'a, H, N, B, O, Exec> StateMachine<'a, H, N, B, O, Exec> where } /// Prove execution using the given state backend, overlayed changes, and call executor. -pub fn prove_execution( +pub fn prove_execution( mut backend: B, overlay: &mut OverlayedChanges, exec: &Exec, method: &str, call_data: &[u8], - keystore: Option, -) -> Result<(Vec, Vec>), Box> + keystore: Option, +) -> Result<(Vec, StorageProof), Box> where B: Backend, - H: Hasher, - Exec: CodeExecutor, - H::Out: Ord + 'static, + H: Hasher, + N: changes_trie::BlockNumber, + Exec: CodeExecutor, { let trie_backend = backend.as_trie_backend() .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; - prove_execution_on_trie_backend(trie_backend, overlay, exec, method, call_data, keystore) + prove_execution_on_trie_backend::<_, _, N, _>(trie_backend, overlay, exec, method, call_data, keystore) } /// Prove execution using the given trie backend, overlayed changes, and call executor. @@ -701,187 +469,206 @@ where /// /// Note: changes to code will be in place if this call is made again. For running partial /// blocks (e.g. a transaction at a time), ensure a different method is used. -pub fn prove_execution_on_trie_backend( +pub fn prove_execution_on_trie_backend( trie_backend: &TrieBackend, overlay: &mut OverlayedChanges, exec: &Exec, method: &str, call_data: &[u8], - keystore: Option, -) -> Result<(Vec, Vec>), Box> + keystore: Option, +) -> Result<(Vec, StorageProof), Box> where S: trie_backend_essence::TrieBackendStorage, - H: Hasher, - Exec: CodeExecutor, - H::Out: Ord + 'static, + H: Hasher, + N: changes_trie::BlockNumber, + Exec: CodeExecutor, { let proving_backend = proving_backend::ProvingBackend::new(trie_backend); - let mut sm = StateMachine { - backend: &proving_backend, - changes_trie_state: changes_trie::disabled_state::(), - offchain_ext: NeverOffchainExt::new(), - overlay, - exec, - method, - call_data, - keystore, - _hasher: PhantomData, - }; + let mut sm = StateMachine::<_, H, N, Exec>::new( + &proving_backend, None, None, overlay, exec, method, call_data, keystore, + ); + let (result, _, _) = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - native_else_wasm(), + always_wasm(), false, None, )?; - let proof = proving_backend.extract_proof(); + let proof = sm.backend.extract_proof(); Ok((result.into_encoded(), proof)) } /// Check execution proof, generated by `prove_execution` call. -pub fn execution_proof_check( +pub fn execution_proof_check( root: H::Out, - proof: Vec>, + proof: StorageProof, overlay: &mut OverlayedChanges, exec: &Exec, method: &str, call_data: &[u8], - keystore: Option, + keystore: Option, ) -> Result, Box> where - H: Hasher, - Exec: CodeExecutor, + H: Hasher, + N: changes_trie::BlockNumber, + Exec: CodeExecutor, H::Out: Ord + 'static, { let trie_backend = create_proof_check_backend::(root.into(), proof)?; - execution_proof_check_on_trie_backend(&trie_backend, overlay, exec, method, call_data, keystore) + execution_proof_check_on_trie_backend::<_, N, _>(&trie_backend, overlay, exec, method, call_data, keystore) } /// Check execution proof on proving backend, generated by `prove_execution` call. -pub fn execution_proof_check_on_trie_backend( +pub fn execution_proof_check_on_trie_backend( trie_backend: &TrieBackend, H>, overlay: &mut OverlayedChanges, exec: &Exec, method: &str, call_data: &[u8], - keystore: Option, + keystore: Option, ) -> Result, Box> where - H: Hasher, - Exec: CodeExecutor, - H::Out: Ord + 'static, + H: Hasher, + N: changes_trie::BlockNumber, + Exec: CodeExecutor, { - let mut sm = StateMachine { - backend: trie_backend, - changes_trie_state: changes_trie::disabled_state::(), - offchain_ext: NeverOffchainExt::new(), - overlay, - exec, - method, - call_data, - keystore, - _hasher: PhantomData, - }; + let mut sm = StateMachine::<_, H, N, Exec>::new( + trie_backend, None, None, overlay, exec, method, call_data, keystore, + ); + sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - native_else_wasm(), + always_untrusted_wasm(), false, None, ).map(|(result, _, _)| result.into_encoded()) } /// Generate storage read proof. -pub fn prove_read( +pub fn prove_read( mut backend: B, - key: &[u8] -) -> Result<(Option>, Vec>), Box> + keys: I, +) -> Result> where B: Backend, - H: Hasher, - H::Out: Ord + H: Hasher, + H::Out: Ord, + I: IntoIterator, + I::Item: AsRef<[u8]>, { let trie_backend = backend.as_trie_backend() .ok_or_else( - ||Box::new(ExecutionError::UnableToGenerateProof) as Box + || Box::new(ExecutionError::UnableToGenerateProof) as Box )?; - prove_read_on_trie_backend(trie_backend, key) + prove_read_on_trie_backend(trie_backend, keys) } /// Generate child storage read proof. -pub fn prove_child_read( +pub fn prove_child_read( mut backend: B, storage_key: &[u8], - key: &[u8], -) -> Result<(Option>, Vec>), Box> + keys: I, +) -> Result> where B: Backend, H: Hasher, - H::Out: Ord + H::Out: Ord, + I: IntoIterator, + I::Item: AsRef<[u8]>, { let trie_backend = backend.as_trie_backend() .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; - prove_child_read_on_trie_backend(trie_backend, storage_key, key) + prove_child_read_on_trie_backend(trie_backend, storage_key, keys) } - /// Generate storage read proof on pre-created trie backend. -pub fn prove_read_on_trie_backend( +pub fn prove_read_on_trie_backend( trie_backend: &TrieBackend, - key: &[u8] -) -> Result<(Option>, Vec>), Box> + keys: I, +) -> Result> where S: trie_backend_essence::TrieBackendStorage, H: Hasher, - H::Out: Ord + H::Out: Ord, + I: IntoIterator, + I::Item: AsRef<[u8]>, { let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); - let result = proving_backend.storage(key).map_err(|e| Box::new(e) as Box)?; - Ok((result, proving_backend.extract_proof())) + for key in keys.into_iter() { + proving_backend + .storage(key.as_ref()) + .map_err(|e| Box::new(e) as Box)?; + } + Ok(proving_backend.extract_proof()) } /// Generate storage read proof on pre-created trie backend. -pub fn prove_child_read_on_trie_backend( +pub fn prove_child_read_on_trie_backend( trie_backend: &TrieBackend, storage_key: &[u8], - key: &[u8] -) -> Result<(Option>, Vec>), Box> + keys: I, +) -> Result> where S: trie_backend_essence::TrieBackendStorage, H: Hasher, - H::Out: Ord + H::Out: Ord, + I: IntoIterator, + I::Item: AsRef<[u8]>, { let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); - let result = proving_backend.child_storage(storage_key, key).map_err(|e| Box::new(e) as Box)?; - Ok((result, proving_backend.extract_proof())) + for key in keys.into_iter() { + proving_backend + .child_storage(storage_key, key.as_ref()) + .map_err(|e| Box::new(e) as Box)?; + } + Ok(proving_backend.extract_proof()) } /// Check storage read proof, generated by `prove_read` call. -pub fn read_proof_check( +pub fn read_proof_check( root: H::Out, - proof: Vec>, - key: &[u8], -) -> Result>, Box> + proof: StorageProof, + keys: I, +) -> Result, Option>>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, + I: IntoIterator, + I::Item: AsRef<[u8]>, { let proving_backend = create_proof_check_backend::(root, proof)?; - read_proof_check_on_proving_backend(&proving_backend, key) + let mut result = HashMap::new(); + for key in keys.into_iter() { + let value = read_proof_check_on_proving_backend(&proving_backend, key.as_ref())?; + result.insert(key.as_ref().to_vec(), value); + } + Ok(result) } /// Check child storage read proof, generated by `prove_child_read` call. -pub fn read_child_proof_check( +pub fn read_child_proof_check( root: H::Out, - proof: Vec>, + proof: StorageProof, storage_key: &[u8], - key: &[u8], -) -> Result>, Box> + keys: I, +) -> Result, Option>>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, + I: IntoIterator, + I::Item: AsRef<[u8]>, { let proving_backend = create_proof_check_backend::(root, proof)?; - read_child_proof_check_on_proving_backend(&proving_backend, storage_key, key) + let mut result = HashMap::new(); + for key in keys.into_iter() { + let value = read_child_proof_check_on_proving_backend( + &proving_backend, + storage_key, + key.as_ref(), + )?; + result.insert(key.as_ref().to_vec(), value); + } + Ok(result) } - /// Check storage read proof on pre-created proving backend. pub fn read_proof_check_on_proving_backend( proving_backend: &TrieBackend, H>, @@ -889,7 +676,7 @@ pub fn read_proof_check_on_proving_backend( ) -> Result>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, { proving_backend.storage(key).map_err(|e| Box::new(e) as Box) } @@ -902,7 +689,7 @@ pub fn read_child_proof_check_on_proving_backend( ) -> Result>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, { proving_backend.child_storage(storage_key, key).map_err(|e| Box::new(e) as Box) } @@ -916,7 +703,7 @@ mod tests { use super::backend::InMemory; use super::ext::Ext; use super::changes_trie::Configuration as ChangesTrieConfig; - use primitives::{Blake2Hasher, map}; + use primitives::{Blake2Hasher, map, traits::Externalities, storage::ChildStorageKey}; struct DummyCodeExecutor { change_changes_trie_config: bool, @@ -925,10 +712,14 @@ mod tests { fallback_succeeds: bool, } - impl CodeExecutor for DummyCodeExecutor { + impl CodeExecutor for DummyCodeExecutor { type Error = u8; - fn call, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result>( + fn call< + E: Externalities, + R: Encode + Decode + PartialEq, + NC: FnOnce() -> result::Result, + >( &self, ext: &mut E, _method: &str, @@ -968,15 +759,16 @@ mod tests { } } - impl Error for u8 {} - #[test] fn execute_works() { - assert_eq!(new( - &trie_backend::tests::test_trie(), + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + + let mut state_machine = StateMachine::new( + &backend, changes_trie::disabled_state::<_, u64>(), - NeverOffchainExt::new(), - &mut Default::default(), + None, + &mut overlayed_changes, &DummyCodeExecutor { change_changes_trie_config: false, native_available: true, @@ -986,19 +778,25 @@ mod tests { "test", &[], None, - ).execute( - ExecutionStrategy::NativeWhenPossible - ).unwrap().0, vec![66]); + ); + + assert_eq!( + state_machine.execute(ExecutionStrategy::NativeWhenPossible).unwrap().0, + vec![66], + ); } #[test] fn execute_works_with_native_else_wasm() { - assert_eq!(new( - &trie_backend::tests::test_trie(), + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + + let mut state_machine = StateMachine::new( + &backend, changes_trie::disabled_state::<_, u64>(), - NeverOffchainExt::new(), - &mut Default::default(), + None, + &mut overlayed_changes, &DummyCodeExecutor { change_changes_trie_config: false, native_available: true, @@ -1008,19 +806,22 @@ mod tests { "test", &[], None, - ).execute( - ExecutionStrategy::NativeElseWasm - ).unwrap().0, vec![66]); + ); + + assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap().0, vec![66]); } #[test] fn dual_execution_strategy_detects_consensus_failure() { let mut consensus_failed = false; - assert!(new( - &trie_backend::tests::test_trie(), + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + + let mut state_machine = StateMachine::new( + &backend, changes_trie::disabled_state::<_, u64>(), - NeverOffchainExt::new(), - &mut Default::default(), + None, + &mut overlayed_changes, &DummyCodeExecutor { change_changes_trie_config: false, native_available: true, @@ -1030,14 +831,18 @@ mod tests { "test", &[], None, - ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - ExecutionManager::Both(|we, _ne| { - consensus_failed = true; - we - }), - true, - None, - ).is_err()); + ); + + assert!( + state_machine.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + ExecutionManager::Both(|we, _ne| { + consensus_failed = true; + we + }), + true, + None, + ).is_err() + ); assert!(consensus_failed); } @@ -1053,7 +858,7 @@ mod tests { // fetch execution proof from 'remote' full node let remote_backend = trie_backend::tests::test_trie(); let remote_root = remote_backend.storage_root(std::iter::empty()).0; - let (remote_result, remote_proof) = prove_execution( + let (remote_result, remote_proof) = prove_execution::<_, _, u64, _>( remote_backend, &mut Default::default(), &executor, @@ -1063,7 +868,7 @@ mod tests { ).unwrap(); // check proof locally - let local_result = execution_proof_check::( + let local_result = execution_proof_check::( remote_root, remote_proof, &mut Default::default(), @@ -1106,7 +911,6 @@ mod tests { &mut overlay, backend, state.as_ref(), - NeverOffchainExt::new(), None, ); ext.clear_prefix(b"ab"); @@ -1137,7 +941,6 @@ mod tests { &mut overlay, backend, changes_trie_state.as_ref(), - NeverOffchainExt::new(), None, ); @@ -1170,20 +973,23 @@ mod tests { // fetch read proof from 'remote' full node let remote_backend = trie_backend::tests::test_trie(); let remote_root = remote_backend.storage_root(::std::iter::empty()).0; - let remote_proof = prove_read(remote_backend, b"value2").unwrap().1; + let remote_proof = prove_read(remote_backend, &[b"value2"]).unwrap(); // check proof locally - let local_result1 = read_proof_check::( + let local_result1 = read_proof_check::( remote_root, remote_proof.clone(), - b"value2" + &[b"value2"], ).unwrap(); - let local_result2 = read_proof_check::( + let local_result2 = read_proof_check::( remote_root, remote_proof.clone(), - &[0xff] + &[&[0xff]], ).is_ok(); // check that results are correct - assert_eq!(local_result1, Some(vec![24])); + assert_eq!( + local_result1.into_iter().collect::>(), + vec![(b"value2".to_vec(), Some(vec![24]))], + ); assert_eq!(local_result2, false); // on child trie let remote_backend = trie_backend::tests::test_trie(); @@ -1191,20 +997,27 @@ mod tests { let remote_proof = prove_child_read( remote_backend, b":child_storage:default:sub1", - b"value3" - ).unwrap().1; - let local_result1 = read_child_proof_check::( + &[b"value3"], + ).unwrap(); + let local_result1 = read_child_proof_check::( remote_root, remote_proof.clone(), - b":child_storage:default:sub1",b"value3" + b":child_storage:default:sub1", + &[b"value3"], ).unwrap(); - let local_result2 = read_child_proof_check::( + let local_result2 = read_child_proof_check::( remote_root, remote_proof.clone(), b":child_storage:default:sub1", - b"value2" + &[b"value2"], ).unwrap(); - assert_eq!(local_result1, Some(vec![142])); - assert_eq!(local_result2, None); + assert_eq!( + local_result1.into_iter().collect::>(), + vec![(b"value3".to_vec(), Some(vec![142]))], + ); + assert_eq!( + local_result2.into_iter().collect::>(), + vec![(b"value2".to_vec(), None)], + ); } } diff --git a/core/state-machine/src/overlayed_changes.rs b/core/state-machine/src/overlayed_changes.rs index 1b93374fde29f359c3df0450c8446c6f4bf97c08..1395c176561001e2a49e3e1cf3cfdecff5de8ff6 100644 --- a/core/state-machine/src/overlayed_changes.rs +++ b/core/state-machine/src/overlayed_changes.rs @@ -16,7 +16,8 @@ //! The overlayed changes to state. -#[cfg(test)] use std::iter::FromIterator; +#[cfg(test)] +use std::iter::FromIterator; use std::collections::{HashMap, BTreeSet}; use codec::Decode; use crate::changes_trie::NO_EXTRINSIC_INDEX; @@ -54,7 +55,7 @@ pub struct OverlayedChangeSet { /// Top level storage changes. pub top: HashMap, OverlayedValue>, /// Child storage changes. - pub children: HashMap, (Option>, HashMap, Option>>)>, + pub children: HashMap, HashMap, OverlayedValue>>, } #[cfg(test)] @@ -105,14 +106,14 @@ impl OverlayedChanges { /// value has been set. pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Option> { if let Some(map) = self.prospective.children.get(storage_key) { - if let Some(val) = map.1.get(key) { - return Some(val.as_ref().map(AsRef::as_ref)); + if let Some(val) = map.get(key) { + return Some(val.value.as_ref().map(AsRef::as_ref)); } } if let Some(map) = self.committed.children.get(storage_key) { - if let Some(val) = map.1.get(key) { - return Some(val.as_ref().map(AsRef::as_ref)); + if let Some(val) = map.get(key) { + return Some(val.value.as_ref().map(AsRef::as_ref)); } } @@ -139,10 +140,11 @@ impl OverlayedChanges { pub(crate) fn set_child_storage(&mut self, storage_key: Vec, key: Vec, val: Option>) { let extrinsic_index = self.extrinsic_index(); let map_entry = self.prospective.children.entry(storage_key).or_default(); - map_entry.1.insert(key, val); + let entry = map_entry.entry(key).or_default(); + entry.value = val; if let Some(extrinsic) = extrinsic_index { - map_entry.0.get_or_insert_with(Default::default) + entry.extrinsics.get_or_insert_with(Default::default) .insert(extrinsic); } } @@ -157,16 +159,28 @@ impl OverlayedChanges { let extrinsic_index = self.extrinsic_index(); let map_entry = self.prospective.children.entry(storage_key.to_vec()).or_default(); - if let Some(extrinsic) = extrinsic_index { - map_entry.0.get_or_insert_with(Default::default) - .insert(extrinsic); - } + map_entry.values_mut().for_each(|e| { + if let Some(extrinsic) = extrinsic_index { + e.extrinsics.get_or_insert_with(Default::default) + .insert(extrinsic); + } - map_entry.1.values_mut().for_each(|e| *e = None); + e.value = None; + }); - if let Some((_, committed_map)) = self.committed.children.get(storage_key) { - for (key, _) in committed_map.iter() { - map_entry.1.insert(key.clone(), None); + if let Some(committed_map) = self.committed.children.get(storage_key) { + for (key, value) in committed_map.iter() { + if !map_entry.contains_key(key) { + map_entry.insert(key.clone(), OverlayedValue { + value: None, + extrinsics: extrinsic_index.map(|i| { + let mut e = value.extrinsics.clone() + .unwrap_or_else(|| BTreeSet::default()); + e.insert(i); + e + }), + }); + } } } } @@ -212,12 +226,12 @@ impl OverlayedChanges { let extrinsic_index = self.extrinsic_index(); let map_entry = self.prospective.children.entry(storage_key.to_vec()).or_default(); - for (key, entry) in map_entry.1.iter_mut() { + for (key, entry) in map_entry.iter_mut() { if key.starts_with(prefix) { - *entry = None; + entry.value = None; if let Some(extrinsic) = extrinsic_index { - map_entry.0.get_or_insert_with(Default::default) + entry.extrinsics.get_or_insert_with(Default::default) .insert(extrinsic); } } @@ -226,13 +240,13 @@ impl OverlayedChanges { if let Some(child_committed) = self.committed.children.get(storage_key) { // Then do the same with keys from commited changes. // NOTE that we are making changes in the prospective change set. - for key in child_committed.1.keys() { + for key in child_committed.keys() { if key.starts_with(prefix) { - let entry = map_entry.1.entry(key.clone()).or_default(); - *entry = None; + let entry = map_entry.entry(key.clone()).or_default(); + entry.value = None; if let Some(extrinsic) = extrinsic_index { - map_entry.0.get_or_insert_with(Default::default) + entry.extrinsics.get_or_insert_with(Default::default) .insert(extrinsic); } } @@ -259,13 +273,16 @@ impl OverlayedChanges { .extend(prospective_extrinsics); } } - for (storage_key, map) in self.prospective.children.drain() { - let entry = self.committed.children.entry(storage_key).or_default(); - entry.1.extend(map.1.iter().map(|(k, v)| (k.clone(), v.clone()))); - - if let Some(prospective_extrinsics) = map.0 { - entry.0.get_or_insert_with(Default::default) - .extend(prospective_extrinsics); + for (storage_key, mut map) in self.prospective.children.drain() { + let map_dest = self.committed.children.entry(storage_key).or_default(); + for (key, val) in map.drain() { + let entry = map_dest.entry(key).or_default(); + entry.value = val.value; + + if let Some(prospective_extrinsics) = val.extrinsics { + entry.extrinsics.get_or_insert_with(Default::default) + .extend(prospective_extrinsics); + } } } } @@ -281,7 +298,8 @@ impl OverlayedChanges { ){ assert!(self.prospective.is_empty()); (self.committed.top.into_iter().map(|(k, v)| (k, v.value)), - self.committed.children.into_iter().map(|(sk, v)| (sk, v.1.into_iter()))) + self.committed.children.into_iter() + .map(|(sk, v)| (sk, v.into_iter().map(|(k, v)| (k, v.value))))) } /// Inserts storage entry responsible for current extrinsic index. @@ -321,11 +339,11 @@ impl From>> for OverlayedValue { #[cfg(test)] mod tests { use hex_literal::hex; - use primitives::{Blake2Hasher, H256}; - use primitives::storage::well_known_keys::EXTRINSIC_INDEX; + use primitives::{ + Blake2Hasher, H256, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX, + }; use crate::backend::InMemory; use crate::ext::Ext; - use crate::Externalities; use super::*; fn strip_extrinsic_index(map: &HashMap, OverlayedValue>) -> HashMap, OverlayedValue> { @@ -389,7 +407,6 @@ mod tests { &mut overlay, &backend, changes_trie_state.as_ref(), - crate::NeverOffchainExt::new(), None, ); const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa"); diff --git a/core/state-machine/src/proving_backend.rs b/core/state-machine/src/proving_backend.rs index 5e8f618c826466a0b798e9f3512f4e1c2982e767..14f17a3a48c475715de15eb60d48d3565a9a76c1 100644 --- a/core/state-machine/src/proving_backend.rs +++ b/core/state-machine/src/proving_backend.rs @@ -16,7 +16,8 @@ //! Proving state machine backend. -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, collections::HashSet, rc::Rc}; +use codec::{Decode, Encode}; use log::debug; use hash_db::{Hasher, HashDB, EMPTY_PREFIX}; use trie::{ @@ -29,6 +30,82 @@ use crate::trie_backend::TrieBackend; use crate::trie_backend_essence::{Ephemeral, TrieBackendEssence, TrieBackendStorage}; use crate::{Error, ExecutionError, Backend}; +/// A proof that some set of key-value pairs are included in the storage trie. The proof contains +/// the storage values so that the partial storage backend can be reconstructed by a verifier that +/// does not already have access to the key-value pairs. +/// +/// The proof consists of the set of serialized nodes in the storage trie accessed when looking up +/// the keys covered by the proof. Verifying the proof requires constructing the partial trie from +/// the serialized nodes and performing the key lookups. +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +pub struct StorageProof { + trie_nodes: Vec>, +} + +impl StorageProof { + /// Constructs a storage proof from a subset of encoded trie nodes in a storage backend. + pub fn new(trie_nodes: Vec>) -> Self { + StorageProof { trie_nodes } + } + + /// Returns a new empty proof. + /// + /// An empty proof is capable of only proving trivial statements (ie. that an empty set of + /// key-value pairs exist in storage). + pub fn empty() -> Self { + StorageProof { + trie_nodes: Vec::new(), + } + } + + /// Returns whether this is an empty proof. + pub fn is_empty(&self) -> bool { + self.trie_nodes.is_empty() + } + + /// Create an iterator over trie nodes constructed from the proof. The nodes are not guaranteed + /// to be traversed in any particular order. + pub fn iter_nodes(self) -> StorageProofNodeIterator { + StorageProofNodeIterator::new(self) + } +} + +/// An iterator over trie nodes constructed from a storage proof. The nodes are not guaranteed to +/// be traversed in any particular order. +pub struct StorageProofNodeIterator { + inner: > as IntoIterator>::IntoIter, +} + +impl StorageProofNodeIterator { + fn new(proof: StorageProof) -> Self { + StorageProofNodeIterator { + inner: proof.trie_nodes.into_iter(), + } + } +} + +impl Iterator for StorageProofNodeIterator { + type Item = Vec; + + fn next(&mut self) -> Option { + self.inner.next() + } +} + +/// Merges multiple storage proofs covering potentially different sets of keys into one proof +/// covering all keys. The merged proof output may be smaller than the aggregate size of the input +/// proofs due to deduplication of trie nodes. +pub fn merge_storage_proofs(proofs: I) -> StorageProof + where I: IntoIterator +{ + let trie_nodes = proofs.into_iter() + .flat_map(|proof| proof.iter_nodes()) + .collect::>() + .into_iter() + .collect(); + StorageProof { trie_nodes } +} + /// Patricia trie-based backend essence which also tracks all touched storage trie values. /// These can be sent to remote node and used as a proof of execution. pub struct ProvingBackendEssence<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { @@ -128,15 +205,21 @@ impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> ProvingBackend<'a, S, H> } } - /// Consume the backend, extracting the gathered proof in lexicographical order - /// by value. - pub fn extract_proof(self) -> Vec> { - self.proof_recorder + /// Consume the backend, extracting the gathered proof in lexicographical order by value. + pub fn extract_proof(&self) -> StorageProof { + let trie_nodes = self.proof_recorder .borrow_mut() .drain() .into_iter() - .map(|n| n.data.to_vec()) - .collect() + .map(|record| record.data) + .collect(); + StorageProof::new(trie_nodes) + } +} + +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> std::fmt::Debug for ProvingBackend<'a, S, H> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ProvingBackend") } } @@ -174,6 +257,10 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> self.backend.for_keys_with_prefix(prefix, f) } + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.backend.for_key_values_with_prefix(prefix, f) + } + fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { self.backend.for_child_keys_with_prefix(storage_key, prefix, f) } @@ -203,16 +290,12 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> { self.backend.child_storage_root(storage_key, delta) } - - fn as_trie_backend(&mut self) -> Option<&TrieBackend> { - None - } } /// Create proof check backend. pub fn create_proof_check_backend( root: H::Out, - proof: Vec> + proof: StorageProof, ) -> Result, H>, Box> where H: Hasher, @@ -228,13 +311,13 @@ where /// Create in-memory storage of proof check backend. pub fn create_proof_check_backend_storage( - proof: Vec> + proof: StorageProof, ) -> MemoryDB where H: Hasher, { let mut db = MemoryDB::default(); - for item in proof { + for item in proof.iter_nodes() { db.insert(EMPTY_PREFIX, &item); } db @@ -245,8 +328,7 @@ mod tests { use crate::backend::{InMemory}; use crate::trie_backend::tests::test_trie; use super::*; - use primitives::{Blake2Hasher}; - use crate::ChildStorageKey; + use primitives::{Blake2Hasher, storage::ChildStorageKey}; fn test_proving<'a>( trie_backend: &'a TrieBackend,Blake2Hasher>, @@ -271,7 +353,11 @@ mod tests { #[test] fn proof_is_invalid_when_does_not_contains_root() { use primitives::H256; - assert!(create_proof_check_backend::(H256::from_low_u64_be(1), vec![]).is_err()); + let result = create_proof_check_backend::( + H256::from_low_u64_be(1), + StorageProof::empty() + ); + assert!(result.is_err()); } #[test] @@ -311,12 +397,8 @@ mod tests { #[test] fn proof_recorded_and_checked_with_child() { - let subtrie1 = ChildStorageKey::::from_slice( - b":child_storage:default:sub1" - ).unwrap(); - let subtrie2 = ChildStorageKey::::from_slice( - b":child_storage:default:sub2" - ).unwrap(); + let subtrie1 = ChildStorageKey::from_slice(b":child_storage:default:sub1").unwrap(); + let subtrie2 = ChildStorageKey::from_slice(b":child_storage:default:sub2").unwrap(); let own1 = subtrie1.into_owned(); let own2 = subtrie2.into_owned(); let contents = (0..64).map(|i| (None, vec![i], Some(vec![i]))) diff --git a/core/state-machine/src/testing.rs b/core/state-machine/src/testing.rs index 3fce99f06bb0dd1e205f8b4b363f4945bb389e21..4a989a0707ce6e68cdac4ea0ba0957cf94d55382 100644 --- a/core/state-machine/src/testing.rs +++ b/core/state-machine/src/testing.rs @@ -16,38 +16,63 @@ //! Test implementation for Externalities. -use std::collections::{HashMap}; -use hash_db::Hasher; -use num_traits::Zero; +use std::{collections::HashMap, any::{Any, TypeId}}; use codec::Decode; -use crate::backend::{InMemory, Backend}; -use primitives::storage::well_known_keys::is_child_storage_key; -use crate::changes_trie::{ - build_changes_trie, InMemoryStorage as ChangesTrieInMemoryStorage, - BlockNumber as ChangesTrieBlockNumber, Configuration as ChangesTrieConfiguration, - State as ChangesTrieState, +use hash_db::Hasher; +use crate::{ + backend::{InMemory, Backend}, OverlayedChanges, + changes_trie::{ + Configuration as ChangesTrieConfiguration, + InMemoryStorage as ChangesTrieInMemoryStorage, + BlockNumber as ChangesTrieBlockNumber, + State as ChangesTrieState, + }, + ext::Ext, }; use primitives::{ - storage::well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES}, traits::BareCryptoStorePtr, offchain + storage::{ + well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES, is_child_storage_key} + }, + hash::H256, Blake2Hasher, }; use codec::Encode; -use super::{ChildStorageKey, Externalities, OverlayedChanges}; - -const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; +use externalities::{Extensions, Extension}; type StorageTuple = (HashMap, Vec>, HashMap, HashMap, Vec>>); /// Simple HashMap-based Externalities impl. -pub struct TestExternalities { +pub struct TestExternalities=Blake2Hasher, N: ChangesTrieBlockNumber=u64> { overlay: OverlayedChanges, backend: InMemory, changes_trie_config: Option, changes_trie_storage: ChangesTrieInMemoryStorage, - offchain: Option>, - keystore: Option, + extensions: Extensions, } -impl TestExternalities { +impl, N: ChangesTrieBlockNumber> TestExternalities { + /// Get externalities implementation. + pub fn with_ext<'a, F: FnOnce(Ext>) -> T, T>(&'a mut self, f: F) -> T { + let overlay = &mut self.overlay; + let backend = &self.backend; + let extensions = &mut self.extensions; + let changes_trie_storage = &self.changes_trie_storage; + let changes_trie_state = match self.changes_trie_config.clone() { + Some(changes_trie_config) => Some(ChangesTrieState { + config: changes_trie_config, + zero: 0.into(), + storage: changes_trie_storage, + }), + None => None, + }; + + f(Ext::new( + overlay, + backend, + changes_trie_state.as_ref(), + Some(extensions), + )) + } + /// Create a new instance of `TestExternalities` with storage. pub fn new(storage: StorageTuple) -> Self { Self::new_with_code(&[], storage) @@ -76,8 +101,7 @@ impl TestExternalities { changes_trie_config, changes_trie_storage: ChangesTrieInMemoryStorage::new(), backend: backend.into(), - offchain: None, - keystore: None, + extensions: Default::default(), } } @@ -86,9 +110,9 @@ impl TestExternalities { self.backend = self.backend.update(vec![(None, k, Some(v))]); } - /// Set offchain externaltiies. - pub fn set_offchain_externalities(&mut self, offchain: impl offchain::Externalities + 'static) { - self.offchain = Some(Box::new(offchain)); + /// Registers the given extension for this instance. + pub fn register_extension(&mut self, ext: E) { + self.extensions.register(ext); } /// Get mutable reference to changes trie storage. @@ -105,22 +129,31 @@ impl TestExternalities { let children = self.overlay.committed.children.clone().into_iter() .chain(self.overlay.prospective.children.clone().into_iter()) .flat_map(|(keyspace, map)| { - map.1.into_iter() - .map(|(k, v)| (Some(keyspace.clone()), k, v)) + map.into_iter() + .map(|(k, v)| (Some(keyspace.clone()), k, v.value)) .collect::>() }); self.backend.update(top.chain(children).collect()) } + + /// Execute the given closure while `self` is set as externalities. + /// + /// Returns the result of the given closure. + pub fn execute_with(&mut self, execute: impl FnOnce() -> R) -> R { + self.with_ext(|mut ext| { + externalities::set_and_run_with_externalities(&mut ext, execute) + }) + } } -impl std::fmt::Debug for TestExternalities { +impl, N: ChangesTrieBlockNumber> std::fmt::Debug for TestExternalities { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(f, "overlay: {:?}\nbackend: {:?}", self.overlay, self.backend.pairs()) } } -impl PartialEq for TestExternalities { +impl, N: ChangesTrieBlockNumber> PartialEq for TestExternalities { /// This doesn't test if they are in the same state, only if they contains the /// same data at this state fn eq(&self, other: &TestExternalities) -> bool { @@ -128,194 +161,57 @@ impl PartialEq for TestExternalities } } -impl Default for TestExternalities { +impl, N: ChangesTrieBlockNumber> Default for TestExternalities { fn default() -> Self { Self::new(Default::default()) } } -impl From for TestExternalities { +impl, N: ChangesTrieBlockNumber> From for TestExternalities { fn from(storage: StorageTuple) -> Self { Self::new(storage) } } -impl Externalities for TestExternalities - where - H: Hasher, - N: ChangesTrieBlockNumber, - H::Out: Ord + 'static +impl externalities::ExtensionStore for TestExternalities where + H: Hasher, + N: ChangesTrieBlockNumber, { - fn storage(&self, key: &[u8]) -> Option> { - self.overlay.storage(key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| - self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL)) - } - - fn original_storage(&self, key: &[u8]) -> Option> { - self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL) - } - - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { - self.overlay - .child_storage(storage_key.as_ref(), key) - .map(|x| x.map(|x| x.to_vec())) - .unwrap_or_else(|| self.backend - .child_storage(storage_key.as_ref(), key) - .expect(EXT_NOT_ALLOWED_TO_FAIL) - ) - } - - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { - self.backend - .child_storage(storage_key.as_ref(), key) - .map(|x| x.map(|x| x.to_vec())) - .expect(EXT_NOT_ALLOWED_TO_FAIL) - } - - fn place_storage(&mut self, key: Vec, maybe_value: Option>) { - if is_child_storage_key(&key) { - panic!("Refuse to directly set child storage key"); - } - - self.overlay.set_storage(key, maybe_value); - } - - fn place_child_storage( - &mut self, - storage_key: ChildStorageKey, - key: Vec, - value: Option> - ) { - self.overlay.set_child_storage(storage_key.into_owned(), key, value); - } - - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { - let backend = &self.backend; - let overlay = &mut self.overlay; - - overlay.clear_child_storage(storage_key.as_ref()); - backend.for_keys_in_child_storage(storage_key.as_ref(), |key| { - overlay.set_child_storage(storage_key.as_ref().to_vec(), key.to_vec(), None); - }); - } - - fn clear_prefix(&mut self, prefix: &[u8]) { - if is_child_storage_key(prefix) { - panic!("Refuse to directly clear prefix that is part of child storage key"); - } - - self.overlay.clear_prefix(prefix); - - let backend = &self.backend; - let overlay = &mut self.overlay; - backend.for_keys_with_prefix(prefix, |key| { - overlay.set_storage(key.to_vec(), None); - }); - } - - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { - - self.overlay.clear_child_prefix(storage_key.as_ref(), prefix); - - let backend = &self.backend; - let overlay = &mut self.overlay; - backend.for_child_keys_with_prefix(storage_key.as_ref(), prefix, |key| { - overlay.set_child_storage(storage_key.as_ref().to_vec(), key.to_vec(), None); - }); - } - - fn chain_id(&self) -> u64 { 42 } - - fn storage_root(&mut self) -> H::Out { - - let child_storage_keys = - self.overlay.prospective.children.keys() - .chain(self.overlay.committed.children.keys()); - - let child_delta_iter = child_storage_keys.map(|storage_key| - (storage_key.clone(), self.overlay.committed.children.get(storage_key) - .into_iter() - .flat_map(|map| map.1.iter().map(|(k, v)| (k.clone(), v.clone()))) - .chain(self.overlay.prospective.children.get(storage_key) - .into_iter() - .flat_map(|map| map.1.iter().map(|(k, v)| (k.clone(), v.clone())))))); - - - // compute and memoize - let delta = self.overlay.committed.top.iter().map(|(k, v)| (k.clone(), v.value.clone())) - .chain(self.overlay.prospective.top.iter().map(|(k, v)| (k.clone(), v.value.clone()))); - self.backend.full_storage_root(delta, child_delta_iter).0 - - } - - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { - let storage_key = storage_key.as_ref(); - - let (root, is_empty, _) = { - let delta = self.overlay.committed.children.get(storage_key) - .into_iter() - .flat_map(|map| map.1.iter().map(|(k, v)| (k.clone(), v.clone()))) - .chain(self.overlay.prospective.children.get(storage_key) - .into_iter() - .flat_map(|map| map.1.clone().into_iter())); - - self.backend.child_storage_root(storage_key, delta) - }; - if is_empty { - self.overlay.set_storage(storage_key.into(), None); - } else { - self.overlay.set_storage(storage_key.into(), Some(root.clone())); - } - root - } - - fn storage_changes_root(&mut self, parent: H::Out) -> Result, ()> { - match self.changes_trie_config.clone() { - Some(config) => { - let state = ChangesTrieState::new(config, Zero::zero(), &self.changes_trie_storage); - Ok(build_changes_trie::<_, H, N>( - &self.backend, - Some(&state), - &self.overlay, - parent, - )?.map(|(_, root)| root)) - }, - None => Ok(None), - } - } - - fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities> { - self.offchain - .as_mut() - .map(|x| &mut **x as _) - } - - fn keystore(&self) -> Option { - self.keystore.clone() + fn extension_by_type_id(&mut self, type_id: TypeId) -> Option<&mut dyn Any> { + self.extensions.get_mut(type_id) } } #[cfg(test)] mod tests { use super::*; - use primitives::{Blake2Hasher, H256}; + use primitives::traits::Externalities; use hex_literal::hex; #[test] fn commit_should_work() { let mut ext = TestExternalities::::default(); - ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); - ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); - ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); - const ROOT: [u8; 32] = hex!("2a340d3dfd52f5992c6b117e9e45f479e6da5afffafeb26ab619cf137a95aeb8"); - assert_eq!(ext.storage_root(), H256::from(ROOT)); + ext.with_ext(|mut ext| { + ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec()); + ext.set_storage(b"dog".to_vec(), b"puppy".to_vec()); + ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec()); + const ROOT: [u8; 32] = hex!("2a340d3dfd52f5992c6b117e9e45f479e6da5afffafeb26ab619cf137a95aeb8"); + assert_eq!(ext.storage_root(), H256::from(ROOT)); + }); } #[test] fn set_and_retrieve_code() { let mut ext = TestExternalities::::default(); + ext.with_ext(|mut ext| { + let code = vec![1, 2, 3]; + ext.set_storage(CODE.to_vec(), code.clone()); - let code = vec![1, 2, 3]; - ext.set_storage(CODE.to_vec(), code.clone()); + assert_eq!(&ext.storage(CODE).unwrap(), &code); + }); + } - assert_eq!(&ext.storage(CODE).unwrap(), &code); + #[test] + fn check_send() { + fn assert_send() {} + assert_send::>(); } } diff --git a/core/state-machine/src/trie_backend.rs b/core/state-machine/src/trie_backend.rs index 53c293b7ad17f3de567fd5cbccc935cb4946fe8b..432ccf3e75f0e47319a30c12daaf3c1a03c7747f 100644 --- a/core/state-machine/src/trie_backend.rs +++ b/core/state-machine/src/trie_backend.rs @@ -57,7 +57,11 @@ impl, H: Hasher> TrieBackend { } } -impl super::Error for String {} +impl, H: Hasher> std::fmt::Debug for TrieBackend { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "TrieBackend") + } +} impl, H: Hasher> Backend for TrieBackend where H::Out: Ord, @@ -78,6 +82,10 @@ impl, H: Hasher> Backend for TrieBackend where self.essence.for_keys_with_prefix(prefix, f) } + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.essence.for_key_values_with_prefix(prefix, f) + } + fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { self.essence.for_keys_in_child_storage(storage_key, f) } @@ -160,7 +168,7 @@ impl, H: Hasher> Backend for TrieBackend where let mut write_overlay = S::Overlay::default(); let mut root = match self.storage(storage_key) { - Ok(value) => value.unwrap_or(default_child_trie_root::>(storage_key)), + Ok(value) => value.unwrap_or(default_root.clone()), Err(e) => { warn!(target: "trie", "Failed to read child storage root: {}", e); default_root.clone() diff --git a/core/state-machine/src/trie_backend_essence.rs b/core/state-machine/src/trie_backend_essence.rs index aeb265c2e2a5657c196e1aef54bb8573995d1d06..5a5431963448cb285489cf64150469d44f135b05 100644 --- a/core/state-machine/src/trie_backend_essence.rs +++ b/core/state-machine/src/trie_backend_essence.rs @@ -119,7 +119,7 @@ impl, H: Hasher> TrieBackendEssence { } /// Execute given closure for all keys starting with prefix. - pub fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { + pub fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], mut f: F) { let root_vec = match self.storage(storage_key) { Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key)), Err(e) => { @@ -130,16 +130,21 @@ impl, H: Hasher> TrieBackendEssence { let mut root = H::Out::default(); root.as_mut().copy_from_slice(&root_vec); - self.keys_with_prefix_inner(&root, prefix, f) + self.keys_values_with_prefix_inner(&root, prefix, |k, _v| f(k)) } /// Execute given closure for all keys starting with prefix. - pub fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { - self.keys_with_prefix_inner(&self.root, prefix, f) + pub fn for_keys_with_prefix(&self, prefix: &[u8], mut f: F) { + self.keys_values_with_prefix_inner(&self.root, prefix, |k, _v| f(k)) } - fn keys_with_prefix_inner(&self, root: &H::Out, prefix: &[u8], mut f: F) { + fn keys_values_with_prefix_inner( + &self, + root: &H::Out, + prefix: &[u8], + mut f: F, + ) { let mut read_overlay = S::Overlay::default(); let eph = Ephemeral { storage: &self.storage, @@ -153,13 +158,13 @@ impl, H: Hasher> TrieBackendEssence { iter.seek(prefix)?; for x in iter { - let (key, _) = x?; + let (key, value) = x?; if !key.starts_with(prefix) { break; } - f(&key); + f(&key, &value); } Ok(()) @@ -170,6 +175,11 @@ impl, H: Hasher> TrieBackendEssence { } } + /// Execute given closure for all key and values starting with prefix. + pub fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + self.keys_values_with_prefix_inner(&self.root, prefix, f) + } + } pub(crate) struct Ephemeral<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> { diff --git a/core/telemetry/Cargo.toml b/core/telemetry/Cargo.toml index d4332eb9ec343ec4307414fdc5dfb1c619df0b6b..82096a2cbf78854fc1def0ecd4da044ed02baf6d 100644 --- a/core/telemetry/Cargo.toml +++ b/core/telemetry/Cargo.toml @@ -6,20 +6,20 @@ description = "Telemetry utils" edition = "2018" [dependencies] -bytes = "0.4" +bytes = "0.4.12" parking_lot = "0.9.0" futures01 = { package = "futures", version = "0.1" } -futures-preview = { version = "=0.3.0-alpha.17", features = ["compat"] } -futures-timer = "0.2.1" -libp2p = { version = "0.11.0", default-features = false, features = ["libp2p-websocket"] } -log = "0.4" -rand = "0.6" -serde = { version = "1.0.81", features = ["derive"] } -slog = { version = "^2", features = ["nested-values"] } +futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] } +futures-timer = "0.4.0" +libp2p = { version = "0.13.0", default-features = false, features = ["libp2p-websocket"] } +log = "0.4.8" +rand = "0.7.2" +serde = { version = "1.0.101", features = ["derive"] } +slog = { version = "2.5.2", features = ["nested-values"] } # TODO: we're using slog-async just to be able to clone records; See https://github.com/slog-rs/slog/issues/221, # https://github.com/paritytech/substrate/issues/2823 and https://github.com/paritytech/substrate/issues/3260 slog-async = { git = "https://github.com/paritytech/slog-async", features = ["nested-values"] } -slog-json = { version = "^2", features = ["nested-values"] } -slog-scope = "^4" -tokio-io = "0.1" -void = "1.0" +slog-json = { version = "2.3.0", features = ["nested-values"] } +slog-scope = "4.1.2" +tokio-io = "0.1.12" +void = "1.0.2" diff --git a/core/telemetry/src/lib.rs b/core/telemetry/src/lib.rs index 71a86defb6d3ee634a5b7531a528dd6a9b260f3c..768fc2df84e6a6c0ae2bb7d4ebd341b3a546321c 100644 --- a/core/telemetry/src/lib.rs +++ b/core/telemetry/src/lib.rs @@ -92,7 +92,7 @@ pub struct TelemetryConfig { /// maximum verbosity level. /// /// The URL string can be either a URL or a multiaddress. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TelemetryEndpoints(Vec<(String, u8)>); impl TelemetryEndpoints { diff --git a/core/telemetry/src/worker.rs b/core/telemetry/src/worker.rs index 24a1de8ec4a3197368f6a3cd3b7c204c6b7a99c9..37b21fa73eb2490ebfa6c55ad46669de124f0256 100644 --- a/core/telemetry/src/worker.rs +++ b/core/telemetry/src/worker.rs @@ -109,7 +109,7 @@ impl TelemetryWorker { let transport = transport .map((|inner, _| Compat01As03Sink::new(inner)) as fn(_, _) -> _) - .with_timeout(CONNECT_TIMEOUT); + .timeout(CONNECT_TIMEOUT); TelemetryWorker { nodes: endpoints.into_iter().map(|(addr, verbosity)| { diff --git a/core/telemetry/src/worker/node.rs b/core/telemetry/src/worker/node.rs index 11b1f2a81e6996da38c9636f563bbf809922b7a2..0f606e40638024c82c9c2cc96784d4faf3217580 100644 --- a/core/telemetry/src/worker/node.rs +++ b/core/telemetry/src/worker/node.rs @@ -58,6 +58,8 @@ struct NodeSocketConnected { pending: VecDeque, /// If true, we need to flush the sink. need_flush: bool, + /// A timeout for the socket to write data. + timeout: Option, } /// Event that can happen with this node. @@ -66,7 +68,16 @@ pub enum NodeEvent { /// We are now connected to this node. Connected, /// We are now disconnected from this node. - Disconnected(TSinkErr), + Disconnected(ConnectionError), +} + +/// Reason for disconnecting from a node. +#[derive(Debug)] +pub enum ConnectionError { + /// The connection timed-out. + Timeout, + /// The sink errored. + Sink(TSinkErr), } impl Node { @@ -116,10 +127,12 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, let mut socket = mem::replace(&mut self.socket, NodeSocket::Poisoned); self.socket = loop { match socket { - NodeSocket::Connected(mut conn) => + NodeSocket::Connected(mut conn) => { match NodeSocketConnected::poll(Pin::new(&mut conn), cx, &self.addr) { - Poll::Ready(Ok(v)) => match v {} - Poll::Pending => break NodeSocket::Connected(conn), + Poll::Ready(Ok(v)) => match v {}, + Poll::Pending => { + break NodeSocket::Connected(conn) + }, Poll::Ready(Err(err)) => { warn!(target: "telemetry", "Disconnected from {}: {:?}", self.addr, err); let timeout = gen_rand_reconnect_delay(); @@ -127,10 +140,16 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin, return Poll::Ready(NodeEvent::Disconnected(err)) } } + } NodeSocket::Dialing(mut s) => match Future::poll(Pin::new(&mut s), cx) { Poll::Ready(Ok(sink)) => { debug!(target: "telemetry", "Connected to {}", self.addr); - let conn = NodeSocketConnected { sink, pending: VecDeque::new(), need_flush: false }; + let conn = NodeSocketConnected { + sink, + pending: VecDeque::new(), + need_flush: false, + timeout: None, + }; self.socket = NodeSocket::Connected(conn); return Poll::Ready(NodeEvent::Connected) }, @@ -189,18 +208,15 @@ where TTrans::Output: Sink fn poll( mut self: Pin<&mut Self>, cx: &mut Context, - my_addr: &Multiaddr - ) -> Poll> { - loop { - if let Some(item) = self.pending.pop_front() { - if let Poll::Pending = Sink::poll_ready(Pin::new(&mut self.sink), cx) { - self.pending.push_front(item); - return Poll::Pending - } + my_addr: &Multiaddr, + ) -> Poll>> { + while let Some(item) = self.pending.pop_front() { + if let Poll::Ready(_) = Sink::poll_ready(Pin::new(&mut self.sink), cx) { let item_len = item.len(); if let Err(err) = Sink::start_send(Pin::new(&mut self.sink), item) { - return Poll::Ready(Err(err)) + self.timeout = None; + return Poll::Ready(Err(ConnectionError::Sink(err))) } trace!( target: "telemetry", "Successfully sent {:?} bytes message to {}", @@ -208,28 +224,59 @@ where TTrans::Output: Sink ); self.need_flush = true; - } else if self.need_flush { - match Sink::poll_flush(Pin::new(&mut self.sink), cx) { - Poll::Pending => return Poll::Pending, - Poll::Ready(Err(err)) => return Poll::Ready(Err(err)), - Poll::Ready(Ok(())) => self.need_flush = false, + } else { + self.pending.push_front(item); + if self.timeout.is_none() { + self.timeout = Some(Delay::new(Duration::from_secs(10))); } + break; + } + } - } else { - match Stream::poll_next(Pin::new(&mut self.sink), cx) { - Poll::Ready(Some(Ok(_))) => { - // We poll the telemetry `Stream` because the underlying implementation relies on - // this in order to answer PINGs. - // We don't do anything with incoming messages, however. - }, - Poll::Ready(Some(Err(err))) => { - return Poll::Ready(Err(err)) - }, - Poll::Pending | Poll::Ready(None) => break, + if self.need_flush { + match Sink::poll_flush(Pin::new(&mut self.sink), cx) { + Poll::Pending => { + if self.timeout.is_none() { + self.timeout = Some(Delay::new(Duration::from_secs(10))); + } + }, + Poll::Ready(Err(err)) => { + self.timeout = None; + return Poll::Ready(Err(ConnectionError::Sink(err))) + }, + Poll::Ready(Ok(())) => { + self.timeout = None; + self.need_flush = false; + }, + } + } + + if let Some(timeout) = self.timeout.as_mut() { + match Future::poll(Pin::new(timeout), cx) { + Poll::Pending => {}, + Poll::Ready(Err(err)) => { + self.timeout = None; + warn!(target: "telemetry", "Connection timeout error for {} {:?}", my_addr, err); + } + Poll::Ready(Ok(_)) => { + self.timeout = None; + return Poll::Ready(Err(ConnectionError::Timeout)) } } } + match Stream::poll_next(Pin::new(&mut self.sink), cx) { + Poll::Ready(Some(Ok(_))) => { + // We poll the telemetry `Stream` because the underlying implementation relies on + // this in order to answer PINGs. + // We don't do anything with incoming messages, however. + }, + Poll::Ready(Some(Err(err))) => { + return Poll::Ready(Err(ConnectionError::Sink(err))) + }, + Poll::Pending | Poll::Ready(None) => {}, + } + Poll::Pending } } diff --git a/core/test-client/Cargo.toml b/core/test-client/Cargo.toml index 1af77ce2f0193045806a0f17c0ace529b7808399..de13b34d69753e3ecd2a6b74907ba892fe38f75f 100644 --- a/core/test-client/Cargo.toml +++ b/core/test-client/Cargo.toml @@ -9,8 +9,8 @@ client = { package = "substrate-client", path = "../client" } client-db = { package = "substrate-client-db", path = "../client/db", features = ["test-helpers"] } consensus = { package = "substrate-consensus-common", path = "../consensus/common" } executor = { package = "substrate-executor", path = "../executor" } -futures-preview = "=0.3.0-alpha.17" -hash-db = "0.15.0" +futures-preview = "0.3.0-alpha.19" +hash-db = "0.15.2" keyring = { package = "substrate-keyring", path = "../keyring" } codec = { package = "parity-scale-codec", version = "1.0.0" } primitives = { package = "substrate-primitives", path = "../primitives" } diff --git a/core/test-client/src/client_ext.rs b/core/test-client/src/client_ext.rs index b29a7db471e5e9bd4f21f70beb3a701660436930..7d3d7301c55d30dcff4374543ad223e5da6b17cf 100644 --- a/core/test-client/src/client_ext.rs +++ b/core/test-client/src/client_ext.rs @@ -16,7 +16,7 @@ //! Client extension for tests. -use client::{self, Client}; +use client::{self, Client, backend::Finalizer}; use consensus::{ BlockImportParams, BlockImport, BlockOrigin, Error as ConsensusError, ForkChoiceStrategy, @@ -126,7 +126,7 @@ impl ClientExt for Client id: BlockId, justification: Option, ) -> client::error::Result<()> { - self.finalize_block(id, justification, true) + Finalizer::finalize_block(self, id, justification, true) } fn genesis_hash(&self) -> ::Hash { diff --git a/core/test-client/src/lib.rs b/core/test-client/src/lib.rs index d0d4a54b0f4ae55b02caac7d399f386873805f7b..dbe4431456a7494385a3525086586968cf510163 100644 --- a/core/test-client/src/lib.rs +++ b/core/test-client/src/lib.rs @@ -24,7 +24,7 @@ pub use client::{ExecutionStrategies, blockchain, backend, self}; pub use client_db::{Backend, self}; pub use client_ext::ClientExt; pub use consensus; -pub use executor::{NativeExecutor, self}; +pub use executor::{NativeExecutor, WasmExecutionMethod, self}; pub use keyring::{ AccountKeyring, ed25519::Keyring as Ed25519Keyring, @@ -36,24 +36,17 @@ pub use state_machine::ExecutionStrategy; use std::sync::Arc; use std::collections::HashMap; -use futures::future::Ready; use hash_db::Hasher; use primitives::storage::well_known_keys; -use sr_primitives::traits::{ - Block as BlockT, NumberFor -}; +use sr_primitives::traits::Block as BlockT; use client::LocalCallExecutor; /// Test client light database backend. pub type LightBackend = client::light::backend::Backend< client_db::light::LightStorage, - LightFetcher, Blake2Hasher, >; -/// Test client light fetcher. -pub struct LightFetcher; - /// A genesis storage initialisation trait. pub trait GenesisInit: Default { /// Construct genesis storage. @@ -67,7 +60,7 @@ impl GenesisInit for () { } /// A builder for creating a test client instance. -pub struct TestClientBuilder { +pub struct TestClientBuilder { execution_strategies: ExecutionStrategies, genesis_init: G, child_storage_extension: HashMap, Vec<(Vec, Vec)>>, @@ -76,9 +69,10 @@ pub struct TestClientBuilder { keystore: Option, } -impl Default for TestClientBuilder< +impl Default for TestClientBuilder< Executor, Backend, + G, > where Block: BlockT::Out>, { @@ -99,6 +93,11 @@ impl TestClientBuilder< let backend = Arc::new(Backend::new_test(std::u32::MAX, std::u64::MAX)); Self::with_backend(backend) } + + /// Give access to the underlying backend of these clients + pub fn backend(&self) -> Arc> { + self.backend.clone() + } } impl TestClientBuilder { @@ -188,6 +187,7 @@ impl TestClientBuilder self.backend.clone(), executor, storage, + Default::default(), self.execution_strategies, ).expect("Creates new client"); @@ -198,7 +198,7 @@ impl TestClientBuilder } impl TestClientBuilder< - client::LocalCallExecutor>, + client::LocalCallExecutor>, Backend, G, > { @@ -209,70 +209,22 @@ impl TestClientBuilder< ) -> ( client::Client< Backend, - client::LocalCallExecutor>, + client::LocalCallExecutor>, Block, RuntimeApi >, client::LongestChain, ) where - I: Into>>, + I: Into>>, E: executor::NativeExecutionDispatch, Backend: client::backend::Backend, Block: BlockT::Out>, { - let executor = executor.into().unwrap_or_else(|| executor::NativeExecutor::new(None)); + let executor = executor.into().unwrap_or_else(|| + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + ); let executor = LocalCallExecutor::new(self.backend.clone(), executor, self.keystore.take()); self.build_with_executor(executor) } } - -impl client::light::fetcher::Fetcher for LightFetcher { - type RemoteHeaderResult = Ready>; - type RemoteReadResult = Ready>, client::error::Error>>; - type RemoteCallResult = Ready, client::error::Error>>; - type RemoteChangesResult = Ready, u32)>, client::error::Error>>; - type RemoteBodyResult = Ready, client::error::Error>>; - - fn remote_header( - &self, - _request: client::light::fetcher::RemoteHeaderRequest, - ) -> Self::RemoteHeaderResult { - unimplemented!("not (yet) used in tests") - } - - fn remote_read( - &self, - _request: client::light::fetcher::RemoteReadRequest, - ) -> Self::RemoteReadResult { - unimplemented!("not (yet) used in tests") - } - - fn remote_read_child( - &self, - _request: client::light::fetcher::RemoteReadChildRequest, - ) -> Self::RemoteReadResult { - unimplemented!("not (yet) used in tests") - } - - fn remote_call( - &self, - _request: client::light::fetcher::RemoteCallRequest, - ) -> Self::RemoteCallResult { - unimplemented!("not (yet) used in tests") - } - - fn remote_changes( - &self, - _request: client::light::fetcher::RemoteChangesRequest, - ) -> Self::RemoteChangesResult { - unimplemented!("not (yet) used in tests") - } - - fn remote_body( - &self, - _request: client::light::fetcher::RemoteBodyRequest, - ) -> Self::RemoteBodyResult { - unimplemented!("not (yet) used in tests") - } -} diff --git a/core/test-runtime/Cargo.toml b/core/test-runtime/Cargo.toml index 13186056ce2dcc31f2c0089013768cb2f6f9a813..4e7c3f8bca450f035706ad465fef44442b62f7ea 100644 --- a/core/test-runtime/Cargo.toml +++ b/core/test-runtime/Cargo.toml @@ -6,8 +6,8 @@ edition = "2018" build = "build.rs" [dependencies] -log = { version = "0.4", optional = true } -serde = { version = "1.0", optional = true, features = ["derive"] } +log = { version = "0.4.8", optional = true } +serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } keyring = { package = "substrate-keyring", path = "../keyring", optional = true } substrate-client = { path = "../client", default-features = false } @@ -23,14 +23,15 @@ session = { package = "substrate-session", path = "../session", default-features runtime_version = { package = "sr-version", path = "../sr-version", default-features = false } runtime_support = { package = "srml-support", path = "../../srml/support", default-features = false } substrate-trie = { path = "../trie", default-features = false } -trie-db = { version = "0.15.0", default-features = false } -memory-db = { version = "0.15.0", default-features = false } +trie-db = { version = "0.15.2", default-features = false } +memory-db = { version = "0.15.2", default-features = false } offchain-primitives = { package = "substrate-offchain-primitives", path = "../offchain/primitives", default-features = false} executive = { package = "srml-executive", path = "../../srml/executive", default-features = false } -cfg-if = "0.1.6" +cfg-if = "0.1.10" srml-babe = { path = "../../srml/babe", default-features = false } srml-timestamp = { path = "../../srml/timestamp", default-features = false } srml-system = { path = "../../srml/system", default-features = false } +srml-system-rpc-runtime-api = { path = "../../srml/system/rpc/runtime-api", default-features = false } [dev-dependencies] substrate-executor = { path = "../executor" } @@ -38,13 +39,12 @@ substrate-test-runtime-client = { path = "./client" } state_machine = { package = "substrate-state-machine", path = "../state-machine" } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.2", path = "../utils/wasm-builder-runner" } +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4", path = "../utils/wasm-builder-runner" } [features] default = [ "std", ] -no_std = [] std = [ "log", "serde", @@ -69,6 +69,7 @@ std = [ "srml-babe/std", "srml-timestamp/std", "srml-system/std", + "srml-system-rpc-runtime-api/std", "app-crypto/std", "session/std", ] diff --git a/core/test-runtime/build.rs b/core/test-runtime/build.rs index e412123b94d88b77d775892bae428181b3c7a857..200cd6d42c2d7705c01ccd4b6b9e26528535163d 100644 --- a/core/test-runtime/build.rs +++ b/core/test-runtime/build.rs @@ -21,7 +21,7 @@ fn main() { "wasm_binary.rs", WasmBuilderSource::CratesOrPath { path: "../utils/wasm-builder", - version: "1.0.4", + version: "1.0.8", }, // Note that we set the stack-size to 1MB explicitly even though it is set // to this value by default. This is because some of our tests (`restoration_of_globals`) diff --git a/core/test-runtime/client/src/lib.rs b/core/test-runtime/client/src/lib.rs index a5598aa08bf206a87fbdb3298e9a2b4ee5836565..b621d5dd629ffb2b514c7811b8d3aa4fff2d2314 100644 --- a/core/test-runtime/client/src/lib.rs +++ b/core/test-runtime/client/src/lib.rs @@ -22,6 +22,8 @@ pub mod trait_tests; mod block_builder_ext; +use std::sync::Arc; +use std::collections::HashMap; pub use block_builder_ext::BlockBuilderExt; pub use generic_test_client::*; pub use runtime; @@ -38,7 +40,7 @@ pub mod prelude { // Client structs pub use super::{ TestClient, TestClientBuilder, Backend, LightBackend, - Executor, LightExecutor, LocalExecutor, NativeExecutor, + Executor, LightExecutor, LocalExecutor, NativeExecutor, WasmExecutionMethod, }; // Keyring pub use super::{AccountKeyring, Sr25519Keyring}; @@ -52,8 +54,7 @@ mod local_executor { native_executor_instance!( pub LocalExecutor, runtime::api::dispatch, - runtime::native_version, - runtime::WASM_BINARY + runtime::native_version ); } @@ -73,21 +74,12 @@ pub type Executor = client::LocalCallExecutor< pub type LightBackend = generic_test_client::LightBackend; /// Test client light executor. -pub type LightExecutor = client::light::call_executor::RemoteOrLocalCallExecutor< - runtime::Block, +pub type LightExecutor = client::light::call_executor::GenesisCallExecutor< LightBackend, - client::light::call_executor::RemoteCallExecutor< - client::light::blockchain::Blockchain< - client_db::light::LightStorage, - LightFetcher - >, - LightFetcher - >, client::LocalCallExecutor< client::light::backend::Backend< client_db::light::LightStorage, - LightFetcher, - Blake2Hasher + Blake2Hasher, >, NativeExecutor > @@ -98,21 +90,45 @@ pub type LightExecutor = client::light::call_executor::RemoteOrLocalCallExecutor pub struct GenesisParameters { changes_trie_config: Option, heap_pages_override: Option, + extra_storage: HashMap, Vec>, + child_extra_storage: HashMap, HashMap, Vec>>, +} + +impl GenesisParameters { + fn genesis_config(&self) -> GenesisConfig { + GenesisConfig::new( + self.changes_trie_config.clone(), + vec![ + sr25519::Public::from(Sr25519Keyring::Alice).into(), + sr25519::Public::from(Sr25519Keyring::Bob).into(), + sr25519::Public::from(Sr25519Keyring::Charlie).into(), + ], + vec![ + AccountKeyring::Alice.into(), + AccountKeyring::Bob.into(), + AccountKeyring::Charlie.into(), + ], + 1000, + self.heap_pages_override, + self.extra_storage.clone(), + self.child_extra_storage.clone(), + ) + } } impl generic_test_client::GenesisInit for GenesisParameters { fn genesis_storage(&self) -> (StorageOverlay, ChildrenStorageOverlay) { use codec::Encode; - let mut storage = genesis_config(self.changes_trie_config.clone(), self.heap_pages_override).genesis_map(); + let mut storage = self.genesis_config().genesis_map(); let child_roots = storage.1.iter().map(|(sk, child_map)| { let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - child_map.clone().into_iter() + child_map.clone().into_iter().collect() ); (sk.clone(), state_root.encode()) }); let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - storage.0.clone().into_iter().chain(child_roots) + storage.0.clone().into_iter().chain(child_roots).collect() ); let block: runtime::Block = client::genesis::construct_genesis_block(state_root); storage.0.extend(additional_storage_with_genesis(&block)); @@ -158,6 +174,25 @@ pub trait TestClientBuilderExt: Sized { /// Override the default value for Wasm heap pages. fn set_heap_pages(self, heap_pages: u64) -> Self; + /// Add an extra value into the genesis storage. + /// + /// # Panics + /// + /// Panics if the key is empty. + fn add_extra_child_storage>, K: Into>, V: Into>>( + self, + storage_key: SK, + key: K, + value: V, + ) -> Self; + + /// Add an extra child value into the genesis storage. + /// + /// # Panics + /// + /// Panics if the key is empty. + fn add_extra_storage>, V: Into>>(self, key: K, value: V) -> Self; + /// Build the test client. fn build(self) -> Client { self.build_with_longest_chain().0 @@ -183,57 +218,61 @@ impl TestClientBuilderExt for TestClientBuilder< self } + fn add_extra_storage>, V: Into>>(mut self, key: K, value: V) -> Self { + let key = key.into(); + assert!(!key.is_empty()); + self.genesis_init_mut().extra_storage.insert(key, value.into()); + self + } + + fn add_extra_child_storage>, K: Into>, V: Into>>( + mut self, + storage_key: SK, + key: K, + value: V, + ) -> Self { + let storage_key = storage_key.into(); + let key = key.into(); + assert!(!storage_key.is_empty()); + assert!(!key.is_empty()); + self.genesis_init_mut().child_extra_storage + .entry(storage_key) + .or_insert_with(Default::default) + .insert(key, value.into()); + self + } + + fn build_with_longest_chain(self) -> (Client, client::LongestChain) { self.build_with_native_executor(None) } } -fn genesis_config( - changes_trie_config: Option, - heap_pages_override: Option, -) -> GenesisConfig { - GenesisConfig::new( - changes_trie_config, - vec![ - sr25519::Public::from(Sr25519Keyring::Alice).into(), - sr25519::Public::from(Sr25519Keyring::Bob).into(), - sr25519::Public::from(Sr25519Keyring::Charlie).into(), - ], vec![ - AccountKeyring::Alice.into(), - AccountKeyring::Bob.into(), - AccountKeyring::Charlie.into(), - ], - 1000, - heap_pages_override, - ) -} - /// Creates new client instance used for tests. pub fn new() -> Client { TestClientBuilder::new().build() } /// Creates new light client instance used for tests. -pub fn new_light() -> client::Client { - use std::sync::Arc; +pub fn new_light() -> ( + client::Client, + Arc, +) { let storage = client_db::light::LightStorage::new_test(); let blockchain = Arc::new(client::light::blockchain::Blockchain::new(storage)); let backend = Arc::new(LightBackend::new(blockchain.clone())); - let executor = NativeExecutor::new(None); - let fetcher = Arc::new(LightFetcher); - let remote_call_executor = client::light::call_executor::RemoteCallExecutor::new( - blockchain.clone(), - fetcher, - ); + let executor = NativeExecutor::new(WasmExecutionMethod::Interpreted, None); let local_call_executor = client::LocalCallExecutor::new(backend.clone(), executor, None); let call_executor = LightExecutor::new( backend.clone(), - remote_call_executor, local_call_executor, ); - TestClientBuilder::with_backend(backend) - .build_with_executor(call_executor) - .0 + ( + TestClientBuilder::with_backend(backend.clone()) + .build_with_executor(call_executor) + .0, + backend, + ) } diff --git a/core/test-runtime/src/genesismap.rs b/core/test-runtime/src/genesismap.rs index e48a34e963d40f541ed167e03c78ed602f172af5..6431de063ab93c5c7287cb70924137c46a879eb4 100644 --- a/core/test-runtime/src/genesismap.rs +++ b/core/test-runtime/src/genesismap.rs @@ -18,17 +18,20 @@ use std::collections::HashMap; use runtime_io::{blake2_256, twox_128}; -use super::{AuthorityId, AccountId, WASM_BINARY}; +use super::{AuthorityId, AccountId, WASM_BINARY, system}; use codec::{Encode, KeyedVec, Joiner}; use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys}; use sr_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; /// Configuration of a general Substrate test genesis block. pub struct GenesisConfig { - pub changes_trie_config: Option, - pub authorities: Vec, - pub balances: Vec<(AccountId, u64)>, - pub heap_pages_override: Option, + changes_trie_config: Option, + authorities: Vec, + balances: Vec<(AccountId, u64)>, + heap_pages_override: Option, + /// Additional storage key pairs that will be added to the genesis map. + extra_storage: HashMap, Vec>, + child_extra_storage: HashMap, HashMap, Vec>>, } impl GenesisConfig { @@ -38,12 +41,16 @@ impl GenesisConfig { endowed_accounts: Vec, balance: u64, heap_pages_override: Option, + extra_storage: HashMap, Vec>, + child_extra_storage: HashMap, HashMap, Vec>>, ) -> Self { GenesisConfig { changes_trie_config, authorities: authorities.clone(), balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(), heap_pages_override, + extra_storage, + child_extra_storage, } } @@ -67,7 +74,16 @@ impl GenesisConfig { map.insert(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), changes_trie_config.encode()); } map.insert(twox_128(&b"sys:auth"[..])[..].to_vec(), self.authorities.encode()); - (map, Default::default()) + // Add the extra storage entries. + map.extend(self.extra_storage.clone().into_iter()); + + // Assimilate the system genesis config. + let mut storage = (map, self.child_extra_storage.clone()); + let mut config = system::GenesisConfig::default(); + config.authorities = self.authorities.clone(); + config.assimilate_storage(&mut storage).expect("Adding `system::GensisConfig` to the genesis"); + + storage } } @@ -77,15 +93,14 @@ pub fn insert_genesis_block( HashMap, HashMap, Vec>>, ) ) -> primitives::hash::H256 { - let child_roots = storage.1.iter().map(|(sk, child_map)| { let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - child_map.clone().into_iter() + child_map.clone().into_iter().collect(), ); (sk.clone(), state_root.encode()) }); let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( - storage.0.clone().into_iter().chain(child_roots) + storage.0.clone().into_iter().chain(child_roots).collect() ); let block: crate::Block = substrate_client::genesis::construct_genesis_block(state_root); let genesis_hash = block.header.hash(); diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index ea80ffd32d5b939c6a93bc9f69df2fe941f88928..369fcdb38d225e828d29985e436cc168e7d22a5f 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -25,7 +25,7 @@ pub mod system; use rstd::{prelude::*, marker::PhantomData}; use codec::{Encode, Decode, Input, Error}; -use primitives::{Blake2Hasher, OpaqueMetadata, ChangesTrieConfiguration}; +use primitives::{Blake2Hasher, OpaqueMetadata, RuntimeDebug, ChangesTrieConfiguration}; use app_crypto::{ed25519, sr25519, RuntimeAppPublic}; pub use app_crypto; use trie_db::{TrieMut, Trie}; @@ -38,14 +38,16 @@ use substrate_client::{ }; use sr_primitives::{ ApplyResult, create_runtime_str, Perbill, impl_opaque_keys, - transaction_validity::{TransactionValidity, ValidTransaction}, + transaction_validity::{ + TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction, + }, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup, }, }; use runtime_version::RuntimeVersion; -pub use primitives::{hash::H256, crypto::key_types}; +pub use primitives::{hash::H256}; #[cfg(any(feature = "std", test))] use runtime_version::NativeVersion; use runtime_support::{impl_outer_origin, parameter_types}; @@ -84,8 +86,7 @@ pub fn native_version() -> NativeVersion { } /// Calls in transactions. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] pub struct Transfer { pub from: AccountId, pub to: AccountId, @@ -104,8 +105,7 @@ impl Transfer { } /// Extrinsic for test-runtime. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] pub enum Extrinsic { AuthoritiesChange(Vec), Transfer(Transfer, AccountSignature), @@ -124,17 +124,17 @@ impl serde::Serialize for Extrinsic { impl BlindCheckable for Extrinsic { type Checked = Self; - fn check(self) -> Result { + fn check(self) -> Result { match self { Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), Extrinsic::Transfer(transfer, signature) => { if sr_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) { Ok(Extrinsic::Transfer(transfer, signature)) } else { - Err(sr_primitives::BAD_SIGNATURE) + Err(InvalidTransaction::BadProof.into()) } }, - Extrinsic::IncludeData(_) => Err(sr_primitives::BAD_SIGNATURE), + Extrinsic::IncludeData(_) => Err(InvalidTransaction::BadProof.into()), Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), Extrinsic::ChangesTrieConfigUpdate(new_config) => Ok(Extrinsic::ChangesTrieConfigUpdate(new_config)), @@ -144,6 +144,7 @@ impl BlindCheckable for Extrinsic { impl ExtrinsicT for Extrinsic { type Call = Extrinsic; + type SignaturePayload = (); fn is_signed(&self) -> Option { if let Extrinsic::IncludeData(_) = *self { @@ -153,7 +154,7 @@ impl ExtrinsicT for Extrinsic { } } - fn new_unsigned(call: Self::Call) -> Option { + fn new(call: Self::Call, _signature_payload: Option) -> Option { Some(call) } } @@ -188,7 +189,7 @@ pub type Header = sr_primitives::generic::Header; /// Run whatever tests we have. pub fn run_tests(mut input: &[u8]) -> Vec { - use runtime_io::print; + use sr_primitives::print; print("run_tests..."); let block = Block::decode(&mut input).unwrap(); @@ -256,6 +257,7 @@ cfg_if! { fn benchmark_direct_call() -> u64; fn returns_mutable_static() -> u64; fn allocates_huge_stack_array(trap: bool) -> Vec; + fn vec_with_capacity(size: u32) -> Vec; /// Returns the initialized block number. fn get_block_number() -> u64; /// Takes and returns the initialized block number. @@ -271,6 +273,8 @@ cfg_if! { /// /// Returns the signature generated for the message `sr25519`. fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); + /// Run various tests against storage. + fn test_storage(); } } } else { @@ -297,6 +301,7 @@ cfg_if! { fn benchmark_direct_call() -> u64; fn returns_mutable_static() -> u64; fn allocates_huge_stack_array(trap: bool) -> Vec; + fn vec_with_capacity(size: u32) -> Vec; /// Returns the initialized block number. fn get_block_number() -> u64; /// Takes and returns the initialized block number. @@ -312,6 +317,8 @@ cfg_if! { /// /// Returns the signature generated for the message `sr25519`. fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic); + /// Run various tests against storage. + fn test_storage(); } } } @@ -332,8 +339,7 @@ impl_outer_origin!{ pub enum Origin for Runtime where system = srml_system {} } -#[derive(Clone, Encode, Decode, Eq, PartialEq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] pub struct Event; impl From for Event { @@ -361,11 +367,11 @@ impl srml_system::Trait for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type WeightMultiplierUpdate = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } impl srml_timestamp::Trait for Runtime { @@ -383,6 +389,10 @@ parameter_types! { impl srml_babe::Trait for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; + // there is no actual runtime in this test-runtime, so testing crates + // are manually adding the digests. normally in this situation you'd use + // srml_babe::SameAuthoritiesForever. + type EpochChangeTrigger = srml_babe::ExternalTrigger; } /// Adds one to the given input and returns the final result. @@ -431,9 +441,7 @@ fn code_using_trie() -> u64 { impl_opaque_keys! { pub struct SessionKeys { - #[id(key_types::ED25519)] pub ed25519: ed25519::AppPublic, - #[id(key_types::SR25519)] pub sr25519: sr25519::AppPublic, } } @@ -469,7 +477,7 @@ cfg_if! { impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { - return TransactionValidity::Valid(ValidTransaction { + return Ok(ValidTransaction { priority: data.len() as u64, requires: vec![], provides: vec![data], @@ -556,6 +564,10 @@ cfg_if! { unimplemented!("is not expected to be invoked from non-wasm builds"); } + fn vec_with_capacity(_size: u32) -> Vec { + unimplemented!("is not expected to be invoked from non-wasm builds"); + } + fn get_block_number() -> u64 { system::get_block_number().expect("Block number is initialized") } @@ -575,6 +587,11 @@ cfg_if! { fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { test_sr25519_crypto() } + + fn test_storage() { + test_read_storage(); + test_read_child_storage(); + } } impl aura_primitives::AuraApi for Runtime { @@ -588,24 +605,15 @@ cfg_if! { } impl babe_primitives::BabeApi for Runtime { - fn startup_data() -> babe_primitives::BabeConfiguration { + fn configuration() -> babe_primitives::BabeConfiguration { babe_primitives::BabeConfiguration { - median_required_blocks: 0, - slot_duration: 3000, + slot_duration: 1000, + epoch_length: EpochDuration::get(), c: (3, 10), - } - } - - fn epoch() -> babe_primitives::Epoch { - let authorities = system::authorities(); - let authorities: Vec<_> = authorities.into_iter().map(|x|(x, 1)).collect(); - - babe_primitives::Epoch { - start_slot: >::epoch_start_slot(), - authorities, + genesis_authorities: system::authorities() + .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - epoch_index: >::epoch_index(), - duration: EpochDuration::get(), + secondary_slots: true, } } } @@ -613,7 +621,7 @@ cfg_if! { impl offchain_primitives::OffchainWorkerApi for Runtime { fn offchain_worker(block: u64) { let ex = Extrinsic::IncludeData(block.encode()); - runtime_io::submit_transaction(&ex).unwrap(); + runtime_io::submit_transaction(ex.encode()).unwrap(); } } @@ -622,6 +630,12 @@ cfg_if! { SessionKeys::generate(None) } } + + impl srml_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(_account: AccountId) -> Index { + 0 + } + } } } else { impl_runtime_apis! { @@ -648,7 +662,7 @@ cfg_if! { impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { - return TransactionValidity::Valid(ValidTransaction{ + return Ok(ValidTransaction{ priority: data.len() as u64, requires: vec![], provides: vec![data], @@ -766,6 +780,10 @@ cfg_if! { data.to_vec() } + fn vec_with_capacity(size: u32) -> Vec { + Vec::with_capacity(size as usize) + } + fn get_block_number() -> u64 { system::get_block_number().expect("Block number is initialized") } @@ -785,6 +803,11 @@ cfg_if! { fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { test_sr25519_crypto() } + + fn test_storage() { + test_read_storage(); + test_read_child_storage(); + } } impl aura_primitives::AuraApi for Runtime { @@ -798,24 +821,15 @@ cfg_if! { } impl babe_primitives::BabeApi for Runtime { - fn startup_data() -> babe_primitives::BabeConfiguration { + fn configuration() -> babe_primitives::BabeConfiguration { babe_primitives::BabeConfiguration { - median_required_blocks: 0, slot_duration: 1000, + epoch_length: EpochDuration::get(), c: (3, 10), - } - } - - fn epoch() -> babe_primitives::Epoch { - let authorities = system::authorities(); - let authorities: Vec<_> = authorities.into_iter().map(|x|(x, 1)).collect(); - - babe_primitives::Epoch { - start_slot: >::epoch_start_slot(), - authorities, + genesis_authorities: system::authorities() + .into_iter().map(|x|(x, 1)).collect(), randomness: >::randomness(), - epoch_index: >::epoch_index(), - duration: EpochDuration::get(), + secondary_slots: true, } } } @@ -823,7 +837,7 @@ cfg_if! { impl offchain_primitives::OffchainWorkerApi for Runtime { fn offchain_worker(block: u64) { let ex = Extrinsic::IncludeData(block.encode()); - runtime_io::submit_transaction(&ex).unwrap() + runtime_io::submit_transaction(ex.encode()).unwrap() } } @@ -832,6 +846,12 @@ cfg_if! { SessionKeys::generate(None) } } + + impl srml_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(_account: AccountId) -> Index { + 0 + } + } } } } @@ -866,10 +886,51 @@ fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) { (signature, public0) } +fn test_read_storage() { + const KEY: &[u8] = b":read_storage"; + runtime_io::set_storage(KEY, b"test"); + + let mut v = [0u8; 4]; + let r = runtime_io::read_storage( + KEY, + &mut v, + 0 + ); + assert_eq!(r, Some(4)); + assert_eq!(&v, b"test"); + + let mut v = [0u8; 4]; + let r = runtime_io::read_storage(KEY, &mut v, 8); + assert_eq!(r, Some(4)); + assert_eq!(&v, &[0, 0, 0, 0]); +} + +fn test_read_child_storage() { + const CHILD_KEY: &[u8] = b":child_storage:default:read_child_storage"; + const KEY: &[u8] = b":read_child_storage"; + runtime_io::set_child_storage(CHILD_KEY, KEY, b"test"); + + let mut v = [0u8; 4]; + let r = runtime_io::read_child_storage( + CHILD_KEY, + KEY, + &mut v, + 0 + ); + assert_eq!(r, Some(4)); + assert_eq!(&v, b"test"); + + let mut v = [0u8; 4]; + let r = runtime_io::read_child_storage(CHILD_KEY, KEY, &mut v, 8); + assert_eq!(r, Some(4)); + assert_eq!(&v, &[0, 0, 0, 0]); +} + #[cfg(test)] mod tests { use substrate_test_runtime_client::{ prelude::*, + consensus::BlockOrigin, DefaultTestClientBuilderExt, TestClientBuilder, runtime::TestAPI, }; @@ -877,7 +938,9 @@ mod tests { generic::BlockId, traits::ProvideRuntimeApi, }; + use primitives::storage::well_known_keys::HEAP_PAGES; use state_machine::ExecutionStrategy; + use codec::Encode; #[test] fn returns_mutable_static() { @@ -925,4 +988,47 @@ mod tests { assert!(ret.is_ok()); } + #[test] + fn heap_pages_is_respected() { + // This tests that the on-chain HEAP_PAGES parameter is respected. + + // Create a client devoting only 8 pages of wasm memory. This gives us ~512k of heap memory. + let client = TestClientBuilder::new() + .set_execution_strategy(ExecutionStrategy::AlwaysWasm) + .set_heap_pages(8) + .build(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().chain.best_number); + + // Try to allocate 1024k of memory on heap. This is going to fail since it is twice larger + // than the heap. + let ret = runtime_api.vec_with_capacity(&block_id, 1048576); + assert!(ret.is_err()); + + // Create a block that sets the `:heap_pages` to 32 pages of memory which corresponds to + // ~2048k of heap memory. + let new_block_id = { + let mut builder = client.new_block(Default::default()).unwrap(); + builder.push_storage_change(HEAP_PAGES.to_vec(), Some(32u64.encode())).unwrap(); + let block = builder.bake().unwrap(); + let hash = block.header.hash(); + client.import(BlockOrigin::Own, block).unwrap(); + BlockId::Hash(hash) + }; + + // Allocation of 1024k while having ~2048k should succeed. + let ret = runtime_api.vec_with_capacity(&new_block_id, 1048576); + assert!(ret.is_ok()); + } + + #[test] + fn test_storage() { + let client = TestClientBuilder::new() + .set_execution_strategy(ExecutionStrategy::Both) + .build(); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().chain.best_number); + + runtime_api.test_storage(&block_id).unwrap(); + } } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 714a3b85070a90ae7ca5290e897c6039651adda3..0e4d76f0b61ec2bc532b3a4583a4ab57fd39ba89 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -18,15 +18,16 @@ //! and depositing logs. use rstd::prelude::*; -use runtime_io::{storage_root, ordered_trie_root, storage_changes_root, twox_128, blake2_256}; -use runtime_support::storage::{self, StorageValue, StorageMap}; -use runtime_support::storage_items; -use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Header as _}; -use sr_primitives::generic; -use sr_primitives::{ApplyError, ApplyOutcome, ApplyResult}; -use sr_primitives::transaction_validity::{TransactionValidity, ValidTransaction}; +use runtime_io::{storage_root, storage_changes_root, blake2_256}; +use runtime_support::storage::{self, StorageMap}; +use runtime_support::{decl_storage, decl_module}; +use sr_primitives::{ + traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyResult, + transaction_validity::{TransactionValidity, ValidTransaction, InvalidTransaction}, +}; use codec::{KeyedVec, Encode}; -use super::{ +use srml_system::Trait; +use crate::{ AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId }; use primitives::{Blake2Hasher, storage::well_known_keys, ChangesTrieConfiguration}; @@ -34,15 +35,21 @@ use primitives::{Blake2Hasher, storage::well_known_keys, ChangesTrieConfiguratio const NONCE_OF: &[u8] = b"nonce:"; const BALANCE_OF: &[u8] = b"balance:"; -storage_items! { - ExtrinsicData: b"sys:xtd" => required map [ u32 => Vec ]; - // The current block number being processed. Set by `execute_block`. - Number: b"sys:num" => BlockNumber; - ParentHash: b"sys:pha" => required Hash; - NewAuthorities: b"sys:new_auth" => Vec; - NewChangesTrieConfig: b"sys:new_changes_trie_config" => Option; - StorageDigest: b"sys:digest" => Digest; - Authorities get(authorities): b"sys:auth" => default Vec; +decl_module! { + pub struct Module for enum Call where origin: T::Origin {} +} + +decl_storage! { + trait Store for Module as TestRuntime { + ExtrinsicData: map u32 => Vec; + // The current block number being processed. Set by `execute_block`. + Number get(fn number): Option; + ParentHash get(fn parent_hash): Hash; + NewAuthorities get(fn new_authorities): Option>; + NewChangesTrieConfig get(fn new_changes_trie_config): Option>; + StorageDigest get(fn storage_digest): Option; + Authorities get(fn authorities) config(): Vec; + } } pub fn balance_of_key(who: AccountId) -> Vec { @@ -63,6 +70,16 @@ pub fn initialize_block(header: &Header) { ::put(&header.parent_hash); ::put(header.digest()); storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32); + + // try to read something that depends on current header digest + // so that it'll be included in execution proof + if let Some(generic::DigestItem::Other(v)) = header.digest().logs().iter().next() { + let _: Option = storage::unhashed::get(&v); + } +} + +pub fn authorities() -> Vec { + Authorities::get() } pub fn get_block_number() -> Option { @@ -96,8 +113,7 @@ fn execute_block_with_state_root_handler( // check transaction trie root represents the transactions. let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); - let txs = txs.iter().map(Vec::as_slice).collect::>(); - let txs_root = ordered_trie_root::(&txs).into(); + let txs_root = BlakeTwo256::ordered_trie_root(txs); info_expect_equal_hash(&txs_root, &header.extrinsics_root); if let Mode::Overwrite = mode { header.extrinsics_root = txs_root; @@ -105,10 +121,16 @@ fn execute_block_with_state_root_handler( assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); } + // try to read something that depends on current header digest + // so that it'll be included in execution proof + if let Some(generic::DigestItem::Other(v)) = header.digest().logs().iter().next() { + let _: Option = storage::unhashed::get(&v); + } + // execute transactions block.extrinsics.iter().enumerate().for_each(|(i, e)| { storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); + let _ = execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); @@ -153,37 +175,29 @@ impl executive::ExecuteBlock for BlockExecutor { /// This doesn't attempt to validate anything regarding the block. pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { if check_signature(&utx).is_err() { - return TransactionValidity::Invalid(ApplyError::BadSignature as i8); + return InvalidTransaction::BadProof.into(); } let tx = utx.transfer(); let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if tx.nonce < expected_nonce { - return TransactionValidity::Invalid(ApplyError::Stale as i8); + return InvalidTransaction::Stale.into(); } if tx.nonce > expected_nonce + 64 { - return TransactionValidity::Unknown(ApplyError::Future as i8); + return InvalidTransaction::Future.into(); } - let hash = |from: &AccountId, nonce: u64| { - twox_128(&nonce.to_keyed_vec(&from.encode())).to_vec() - }; + let encode = |from: &AccountId, nonce: u64| (from, nonce).encode(); let requires = if tx.nonce != expected_nonce && tx.nonce > 0 { - let mut deps = Vec::new(); - deps.push(hash(&tx.from, tx.nonce - 1)); - deps + vec![encode(&tx.from, tx.nonce - 1)] } else { - Vec::new() + vec![] }; - let provides = { - let mut p = Vec::new(); - p.push(hash(&tx.from, tx.nonce)); - p - }; + let provides = vec![encode(&tx.from, tx.nonce)]; - TransactionValidity::Valid(ValidTransaction { + Ok(ValidTransaction { priority: tx.amount, requires, provides, @@ -206,8 +220,7 @@ pub fn execute_transaction(utx: Extrinsic) -> ApplyResult { pub fn finalize_block() -> Header { let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap(); let txs: Vec<_> = (0..extrinsic_index).map(ExtrinsicData::take).collect(); - let txs = txs.iter().map(Vec::as_slice).collect::>(); - let extrinsics_root = ordered_trie_root::(&txs).into(); + let extrinsics_root = BlakeTwo256::ordered_trie_root(txs).into(); let number = ::take().expect("Number is set by `initialize_block`"); let parent_hash = ::take(); let mut digest = ::take().expect("StorageDigest is set by `initialize_block`"); @@ -247,8 +260,7 @@ pub fn finalize_block() -> Header { #[inline(always)] fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> { use sr_primitives::traits::BlindCheckable; - utx.clone().check().map_err(|_| ApplyError::BadSignature)?; - Ok(()) + utx.clone().check().map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ()) } fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { @@ -256,7 +268,7 @@ fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { match utx { Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), - Extrinsic::IncludeData(_) => Ok(ApplyOutcome::Success), + Extrinsic::IncludeData(_) => Ok(Ok(())), Extrinsic::StorageChange(key, value) => execute_storage_change(key, value.as_ref().map(|v| &**v)), Extrinsic::ChangesTrieConfigUpdate(ref new_config) => execute_changes_trie_config_update(new_config.clone()), @@ -268,7 +280,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if !(tx.nonce == expected_nonce) { - return Err(ApplyError::Stale) + return Err(InvalidTransaction::Stale.into()); } // increment nonce in storage @@ -280,18 +292,18 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { // enact transfer if !(tx.amount <= from_balance) { - return Err(ApplyError::CantPay) + return Err(InvalidTransaction::Payment.into()); } let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount)); storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount)); - Ok(ApplyOutcome::Success) + Ok(Ok(())) } fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { NewAuthorities::put(new_authorities.to_vec()); - Ok(ApplyOutcome::Success) + Ok(Ok(())) } fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyResult { @@ -299,7 +311,7 @@ fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyResult { Some(value) => storage::unhashed::put_raw(key, value), None => storage::unhashed::kill(key), } - Ok(ApplyOutcome::Success) + Ok(Ok(())) } fn execute_changes_trie_config_update(new_config: Option) -> ApplyResult { @@ -311,7 +323,7 @@ fn execute_changes_trie_config_update(new_config: Option storage::unhashed::kill(well_known_keys::CHANGES_TRIE_CONFIG), } ::put(new_config); - Ok(ApplyOutcome::Success) + Ok(Ok(())) } #[cfg(feature = "std")] @@ -321,7 +333,7 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) { println!( "Hash: given={}, expected={}", HexDisplay::from(given.as_fixed_bytes()), - HexDisplay::from(expected.as_fixed_bytes()) + HexDisplay::from(expected.as_fixed_bytes()), ); } } @@ -329,9 +341,9 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) { #[cfg(not(feature = "std"))] fn info_expect_equal_hash(given: &Hash, expected: &Hash) { if given != expected { - ::runtime_io::print("Hash not equal"); - ::runtime_io::print(given.as_bytes()); - ::runtime_io::print(expected.as_bytes()); + sr_primitives::print("Hash not equal"); + sr_primitives::print(given.as_bytes()); + sr_primitives::print(expected.as_bytes()); } } @@ -339,28 +351,46 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) { mod tests { use super::*; - use runtime_io::{with_externalities, TestExternalities}; + use runtime_io::TestExternalities; use substrate_test_runtime_client::{AccountKeyring, Sr25519Keyring}; use crate::{Header, Transfer, WASM_BINARY}; - use primitives::{Blake2Hasher, map}; - use substrate_executor::WasmExecutor; + use primitives::{NeverNativeValue, map, traits::CodeExecutor}; + use substrate_executor::{NativeExecutor, WasmExecutionMethod, native_executor_instance}; + use runtime_io::twox_128; + + // Declare an instance of the native executor dispatch for the test runtime. + native_executor_instance!( + NativeDispatch, + crate::api::dispatch, + crate::native_version + ); + + fn executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + } - fn new_test_ext() -> TestExternalities { + fn new_test_ext() -> TestExternalities { let authorities = vec![ Sr25519Keyring::Alice.to_raw_public(), Sr25519Keyring::Bob.to_raw_public(), Sr25519Keyring::Charlie.to_raw_public() ]; - TestExternalities::new((map![ - twox_128(b"latest").to_vec() => vec![69u8; 32], - twox_128(b"sys:auth").to_vec() => authorities.encode(), - blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => { - vec![111u8, 0, 0, 0, 0, 0, 0, 0] - } - ], map![])) + TestExternalities::new_with_code( + WASM_BINARY, + ( + map![ + twox_128(b"latest").to_vec() => vec![69u8; 32], + twox_128(b"sys:auth").to_vec() => authorities.encode(), + blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0] + } + ], + map![], + ) + ) } - fn block_import_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { + fn block_import_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { let h = Header { parent_hash: [69u8; 32].into(), number: 1, @@ -373,28 +403,32 @@ mod tests { extrinsics: vec![], }; - with_externalities(&mut new_test_ext(), || polish_block(&mut b)); + new_test_ext().execute_with(|| polish_block(&mut b)); block_executor(b, &mut new_test_ext()); } #[test] fn block_import_works_native() { - block_import_works(|b, ext| { - with_externalities(ext, || { - execute_block(b); - }); - }); + block_import_works(|b, ext| ext.execute_with(|| execute_block(b))); } #[test] fn block_import_works_wasm() { - block_import_works(|b, ext| { - WasmExecutor::new().call(ext, 8, &WASM_BINARY, "Core_execute_block", &b.encode()).unwrap(); - }) + block_import_works(|b, ext| ext.with_ext(|mut ext| { + executor().call::<_, NeverNativeValue, fn() -> _>( + &mut ext, + "Core_execute_block", + &b.encode(), + false, + None, + ).0.unwrap(); + })) } - fn block_import_with_transaction_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { + fn block_import_with_transaction_works(block_executor: F) + where F: Fn(Block, &mut TestExternalities) + { let mut b1 = Block { header: Header { parent_hash: [69u8; 32].into(), @@ -414,7 +448,7 @@ mod tests { }; let mut dummy_ext = new_test_ext(); - with_externalities(&mut dummy_ext, || polish_block(&mut b1)); + dummy_ext.execute_with(|| polish_block(&mut b1)); let mut b2 = Block { header: Header { @@ -440,26 +474,26 @@ mod tests { ], }; - with_externalities(&mut dummy_ext, || polish_block(&mut b2)); + dummy_ext.execute_with(|| polish_block(&mut b2)); drop(dummy_ext); let mut t = new_test_ext(); - with_externalities(&mut t, || { + t.execute_with(|| { assert_eq!(balance_of(AccountKeyring::Alice.into()), 111); assert_eq!(balance_of(AccountKeyring::Bob.into()), 0); }); block_executor(b1, &mut t); - with_externalities(&mut t, || { + t.execute_with(|| { assert_eq!(balance_of(AccountKeyring::Alice.into()), 42); assert_eq!(balance_of(AccountKeyring::Bob.into()), 69); }); block_executor(b2, &mut t); - with_externalities(&mut t, || { + t.execute_with(|| { assert_eq!(balance_of(AccountKeyring::Alice.into()), 0); assert_eq!(balance_of(AccountKeyring::Bob.into()), 42); assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69); @@ -468,17 +502,19 @@ mod tests { #[test] fn block_import_with_transaction_works_native() { - block_import_with_transaction_works(|b, ext| { - with_externalities(ext, || { - execute_block(b); - }); - }); + block_import_with_transaction_works(|b, ext| ext.execute_with(|| execute_block(b))); } #[test] fn block_import_with_transaction_works_wasm() { - block_import_with_transaction_works(|b, ext| { - WasmExecutor::new().call(ext, 8, &WASM_BINARY, "Core_execute_block", &b.encode()).unwrap(); - }) + block_import_with_transaction_works(|b, ext| ext.with_ext(|mut ext| { + executor().call::<_, NeverNativeValue, fn() -> _>( + &mut ext, + "Core_execute_block", + &b.encode(), + false, + None, + ).0.unwrap(); + })) } } diff --git a/core/transaction-pool/Cargo.toml b/core/transaction-pool/Cargo.toml index 747c39a16566a9881d7319fb2ab42d5ae995d512..33ec9e9ece176b49ffca017ca9b7d0603c9e32d9 100644 --- a/core/transaction-pool/Cargo.toml +++ b/core/transaction-pool/Cargo.toml @@ -5,9 +5,9 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -derive_more = "0.14.0" -futures = "0.1" -log = "0.4" +derive_more = "0.15.0" +log = "0.4.8" +futures-preview = "0.3.0-alpha.19" codec = { package = "parity-scale-codec", version = "1.0.0" } parking_lot = "0.9.0" sr-primitives = { path = "../sr-primitives" } diff --git a/core/transaction-pool/graph/Cargo.toml b/core/transaction-pool/graph/Cargo.toml index 4dc7ce69cffe943817077c385678580cc0eb0f42..4b628079cd3cef6915f041e679955f66c0da7db9 100644 --- a/core/transaction-pool/graph/Cargo.toml +++ b/core/transaction-pool/graph/Cargo.toml @@ -5,16 +5,21 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -derive_more = "0.14.0" -futures = "0.1" -log = "0.4" +derive_more = "0.15.0" +futures-preview = "0.3.0-alpha.19" +log = "0.4.8" parking_lot = "0.9.0" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.101", features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../primitives" } sr-primitives = { path = "../../sr-primitives" } [dev-dependencies] assert_matches = "1.3.0" -env_logger = "0.6.1" +env_logger = "0.7.0" codec = { package = "parity-scale-codec", version = "1.0.0" } test_runtime = { package = "substrate-test-runtime", path = "../../test-runtime" } +criterion = "0.3" + +[[bench]] +name = "basics" +harness = false diff --git a/core/transaction-pool/graph/benches/basics.rs b/core/transaction-pool/graph/benches/basics.rs new file mode 100644 index 0000000000000000000000000000000000000000..dcd725ce465f42c6e90f1c70315642ab9d9c326d --- /dev/null +++ b/core/transaction-pool/graph/benches/basics.rs @@ -0,0 +1,165 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use criterion::{criterion_group, criterion_main, Criterion}; + +use futures::executor::block_on; +use substrate_transaction_graph::*; +use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction}; +use codec::Encode; +use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; +use sr_primitives::{ + generic::BlockId, + transaction_validity::{TransactionValidity, TransactionTag as Tag}, +}; +use primitives::blake2_256; + +#[derive(Clone, Debug, Default)] +struct TestApi { + nonce_dependant: bool, +} + +impl TestApi { + fn new_dependant() -> Self { + TestApi { nonce_dependant: true } + } +} + +fn to_tag(nonce: u64, from: AccountId) -> Tag { + let mut data = [0u8; 40]; + data[..8].copy_from_slice(&nonce.to_le_bytes()[..]); + data[8..].copy_from_slice(&from.0[..]); + data.to_vec() +} + +impl ChainApi for TestApi { + type Block = Block; + type Hash = H256; + type Error = error::Error; + type ValidationFuture = futures::future::Ready>; + + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture { + let nonce = uxt.transfer().nonce; + let from = uxt.transfer().from.clone(); + + match self.block_id_to_number(at) { + Ok(Some(num)) if num > 5 => { + return futures::future::ready( + Ok(Err(InvalidTransaction::Stale.into())) + ) + }, + _ => {}, + } + + futures::future::ready( + Ok(Ok(ValidTransaction { + priority: 4, + requires: if nonce > 1 && self.nonce_dependant { + vec![to_tag(nonce-1, from.clone())] + } else { vec![] }, + provides: vec![to_tag(nonce, from)], + longevity: 10, + propagate: true, + })) + ) + } + + fn block_id_to_number( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(*num), + BlockId::Hash(_) => None, + }) + } + + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), + BlockId::Hash(_) => None, + }) + } + + fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { + let encoded = uxt.encode(); + (blake2_256(&encoded).into(), encoded.len()) + } +} + +fn uxt(transfer: Transfer) -> Extrinsic { + Extrinsic::Transfer(transfer, Default::default()) +} + +fn bench_configured(pool: Pool, number: u64) { + let mut futures = Vec::new(); + let mut tags = Vec::new(); + + for nonce in 1..=number { + let xt = uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce, + }); + + tags.push(to_tag(nonce, AccountId::from_h256(H256::from_low_u64_be(1)))); + futures.push(pool.submit_one(&BlockId::Number(1), xt)); + } + + let res = block_on(futures::future::join_all(futures.into_iter())); + assert!(res.iter().all(Result::is_ok)); + + assert_eq!(pool.status().future, 0); + assert_eq!(pool.status().ready, number as usize); + + // Prune all transactions. + let block_num = 6; + block_on(pool.prune_tags( + &BlockId::Number(block_num), + tags, + vec![], + )).expect("Prune failed"); + + // pool is empty + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); +} + +fn benchmark_main(c: &mut Criterion) { + + c.bench_function("sequential 50 tx", |b| { + b.iter(|| { + bench_configured(Pool::new(Default::default(), TestApi::new_dependant()), 50); + }); + }); + + c.bench_function("random 100 tx", |b| { + b.iter(|| { + bench_configured(Pool::new(Default::default(), TestApi::default()), 100); + }); + }); +} + +criterion_group!(benches, benchmark_main); +criterion_main!(benches); diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs index 07e0324354dfae0d866b390ec17e08d0779e58e6..79006461c6e37f0ef0e1ae793fa13f12a459a87b 100644 --- a/core/transaction-pool/graph/src/error.rs +++ b/core/transaction-pool/graph/src/error.rs @@ -16,7 +16,9 @@ //! Transaction pool errors. -use sr_primitives::transaction_validity::TransactionPriority as Priority; +use sr_primitives::transaction_validity::{ + TransactionPriority as Priority, InvalidTransaction, UnknownTransaction, +}; /// Transaction pool result. pub type Result = std::result::Result; @@ -25,11 +27,17 @@ pub type Result = std::result::Result; #[derive(Debug, derive_more::Display, derive_more::From)] pub enum Error { /// Transaction is not verifiable yet, but might be in the future. - #[display(fmt="Unkown Transaction Validity. Error code: {}", _0)] - UnknownTransactionValidity(i8), + #[display(fmt="Unknown transaction validity: {:?}", _0)] + UnknownTransaction(UnknownTransaction), /// Transaction is invalid. - #[display(fmt="Invalid Transaction. Error Code: {}", _0)] - InvalidTransaction(i8), + #[display(fmt="Invalid transaction validity: {:?}", _0)] + InvalidTransaction(InvalidTransaction), + /// The transaction validity returned no "provides" tag. + /// + /// Such transactions are not accepted to the pool, since we use those tags + /// to define identity of transactions (occupance of the same "slot"). + #[display(fmt="The transaction does not provide any tags, so the pool can't identify it.")] + NoTagsProvided, /// The transaction is temporarily banned. #[display(fmt="Temporarily Banned")] TemporarilyBanned, diff --git a/core/transaction-pool/graph/src/lib.rs b/core/transaction-pool/graph/src/lib.rs index ea890a5cd0f2182d3d85c95250bf37c6914957eb..715e60874be951fdabfdb05e04c141f5cfa49c8c 100644 --- a/core/transaction-pool/graph/src/lib.rs +++ b/core/transaction-pool/graph/src/lib.rs @@ -29,6 +29,7 @@ mod listener; mod pool; mod ready; mod rotator; +mod validated_pool; pub mod base_pool; pub mod error; @@ -36,4 +37,8 @@ pub mod watcher; pub use self::error::IntoPoolError; pub use self::base_pool::{Transaction, Status}; -pub use self::pool::{Pool, Options, ChainApi, EventStream, ExtrinsicFor, BlockHash, ExHash, NumberFor, TransactionFor}; +pub use self::pool::{ + Pool, + Options, ChainApi, EventStream, ExtrinsicFor, + BlockHash, ExHash, NumberFor, TransactionFor, +}; diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 6eec0d222f1a3f8fc4621ce9775c13ef814c339d..081397bea135cb0ec2e9d0598b1c34f97a76ec5d 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -15,29 +15,27 @@ // along with Substrate. If not, see . use std::{ - collections::{HashSet, HashMap}, hash, + collections::HashMap, sync::Arc, - time, }; use crate::base_pool as base; use crate::error; -use crate::listener::Listener; -use crate::rotator::PoolRotator; use crate::watcher::Watcher; use serde::Serialize; -use log::debug; -use futures::sync::mpsc; -use parking_lot::{Mutex, RwLock}; +use futures::{ + Future, FutureExt, + channel::mpsc, + future::{Either, ready, join_all}, +}; use sr_primitives::{ generic::BlockId, traits::{self, SaturatedConversion}, - transaction_validity::{TransactionValidity, TransactionTag as Tag}, + transaction_validity::{TransactionValidity, TransactionTag as Tag, TransactionValidityError}, }; - -pub use crate::base_pool::Limit; +use crate::validated_pool::{ValidatedPool, ValidatedTransaction}; /// Modification notification event stream type; pub type EventStream = mpsc::UnboundedReceiver<()>; @@ -52,6 +50,12 @@ pub type ExtrinsicFor = <::Block as traits::Block>::Extrinsic; pub type NumberFor = traits::NumberFor<::Block>; /// A type of transaction stored in the pool pub type TransactionFor = Arc, ExtrinsicFor>>; +/// A type of validated transaction stored in the pool. +pub type ValidatedTransactionFor = ValidatedTransaction< + ExHash, + ExtrinsicFor, + ::Error, +>; /// Concrete extrinsic validation and query logic. pub trait ChainApi: Send + Sync { @@ -61,9 +65,15 @@ pub trait ChainApi: Send + Sync { type Hash: hash::Hash + Eq + traits::Member + Serialize; /// Error type. type Error: From + error::IntoPoolError; + /// Validate transaction future. + type ValidationFuture: Future> + Send + Unpin; /// Verify extrinsic at given block. - fn validate_transaction(&self, at: &BlockId, uxt: ExtrinsicFor) -> Result; + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture; /// Returns a block number given the block id. fn block_id_to_number(&self, at: &BlockId) -> Result>, Self::Error>; @@ -79,19 +89,19 @@ pub trait ChainApi: Send + Sync { #[derive(Debug, Clone)] pub struct Options { /// Ready queue limits. - pub ready: Limit, + pub ready: base::Limit, /// Future queue limits. - pub future: Limit, + pub future: base::Limit, } impl Default for Options { fn default() -> Self { Options { - ready: Limit { + ready: base::Limit { count: 512, total_bytes: 10 * 1024 * 1024, }, - future: Limit { + future: base::Limit { count: 128, total_bytes: 1 * 1024 * 1024, }, @@ -99,122 +109,60 @@ impl Default for Options { } } -/// Extrinsics pool. +/// Extrinsics pool that performs validation. pub struct Pool { - api: B, - options: Options, - listener: RwLock, BlockHash>>, - pool: RwLock, - ExtrinsicFor, - >>, - import_notification_sinks: Mutex>>, - rotator: PoolRotator>, + validated_pool: Arc>, } impl Pool { + /// Create a new transaction pool. + pub fn new(options: Options, api: B) -> Self { + Pool { + validated_pool: Arc::new(ValidatedPool::new(options, api)), + } + } + /// Imports a bunch of unverified extrinsics to the pool - pub fn submit_at(&self, at: &BlockId, xts: T) -> Result, B::Error>>, B::Error> where + pub fn submit_at(&self, at: &BlockId, xts: T, force: bool) + -> impl Future, B::Error>>, B::Error>> + where T: IntoIterator> { - let block_number = self.api.block_id_to_number(at)? - .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; - - let results = xts - .into_iter() - .map(|xt| -> Result<_, B::Error> { - let (hash, bytes) = self.api.hash_and_length(&xt); - if self.rotator.is_banned(&hash) { - return Err(error::Error::TemporarilyBanned.into()) - } - - match self.api.validate_transaction(at, xt.clone())? { - TransactionValidity::Valid(validity) => { - Ok(base::Transaction { - data: xt, - bytes - , - hash, - priority: validity.priority, - requires: validity.requires, - provides: validity.provides, - propagate: validity.propagate, - valid_till: block_number - .saturated_into::() - .saturating_add(validity.longevity), - }) - }, - TransactionValidity::Invalid(e) => { - Err(error::Error::InvalidTransaction(e).into()) - }, - TransactionValidity::Unknown(e) => { - self.listener.write().invalid(&hash); - Err(error::Error::UnknownTransactionValidity(e).into()) - }, - } - }) - .map(|tx| { - let imported = self.pool.write().import(tx?)?; - - if let base::Imported::Ready { .. } = imported { - self.import_notification_sinks.lock().retain(|sink| sink.unbounded_send(()).is_ok()); - } - - let mut listener = self.listener.write(); - fire_events(&mut *listener, &imported); - Ok(imported.hash().clone()) - }) - .collect::>(); - - let removed = self.enforce_limits(); - - Ok(results.into_iter().map(|res| match res { - Ok(ref hash) if removed.contains(hash) => Err(error::Error::ImmediatelyDropped.into()), - other => other, - }).collect()) - } - - fn enforce_limits(&self) -> HashSet> { - let status = self.pool.read().status(); - let ready_limit = &self.options.ready; - let future_limit = &self.options.future; - - debug!(target: "txpool", "Pool Status: {:?}", status); - - if ready_limit.is_exceeded(status.ready, status.ready_bytes) - || future_limit.is_exceeded(status.future, status.future_bytes) { - // clean up the pool - let removed = { - let mut pool = self.pool.write(); - let removed = pool.enforce_limits(ready_limit, future_limit) - .into_iter().map(|x| x.hash.clone()).collect::>(); - // ban all removed transactions - self.rotator.ban(&std::time::Instant::now(), removed.iter().map(|x| x.clone())); - removed - }; - // run notifications - let mut listener = self.listener.write(); - for h in &removed { - listener.dropped(h, None); - } - - removed - } else { - Default::default() - } + let validated_pool = self.validated_pool.clone(); + self.verify(at, xts, force) + .map(move |validated_transactions| validated_transactions + .map(|validated_transactions| validated_pool.submit(validated_transactions))) } /// Imports one unverified extrinsic to the pool - pub fn submit_one(&self, at: &BlockId, xt: ExtrinsicFor) -> Result, B::Error> { - Ok(self.submit_at(at, ::std::iter::once(xt))?.pop().expect("One extrinsic passed; one result returned; qed")?) + pub fn submit_one( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> impl Future, B::Error>> { + self.submit_at(at, std::iter::once(xt), false) + .map(|import_result| import_result.and_then(|mut import_result| import_result + .pop() + .expect("One extrinsic passed; one result returned; qed") + )) } /// Import a single extrinsic and starts to watch their progress in the pool. - pub fn submit_and_watch(&self, at: &BlockId, xt: ExtrinsicFor) -> Result, BlockHash>, B::Error> { - let hash = self.api.hash_and_length(&xt).0; - let watcher = self.listener.write().create_watcher(hash); - self.submit_one(at, xt)?; - Ok(watcher) + pub fn submit_and_watch( + &self, + at: &BlockId, + xt: ExtrinsicFor, + ) -> impl Future, BlockHash>, B::Error>> { + let block_number = match self.resolve_block_number(at) { + Ok(block_number) => block_number, + Err(err) => return Either::Left(ready(Err(err))) + }; + + let validated_pool = self.validated_pool.clone(); + Either::Right( + self.verify_one(at, block_number, xt, false) + .map(move |validated_transactions| validated_pool.submit_and_watch(validated_transactions)) + ) } /// Prunes ready transactions. @@ -223,41 +171,46 @@ impl Pool { /// To perform pruning we need the tags that each extrinsic provides and to avoid calling /// into runtime too often we first lookup all extrinsics that are in the pool and get /// their provided tags from there. Otherwise we query the runtime at the `parent` block. - pub fn prune(&self, at: &BlockId, parent: &BlockId, extrinsics: &[ExtrinsicFor]) -> Result<(), B::Error> { - let mut tags = Vec::with_capacity(extrinsics.len()); + pub fn prune( + &self, + at: &BlockId, + parent: &BlockId, + extrinsics: &[ExtrinsicFor], + ) -> impl Future> { // Get details of all extrinsics that are already in the pool - let hashes = extrinsics.iter().map(|extrinsic| self.api.hash_and_length(extrinsic).0).collect::>(); - let in_pool = self.pool.read().by_hash(&hashes); - { - // Zip the ones from the pool with the full list (we get pairs `(Extrinsic, Option)`) - let all = extrinsics.iter().zip(in_pool.iter()); - - for (extrinsic, existing_in_pool) in all { - match *existing_in_pool { + let (in_pool_hashes, in_pool_tags) = self.validated_pool.extrinsics_tags(extrinsics); + + // Zip the ones from the pool with the full list (we get pairs `(Extrinsic, Option>)`) + let all = extrinsics.iter().zip(in_pool_tags.into_iter()); + + // Prepare future that collect tags for all extrinsics + let future_tags = join_all(all + .map(|(extrinsic, in_pool_tags)| + match in_pool_tags { // reuse the tags for extrinsics that were found in the pool - Some(ref transaction) => { - tags.extend(transaction.provides.iter().cloned()); - }, + Some(tags) => Either::Left( + ready(tags) + ), // if it's not found in the pool query the runtime at parent block // to get validity info and tags that the extrinsic provides. - None => { - let validity = self.api.validate_transaction(parent, extrinsic.clone()); - match validity { - Ok(TransactionValidity::Valid(mut validity)) => { - tags.append(&mut validity.provides); - }, + None => Either::Right(self.validated_pool.api().validate_transaction(parent, extrinsic.clone()) + .then(|validity| ready(match validity { + Ok(Ok(validity)) => validity.provides, // silently ignore invalid extrinsics, // cause they might just be inherent - _ => {} - } - }, + _ => Vec::new(), + }))), } - } - } - - self.prune_tags(at, tags, in_pool.into_iter().filter_map(|x| x).map(|x| x.hash.clone()))?; - - Ok(()) + )); + + // Prune transactions by tags + let at = at.clone(); + let self_clone = self.clone(); + future_tags.then(move |tags| self_clone.prune_tags( + &at, + tags.into_iter().flat_map(|tags| tags), + in_pool_hashes, + )) } /// Prunes ready transactions that provide given list of tags. @@ -270,6 +223,9 @@ impl Pool { /// 1. Provide that tag directly /// 2. Are a dependency of pruned transaction. /// + /// Returns transactions that have been removed from the pool and must be reverified + /// before reinserting to the pool. + /// /// By removing predecessor transactions as well we might actually end up /// pruning too much, so all removed transactions are reverified against /// the runtime (`validate_transaction`) to make sure they are invalid. @@ -283,196 +239,185 @@ impl Pool { at: &BlockId, tags: impl IntoIterator, known_imported_hashes: impl IntoIterator> + Clone, - ) -> Result<(), B::Error> { - // Perform tag-based pruning in the base pool - let status = self.pool.write().prune_tags(tags); - // Notify event listeners of all transactions - // that were promoted to `Ready` or were dropped. - { - let mut listener = self.listener.write(); - for promoted in &status.promoted { - fire_events(&mut *listener, promoted); - } - for f in &status.failed { - listener.dropped(f, None); - } - } - // make sure that we don't revalidate extrinsics that were part of the recently + ) -> impl Future> { + log::trace!(target: "txpool", "Pruning at {:?}", at); + // Prune all transactions that provide given tags + let prune_status = match self.validated_pool.prune_tags(tags) { + Ok(prune_status) => prune_status, + Err(e) => return Either::Left(ready(Err(e))), + }; + + // Make sure that we don't revalidate extrinsics that were part of the recently // imported block. This is especially important for UTXO-like chains cause the // inputs are pruned so such transaction would go to future again. - self.rotator.ban(&std::time::Instant::now(), known_imported_hashes.clone().into_iter()); + self.validated_pool.ban(&std::time::Instant::now(), known_imported_hashes.clone().into_iter()); - // try to re-submit pruned transactions since some of them might be still valid. + // Try to re-validate pruned transactions since some of them might be still valid. // note that `known_imported_hashes` will be rejected here due to temporary ban. - let hashes = status.pruned.iter().map(|tx| tx.hash.clone()).collect::>(); - let results = self.submit_at(at, status.pruned.into_iter().map(|tx| tx.data.clone()))?; - - // Collect the hashes of transactions that now became invalid (meaning that they are successfully pruned). - let hashes = results.into_iter().enumerate().filter_map(|(idx, r)| match r.map_err(error::IntoPoolError::into_pool_error) { - Err(Ok(error::Error::InvalidTransaction(_))) => Some(hashes[idx].clone()), - _ => None, - }); - // Fire `pruned` notifications for collected hashes and make sure to include - // `known_imported_hashes` since they were just imported as part of the block. - let hashes = hashes.chain(known_imported_hashes.into_iter()); - { - let header_hash = self.api.block_id_to_hash(at)? - .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; - let mut listener = self.listener.write(); - for h in hashes { - listener.pruned(header_hash, &h); - } - } - // perform regular cleanup of old transactions in the pool - // and update temporary bans. - self.clear_stale(at)?; - Ok(()) - } - - /// Removes stale transactions from the pool. - /// - /// Stale transactions are transaction beyond their longevity period. - /// Note this function does not remove transactions that are already included in the chain. - /// See `prune_tags` if you want this. - pub fn clear_stale(&self, at: &BlockId) -> Result<(), B::Error> { - let block_number = self.api.block_id_to_number(at)? - .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())? - .saturated_into::(); - let now = time::Instant::now(); - let to_remove = { - self.ready() - .filter(|tx| self.rotator.ban_if_stale(&now, block_number, &tx)) - .map(|tx| tx.hash.clone()) - .collect::>() - }; - let futures_to_remove: Vec> = { - let p = self.pool.read(); - let mut hashes = Vec::new(); - for tx in p.futures() { - if self.rotator.ban_if_stale(&now, block_number, &tx) { - hashes.push(tx.hash.clone()); - } - } - hashes - }; - // removing old transactions - self.remove_invalid(&to_remove); - self.remove_invalid(&futures_to_remove); - // clear banned transactions timeouts - self.rotator.clear_timeouts(&now); - - Ok(()) - } - - /// Create a new transaction pool. - pub fn new(options: Options, api: B) -> Self { - Pool { - api, - options, - listener: Default::default(), - pool: Default::default(), - import_notification_sinks: Default::default(), - rotator: Default::default(), - } + let pruned_hashes = prune_status.pruned.iter().map(|tx| tx.hash.clone()).collect::>(); + let pruned_transactions = prune_status.pruned.into_iter().map(|tx| tx.data.clone()); + let reverify_future = self.verify(at, pruned_transactions, false); + + log::trace!(target: "txpool", "Prunning at {:?}. Resubmitting transactions.", at); + // And finally - submit reverified transactions back to the pool + let at = at.clone(); + let validated_pool = self.validated_pool.clone(); + Either::Right(reverify_future.then(move |reverified_transactions| + ready(reverified_transactions.and_then(|reverified_transactions| + validated_pool.resubmit_pruned( + &at, + known_imported_hashes, + pruned_hashes, + reverified_transactions, + )) + ))) } /// Return an event stream of transactions imported to the pool. pub fn import_notification_stream(&self) -> EventStream { - let (sink, stream) = mpsc::unbounded(); - self.import_notification_sinks.lock().push(sink); - stream + self.validated_pool.import_notification_stream() } /// Invoked when extrinsics are broadcasted. pub fn on_broadcasted(&self, propagated: HashMap, Vec>) { - let mut listener = self.listener.write(); - for (hash, peers) in propagated.into_iter() { - listener.broadcasted(&hash, peers); - } + self.validated_pool.on_broadcasted(propagated) } /// Remove from the pool. pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { - // temporarily ban invalid transactions - debug!(target: "txpool", "Banning invalid transactions: {:?}", hashes); - self.rotator.ban(&time::Instant::now(), hashes.iter().cloned()); - - let invalid = self.pool.write().remove_invalid(hashes); - - let mut listener = self.listener.write(); - for tx in &invalid { - listener.invalid(&tx.hash); - } - - invalid + self.validated_pool.remove_invalid(hashes) } /// Get an iterator for ready transactions ordered by priority pub fn ready(&self) -> impl Iterator> { - self.pool.read().ready() + self.validated_pool.ready() } /// Returns pool status. pub fn status(&self) -> base::Status { - self.pool.read().status() + self.validated_pool.status() } /// Returns transaction hash pub fn hash_of(&self, xt: &ExtrinsicFor) -> ExHash { - self.api.hash_and_length(xt).0 + self.validated_pool.api().hash_and_length(xt).0 + } + + /// Resolves block number by id. + fn resolve_block_number(&self, at: &BlockId) -> Result, B::Error> { + self.validated_pool.api().block_id_to_number(at) + .and_then(|number| number.ok_or_else(|| + error::Error::InvalidBlockId(format!("{:?}", at)).into())) + } + + /// Returns future that validates a bunch of transactions at given block. + fn verify( + &self, + at: &BlockId, + xts: impl IntoIterator>, + force: bool, + ) -> impl Future>, B::Error>> { + // we need a block number to compute tx validity + let block_number = match self.resolve_block_number(at) { + Ok(block_number) => block_number, + Err(err) => return Either::Left(ready(Err(err))), + }; + + // for each xt, prepare a validation future + let validation_futures = xts.into_iter().map(move |xt| + self.verify_one(at, block_number, xt, force) + ); + + // make single validation future that waits all until all extrinsics are validated + Either::Right(join_all(validation_futures).then(|x| ready(Ok(x)))) + } + + /// Returns future that validates single transaction at given block. + fn verify_one( + &self, + block_id: &BlockId, + block_number: NumberFor, + xt: ExtrinsicFor, + force: bool, + ) -> impl Future> { + let (hash, bytes) = self.validated_pool.api().hash_and_length(&xt); + if !force && self.validated_pool.is_banned(&hash) { + return Either::Left(ready(ValidatedTransaction::Invalid(hash, error::Error::TemporarilyBanned.into()))) + } + + Either::Right(self.validated_pool.api().validate_transaction(block_id, xt.clone()) + .then(move |validation_result| ready(match validation_result { + Ok(validity) => match validity { + Ok(validity) => if validity.provides.is_empty() { + ValidatedTransaction::Invalid(hash, error::Error::NoTagsProvided.into()) + } else { + ValidatedTransaction::Valid(base::Transaction { + data: xt, + bytes, + hash, + priority: validity.priority, + requires: validity.requires, + provides: validity.provides, + propagate: validity.propagate, + valid_till: block_number + .saturated_into::() + .saturating_add(validity.longevity), + }) + }, + Err(TransactionValidityError::Invalid(e)) => + ValidatedTransaction::Invalid(hash, error::Error::InvalidTransaction(e).into()), + Err(TransactionValidityError::Unknown(e)) => + ValidatedTransaction::Unknown(hash, error::Error::UnknownTransaction(e).into()), + }, + Err(e) => ValidatedTransaction::Invalid(hash, e), + }))) } } -fn fire_events( - listener: &mut Listener, - imported: &base::Imported, -) where - H: hash::Hash + Eq + traits::Member + Serialize, - H2: Clone, -{ - match *imported { - base::Imported::Ready { ref promoted, ref failed, ref removed, ref hash } => { - listener.ready(hash, None); - for f in failed { - listener.invalid(f); - } - for r in removed { - listener.dropped(&r.hash, Some(hash)); - } - for p in promoted { - listener.ready(p, None); - } - }, - base::Imported::Future { ref hash } => { - listener.future(hash) - }, +impl Clone for Pool { + fn clone(&self) -> Self { + Self { + validated_pool: self.validated_pool.clone(), + } } } #[cfg(test)] mod tests { + use std::{ + collections::HashMap, + time::Instant, + }; + use parking_lot::Mutex; + use futures::executor::block_on; use super::*; - use sr_primitives::transaction_validity::ValidTransaction; - use futures::Stream; + use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction}; use codec::Encode; use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; use assert_matches::assert_matches; + use crate::base_pool::Limit; use crate::watcher; - #[derive(Debug, Default)] + const INVALID_NONCE: u64 = 254; + + #[derive(Clone, Debug, Default)] struct TestApi { - delay: Mutex>>, + delay: Arc>>>, } impl ChainApi for TestApi { type Block = Block; type Hash = u64; type Error = error::Error; + type ValidationFuture = futures::future::Ready>; /// Verify extrinsic at given block. - fn validate_transaction(&self, at: &BlockId, uxt: ExtrinsicFor) -> Result { - - let block_number = self.block_id_to_number(at)?.unwrap(); + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Self::ValidationFuture { + let block_number = self.block_id_to_number(at).unwrap().unwrap(); let nonce = uxt.transfer().nonce; // This is used to control the test flow. @@ -485,17 +430,17 @@ mod tests { } } - if nonce < block_number { - Ok(TransactionValidity::Invalid(0)) + futures::future::ready(if nonce < block_number { + Ok(InvalidTransaction::Stale.into()) } else { - Ok(TransactionValidity::Valid(ValidTransaction { + Ok(Ok(ValidTransaction { priority: 4, requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] }, - provides: vec![vec![nonce as u8]], + provides: if nonce == INVALID_NONCE { vec![] } else { vec![vec![nonce as u8]] }, longevity: 3, propagate: true, })) - } + }) } /// Returns a block number given the block id. @@ -532,19 +477,18 @@ mod tests { Pool::new(Default::default(), TestApi::default()) } - #[test] fn should_validate_and_import_transaction() { // given let pool = pool(); // when - let hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + let hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, - })).unwrap(); + }))).unwrap(); // then assert_eq!(pool.ready().map(|v| v.hash).collect::>(), vec![hash]); @@ -562,8 +506,8 @@ mod tests { }); // when - pool.rotator.ban(&time::Instant::now(), vec![pool.hash_of(&uxt)]); - let res = pool.submit_one(&BlockId::Number(0), uxt); + pool.validated_pool.rotator().ban(&Instant::now(), vec![pool.hash_of(&uxt)]); + let res = block_on(pool.submit_one(&BlockId::Number(0), uxt)); assert_eq!(pool.status().ready, 0); assert_eq!(pool.status().future, 0); @@ -579,25 +523,25 @@ mod tests { let stream = pool.import_notification_stream(); // when - let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, - })).unwrap(); - let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + }))).unwrap(); + let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, - })).unwrap(); + }))).unwrap(); // future doesn't count - let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + let _hash = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, - })).unwrap(); + }))).unwrap(); assert_eq!(pool.status().ready, 2); assert_eq!(pool.status().future, 1); @@ -605,9 +549,9 @@ mod tests { }; // then - let mut it = stream.wait(); - assert_eq!(it.next(), Some(Ok(()))); - assert_eq!(it.next(), Some(Ok(()))); + let mut it = futures::executor::block_on_stream(stream); + assert_eq!(it.next(), Some(())); + assert_eq!(it.next(), Some(())); assert_eq!(it.next(), None); } @@ -615,54 +559,54 @@ mod tests { fn should_clear_stale_transactions() { // given let pool = pool(); - let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, - })).unwrap(); - let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + }))).unwrap(); + let hash2 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, - })).unwrap(); - let hash3 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + }))).unwrap(); + let hash3 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, - })).unwrap(); + }))).unwrap(); // when - pool.clear_stale(&BlockId::Number(5)).unwrap(); + pool.validated_pool.clear_stale(&BlockId::Number(5)).unwrap(); // then assert_eq!(pool.ready().count(), 0); assert_eq!(pool.status().future, 0); assert_eq!(pool.status().ready, 0); // make sure they are temporarily banned as well - assert!(pool.rotator.is_banned(&hash1)); - assert!(pool.rotator.is_banned(&hash2)); - assert!(pool.rotator.is_banned(&hash3)); + assert!(pool.validated_pool.rotator().is_banned(&hash1)); + assert!(pool.validated_pool.rotator().is_banned(&hash2)); + assert!(pool.validated_pool.rotator().is_banned(&hash3)); } #[test] fn should_ban_mined_transactions() { // given let pool = pool(); - let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, - })).unwrap(); + }))).unwrap(); // when - pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1.clone()]).unwrap(); + block_on(pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1.clone()])).unwrap(); // then - assert!(pool.rotator.is_banned(&hash1)); + assert!(pool.validated_pool.rotator().is_banned(&hash1)); } #[test] @@ -677,26 +621,26 @@ mod tests { future: limit.clone(), }, TestApi::default()); - let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, - })).unwrap(); + }))).unwrap(); assert_eq!(pool.status().future, 1); // when - let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { + let hash2 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(2)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 10, - })).unwrap(); + }))).unwrap(); // then assert_eq!(pool.status().future, 1); - assert!(pool.rotator.is_banned(&hash1)); - assert!(!pool.rotator.is_banned(&hash2)); + assert!(pool.validated_pool.rotator().is_banned(&hash1)); + assert!(!pool.validated_pool.rotator().is_banned(&hash2)); } #[test] @@ -712,18 +656,36 @@ mod tests { }, TestApi::default()); // when - pool.submit_one(&BlockId::Number(0), uxt(Transfer { + block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, - })).unwrap_err(); + }))).unwrap_err(); // then assert_eq!(pool.status().ready, 0); assert_eq!(pool.status().future, 0); } + #[test] + fn should_reject_transactions_with_no_provides() { + // given + let pool = pool(); + + // when + let err = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), + amount: 5, + nonce: INVALID_NONCE, + }))).unwrap_err(); + + // then + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 0); + assert_matches!(err, error::Error::NoTagsProvided); + } mod listener { use super::*; @@ -732,24 +694,24 @@ mod tests { fn should_trigger_ready_and_finalized() { // given let pool = pool(); - let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, - })).unwrap(); + }))).unwrap(); assert_eq!(pool.status().ready, 1); assert_eq!(pool.status().future, 0); // when - pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![]).unwrap(); + block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![])).unwrap(); assert_eq!(pool.status().ready, 0); assert_eq!(pool.status().future, 0); // then - let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalized(H256::from_low_u64_be(2).into())))); + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(watcher::Status::Ready)); + assert_eq!(stream.next(), Some(watcher::Status::Finalized(H256::from_low_u64_be(2).into()))); assert_eq!(stream.next(), None); } @@ -757,24 +719,24 @@ mod tests { fn should_trigger_ready_and_finalized_when_pruning_via_hash() { // given let pool = pool(); - let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, - })).unwrap(); + }))).unwrap(); assert_eq!(pool.status().ready, 1); assert_eq!(pool.status().future, 0); // when - pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![2u64]).unwrap(); + block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![2u64])).unwrap(); assert_eq!(pool.status().ready, 0); assert_eq!(pool.status().future, 0); // then - let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalized(H256::from_low_u64_be(2).into())))); + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(watcher::Status::Ready)); + assert_eq!(stream.next(), Some(watcher::Status::Finalized(H256::from_low_u64_be(2).into()))); assert_eq!(stream.next(), None); } @@ -782,28 +744,28 @@ mod tests { fn should_trigger_future_and_ready_after_promoted() { // given let pool = pool(); - let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, - })).unwrap(); + }))).unwrap(); assert_eq!(pool.status().ready, 0); assert_eq!(pool.status().future, 1); // when - pool.submit_one(&BlockId::Number(0), uxt(Transfer { + block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer { from: AccountId::from_h256(H256::from_low_u64_be(1)), to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, - })).unwrap(); + }))).unwrap(); assert_eq!(pool.status().ready, 2); // then - let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Future))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(watcher::Status::Future)); + assert_eq!(stream.next(), Some(watcher::Status::Ready)); } #[test] @@ -816,17 +778,17 @@ mod tests { amount: 5, nonce: 0, }); - let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt).unwrap(); + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt)).unwrap(); assert_eq!(pool.status().ready, 1); // when - pool.remove_invalid(&[*watcher.hash()]); + pool.validated_pool.remove_invalid(&[*watcher.hash()]); // then - let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Invalid))); + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(watcher::Status::Ready)); + assert_eq!(stream.next(), Some(watcher::Status::Invalid)); assert_eq!(stream.next(), None); } @@ -840,7 +802,7 @@ mod tests { amount: 5, nonce: 0, }); - let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt).unwrap(); + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), uxt)).unwrap(); assert_eq!(pool.status().ready, 1); // when @@ -851,9 +813,9 @@ mod tests { // then - let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Broadcast(peers)))); + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(watcher::Status::Ready)); + assert_eq!(stream.next(), Some(watcher::Status::Broadcast(peers))); } #[test] @@ -874,7 +836,7 @@ mod tests { amount: 5, nonce: 0, }); - let watcher = pool.submit_and_watch(&BlockId::Number(0), xt).unwrap(); + let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), xt)).unwrap(); assert_eq!(pool.status().ready, 1); // when @@ -884,13 +846,13 @@ mod tests { amount: 4, nonce: 1, }); - pool.submit_one(&BlockId::Number(1), xt).unwrap(); + block_on(pool.submit_one(&BlockId::Number(1), xt)).unwrap(); assert_eq!(pool.status().ready, 1); // then - let mut stream = watcher.into_stream().wait(); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Dropped))); + let mut stream = futures::executor::block_on_stream(watcher.into_stream()); + assert_eq!(stream.next(), Some(watcher::Status::Ready)); + assert_eq!(stream.next(), Some(watcher::Status::Dropped)); } #[test] @@ -900,7 +862,7 @@ mod tests { let (ready, is_ready) = std::sync::mpsc::sync_channel(0); let (tx, rx) = std::sync::mpsc::sync_channel(1); let mut api = TestApi::default(); - api.delay = Mutex::new(rx.into()); + api.delay = Arc::new(Mutex::new(rx.into())); let pool = Arc::new(Pool::new(Default::default(), api)); // when @@ -914,7 +876,7 @@ mod tests { // This transaction should go to future, since we use `nonce: 1` let pool2 = pool.clone(); std::thread::spawn(move || { - pool2.submit_one(&BlockId::Number(0), xt).unwrap(); + block_on(pool2.submit_one(&BlockId::Number(0), xt)).unwrap(); ready.send(()).unwrap(); }); @@ -928,11 +890,11 @@ mod tests { }); // The tag the above transaction provides (TestApi is using just nonce as u8) let provides = vec![0_u8]; - pool.submit_one(&BlockId::Number(0), xt).unwrap(); + block_on(pool.submit_one(&BlockId::Number(0), xt)).unwrap(); assert_eq!(pool.status().ready, 1); // Now block import happens before the second transaction is able to finish verification. - pool.prune_tags(&BlockId::Number(1), vec![provides], vec![]).unwrap(); + block_on(pool.prune_tags(&BlockId::Number(1), vec![provides], vec![])).unwrap(); assert_eq!(pool.status().ready, 0); @@ -948,3 +910,4 @@ mod tests { } } } + diff --git a/core/transaction-pool/graph/src/ready.rs b/core/transaction-pool/graph/src/ready.rs index 85bb4dd783c42292b07dfb7292bbd709de081960..3698bf447eeaaecf0a6c2ad3212b9f7091b3e871 100644 --- a/core/transaction-pool/graph/src/ready.rs +++ b/core/transaction-pool/graph/src/ready.rs @@ -338,7 +338,20 @@ impl ReadyTransactions { } } - debug!(target: "txpool", "[{:?}] Pruned.", tx.hash); + // we also need to remove all other tags that this transaction provides, + // but since all the hard work is done, we only clear the provided_tag -> hash + // mapping. + let current_tag = &tag; + for tag in &tx.provides { + let removed = self.provided_tags.remove(tag); + assert_eq!( + removed.as_ref(), + if current_tag == tag { None } else { Some(&tx.hash) }, + "The pool contains exactly one transaction providing given tag; the removed transaction + claims to provide that tag, so it has to be mapped to it's hash; qed" + ); + } + removed.push(tx); } } diff --git a/core/transaction-pool/graph/src/validated_pool.rs b/core/transaction-pool/graph/src/validated_pool.rs new file mode 100644 index 0000000000000000000000000000000000000000..d528843e98d73261cf11832d48c8f0f0a1f6022c --- /dev/null +++ b/core/transaction-pool/graph/src/validated_pool.rs @@ -0,0 +1,377 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{ + collections::{HashSet, HashMap}, + hash, + time, +}; + +use crate::base_pool as base; +use crate::error; +use crate::listener::Listener; +use crate::rotator::PoolRotator; +use crate::watcher::Watcher; +use serde::Serialize; +use log::debug; + +use futures::channel::mpsc; +use parking_lot::{Mutex, RwLock}; +use sr_primitives::{ + generic::BlockId, + traits::{self, SaturatedConversion}, + transaction_validity::TransactionTag as Tag, +}; + +use crate::base_pool::PruneStatus; +use crate::pool::{EventStream, Options, ChainApi, BlockHash, ExHash, ExtrinsicFor, TransactionFor}; + +/// Pre-validated transaction. Validated pool only accepts transactions wrapped in this enum. +#[derive(Debug)] +pub enum ValidatedTransaction { + /// Transaction that has been validated successfully. + Valid(base::Transaction), + /// Transaction that is invalid. + Invalid(Hash, Error), + /// Transaction which validity can't be determined. + /// + /// We're notifying watchers about failure, if 'unknown' transaction is submitted. + Unknown(Hash, Error), +} + +/// A type of validated transaction stored in the pool. +pub type ValidatedTransactionFor = ValidatedTransaction< + ExHash, + ExtrinsicFor, + ::Error, +>; + +/// Pool that deals with validated transactions. +pub(crate) struct ValidatedPool { + api: B, + options: Options, + listener: RwLock, BlockHash>>, + pool: RwLock, + ExtrinsicFor, + >>, + import_notification_sinks: Mutex>>, + rotator: PoolRotator>, +} + +impl ValidatedPool { + /// Create a new transaction pool. + pub fn new(options: Options, api: B) -> Self { + ValidatedPool { + api, + options, + listener: Default::default(), + pool: Default::default(), + import_notification_sinks: Default::default(), + rotator: Default::default(), + } + } + + /// Bans given set of hashes. + pub fn ban(&self, now: &std::time::Instant, hashes: impl IntoIterator>) { + self.rotator.ban(now, hashes) + } + + /// Returns true if transaction with given hash is currently banned from the pool. + pub fn is_banned(&self, hash: &ExHash) -> bool { + self.rotator.is_banned(hash) + } + + /// Imports a bunch of pre-validated transactions to the pool. + pub fn submit(&self, txs: T) -> Vec, B::Error>> where + T: IntoIterator> + { + let results = txs.into_iter() + .map(|validated_tx| self.submit_one(validated_tx)) + .collect::>(); + + let removed = self.enforce_limits(); + + results.into_iter().map(|res| match res { + Ok(ref hash) if removed.contains(hash) => Err(error::Error::ImmediatelyDropped.into()), + other => other, + }).collect() + } + + /// Submit single pre-validated transaction to the pool. + fn submit_one(&self, tx: ValidatedTransactionFor) -> Result, B::Error> { + match tx { + ValidatedTransaction::Valid(tx) => { + let imported = self.pool.write().import(tx)?; + + if let base::Imported::Ready { .. } = imported { + self.import_notification_sinks.lock().retain(|sink| sink.unbounded_send(()).is_ok()); + } + + let mut listener = self.listener.write(); + fire_events(&mut *listener, &imported); + Ok(imported.hash().clone()) + } + ValidatedTransaction::Invalid(hash, err) => { + self.rotator.ban(&std::time::Instant::now(), std::iter::once(hash)); + Err(err.into()) + }, + ValidatedTransaction::Unknown(hash, err) => { + self.listener.write().invalid(&hash); + Err(err.into()) + } + } + } + + fn enforce_limits(&self) -> HashSet> { + let status = self.pool.read().status(); + let ready_limit = &self.options.ready; + let future_limit = &self.options.future; + + debug!(target: "txpool", "Pool Status: {:?}", status); + + if ready_limit.is_exceeded(status.ready, status.ready_bytes) + || future_limit.is_exceeded(status.future, status.future_bytes) { + // clean up the pool + let removed = { + let mut pool = self.pool.write(); + let removed = pool.enforce_limits(ready_limit, future_limit) + .into_iter().map(|x| x.hash.clone()).collect::>(); + // ban all removed transactions + self.rotator.ban(&std::time::Instant::now(), removed.iter().map(|x| x.clone())); + removed + }; + // run notifications + let mut listener = self.listener.write(); + for h in &removed { + listener.dropped(h, None); + } + + removed + } else { + Default::default() + } + } + + /// Import a single extrinsic and starts to watch their progress in the pool. + pub fn submit_and_watch( + &self, + tx: ValidatedTransactionFor, + ) -> Result, BlockHash>, B::Error> { + match tx { + ValidatedTransaction::Valid(tx) => { + let hash = self.api.hash_and_length(&tx.data).0; + let watcher = self.listener.write().create_watcher(hash); + self.submit(std::iter::once(ValidatedTransaction::Valid(tx))) + .pop() + .expect("One extrinsic passed; one result returned; qed") + .map(|_| watcher) + }, + ValidatedTransaction::Invalid(hash, err) => { + self.rotator.ban(&std::time::Instant::now(), std::iter::once(hash)); + Err(err.into()) + }, + ValidatedTransaction::Unknown(_, err) => Err(err.into()), + } + } + + /// For each extrinsic, returns tags that it provides (if known), or None (if it is unknown). + pub fn extrinsics_tags(&self, extrinsics: &[ExtrinsicFor]) -> (Vec>, Vec>>) { + let hashes = extrinsics.iter().map(|extrinsic| self.api.hash_and_length(extrinsic).0).collect::>(); + let in_pool = self.pool.read().by_hash(&hashes); + ( + hashes, + in_pool.into_iter() + .map(|existing_in_pool| existing_in_pool + .map(|transaction| transaction.provides.iter().cloned() + .collect())) + .collect(), + ) + } + + /// Prunes ready transactions that provide given list of tags. + pub fn prune_tags( + &self, + tags: impl IntoIterator, + ) -> Result, ExtrinsicFor>, B::Error> { + // Perform tag-based pruning in the base pool + let status = self.pool.write().prune_tags(tags); + // Notify event listeners of all transactions + // that were promoted to `Ready` or were dropped. + { + let mut listener = self.listener.write(); + for promoted in &status.promoted { + fire_events(&mut *listener, promoted); + } + for f in &status.failed { + listener.dropped(f, None); + } + } + + Ok(status) + } + + /// Resubmit transactions that have been revalidated after prune_tags call. + pub fn resubmit_pruned( + &self, + at: &BlockId, + known_imported_hashes: impl IntoIterator> + Clone, + pruned_hashes: Vec>, + pruned_xts: Vec>, + ) -> Result<(), B::Error> { + debug_assert_eq!(pruned_hashes.len(), pruned_xts.len()); + + // Resubmit pruned transactions + let results = self.submit(pruned_xts); + + // Collect the hashes of transactions that now became invalid (meaning that they are successfully pruned). + let hashes = results + .into_iter() + .enumerate() + .filter_map(|(idx, r)| match r.map_err(error::IntoPoolError::into_pool_error) { + Err(Ok(error::Error::InvalidTransaction(_))) => Some(pruned_hashes[idx].clone()), + _ => None, + }); + // Fire `pruned` notifications for collected hashes and make sure to include + // `known_imported_hashes` since they were just imported as part of the block. + let hashes = hashes.chain(known_imported_hashes.into_iter()); + { + let header_hash = self.api.block_id_to_hash(at)? + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())?; + let mut listener = self.listener.write(); + for h in hashes { + listener.pruned(header_hash, &h); + } + } + // perform regular cleanup of old transactions in the pool + // and update temporary bans. + self.clear_stale(at)?; + Ok(()) + } + + /// Removes stale transactions from the pool. + /// + /// Stale transactions are transaction beyond their longevity period. + /// Note this function does not remove transactions that are already included in the chain. + /// See `prune_tags` if you want this. + pub fn clear_stale(&self, at: &BlockId) -> Result<(), B::Error> { + let block_number = self.api.block_id_to_number(at)? + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into())? + .saturated_into::(); + let now = time::Instant::now(); + let to_remove = { + self.ready() + .filter(|tx| self.rotator.ban_if_stale(&now, block_number, &tx)) + .map(|tx| tx.hash.clone()) + .collect::>() + }; + let futures_to_remove: Vec> = { + let p = self.pool.read(); + let mut hashes = Vec::new(); + for tx in p.futures() { + if self.rotator.ban_if_stale(&now, block_number, &tx) { + hashes.push(tx.hash.clone()); + } + } + hashes + }; + // removing old transactions + self.remove_invalid(&to_remove); + self.remove_invalid(&futures_to_remove); + // clear banned transactions timeouts + self.rotator.clear_timeouts(&now); + + Ok(()) + } + + /// Get rotator reference. + #[cfg(test)] + pub fn rotator(&self) -> &PoolRotator> { + &self.rotator + } + + /// Get api reference. + pub fn api(&self) -> &B { + &self.api + } + + /// Return an event stream of transactions imported to the pool. + pub fn import_notification_stream(&self) -> EventStream { + let (sink, stream) = mpsc::unbounded(); + self.import_notification_sinks.lock().push(sink); + stream + } + + /// Invoked when extrinsics are broadcasted. + pub fn on_broadcasted(&self, propagated: HashMap, Vec>) { + let mut listener = self.listener.write(); + for (hash, peers) in propagated.into_iter() { + listener.broadcasted(&hash, peers); + } + } + + /// Remove from the pool. + pub fn remove_invalid(&self, hashes: &[ExHash]) -> Vec> { + // temporarily ban invalid transactions + debug!(target: "txpool", "Banning invalid transactions: {:?}", hashes); + self.rotator.ban(&time::Instant::now(), hashes.iter().cloned()); + + let invalid = self.pool.write().remove_invalid(hashes); + + let mut listener = self.listener.write(); + for tx in &invalid { + listener.invalid(&tx.hash); + } + + invalid + } + + /// Get an iterator for ready transactions ordered by priority + pub fn ready(&self) -> impl Iterator> { + self.pool.read().ready() + } + + /// Returns pool status. + pub fn status(&self) -> base::Status { + self.pool.read().status() + } +} + +fn fire_events( + listener: &mut Listener, + imported: &base::Imported, +) where + H: hash::Hash + Eq + traits::Member + Serialize, + H2: Clone, +{ + match *imported { + base::Imported::Ready { ref promoted, ref failed, ref removed, ref hash } => { + listener.ready(hash, None); + for f in failed { + listener.invalid(f); + } + for r in removed { + listener.dropped(&r.hash, Some(hash)); + } + for p in promoted { + listener.ready(p, None); + } + }, + base::Imported::Future { ref hash } => { + listener.future(hash) + }, + } +} diff --git a/core/transaction-pool/graph/src/watcher.rs b/core/transaction-pool/graph/src/watcher.rs index 44ab8431e8f612b7d5225aa452f5b13af7b41582..11d6b9f40742a3837ea66a3a926c90005fa51b0a 100644 --- a/core/transaction-pool/graph/src/watcher.rs +++ b/core/transaction-pool/graph/src/watcher.rs @@ -18,7 +18,7 @@ use futures::{ Stream, - sync::mpsc, + channel::mpsc, }; use serde::{Serialize, Deserialize}; @@ -60,9 +60,8 @@ impl Watcher { /// Pipe the notifications to given sink. /// /// Make sure to drive the future to completion. - pub fn into_stream(self) -> impl Stream, Error=()> { - // we can safely ignore the error here, `UnboundedReceiver` never fails. - self.receiver.map_err(|_| ()) + pub fn into_stream(self) -> impl Stream> { + self.receiver } } diff --git a/core/transaction-pool/src/api.rs b/core/transaction-pool/src/api.rs index c0c4c787a5012d652ff1aac873f483331d304da5..96403bd3f876f63e044d9a29279554de741bab2c 100644 --- a/core/transaction-pool/src/api.rs +++ b/core/transaction-pool/src/api.rs @@ -37,24 +37,24 @@ use sr_primitives::{ use crate::error; /// The transaction pool logic -pub struct ChainApi { +pub struct FullChainApi { client: Arc, _marker: PhantomData, } -impl ChainApi where +impl FullChainApi where Block: traits::Block, T: traits::ProvideRuntimeApi + HeaderBackend { /// Create new transaction pool logic. pub fn new(client: Arc) -> Self { - ChainApi { + FullChainApi { client, _marker: Default::default() } } } -impl txpool::ChainApi for ChainApi where +impl txpool::ChainApi for FullChainApi where Block: traits::Block, T: traits::ProvideRuntimeApi + HeaderBackend, T::Api: TaggedTransactionQueue @@ -62,9 +62,14 @@ impl txpool::ChainApi for ChainApi where type Block = Block; type Hash = H256; type Error = error::Error; + type ValidationFuture = futures::future::Ready>; - fn validate_transaction(&self, at: &BlockId, uxt: txpool::ExtrinsicFor) -> error::Result { - Ok(self.client.runtime_api().validate_transaction(at, uxt)?) + fn validate_transaction( + &self, + at: &BlockId, + uxt: txpool::ExtrinsicFor, + ) -> Self::ValidationFuture { + futures::future::ready(self.client.runtime_api().validate_transaction(at, uxt).map_err(Into::into)) } fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { diff --git a/core/transaction-pool/src/lib.rs b/core/transaction-pool/src/lib.rs index 1899c601b2fdbbc8b73aac524c5bd030026615e5..6938166299d852ccf53459f09f326bb42a2c3557 100644 --- a/core/transaction-pool/src/lib.rs +++ b/core/transaction-pool/src/lib.rs @@ -25,5 +25,5 @@ mod tests; pub mod error; -pub use api::ChainApi; +pub use api::FullChainApi; pub use txpool; diff --git a/core/transaction-pool/src/tests.rs b/core/transaction-pool/src/tests.rs index 71ed988e5e7b34901cd46d42ca1f6f3bb086e9fe..60a9e0562fce30ce678ee0cf52ee685608482484 100644 --- a/core/transaction-pool/src/tests.rs +++ b/core/transaction-pool/src/tests.rs @@ -18,6 +18,7 @@ use super::*; use codec::Encode; +use futures::executor::block_on; use txpool::{self, Pool}; use test_client::{runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}, AccountKeyring::{self, *}}; use sr_primitives::{ @@ -26,11 +27,15 @@ use sr_primitives::{ transaction_validity::{TransactionValidity, ValidTransaction}, }; -struct TestApi; +struct TestApi { + pub modifier: Box, +} impl TestApi { fn default() -> Self { - TestApi + TestApi { + modifier: Box::new(|_| {}), + } } } @@ -38,8 +43,13 @@ impl txpool::ChainApi for TestApi { type Block = Block; type Hash = Hash; type Error = error::Error; + type ValidationFuture = futures::future::Ready>; - fn validate_transaction(&self, at: &BlockId, uxt: txpool::ExtrinsicFor) -> error::Result { + fn validate_transaction( + &self, + at: &BlockId, + uxt: txpool::ExtrinsicFor, + ) -> Self::ValidationFuture { let expected = index(at); let requires = if expected == uxt.transfer().nonce { vec![] @@ -48,13 +58,19 @@ impl txpool::ChainApi for TestApi { }; let provides = vec![vec![uxt.transfer().nonce as u8]]; - Ok(TransactionValidity::Valid(ValidTransaction { + let mut validity = ValidTransaction { priority: 1, requires, provides, longevity: 64, propagate: true, - })) + }; + + (self.modifier)(&mut validity); + + futures::future::ready(Ok( + Ok(validity) + )) } fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { @@ -105,7 +121,7 @@ fn pool() -> Pool { fn submission_should_work() { let pool = pool(); assert_eq!(209, index(&BlockId::number(0))); - pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209]); @@ -114,8 +130,8 @@ fn submission_should_work() { #[test] fn multiple_submission_should_work() { let pool = pool(); - pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); - pool.submit_one(&BlockId::number(0), uxt(Alice, 210)).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209, 210]); @@ -124,7 +140,7 @@ fn multiple_submission_should_work() { #[test] fn early_nonce_should_be_culled() { let pool = pool(); - pool.submit_one(&BlockId::number(0), uxt(Alice, 208)).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 208))).unwrap(); let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, Vec::::new()); @@ -134,11 +150,11 @@ fn early_nonce_should_be_culled() { fn late_nonce_should_be_queued() { let pool = pool(); - pool.submit_one(&BlockId::number(0), uxt(Alice, 210)).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, Vec::::new()); - pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209, 210]); } @@ -146,13 +162,13 @@ fn late_nonce_should_be_queued() { #[test] fn prune_tags_should_work() { let pool = pool(); - pool.submit_one(&BlockId::number(0), uxt(Alice, 209)).unwrap(); - pool.submit_one(&BlockId::number(0), uxt(Alice, 210)).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 209))).unwrap(); + block_on(pool.submit_one(&BlockId::number(0), uxt(Alice, 210))).unwrap(); let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![209, 210]); - pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![]).unwrap(); + block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![])).unwrap(); let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, vec![210]); @@ -162,14 +178,45 @@ fn prune_tags_should_work() { fn should_ban_invalid_transactions() { let pool = pool(); let uxt = uxt(Alice, 209); - let hash = pool.submit_one(&BlockId::number(0), uxt.clone()).unwrap(); + let hash = block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap(); pool.remove_invalid(&[hash]); - pool.submit_one(&BlockId::number(0), uxt.clone()).unwrap_err(); + block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap_err(); // when let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); assert_eq!(pending, Vec::::new()); // then - pool.submit_one(&BlockId::number(0), uxt.clone()).unwrap_err(); + block_on(pool.submit_one(&BlockId::number(0), uxt.clone())).unwrap_err(); +} + +#[test] +fn should_correctly_prune_transactions_providing_more_than_one_tag() { + let mut api = TestApi::default(); + api.modifier = Box::new(|v: &mut ValidTransaction| { + v.provides.push(vec![155]); + }); + let pool = Pool::new(Default::default(), api); + let xt = uxt(Alice, 209); + block_on(pool.submit_one(&BlockId::number(0), xt.clone())).expect("1. Imported"); + assert_eq!(pool.status().ready, 1); + + // remove the transaction that just got imported. + block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![])).expect("1. Pruned"); + assert_eq!(pool.status().ready, 0); + // it's re-imported to future + assert_eq!(pool.status().future, 1); + + // so now let's insert another transaction that also provides the 155 + let xt = uxt(Alice, 211); + block_on(pool.submit_one(&BlockId::number(2), xt.clone())).expect("2. Imported"); + assert_eq!(pool.status().ready, 1); + assert_eq!(pool.status().future, 1); + let pending: Vec<_> = pool.ready().map(|a| a.data.transfer().nonce).collect(); + assert_eq!(pending, vec![211]); + + // prune it and make sure the pool is empty + block_on(pool.prune_tags(&BlockId::number(3), vec![vec![155]], vec![])).expect("2. Pruned"); + assert_eq!(pool.status().ready, 0); + assert_eq!(pool.status().future, 2); } diff --git a/core/trie/Cargo.toml b/core/trie/Cargo.toml index 82945d90f33d7d49aec9f4a150cd31bfd4629181..50498a17ba65dda363f79496b4d8e515811d1d8b 100644 --- a/core/trie/Cargo.toml +++ b/core/trie/Cargo.toml @@ -3,7 +3,7 @@ name = "substrate-trie" version = "2.0.0" authors = ["Parity Technologies "] description = "Patricia trie stuff using a parity-scale-codec node format" -repository = "https://github.com/paritytech/parity-common" +repository = "https://github.com/paritytech/substrate" license = "GPL-3.0" edition = "2018" @@ -14,18 +14,18 @@ harness = false [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false } -hash-db = { version = "0.15.0", default-features = false } -trie-db = { version = "0.15.0", default-features = false } -trie-root = { version = "0.15.0", default-features = false } -memory-db = { version = "0.15.0", default-features = false } +hash-db = { version = "0.15.2", default-features = false } +trie-db = { version = "0.15.2", default-features = false } +trie-root = { version = "0.15.2", default-features = false } +memory-db = { version = "0.15.2", default-features = false } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } [dev-dependencies] -trie-bench = { version = "0.16.0" } -trie-standardmap = { version = "0.15.0" } -keccak-hasher = { version = "0.15.0" } -criterion = "0.2" -hex-literal = "0.2.0" +trie-bench = "0.16.2" +trie-standardmap = "0.15.2" +keccak-hasher = "0.15.2" +criterion = "0.2.11" +hex-literal = "0.2.1" [features] default = ["std"] diff --git a/core/trie/src/lib.rs b/core/trie/src/lib.rs index e526a27ebefba5f152b4aee379cfb4ec73bf7142..eab05bab28af016ed9d9c092d832f97ad69b6122 100644 --- a/core/trie/src/lib.rs +++ b/core/trie/src/lib.rs @@ -33,15 +33,15 @@ pub use trie_stream::TrieStream; /// The Substrate format implementation of `NodeCodec`. pub use node_codec::NodeCodec; /// Various re-exports from the `trie-db` crate. -pub use trie_db::{Trie, TrieMut, DBValue, Recorder, CError, - Query, TrieLayout, TrieConfiguration, nibble_ops}; +pub use trie_db::{ + Trie, TrieMut, DBValue, Recorder, CError, Query, TrieLayout, TrieConfiguration, nibble_ops, +}; /// Various re-exports from the `memory-db` crate. pub use memory_db::KeyFunction; pub use memory_db::prefixed_key; /// Various re-exports from the `hash-db` crate. pub use hash_db::{HashDB as HashDBT, EMPTY_PREFIX}; - #[derive(Default)] /// substrate trie layout pub struct Layout(rstd::marker::PhantomData); @@ -166,25 +166,6 @@ pub fn read_trie_value_with< Ok(TrieDB::::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) } -/// Determine whether a child trie key is valid. -/// -/// For now, the only valid child trie key is `:child_storage:default:`. -/// -/// `child_trie_root` and `child_delta_trie_root` can panic if invalid value is provided to them. -pub fn is_child_trie_key_valid(storage_key: &[u8]) -> bool { - use primitives::storage::well_known_keys; - let has_right_prefix = storage_key.starts_with(b":child_storage:default:"); - if has_right_prefix { - // This is an attempt to catch a change of `is_child_storage_key`, which - // just checks if the key has prefix `:child_storage:` at the moment of writing. - debug_assert!( - well_known_keys::is_child_storage_key(&storage_key), - "`is_child_trie_key_valid` is a subset of `is_child_storage_key`", - ); - } - has_right_prefix -} - /// Determine the default child trie root. pub fn default_child_trie_root(_storage_key: &[u8]) -> Vec { L::trie_root::<_, Vec, Vec>(core::iter::empty()).as_ref().iter().cloned().collect() diff --git a/core/trie/src/node_header.rs b/core/trie/src/node_header.rs index 50d3d87250de6002c5df232bb44cc7db6c250a96..616273e574d6007106a495965d384bb0238c20fd 100644 --- a/core/trie/src/node_header.rs +++ b/core/trie/src/node_header.rs @@ -22,7 +22,7 @@ use rstd::iter::once; /// A node header #[derive(Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(primitives::RuntimeDebug)] pub(crate) enum NodeHeader { Null, Branch(bool, usize), diff --git a/core/utils/build-script-utils/Cargo.toml b/core/utils/build-script-utils/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..36703ab838f065f3b1e0b0c37bed1bc39cc05c17 --- /dev/null +++ b/core/utils/build-script-utils/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "substrate-build-script-utils" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] diff --git a/core/utils/build-script-utils/src/lib.rs b/core/utils/build-script-utils/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..be2f4636b6746d8a2f6dbf164aa64564f8d47ccb --- /dev/null +++ b/core/utils/build-script-utils/src/lib.rs @@ -0,0 +1,44 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Crate with utility functions for `build.rs` scripts. + +use std::{env, path::PathBuf}; + +/// Make sure the calling `build.rs` script is rerun when `.git/HEAD` changed. +/// +/// The file is searched from the `CARGO_MANIFEST_DIR` upwards. If the file can not be found, +/// a warning is generated. +pub fn rerun_if_git_head_changed() { + let mut manifest_dir = PathBuf::from( + env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo.") + ); + let manifest_dir_copy = manifest_dir.clone(); + + while manifest_dir.parent().is_some() { + if manifest_dir.join(".git/HEAD").exists() { + println!("cargo:rerun-if-changed={}", manifest_dir.join(".git/HEAD").display()); + return + } + + manifest_dir.pop(); + } + + println!( + "cargo:warning=Could not find `.git/HEAD` searching from `{}` upwards!", + manifest_dir_copy.display(), + ); +} diff --git a/core/utils/fork-tree/src/lib.rs b/core/utils/fork-tree/src/lib.rs index 5a7480e0651aa0ca1c803e0105c5bdf4db2883a3..f192ee54785b18c402e321500a93f17f6aa9aba1 100644 --- a/core/utils/fork-tree/src/lib.rs +++ b/core/utils/fork-tree/src/lib.rs @@ -86,55 +86,46 @@ impl ForkTree where N: Ord + Clone, V: Clone, { - /// Prune all nodes that are not descendents of `hash` according to - /// `is_descendent_of`. The given function `is_descendent_of` should return - /// `true` if the second hash (target) is a descendent of the first hash - /// (base). After pruning the tree it should have one or zero roots. The - /// number and order of calls to `is_descendent_of` is unspecified and - /// subject to change. - pub fn prune( + /// Prune the tree, removing all non-canonical nodes. We find the node in the + /// tree that is the deepest ancestor of the given hash and that passes the + /// given predicate. If such a node exists, we re-root the tree to this + /// node. Otherwise the tree remains unchanged. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is a + /// descendent of the first hash (base). + pub fn prune( &mut self, hash: &H, - number: N, - is_descendent_of: &F + number: &N, + is_descendent_of: &F, + predicate: &P, ) -> Result<(), Error> where E: std::error::Error, - F: Fn(&H, &H) -> Result + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, { - let mut new_root = None; - for node in self.node_iter() { - // if the node has a lower number than the one being finalized then - // we only keep if it has no children and the finalized block is a - // descendent of this node - if node.number < number { - if !node.children.is_empty() || !is_descendent_of(&node.hash, hash)? { - continue; - } - } - - // if the node has the same number as the finalized block then it - // must have the same hash - if node.number == number && node.hash != *hash { - continue; - } + let new_root = self.find_node_where( + hash, + number, + is_descendent_of, + predicate, + )?; - // if the node has a higher number then we keep it if it is a - // descendent of the finalized block - if node.number > number && !is_descendent_of(hash, &node.hash)? { - continue; - } + if let Some(root) = new_root { + let mut root = root.clone(); - new_root = Some(node); - break; - } + // we found the deepest ancestor of the finalized block, so we prune + // out any children that don't include the finalized block. + let children = std::mem::replace(&mut root.children, Vec::new()); + root.children = children.into_iter().filter(|node| { + node.number == *number && node.hash == *hash || + node.number < *number && is_descendent_of(&node.hash, hash).unwrap_or(false) + }).take(1).collect(); - if let Some(root) = new_root { - self.roots = vec![root.clone()]; + self.roots = vec![root]; } Ok(()) } - } impl ForkTree where @@ -153,6 +144,8 @@ impl ForkTree where /// should return `true` if the second hash (target) is a descendent of the /// first hash (base). This method assumes that nodes in the same branch are /// imported in order. + /// + /// Returns `true` if the imported node is a root. pub fn import( &mut self, mut hash: H, @@ -208,7 +201,7 @@ impl ForkTree where self.node_iter().map(|node| (&node.hash, &node.number, &node.data)) } - /// Find a node in the tree that is the lowest ancestor of the given + /// Find a node in the tree that is the deepest ancestor of the given /// block hash and which passes the given predicate. The given function /// `is_descendent_of` should return `true` if the second hash (target) /// is a descendent of the first hash (base). @@ -228,8 +221,8 @@ impl ForkTree where let node = root.find_node_where(hash, number, is_descendent_of, predicate)?; // found the node, early exit - if let Some(node) = node { - return Ok(node); + if let FindOutcome::Found(node) = node { + return Ok(Some(node)); } } @@ -240,14 +233,16 @@ impl ForkTree where /// with the given hash exists. All other roots are pruned, and the children /// of the finalized node become the new roots. pub fn finalize_root(&mut self, hash: &H) -> Option { - if let Some(position) = self.roots.iter().position(|node| node.hash == *hash) { - let node = self.roots.swap_remove(position); - self.roots = node.children; - self.best_finalized_number = Some(node.number); - return Some(node.data); - } + self.roots.iter().position(|node| node.hash == *hash) + .map(|position| self.finalize_root_at(position)) + } - None + /// Finalize root at given positiion. See `finalize_root` comment for details. + fn finalize_root_at(&mut self, position: usize) -> V { + let node = self.roots.swap_remove(position); + self.roots = node.children; + self.best_finalized_number = Some(node.number); + return node.data; } /// Finalize a node in the tree. This method will make sure that the node @@ -305,6 +300,79 @@ impl ForkTree where } } + /// Finalize a node in the tree and all its ancestors. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is + // a descendent of the first hash (base). + pub fn finalize_with_ancestors( + &mut self, + hash: &H, + number: N, + is_descendent_of: &F, + ) -> Result, Error> + where E: std::error::Error, + F: Fn(&H, &H) -> Result + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert); + } + } + + // check if one of the current roots is being finalized + if let Some(root) = self.finalize_root(hash) { + return Ok(FinalizationResult::Changed(Some(root))); + } + + // we need to: + // 1) remove all roots that are not ancestors AND not descendants of finalized block; + // 2) if node is descendant - just leave it; + // 3) if node is ancestor - 'open it' + let mut changed = false; + let mut idx = 0; + while idx != self.roots.len() { + let (is_finalized, is_descendant, is_ancestor) = { + let root = &self.roots[idx]; + let is_finalized = root.hash == *hash; + let is_descendant = !is_finalized + && root.number > number && is_descendent_of(hash, &root.hash).unwrap_or(false); + let is_ancestor = !is_finalized && !is_descendant + && root.number < number && is_descendent_of(&root.hash, hash).unwrap_or(false); + (is_finalized, is_descendant, is_ancestor) + }; + + // if we have met finalized root - open it and return + if is_finalized { + return Ok(FinalizationResult::Changed(Some(self.finalize_root_at(idx)))); + } + + // if node is descendant of finalized block - just leave it as is + if is_descendant { + idx += 1; + continue; + } + + // if node is ancestor of finalized block - remove it and continue with children + if is_ancestor { + let root = self.roots.swap_remove(idx); + self.roots.extend(root.children); + changed = true; + continue; + } + + // if node is neither ancestor, nor descendant of the finalized block - remove it + self.roots.swap_remove(idx); + changed = true; + } + + self.best_finalized_number = Some(number); + + if changed { + Ok(FinalizationResult::Changed(None)) + } else { + Ok(FinalizationResult::Unchanged) + } + } + /// Checks if any node in the tree is finalized by either finalizing the /// node itself or a child node that's not in the tree, guaranteeing that /// the node being finalized isn't a descendent of any of the node's @@ -435,6 +503,17 @@ impl ForkTree where mod node_implementation { use super::*; + /// The outcome of a search within a node. + pub enum FindOutcome { + // this is the node we were looking for. + Found(T), + // not the node we're looking for. contains a flag indicating + // whether the node was a descendent. true implies the predicate failed. + Failure(bool), + // Abort search. + Abort, + } + #[derive(Clone, Debug, Decode, Encode, PartialEq)] pub struct Node { pub hash: H, @@ -485,9 +564,10 @@ mod node_implementation { } } - /// Find a node in the tree that is the lowest ancestor of the given - /// block hash and which passes the given predicate. The given function - /// `is_descendent_of` should return `true` if the second hash (target) + /// Find a node in the tree that is the deepest ancestor of the given + /// block hash which also passes the given predicate, backtracking + /// when the predicate fails. + /// The given function `is_descendent_of` should return `true` if the second hash (target) /// is a descendent of the first hash (base). // FIXME: it would be useful if this returned a mutable reference but // rustc can't deal with lifetimes properly. an option would be to try @@ -498,23 +578,32 @@ mod node_implementation { number: &N, is_descendent_of: &F, predicate: &P, - ) -> Result>>, Error> + ) -> Result>, Error> where E: std::error::Error, F: Fn(&H, &H) -> Result, P: Fn(&V) -> bool, { // stop searching this branch if *number < self.number { - return Ok(None); + return Ok(FindOutcome::Failure(false)); } + let mut known_descendent_of = false; + // continue depth-first search through all children for node in self.children.iter() { - let node = node.find_node_where(hash, number, is_descendent_of, predicate)?; - // found node, early exit - if node.is_some() { - return Ok(node); + match node.find_node_where(hash, number, is_descendent_of, predicate)? { + FindOutcome::Abort => return Ok(FindOutcome::Abort), + FindOutcome::Found(x) => return Ok(FindOutcome::Found(x)), + FindOutcome::Failure(true) => { + // if the block was a descendent of this child, + // then it cannot be a descendent of any others, + // so we don't search them. + known_descendent_of = true; + break; + }, + FindOutcome::Failure(false) => {}, } } @@ -522,24 +611,23 @@ mod node_implementation { // searching for is a descendent of this node then we will stop the // search here, since there aren't any more children and we found // the correct node so we don't want to backtrack. - if is_descendent_of(&self.hash, hash)? { + let is_descendent_of = known_descendent_of || is_descendent_of(&self.hash, hash)?; + if is_descendent_of { // if the predicate passes we return the node if predicate(&self.data) { - Ok(Some(Some(self))) - - // otherwise we stop the search returning `None` - } else { - Ok(Some(None)) + return Ok(FindOutcome::Found(self)); } - } else { - Ok(None) } + + // otherwise, tell our ancestor that we failed, and whether + // the block was a descendent. + Ok(FindOutcome::Failure(is_descendent_of)) } } } // Workaround for: https://github.com/rust-lang/rust/issues/34537 -use node_implementation::Node; +use node_implementation::{Node, FindOutcome}; struct ForkTreeIterator<'a, H, N, V> { stack: Vec<&'a Node>, @@ -580,23 +668,32 @@ mod test { // / - G // / / // A - F - H - I + // \ + // - L - M - N + // \ + // - O // \ // — J - K // + // (where N is not a part of fork tree) let is_descendent_of = |base: &&str, block: &&str| -> Result { - let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]; match (*base, *block) { ("A", b) => Ok(letters.into_iter().any(|n| n == b)), ("B", b) => Ok(b == "C" || b == "D" || b == "E"), ("C", b) => Ok(b == "D" || b == "E"), ("D", b) => Ok(b == "E"), ("E", _) => Ok(false), - ("F", b) => Ok(b == "G" || b == "H" || b == "I"), + ("F", b) => Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "N" || b == "O"), ("G", _) => Ok(false), - ("H", b) => Ok(b == "I"), + ("H", b) => Ok(b == "I" || b == "L" || b == "M" || b == "O"), ("I", _) => Ok(false), ("J", b) => Ok(b == "K"), ("K", _) => Ok(false), + ("L", b) => Ok(b == "M" || b == "O" || b == "N"), + ("M", b) => Ok(b == "N"), + ("N", _) => Ok(false), + ("O", _) => Ok(false), ("0", _) => Ok(true), _ => Ok(false), } @@ -614,6 +711,9 @@ mod test { tree.import("H", 3, (), &is_descendent_of).unwrap(); tree.import("I", 4, (), &is_descendent_of).unwrap(); + tree.import("L", 4, (), &is_descendent_of).unwrap(); + tree.import("M", 5, (), &is_descendent_of).unwrap(); + tree.import("O", 5, (), &is_descendent_of).unwrap(); tree.import("J", 2, (), &is_descendent_of).unwrap(); tree.import("K", 3, (), &is_descendent_of).unwrap(); @@ -770,7 +870,7 @@ mod test { assert_eq!( tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), - vec![("I", 4)], + vec![("I", 4), ("L", 4)], ); // finalizing a node from another fork that isn't part of the tree clears the tree @@ -782,6 +882,71 @@ mod test { assert!(tree.roots.is_empty()); } + #[test] + fn finalize_with_ancestor_works() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + let original_roots = tree.roots.clone(); + + // finalizing a block prior to any in the node doesn't change the tree + assert_eq!( + tree.finalize_with_ancestors(&"0", 0, &is_descendent_of), + Ok(FinalizationResult::Unchanged), + ); + + assert_eq!(tree.roots, original_roots); + + // finalizing "A" opens up three possible forks + assert_eq!( + tree.finalize_with_ancestors(&"A", 1, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), + vec![("B", 2), ("F", 2), ("J", 2)], + ); + + // finalizing H: + // 1) removes roots that are not ancestors/descendants of H (B, J) + // 2) opens root that is ancestor of H (F -> G+H) + // 3) finalizes the just opened root H (H -> I + L) + assert_eq!( + tree.finalize_with_ancestors(&"H", 3, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), + vec![("I", 4), ("L", 4)], + ); + + assert_eq!( + tree.best_finalized_number, + Some(3), + ); + + // finalizing N (which is not a part of the tree): + // 1) removes roots that are not ancestors/descendants of N (I) + // 2) opens root that is ancestor of N (L -> M+O) + // 3) removes roots that are not ancestors/descendants of N (O) + // 4) opens root that is ancestor of N (M -> {}) + assert_eq!( + tree.finalize_with_ancestors(&"N", 6, &is_descendent_of), + Ok(FinalizationResult::Changed(None)), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (h.clone(), n.clone())).collect::>(), + vec![], + ); + + assert_eq!( + tree.best_finalized_number, + Some(6), + ); + } + #[test] fn finalize_with_descendent_works() { #[derive(Debug, PartialEq)] @@ -927,7 +1092,9 @@ mod test { vec![ ("A", 1), ("J", 2), ("K", 3), - ("F", 2), ("H", 3), ("I", 4), + ("F", 2), ("H", 3), ("L", 4), ("O", 5), + ("M", 5), + ("I", 4), ("G", 3), ("B", 2), ("C", 3), ("D", 4), ("E", 5), ], @@ -1027,23 +1194,41 @@ mod test { tree.prune( &"C", - 3, + &3, &is_descendent_of, + &|_| true, + ).unwrap(); + + assert_eq!( + tree.roots.iter().map(|node| node.hash).collect::>(), + vec!["B"], + ); + + assert_eq!( + tree.iter().map(|(hash, _, _)| *hash).collect::>(), + vec!["B", "C", "D", "E"], + ); + + tree.prune( + &"E", + &5, + &is_descendent_of, + &|_| true, ).unwrap(); assert_eq!( tree.roots.iter().map(|node| node.hash).collect::>(), - vec!["C"], + vec!["D"], ); assert_eq!( tree.iter().map(|(hash, _, _)| *hash).collect::>(), - vec!["C", "D", "E"], + vec!["D", "E"], ); } #[test] - fn find_node_doesnt_backtrack_after_finding_highest_descending_node() { + fn find_node_backtracks_after_finding_highest_descending_node() { let mut tree = ForkTree::new(); // @@ -1061,11 +1246,12 @@ mod test { }; tree.import("A", 1, 1, &is_descendent_of).unwrap(); - tree.import("B", 2, 4, &is_descendent_of).unwrap(); + tree.import("B", 2, 2, &is_descendent_of).unwrap(); tree.import("C", 2, 4, &is_descendent_of).unwrap(); - // when searching the tree we reach both node `B` and `C`, but the - // predicate doesn't pass. still, we should not backtrack to node `A`. + // when searching the tree we reach node `C`, but the + // predicate doesn't pass. we should backtrack to `B`, but not to `A`, + // since "B" fulfills the predicate. let node = tree.find_node_where( &"D", &3, @@ -1073,6 +1259,6 @@ mod test { &|data| *data < 3, ).unwrap(); - assert_eq!(node, None); + assert_eq!(node.unwrap().hash, "B"); } } diff --git a/core/utils/wasm-builder-runner/Cargo.toml b/core/utils/wasm-builder-runner/Cargo.toml index 4046b7e4e2f2551284fabff97501a3731c204edb..ab8a539054820445d744711a99192b3adf6f524f 100644 --- a/core/utils/wasm-builder-runner/Cargo.toml +++ b/core/utils/wasm-builder-runner/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-wasm-builder-runner" -version = "1.0.2" +version = "1.0.4" authors = ["Parity Technologies "] description = "Runner for substrate-wasm-builder" edition = "2018" diff --git a/core/utils/wasm-builder-runner/src/lib.rs b/core/utils/wasm-builder-runner/src/lib.rs index 1558dbf22044f1e2f414a7e8c2ba73546c895cc2..1739c5eff211e7b5aaa92237a31f80b1a8b32b16 100644 --- a/core/utils/wasm-builder-runner/src/lib.rs +++ b/core/utils/wasm-builder-runner/src/lib.rs @@ -30,9 +30,6 @@ use std::{env, process::{Command, self}, fs, path::{PathBuf, Path}}; /// Environment variable that tells us to skip building the WASM binary. const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; -/// Environment variable to extend the `RUSTFLAGS` variable given to the WASM build. -const WASM_BUILD_RUSTFLAGS_ENV: &str = "WASM_BUILD_RUSTFLAGS"; - /// Environment variable that tells us to create a dummy WASM binary. /// /// This is useful for `cargo check` to speed-up the compilation. @@ -102,22 +99,8 @@ impl WasmBuilderSource { pub fn build_current_project_with_rustflags( file_name: &str, wasm_builder_source: WasmBuilderSource, - rustflags: &str, + default_rustflags: &str, ) { - let given_rustflags = env::var(WASM_BUILD_RUSTFLAGS_ENV).unwrap_or_default(); - env::set_var(WASM_BUILD_RUSTFLAGS_ENV, format!("{} {}", given_rustflags, rustflags)); - - build_current_project(file_name, wasm_builder_source) -} - -/// Build the currently built project as WASM binary. -/// -/// The current project is determined using the `CARGO_MANIFEST_DIR` environment variable. -/// -/// `file_name` - The name of the file being generated in the `OUT_DIR`. The file contains the -/// constant `WASM_BINARY` which contains the build wasm binary. -/// `wasm_builder_path` - Path to the wasm-builder project, relative to `CARGO_MANIFEST_DIR`. -pub fn build_current_project(file_name: &str, wasm_builder_source: WasmBuilderSource) { if check_skip_build() { // If we skip the build, we still want to make sure to be called when an env variable changes generate_rerun_if_changed_instructions(); @@ -133,12 +116,20 @@ pub fn build_current_project(file_name: &str, wasm_builder_source: WasmBuilderSo let cargo_toml_path = manifest_dir.join("Cargo.toml"); let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!")); let file_path = out_dir.join(file_name); - let project_folder = out_dir.join("wasm_build_runner"); + let project_name = env::var("CARGO_PKG_NAME").expect("`CARGO_PKG_NAME` is set by cargo!"); + let project_folder = get_workspace_root().join(project_name); if check_provide_dummy_wasm_binary() { provide_dummy_wasm_binary(&file_path); } else { - create_project(&project_folder, &file_path, &manifest_dir, wasm_builder_source, &cargo_toml_path); + create_project( + &project_folder, + &file_path, + &manifest_dir, + wasm_builder_source, + &cargo_toml_path, + default_rustflags, + ); run_project(&project_folder); } @@ -147,12 +138,43 @@ pub fn build_current_project(file_name: &str, wasm_builder_source: WasmBuilderSo generate_rerun_if_changed_instructions(); } +/// Build the currently built project as WASM binary. +/// +/// The current project is determined using the `CARGO_MANIFEST_DIR` environment variable. +/// +/// `file_name` - The name of the file being generated in the `OUT_DIR`. The file contains the +/// constant `WASM_BINARY` which contains the build wasm binary. +/// `wasm_builder_path` - Path to the wasm-builder project, relative to `CARGO_MANIFEST_DIR`. +pub fn build_current_project(file_name: &str, wasm_builder_source: WasmBuilderSource) { + build_current_project_with_rustflags(file_name, wasm_builder_source, ""); +} + +/// Returns the root path of the wasm-builder-runner workspace. +/// +/// The wasm-builder-runner workspace contains all wasm-builder-runner's projects. +fn get_workspace_root() -> PathBuf { + let out_dir_env = env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!"); + let mut out_dir = PathBuf::from(&out_dir_env); + + loop { + match out_dir.parent() { + Some(parent) if out_dir.ends_with("build") => return parent.join("wbuild-runner"), + _ => if !out_dir.pop() { + break; + } + } + } + + panic!("Could not find target dir in: {}", out_dir_env) +} + fn create_project( project_folder: &Path, file_path: &Path, manifest_dir: &Path, wasm_builder_source: WasmBuilderSource, cargo_toml_path: &Path, + default_rustflags: &str, ) { fs::create_dir_all(project_folder.join("src")) .expect("WASM build runner dir create can not fail; qed"); @@ -179,12 +201,19 @@ fn create_project( project_folder.join("src/main.rs"), format!( r#" + use substrate_wasm_builder::build_project_with_default_rustflags; + fn main() {{ - substrate_wasm_builder::build_project("{file_path}", "{cargo_toml_path}") + build_project_with_default_rustflags( + "{file_path}", + "{cargo_toml_path}", + "{default_rustflags}", + ) }} "#, file_path = replace_back_slashes(file_path.display()), cargo_toml_path = replace_back_slashes(cargo_toml_path.display()), + default_rustflags = default_rustflags, ) ).expect("WASM build runner `main.rs` writing can not fail; qed"); } @@ -198,6 +227,11 @@ fn run_project(project_folder: &Path) { cmd.arg("--release"); } + // Unset the `CARGO_TARGET_DIR` to prevent a cargo deadlock (cargo locks a target dir exclusive). + // The runner project is created in `CARGO_TARGET_DIR` and executing it will create a sub target + // directory inside of `CARGO_TARGET_DIR`. + cmd.env_remove("CARGO_TARGET_DIR"); + if !cmd.status().map(|s| s.success()).unwrap_or(false) { // Don't spam the output with backtraces when a build failed! process::exit(1); @@ -226,7 +260,7 @@ fn check_provide_dummy_wasm_binary() -> bool { fn provide_dummy_wasm_binary(file_path: &Path) { fs::write( file_path, - "pub const WASM_BINARY: &[u8] = &[]; pub const WASM_BINARY_BLOATY: &[u8] = &[];" + "pub const WASM_BINARY: &[u8] = &[]; pub const WASM_BINARY_BLOATY: &[u8] = &[];", ).expect("Writing dummy WASM binary should not fail"); } diff --git a/core/utils/wasm-builder/Cargo.toml b/core/utils/wasm-builder/Cargo.toml index 44288dbcd268f97844230cc9b9f5a701cfcaac9f..66d94c32ab330d151face2cb671aaa7e9b7d0b90 100644 --- a/core/utils/wasm-builder/Cargo.toml +++ b/core/utils/wasm-builder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-wasm-builder" -version = "1.0.4" +version = "1.0.8" authors = ["Parity Technologies "] description = "Utility for building WASM binaries" edition = "2018" @@ -10,8 +10,10 @@ license = "GPL-3.0" [dependencies] build-helper = "0.1.1" -cargo_metadata = "0.8" +cargo_metadata = "0.9.0" tempfile = "3.1.0" -toml = "0.5.1" -walkdir = "2.2.8" +toml = "0.5.4" +walkdir = "2.2.9" fs2 = "0.4.3" +wasm-gc-api = "0.1.11" +atty = "0.2.13" diff --git a/core/utils/wasm-builder/README.md b/core/utils/wasm-builder/README.md index 8a8c67d6a8c1d164e10d1d4f68a714d83086f5d9..5b94f040ff9e61e449addf3f4940d30fd73b8d4f 100644 --- a/core/utils/wasm-builder/README.md +++ b/core/utils/wasm-builder/README.md @@ -1,15 +1,14 @@ -## WASM builder is a utility for building a project as a WASM binary +# WASM builder is a utility for building a project as a WASM binary The WASM builder is a tool that integrates the process of building the WASM binary of your project into the main `cargo` build process. -### Project setup +## Project setup A project that should be compiled as a WASM binary needs to: 1. Add a `build.rs` file. 2. Add `substrate-wasm-builder-runner` as dependency into `build-dependencies`. -3. Add a feature called `no-std`. The `build.rs` file needs to contain the following code: @@ -26,8 +25,6 @@ fn main() { } ``` -The `no-std` feature will be enabled by WASM builder while compiling your project to WASM. - As the final step, you need to add the following to your project: ```rust @@ -37,30 +34,32 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); This will include the generated WASM binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`. The former is a compact WASM binary and the latter is not compacted. -### Environment variables +## Environment variables By using environment variables, you can configure which WASM binaries are built and how: -- `SKIP_WASM_BUILD` - Skips building any WASM binary. This is useful when only native should be recompiled. -- `BUILD_DUMMY_WASM_BINARY` - Builds dummy WASM binaries. These dummy binaries are empty and useful +- `SKIP_WASM_BUILD` - Skips building any wasm binary. This is useful when only native should be recompiled. +- `BUILD_DUMMY_WASM_BINARY` - Builds dummy wasm binaries. These dummy binaries are empty and useful for `cargo check` runs. -- `WASM_BUILD_TYPE` - Sets the build type for building WASM binaries. Supported values are `release` or `debug`. +- `WASM_BUILD_TYPE` - Sets the build type for building wasm binaries. Supported values are `release` or `debug`. By default the build type is equal to the build type used by the main build. -- `TRIGGER_WASM_BUILD` - Can be set to trigger a WASM build. On subsequent calls the value of the variable +- `TRIGGER_WASM_BUILD` - Can be set to trigger a wasm build. On subsequent calls the value of the variable needs to change. As WASM builder instructs `cargo` to watch for file changes this environment variable should only be required in certain circumstances. -- `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the WASM binary. +- `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. +- `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. +- `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs + to be absolute. Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will be `NODE_RUNTIME`. -### Prerequisites: +## Prerequisites: WASM builder requires the following prerequisities for building the WASM binary: - rust nightly + `wasm32-unknown-unknown` toolchain -- wasm-gc License: GPL-3.0 diff --git a/core/utils/wasm-builder/src/lib.rs b/core/utils/wasm-builder/src/lib.rs index 5bb0342c665dec533f79c0603b903ef4b4dcbd63..ea3eb6a15bed31a0a04625a41248e10d02376201 100644 --- a/core/utils/wasm-builder/src/lib.rs +++ b/core/utils/wasm-builder/src/lib.rs @@ -25,7 +25,6 @@ //! //! 1. Add a `build.rs` file. //! 2. Add `substrate-wasm-builder-runner` as dependency into `build-dependencies`. -//! 3. Add a feature called `no-std`. //! //! The `build.rs` file needs to contain the following code: //! @@ -42,8 +41,6 @@ //! } //! ``` //! -//! The `no-std` feature will be enabled by WASM builder while compiling your project to WASM. -//! //! As the final step, you need to add the following to your project: //! //! ```ignore @@ -57,15 +54,18 @@ //! //! By using environment variables, you can configure which WASM binaries are built and how: //! -//! - `SKIP_WASM_BUILD` - Skips building any WASM binary. This is useful when only native should be recompiled. -//! - `BUILD_DUMMY_WASM_BINARY` - Builds dummy WASM binaries. These dummy binaries are empty and useful +//! - `SKIP_WASM_BUILD` - Skips building any wasm binary. This is useful when only native should be recompiled. +//! - `BUILD_DUMMY_WASM_BINARY` - Builds dummy wasm binaries. These dummy binaries are empty and useful //! for `cargo check` runs. -//! - `WASM_BUILD_TYPE` - Sets the build type for building WASM binaries. Supported values are `release` or `debug`. +//! - `WASM_BUILD_TYPE` - Sets the build type for building wasm binaries. Supported values are `release` or `debug`. //! By default the build type is equal to the build type used by the main build. -//! - `TRIGGER_WASM_BUILD` - Can be set to trigger a WASM build. On subsequent calls the value of the variable +//! - `TRIGGER_WASM_BUILD` - Can be set to trigger a wasm build. On subsequent calls the value of the variable //! needs to change. As WASM builder instructs `cargo` to watch for file changes //! this environment variable should only be required in certain circumstances. -//! - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the WASM binary. +//! - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary. +//! - `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build. +//! - `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs +//! to be absolute. //! //! Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`. //! Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will @@ -76,7 +76,6 @@ //! WASM builder requires the following prerequisities for building the WASM binary: //! //! - rust nightly + `wasm32-unknown-unknown` toolchain -//! - wasm-gc //! use std::{env, fs, path::PathBuf, process::{Command, Stdio, self}}; @@ -84,19 +83,27 @@ use std::{env, fs, path::PathBuf, process::{Command, Stdio, self}}; mod prerequisites; mod wasm_project; -/// Environment variable that tells us to skip building the WASM binary. +/// Environment variable that tells us to skip building the wasm binary. const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD"; -/// Environment variable to force a certain build type when building the WASM binary. +/// Environment variable to force a certain build type when building the wasm binary. /// Expects "debug" or "release" as value. /// /// By default the WASM binary uses the same build type as the main cargo build. const WASM_BUILD_TYPE_ENV: &str = "WASM_BUILD_TYPE"; -/// Environment variable to extend the `RUSTFLAGS` variable given to the WASM build. +/// Environment variable to extend the `RUSTFLAGS` variable given to the wasm build. const WASM_BUILD_RUSTFLAGS_ENV: &str = "WASM_BUILD_RUSTFLAGS"; -/// Build the currently built project as WASM binary. +/// Environment variable to set the target directory to copy the final wasm binary. +/// +/// The directory needs to be an absolute path. +const WASM_TARGET_DIRECTORY: &str = "WASM_TARGET_DIRECTORY"; + +/// Environment variable to disable color output of the wasm build. +const WASM_BUILD_NO_COLOR: &str = "WASM_BUILD_NO_COLOR"; + +/// Build the currently built project as wasm binary. /// /// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. /// @@ -104,6 +111,22 @@ const WASM_BUILD_RUSTFLAGS_ENV: &str = "WASM_BUILD_RUSTFLAGS"; /// constant `WASM_BINARY`, which contains the built WASM binary. /// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. pub fn build_project(file_name: &str, cargo_manifest: &str) { + build_project_with_default_rustflags(file_name, cargo_manifest, ""); +} + +/// Build the currently built project as wasm binary. +/// +/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable. +/// +/// `file_name` - The name + path of the file being generated. The file contains the +/// constant `WASM_BINARY`, which contains the built WASM binary. +/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built. +/// `default_rustflags` - Default `RUSTFLAGS` that will always be set for the build. +pub fn build_project_with_default_rustflags( + file_name: &str, + cargo_manifest: &str, + default_rustflags: &str, +) { if check_skip_build() { return; } @@ -123,10 +146,13 @@ pub fn build_project(file_name: &str, cargo_manifest: &str) { process::exit(1); } - let (wasm_binary, bloaty) = wasm_project::create_and_compile(&cargo_manifest); + let (wasm_binary, bloaty) = wasm_project::create_and_compile( + &cargo_manifest, + default_rustflags, + ); - create_out_file( - file_name, + write_file_if_changed( + file_name.into(), format!( r#" pub const WASM_BINARY: &[u8] = include_bytes!("{wasm_binary}"); @@ -143,11 +169,11 @@ fn check_skip_build() -> bool { env::var(SKIP_BUILD_ENV).is_ok() } -fn create_out_file(file_name: &str, content: String) { - fs::write( - file_name, - content - ).expect("Creating and writing can not fail; qed"); +/// Write to the given `file` if the `content` is different. +fn write_file_if_changed(file: PathBuf, content: String) { + if fs::read_to_string(&file).ok().as_ref() != Some(&content) { + fs::write(&file, content).expect(&format!("Writing `{}` can not fail!", file.display())); + } } /// Get a cargo command that compiles with nightly @@ -183,9 +209,7 @@ impl CargoCommand { } fn args(&mut self, args: &[&str]) -> &mut Self { - for arg in args { - self.arg(arg); - } + args.into_iter().for_each(|a| { self.arg(a); }); self } @@ -205,12 +229,17 @@ impl CargoCommand { /// Check if the supplied cargo command is a nightly version fn is_nightly(&self) -> bool { - self.command() - .arg("--version") - .output() - .map_err(|_| ()) - .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ())) - .unwrap_or_default() - .contains("-nightly") + // `RUSTC_BOOTSTRAP` tells a stable compiler to behave like a nightly. So, when this env + // variable is set, we can assume that whatever rust compiler we have, it is a nightly compiler. + // For "more" information, see: + // https://github.com/rust-lang/rust/blob/fa0f7d0080d8e7e9eb20aa9cbf8013f96c81287f/src/libsyntax/feature_gate/check.rs#L891 + env::var("RUSTC_BOOTSTRAP").is_ok() || + self.command() + .arg("--version") + .output() + .map_err(|_| ()) + .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ())) + .unwrap_or_default() + .contains("-nightly") } } diff --git a/core/utils/wasm-builder/src/prerequisites.rs b/core/utils/wasm-builder/src/prerequisites.rs index 52ff40887cfd829074458134f37794453ee481a1..3a7f8387dc8b8c09de41b0d8cbdc2ab449765c6d 100644 --- a/core/utils/wasm-builder/src/prerequisites.rs +++ b/core/utils/wasm-builder/src/prerequisites.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::{process::{Command, Stdio}, fs}; +use std::fs; use tempfile::tempdir; @@ -23,32 +23,18 @@ use tempfile::tempdir; /// # Returns /// Returns `None` if everything was found and `Some(ERR_MSG)` if something could not be found. pub fn check() -> Option<&'static str> { - if !check_nightly_installed() { + if !check_nightly_installed(){ return Some("Rust nightly not installed, please install it!") } - if Command::new("wasm-gc") - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status() - .map(|s| !s.success()).unwrap_or(true) - { - return Some("`wasm-gc` not installed, please install it!") - } - - if !check_wasm_toolchain_installed() { - return Some("Rust WASM toolchain not installed, please install it!") - } - - None + check_wasm_toolchain_installed() } fn check_nightly_installed() -> bool { - let command = crate::get_nightly_cargo(); - command.is_nightly() + crate::get_nightly_cargo().is_nightly() } -fn check_wasm_toolchain_installed() -> bool { +fn check_wasm_toolchain_installed() -> Option<&'static str> { let temp = tempdir().expect("Creating temp dir does not fail; qed"); fs::create_dir_all(temp.path().join("src")).expect("Creating src dir does not fail; qed"); @@ -72,13 +58,24 @@ fn check_wasm_toolchain_installed() -> bool { fs::write(&test_file, "pub fn test() {}") .expect("Writing to the test file does not fail; qed"); + let err_msg = "Rust WASM toolchain not installed, please install it!"; let manifest_path = manifest_path.display().to_string(); crate::get_nightly_cargo() .command() .args(&["build", "--target=wasm32-unknown-unknown", "--manifest-path", &manifest_path]) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status() - .map(|s| s.success()) - .unwrap_or(false) + .output() + .map_err(|_| err_msg) + .and_then(|s| + if s.status.success() { + Ok(()) + } else { + match String::from_utf8(s.stderr) { + Ok(ref err) if err.contains("linker `rust-lld` not found") => { + Err("`rust-lld` not found, please install it!") + }, + _ => Err(err_msg) + } + } + ) + .err() } diff --git a/core/utils/wasm-builder/src/wasm_project.rs b/core/utils/wasm-builder/src/wasm_project.rs index 4bc908114cf4612c655692e2fc90d46b26b48d8a..701a50fe1c9c77849b971301b2febde70b4665b9 100644 --- a/core/utils/wasm-builder/src/wasm_project.rs +++ b/core/utils/wasm-builder/src/wasm_project.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use std::{fs, path::{Path, PathBuf}, borrow::ToOwned, process::{Command, self}, env}; +use crate::write_file_if_changed; + +use std::{fs, path::{Path, PathBuf}, borrow::ToOwned, process, env}; use toml::value::Table; @@ -75,7 +77,10 @@ impl Drop for WorkspaceLock { /// /// # Returns /// The path to the compact WASM binary and the bloaty WASM binary. -pub fn create_and_compile(cargo_manifest: &Path) -> (WasmBinary, WasmBinaryBloaty) { +pub fn create_and_compile( + cargo_manifest: &Path, + default_rustflags: &str, +) -> (WasmBinary, WasmBinaryBloaty) { let wasm_workspace_root = get_wasm_workspace_root(); let wasm_workspace = wasm_workspace_root.join("wbuild"); @@ -83,10 +88,16 @@ pub fn create_and_compile(cargo_manifest: &Path) -> (WasmBinary, WasmBinaryBloat let _lock = WorkspaceLock::new(&wasm_workspace_root); let project = create_project(cargo_manifest, &wasm_workspace); - create_wasm_workspace_project(&wasm_workspace); + create_wasm_workspace_project(&wasm_workspace, cargo_manifest); + + build_project(&project, default_rustflags); + let (wasm_binary, bloaty) = compact_wasm_file( + &project, + cargo_manifest, + &wasm_workspace, + ); - build_project(&project); - let (wasm_binary, bloaty) = compact_wasm_file(&project, cargo_manifest, &wasm_workspace); + copy_wasm_to_target_directory(cargo_manifest, &wasm_binary); generate_rerun_if_changed_instructions(cargo_manifest, &project, &wasm_workspace); @@ -122,6 +133,7 @@ fn find_cargo_lock(cargo_manifest: &Path) -> Option { cargo_manifest.display(), build_helper::out_dir().display() ); + None } @@ -160,7 +172,7 @@ fn get_wasm_workspace_root() -> PathBuf { panic!("Could not find target dir in: {}", build_helper::out_dir().display()) } -fn create_wasm_workspace_project(wasm_workspace: &Path) { +fn create_wasm_workspace_project(wasm_workspace: &Path, cargo_manifest: &Path) { let members = WalkDir::new(wasm_workspace) .min_depth(1) .max_depth(1) @@ -169,25 +181,66 @@ fn create_wasm_workspace_project(wasm_workspace: &Path) { .map(|d| d.into_path()) .filter(|p| p.is_dir() && !p.ends_with("target")) .filter_map(|p| p.file_name().map(|f| f.to_owned()).and_then(|s| s.into_string().ok())) - .map(|s| format!("\"{}\", ", s)) - .collect::(); + .collect::>(); + + let crate_metadata = MetadataCommand::new() + .manifest_path(cargo_manifest) + .exec() + .expect("`cargo metadata` can not fail on project `Cargo.toml`; qed"); + let workspace_root_path = crate_metadata.workspace_root; + + let mut workspace_toml: Table = toml::from_str( + &fs::read_to_string( + workspace_root_path.join("Cargo.toml"), + ).expect("Workspace root `Cargo.toml` exists; qed") + ).expect("Workspace root `Cargo.toml` is a valid toml file; qed"); + + let mut wasm_workspace_toml = Table::new(); + + // Add `profile` with release and dev + let mut release_profile = Table::new(); + release_profile.insert("panic".into(), "abort".into()); + release_profile.insert("lto".into(), true.into()); + + let mut dev_profile = Table::new(); + dev_profile.insert("panic".into(), "abort".into()); + + let mut profile = Table::new(); + profile.insert("release".into(), release_profile.into()); + profile.insert("dev".into(), dev_profile.into()); + + wasm_workspace_toml.insert("profile".into(), profile.into()); + + // Add `workspace` with members + let mut workspace = Table::new(); + workspace.insert("members".into(), members.into()); + + wasm_workspace_toml.insert("workspace".into(), workspace.into()); + + // Add patch section from the project root `Cargo.toml` + if let Some(mut patch) = workspace_toml.remove("patch").and_then(|p| p.try_into::().ok()) { + // Iterate over all patches and make the patch path absolute from the workspace root path. + patch.iter_mut() + .filter_map(|p| + p.1.as_table_mut().map(|t| t.iter_mut().filter_map(|t| t.1.as_table_mut())) + ) + .flatten() + .for_each(|p| + p.iter_mut() + .filter(|(k, _)| k == &"path") + .for_each(|(_, v)| { + if let Some(path) = v.as_str() { + *v = workspace_root_path.join(path).display().to_string().into(); + } + }) + ); + + wasm_workspace_toml.insert("patch".into(), patch.into()); + } fs::write( wasm_workspace.join("Cargo.toml"), - format!( - r#" - [profile.release] - panic = "abort" - lto = true - - [profile.dev] - panic = "abort" - - [workspace] - members = [ {members} ] - "#, - members = members, - ) + toml::to_string_pretty(&wasm_workspace_toml).expect("Wasm workspace toml is valid; qed"), ).expect("WASM workspace `Cargo.toml` writing can not fail; qed"); } @@ -203,7 +256,7 @@ fn create_project(cargo_manifest: &Path, wasm_workspace: &Path) -> PathBuf { fs::create_dir_all(project_folder.join("src")).expect("Wasm project dir create can not fail; qed"); - fs::write( + write_file_if_changed( project_folder.join("Cargo.toml"), format!( r#" @@ -217,18 +270,18 @@ fn create_project(cargo_manifest: &Path, wasm_workspace: &Path) -> PathBuf { crate-type = ["cdylib"] [dependencies] - wasm_project = {{ package = "{crate_name}", path = "{crate_path}", default-features = false, features = [ "no_std" ] }} + wasm_project = {{ package = "{crate_name}", path = "{crate_path}", default-features = false }} "#, crate_name = crate_name, crate_path = crate_path.display(), wasm_binary = wasm_binary, ) - ).expect("Project `Cargo.toml` writing can not fail; qed"); + ); - fs::write( + write_file_if_changed( project_folder.join("src/lib.rs"), - "#![no_std] pub use wasm_project::*;", - ).expect("Project `lib.rs` writing can not fail; qed"); + "#![no_std] pub use wasm_project::*;".into(), + ); if let Some(crate_lock_file) = find_cargo_lock(cargo_manifest) { // Use the `Cargo.lock` of the main project. @@ -257,21 +310,26 @@ fn is_release_build() -> bool { } /// Build the project to create the WASM binary. -fn build_project(project: &Path) { +fn build_project(project: &Path, default_rustflags: &str) { let manifest_path = project.join("Cargo.toml"); let mut build_cmd = crate::get_nightly_cargo().command(); let rustflags = format!( - "-C link-arg=--export-table {}", + "-C link-arg=--export-table {} {}", + default_rustflags, env::var(crate::WASM_BUILD_RUSTFLAGS_ENV).unwrap_or_default(), ); - build_cmd.args(&["build", "--target=wasm32-unknown-unknown"]) + build_cmd.args(&["rustc", "--target=wasm32-unknown-unknown"]) .arg(format!("--manifest-path={}", manifest_path.display())) .env("RUSTFLAGS", rustflags) // We don't want to call ourselves recursively .env(crate::SKIP_BUILD_ENV, ""); + if env::var(crate::WASM_BUILD_NO_COLOR).is_err() { + build_cmd.arg("--color=always"); + } + if is_release_build() { build_cmd.arg("--release"); }; @@ -298,15 +356,8 @@ fn compact_wasm_file( .join(format!("{}.wasm", wasm_binary)); let wasm_compact_file = project.join(format!("{}.compact.wasm", wasm_binary)); - let res = Command::new("wasm-gc") - .arg(&wasm_file) - .arg(&wasm_compact_file) - .status() - .map(|s| s.success()); - - if !res.unwrap_or(false) { - panic!("Failed to compact generated WASM binary."); - } + wasm_gc::garbage_collect_file(&wasm_file, &wasm_compact_file) + .expect("Failed to compact generated WASM binary."); (WasmBinary(wasm_compact_file), WasmBinaryBloaty(wasm_file)) } @@ -349,4 +400,29 @@ fn generate_rerun_if_changed_instructions( println!("cargo:rerun-if-env-changed={}", crate::SKIP_BUILD_ENV); println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_TYPE_ENV); println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_RUSTFLAGS_ENV); + println!("cargo:rerun-if-env-changed={}", crate::WASM_TARGET_DIRECTORY); +} + +/// Copy the WASM binary to the target directory set in `WASM_TARGET_DIRECTORY` environment variable. +/// If the variable is not set, this is a no-op. +fn copy_wasm_to_target_directory(cargo_manifest: &Path, wasm_binary: &WasmBinary) { + let target_dir = match env::var(crate::WASM_TARGET_DIRECTORY) { + Ok(path) => PathBuf::from(path), + Err(_) => return, + }; + + if !target_dir.is_absolute() { + panic!( + "Environment variable `{}` with `{}` is not an absolute path!", + crate::WASM_TARGET_DIRECTORY, + target_dir.display(), + ); + } + + fs::create_dir_all(&target_dir).expect("Creates `WASM_TARGET_DIRECTORY`."); + + fs::copy( + wasm_binary.wasm_binary_path(), + target_dir.join(format!("{}.wasm", get_wasm_binary_name(cargo_manifest))), + ).expect("Copies WASM binary to `WASM_TARGET_DIRECTORY`."); } diff --git a/core/wasm-interface/Cargo.toml b/core/wasm-interface/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b8169031d0bb6ecb6612536ea939167df1700cfe --- /dev/null +++ b/core/wasm-interface/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "substrate-wasm-interface" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +wasmi = "0.5.1" diff --git a/core/wasm-interface/src/lib.rs b/core/wasm-interface/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..83689ddc819a8b5c18652cf102af8b85d69ab309 --- /dev/null +++ b/core/wasm-interface/src/lib.rs @@ -0,0 +1,336 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Types and traits for interfacing between the host and the wasm runtime. + +use std::{borrow::Cow, marker::PhantomData, mem, iter::Iterator, result}; + +mod wasmi_impl; + +/// Result type used by traits in this crate. +pub type Result = result::Result; + +/// Value types supported by Substrate on the boundary between host/Wasm. +#[derive(Copy, Clone, PartialEq, Debug, Eq)] +pub enum ValueType { + /// An `i32` value type. + I32, + /// An `i64` value type. + I64, + /// An `f32` value type. + F32, + /// An `f64` value type. + F64, +} + +/// Values supported by Substrate on the boundary between host/Wasm. +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum Value { + /// An `i32` value. + I32(i32), + /// An `i64` value. + I64(i64), + /// An nan-preserving `f32` value. + F32(u32), + /// An nan-preserving `f64` value. + F64(u64), +} + +impl Value { + /// Returns the type of this value. + pub fn value_type(&self) -> ValueType { + match self { + Value::I32(_) => ValueType::I32, + Value::I64(_) => ValueType::I64, + Value::F32(_) => ValueType::F32, + Value::F64(_) => ValueType::F64, + } + } +} + +/// Provides `Sealed` trait to prevent implementing trait `PointerType` outside of this crate. +mod private { + pub trait Sealed {} + + impl Sealed for u8 {} + impl Sealed for u16 {} + impl Sealed for u32 {} + impl Sealed for u64 {} +} + +/// Something that can be wrapped in a wasm `Pointer`. +/// +/// This trait is sealed. +pub trait PointerType: Sized { + /// The size of the type in wasm. + const SIZE: u32 = mem::size_of::() as u32; +} + +impl PointerType for u8 {} +impl PointerType for u16 {} +impl PointerType for u32 {} +impl PointerType for u64 {} + +/// Type to represent a pointer in wasm at the host. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Pointer { + ptr: u32, + _marker: PhantomData, +} + +impl Pointer { + /// Create a new instance of `Self`. + pub fn new(ptr: u32) -> Self { + Self { + ptr, + _marker: Default::default(), + } + } + + /// Calculate the offset from this pointer. + /// + /// `offset` is in units of `T`. So, `3` means `3 * mem::size_of::()` as offset to the pointer. + /// + /// Returns an `Option` to respect that the pointer could probably overflow. + pub fn offset(self, offset: u32) -> Option { + offset.checked_mul(T::SIZE).and_then(|o| self.ptr.checked_add(o)).map(|ptr| { + Self { + ptr, + _marker: Default::default(), + } + }) + } + + /// Create a null pointer. + pub fn null() -> Self { + Self::new(0) + } + + /// Cast this pointer of type `T` to a pointer of type `R`. + pub fn cast(self) -> Pointer { + Pointer::new(self.ptr) + } +} + +impl From> for u32 { + fn from(ptr: Pointer) -> Self { + ptr.ptr + } +} + +impl From> for usize { + fn from(ptr: Pointer) -> Self { + ptr.ptr as _ + } +} + +impl IntoValue for Pointer { + const VALUE_TYPE: ValueType = ValueType::I32; + fn into_value(self) -> Value { Value::I32(self.ptr as _) } +} + +impl TryFromValue for Pointer { + fn try_from_value(val: Value) -> Option { + match val { + Value::I32(val) => Some(Self::new(val as _)), + _ => None, + } + } +} + +/// The word size used in wasm. Normally known as `usize` in Rust. +pub type WordSize = u32; + +/// The Signature of a function +#[derive(Eq, PartialEq, Debug, Clone)] +pub struct Signature { + /// The arguments of a function. + pub args: Cow<'static, [ValueType]>, + /// The optional return value of a function. + pub return_value: Option, +} + +impl Signature { + /// Create a new instance of `Signature`. + pub fn new>>(args: T, return_value: Option) -> Self { + Self { + args: args.into(), + return_value, + } + } + + /// Create a new instance of `Signature` with the given `args` and without any return value. + pub fn new_with_args>>(args: T) -> Self { + Self { + args: args.into(), + return_value: None, + } + } + +} + +/// Something that provides a function implementation on the host for a wasm function. +pub trait Function { + /// Returns the name of this function. + fn name(&self) -> &str; + /// Returns the signature of this function. + fn signature(&self) -> Signature; + /// Execute this function with the given arguments. + fn execute( + &self, + context: &mut dyn FunctionContext, + args: &mut dyn Iterator, + ) -> Result>; +} + +/// Context used by `Function` to interact with the allocator and the memory of the wasm instance. +pub trait FunctionContext { + /// Read memory from `address` into a vector. + fn read_memory(&self, address: Pointer, size: WordSize) -> Result> { + let mut vec = Vec::with_capacity(size as usize); + vec.resize(size as usize, 0); + self.read_memory_into(address, &mut vec)?; + Ok(vec) + } + /// Read memory into the given `dest` buffer from `address`. + fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> Result<()>; + /// Write the given data at `address` into the memory. + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> Result<()>; + /// Allocate a memory instance of `size` bytes. + fn allocate_memory(&mut self, size: WordSize) -> Result>; + /// Deallocate a given memory instance. + fn deallocate_memory(&mut self, ptr: Pointer) -> Result<()>; + /// Provides access to the sandbox. + fn sandbox(&mut self) -> &mut dyn Sandbox; +} + +/// Sandbox memory identifier. +pub type MemoryId = u32; + +/// Something that provides access to the sandbox. +pub trait Sandbox { + /// Get sandbox memory from the `memory_id` instance at `offset` into the given buffer. + fn memory_get( + &mut self, + memory_id: MemoryId, + offset: WordSize, + buf_ptr: Pointer, + buf_len: WordSize, + ) -> Result; + /// Set sandbox memory from the given value. + fn memory_set( + &mut self, + memory_id: MemoryId, + offset: WordSize, + val_ptr: Pointer, + val_len: WordSize, + ) -> Result; + /// Delete a memory instance. + fn memory_teardown(&mut self, memory_id: MemoryId) -> Result<()>; + /// Create a new memory instance with the given `initial` size and the `maximum` size. + /// The size is given in wasm pages. + fn memory_new(&mut self, initial: u32, maximum: u32) -> Result; + /// Invoke an exported function by a name. + fn invoke( + &mut self, + instance_id: u32, + export_name: &str, + args: &[u8], + return_val: Pointer, + return_val_len: WordSize, + state: u32, + ) -> Result; + /// Delete a sandbox instance. + fn instance_teardown(&mut self, instance_id: u32) -> Result<()>; + /// Create a new sandbox instance. + fn instance_new( + &mut self, + dispatch_thunk_id: u32, + wasm: &[u8], + raw_env_def: &[u8], + state: u32, + ) -> Result; +} + +/// Something that provides implementations for host functions. +pub trait HostFunctions { + /// Returns all host functions. + fn functions() -> &'static [&'static dyn Function]; +} + +/// Something that can be converted into a wasm compatible `Value`. +pub trait IntoValue { + /// The type of the value in wasm. + const VALUE_TYPE: ValueType; + + /// Convert `self` into a wasm `Value`. + fn into_value(self) -> Value; +} + +/// Something that can may be created from a wasm `Value`. +pub trait TryFromValue: Sized { + /// Try to convert the given `Value` into `Self`. + fn try_from_value(val: Value) -> Option; +} + +macro_rules! impl_into_and_from_value { + ( + $( + $type:ty, $( < $gen:ident >, )? $value_variant:ident, + )* + ) => { + $( + impl $( <$gen> )? IntoValue for $type { + const VALUE_TYPE: ValueType = ValueType::$value_variant; + fn into_value(self) -> Value { Value::$value_variant(self as _) } + } + + impl $( <$gen> )? TryFromValue for $type { + fn try_from_value(val: Value) -> Option { + match val { + Value::$value_variant(val) => Some(val as _), + _ => None, + } + } + } + )* + } +} + +impl_into_and_from_value! { + u32, I32, + i32, I32, + u64, I64, + i64, I64, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn pointer_offset_works() { + let ptr = Pointer::::null(); + + assert_eq!(ptr.offset(10).unwrap(), Pointer::new(40)); + assert_eq!(ptr.offset(32).unwrap(), Pointer::new(128)); + + let ptr = Pointer::::null(); + + assert_eq!(ptr.offset(10).unwrap(), Pointer::new(80)); + assert_eq!(ptr.offset(32).unwrap(), Pointer::new(256)); + } +} diff --git a/core/wasm-interface/src/wasmi_impl.rs b/core/wasm-interface/src/wasmi_impl.rs new file mode 100644 index 0000000000000000000000000000000000000000..be9b724d29b74bab16905ab9b905d88cff307c54 --- /dev/null +++ b/core/wasm-interface/src/wasmi_impl.rs @@ -0,0 +1,79 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of conversions between Substrate and wasmi types. + +use crate::{Value, ValueType, Signature}; + +impl From for wasmi::RuntimeValue { + fn from(value: Value) -> Self { + match value { + Value::I32(val) => Self::I32(val), + Value::I64(val) => Self::I64(val), + Value::F32(val) => Self::F32(val.into()), + Value::F64(val) => Self::F64(val.into()), + } + } +} + +impl From for Value { + fn from(value: wasmi::RuntimeValue) -> Self { + match value { + wasmi::RuntimeValue::I32(val) => Self::I32(val), + wasmi::RuntimeValue::I64(val) => Self::I64(val), + wasmi::RuntimeValue::F32(val) => Self::F32(val.into()), + wasmi::RuntimeValue::F64(val) => Self::F64(val.into()), + } + } +} + +impl From for wasmi::ValueType { + fn from(value: ValueType) -> Self { + match value { + ValueType::I32 => Self::I32, + ValueType::I64 => Self::I64, + ValueType::F32 => Self::F32, + ValueType::F64 => Self::F64, + } + } +} + +impl From for ValueType { + fn from(value: wasmi::ValueType) -> Self { + match value { + wasmi::ValueType::I32 => Self::I32, + wasmi::ValueType::I64 => Self::I64, + wasmi::ValueType::F32 => Self::F32, + wasmi::ValueType::F64 => Self::F64, + } + } +} + +impl From for wasmi::Signature { + fn from(sig: Signature) -> Self { + let args = sig.args.iter().map(|a| (*a).into()).collect::>(); + wasmi::Signature::new(args, sig.return_value.map(Into::into)) + } +} + +impl From<&wasmi::Signature> for Signature { + fn from(sig: &wasmi::Signature) -> Self { + Signature::new( + sig.params().into_iter().copied().map(Into::into).collect::>(), + sig.return_type().map(Into::into), + ) + } +} diff --git a/node-template/Cargo.toml b/node-template/Cargo.toml index 4112452b2722f7741a8f3e71d941a7d171fb3596..e68cbc189379bba6fca5080cd925dbf7bdf3bc4d 100644 --- a/node-template/Cargo.toml +++ b/node-template/Cargo.toml @@ -10,15 +10,15 @@ name = "node-template" path = "src/main.rs" [dependencies] -derive_more = "0.14.0" -futures = "0.1" -ctrlc = { version = "3.0", features = ["termination"] } -log = "0.4" -tokio = "0.1" -exit-future = "0.1" +derive_more = "0.15.0" +futures = "0.1.29" +ctrlc = { version = "3.1.3", features = ["termination"] } +log = "0.4.8" +tokio = "0.1.22" +exit-future = "0.1.4" parking_lot = "0.9.0" codec = { package = "parity-scale-codec", version = "1.0.0" } -trie-root = "0.15.0" +trie-root = "0.15.2" sr-io = { path = "../core/sr-io" } substrate-cli = { path = "../core/cli" } primitives = { package = "substrate-primitives", path = "../core/primitives" } @@ -27,12 +27,15 @@ substrate-service = { path = "../core/service" } inherents = { package = "substrate-inherents", path = "../core/inherents" } transaction-pool = { package = "substrate-transaction-pool", path = "../core/transaction-pool" } network = { package = "substrate-network", path = "../core/network" } -consensus = { package = "substrate-consensus-aura", path = "../core/consensus/aura" } +aura = { package = "substrate-consensus-aura", path = "../core/consensus/aura" } aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../core/consensus/aura/primitives" } +grandpa = { package = "substrate-finality-grandpa", path = "../core/finality-grandpa" } grandpa-primitives = { package = "substrate-finality-grandpa-primitives", path = "../core/finality-grandpa/primitives" } substrate-client = { path = "../core/client" } basic-authorship = { package = "substrate-basic-authorship", path = "../core/basic-authorship" } -node-template-runtime = { path = "runtime" } +runtime = { package = "node-template-runtime", path = "runtime" } +sr-primitives = { path = "../core/sr-primitives" } [build-dependencies] -vergen = "3" +vergen = "3.0.4" +build-script-utils = { package = "substrate-build-script-utils", path = "../core/utils/build-script-utils" } diff --git a/node-template/README.md b/node-template/README.md index 497ed84a52bcd33920af114154ed34e17d5cde3d..c411dbeef5bcccf9e05d64ddee2405cb5237c678 100644 --- a/node-template/README.md +++ b/node-template/README.md @@ -1,8 +1,8 @@ -# Template Node +# Substrate Node Template A new SRML-based Substrate node, ready for hacking. -# Building +## Build Install Rust: @@ -10,29 +10,43 @@ Install Rust: curl https://sh.rustup.rs -sSf | sh ``` -Install required tools: +Initialize your Wasm Build environment: ```bash ./scripts/init.sh ``` -Build all native code: +Build Wasm and native code: ```bash -cargo build +cargo build --release ``` -# Run +## Run -You can start a development chain with: +### Single node development chain + +Purge any existing developer chain state: + +```bash +./target/release/node-template purge-chain --dev +``` + +Start a development chain with: ```bash -cargo run -- --dev +./target/release/node-template --dev ``` Detailed logs may be shown by running the node with the following environment variables set: `RUST_LOG=debug RUST_BACKTRACE=1 cargo run -- --dev`. -If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain that have been endowed with testnet units. Give each node a name and expose them so they are listed on the Polkadot [telemetry site](https://telemetry.polkadot.io/#/Local%20Testnet). You'll need two terminal windows open. +### Multi-node local testnet + +If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two validator nodes for Alice and Bob, who are the initial authorities of the genesis chain that have been endowed with testnet units. + +Optionally, give each node a name and expose them so they are listed on the Polkadot [telemetry site](https://telemetry.polkadot.io/#/Local%20Testnet). + +You'll need two terminal windows open. We'll start Alice's substrate node first on default TCP port 30333 with her chain database stored locally at `/tmp/alice`. The bootnode ID of her node is `QmRpheLN4JWdAnY7HGJfWFNbfkQCb6tFf4vvA6hgjMZKrR`, which is generated from the `--node-key` value that we specify below: diff --git a/node-template/build.rs b/node-template/build.rs index bab46f579d06830f81a91607841bdd64e03e1eb8..a9550783c4304db7a895053232ff740fd2e72c73 100644 --- a/node-template/build.rs +++ b/node-template/build.rs @@ -7,18 +7,5 @@ const ERROR_MSG: &str = "Failed to generate metadata files"; fn main() { generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); - let mut manifest_dir = PathBuf::from( - env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo.") - ); - - while manifest_dir.parent().is_some() { - if manifest_dir.join(".git/HEAD").exists() { - println!("cargo:rerun-if-changed={}", manifest_dir.join(".git/HEAD").display()); - return - } - - manifest_dir.pop(); - } - - println!("cargo:warning=Could not find `.git/HEAD` from manifest dir!"); + build_script_utils::rerun_if_git_head_changed(); } diff --git a/node-template/runtime/Cargo.toml b/node-template/runtime/Cargo.toml index 2f41513048dc056f10c2ff13f8f273c44766ba54..ff2e3eb2b1676ad3642c854360c929245a1a999c 100644 --- a/node-template/runtime/Cargo.toml +++ b/node-template/runtime/Cargo.toml @@ -5,9 +5,8 @@ authors = ["Anonymous"] edition = "2018" [dependencies] - -serde = { version = "1.0", optional = true, features = ["derive"] } -safe-mix = { version = "1.0", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default_features = false } runtime-io = { package = "sr-io", path = "../../core/sr-io", default_features = false } @@ -17,18 +16,21 @@ primitives = { package = "substrate-primitives", path = "../../core/primitives", substrate-session = { path = "../../core/session", default-features = false } balances = { package = "srml-balances", path = "../../srml/balances", default_features = false } aura = { package = "srml-aura", path = "../../srml/aura", default_features = false } +aura-primitives = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default_features = false } +grandpa = { package = "srml-grandpa", path = "../../srml/grandpa", default_features = false } executive = { package = "srml-executive", path = "../../srml/executive", default_features = false } indices = { package = "srml-indices", path = "../../srml/indices", default_features = false } +randomness-collective-flip = { package = "srml-randomness-collective-flip", path = "../../srml/randomness-collective-flip", default_features = false } system = { package = "srml-system", path = "../../srml/system", default_features = false } timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default_features = false } sudo = { package = "srml-sudo", path = "../../srml/sudo", default_features = false } +transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment", default_features = false } sr-primitives = { path = "../../core/sr-primitives", default_features = false } client = { package = "substrate-client", path = "../../core/client", default_features = false } -consensus-aura = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default_features = false } offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.2" } +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4" } [features] default = ["std"] @@ -39,19 +41,21 @@ std = [ "runtime-io/std", "support/std", "balances/std", - "executive/std", "aura/std", + "aura-primitives/std", + "grandpa/std", + "executive/std", "indices/std", "primitives/std", "sr-primitives/std", + "randomness-collective-flip/std", "system/std", "timestamp/std", "sudo/std", + "transaction-payment/std", "version/std", "serde", "safe-mix/std", - "consensus-aura/std", "offchain-primitives/std", "substrate-session/std", ] -no_std = [] diff --git a/node-template/runtime/build.rs b/node-template/runtime/build.rs index 7000c602e852514254baef95a37676238cd59626..c5e798c6efa90a4fdb10e8ffc005afad7066d897 100644 --- a/node-template/runtime/build.rs +++ b/node-template/runtime/build.rs @@ -19,7 +19,7 @@ use wasm_builder_runner::{build_current_project_with_rustflags, WasmBuilderSourc fn main() { build_current_project_with_rustflags( "wasm_binary.rs", - WasmBuilderSource::Crates("1.0.4"), + WasmBuilderSource::Crates("1.0.8"), // This instructs LLD to export __heap_base as a global variable, which is used by the // external memory allocator. "-Clink-arg=--export=__heap_base", diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 16235db1183c3b6c6b7e27992988d1651219bc3e..c0cd2cf33770cebf96060cb6f5afc035164a2b54 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -9,17 +9,22 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); use rstd::prelude::*; -use primitives::{sr25519, OpaqueMetadata, crypto::key_types}; +use primitives::OpaqueMetadata; use sr_primitives::{ ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str, - impl_opaque_keys, + impl_opaque_keys, MultiSignature +}; +use sr_primitives::traits::{ + NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify, ConvertInto, IdentifyAccount }; -use sr_primitives::traits::{NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify, ConvertInto}; use sr_primitives::weights::Weight; use client::{ block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api}, - runtime_api, impl_runtime_apis + runtime_api as client_api, impl_runtime_apis }; +use aura_primitives::sr25519::AuthorityId as AuraId; +use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight}; +use grandpa::fg_primitives; use version::RuntimeVersion; #[cfg(feature = "std")] use version::NativeVersion; @@ -30,31 +35,33 @@ pub use sr_primitives::BuildStorage; pub use timestamp::Call as TimestampCall; pub use balances::Call as BalancesCall; pub use sr_primitives::{Permill, Perbill}; -pub use support::{StorageValue, construct_runtime, parameter_types}; +pub use support::{StorageValue, construct_runtime, parameter_types, traits::Randomness}; -/// Alias to the signature scheme used for Aura authority signatures. -pub type AuraSignature = consensus_aura::sr25519::AuthoritySignature; +/// An index to a block. +pub type BlockNumber = u32; -/// The Ed25519 pub key of an session that belongs to an Aura authority of the chain. -pub type AuraId = consensus_aura::sr25519::AuthorityId; +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; -/// Alias to pubkey that identifies an account on the chain. -pub type AccountId = ::Signer; +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; -/// The type used by authorities to prove their ID. -pub type AccountSignature = sr25519::Signature; +/// The type for looking up accounts. We don't expect more than 4 billion of them, but you +/// never know... +pub type AccountIndex = u32; -/// A hash of some data used by the chain. -pub type Hash = primitives::H256; +/// Balance of an account. +pub type Balance = u128; -/// Index of a block number in the chain. -pub type BlockNumber = u32; +/// Index of a transaction in the chain. +pub type Index = u32; -/// Index of an account's extrinsic in the chain. -pub type Nonce = u32; +/// A hash of some data used by the chain. +pub type Hash = primitives::H256; -/// Balance type for the node. -pub type Balance = u128; +/// Digest item type. +pub type DigestItem = generic::DigestItem; /// Used for the module template in `./template.rs` mod template; @@ -77,8 +84,8 @@ pub mod opaque { impl_opaque_keys! { pub struct SessionKeys { - #[id(key_types::AURA)] - pub aura: AuraId, + pub aura: Aura, + pub grandpa: Grandpa, } } } @@ -87,12 +94,21 @@ pub mod opaque { pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node-template"), impl_name: create_runtime_str!("node-template"), - authoring_version: 3, - spec_version: 4, - impl_version: 4, + authoring_version: 1, + spec_version: 1, + impl_version: 1, apis: RUNTIME_API_VERSIONS, }; +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// These time units are defined in number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + /// The version infromation used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { @@ -107,6 +123,7 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 1_000_000; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; } impl system::Trait for Runtime { @@ -117,7 +134,7 @@ impl system::Trait for Runtime { /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = Indices; /// The index type for storing how many extrinsics an account has signed. - type Index = Nonce; + type Index = Index; /// The index type for blocks. type BlockNumber = BlockNumber; /// The type for hashing blocks and tries. @@ -128,29 +145,32 @@ impl system::Trait for Runtime { type Header = generic::Header; /// The ubiquitous event type. type Event = Event; - /// Update weight (to fee) multiplier per-block. - type WeightMultiplierUpdate = (); /// The ubiquitous origin type. type Origin = Origin; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; - /// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok. + /// Maximum weight of each block. type MaximumBlockWeight = MaximumBlockWeight; /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. type MaximumBlockLength = MaximumBlockLength; /// Portion of the block weight that is available to all normal transactions. type AvailableBlockRatio = AvailableBlockRatio; + /// Version of the runtime. + type Version = Version; } impl aura::Trait for Runtime { - type HandleReport = (); type AuthorityId = AuraId; } +impl grandpa::Trait for Runtime { + type Event = Event; +} + impl indices::Trait for Runtime { /// The type for recording indexing into the account enumeration. If this ever overflows, there /// will be problems! - type AccountIndex = u32; + type AccountIndex = AccountIndex; /// Use the standard means of resolving an index hint from an id. type ResolveHint = indices::SimpleResolveHint; /// Determine whether an account is dead. @@ -160,7 +180,7 @@ impl indices::Trait for Runtime { } parameter_types! { - pub const MinimumPeriod: u64 = 5000; + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; } impl timestamp::Trait for Runtime { @@ -174,8 +194,6 @@ parameter_types! { pub const ExistentialDeposit: u128 = 500; pub const TransferFee: u128 = 0; pub const CreationFee: u128 = 0; - pub const TransactionBaseFee: u128 = 0; - pub const TransactionByteFee: u128 = 1; } impl balances::Trait for Runtime { @@ -187,20 +205,28 @@ impl balances::Trait for Runtime { type OnNewAccount = Indices; /// The ubiquitous event type. type Event = Event; - - type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; +} + +parameter_types! { + pub const TransactionBaseFee: Balance = 0; + pub const TransactionByteFee: Balance = 1; +} + +impl transaction_payment::Trait for Runtime { + type Currency = balances::Module; + type OnTransactionPayment = (); type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; type WeightToFee = ConvertInto; + type FeeMultiplierUpdate = (); } impl sudo::Trait for Runtime { - /// The ubiquitous event type. type Event = Event; type Proposal = Call; } @@ -219,36 +245,45 @@ construct_runtime!( System: system::{Module, Call, Storage, Config, Event}, Timestamp: timestamp::{Module, Call, Storage, Inherent}, Aura: aura::{Module, Config, Inherent(Timestamp)}, + Grandpa: grandpa::{Module, Call, Storage, Config, Event}, Indices: indices::{default, Config}, - Balances: balances, + Balances: balances::{default, Error}, + TransactionPayment: transaction_payment::{Module, Storage}, Sudo: sudo, // Used for the module template in `./template.rs` TemplateModule: template::{Module, Call, Storage, Event}, + RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage}, } ); -/// The type used as a helper for interpreting the sender of transactions. -type Context = system::ChainContext; /// The address format for describing accounts. -type Address = ::Source; +pub type Address = ::Source; /// Block header type as expected by this runtime. pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. -pub type SignedExtra = (system::CheckNonce, system::CheckWeight, balances::TakeFees); +pub type SignedExtra = ( + system::CheckVersion, + system::CheckGenesis, + system::CheckEra, + system::CheckNonce, + system::CheckWeight, + transaction_payment::ChargeTransactionPayment +); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive; +pub type Executive = executive::Executive, Runtime, AllModules>; -// Implement our runtime API endpoints. This is just a bunch of proxying. impl_runtime_apis! { - impl runtime_api::Core for Runtime { + impl client_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION } @@ -262,7 +297,7 @@ impl_runtime_apis! { } } - impl runtime_api::Metadata for Runtime { + impl client_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { Runtime::metadata().into() } @@ -286,35 +321,42 @@ impl_runtime_apis! { } fn random_seed() -> ::Hash { - System::random_seed() + RandomnessCollectiveFlip::random_seed() } } - impl runtime_api::TaggedTransactionQueue for Runtime { + impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { Executive::validate_transaction(tx) } } - impl consensus_aura::AuraApi for Runtime { + impl offchain_primitives::OffchainWorkerApi for Runtime { + fn offchain_worker(number: NumberFor) { + Executive::offchain_worker(number) + } + } + + impl aura_primitives::AuraApi for Runtime { fn slot_duration() -> u64 { Aura::slot_duration() } + fn authorities() -> Vec { Aura::authorities() } } - impl offchain_primitives::OffchainWorkerApi for Runtime { - fn offchain_worker(n: NumberFor) { - Executive::offchain_worker(n) - } - } - impl substrate_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string")); opaque::SessionKeys::generate(seed) } } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> { + Grandpa::grandpa_authorities() + } + } } diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index aa399a8edde9cac4ea996cad3816bb419d9c5bf3..db7bd24b0e419268610612ae03275164cec7a9ff 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -8,7 +8,7 @@ /// For more guidance on Substrate modules, see the example module /// https://github.com/paritytech/substrate/blob/master/srml/example/src/lib.rs -use support::{decl_module, decl_storage, decl_event, StorageValue, dispatch::Result}; +use support::{decl_module, decl_storage, decl_event, dispatch::Result}; use system::ensure_signed; /// The module's configuration trait. @@ -24,8 +24,8 @@ decl_storage! { trait Store for Module as TemplateModule { // Just a dummy storage item. // Here we are declaring a StorageValue, `Something` as a Option - // `get(something)` is the default getter which returns either the stored `u32` or `None` if nothing stored - Something get(something): Option; + // `get(fn something)` is the default getter which returns either the stored `u32` or `None` if nothing stored + Something get(fn something): Option; } } @@ -35,7 +35,7 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { // Initializing events // this is needed only if you are using events in your module - fn deposit_event() = default; + fn deposit_event() = default; // Just a dummy entry point. // function that can be called by the external world as an extrinsics call @@ -69,12 +69,11 @@ decl_event!( mod tests { use super::*; - use runtime_io::with_externalities; - use primitives::{H256, Blake2Hasher}; + use primitives::H256; use support::{impl_outer_origin, assert_ok, parameter_types}; - use sr_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - use sr_primitives::weights::Weight; - use sr_primitives::Perbill; + use sr_primitives::{ + traits::{BlakeTwo256, IdentityLookup}, testing::Header, weights::Weight, Perbill, + }; impl_outer_origin! { pub enum Origin for Test {} @@ -101,12 +100,12 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } impl Trait for Test { type Event = (); @@ -115,13 +114,13 @@ mod tests { // This function basically just builds a genesis storage key/value store according to // our desired mockup. - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { system::GenesisConfig::default().build_storage::().unwrap().into() } #[test] fn it_works_for_default_value() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { // Just a dummy test for the dummy funtion `do_something` // calling the `do_something` function with a value 42 assert_ok!(TemplateModule::do_something(Origin::signed(1), 42)); diff --git a/node-template/scripts/init.sh b/node-template/scripts/init.sh index cf5ecf97926fea7a5e8fd2a91df96853f90e8ee7..1405a41ef333e6af863080d83f854d3edb5fb4fa 100755 --- a/node-template/scripts/init.sh +++ b/node-template/scripts/init.sh @@ -10,7 +10,3 @@ if [ -z $CI_PROJECT_NAME ] ; then fi rustup target add wasm32-unknown-unknown --toolchain nightly - -# Install wasm-gc. It's useful for stripping slimming down wasm binaries. -command -v wasm-gc || \ - cargo +nightly install --git https://github.com/alexcrichton/wasm-gc --force diff --git a/node-template/src/chain_spec.rs b/node-template/src/chain_spec.rs index 65caab70dbe5ff5c6ad1c25771dfee42d030a250..8d43e67304c795b510777e3de154d75513f16eb1 100644 --- a/node-template/src/chain_spec.rs +++ b/node-template/src/chain_spec.rs @@ -1,10 +1,12 @@ -use primitives::{sr25519, Pair}; -use node_template_runtime::{ - AccountId, GenesisConfig, AuraConfig, BalancesConfig, - SudoConfig, IndicesConfig, SystemConfig, WASM_BINARY, AuraId +use primitives::{Pair, Public, sr25519}; +use runtime::{ + AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, + SudoConfig, IndicesConfig, SystemConfig, WASM_BINARY, Signature }; -use aura_primitives::sr25519::AuthorityPair as AuraPair; +use aura_primitives::sr25519::{AuthorityId as AuraId}; +use grandpa_primitives::{AuthorityId as GrandpaId}; use substrate_service; +use sr_primitives::traits::{Verify, IdentifyAccount}; // Note this is the URL for the telemetry server //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -23,16 +25,28 @@ pub enum Alternative { LocalTestnet, } -fn authority_key(s: &str) -> AuraId { - AuraPair::from_string(&format!("//{}", s), None) +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) .expect("static values are valid; qed") .public() } -fn account_key(s: &str) -> AccountId { - sr25519::Pair::from_string(&format!("//{}", s), None) - .expect("static values are valid; qed") - .public() +type AccountPublic = ::Signer; + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId where + AccountPublic: From<::Public> +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Helper function to generate an authority key for Aura +pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { + ( + get_from_seed::(s), + get_from_seed::(s), + ) } impl Alternative { @@ -43,12 +57,16 @@ impl Alternative { "Development", "dev", || testnet_genesis(vec![ - authority_key("Alice") - ], vec![ - account_key("Alice") + get_authority_keys_from_seed("Alice"), + ], + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), ], - account_key("Alice") - ), + true), vec![], None, None, @@ -59,18 +77,25 @@ impl Alternative { "Local Testnet", "local_testnet", || testnet_genesis(vec![ - authority_key("Alice"), - authority_key("Bob"), - ], vec![ - account_key("Alice"), - account_key("Bob"), - account_key("Charlie"), - account_key("Dave"), - account_key("Eve"), - account_key("Ferdie"), + get_authority_keys_from_seed("Alice"), + get_authority_keys_from_seed("Bob"), ], - account_key("Alice"), - ), + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + true), vec![], None, None, @@ -89,15 +114,15 @@ impl Alternative { } } -fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec, root_key: AccountId) -> GenesisConfig { +fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, + root_key: AccountId, + endowed_accounts: Vec, + _enable_println: bool) -> GenesisConfig { GenesisConfig { system: Some(SystemConfig { code: WASM_BINARY.to_vec(), changes_trie_config: Default::default(), }), - aura: Some(AuraConfig { - authorities: initial_authorities.clone(), - }), indices: Some(IndicesConfig { ids: endowed_accounts.clone(), }), @@ -108,5 +133,11 @@ fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec(args: I, exit: E, version: VersionInfo) -> error::Result<()> T: Into + Clone, E: IntoExit, { + type Config = Configuration<(), T>; match parse_and_prepare::(&version, "substrate-node", args) { - ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, |exit, _cli_args, _custom_args, config| { + ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, + |exit, _cli_args, _custom_args, config: Config<_>| { info!("{}", version.name); info!(" version {}", config.full_version()); info!(" by {}, 2017, 2018", version.author); info!("Chain specification: {}", config.chain_spec.name()); info!("Node name: {}", config.name); - info!("Roles: {:?}", config.roles); + info!("Roles: {}", display_role(&config)); let runtime = Runtime::new().map_err(|e| format!("{:?}", e))?; match config.roles { ServiceRoles::LIGHT => run_until_exit( runtime, - service::Factory::new_light(config).map_err(|e| format!("{:?}", e))?, + service::new_light(config)?, exit ), _ => run_until_exit( runtime, - service::Factory::new_full(config).map_err(|e| format!("{:?}", e))?, + service::new_full(config)?, exit ), - }.map_err(|e| format!("{:?}", e)) + } }), - ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), - ParseAndPrepare::ExportBlocks(cmd) => cmd.run::(load_spec, exit), - ParseAndPrepare::ImportBlocks(cmd) => cmd.run::(load_spec, exit), + ParseAndPrepare::BuildSpec(cmd) => cmd.run::(load_spec), + ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>| + Ok(new_full_start!(config).0), load_spec, exit), ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::RevertChain(cmd) => cmd.run::(load_spec), + ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>| + Ok(new_full_start!(config).0), load_spec), ParseAndPrepare::CustomCommand(_) => Ok(()) }?; @@ -55,14 +60,13 @@ fn load_spec(id: &str) -> Result, String> { }) } -fn run_until_exit( +fn run_until_exit( mut runtime: Runtime, service: T, e: E, -) -> error::Result<()> where - T: Deref>, - T: Future + Send + 'static, - C: substrate_service::Components, +) -> error::Result<()> +where + T: AbstractService, E: IntoExit, { let (exit_send, exit) = exit_future::signal(); @@ -99,7 +103,8 @@ impl IntoExit for Exit { let exit_send_cell = RefCell::new(Some(exit_send)); ctrlc::set_handler(move || { - if let Some(exit_send) = exit_send_cell.try_borrow_mut().expect("signal handler not reentrant; qed").take() { + let exit_send = exit_send_cell.try_borrow_mut().expect("signal handler not reentrant; qed").take(); + if let Some(exit_send) = exit_send { exit_send.send(()).expect("Error sending exit notification"); } }).expect("Error setting Ctrl-C handler"); diff --git a/node-template/src/main.rs b/node-template/src/main.rs index 18e9638833fd22230ae292df41d9268acf6054b4..1f286a2237548dfc84a9c9ccce7c9f78a3eb38d4 100644 --- a/node-template/src/main.rs +++ b/node-template/src/main.rs @@ -4,12 +4,13 @@ #![warn(unused_extern_crates)] mod chain_spec; +#[macro_use] mod service; mod cli; pub use substrate_cli::{VersionInfo, IntoExit, error}; -fn main() { +fn main() -> Result<(), cli::error::Error> { let version = VersionInfo { name: "Substrate Node", commit: env!("VERGEN_SHA_SHORT"), @@ -20,8 +21,5 @@ fn main() { support_url: "support.anonymous.an", }; - if let Err(e) = cli::run(::std::env::args(), cli::Exit, version) { - eprintln!("Fatal error: {}\n\n{:?}", e, e); - std::process::exit(1) - } + cli::run(std::env::args(), cli::Exit, version) } diff --git a/node-template/src/service.rs b/node-template/src/service.rs index 7f2c80c48b2b821f42086c2befbc83d1ed531208..398795325fd04075ce025122209f6d6f8b3b060b 100644 --- a/node-template/src/service.rs +++ b/node-template/src/service.rs @@ -1,141 +1,224 @@ -//! Service and ServiceFactory implementation. Specialized wrapper over Substrate service. - -#![warn(unused_extern_crates)] +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use std::sync::Arc; +use std::time::Duration; +use substrate_client::LongestChain; +use runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; +use substrate_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; use transaction_pool::{self, txpool::{Pool as TransactionPool}}; -use node_template_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi, WASM_BINARY}; -use substrate_service::{ - FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, - FullClient, LightClient, LightBackend, FullExecutor, LightExecutor, - error::{Error as ServiceError}, -}; -use basic_authorship::ProposerFactory; -use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration}; -use futures::prelude::*; -use substrate_client::{self as client, LongestChain}; use inherents::InherentDataProviders; -use network::{config::DummyFinalityProofRequestBuilder, construct_simple_protocol}; +use network::{construct_simple_protocol}; use substrate_executor::native_executor_instance; -use substrate_service::construct_service_factory; -use aura_primitives::sr25519::AuthorityPair as AuraAuthorityPair; - pub use substrate_executor::NativeExecutor; +use aura_primitives::sr25519::{AuthorityPair as AuraPair}; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; + // Our native executor instance. native_executor_instance!( pub Executor, - node_template_runtime::api::dispatch, - node_template_runtime::native_version, - WASM_BINARY + runtime::api::dispatch, + runtime::native_version, ); -#[derive(Default)] -pub struct NodeConfig { - inherent_data_providers: InherentDataProviders, -} - construct_simple_protocol! { /// Demo protocol attachment for substrate. pub struct NodeProtocol where Block = Block { } } -construct_service_factory! { - struct Factory { - Block = Block, - RuntimeApi = RuntimeApi, - NetworkProtocol = NodeProtocol { |config| Ok(NodeProtocol::new()) }, - RuntimeDispatch = Executor, - FullTransactionPoolApi = transaction_pool::ChainApi< - client::Client, FullExecutor, Block, RuntimeApi>, - Block - > { - |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) - }, - LightTransactionPoolApi = transaction_pool::ChainApi< - client::Client, LightExecutor, Block, RuntimeApi>, - Block - > { - |config, client| Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) - }, - Genesis = GenesisConfig, - Configuration = NodeConfig, - FullService = FullComponents - { |config: FactoryFullConfiguration| - FullComponents::::new(config) - }, - AuthoritySetup = { - |service: Self::FullService| { - if service.config().roles.is_authority() { - let proposer = ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; - let client = service.client(); - let select_chain = service.select_chain() - .ok_or_else(|| ServiceError::SelectChainRequired)?; - let aura = start_aura::<_, _, _, _, _, AuraAuthorityPair, _, _, _>( - SlotDuration::get_or_compute(&*client)?, - client.clone(), - select_chain, - client, - proposer, - service.network(), - service.config().custom.inherent_data_providers.clone(), - service.config().force_authoring, - Some(service.keystore()), +/// Starts a `ServiceBuilder` for a full service. +/// +/// Use this macro if you don't actually need the full service, but just the builder in order to +/// be able to perform chain operations. +macro_rules! new_full_start { + ($config:expr) => {{ + let mut import_setup = None; + let inherent_data_providers = inherents::InherentDataProviders::new(); + + let builder = substrate_service::ServiceBuilder::new_full::< + runtime::opaque::Block, runtime::RuntimeApi, crate::service::Executor + >($config)? + .with_select_chain(|_config, backend| { + Ok(substrate_client::LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client| + Ok(transaction_pool::txpool::Pool::new(config, transaction_pool::FullChainApi::new(client))) + )? + .with_import_queue(|_config, client, mut select_chain, transaction_pool| { + let select_chain = select_chain.take() + .ok_or_else(|| substrate_service::Error::SelectChainRequired)?; + + let (grandpa_block_import, grandpa_link) = + grandpa::block_import::<_, _, _, runtime::RuntimeApi, _, _>( + client.clone(), &*client, select_chain )?; - service.spawn_task(Box::new(aura.select(service.on_exit()).then(|_| Ok(())))); - } - Ok(service) - } + let import_queue = aura::import_queue::<_, _, AuraPair, _>( + aura::SlotDuration::get_or_compute(&*client)?, + Box::new(grandpa_block_import.clone()), + Some(Box::new(grandpa_block_import.clone())), + None, + client, + inherent_data_providers.clone(), + Some(transaction_pool), + )?; + + import_setup = Some((grandpa_block_import, grandpa_link)); + + Ok(import_queue) + })?; + + (builder, import_setup, inherent_data_providers) + }} +} + +/// Builds a new service for a full client. +pub fn new_full(config: Configuration) + -> Result +{ + let is_authority = config.roles.is_authority(); + let force_authoring = config.force_authoring; + let name = config.name.clone(); + let disable_grandpa = config.disable_grandpa; + + // sentry nodes announce themselves as authorities to the network + // and should run the same protocols authorities do, but it should + // never actively participate in any consensus process. + let participates_in_consensus = is_authority && !config.sentry_mode; + + let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); + + let (block_import, grandpa_link) = + import_setup.take() + .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + + let service = builder.with_network_protocol(|_| Ok(NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .build()?; + + if participates_in_consensus { + let proposer = basic_authorship::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }; + + let client = service.client(); + let select_chain = service.select_chain() + .ok_or(ServiceError::SelectChainRequired)?; + + let aura = aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( + aura::SlotDuration::get_or_compute(&*client)?, + client, + select_chain, + block_import, + proposer, + service.network(), + inherent_data_providers.clone(), + force_authoring, + service.keystore(), + )?; + + // the AURA authoring task is considered essential, i.e. if it + // fails we take down the service with it. + service.spawn_essential_task(aura); + } + + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if participates_in_consensus { + Some(service.keystore()) + } else { + None + }; + + let grandpa_config = grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: true, + keystore, + is_authority, + }; + + match (is_authority, disable_grandpa) { + (false, false) => { + // start the lightweight GRANDPA observer + service.spawn_task(grandpa::run_grandpa_observer( + grandpa_config, + grandpa_link, + service.network(), + service.on_exit(), + )?); }, - LightService = LightComponents - { |config| >::new(config) }, - FullImportQueue = AuraImportQueue< - Self::Block, - > - { | - config: &mut FactoryFullConfiguration, - client: Arc>, - _select_chain: Self::SelectChain, - transaction_pool: Option>>, - | { - import_queue::<_, _, aura_primitives::sr25519::AuthorityPair, _>( - SlotDuration::get_or_compute(&*client)?, - Box::new(client.clone()), - None, - None, - client, - config.custom.inherent_data_providers.clone(), - transaction_pool, - ).map_err(Into::into) - } - }, - LightImportQueue = AuraImportQueue< - Self::Block, - > - { |config: &mut FactoryFullConfiguration, client: Arc>| { - let fprb = Box::new(DummyFinalityProofRequestBuilder::default()) as Box<_>; - import_queue::<_, _, AuraAuthorityPair, TransactionPool>( - SlotDuration::get_or_compute(&*client)?, - Box::new(client.clone()), - None, - None, - client, - config.custom.inherent_data_providers.clone(), - None, - ).map(|q| (q, fprb)).map_err(Into::into) - } - }, - SelectChain = LongestChain, Self::Block> - { |config: &FactoryFullConfiguration, client: Arc>| { - #[allow(deprecated)] - Ok(LongestChain::new(client.backend().clone())) - } + (true, false) => { + // start the full GRANDPA voter + let voter_config = grandpa::GrandpaParams { + config: grandpa_config, + link: grandpa_link, + network: service.network(), + inherent_data_providers: inherent_data_providers.clone(), + on_exit: service.on_exit(), + telemetry_on_connect: Some(service.telemetry_on_connect_stream()), + voting_rule: grandpa::VotingRulesBuilder::default().build(), + }; + + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + service.spawn_essential_task(grandpa::run_grandpa_voter(voter_config)?); + }, + (_, true) => { + grandpa::setup_disabled_grandpa( + service.client(), + &inherent_data_providers, + service.network(), + )?; }, - FinalityProofProvider = { |_client: Arc>| { - Ok(None) - }}, } + + Ok(service) +} + +/// Builds a new service for a light client. +pub fn new_light(config: Configuration) + -> Result +{ + let inherent_data_providers = InherentDataProviders::new(); + + ServiceBuilder::new_light::(config)? + .with_select_chain(|_config, backend| { + Ok(LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client| + Ok(TransactionPool::new(config, transaction_pool::FullChainApi::new(client))) + )? + .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { + let fetch_checker = fetcher + .map(|fetcher| fetcher.checker().clone()) + .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; + let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, _>( + client.clone(), backend, Arc::new(fetch_checker), client.clone() + )?; + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = + finality_proof_import.create_finality_proof_request_builder(); + + let import_queue = aura::import_queue::<_, _, AuraPair, ()>( + aura::SlotDuration::get_or_compute(&*client)?, + Box::new(grandpa_block_import), + None, + Some(Box::new(finality_proof_import)), + client, + inherent_data_providers.clone(), + None, + )?; + + Ok((import_queue, finality_proof_request_builder)) + })? + .with_network_protocol(|_| Ok(NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .build() } diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml index c266427439d781e1e96965ab9809bf527aaf9f25..6c5e8097092cd080ffc14f3d335916ab624db3ec 100644 --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -5,23 +5,39 @@ authors = ["Parity Technologies "] description = "Substrate node implementation in Rust." build = "build.rs" edition = "2018" +default-run = "substrate" + +[badges] +travis-ci = { repository = "paritytech/substrate", branch = "master" } +maintenance = { status = "actively-developed" } +is-it-maintained-issue-resolution = { repository = "paritytech/substrate" } +is-it-maintained-open-issues = { repository = "paritytech/substrate" } + +[[bin]] +name = "substrate" +path = "bin/main.rs" +required-features = ["cli"] + +[lib] +crate-type = ["cdylib", "rlib"] [dependencies] -log = "0.4" -tokio = "0.1.7" -futures = "0.1" -exit-future = "0.1" -cli = { package = "substrate-cli", path = "../../core/cli" } +log = "0.4.8" +futures = "0.1.29" +jsonrpc-core = "14.0.3" codec = { package = "parity-scale-codec", version = "1.0.0" } sr-io = { path = "../../core/sr-io" } client = { package = "substrate-client", path = "../../core/client" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } inherents = { package = "substrate-inherents", path = "../../core/inherents" } node-runtime = { path = "../runtime" } +node-rpc = { path = "../rpc" } node-primitives = { path = "../primitives" } -hex-literal = "0.2" +hex-literal = "0.2.1" +substrate-rpc = { package = "substrate-rpc", path = "../../core/rpc" } substrate-basic-authorship = { path = "../../core/basic-authorship" } -substrate-service = { path = "../../core/service" } +substrate-service = { path = "../../core/service", default-features = false } +chain-spec = { package = "substrate-chain-spec", path = "../../core/chain-spec" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } network = { package = "substrate-network", path = "../../core/network" } babe = { package = "substrate-consensus-babe", path = "../../core/consensus/babe" } @@ -31,27 +47,79 @@ grandpa_primitives = { package = "substrate-finality-grandpa-primitives", path = sr-primitives = { path = "../../core/sr-primitives" } node-executor = { path = "../executor" } substrate-telemetry = { package = "substrate-telemetry", path = "../../core/telemetry" } -structopt = "0.2" -transaction-factory = { path = "../../test-utils/transaction-factory" } +structopt = "0.3.3" keyring = { package = "substrate-keyring", path = "../../core/keyring" } indices = { package = "srml-indices", path = "../../srml/indices" } timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default-features = false } -rand = "0.6" +rand = "0.7.2" finality_tracker = { package = "srml-finality-tracker", path = "../../srml/finality-tracker", default-features = false } contracts = { package = "srml-contracts", path = "../../srml/contracts" } system = { package = "srml-system", path = "../../srml/system" } balances = { package = "srml-balances", path = "../../srml/balances" } +transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment" } support = { package = "srml-support", path = "../../srml/support", default-features = false } im_online = { package = "srml-im-online", path = "../../srml/im-online", default-features = false } +serde = { version = "1.0.101", features = [ "derive" ] } +client_db = { package = "substrate-client-db", path = "../../core/client/db", default-features = false } +offchain = { package = "substrate-offchain", path = "../../core/offchain" } + +# CLI-specific dependencies +tokio = { version = "0.1.22", optional = true } +exit-future = { version = "0.1.4", optional = true } +substrate-cli = { path = "../../core/cli", optional = true } +transaction-factory = { path = "../../test-utils/transaction-factory", optional = true } +ctrlc = { version = "3.1.3", features = ["termination"], optional = true } + +# WASM-specific dependencies +libp2p = { version = "0.13.0", default-features = false, optional = true } +clear_on_drop = { version = "0.2.3", features = ["no_cc"], optional = true } # Imported just for the `no_cc` feature +console_error_panic_hook = { version = "0.1.1", optional = true } +console_log = { version = "0.1.2", optional = true } +js-sys = { version = "0.3.22", optional = true } +wasm-bindgen = { version = "0.2.45", optional = true } +wasm-bindgen-futures = { version = "0.3.22", optional = true } +kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d", optional = true } +rand6 = { package = "rand", version = "0.6", features = ["wasm-bindgen"], optional = true } # Imported just for the `wasm-bindgen` feature [dev-dependencies] keystore = { package = "substrate-keystore", path = "../../core/keystore" } babe = { package = "substrate-consensus-babe", path = "../../core/consensus/babe", features = ["test-helpers"] } consensus-common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } service-test = { package = "substrate-service-test", path = "../../core/service/test" } -futures03 = { package = "futures-preview", version = "=0.3.0-alpha.17" } -tempfile = "3.1" +futures03 = { package = "futures-preview", version = "0.3.0-alpha.19" } +tempfile = "3.1.0" [build-dependencies] -cli = { package = "substrate-cli", path = "../../core/cli" } -structopt = "0.2" +substrate-cli = { package = "substrate-cli", path = "../../core/cli" } +build-script-utils = { package = "substrate-build-script-utils", path = "../../core/utils/build-script-utils" } +structopt = "0.3.3" +vergen = "3.0.4" + +[features] +default = ["cli"] +browser = [ + "clear_on_drop", + "console_error_panic_hook", + "console_log", + "js-sys", + "libp2p", + "wasm-bindgen", + "wasm-bindgen-futures", + "kvdb-memorydb", + "rand/wasm-bindgen", + "rand6" +] +cli = [ + "substrate-cli", + "transaction-factory", + "tokio", + "exit-future", + "ctrlc", + "substrate-service/rocksdb" +] +wasmtime = [ + "cli", + "node-executor/wasmtime", + "substrate-cli/wasmtime", + "substrate-service/wasmtime", +] diff --git a/node/src/main.rs b/node/cli/bin/main.rs similarity index 89% rename from node/src/main.rs rename to node/cli/bin/main.rs index ca4a6b4c601de658896d0d9dbc43f006c2462ca7..e4415a2a89e664d21248d189381133a107c6b484 100644 --- a/node/src/main.rs +++ b/node/cli/bin/main.rs @@ -18,15 +18,15 @@ #![warn(missing_docs)] -use cli::VersionInfo; use futures::sync::oneshot; use futures::{future, Future}; +use substrate_cli::VersionInfo; use std::cell::RefCell; // handles ctrl-c struct Exit; -impl cli::IntoExit for Exit { +impl substrate_cli::IntoExit for Exit { type Exit = future::MapErr, fn(oneshot::Canceled) -> ()>; fn into_exit(self) -> Self::Exit { // can't use signal directly here because CtrlC takes only `Fn`. @@ -43,7 +43,7 @@ impl cli::IntoExit for Exit { } } -fn main() { +fn main() -> Result<(), substrate_cli::error::Error> { let version = VersionInfo { name: "Substrate Node", commit: env!("VERGEN_SHA_SHORT"), @@ -54,8 +54,5 @@ fn main() { support_url: "https://github.com/paritytech/substrate/issues/new", }; - if let Err(e) = cli::run(::std::env::args(), Exit, version) { - eprintln!("Fatal error: {}\n\n{:?}", e, e); - std::process::exit(1) - } + node_cli::run(std::env::args(), Exit, version) } diff --git a/node/cli/browser-demo/.gitignore b/node/cli/browser-demo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..0c6117d9fb83be5d944c757c10508e44b4cf2b30 --- /dev/null +++ b/node/cli/browser-demo/.gitignore @@ -0,0 +1 @@ +pkg \ No newline at end of file diff --git a/node/cli/browser-demo/README.md b/node/cli/browser-demo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4faebcbc76df4b416dd3274635c99e23b8fbd5bd --- /dev/null +++ b/node/cli/browser-demo/README.md @@ -0,0 +1,10 @@ +# How to run this demo + +```sh +cargo install wasm-pack # If necessary + +# From the `node/cli` directory (parent from this README) +wasm-pack build --target web --out-dir ./demo/pkg --no-typescript --release -- --no-default-features --features "browser" + +xdg-open index.html +``` diff --git a/node/cli/browser-demo/build.sh b/node/cli/browser-demo/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..c16100794ad2e3f5ac315d4acaf684485cfac6db --- /dev/null +++ b/node/cli/browser-demo/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +wasm-pack build --target web --out-dir ./browser-demo/pkg --no-typescript --release ./.. -- --no-default-features --features "browser" +python -m SimpleHTTPServer 8000 diff --git a/node/cli/browser-demo/favicon.png b/node/cli/browser-demo/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4548ce34dfa220f612080820cfde778a39cb8f Binary files /dev/null and b/node/cli/browser-demo/favicon.png differ diff --git a/node/cli/browser-demo/index.html b/node/cli/browser-demo/index.html new file mode 100644 index 0000000000000000000000000000000000000000..cf107e64568f25c28f891c15577047fd2995a303 --- /dev/null +++ b/node/cli/browser-demo/index.html @@ -0,0 +1,39 @@ + + + + + Substrate node + + + + + diff --git a/node/cli/browser-demo/ws.js b/node/cli/browser-demo/ws.js new file mode 100644 index 0000000000000000000000000000000000000000..fa7a499a8a7a3046e72495b90c03827f3000c839 --- /dev/null +++ b/node/cli/browser-demo/ws.js @@ -0,0 +1,148 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +export default () => { + return { + dial: dial, + listen_on: (addr) => { + let err = new Error("Listening on WebSockets is not possible from within a browser"); + err.name = "NotSupportedError"; + throw err; + }, + }; +} + +/// Turns a string multiaddress into a WebSockets string URL. +// TODO: support dns addresses as well +const multiaddr_to_ws = (addr) => { + let parsed = addr.match(/^\/(ip4|ip6|dns4|dns6)\/(.*?)\/tcp\/(.*?)\/(ws|wss|x-parity-ws\/(.*)|x-parity-wss\/(.*))$/); + let proto = 'wss'; + if (parsed[4] == 'ws' || parsed[4] == 'x-parity-ws') { + proto = 'ws'; + } + let url = decodeURIComponent(parsed[5] || parsed[6] || ''); + if (parsed != null) { + if (parsed[1] == 'ip6') { + return proto + "://[" + parsed[2] + "]:" + parsed[3] + url; + } else { + return proto + "://" + parsed[2] + ":" + parsed[3] + url; + } + } + + let err = new Error("Address not supported: " + addr); + err.name = "NotSupportedError"; + throw err; +} + +// Attempt to dial a multiaddress. +const dial = (addr) => { + let ws = new WebSocket(multiaddr_to_ws(addr)); + let reader = read_queue(); + + return new Promise((resolve, reject) => { + // TODO: handle ws.onerror properly after dialing has happened + ws.onerror = (ev) => reject(ev); + ws.onmessage = (ev) => reader.inject_blob(ev.data); + ws.onclose = () => reader.inject_eof(); + ws.onopen = () => resolve({ + read: (function*() { while(ws.readyState == 1) { yield reader.next(); } })(), + write: (data) => { + if (ws.readyState == 1) { + ws.send(data); + return promise_when_ws_finished(ws); + } else { + return Promise.reject("WebSocket is closed"); + } + }, + shutdown: () => {}, + close: () => ws.close() + }); + }); +} + +// Takes a WebSocket object and returns a Promise that resolves when bufferedAmount is 0. +const promise_when_ws_finished = (ws) => { + if (ws.bufferedAmount == 0) { + return Promise.resolve(); + } + + return new Promise((resolve, reject) => { + setTimeout(function check() { + if (ws.bufferedAmount == 0) { + resolve(); + } else { + setTimeout(check, 100); + } + }, 2); + }) +} + +// Creates a queue reading system. +const read_queue = () => { + // State of the queue. + let state = { + // Array of promises resolving to `ArrayBuffer`s, that haven't been transmitted back with + // `next` yet. + queue: new Array(), + // If `resolve` isn't null, it is a "resolve" function of a promise that has already been + // returned by `next`. It should be called with some data. + resolve: null, + }; + + return { + // Inserts a new Blob in the queue. + inject_blob: (blob) => { + if (state.resolve != null) { + var resolve = state.resolve; + state.resolve = null; + + var reader = new FileReader(); + reader.addEventListener("loadend", () => resolve(reader.result)); + reader.readAsArrayBuffer(blob); + } else { + state.queue.push(new Promise((resolve, reject) => { + var reader = new FileReader(); + reader.addEventListener("loadend", () => resolve(reader.result)); + reader.readAsArrayBuffer(blob); + })); + } + }, + + // Inserts an EOF message in the queue. + inject_eof: () => { + if (state.resolve != null) { + var resolve = state.resolve; + state.resolve = null; + resolve(null); + } else { + state.queue.push(Promise.resolve(null)); + } + }, + + // Returns a Promise that yields the next entry as an ArrayBuffer. + next: () => { + if (state.queue.length != 0) { + return state.queue.shift(0); + } else { + if (state.resolve !== null) + throw "Internal error: already have a pending promise"; + return new Promise((resolve, reject) => { + state.resolve = resolve; + }); + } + } + }; +}; diff --git a/node/cli/build.rs b/node/cli/build.rs index e7a7b271f15034498ad00dbf17827a96a7a0a127..ae936ce4fbacef2b32e8bec34e2286997448035d 100644 --- a/node/cli/build.rs +++ b/node/cli/build.rs @@ -14,14 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use cli::{NoCustom, CoreParams}; - use std::{fs, env, path::Path}; - use structopt::{StructOpt, clap::Shell}; +use substrate_cli::{NoCustom, CoreParams}; +use vergen::{ConstantsFlags, generate_cargo_keys}; fn main() { build_shell_completion(); + generate_cargo_keys(ConstantsFlags::all()).expect("Failed to generate metadata files"); + + build_script_utils::rerun_if_git_head_changed(); } /// Build shell completion scripts for all known shells diff --git a/node/cli/res/flaming-fir.json b/node/cli/res/flaming-fir.json index 851aaa21b4a9a332147279495349e32a5fc95862..5cd11eb97fa008d124b4d51322520610538d6d8c 100644 --- a/node/cli/res/flaming-fir.json +++ b/node/cli/res/flaming-fir.json @@ -21,86 +21,91 @@ "protocolId": "fir", "consensusEngine": null, "genesis": { - "raw": [{ - "0xbc3717660105a864bd63dcd430de64128d58bd0917fa8dd75aee827cf086e19c": "0x0000c16ff28623000000000000000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973a6e391e5d17627fa5aaa7a76b39ebee4b139bff595608fe41aea21aa7ea48053": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x7eb7a404bf7e3466c3f6c5914e25edfaab48b1e24fd29ea5a94deaaa1aba80e6": "0x0c0001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65019c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797372fff749dbf31067eff27b442ec22922d2b7817d7c6fbc6895d90847fd91504c": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0xc98362e2ca21b342cc749022ed9b560e4d29ec9862a960c2538c314f1d279635": "0x149ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e3180973474718099c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d1268655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b657973e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a", - "0xc63b8a0db7e72fd87c88d8dcf4777b883f86728613c57148c4e5cdceb05b7a1a": "0x0c0001f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b6579737f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0x2b334d6ac6698775ed17edf8cd3cbd9dae56cead0d69cb54f6af6aaecba544d8": "0x0f0000c16ff286230f0000c16ff2862300", - "0x9651d20f401bfac47731a01d6eba33b4": "0x00000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797361be8e37f76f246c8d427bc3a669795df24fff7035dc10ba08f864f7d286c05e": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", - "0x154ebcb2c318b2e1c23e43e65aea27cd1348c4c5157502d7669a31c7635019cc": "0x9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526", - "0x26ac4a74e1ba94e0e7dbfc3b2aea083cf3c0f0d80eb999c7cebb340ee8934da9": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde780f0000c16ff286230f0000c16ff2862300", - "0x2d5205eddfc20f1a616c0391abb78a3920e823abe7ed33cfd7945dd1a1bf8651": "0x047374616b696e67200000c16ff28623000000000000000000ffffffffffffffff0e", - "0x121725e2f949944d00a8c011c0db54ae07b84a6ca772adf3c65417345d91522d": "0x0000c16ff28623000000000000000000", - "0x2dce29f1a768624dc5343063cb77f77d": "0x07000000", - "0x46cef122497fefa60faf6c66d3ef05caf9870446796ae11f0a4f734fee993d8b": "0x00", - "0xfff675c76ad8a5dfbd7db9a4e80f7c0ece595ad1878d2b6fca6086b2483a055b": "0x0000c16ff28623000000000000000000", - "0x75f6361fd25fec35714be80f2d9870af8c92e73cb6d299ba4774f5b0ad842275": "0x00", - "0x633daafcb669e97549c1b9d65660881016f969040bc16171709159437c31294a": "0x0f0000c16ff286230f0000c16ff2862300", - "0x7c79972b34b7e51bdd5f168ba3accd35fbec396be75dfad19dd1121327f1a1ad": "0x0c000168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde7800", - "0x4e62513de81454ce76df887573f7f98b101eb4585b1485a222b7db599f4e93e2": "0x047374616b696e67200000c16ff28623000000000000000000ffffffffffffffff0e", - "0xd437fe93b0bd0a5d67d30d85d010edc2": "0x40420f00", - "0xb2029f8665aac509629f2d28cea790a3": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", - "0xdfaac108e0d4bc78fc9419a7fcfa84dc": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde789c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973887a8c8429d90d6cf7a8ba6b60877979bff529eab6930cb2fdea5edf5a79c7d5": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x579ab55d37b1220812be3c3df29d4858": "0x00000000", - "0xa902f1f0ef97177b8df9f9fd413768e7": "0x00000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973559fe6ed570e93d5c6b0b335ecf466e5fbbbe8261673da66a68c9fcc835db06b": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0x366a192e1ce90bf109f11cf4d4bdab1ce310d835c09411b1be3ad53814e33196": "0x0c000001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0x125dc846383907f5846f72ce53ca0e4b": "0x00ca9a3b000000000000000000000000", - "0x8b4621d5f16433d6024b5a31547c59ee24e749e051dbb4bc7e64502f2a4f62fb": "0x66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f", - "0x4ac2684a5a20e7a5adf17ed7aa792a3f6334a0505f02b2a44c3934d36cc4ee0a": "0xc8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e", - "0xd546f8df064d356bc9db11de6d1207a8": "0x00", - "0x71020fee971bd00e8248d1830b8cffbe5b9cf4de1ea2911a1665c44fd70ab6f3": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630f0000c16ff286230f0000c16ff2862300", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b65797394f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378", - "0x3a636f6465": "0x0061736d0100000001c6022b60027f7f0060017f0060037f7f7f0060047f7f7f7f0060027f7f017f60037f7f7f017f60057f7f7f7f7f0060057f7f7f7f7f017f60067f7f7f7f7f7f017f60087f7f7f7f7f7f7f7f017f60067f7f7f7f7f7f0060047f7f7f7f017f60077f7f7f7f7f7f7f017f60027e7f017f60017f017f60047e7f7f7f017f60017e0060000060077f7e7e7e7e7e7e0060087f7f7f7f7f7f7f7f0060047f7f7f7f017e60047f7f7e7e0060037f7e7e0060057f7f7e7e7f0060057f7f7f7e7e0060077f7e7e7f7f7f7f0060047f7f7e7f0060037f7f7e0060067f7f7e7e7e7f0060037e7f7f017f60087f7f7e7e7f7f7f7f0060097f7f7f7e7e7f7f7f7f0060047f7e7e7e0060027f7e0060027f7f017e60087f7f7f7f7f7e7e7f0060017e017f60057f7e7f7f7e0060037f7e7f0060017f017e60047f7e7e7f0060057f7e7e7e7e0060067f7e7e7e7e7f0002cd072503656e760e6578745f626c616b65325f323536000203656e761f6578745f6765745f616c6c6f63617465645f6368696c645f73746f72616765000703656e76176578745f636c6561725f6368696c645f73746f72616765000303656e760f6578745f7365745f73746f72616765000303656e760c6578745f74776f785f313238000203656e76196578745f6765745f616c6c6f63617465645f73746f72616765000503656e76166578745f73616e64626f785f6d656d6f72795f6e6577000403656e761b6578745f73616e64626f785f6d656d6f72795f74656172646f776e000103656e76176578745f73616e64626f785f696e7374616e7469617465000803656e76126578745f73616e64626f785f696e766f6b65000903656e761d6578745f73616e64626f785f696e7374616e63655f74656172646f776e000103656e76146578745f6765745f73746f726167655f696e746f000703656e76116578745f636c6561725f73746f72616765000003656e76166578745f6b696c6c5f6368696c645f73746f72616765000003656e76106578745f636c6561725f707265666978000003656e76166578745f6368696c645f73746f726167655f726f6f74000503656e760e6578745f7072696e745f75746638000003656e76156578745f7365745f6368696c645f73746f72616765000a03656e76166578745f73616e64626f785f6d656d6f72795f676574000b03656e76166578745f73616e64626f785f6d656d6f72795f736574000b03656e76126578745f737232353531395f766572696679000b03656e76126578745f656432353531395f766572696679000b03656e760d6578745f7072696e745f686578000003656e76156578745f6c6f63616c5f73746f726167655f676574000b03656e76216578745f6c6f63616c5f73746f726167655f636f6d706172655f616e645f736574000c03656e760a6578745f7075626b6579000d03656e76116578745f6e6574776f726b5f7374617465000e03656e76086578745f7369676e000f03656e76166578745f7375626d69745f7472616e73616374696f6e000403656e76156578745f6c6f63616c5f73746f726167655f736574000603656e76106578745f73746f726167655f726f6f74000103656e76186578745f73746f726167655f6368616e6765735f726f6f74000503656e760b6578745f74776f785f3634000203656e76236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74000303656e760d6578745f7072696e745f6e756d001003656e760a6578745f6d616c6c6f63000e03656e76086578745f66726565000103b404b20400000e0501001100000000000000000000000200110100000100000000000000000000000000000000000000000000000404000100040000001202020013110303030303030303030303030303030303030303030314020e00020004040515021502010216000100000200171800000200190101010100160101151a00030101011b001c041d08151601010000020010020001000003020001010001000000000000000002040600000002060204020000010000011e0202060403031f02020402000001010020010101000000000015022001000002000200000101010002020300210002040000000000000000000000001111000000000000010101010101010101010101010002110311020202020201010001001003222200020210012222000200000000222222002222220222222222222222000000010101000000010000000000000000000000000000000101010e120500000001000300000004000e02000102020101000100010102000002000100010101000001001111230100242400000006012100000001000100002500010100000001000000000000000b0000000001010101000000000000000100150000010200000402020602260000040000020502060002000400020000040003040204040001000203030202040606020202020304050104040405040404070204020402020000040204010404010404040400010100020000000e01050e050404270b0304040e0404040404030105010404050404040505050528282929292a0407017001cf01cf0105030100120611027f01418080c0000b7f0041c882c6000b07ab0414066d656d6f72790200195f5f696e6469726563745f66756e6374696f6e5f7461626c6501000b5f5f686561705f6261736503010c436f72655f76657273696f6e00bd0212436f72655f657865637574655f626c6f636b00be0215436f72655f696e697469616c697a655f626c6f636b00c402114d657461646174615f6d6574616461746100c5021c426c6f636b4275696c6465725f6170706c795f65787472696e73696300cc021b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b00cd0220426c6f636b4275696c6465725f696e686572656e745f65787472696e7369637300ce021c426c6f636b4275696c6465725f636865636b5f696e686572656e747300d00218426c6f636b4275696c6465725f72616e646f6d5f7365656400d1022b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e00d202214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b657200d402214772616e6470614170695f6772616e6470615f70656e64696e675f6368616e676500d502204772616e6470614170695f6772616e6470615f666f726365645f6368616e676500d6021e4772616e6470614170695f6772616e6470615f617574686f72697469657300d70214426162654170695f737461727475705f6461746100d8020d426162654170695f65706f636800d90218436f6e73656e7375734170695f617574686f72697469657300da02098903010041010bce01f403ca0155565a6465666768696a6b6c6d6e6f707172737475767778797a8001c204e503f703f903fa03ef039e0483048b049004bf0497049904bb04bc04f7018101e0029b01bb03c601e902ea02ce038d03c401a104a901b001e802e202c701c501c301c201bf01c101ee02c104c004ea01f101f001ef01f801f901fa0182029b039a03a0029e03b003b2038c038b038e0391039003fd02a1029a019901a2029d01cc03cb03a302d4038002ff01a4028102b803b703a502bc03f502f402a602f602be01bd01a702c001ae01af01e901e801a802ed01ec01a902ee01df02de02aa02e402b602b7029f02a401a301ab02a501b802e302e102f002ef02ed02ec02eb02e702e602e5028f03d001d101d301d201cf01d4019d039c03a303dd01e301e501e401e201e601b103b403b303ba03b903c003bf03be03bd03d203d103d003cf03cd03d503d903ae03d703da038d0492048e048f04a0049404a204a304a504a604a704a804a904aa04b504b604b704cc04b804c604c504c704c804c904ca04cb040a84f838b2049a1002187f017e230041f0006b2202240002400240024020012802042203200128020022046b41e100490d0003402001200441206a3602002001280208220341306a280200210520032802282106200241d0006a41186a22034200370300200241d0006a41106a22074200370300200241d0006a41086a220842003703002002420037035020044120200241d0006a1000200241106a41186a22092003290300370300200241106a41106a220a2007290300370300200241106a41086a220b2008290300370300200220022903503703102002410036025020062005200241106a4120200241d0006a100121060240024020022802502205417f470d002002200c36020c2002200d3602082002200e3602040c010b2001280208220f2802302110200f280228210f2003420037030020074200370300200842003703002002420037035020044120200241d0006a1000200241306a41186a2003290300370300200241306a41106a2007290300370300200241306a41086a200829030037030020022002290350370330200f2010200241306a412010022002200536020c20022005360208200220063602042006210e2005210d2005210c2004450d00200241046a21010c030b20012001280200220441206a3602002001280208220541306a2802002106200528022821052003420037030020074200370300200842003703002002420037035020044120200241d0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903503703102002410036025020052006200241106a4120200241d0006a100121060240024020022802502205417f470d002002201136020c20022012360208200220133602040c010b2001280208220f2802302110200f280228210f2003420037030020074200370300200842003703002002420037035020044120200241d0006a1000200241306a41186a2003290300370300200241306a41106a2007290300370300200241306a41086a200829030037030020022002290350370330200f2010200241306a412010022002200536020c20022005360208200220063602042006211320052112200521112004450d00200241046a21010c030b20012001280200220441206a3602002001280208220541306a2802002106200528022821052003420037030020074200370300200842003703002002420037035020044120200241d0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903503703102002410036025020052006200241106a4120200241d0006a100121060240024020022802502205417f470d002002201436020c20022015360208200220163602040c010b2001280208220f2802302110200f280228210f2003420037030020074200370300200842003703002002420037035020044120200241d0006a1000200241306a41186a2003290300370300200241306a41106a2007290300370300200241306a41086a200829030037030020022002290350370330200f2010200241306a412010022002200536020c20022005360208200220063602042006211620052115200521142004450d00200241046a21010c030b20012001280200220441206a3602002001280208220541306a2802002106200528022821052003420037030020074200370300200842003703002002420037035020044120200241d0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903503703102002410036025020052006200241106a4120200241d0006a1001210a0240024020022802502209417f470d002002201736020c20022018360208200220193602040c010b2001280208220b2802302105200b280228210b2003420037030020074200370300200842003703002002420037035020044120200241d0006a1000200241306a41186a2003290300370300200241306a41106a2007290300370300200241306a41086a200829030037030020022002290350370330200b2005200241306a412010022002200936020c200220093602082002200a360204200a211920092118200921172004450d00200241046a21010c030b20012802042203200128020022046b41e0004b0d000b0b024020042003460d0003402001200441206a3602002001280208220341306a280200210a20032802282103200241d0006a41186a22074200370300200241d0006a41106a22084200370300200241d0006a41086a220942003703002002420037035020044120200241d0006a1000200241106a41186a2007290300370300200241106a41106a2008290300370300200241106a41086a200929030037030020022002290350370310200241003602502003200a200241106a4120200241d0006a1001210a0240024020022802502203417f470d002002200b36020c20022005360208200220063602040c010b2001280208220b2802302105200b280228210b2007420037030020084200370300200942003703002002420037035020044120200241d0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a200929030037030020022002290350370330200b2005200241306a412010022002200336020c200220033602082002200a360204200a2106200321052003210b2004450d00200241046a21010c030b200128020022042001280204470d000b0b200041003602000c010b200241d0006a41086a200141086a280200220336020020022001290200221a370350200020043602002000201a3702042000410c6a20033602000b200241f0006a24000b910202077f017e0240024002400240200041046a2802002202200041086a28020022036b2001410c6a2802002204200141086a28020022056b220641a8016d2207490d00200028020021020c010b200320076a22082003490d0220024101742203200820082003491b2203ad42a8017e2209422088a70d022009a722084100480d020240024020020d002008102721020c010b2000280200200241a8016c2008102821020b2002450d0120002002360200200041046a2003360200200041086a28020021030b2002200341a8016c6a2005200610ce041a200141086a2004360200200041086a2200200028020020076a36020002402001280204450d00200128020010290b0f0b20084108102a000b102b000b0700200010b1040b0b0020002001200210b3040b0700200010b2040b0e0041e8cfc500412210ac0400000b0a0041b0d2c5001058000b910202077f017e0240024002400240200041046a2802002202200041086a28020022036b2001410c6a2802002204200141086a28020022056b220641e8006d2207490d00200028020021020c010b200320076a22082003490d0220024101742203200820082003491b2203ad42e8007e2209422088a70d022009a722084100480d020240024020020d002008102721020c010b2000280200200241e8006c2008102821020b2002450d0120002002360200200041046a2003360200200041086a28020021030b2002200341e8006c6a2005200610ce041a200141086a2004360200200041086a2200200028020020076a36020002402001280204450d00200128020010290b0f0b20084108102a000b102b000b9904010f7f230041d0006b22022400200241086a2001102e02400240024020022802080d00200041003602000c010b02400240200228020c22034180012003418001491b22040d00410121050c010b2004410574220610272205450d020b02402003450d00200241306a41186a2107200241306a41106a2108200241306a41086a21094100210a4100210b4100210c034020074200370300200842003703002009420037030020024200370330200241306a2001280200220d20012802042206412020064120491b220e10ce041a20012006200e6b3602042001200d200e6a36020002402006411f4b0d00200041003602002004450d03200510290c030b200c41016a2106200241106a41186a220e2007290300370300200241106a41106a220d2008290300370300200241106a41086a220f2009290300370300200220022903303703100240200c2004470d000240200a20062006200a491b220441ffffff3f712004470d00200441057422104100480d0002400240200c0d002010102721050c010b2005200b2010102821050b20050d0120104101102a000b102b000b2005200b6a220c2002290310370000200c41186a200e290300370000200c41106a200d290300370000200c41086a200f290300370000200a41026a210a200b41206a210b2006210c20032006470d000b0b2000200436020420002005360200200041086a20033602000b200241d0006a24000f0b20064101102a000bbd0301077f230041106b22022400200241003a0003200241036a2001280200220320012802042204410047220510ce041a0240024002400240024020042005490d002001200420056b22063602042001200320056a22053602002004450d02024020022d0003220341037122044103460d0002400240024020040e03000102000b20034102762101410121040c070b200241003a000b2002410b6a20052006410047220410ce041a20062004490d032001200620046b3602042001200520046a3602002006450d0420022d000b4108742003724102762101410121040c060b41002104200241003a000e200241003b010c2002410c6a200520064103200641034922071b220810ce041a2001200620086b3602042001200520086a36020020070d0520022f010c20022d000e411074724108742003724102762101410121040c050b200341034b0d024100210420024100360204200241046a200520064104200641044922081b220310ce041a2001200620036b3602042001200520036a36020020080d0320022802042101410121040c040b20052004103e000b20042006103e000b410021040b0b2000200136020420002004360200200241106a24000b860402077f017e230041106b2202240020024100360208200242013703002000280200210320022000280208220036020c2002410c6a200210300240024002400240024020000d002002280208210020022802042104200228020021050c010b2003200041286c6a21062002280204210420022802082100034002400240200420006b4120490d00200041206a2107200228020021050c010b200041206a22072000490d0520044101742205200720072005491b22084100480d050240024020040d002008102721050c010b200228020020042008102821050b2005450d032002200836020420022005360200200821040b200520006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a2900003700002002200736020820002003290000370000200341206a290300210902400240200420076b4108490d00200741086a21000c010b200741086a22002007490d0520044101742208200020002008491b22084100480d050240024020040d002008102721050c010b200520042008102821050b2005450d042002200836020420022005360200200821040b20022000360208200520076a20093700002006200341286a2203470d000b0b2001280200200128020420052000100302402004450d00200510290b200241106a24000f0b20084101102a000b20084101102a000b102b000b9e0701037f02400240024002400240024020002802002202413f4b0d0002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0620004101742204200320032004491b22044100480d060240024020000d002004102721030c010b200128020020002004102821030b2003450d0220012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20024102743a00000f0b200241808001490d032002418080808004490d020c010b20044101102a000b0240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0520024101742204200320032004491b22044100480d050240024020020d002004102721030c010b200128020020022004102821030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280200210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d0520024101742200200420042000491b22004100480d050240024020020d002000102721020c010b200128020020022000102821020b2002450d0220012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b20044101102a000b20004101102a000b024002400240200141046a2802002203200141086a28020022006b4104490d00200128020021030c010b200041046a22042000490d0320034101742200200420042000491b22004100480d030240024020030d002000102721030c010b200128020020032000102821030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20024102744102723600000f0b20004101102a000b024002400240200141046a2802002203200141086a28020022006b4102490d00200128020021030c010b200041026a22042000490d0220034101742200200420042000491b22004100480d020240024020030d002000102721030c010b200128020020032000102821030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20024102744101723b00000f0b20004101102a000b102b000b800501067f230041106b2202240020024100360208200242013703002000280200210320022000280208220036020c2002410c6a20021030024002400240024002402000450d0020004190016c2104034020022802042105200228020821000240024020032802004112470d000240024020052000460d00200228020021050c010b200041016a22052000490d0820004101742206200520052006491b22064100480d080240024020000d002006102721050c010b200228020020002006102821050b2005450d052002200636020420022005360200200228020821000b2002200041016a360208200520006a41003a00000c010b0240024020052000460d00200228020021050c010b200041016a22052000490d0720004101742206200520052006491b22064100480d070240024020000d002006102721050c010b200228020020002006102821050b2005450d052002200636020420022005360200200228020821000b2002200041016a360208200520006a41013a000020032002103220034188016a28020021060240024020022802042205200228020822006b4104490d00200228020021050c010b200041046a22072000490d0720054101742200200720072000491b22004100480d070240024020050d002000102721050c010b200228020020052000102821050b2005450d062002200036020420022005360200200228020821000b2002200041046a360208200520006a20063600000b20034190016a2103200441f07e6a22040d000b0b2002280204210020012802002001280204200228020022032002280208100302402000450d00200310290b200241106a24000f0b20064101102a000b20064101102a000b20004101102a000b102b000be3d00104057f017e067f017e230041206b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000280200220341114b0d0002400240024002400240024002400240024002400240024002400240024002400240024020030e12000102030405060708090a0b0c0d0e0f1011000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5e20034101742205200420042005491b22054100480d5e0240024020030d002005102721040c010b200128020020032005102821040b2004450d1320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208417f6a220341054b0d1102400240024002400240024020030e06000102030405000b200241003a001c02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d6320004101742204200320032004491b22044100480d630240024020000d002004102721030c010b200128020020002004102821030b2003450d1920012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c160b200241013a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6220034101742205200420042005491b22054100480d620240024020030d002005102721040c010b200128020020032005102821040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200028020c21062002200041146a2802002200360208200241086a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d6220044101742203200520052003491b22034100480d620240024020040d002003102721040c010b200128020020042003102821040b2004450d1a20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010ce041a0c150b200241023a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6120034101742205200420042005491b22054100480d610240024020030d002005102721040c010b200128020020032005102821040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000290310210702400240200141046a2802002203200528020022006b4108490d00200128020021030c010b200041086a22042000490d6120034101742200200420042000491b22004100480d610240024020030d002000102721030c010b200128020020032000102821030b2003450d1b20012003360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200320006a20073700000c140b200241033a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6020034101742205200420042005491b22054100480d600240024020030d002005102721040c010b200128020020032005102821040b2004450d1b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c21062002200041146a2802002200360208200241086a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d6020044101742203200520052003491b22034100480d600240024020040d002003102721040c010b200128020020042003102821040b2004450d1c20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010ce041a0c130b200141086a2802002103200241043a001c024002402003200141046a280200460d00200128020021050c010b200341016a22042003490d5f20034101742205200420042005491b22044100480d5f0240024020030d002004102721050c010b200128020020032004102821050b2005450d1c20012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41043a0000200028020c21032002200041146a2802002200360208200241086a200110302000450d122003200041186c6a2108200141046a21060340200328020021092002200341086a2802002200360208200241086a20011030024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d60200a4101742205200b200b2005491b22054100480d6002400240200a0d0020051027210a0c010b2001280200200a20051028210a0b200a450d1e2001200a36020020062005360200200428020021050b2004200520006a360200200a20056a2009200010ce041a2003410c6a28020021092002200341146a2802002200360208200241086a20011030024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d60200a4101742205200b200b2005491b22054100480d6002400240200a0d0020051027210a0c010b2001280200200a20051028210a0b200a450d1f2001200a36020020062005360200200428020021050b2004200520006a360200200a20056a2009200010ce041a200341186a22032008470d000c130b0b200241053a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5e20034101742205200420042005491b22054100480d5e0240024020030d002005102721040c010b200128020020032005102821040b2004450d1e20012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41053a0000200028020c21042002200041146a2802002200360208200241086a200110302000450d1120042000410c6c6a2108200141046a210903402004280200210a2002200441086a2802002203360208200241086a200110300240024020092802002205200628020022006b2003490d00200128020021050c010b200020036a220b2000490d5f20054101742200200b200b2000491b22004100480d5f0240024020050d002000102721050c010b200128020020052000102821050b2005450d202001200536020020092000360200200628020021000b2006200020036a360200200520006a200a200310ce041a2004410c6a22042008470d000c120b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d5d20004101742204200320032004491b22044100480d5d0240024020000d002004102721030c010b200128020020002004102821030b2003450d1f20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c20034101742205200420042005491b22054100480d5c0240024020030d002005102721040c010b200128020020032005102821040b2004450d1f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5c20034101742205200420042005491b22054100480d5c0240024020030d002005102721040c010b200128020020032005102821040b2004450d2020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a200110540c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b20034101742205200420042005491b22054100480d5b0240024020030d002005102721040c010b200128020020032005102821040b2004450d2020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5b20034101742205200420042005491b22054100480d5b0240024020030d002005102721040c010b200128020020032005102821040b2004450d2120012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41003a00002000280204210c20022000410c6a2802002200360208200241086a200110302000450d0e200c200041f8006c6a210d200141046a210b034002400240200b2802002203200628020022006b4120490d00200128020021030c010b200041206a22042000490d5c20034101742200200420042000491b22004100480d5c0240024020030d002000102721030c010b200128020020032000102821030b2003450d2320012003360200200b2000360200200628020021000b2006200041206a360200200320006a220041186a200c412c6a290000370000200041106a200c41246a290000370000200041086a200c411c6a2900003700002000200c290014370000200c2001105402400240200b2802002203200628020022006b4120490d00200128020021030c010b200041206a22042000490d5c20034101742200200420042000491b22004100480d5c0240024020030d002000102721030c010b200128020020032000102821030b2003450d2420012003360200200b2000360200200628020021000b2006200041206a360200200320006a220041186a200c41cc006a290000370000200041106a200c41c4006a290000370000200041086a200c413c6a2900003700002000200c29003437000002400240200b2802002203200628020022006b4120490d00200128020021030c010b200041206a22042000490d5c20034101742200200420042000491b22004100480d5c0240024020030d002000102721030c010b200128020020032000102821030b2003450d2520012003360200200b2000360200200628020021000b2006200041206a360200200320006a220041186a200c41ec006a290000370000200041106a200c41e4006a290000370000200041086a200c41dc006a2900003700002000200c290054370000200c28020821042002200c2802102200360208200241086a2001103002402000450d00200041246c21090340200241086a2004104f2002280208210a02400240200b2802002205200628020022006b20022802102203490d00200128020021050c010b200020036a22082000490d5e20054101742200200820082000491b22004100480d5e0240024020050d002000102721050c010b200128020020052000102821050b2005450d2820012005360200200b2000360200200628020021000b2006200020036a360200200520006a200a200310ce041a0240200228020c450d00200a10290b200441246a21042009415c6a22090d000b0b200c41f8006a220c200d470d000c0f0b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d5a20004101742204200320032004491b22044100480d5a0240024020000d002004102721030c010b200128020020002004102821030b2003450d2520012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41043a00000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5920034101742205200420042005491b22054100480d590240024020030d002005102721040c010b200128020020032005102821040b2004450d2520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000280208417f6a220341014b0d0c02400240024020030e020001000b200241003a001c02400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d5b20034101742205200420042005491b22044100480d5b0240024020030d002004102721050c010b200128020020032004102821050b2005450d2820012005360200200141046a2004360200200141086a28020021030b200041306a2104200141086a200341016a360200200520036a41003a00002000410c6a20011051200241186a21000c010b200241013a001c02400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d5a20034101742205200420042005491b22044100480d5a0240024020030d002004102721050c010b200128020020032004102821050b2005450d2820012005360200200141046a2004360200200141086a28020021030b200041c0006a2104200141086a200341016a360200200520036a41013a00002000410c6a200110512002200041306a36021c2002411c6a20011059200241086a21000b200020043602002000200110590c0c0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d582003410174220a20052005200a491b220a4100480d580240024020030d00200a102721050c010b20012802002003200a102821050b2005450d2720012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41063a000020002d0008417f6a2203410c4b0d0b024002400240024002400240024002400240024002400240024020030e0d000102030405060708090a0b0c000b200241003a001c02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d642003410174220a20052005200a491b220a4100480d640240024020030d00200a102721050c010b20012802002003200a102821050b2005450d3420012005360200200141046a200a360200200141086a28020021030b200141086a200341016a360200200520036a41003a00002000410c6a200110512002200041306a360208200241086a2001105920002d0009220041024b0d1702400240024020000e03000102000b200241003a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d6620004101742205200320032005491b22054100480d660240024020000d002005102721030c010b200128020020002005102821030b2003450d3720012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41003a00000c190b200241013a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d6520004101742205200320032005491b22054100480d650240024020000d002005102721030c010b200128020020002005102821030b2003450d3720012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41013a00000c180b200241023a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d6420004101742205200320032005491b22054100480d640240024020000d002005102721030c010b200128020020002005102821030b2003450d3720012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c170b200241013a001c02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6320034101742205200420042005491b22054100480d630240024020030d002005102721040c010b200128020020032005102821040b2004450d3720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002002200041106a360208200241086a200110590c160b200241023a001c02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6220034101742205200420042005491b22054100480d620240024020030d002005102721040c010b200128020020032005102821040b2004450d3720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200041106a360208200241086a200110590c150b200241033a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d6120004101742205200320032005491b22054100480d610240024020000d002005102721030c010b200128020020002005102821030b2003450d3720012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41033a00000c140b200241043a001c02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6020034101742205200420042005491b22054100480d600240024020030d002005102721040c010b200128020020032005102821040b2004450d3720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a0000200041206a200110302002200041106a360208200241086a200110590c130b200241053a001c02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5f20034101742205200420042005491b22054100480d5f0240024020030d002005102721040c010b200128020020032005102821040b2004450d3720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200028020c21032002200041146a2802002200360208200241086a200110302000450d12200041246c21000340200320011051200341246a21032000415c6a22000d000c130b0b200241063a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5e20004101742205200320032005491b22054100480d5e0240024020000d002005102721030c010b200128020020002005102821030b2003450d3720012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41063a00000c110b200241073a001c02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5d2003410174220a20052005200a491b220a4100480d5d0240024020030d00200a102721050c010b20012802002003200a102821050b2005450d3720012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41073a000020002d0009220041024b0d1002400240024020000e03000102000b200241003a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5f20004101742205200320032005491b22054100480d5f0240024020000d002005102721030c010b200128020020002005102821030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41003a00000c120b200241013a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5e20004101742205200320032005491b22054100480d5e0240024020000d002005102721030c010b200128020020002005102821030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41013a00000c110b200241023a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5d20004101742205200320032005491b22054100480d5d0240024020000d002005102721030c010b200128020020002005102821030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c100b200241083a001c02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5c20034101742205200420042005491b22054100480d5c0240024020030d002005102721040c010b200128020020032005102821040b2004450d3a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a00002000410c6a200110510c0f0b200241093a001c02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5b20034101742205200420042005491b22054100480d5b0240024020030d002005102721040c010b200128020020032005102821040b2004450d3a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a200110300c0e0b2002410a3a001c02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5a20004101742205200320032005491b22054100480d5a0240024020000d002005102721030c010b200128020020002005102821030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a410a3a00000c0d0b2002410b3a001c02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5920034101742205200420042005491b22054100480d590240024020030d002005102721040c010b200128020020032005102821040b2004450d3a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000410c6a200110300c0c0b2002410c3a001c02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d582003410174220a20052005200a491b220a4100480d580240024020030d00200a102721050c010b20012802002003200a102821050b2005450d3a20012005360200200141046a200a360200200141086a28020021030b200141086a220b200341016a360200200520036a410c3a0000200028020c21032002200041146a2802002200360208200241086a200110302000450d0b2000410574210a200141046a210803400240024020062802002205200428020022006b4120490d00200128020021050c010b200041206a22092000490d5920054101742200200920092000491b22004100480d590240024020050d002000102721050c010b200128020020052000102821050b2005450d3c2001200536020020082000360200200b28020021000b2004200041206a360200200520006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2103200a41606a220a0d000c0c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5720034101742205200420042005491b22054100480d570240024020030d002005102721040c010b200128020020032005102821040b2004450d3b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41073a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5720034101742205200420042005491b22054100480d570240024020030d002005102721040c010b200128020020032005102821040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5720044101742203200520052003491b22034100480d570240024020040d002003102721040c010b200128020020042003102821040b2004450d3d20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041106a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5720044101742203200520052003491b22034100480d570240024020040d002003102721040c010b200128020020042003102821040b2004450d3e20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041306a220441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002000280204210620022000410c6a2802002200360208200241086a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d5720044101742203200520052003491b22034100480d570240024020040d002003102721040c010b200128020020042003102821040b2004450d3f20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010ce041a0c0a0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d562003410174220a20052005200a491b220a4100480d560240024020030d00200a102721050c010b20012802002003200a102821050b2005450d3f20012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41083a0000200041086a22032d0000417f6a220541104b0d090240024002400240024002400240024002400240024002400240024002400240024020050e11000102030405060708090a0b0c0d0e0f10000b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6620034101742205200420042005491b22054100480d660240024020030d002005102721040c010b200128020020032005102821040b2004450d5020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020c200110322002200041106a360208200241086a200110590c190b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6520034101742205200420042005491b22054100480d650240024020030d002005102721040c010b200128020020032005102821040b2004450d5020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110300c180b02400240200628020020042802002205460d00200128020021060c010b200541016a22062005490d642005410174220a20062006200a491b220a4100480d640240024020050d00200a102721060c010b20012802002005200a102821060b2006450d5020012006360200200141046a200a360200200141086a28020021050b200141086a220a200541016a360200200620056a41023a00002000410c6a2001103020032d00012105200341026a2d0000210602400240200141046a280200200a2802002200460d00200128020021030c010b200041016a22032000490d642000410174220a20032003200a491b220a4100480d640240024020000d00200a102721030c010b20012802002000200a102821030b2003450d5120012003360200200141046a200a360200200141086a28020021000b2004200041016a360200200320006a20054100474107742006723a00000c170b02400240200628020020042802002205460d00200128020021060c010b200541016a22062005490d632005410174220a20062006200a491b220a4100480d630240024020050d00200a102721060c010b20012802002005200a102821060b2006450d5120012006360200200141046a200a360200200141086a28020021050b200141086a220a200541016a360200200620056a41033a00002000410c6a2001103020032d00012105200341026a2d0000210602400240200141046a280200200a2802002200460d00200128020021030c010b200041016a22032000490d632000410174220a20032003200a491b220a4100480d630240024020000d00200a102721030c010b20012802002000200a102821030b2003450d5220012003360200200141046a200a360200200141086a28020021000b2004200041016a360200200320006a20054100474107742006723a00000c160b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d622003410174220a20052005200a491b220a4100480d620240024020030d00200a102721050c010b20012802002003200a102821050b2005450d5220012005360200200141046a200a360200200141086a28020021030b200141086a220a200341016a360200200520036a41043a0000200028020c2001103220002d0009210902400240200141046a280200200a2802002203460d00200128020021050c010b200341016a22052003490d622003410174220a20052005200a491b220a4100480d620240024020030d00200a102721050c010b20012802002003200a102821050b2005450d5320012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a20093a0000200029031021070240024020062802002205200428020022036b4108490d00200128020021050c010b200341086a220a2003490d6220054101742203200a200a2003491b22034100480d620240024020050d002003102721050c010b200128020020052003102821050b2005450d5420012005360200200141046a2003360200200141086a28020021030b2004200341086a360200200520036a2007370000200029031821070240024020062802002203200428020022006b4108490d00200128020021030c010b200041086a22052000490d6220034101742200200520052000491b22004100480d620240024020030d002000102721030c010b200128020020032000102821030b2003450d5520012003360200200141046a2000360200200141086a28020021000b2004200041086a360200200320006a20073700000c150b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d612003410174220a20052005200a491b220a4100480d610240024020030d00200a102721050c010b20012802002003200a102821050b2005450d5520012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41053a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d6120034101742200200620062000491b22004100480d610240024020030d002000102721030c010b200128020020032000102821030b2003450d5620012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c140b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6020034101742205200420042005491b22054100480d600240024020030d002005102721040c010b200128020020032005102821040b2004450d5620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a0000200028020c200110320c130b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5f20034101742205200420042005491b22054100480d5f0240024020030d002005102721040c010b200128020020032005102821040b2004450d5620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200028020c200110320c120b02400240200628020020042802002205460d002001280200210a0c010b200541016a220a2005490d5e20054101742209200a200a2009491b22094100480d5e0240024020050d0020091027210a0c010b2001280200200520091028210a0b200a450d562001200a360200200141046a2009360200200141086a28020021050b2004200541016a360200200a20056a41083a0000024002402006280200220a200428020022056b4120490d002001280200210a0c010b200541206a22092005490d5e200a4101742205200920092005491b22054100480d5e02400240200a0d0020051027210a0c010b2001280200200a20051028210a0b200a450d572001200a360200200141046a2005360200200141086a28020021050b2004200541206a360200200a20056a220541186a200341196a290000370000200541106a200341116a290000370000200541086a200341096a29000037000020052003290001370000200029033021070240024020062802002205200428020022036b4108490d00200128020021050c010b200341086a220a2003490d5e20054101742203200a200a2003491b22034100480d5e0240024020050d002003102721050c010b200128020020052003102821050b2005450d5820012005360200200141046a2003360200200141086a28020021030b2004200341086a360200200520036a2007370000200029033821070240024020062802002203200428020022006b4108490d00200128020021030c010b200041086a22052000490d5e20034101742200200520052000491b22004100480d5e0240024020030d002000102721030c010b200128020020032000102821030b2003450d5920012003360200200141046a2000360200200141086a28020021000b2004200041086a360200200320006a20073700000c110b02400240200628020020042802002200460d00200128020021050c010b200041016a22052000490d5d2000410174220a20052005200a491b220a4100480d5d0240024020000d00200a102721050c010b20012802002000200a102821050b2005450d5920012005360200200141046a200a360200200141086a28020021000b2004200041016a360200200520006a41093a00000240024020062802002205200428020022006b4120490d00200128020021050c010b200041206a22062000490d5d20054101742200200620062000491b22004100480d5d0240024020050d002000102721050c010b200128020020052000102821050b2005450d5a20012005360200200141046a2000360200200141086a28020021000b2004200041206a360200200520006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c100b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5c20034101742205200420042005491b22054100480d5c0240024020030d002005102721040c010b200128020020032005102821040b2004450d5a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a00002000410c6a200110300c0f0b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5b20034101742205200420042005491b22054100480d5b0240024020030d002005102721040c010b200128020020032005102821040b2004450d5a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a0000200041186a200110542000410c6a20011030200041106a200110300c0e0b02400240200628020020042802002200460d00200128020021050c010b200041016a22052000490d9a012000410174220a20052005200a491b220a4100480d9a010240024020000d00200a102721050c010b20012802002000200a102821050b2005450d5b20012005360200200141046a200a360200200141086a28020021000b2004200041016a360200200520006a410c3a00000240024020062802002205200428020022006b4120490d00200128020021050c010b200041206a22062000490d9a0120054101742200200620062000491b22004100480d9a010240024020050d002000102721050c010b200128020020052000102821050b2005450d5c20012005360200200141046a2000360200200141086a28020021000b2004200041206a360200200520006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c0d0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d990120004101742205200320032005491b22054100480d99010240024020000d002005102721030c010b200128020020002005102821030b2003450d5c20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a410d3a00000c0c0b02400240200628020020042802002200460d00200128020021050c010b200041016a22052000490d98012000410174220a20052005200a491b220a4100480d98010240024020000d00200a102721050c010b20012802002000200a102821050b2005450d5c20012005360200200141046a200a360200200141086a28020021000b2004200041016a360200200520006a410e3a00000240024020062802002205200428020022006b4120490d00200128020021050c010b200041206a22062000490d980120054101742200200620062000491b22004100480d98010240024020050d002000102721050c010b200128020020052000102821050b2005450d5d20012005360200200141046a2000360200200141086a28020021000b2004200041206a360200200520006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a290000370000200020032900013700000c0b0b02400240200628020020042802002200460d00200128020021050c010b200041016a22052000490d97012000410174220a20052005200a491b220a4100480d97010240024020000d00200a102721050c010b20012802002000200a102821050b2005450d5d20012005360200200141046a200a360200200141086a28020021000b2004200041016a360200200520006a410f3a00000240024020062802002205200428020022006b4120490d00200128020021050c010b200041206a220a2000490d970120054101742200200a200a2000491b22004100480d97010240024020050d002000102721050c010b200128020020052000102821050b2005450d5e20012005360200200141046a2000360200200141086a28020021000b2004200041206a360200200520006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a2900003700002000200329000137000020032d0021220041054b0d0a024002400240024002400240024020000e06000102030405000b410021030c050b410121030c040b410221030c030b410321030c020b410421030c010b410521030b200220033a001c02400240200628020020042802002200460d00200128020021050c010b200041016a22052000490d970120004101742206200520052006491b22064100480d97010240024020000d002006102721050c010b200128020020002006102821050b2005450d5f20012005360200200141046a2006360200200141086a28020021000b2004200041016a360200200520006a20033a00000c0a0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d960120004101742205200320032005491b22054100480d96010240024020000d002005102721030c010b200128020020002005102821030b2003450d5f20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41103a00000c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d950120034101742205200420042005491b22054100480d95010240024020030d002005102721040c010b200128020020032005102821040b2004450d5f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041046a20011092020c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d940120034101742205200420042005491b22054100480d94010240024020030d002005102721040c010b200128020020032005102821040b2004450d5f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a0000200041046a20011092020c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d930120034101742205200420042005491b22054100480d93010240024020030d002005102721040c010b200128020020032005102821040b2004450d5f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000280208417f6a220341094b0d06024002400240024002400240024002400240024020030e0a00010203040506070809000b200241003a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9c0120034101742205200420042005491b22054100480d9c010240024020030d002005102721040c010b200128020020032005102821040b2004450d6920012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41003a0000200028020c21042002200041146a280200220a360208200241086a200110300240200a450d00200141046a2109034002400240200928020020062802002203460d00200128020021050c010b200341016a22052003490d9e012003410174220b20052005200b491b220b4100480d9e010240024020030d00200b102721050c010b20012802002003200b102821050b2005450d6c200120053602002009200b360200200628020021030b2006200341016a360200200520036a20042d00003a0000200441016a2104200a417f6a220a0d000b0b200041186a20011030200028021c210402400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22052000490d9c0120034101742200200520052000491b22004100480d9c010240024020030d002000102721030c010b200128020020032000102821030b2003450d6b20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0f0b200241013a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9b0120034101742205200420042005491b22054100480d9b010240024020030d002005102721040c010b200128020020032005102821040b2004450d6b20012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41013a0000200028020c21042002200041146a280200220a360208200241086a200110300240200a450d00200141046a2109034002400240200928020020062802002203460d00200128020021050c010b200341016a22052003490d9d012003410174220b20052005200b491b220b4100480d9d010240024020030d00200b102721050c010b20012802002003200b102821050b2005450d6e200120053602002009200b360200200628020021030b2006200341016a360200200520036a20042d00003a0000200441016a2104200a417f6a220a0d000b0b200041186a20011030200028021c210402400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22052000490d9b0120034101742200200520052000491b22004100480d9b010240024020030d002000102721030c010b200128020020032000102821030b2003450d6d20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0e0b200241023a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9a0120034101742205200420042005491b22054100480d9a010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a20011030200041106a20011051200041346a20011030200041386a200110300c0d0b200241033a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d990120034101742205200420042005491b22054100480d99010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002000410c6a200110300c0c0b200141086a2802002103200241043a001c024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d980120034101742205200420042005491b22054100480d98010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a200110300c0b0b200241053a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d970120034101742205200420042005491b22054100480d97010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000410c6a200110512002200041386a360208200241086a20011059200041306a200110300c0a0b200241063a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d960120034101742205200420042005491b22054100480d96010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a00002000410c6a200110300c090b200241073a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d950120034101742205200420042005491b22054100480d95010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a00002000410c6a200110510c080b200141046a2802002104200241083a001c024002402004200141086a2802002203460d00200128020021040c010b200341016a22042003490d940120034101742205200420042005491b22054100480d94010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a0000200041106a200110540c070b200241093a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d930120034101742205200420042005491b22054100480d93010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041106a200110540c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d920120034101742205200420042005491b22054100480d92010240024020030d002005102721040c010b200128020020032005102821040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410c3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d920120034101742205200420042005491b22054100480d92010240024020030d002005102721040c010b200128020020032005102821040b2004450d6e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a200110540c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d910120034101742205200420042005491b22054100480d91010240024020030d002005102721040c010b200128020020032005102821040b2004450d6e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410d3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d910120034101742205200420042005491b22054100480d91010240024020030d002005102721040c010b200128020020032005102821040b2004450d6f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210620022000410c6a2802002200360208200241086a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d910120044101742203200520052003491b22034100480d91010240024020040d002003102721040c010b200128020020042003102821040b2004450d7020012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010ce041a0c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d900120034101742205200420042005491b22054100480d90010240024020030d002005102721040c010b200128020020032005102821040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410e3a00002000280208417f6a220341024b0d0302400240024020030e03000102000b200241003a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d920120034101742205200420042005491b22054100480d92010240024020030d002005102721040c010b200128020020032005102821040b2004450d7320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002002200041306a360208200241086a200110592000410c6a200110510c050b200241013a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d910120034101742205200420042005491b22054100480d91010240024020030d002005102721040c010b200128020020032005102821040b2004450d7320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110300c040b200241023a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d900120034101742205200420042005491b22054100480d90010240024020030d002005102721040c010b200128020020032005102821040b2004450d7320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a200110300c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d8f0120034101742205200420042005491b22054100480d8f010240024020030d002005102721040c010b200128020020032005102821040b2004450d7320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410f3a0000200041086a22032d0000417f6a220441054b0d0202400240024002400240024020040e06000102030405000b200241003a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d940120034101742205200420042005491b22054100480d94010240024020030d002005102721040c010b200128020020032005102821040b2004450d7920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041106a20011093020c070b200241013a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d930120034101742205200420042005491b22054100480d93010240024020030d002005102721040c010b200128020020032005102821040b2004450d7920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a20011054200028020c21062002200041146a2802002200360208200241086a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d930120044101742203200520052003491b22034100480d93010240024020040d002003102721040c010b200128020020042003102821040b2004450d7a20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010ce041a0c060b200241023a001c02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d920120034101742205200420042005491b22054100480d92010240024020030d002005102721040c010b200128020020032005102821040b2004450d7a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000410c6a200110512002200041c0006a360208200241086a20011059200041d0006a20011054200028023021062002200041386a2802002200360208200241086a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d920120044101742203200520052003491b22034100480d92010240024020040d002003102721040c010b200128020020042003102821040b2004450d7b20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010ce041a0c050b200241033a001c02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d910120044101742206200520052006491b22064100480d91010240024020040d002006102721050c010b200128020020042006102821050b2005450d7b20012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41033a00002002200041386a360208200241086a20011059200041c8006a2001105402400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d910120054101742204200620062004491b22044100480d91010240024020050d002004102721050c010b200128020020052004102821050b2005450d7c20012005360200200141046a2004360200200141086a28020021040b200141086a2206200441206a360200200520046a220441186a200341196a290000370000200441106a200341116a290000370000200441086a200341096a29000037000020042003290001370000200028022c21052002200041346a2802002200360208200241086a2001103002400240200141046a2802002204200628020022036b2000490d00200128020021040c010b200320006a22062003490d910120044101742203200620062003491b22034100480d91010240024020040d002003102721040c010b200128020020042003102821040b2004450d7d20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2005200010ce041a0c040b200141086a2802002100200241043a001c024002402000200141046a280200460d00200128020021040c010b200041016a22042000490d900120004101742205200420042005491b22054100480d90010240024020000d002005102721040c010b200128020020002005102821040b2004450d7d20012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41043a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d900120044101742200200520052000491b22004100480d90010240024020040d002000102721040c010b200128020020042000102821040b2004450d7e20012004360200200141046a2000360200200141086a28020021000b200141086a2205200041206a360200200420006a220041186a200341196a290000370000200041106a200341116a290000370000200041086a200341096a29000037000020002003290001370000024020032d00214101460d00200241003a001c02400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d910120004101742204200320032004491b22044100480d91010240024020000d002004102721030c010b200128020020002004102821030b2003450d800120012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c040b200241013a001c02400240200141046a28020020052802002200460d00200128020021040c010b200041016a22042000490d900120004101742205200420042005491b22054100480d90010240024020000d002005102721040c010b200128020020002005102821040b2004450d800120012004360200200141046a2005360200200141086a28020021000b200141086a2205200041016a360200200420006a41013a000002400240200141046a2802002204200528020022006b4120490d00200128020021040c010b200041206a22052000490d900120044101742200200520052000491b22004100480d90010240024020040d002000102721040c010b200128020020042000102821040b2004450d810120012004360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200420006a220041186a200341226a220341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200020032900003700000c030b200241053a001c02400240200141046a280200200141086a2802002204460d00200128020021050c010b200441016a22052004490d8f0120044101742206200520052006491b22064100480d8f010240024020040d002006102721050c010b200128020020042006102821050b2005450d810120012005360200200141046a2006360200200141086a28020021040b200141086a2206200441016a360200200520046a41053a000002400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d8f0120054101742204200620062004491b22044100480d8f010240024020050d002004102721050c010b200128020020052004102821050b2005450d820120012005360200200141046a2004360200200141086a28020021040b200141086a2206200441206a360200200520046a220441186a200341196a290000370000200441106a200341116a290000370000200441086a200341096a2900003700002004200329000137000002400240200141046a2802002205200628020022046b4120490d00200128020021050c010b200441206a22062004490d8f0120054101742204200620062004491b22044100480d8f010240024020050d002004102721050c010b200128020020052004102821050b2005450d830120012005360200200141046a2004360200200141086a28020021040b200141086a2206200441206a360200200520046a220441186a200341216a220341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200041e0006a29030021072000290358210e02400240200141046a2802002204200628020022036b4110490d00200128020021040c010b200341106a22052003490d8f0120044101742203200520052003491b22034100480d8f010240024020040d002003102721040c010b200128020020042003102821040b2004450d840120012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a220320073700082003200e370000200028024c21032002200041d4006a2802002200360208200241086a200110302000450d0220004105742106200141046a210a034002400240200a2802002204200528020022006b4120490d00200128020021040c010b200041206a22092000490d900120044101742200200920092000491b22004100480d90010240024020040d002000102721040c010b200128020020042000102821040b2004450d860120012004360200200a2000360200200528020021000b2005200041206a360200200420006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2103200641606a22060d000c030b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d8e0120034101742205200420042005491b22054100480d8e010240024020030d002005102721040c010b200128020020032005102821040b2004450d850120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41103a00002000280204417f6a220341014b0d010240024020030e020001000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d8f0120034101742205200420042005491b22054100480d8f010240024020030d002005102721040c010b200128020020032005102821040b2004450d870120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208200110320c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d8e0120034101742205200420042005491b22054100480d8e010240024020030d002005102721040c010b200128020020032005102821040b2004450d870120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041086a200110510c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d8d0120034101742205200420042005491b22054100480d8d010240024020030d002005102721040c010b200128020020032005102821040b2004450d870120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41113a0000200241003a001c02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d8d0120034101742205200420042005491b22054100480d8d010240024020030d002005102721040c010b200128020020032005102821040b2004450d880120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000290308210702400240200141046a2802002204200528020022036b4108490d00200128020021040c010b200341086a22052003490d8d0120044101742203200520052003491b22034100480d8d010240024020040d002003102721040c010b200128020020042003102821040b2004450d890120012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a2007370000200041106a20011061200041286a280200210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d8d0120044101742203200520052003491b22034100480d8d010240024020040d002003102721040c010b200128020020042003102821040b2004450d8a0120012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a200636000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d8d0120044101742203200520052003491b22034100480d8d010240024020040d002003102721040c010b200128020020042003102821040b2004450d8b0120012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a2000412c6a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200028025021062002200041d8006a2802002200360208200241086a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d8d0120044101742203200520052003491b22034100480d8d010240024020040d002003102721040c010b200128020020042003102821040b2004450d8c0120012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2006200010ce041a0b200241206a24000f0b20054101102a000b20044101102a000b20054101102a000b20034101102a000b20054101102a000b20004101102a000b20054101102a000b20034101102a000b20044101102a000b20054101102a000b20054101102a000b20054101102a000b20004101102a000b20044101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20004101102a000b20004101102a000b20004101102a000b20004101102a000b20044101102a000b20054101102a000b20044101102a000b20044101102a000b200a4101102a000b200a4101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b200a4101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b200a4101102a000b20004101102a000b20054101102a000b20054101102a000b20034101102a000b20034101102a000b20034101102a000b200a4101102a000b20054101102a000b20054101102a000b200a4101102a000b200a4101102a000b200a4101102a000b200a4101102a000b200a4101102a000b200a4101102a000b20034101102a000b20004101102a000b200a4101102a000b20004101102a000b20054101102a000b20054101102a000b20094101102a000b20054101102a000b20034101102a000b20004101102a000b200a4101102a000b20004101102a000b20054101102a000b20054101102a000b102b000b200a4101102a000b20004101102a000b20054101102a000b200a4101102a000b20004101102a000b200a4101102a000b20004101102a000b20064101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b200b4101102a000b20004101102a000b20054101102a000b200b4101102a000b20004101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20034101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20034101102a000b20054101102a000b20034101102a000b20064101102a000b20044101102a000b20034101102a000b20054101102a000b20004101102a000b20044101102a000b20054101102a000b20004101102a000b20064101102a000b20044101102a000b20044101102a000b20034101102a000b20004101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20034101102a000b20034101102a000b20034101102a000b20034101102a000b102b000bae0401067f230041106b2202240020024100360208200242013703002000280200210320022000280208220036020c2002410c6a200210300240024002400240024020000d002002280208210020022802042104200228020021050c010b200041b0016c21062002280204210420022802082100034020034188016a280200210702400240200420006b4104490d00200228020021040c010b200041046a22052000490d0520044101742200200520052000491b22004100480d050240024020040d002000102721040c010b200228020020042000102821040b2004450d032002200036020420022004360200200228020821000b2002200041046a360208200420006a20073600002003200210320240024020022802042204200228020822006b4120490d00200228020021050c010b200041206a22072000490d0520044101742200200720072000491b22074100480d050240024020040d002007102721050c010b200228020020042007102821050b2005450d04200220073602042002200536020020022802082100200721040b200520006a220741086a20034194016a290000370000200741106a2003419c016a290000370000200741186a200341a4016a2900003700002002200041206a220036020820072003418c016a290000370000200341b0016a2103200641d07e6a22060d000b0b2001280200200128020420052000100302402004450d00200510290b200241106a24000f0b20004101102a000b20074101102a000b102b000b840403057f027e027f230041106b2202240020024100360208200242013703002000280200210320022000280208220036020c2002410c6a200210300240024020000d002002280208210420022802042100200228020021050c010b2003200041306c6a21062002280200210520022802042100200228020821040340200341086a29030021072003290300210802400240024002400240200020046b4110490d00200441106a21090c010b200441106a22092004490d012000410174220a20092009200a491b220a4100480d010240024020000d00200a102721050c010b20052000200a102821050b2005450d02200a21000b200520046a22042007370008200420083700000240200020096b4120490d00200941206a21040c030b200941206a22042009490d002000410174220a20042004200a491b220a4100480d000240024020000d00200a102721050c010b20052000200a102821050b02402005450d00200a21000c030b200a4101102a000b102b000b200a4101102a000b200520096a220941186a200341286a290000370000200941106a200341206a290000370000200941086a200341186a2900003700002009200341106a290000370000200341306a22032006470d000b2002200036020420022004360208200220053602000b2001280200200128020420052004100302402000450d00200510290b200241106a24000b990501077f230041106b2202240020024100360208200242013703002000280200210320022000280208220036020c2002410c6a2002103002400240024002400240024020000d002002280208210420022802042105200228020021000c010b200041216c210603400240024020032d00004101460d00024002402002280204220520022802082207460d00200228020021000c010b200741016a22002007490d0820074101742205200020002005491b22054100480d080240024020070d002005102721000c010b200228020020072005102821000b2000450d0520022005360204200220003602000b2002200741016a2204360208200020076a41003a00000c010b024002402002280204220520022802082207460d00200228020021000c010b200741016a22002007490d0720074101742205200020002005491b22054100480d070240024020070d002005102721000c010b200228020020072005102821000b2000450d0520022005360204200220003602000b2002200741016a2208360208200020076a41013a000002400240200520086b4120490d00200741216a21040c010b200841206a22042008490d0720054101742207200420042007491b22074100480d070240024020050d002007102721000c010b200020052007102821000b2000450d062002200736020420022000360200200721050b200020086a220741086a200341016a220841086a290000370000200741106a200841106a290000370000200741186a200841186a29000037000020022004360208200720082900003700000b200341216a21032006415f6a22060d000b0b2001280200200128020420002004100302402005450d00200010290b200241106a24000f0b20054101102a000b20054101102a000b20074101102a000b102b000b9203010a7f200041086a220228020021034100210420024100360200024002402003450d004100210541002106410021044100210702400340024002402004450d00200741057421080340200720034f0d062001200028020022096b2008460d02200920086a220a2001412010d004450d020240200620076a220b20034f0d00200920056a20086a2209200a290000370000200941186a200a41186a290000370000200941106a200a41106a290000370000200941086a200a41086a290000370000200841206a2108200741016a22072003490d010c050b0b419481c000200b20031037000b200028020020074105746a21080340200720034f0d0520012008460d0120082001412010d004450d01200841206a2108200741016a22072003490d000b410021040c030b200541606a21052006417f6a2106200441016a2104200741016a22072003490d000b0b2004450d00200320074d0d00200028020020074105746a220820044105746b2008200320076b41057410cf041a0b2002200320046b3602000f0b41b880c000200720031037000b6c01017f230041306b2203240020032002360204200320013602002003411c6a41023602002003412c6a41013602002003420237020c200341a8d6c500360208200341013602242003200341206a360218200320033602282003200341046a360220200341086a20001057000bae0a03027f017e1a7f230041f0006b22022400024002400240024002400240024020012802082203ad42f8007e2204422088a70d002004a72205417f4c0d00200128020021060240024020050d00410821070c010b200510272207450d020b0240024020030d00410021080c010b2006200341f8006c6a2109410021082007210a0340200241c0006a41086a220b2006411c6a290000370300200241c0006a41106a220c200641246a290000370300200241c0006a41186a220d2006412c6a290000370300200241206a41086a220e2006413c6a29000037030020062900142104200241206a41106a220f200641c4006a290000370300200241206a41186a2210200641cc006a290000370300200241106a2211200641e4006a290000370300200241086a2212200641dc006a290000370300200241186a2213200641ec006a29000037030020022004370340200220062900343703202002200629005437030020062802102214ad42247e2204422088a70d022004a72201417f4c0d0220062903002104200628020821150240024020010d00410421160c010b200110272216450d050b0240024020140d00410021170c010b201441246c211841002119410021170340024002400240024002400240201520196a22012d00000e050001020304000b2002200141146a2900003703602002200141196a290000370065200141056a2f0000200141076a2d000041107472211a200141106a280000211b2001410c6a2800002105200141086a280000211c200141016a280000211d4100211e0c040b200141106a2802002205417f4c0d08200141086a280200211b200141016a280000211d4101211e4101211c02402005450d0020051027221c450d0c0b201c201b200510ce041a2005211b0c030b200141106a2802002205417f4c0d07200141086a280200211e200141016a280000211d0240024020050d004101211c0c010b20051027221c450d0c0b201c201e200510ce041a4102211e2005211b0c020b200141106a2802002205417f4c0d06200141086a280200211e200141016a280000211d0240024020050d004101211c0c010b20051027221c450d0c0b201c201e200510ce041a4103211e2005211b0c010b2001410c6a280200221c417f4c0d05200141046a280200210102400240201c0d00410121050c010b201c10272205450d0c0b20052001201c10ce042201410876211a2001411874211d4104211e201c21050b201620196a2201201e3a0000200141076a201a4110763a0000200141056a201a3b0000200141106a201b3600002001410c6a2005360000200141086a201c360000200141016a201d360000200141146a20022903603702002001411c6a200241e0006a41086a290300370200201741016a21172018201941246a2219470d000b0b200a2016360208200a410c6a2014360200200a41106a2017360200200a2002290340370214200a411c6a200b290300370200200a2004370300200a2002290320370234200a41246a200c290300370200200a412c6a200d290300370200200a413c6a200e290300370200200a41c4006a200f290300370200200a41cc006a2010290300370200200a41ec006a2013290300370200200a41e4006a2011290300370200200a41dc006a2012290300370200200a2002290300370254200841016a2108200a41f8006a210a200641f8006a22062009470d000b0b200020083602082000200336020420002007360200200241f0006a24000f0b1039000b20054108102a000b20014104102a000b20054101102a000b20054101102a000b20054101102a000b201c4101102a000b0500102b000b900201077f024020002802082201200028020c460d0003402000200141306a36020820012d00284102460d01200141246a2802002102200141206a2802002103200141146a2802002104200128021c2105200128021021060240200141186a2802002201450d002001410c6c21072006210103400240200141046a280200450d00200128020010290b2001410c6a2101200741746a22070d000b0b02402004450d00200610290b02402002450d002002410c6c21072005210103400240200141046a280200450d00200128020010290b2001410c6a2101200741746a22070d000b0b02402003450d00200510290b20002802082201200028020c470d000b0b02402000280204450d00200028020010290b0bbb06020c7f017e230041b0056b2202240020022001102e02400240024002400240024020022802000d00200041003602000c010b0240024020022802042203411c2003411c491b22040d00410821050c010b20044190016c220610272205450d020b02402003450d0020024198036a41047221074100210841002106410021090340200241003a00a004200241a0046a2001280200220a2001280204220b410047220c10ce041a200b200c490d042001200b200c6b3602042001200a200c6a36020002400240024002400240200b450d0020022d00a004220b41014b0d000240200b0e020400040b200241a0046a2001103c0240024020022802a0044112460d0020024198036a200241a0046a41880110ce041a200241003602ac05200241ac056a2001280200220a2001280204220b4104200b4104491b220c10ce041a2001200b200c6b3602042001200a200c6a360200200b41034b0d0120024198036a103d0b200241a0046a20024194026a41840110ce041a0c010b20022802ac05210d200228029803210c20024194026a200741840110ce041a200241a0046a20024194026a41840110ce041a200c4112470d010b200241a0046a20024190016a41840110ce041a0c010b20024190016a200241a0046a41840110ce041a200241a0046a20024190016a41840110ce041a200c4113470d020b2000410036020002402009450d00200521010340024020012802004112460d002001103d0b20014190016a2101200641f07e6a22060d000b0b2004450d04200510290c040b200241a0046a20024190016a41840110ce041a4112210c0b200941016a210b2002410c6a200241a0046a41840110ce041a024020092004470d002008200b200b2008491b2204ad4290017e220e422088a70d07200ea7220a4100480d070240024020090d00200a102721050c010b20052006200a102821050b2005450d060b200520066a2209200c360200200941046a2002410c6a41840110ce041a20094188016a200d360200200841026a210820064190016a2106200b21092003200b470d000b0b2000200436020420002005360200200041086a20033602000b200241b0056a24000f0b20064108102a000b200c200b103e000b200a4108102a000b102b000bfe5e07067f017e047f037e017f037e047f23004190096b22022400200241003a00e803200241e8036a2001280200220320012802042204410047220510ce041a0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020042005490d002001200420056b22063602042001200320056a2205360200024020040d00200041123602000c290b0240024002400240024002400240024002400240024020022d00e803220441114b0d0002400240024002400240024002400240024002400240024002400240024002400240024020040e12000102030405060708090a0b0c0d0e0f1011000b200241003a00f008200241f0086a20052006410047220410ce041a20062004490d1d2001200620046b22033602042001200520046a22053602002006450d4220022d00f008220641054b0d42410121070240024002400240024020060e06480001020304480b200241f8056a2001104420022802f8052204450d4620022902fc052108410221070c470b200242003703f805200241f8056a20052003410820034108491b220410ce041a2001200320046b3602042001200520046a360200200341074d0d4520022903f8052108410321070c460b200241f8056a2001104420022802f8052204450d4420022902fc052108410421070c450b20022001102e2002280200450d43024002402002280204220941aa01200941aa01491b220a0d00410421040c010b200a41186c220510272204450d200b02402009450d0020024180066a210b4100210741002105410021030340200241e8036a200110440240024020022802e803220c450d0020022902ec032108200241f8056a2001104420022802f8050d012008a7450d00200c10290b02402003450d002004210103400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141186a2101200541686a22050d000b0b200a0d450c460b200341016a2106200b350200210d20022903f805210e02402003200a470d002007200620062007491b220aad42187e220f422088a70d3c200fa722104100480d3c0240024020030d002010102721040c010b200420052010102821040b2004450d230b200420056a2203200c360200200341146a200d3e02002003410c6a200e370200200341046a2008370200200741026a2107200541186a21052006210320092006470d000b0b2004450d432009ad422086200aad842108410521070c440b200241086a2001102e2002280208450d4202400240200228020c220941d502200941d502491b220a0d00410421040c010b200a410c6c220510272204450d210b02402009450d004100210741002105410021030340200241f8056a20011044024020022802f805220c0d0002402003450d002004210103400240200141046a280200450d00200128020010290b2001410c6a2101200541746a22050d000b0b200a450d450c440b200341016a210620022902fc05210802402003200a470d002007200620062007491b220aad420c7e220d422088a70d3b200da7220b4100480d3b0240024020030d00200b102721040c010b20042005200b102821040b2004450d240b200420056a2203200c360200200341046a2008370200200741026a21072005410c6a21052006210320092006470d000b0b2004450d422009ad422086200aad842108410621070c430b200241003a00e803200241e8036a20052006410047220410ce041a20062004490d212001200620046b3602042001200520046a360200200041123602000c430b200241003a00e803200241e8036a20052006410047220410ce041a20062004490d212001200620046b3602042001200520046a36020002402006450d0020022d00e8030d00200241106a200110522002290310a7450d002002290318210820004102360200200041086a2008370300200041106a200241f0046a41f80010ce041a0c430b200041123602000c420b200241003a00e803200241e8036a20052006410047220410ce041a20062004490d212001200620046b3602042001200520046a36020002402006450d0020022d00e8030d00200241206a2001102e2002280220450d000240024020022802242209412220094122491b220a0d004108210c0c010b200a41f8006c22041027220c450d240b02402009450d00200241f0046a410c6a210b4100210741002106410021050340200241f0046a2001108e0220022903f004210820022802f8042103200241e8036a200b41ec0010ce041a024020030d0002402005450d00200c20066a2103200c210603400240200641106a2802002204450d0020062802082101200441246c210403400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012004415c6a22040d000b0b200641f8006a210102402006410c6a280200450d00200628020810290b2001210620032001470d000b0b200a450d03200c10290c030b200541016a210420024180086a200241e8036a41ec0010ce041a02402005200a470d002007200420042007491b220aad42f8007e220d422088a70d39200da722104100480d390240024020050d0020101027210c0c010b200c200620101028210c0b200c450d270b200c20066a22052008370300200541086a20033602002005410c6a20024180086a41ec0010ce041a200741026a2107200641f8006a21062004210520092004470d000b0b200c0d120b200041123602000c410b200241003a00e803200241e8036a20052006410047220410ce041a20062004490d232001200620046b3602042001200520046a360200200041123602000c400b200241003a00f008200241f0086a20052006410047220410ce041a20062004490d232001200620046b3602042001200520046a36020002402006450d0020022d00f008220441014b0d0002400240024020040e020001000b200241f8056a2001105020022d00f80522044102460d0220022d00fb05210320022f00f905210720024184066a290200210820024198066a280200210520024190066a290300210d2002418c066a280200210620022902fc05210e200241286a200110532002280228450d0220072003411074722101200241286a41106a290300210f41012103200229033021110c010b200241f8056a2001105020022d00f80522044102460d0120022d00fb05210320022f00f905210720024184066a290200210820024198066a280200210520024190066a290300210d2002418c066a280200210620022902fc05210e200241d8006a200110532002290358a7450d01200241d8006a41106a290300210f20022903602111200241c0006a200110532002290340a7450d0120072003411074722101200241d0006a290300211220022903482113410221030b200020013b000d200041053602002000410f6a20014110763a0000200041c8006a2012370200200041c0006a2013370200200041386a200f370200200041306a2011370200200041186a2008370000200041106a200e3700002000412c6a2005360000200041246a200d370000200041206a20063600002000410c6a20043a0000200041086a2003360200200041d0006a20022903f004370300200041d8006a200241f0046a41086a290300370300200041e0006a200241f0046a41106a290300370300200041e8006a200241f0046a41186a290300370300200041f0006a200241f0046a41206a290300370300200041f8006a20024198056a29030037030020004180016a200241f0046a41306a2903003703000c400b200041123602000c3f0b200241003a00f008200241f0086a20052006410047220410ce041a20062004490d232001200620046b22093602042001200520046a220b3602002006450d3a20022d00f008220a410c4b0d3a41042107024002400240024002400240024002400240024002400240200a0e0d00010245030405060708090a0b000b200241f8056a2001105020022d00f80522044102460d4520022d00fb05210a20022f00f905210920024184066a290200210d20024198066a280200210320024190066a29030021082002418c066a280200210520022902fc05210e200241f0006a200110532002290370a7450d45200241f0006a41106a29030021112002290378210f200241003a00f008200241f0086a2001280200220c20012802042206410047220710ce041a20062007490d2f2001200620076b3602042001200c20076a3602002006450d4520022d00f008220641024b0d452009200a41107472210c410121070c440b20024188016a20011053200229038801a7450d4420024198016a290300210d200229039001210e200220022f01f8053b018008410221074100210c0c430b200241a0016a2001105320022903a001a7450d43200241b0016a290300210d20022903a801210e200220022f01f8053b018008410321074100210c0c420b200241d0016a2001102e20022802d001450d4220022802d4012105200241b8016a2001105320022903b801a7450d42200241c8016a290300210d20022903c001210e200220022f01f8053b018008410521074100210c0c410b200241d8016a2001102e20022802d801450d410240024020022802dc01221441f100201441f100491b22150d00410421040c010b201541246c220510272204450d2d0b02402014450d004120210320024184066a211641002107410021050340200241f8056a20011050024020022d00f805220c4102470d002015450d44200410290c440b200541016a210620022d00fb05210a20022f00f90521092016290200210820022902fc05210d200228029806210b200229039006210e200228028c062110024020052015470d002007200620062007491b2215ad42247e220f422088a70d3c200fa722174100480d3c0240024020050d002017102721040c010b2004200341606a2017102821040b2004450d300b200420036a2205200b360000200541616a220b2009200a41107472220a3b0000200541646a220920083700082009200d370000200541786a200e370000200541746a2010360000200541606a200c3a0000200b41026a200a4110763a0000200741026a2107200341246a21032006210520142006470d000b0b2004450d412014ad4220862015ad84210e200220022f01e8033b0180082004410876210c410621070c400b410721070c3f0b200241003a00f008200241f0086a200b2009410047220410ce041a20092004490d2c2001200920046b3602042001200b20046a3602002009450d3f20022d00f008220641034f0d3f200220022f01f8053b018008410821074200210d4100210c0c3e0b200241f8056a2001105020022d00f80522044102460d3e20024184066a290200210d20022902fc05210e200220022f01e8033b01800820022f00f90520022d00fb0541107472210c2002418c066a280200210520024190066a290300210820024198066a2802002103410921070c3d0b200241e0016a2001102e20022802e001450d3d20022802e4012104200220022f01f8053b0180082004410876210c410a21074200210d0c3c0b410b21070c3b0b200241e8016a2001102e20022802e801450d3b20022802ec012104200220022f01f8053b0180082004410876210c410c21074200210d0c3a0b200241f8056a2001102d20022802f8052204450d3a200220022f01e8033b0180082004410876210c20022902fc05210e410d21070c390b200241003a00f008200241f0086a20052006410047220410ce041a20062004490d272001200620046b22033602042001200520046a220436020002402006450d0020022d00f0080d00200241e0076a2003412020034120491b22056a41004100412020056b2005411f4b1b10cd041a200241e0076a2004200510ce041a2001200320056b22063602042001200420056a22053602002003411f4d0d00200241f0086a41086a2203200241e0076a41086a2207290300370300200241f0086a41106a220c200241e0076a41106a220a290300370300200241f0086a41186a2209200241e0076a41186a220b290300370300200220022903e00722083703a007200220083703f008200241e0076a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241e0076a2005200410ce041a2001200620046b3602042001200520046a3602002006411f4d0d0020024180076a41086a2204200729030037030020024180076a41106a2205200a29030037030020024180076a41186a2206200b290300370300200241f0046a41186a22072009290300370300200241f0046a41106a220a200c290300370300200241f0046a41086a220c2003290300370300200220022903e00722083703a0072002200837038007200220022903f0083703f004200241f0046a41386a22032006290300370300200241f0046a41306a22062005290300370300200241f0046a41286a22052004290300370300200220022903800737039005200241f8056a41386a22042003290300370300200241f8056a41306a22032006290300370300200241f8056a41286a22062005290300370300200241f8056a41206a2205200229039005370300200241f8056a41186a2007290300370300200241f8056a41106a200a290300370300200241f8056a41086a200c290300370300200220022903f0043703f805200241f0046a2001104420022802f00422010d0f0b200041123602000c3d0b200241f8056a2001108f02200220022f01fa053b01e80320022d00f80522014112470d0e200041123602000c3c0b200241f8056a2001109002200241e8036a41086a2201200241f8056a41096a290000370300200241e8036a41106a220420024189066a290000370300200241e8036a41186a220520024191066a290000370300200241e8036a411f6a220620024198066a290000370000200220022900f9053703e80320022d00f80522034105470d0e200041123602000c3b0b200241f8056a2001109002200241e8036a41086a220120024181066a290000370300200241e8036a41106a220420024189066a290000370300200241e8036a41186a220520024191066a290000370300200241e8036a411f6a220620024198066a290000370000200220022900f9053703e80320022d00f80522034105470d0e200041123602000c3a0b200241003a00f008200241f0086a20052006410047220410ce041a20062004490d242001200620046b3602042001200520046a3602002006450d3320022d00f008220441094b0d33024002400240024002400240024002400240024020040e0a00010203040506070809000b200241f8056a2001104220022802f8052204450d3c20022902fc052108200241f0016a2001102e2008a72105024020022802f0010d002005450d3d0c3c0b20022802f4012106200241003602f805200241f8056a2001280200220c20012802042203410420034104491b220710ce041a2001200320076b3602042001200c20076a3602000240200341034b0d0020050d3c0c3d0b2008422088210820024180086a41086a200241e8036a41086a280200360200200220022902e80337038008200541087621092004410876210b20022802f80521014101210a0c3a0b200241f8056a2001104220022802f8052204450d3b20022902fc052108200241f8016a2001102e2008a72105024020022802f8010d0020050d3b0c3c0b20022802fc012106200241003602f805200241f8056a2001280200220c20012802042203410420034104491b220710ce041a2001200320076b3602042001200c20076a3602000240200341034b0d0020050d3b0c3c0b2008422088210820024180086a41086a200241e8036a41086a280200360200200220022902e80337038008200541087621092004410876210b20022802f80521014102210a0c390b20024190026a2001102e200228029002450d3a2002280294022104200241f8056a2001105020022d00f80522054102460d3a20022d00fb05210620022f00f905210320024184066a290200210e20024198066a280200210720024190066a290300210d2002418c066a280200210a20022902fc05210820024188026a2001102e200228028802450d3a200228028c02210c20024180026a2001102e200228028002450d3a2003200641107472210920022802840221012002200d370284082002200a360280082004410876210b2008422088a72106200e422088a721032001ad210d200ea721014200210e4103210a0c380b20024198026a2001102e200228029802450d39200228029c02210420024180086a41086a200241f8056a41086a280200360200200220022902f805370380082004410876210b4104210a0c360b200241a0026a2001102e20022802a002450d3820022802a402210420024180086a41086a200241f8056a41086a280200360200200220022902f805370380082004410876210b4105210a0c350b200241f8056a2001105020022d00f80522044102460d3720022d00fb05210520022f00f905210620024184066a290200210f20024198066a280200210c20024190066a29030021082002418c066a280200210320022902fc052111200241b0026a2001105320022903b002a7450d37200241b0026a41106a290300210e20022903b802210d200241a8026a2001102e20022802a802450d372006200541107472210b20022802ac0221072002200c360288082002200837038008201142208821082011a722054108762109200f422088a72101200fa721064106210a0c350b200241c8026a2001102e20022802c802450d3620022802cc02210420024180086a41086a200241f8056a41086a280200360200200220022902f805370380082004410876210b4107210a0c330b200241f8056a2001105020022d00f80522044102460d3520024184066a290200210d20022902fc05210e200220024198066a28020036028808200220024190066a29030037038008200e42208821084108210a200ea72205410876210920022f00f90520022d00fb0541107472210b200d422088a721012002418c066a2802002103200da721060c330b200241d0026a2001105220022903d002a7450d3420022903d802220d4220882108200da7220541087621094109210a0c320b200241e0026a2001105220022903e002a7450d3320022903e802220d4220882108200da722054108762109410a210a0c310b200241003a00e803200241e8036a20052006410047220410ce041a20062004490d242001200620046b3602042001200520046a36020002402006450d0020022d00e8030d00200241f0026a2001105220022903f002a7450d0020022903f80221082000410c360200200041086a2008370300200041106a200241f0046a41f80010ce041a0c390b200041123602000c380b200241003a00e803200241e8036a20052006410047220410ce041a20062004490d242001200620046b3602042001200520046a36020002402006450d0020022d00e8030d00200241f8056a2001104420022802f80522010d0d0b200041123602000c370b200241003a00f008200241f0086a20052006410047220410ce041a20062004490d242001200620046b3602042001200520046a36020002402006450d0020022d00f008220441024b0d0002400240024020040e03000102000b20024180036a20011053200229038003a7450d0220024190036a2903002108200229038803210d200241f8056a2001105020022d00f80522014102460d0220022f00f90520022d00fb0541107472210420024184066a290200210e2002418c066a280200210520024190066a290300210f20024198066a280200210620022902fc052111410121030c2f0b20024198036a2001102e200228029803450d01200228029c032201410876210442002111410221030c2d0b200241a0036a2001102e20022802a003450d0020022802a4032201410876210442002111410321030c2c0b200041123602000c360b200241f0046a200110910220022d00f0042101200241f8056a200241f0046a41017241ff0010ce041a20014107470d0b200041123602000c350b200241003a00e803200241e8036a20052006410047220410ce041a20062004490d232001200620046b3602042001200520046a36020002402006450d0020022d00e803220441014b0d0002400240024020040e020001000b200241f0046a2001103c20022802f0042104200241f8056a200241f0046a41047241840110ce041a20044112460d02200241e8036a200241f8056a41840110ce041a41880110272201450d2720012004360200200141046a200241e8036a41840110ce041a200241f0086a41086a200241b0036a41086a290200370300200241f0086a41106a200241b0036a41106a290200370300200241f0086a41186a200241b0036a41186a290200370300200220022902b0033703f008410121040c010b200241f0046a20011050200241f8056a41086a2201200241fc046a290200370300200241f8056a41106a220520024184056a290200370300200241f8056a41186a22062002418c056a290200370300200220022902f4043703f8054102210420022d00f00422034102460d0120022d00f304210720022f00f104210c200241f0086a41186a2006290300370300200241f0086a41106a2005290300370300200241f0086a41086a2001290300370300200220022903f8053703f008200c20074110747241087420037221010b200241e0076a41086a200241f0086a41086a2903002208370300200241e0076a41106a200241f0086a41106a290300220d370300200241e0076a41186a200241f0086a41186a290300220e370300200220022903f008220f3703e007200041086a200136020020002004360204200041103602002000410c6a200f370200200041146a20083702002000411c6a200d370200200041246a200e3702002000412c6a20024180086a41dc0010ce041a0c350b200041123602000c340b200241003a00f008200241f0086a20052006410047220410ce041a20062004490d242001200620046b22033602042001200520046a220436020002402006450d0020022d00f0080d00200242003703f805200241f8056a20042003410820034108491b220510ce041a2001200320056b3602042001200420056a360200200341074d0d0020022903f805210f200241f8056a2001104420022802f8052210450d0020022902fc05210e200241a8036a2001102e200ea721150240024020022802a803450d000240024020022802ac03220941d502200941d502491b220a0d00410421070c010b200a410c6c220410272207450d290b02402009450d004100210341002104410021060340200241f8056a20011044024020022802f805220c0d0002402006450d002007210103400240200141046a280200450d00200128020010290b2001410c6a2101200441746a22040d000b0b200a450d03200710290c030b200641016a210520022902fc05210802402006200a470d002003200520052003491b220aad420c7e220d422088a70d2d200da7220b4100480d2d0240024020060d00200b102721070c010b20072004200b102821070b2007450d2c0b200720046a2206200c360200200641046a2008370200200341026a21032004410c6a21042005210620092005470d000b0b20070d010b2015450d01201010290c010b200241003602f805200241f8056a2001280200220320012802042204410420044104491b220610ce041a2001200420066b22053602042001200320066a22033602002009ad422086200aad842208422088a721062008a7210c02400240200441034b0d0002402015450d00201010290b02402006450d002006410c6c21042007210103400240200141046a280200450d00200128020010290b2001410c6a2101200441746a22040d000b0b200c0d010c020b20022802f805210a200241e0076a2005412020054120491b22046a41004100412020046b2004411f4b1b10cd041a200241e0076a2003200410ce041a2001200520046b3602042001200320046a36020002402005411f4b0d0002402015450d00201010290b02402006450d002006410c6c21042007210103400240200141046a280200450d00200128020010290b2001410c6a2101200441746a22040d000b0b200c0d010c020b200241a0076a41086a2204200241e0076a41086a290300370300200241a0076a41106a2205200241e0076a41106a290300370300200241a0076a41186a2203200241e0076a41186a290300370300200220022903e0073703a007200241f8056a2001104420022802f80522010d0302402015450d00201010290b02402006450d002006410c6c21042007210103400240200141046a280200450d00200128020010290b2001410c6a2101200441746a22040d000b0b200c450d010b200710290b200241f8056a41186a200241e8036a41186a290300370300200241f8056a41106a200241e8036a41106a290300370300200241f8056a41086a200241e8036a41086a290300370300200220022903e8033703f8050c020b200041123602000c320b200241e8036a41086a20042903002208370300200241e8036a41106a2005290300220d370300200241e8036a41186a20032903002211370300200220022903a00722133703e80320022902fc052112200241f8056a41186a2011370300200241f8056a41106a200d370300200241f8056a41086a2008370300200220133703f80520100d080b200041123602000c300b2000200c36020420004103360200200041086a2009ad422086200aad84370200200041106a200241f8056a41f80010ce041a0c2f0b200241e8036a41086a2207200241f8056a41086a290300370300200241e8036a41106a220c200241f8056a41106a290300370300200241e8036a41186a220a200241f8056a41186a290300370300200241e8036a41206a22092005290300370300200241e8036a41286a22052006290300370300200241e8036a41306a22062003290300370300200241e8036a41386a22032004290300370300200220022903f8053703e80320022902f404210820024180086a41386a2204200329030037030020024180086a41306a2203200629030037030020024180086a41286a2206200529030037030020024180086a41206a2205200929030037030020024180086a41186a2209200a29030037030020024180086a41106a220a200c29030037030020024180086a41086a220c2007290300370300200220022903e80337038008200041086a20083702002000200136020420004107360200200041106a200229038008370200200041186a200c290300370200200041206a200a290300370200200041286a2009290300370200200041306a2005290300370200200041386a2006290300370200200041c0006a2003290300370200200041c8006a200429030037020020004180016a200241b0036a41306a290300370300200041f8006a200241b0036a41286a290300370300200041f0006a200241b0036a41206a290300370300200041e8006a200241b0036a41186a290300370300200041e0006a200241b0036a41106a290300370300200041d8006a200241b0036a41086a290300370300200041d0006a20022903b0033703000c2e0b20022d00f9052104200220022f01e80322053b018008200241f8056a41186a280200210620024194066a2902002108200241f8056a41246a2802002103200241f8056a41086a290300210d200241f8056a41106a290300210e200241a0066a290300210f20022802fc052107200041386a200241f8056a41306a290300370200200041306a200f370200200041186a200e370200200041106a200d370200200020043a0009200041086a20013a0000200041083602002000412c6a2003360200200041246a2008370200200041206a20063602002000410c6a2007360200200020053b000a200041c0006a200241f0046a41c80010ce041a0c2d0b20024180086a411f6a2207200629000037000020024180086a41186a2206200529030037030020024180086a41106a2004290300220837030020024180086a41086a2001290300220d370300200220022903e803220e37038008200020033a0004200041093602002000200e3700052000410d6a200d370000200041156a20083700002000411d6a2006290300370000200041246a20072900003700002000412c6a200241f0046a41dc0010ce041a0c2c0b20024180086a411f6a2207200629000037000020024180086a41186a2206200529030037030020024180086a41106a2004290300220837030020024180086a41086a2001290300220d370300200220022903e803220e37038008200020033a00042000410a3602002000200e3700052000410d6a200d370000200041156a20083700002000411d6a2006290300370000200041246a20072900003700002000412c6a200241f0046a41dc0010ce041a0c2b0b200041086a20022902fc05370200200020013602042000410d360200200041106a200241f0046a41f80010ce041a0c2a0b200241e8036a200241f8056a41ff0010ce041a200041086a20013a00002000410f360200200041096a200241e8036a41ff0010ce041a0c290b20024180086a41186a2204200241f8056a41186a29030037030020024180086a41106a2205200241f8056a41106a29030037030020024180086a41086a2203200241f8056a41086a290300370300200220022903f80537038008200041286a200a360200200041246a2006360200200041206a200c3602002000411c6a2007360200200041186a200e422088a7360200200041146a2015360200200041106a2010360200200041086a200f37020020004111360200200041d4006a2012370200200041d0006a20013602002000412c6a200229038008370200200041346a20032903003702002000413c6a2005290300370200200041c4006a200429030037020020004180016a200241f0046a41206a290300370300200041f8006a200241f0046a41186a290300370300200041f0006a200241f0046a41106a290300370300200041e8006a200241f0046a41086a290300370300200041e0006a20022903f0043703000c280b20052004103e000b20042006103e000b20054104102a000b20104104102a000b20054104102a000b200b4104102a000b20042006103e000b20042006103e000b20042006103e000b20044108102a000b20104108102a000b20042006103e000b20042006103e000b20042006103e000b20072006103e000b20054104102a000b20174104102a000b20042009103e000b20042006103e000b20042006103e000b20042006103e000b20042006103e000b20042006103e000b20042006103e000b4188014108102a000b20042006103e000b20044104102a000b200b4104102a000b102b000b4200210e4200210f0b2000410e360200200041386a2008370200200041306a200d370200200041186a200e370200200041106a20113702002000412c6a2006360200200041246a200f370200200041206a2005360200200041086a20033602002000410c6a2004410874200141ff017172360200200041c0006a200241f0046a41c80010ce041a0c090b42002108410021090b200241b0036a41086a20024180086a41086a28020022103602002002200229038008220f3703b003200041206a20033602002000411c6a2001360200200041186a2006360200200041106a20084220862009ad42ffffff07834208862005ad42ff018384843702002000410c6a200b410874200441ff017172360200200041086a200a3602002000410b360200200041c0006a200e370200200041386a200d370200200041246a200f3702002000412c6a2010360200200041346a200c360200200041306a2007360200200041c8006a20022903f004370300200041d0006a200241f0046a41086a290300370300200041d8006a200241f0046a41106a290300370300200041e0006a200241f0046a41186a290300370300200041e8006a200241f0046a41206a290300370300200041f0006a20024198056a290300370300200041f8006a200241f0046a41306a29030037030020004180016a200241f0046a41386a2903003703000c070b200410290b200041123602000c050b200220022f01800822013b01b003200041386a2011370200200041306a200f370200200041186a200d370200200041106a200e370200200020063a0009200041086a20073a0000200041063602002000412c6a2003360200200041246a2008370200200041206a20053602002000410c6a200c410874200441ff017172360200200020013b000a200041c0006a200241f0046a41c80010ce041a0c040b200041123602000c030b200410290b200041123602000c010b20004100360200200041106a20083702002000410c6a2004360200200041086a2007360200200041186a200241f0046a41f00010ce041a0b20024190096a24000b960b01057f024002402000280200220141104b0d000240024002400240024002400240024002400240024020010e11000c0c010c0c0203040506070c080c090a000b0240200041086a280200220141054b0d0002400240024020010e060f0f000f01020f0b200041106a280200450d0e2000410c6a28020010290f0b200041106a280200450d0d2000410c6a28020010290f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141186a2101200241686a22020d000b0b200041106a280200450d0c200028020c10290f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d00200128020010290b2001410c6a2101200241746a22020d000b0b200041106a280200450d0b200028020c10290f0b02402000410c6a2802002201450d0020002802042203200141f8006c6a210403400240200341106a2802002202450d0020032802082101200241246c210203400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012002415c6a22020d000b0b200341f8006a210102402003410c6a280200450d00200328020810290b2001210320012004470d000b0b200041086a280200450d0a200028020410290f0b0240200041086a2d00002201410c4b0d0020014106470d0a200041106a280200450d0a2000410c6a28020010290f0b200041106a280200450d092000410c6a28020010290f0b200041086a280200450d08200028020410290f0b200041086a2d0000417f6a220141074b0d07024002400240024020010e08000b0b0b010b0203000b2000410c6a2201280200103d200128020010290f0b2000410c6a2201280200103d200128020010290f0b2000410c6a2201280200103d200128020010290f0b2000410c6a2201280200103d200128020010290f0b20002d0004417f6a220141024b0d0602400240024020010e03000102000b2000410c6a280200450d08200041086a28020010290f0b200041086a2201280200103d200128020010290f0b2000410c6a2201280200103d200128020010290f0b20002d0004417f6a220141024b0d0502400240024020010e03000102000b2000410c6a280200450d07200041086a28020010290f0b200041086a2201280200103d200128020010290f0b2000410c6a2201280200103d200128020010290f0b200041086a280200417f6a220141014b0d040240024020010e020001000b200041106a280200450d052000410c6a28020010290f0b200041106a280200450d042000410c6a28020010290f0b200041086a280200450d03200028020410290f0b0240200041086a2d0000220141054b0d0002400240024020010e06060600010206060b200041106a280200450d052000410c6a28020010290f0b200041346a280200450d04200041306a28020010290f0b200041306a280200450d032000412c6a28020010290c030b200041d0006a280200450d02200041cc006a28020010290f0b20002802044101470d01200041086a2201280200103d200128020010290f0b0240200041146a280200450d00200041106a28020010290b0240200041246a2802002202450d002000411c6a28020021012002410c6c210203400240200141046a280200450d00200128020010290b2001410c6a2101200241746a22020d000b0b0240200041206a280200450d00200028021c10290b200041d4006a280200450d00200041d0006a28020010290f0b0b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c200241a4d9c500360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41b4d9c5001057000bfa0702137f017e23004190056b22022400200241086a2001102e0240024002400240024020022802080d00200041003602000c010b02400240200228020c2203411720034117491b22040d00410821050c010b200441b0016c220610272205450d020b02402003450d00200241e0026a4104722107200241f0046a41186a2108200241f0046a41106a2109200241f0046a41086a210a4100210b4100210c4100210d0340200241003602e803200241e8036a2001280200220e20012802042206410420064104491b220f10ce041a20012006200f6b3602042001200e200f6a36020002400240200641034b0d004112210e0c010b20022802e8032110200241e8036a2001103c024020022802e8034112470d004112210e0c010b200241e0026a200241e8036a41880110ce041a2008420037030020094200370300200a4200370300200242003703f004200241f0046a2001280200220e20012802042206412020064120491b220f10ce041a20012006200f6b3602042001200e200f6a36020002402006411f4b0d00200241e0026a103d4112210e0c010b200241b8016a41186a2008290300370300200241b8016a41106a2009290300370300200241b8016a41086a200a290300370300200220022903f0043703b80120022802e002210e200241dc016a200741840110ce041a201021110b200241e8036a200241dc016a41840110ce041a200241e0026a41186a2206200241b8016a41186a290300370300200241e0026a41106a2210200241b8016a41106a290300370300200241e0026a41086a2212200241b8016a41086a290300370300200220022903b8013703e0020240200e4112470d00200041003602000240200d450d002005210603402006103d200641b0016a2106200c41d07e6a220c0d000b0b2004450d03200510290c030b200d41016a210f200241346a200241e8036a41840110ce041a200241106a41186a22132006290300370300200241106a41106a22142010290300370300200241106a41086a22102012290300370300200220022903e0023703100240200d2004470d00200b200f200f200b491b2204ad42b0017e2215422088a70d062015a722064100480d0602400240200d0d002006102721050c010b2005200c2006102821050b2005450d050b2005200c6a2206200e360200200641046a200241346a41840110ce041a20064188016a20113602002006418c016a200229031037020020064194016a20102903003702002006419c016a2014290300370200200641a4016a2013290300370200200b41026a210b200c41b0016a210c200f210d2003200f470d000b0b2000200436020420002005360200200041086a20033602000b20024190056a24000f0b20064108102a000b20064108102a000b102b000b8303020a7f017e230041106b2202240020022001102e0240024002400240024020022802000d00200041003602000c010b02400240200228020422034180042003418004491b22040d00410821050c010b2004410374220610272205450d020b02402003450d00410021074100210841002109034020024200370308200241086a2001280200220a20012802042206410820064108491b220b10ce041a20012006200b6b3602042001200a200b6a3602000240200641074b0d00200041003602002004450d03200510290c030b200941016a21062002290308210c024020092004470d002007200620062007491b220441ffffffff01712004470d062004410374220b4100480d060240024020090d00200b102721050c010b20052008200b102821050b2005450d050b200520086a200c370300200741026a2107200841086a21082006210920032006470d000b0b2000200436020420002005360200200041086a20033602000b200241106a24000f0b20064108102a000b200b4108102a000b102b000bb40502107f027e230041f0006b22022400200241086a2001102e0240024002400240024020022802080d00200041003602000c010b02400240200228020c220341e600200341e600491b22040d00410821050c010b200441286c220610272205450d020b02402003450d00200241d0006a41186a2107200241d0006a41106a2108200241d0006a41086a21094100210a4100210b4100210c034020074200370300200842003703002009420037030020024200370350200241d0006a2001280200220d2001280204220e4120200e4120491b220f10ce041a2001200e200f6b22063602042001200d200f6a220f36020002400240200e411f4d0d00200241306a41186a220d2007290300370300200241306a41106a22102008290300370300200241306a41086a221120092903003703002002200229035037033020024200370350200241d0006a200f2006410820064108491b220e10ce041a20012006200e6b3602042001200f200e6a360200200641074b0d010b200041003602002004450d03200510290c030b200c41016a210e200241106a41086a220f2011290300370300200241106a41106a22112010290300370300200241106a41186a2210200d29030037030020022002290330370310200229035021120240200c2004470d00200a200e200e200a491b2204ad42287e2213422088a70d062013a722064100480d0602400240200c0d002006102721050c010b2005200b2006102821050b2005450d050b2005200b6a22062002290310370300200641186a2010290300370300200641106a2011290300370300200641086a200f290300370300200641206a2012370300200a41026a210a200b41286a210b200e210c2003200e470d000b0b2000200436020420002005360200200041086a20033602000b200241f0006a24000f0b20064108102a000b20064108102a000b102b000be30201097f230041106b2202240020022001102e024002400240024020022802000d00200041003602000c010b02400240200228020422034180202003418020491b22040d00410121050c010b200410272205450d020b02402003450d0041002106410021070340200241003a000f2002410f6a2001280200220820012802042209410047220a10ce041a2009200a490d0420012009200a6b36020420012008200a6a360200024020090d00200041003602002004450d03200510290c030b200741016a210920022d000f210a024020072004470d0002402006200920092006491b22044100480d000240024020070d002004102721050c010b200520072004102821050b20050d0120044101102a000b102b000b200520076a200a3a0000200641026a21062009210720032009470d000b0b2000200436020420002005360200200041086a20033602000b200241106a24000f0b20044101102a000b200a2009103e000bf10b030e7f017e067f230041e0006b22022400200241086a2001102e0240024020022802080d00200041003602000c010b0240024002400240024002400240200228020c220341f100200341f100491b22040d00410421050c010b200441246c220610272205450d010b024020030d00410021070c050b2002412d6a2108200241d3006a220941056a210a4100210b410021070340200241003a0040200241c0006a2001280200220c20012802042206410047220d10ce041a2006200d490d0220012006200d6b220e3602042001200c200d6a220c3602000240024020060d004105210d0c010b4105210d20022d0040220641064b0d000240024002400240024020060e0704050005020301040b200241c0006a200e4120200e4120491b22066a41004100412020066b2006411f4b1b10cd041a200241c0006a200c200610ce041a2001200e20066b3602042001200c20066a360200200e411f4d0d04200220092900003703202002200a2900003700252002280047210f200229004b211020022f0140210620022d0042210d20022800432111200841026a200241306a41026a2d00003a0000200820022f00303b0000201141087621122006200d4110747221132010422088a721142010a721154100210d0c040b20024100360240200241c0006a200c200e4104200e4104491b220610ce041a2001200e20066b3602042001200c20066a360200200e41034d0d0320022d0043210620022f0140210e20022d0042210c200241c0006a2001104420022802402216450d03200e200c41107472211320022902442210422088a721142010a721154101210d200621112016210f0c030b20024100360240200241c0006a200c200e4104200e4104491b220610ce041a2001200e20066b3602042001200c20066a360200200e41034d0d0220022d0043210620022f0140210e20022d0042210c200241c0006a2001104420022802402216450d02200e200c41107472211320022902442210422088a721142010a721154102210d200621112016210f0c020b20024100360240200241c0006a200c200e4104200e4104491b220610ce041a2001200e20066b3602042001200c20066a360200200e41034d0d0120022d0043210620022f0140210e20022d0042210c200241c0006a2001104420022802402216450d01200e200c41107472211320022902442210422088a721142010a721154103210d200621112016210f0c010b200241306a2001104420022802302206450d00200241206a41086a200241c0006a41086a2902003703002002200229024037032020064108762112200228023821152002280234210f4104210d200621110b200241c0006a41086a2206200241206a41086a290300370300200220022903203703400240200d4105470d002000410036020002402007450d002005210603400240024020062d0000220141034b0d0002400240024020010e0404000102040b2006410c6a280200450d03200641086a28020010290c030b2006410c6a280200450d02200641086a28020010290c020b2006410c6a280200450d01200641086a28020010290c010b200641086a280200450d00200641046a28020010290b200641246a2106200b415c6a220b0d000b0b2004450d07200510290c070b200241106a41086a220e200629030037030020022002290340370310024020072004470d00200441016a22062004490d052004410174220c20062006200c491b2206ad42247e2210422088a70d052010a7220c4100480d050240024020040d00200c102721050c010b2005200441246c200c102821050b2005450d04200621040b2005200b6a2206200d3a0000200641106a20143602002006410c6a2015360200200641086a200f360200200641046a2012410874201141ff017172360200200641036a20134110763a0000200641016a20133b0000200641146a20022903103702002006411c6a200e290300370200200b41246a210b2003200741016a2207460d050c000b0b20064104102a000b200d2006103e000b200c4104102a000b102b000b2000200436020420002005360200200041086a20073602000b200241e0006a24000bbd04010a7f230041106b22022400200241086a2001102e0240024002400240024020022802080d00200041003602000c010b0240200228020c2203418020490d00418020107c2204450d044101210541002106410021070340200420012802002001280204220820034180202003418020491b220920082009491b220810ce04210a024002400240200128020422092008490d002001200920086b3602042001200128020020086a36020002402008450d0020084181204f0d020240200620076b2008490d00200820076a21090c040b0240200720086a22092007490d002006410174220b20092009200b491b220b4100480d000240024020060d00200b102721050c010b20052006200b102821050b02402005450d00200b21060c050b200b4101102a000b102b000b20004100360200200a10292006450d05200510290c050b20082009103e000b2008418020107f000b200520076a200a200810ce041a20092107200320086b22030d000b2000200636020420002005360200200041086a2009360200200a10290c010b0240024020030d0041012107410021080c010b2003107c2207450d032007200128020020012802042208200320082003491b220810ce041a200128020422092008490d022001200920086b3602042001200128020020086a3602000b024020082003470d002000200336020420002007360200200041086a20033602000c010b200041003602002003450d00200710290b200241106a24000f0b20082009103e000b20034101102a000b4180204101102a000b8103010a7f230041106b2202240020022001102e0240024002400240024020022802000d00200041003602000c010b02400240200228020422034180082003418008491b22040d00410421050c010b2004410274220610272205450d020b02402003450d0041002107410021084100210903402002410036020c2002410c6a2001280200220a20012802042206410420064104491b220b10ce041a20012006200b6b3602042001200a200b6a3602000240200641034b0d00200041003602002004450d03200510290c030b200941016a2106200228020c210b024020092004470d002007200620062007491b220441ffffffff03712004470d062004410274220a4100480d060240024020090d00200a102721050c010b20052008200a102821050b2005450d050b200520086a200b360200200741026a2107200841046a21082006210920032006470d000b0b2000200436020420002005360200200041086a20033602000b200241106a24000f0b20064104102a000b200a4104102a000b102b000bda0f040d7f017e077f017e23004180026b2202240020022001102e02400240024002400240024020022802000d00200041003602000c010b0240024020022802042203413820034138491b22040d00410821050c010b200441c8006c220610272205450d020b02402003450d00200241ef016a210741c2002108200241b8016a41036a21094100210a4100210b0340200241003a00e001200241e0016a2001280200220c2001280204220d410047220e10ce041a200d200e490d042001200d200e6b22063602042001200c200e6a220e360200024002400240200d450d0020022d00e001220d41014b0d00024002400240200d0e020001000b200242003703a001200241a0016a200e2006410820064108491b220d10ce041a20012006200d6b3602042001200e200d6a360200200641074d0d02200241f8006a41086a200241c0016a41086a290300370300200241f8006a41106a200241c0016a41106a2d00003a0000200241d8006a41086a200241e0016a41086a290100370300200241d8006a41106a200241e0016a41106a290100370300200241d8006a41186a200241e0016a41186a290100370300200220022800b80136029001200220022903c001370378200220022901e001370358200220092800003600930120022903a001210f200241d0006a41046a2002419a016a41046a2f01003b01002002200228019a013602504100210e0c010b200241e0016a2006412020064120491b220d6a410041004120200d6b200d411f4b1b10cd041a200241e0016a200e200d10ce041a20012006200d6b220c3602042001200e200d6a220d3602002006411f4d0d01200241a0016a41086a2210200741086a290000370300200241a0016a41106a2211200741106a2d00003a0000200220022800e0013602b801200220072900003703a0012002200241e0016a41036a2800003600bb0120022900e701210f200241003a00e001200241e0016a200d200c410047220610ce041a200c2006490d092001200c20066b220e3602042001200d20066a220d360200200c450d0120022d00e001220641014b0d014100210c0240024020060e020100010b200241e0016a200e4120200e4120491b22066a41004100412020066b2006411f4b1b10cd041a200241e0016a200d200610ce041a2001200e20066b3602042001200d20066a360200200e411f4d0d02200241c0016a41186a200241e0016a41186a290000370300200241c0016a41106a200241e0016a41106a290000370300200241c0016a41086a200241e0016a41086a290000370300200220022900e0013703c0014101210c0b200241d8006a41186a200241c0016a41186a290300370300200241d8006a41106a200241c0016a41106a290300370300200241d8006a41086a200241c0016a41086a290300370300200241f8006a41086a2010290300370300200241f8006a41106a20112d00003a0000200220022903c001370358200220022802b80136029001200220022800bb0136009301200220022903a001370378200241d0006a41046a2002419a016a41046a2f01003b01002002200228019a013602504101210e0b200b41016a210d200241c0016a41086a2206200241f8006a41086a290300370300200241c0016a41106a2210200241f8006a41106a2d00003a0000200241e0016a41086a2211200241d8006a41086a290300370300200241e0016a41106a2212200241d8006a41106a290300370300200241e0016a41186a2213200241d8006a41186a29030037030020022002280290013602a00120022002280093013600a301200220022903783703c001200220022903583703e001200241b8016a41046a2214200241d0006a41046a2f01003b0100200241306a41086a22152006290300370300200241306a41106a221620102d00003a0000200241106a41086a22102011290300370300200241106a41106a22112012290300370300200241106a41186a22122013290300370300200220022802503602b801200220022800a30136004b200220022802a001360248200220022903c001370330200220022903e001370310200241086a41046a221320142f01003b0100200220022802b801360208200b2004470d020240200a200d200d200a491b2204ad42c8007e2217422088a70d002017a7220641004e0d020b102b000b200241c0016a41086a200241f8006a41086a290300370300200241e0016a41086a200241d8006a41086a290300370300200241e0016a41106a200241d8006a41106a290300370300200220022903783703c001200220022903583703e001200041003602002004450d04200510290c040b02400240200b0d002006102721050c010b2005200841be7f6a2006102821050b2005450d070b200520086a220641be7f6a200e3a0000200641466a200f370000200641bf7f6a220e2002280248360000200e41036a200228004b3600002006414e6a220e2002290330370000200e41086a2015290300370000200e41106a20162d00003a00002006415f6a200c3a0000200641606a220e2002290310370000200e41086a2010290300370000200e41106a2011290300370000200e41186a201229030037000020062002280208360000200641046a20132f01003b0000200a41026a210a200841c8006a2108200d210b2003200d470d000b0b2000200436020420002005360200200041086a20033602000b20024180026a24000f0b20064108102a000b200e200d103e000b2006200c103e000b20064108102a000bff04040c7f027e017f017e230041d0006b22022400200241086a2001102e0240024002400240024020022802080d00200041003602000c010b02400240200228020c220341d500200341d500491b22040d00410821050c010b200441306c220610272205450d020b02402003450d00200241306a41086a210741002108410021094100210a03402002420037033820024200370330200241306a2001280200220b20012802042206411020064110491b220c10ce041a20012006200c6b220d3602042001200b200c6a220c360200024002402006410f4d0d002007290300210e2002290330210f200241306a200d4120200d4120491b22066a41004100412020066b2006411f4b1b10cd041a200241306a200c200610ce041a2001200d20066b3602042001200c20066a360200200d411f4b0d010b200041003602002004450d03200510290c030b200a41016a210d200241106a41186a220c200241306a41186a290000370300200241106a41106a220b200241306a41106a290000370300200241106a41086a22102007290000370300200220022900303703100240200a2004470d002008200d200d2008491b2204ad42307e2211422088a70d062011a722064100480d0602400240200a0d002006102721050c010b200520092006102821050b2005450d050b200520096a2206200e3703082006200f370300200641106a2002290310370300200641186a2010290300370300200641206a200b290300370300200641286a200c290300370300200841026a2108200941306a2109200d210a2003200d470d000b0b2000200436020420002005360200200041086a20033602000b200241d0006a24000f0b20064108102a000b20064108102a000b102b000bff0305087f017e017f017e017f230041e0066b22022400200241086a2001102e024002400240024020022802080d00200041003602000c010b02400240200228020c2203410e2003410e491b22040d00410821050c010b200441a0026c220610272205450d020b02402003450d00200241a8026a41f0006a21074100210841002106410021090340200241a8026a20011049200241f8056a200241a8026a41e80010ce041a200229039003210a200241c8046a200741b00110ce041a024002400240200a4203510d00200941016a210b200241c0016a200241f8056a41e80010ce041a200241106a200241c8046a41b00110ce041a20092004470d0202402008200b200b2008491b2204ad42a0027e220c422088a70d00200ca7220d41004e0d020b102b000b2000410036020002402009450d0020054198016a210b0340200b103d200b41a0026a210b200641e07d6a22060d000b0b2004450d04200510290c040b0240024020090d00200d102721050c010b20052006200d102821050b2005450d050b200520066a200241c0016a41e80010ce04220941e8006a200a370300200941f0006a200241106a41b00110ce041a200841026a2108200641a0026a2106200b21092003200b470d000b0b2000200436020420002005360200200041086a20033602000b200241e0066a24000f0b20064108102a000b200d4108102a000bae0b04047f017e087f057e230041c0056b22022400200241286a2001102e0240024020022802280d00200042033703680c010b200241003a00a002200241a0026a2001280200220320012802042204410047220510ce041a0240024020042005490d002001200420056b3602042001200320056a36020020040d01200042033703680c020b20052004103e000b02400240024020022d00a002220441ff00714102470d0020044118744118754100480d01420221060c020b200042033703680c020b200241d8046a200110500240024020022d00d8044102460d00200241b0046a41206a200241d8046a41206a280200360200200241b0046a41186a200241d8046a41186a290300370300200241b0046a41106a200241d8046a41106a290300370300200241b0046a41086a200241d8046a41086a290300370300200220022903d8043703b00420024198016a41386a2207420037030020024198016a41306a2208420037030020024198016a41286a2209420037030020024198016a41206a220a420037030020024198016a41186a220b420037030020024198016a41106a220c420037030020024198016a41086a220d4200370300200242003703980120024198016a2001280200220e2001280204220441c000200441c000491b220510ce041a2001200420056b22033602042001200e20056a22053602002004413f4d0d0020024180056a41386a200729030037030020024180056a41306a200829030037030020024180056a41286a200929030037030020024180056a41206a200a29030037030020024180056a41186a200b29030037030020024180056a41106a200c29030037030020024180056a41086a200d290300370300200220022903980137038005200241003a00980120024198016a20052003410047220410ce041a0240024020032004490d002001200320046b220e3602042001200520046a22043602002003450d0202400240200231009801220f50450d00420021060c010b200241003a00980120024198016a2004200e410047220510ce041a200e2005490d022001200e20056b3602042001200420056a360200200e450d034202200f420f838622104204540d0342012106200231009801420886200f844204882010420c88220f4201200f4201561b7e220f20105a0d030b200241186a200110522002290318a7450d02200229032021112002200110532002290300a7450d02200241106a290300211220022903082113200241a0026a41206a200241b0046a41206a280200360200200241a0026a41186a200241b0046a41186a290300370300200241a0026a41106a200241b0046a41106a290300370300200241a0026a41086a200241b0046a41086a290300370300200241cc026a20024180056a41086a290300370200200241d4026a20024180056a41106a290300370200200241dc026a20024180056a41186a290300370200200241e4026a20024180056a41206a290300370200200241ec026a200241a8056a290300370200200241f4026a200241b0056a290300370200200241fc026a200241b8056a290300370200200220022903b0043703a00220022002290380053702c402200241a8036a200241a0026a41e80010ce041a0c030b20042003103e000b2005200e103e000b420221060b200241a0026a200241a8036a41e80010ce041a024020064202520d00200042033703680c020b200241306a200241a0026a41e80010ce041a0b200241a0026a2001103c20022802a0022104200241a8036a200241a0026a41047241840110ce041a024020044112470d00200042033703680c010b20024198016a200241a8036a41840110ce041a2000200241306a41e80010ce0422014190016a201237030020014188016a201337030020014198016a200436020020014180016a2011370300200141f8006a200f37030020012010370370200120063703682001419c016a20024198016a41840110ce041a0b200241c0056a24000be20805077f047e087f017e017f230041a0016b22022400024002400240200141086a220328020022042001410c6a2802002205460d0020012802102106200241f8006a41186a2107034020032004220841286a2204360200200841086a2903002109200841106a290300210a200841186a290300210b2008290300210c200241f8006a41206a200841206a2903003703002007200b370300200241f8006a41106a200a370300200241f8006a41086a20093703002002200c3703780240200a2006290300580d002001280214220d2007460d002007290000200d290000520d030b20052004470d000b200521040b2000410036020820004208370200024020042005460d00200141086a200520046b41586a41286e41286c20046a41286a3602000b2001280204450d01200128020010290c010b200241286a41086a200241f8006a41086a290300220a370300200241086a2204200a370300200241106a2207200241f8006a41106a290300370300200241186a2203200241f8006a41186a290300370300200241206a220e200241f8006a41206a29030037030020022002290378220a3703282002200a37030002400240024041281027220f450d00200f2002290300370300200f41206a200e290300370300200f41186a2003290300370300200f41106a2007290300370300200f41086a200429030037030020012802042110200128020021114101210e02400240200541586a2008470d00410121120c010b0240200d200241f8006a41186a2204470d00410121120c010b200841286a2113200541586a21144101210e4101211203402013210802400340200241f8006a41206a2207200841206a2903003703002004200841186a290300370300200241f8006a41106a2203200841106a290300220a370300200241f8006a41086a2201200841086a290300370300200220082903003703780240200a2006290300580d002004290000200d290000520d020b2005200841286a2208470d000c030b0b200241d0006a41206a2007290300220a370300200241286a41086a20012903002209370300200241286a41106a2003290300220b370300200241286a41186a2004290300220c370300200241286a41206a200a3703002002200229037822153703282007200a3703002004200c3703002003200b370300200120093703002002201537037802402012200e470d00200e41016a2212200e490d05200e4101742213201220122013491b2212ad42287e220a422088a70d05200aa722134100480d0502400240200e0d0020131027210f0c010b200f200e41286c20131028210f0b200f450d040b200841286a2113200f200e41286c6a22162002290378370300201641206a2007290300370300201641186a2004290300370300201641106a2003290300370300201641086a2001290300370300200e41016a210e20142008470d000b0b02402010450d00201110290b2000200e360208200020123602042000200f3602000c030b41284108102a000b20134108102a000b102b000b200241a0016a24000bd408040c7f017e057f037e23004180016b22022400024002400240200141086a220328020022042001410c6a2802002205460d002001280210220628020021072006280208220841014b210903402003200441206a220a360200200241e0006a41186a200441186a290000370300200241e0006a41106a200441106a290000370300200241e0006a41086a200441086a29000037030020022004290000370360410021040240024020090d0020080e020401040b2008210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a412010d0044101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a412010d0040d02200a2104200a2005470d000b200521040b2000410036020820004201370200024020042005460d00200141086a200520046b41606a41607120046a41206a3602000b2001280204450d01200128020010290c010b200241c0006a41086a2204200241e0006a41086a290300370300200241c0006a41106a220b200241e0006a41106a290300370300200241c0006a41186a220c200241e0006a41186a29030037030020022002290360220e3703002002200e370340024041201027220f450d00200f2002290340370000200f41186a200c290300370000200f41106a200b290300370000200f41086a2004290300370000200128020421102001280200211102400240200a2005470d0041012112410121130c010b41012112410121130340200628020821032006280200210702400340200241e0006a41186a2208200a41186a290000370300200241e0006a41106a2209200a41106a290000370300200241e0006a41086a2201200a41086a2900003703002002200a290000370360200a41206a210a4100210402400240200341014b0d0020030e020301030b2003210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a412010d0044101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a412010d0040d01200a2005470d000c030b0b200241c0006a41086a2001290300220e370300200241c0006a41106a20092903002214370300200241c0006a41186a20082903002215370300200220022903602216370340200241186a220b2015370300200241106a220c2014370300200241086a220d200e37030020022016370300024020132012470d000240201241016a22042012490d0020124101742207200420042007491b221341ffffff3f712013470d00201341057422044100480d000240024020120d0020041027210f0c010b200f201241057420041028210f0b200f0d0120044101102a000b102b000b200f20124105746a22042002290300370000200441186a200b290300370000200441106a200c290300370000200441086a200d290300370000201241016a2112200a2005470d000b0b02402010450d00201110290b20002012360208200020133602042000200f3602000c010b41204101102a000b20024180016a24000b810c05047f037e017f037e0d7f230041e0016b22022400200241e8006a200128020022032001280204220428020c220511000002400240200228026822010d002000410036020820004208370200200320042802001101002004280204450d01200310290c010b200241e0006a20024184016a290200370300200241c8006a41106a200241fc006a290200370300200241c8006a41086a200241f4006a2902003703002002200229026c370348200241a0016a2001104d200241a0016a41086a290300210620022903a001210742002108200241d0016a41086a22014200370300200242003703d00141b18ac0004116200241d0016a100420024190016a41086a2001290300370300200220022903d00137039001200241003602d00120024190016a4110200241d0016a100521090240024020022802d0012201417f460d00200242003703d801200242003703d001200241d0016a20092001411020014110491b10ce041a02402001410f4d0d00200241d0016a41086a290300210a20022903d001210b200910294201210c42002108200b427d56200a420156200a4201511b450d02200241386a200b200a427f420010d404200241386a41086a29030021082002290338210c0c020b418f89c3004133104e000b4201210c0b200241286a20072006200c200810d404200229032821080240200241c4016a280200450d0020022802c00110290b200241a0016a20032004280210220d1100000240024002400240417f20022802a001220141016a220920092001491b220ead42287e220c422088a70d00200ca72201417f4c0d000240024020010d004108210f410821100c010b20011027220f450d02200f21100b200f2002290348370300200f41186a200241c8006a41186a2211290300370300200f41106a200241c8006a41106a2212290300370300200f41086a200241c8006a41086a29030037030020102008370320200241e8006a2003200511000002400240200228026822010d00410121090c010b200241e8006a410472211341022114412821154101210903402011201341186a2902003703002012201341106a290200370300200241c8006a41086a2216201341086a29020037030020022013290200370348200241a0016a2001104d200241a0016a41086a2217290300210a20022903a0012106200241d0016a41086a22184200370300200242003703d00141b18ac0004116200241d0016a100420024190016a41086a2018290300370300200220022903d00137039001200241003602d00120024190016a4110200241d0016a1005210102400240024020022802d0012219417f460d002001450d00200242003703d801200242003703d001200241d0016a20012019411020194110491b10ce041a2019410f4b0d01418f89c3004133104e000b420021084201210c0c010b2018290300210720022903d001210b200110294201210c42002108200b427e5420075020074201511b0d00200241186a200b2007427f420010d404200241186a41086a29030021082002290318210c0b200241086a2006200a200c200810d40420022903082108024020022802c401450d0020022802c00110290b200241a0016a41186a22182011290300370300200241a0016a41106a2219201229030037030020172016290300370300200220022903483703a00102402009200e470d00200241e8006a2003200d1100002009417f2002280268220141016a221620162001491b6a22012009490d062014200120012014491b220ead42287e220c422088a70d06200ca722014100480d060240024020090d0020011027210f0c010b200f201520011028210f0b200f450d05200f21100b201020156a220120022903a001370300200141186a2018290300370300200141106a2019290300370300200141086a2017290300370300200141206a2008370300200241e8006a20032005110000201441026a2114201541286a2115200941016a2109200228026822010d000b0b2003200428020011010002402004280204450d00200310290b200020093602082000200e360204200020103602000c040b1039000b20014108102a000b20014108102a000b102b000b200241e0016a24000ba70906067f047e077f027e027f017e230041e0016b22022400024002400240024002400240410f10272203450d00200341076a4100290091a3443700002003410029008aa3443700002003410f412f10282204450d012004200129000037000f200441276a200141186a2900003700002004411f6a200141106a290000370000200441176a200141086a290000370000200241f8006a41186a22014200370300200241f8006a41106a22034200370300200241f8006a41086a22054200370300200242003703782004412f200241f8006a1000200241d8006a41186a2001290300370300200241d8006a41106a2003290300370300200241d8006a41086a200529030037030020022002290378370358200241003602c001200241d8006a4120200241c0016a100521060240024020022802c0012207417f460d002002200736029c012002200636029801200241c0006a20024198016a10532002290340a7450d07200241c0006a41106a290300210820022903482109200241286a20024198016a10532002290328a7450d07200241386a290300210a2002290330210b200241206a20024198016a102e2002280220450d07024002402002280224220c41d500200c41d500491b220d0d004108210e0c010b200d41306c22011027220e450d050b0240200c450d004100210f410021104100210503402002280298012111200241f8006a200228029c012203412020034120491b22016a41004100412020016b2001411f4b1b10cd041a200241f8006a2011200110ce041a2002200320016b36029c012002201120016a36029801024002402003411f4d0d00200241c0016a41186a2201200241f8006a41186a290300370300200241c0016a41106a2211200241f8006a41106a290300370300200241c0016a41086a2212200241f8006a41086a290300370300200220022903783703c001200241086a20024198016a10532002290308a70d010b200d450d0a200e10290c0a0b200541016a2103200241086a41106a290300211320022903102114200241a0016a41186a22152001290300370300200241a0016a41106a22162011290300370300200241a0016a41086a22112012290300370300200220022903c0013703a00102402005200d470d00200f20032003200f491b220dad42307e2217422088a70d092017a722014100480d090240024020050d0020011027210e0c010b200e201020011028210e0b200e450d080b200e20106a2201201337030820012014370300200141106a20022903a001370300200141186a2011290300370300200141206a2016290300370300200141286a2015290300370300200f41026a210f201041306a211020032105200c2003470d000b0b200e450d07200cad422086200dad84211302402007450d00200610290b2000200b370310200020093703002000200e360220200041186a200a37030020002008370308200041246a20133702000c010b200041186a4200370300200041106a4200370300200041086a420037030020004200370300200041286a4100360200200042083703200b20041029200241e0016a24000f0b410f4101102a000b412f4101102a000b20014108102a000b20014108102a000b102b000b418f89c3004133104e000b5e01017f230041306b220224002002200136020c20022000360208200241246a4101360200200242013702142002419c81c6003602102002410236022c2002200241286a3602202002200241086a360228200241106a41a481c6001057000b950e01057f230041106b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e050003010204000b2002410036020820024201370300410110272203450d05200242818080801037020420022003360200200341023a00000240024020022802042204200228020822036b4120490d00200341206a2105200228020021040c010b200341206a22052003490d1320044101742206200520052006491b22064100480d130240024020040d002006102721040c010b200228020020042006102821040b2004450d0720022006360204200220043602000b20022005360208200420036a22032001290001370000200341086a200141096a290000370000200341106a200141116a290000370000200341186a200141196a2900003700000c040b2002410036020820024201370300410110272203450d06200242818080801037020420022003360200200341043a00000240024020022802042205200228020822036b4104490d00200228020021050c010b200341046a22042003490d1220054101742206200420042006491b22044100480d120240024020050d002004102721050c010b200228020020052004102821050b2005450d0820022004360204200220053602000b2002200341046a360208200520036a2001280001360000200128020821042002200141106a280200220136020c2002410c6a200210300240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d1220054101742203200620062003491b22034100480d120240024020050d002003102721050c010b200228020020052003102821050b2005450d092002200336020420022005360200200228020821030b2002200320016a360208200520036a2004200110ce041a0c030b2002410036020820024201370300410110272203450d08200242818080801037020420022003360200200341053a00000240024020022802042204200228020822036b4104490d00200341046a2105200228020021040c010b200341046a22052003490d1120044101742206200520052006491b22064100480d110240024020040d002006102721040c010b200228020020042006102821040b2004450d0a20022006360204200220043602000b20022005360208200420036a2001280001360000200128020821042002200141106a280200220136020c2002410c6a200210300240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d1120054101742203200620062003491b22034100480d110240024020050d002003102721050c010b200228020020052003102821050b2005450d0b2002200336020420022005360200200228020821030b2002200320016a360208200520036a2004200110ce041a0c020b2002410036020820024201370300410110272203450d0a200242818080801037020420022003360200200341063a00000240024020022802042205200228020822036b4104490d00200228020021050c010b200341046a22042003490d1020054101742206200420042006491b22044100480d100240024020050d002004102721050c010b200228020020052004102821050b2005450d0c20022004360204200220053602000b2002200341046a360208200520036a2001280001360000200128020821042002200141106a280200220136020c2002410c6a200210300240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d1020054101742203200620062003491b22034100480d100240024020050d002003102721050c010b200228020020052003102821050b2005450d0d2002200336020420022005360200200228020821030b2002200320016a360208200520036a2004200110ce041a0c010b2002410036020820024201370300410110272203450d0c200242818080801037020420022003360200200341003a0000200141046a280200210420022001410c6a280200220136020c2002410c6a200210300240024020022802042205200228020822036b2001490d00200228020021050c010b200320016a22062003490d0f20054101742203200620062003491b22034100480d0f0240024020050d002003102721050c010b200228020020052003102821050b2005450d0e2002200336020420022005360200200228020821030b2002200320016a360208200520036a2004200110ce041a0b200020022201290200370200200041086a200141086a280200360200200241106a24000f0b41014101102a000b20064101102a000b41014101102a000b20044101102a000b20034101102a000b41014101102a000b20064101102a000b20034101102a000b41014101102a000b20044101102a000b20034101102a000b41014101102a000b20034101102a000b102b000bf50601067f230041f0006b22022400200241003a0050200241d0006a2001280200220320012802042204410047220510ce041a02400240024002400240024020042005490d002001200420056b22063602042001200320056a22053602002004450d04024020022d0050220441ef014b0d00410121010c030b200441847e6a220441034b0d040240024020040e0400010503000b200241003b0150200241d0006a20052006410220064102491b220410ce041a2001200620046b3602042001200520046a360200200641014d0d0520022f0150220441f001490d05410121010c030b20024100360250200241d0006a20052006410420064104491b220410ce041a2001200620046b3602042001200520046a360200200641034d0d04410121012002280250220441808004490d040c020b20052004103e000b41002103200241d0006a20064120200641204922071b22046a41004100412020046b2004411f4b1b10cd041a200241d0006a2005200410ce041a2001200620046b3602042001200520046a360200024020070d002002412c6a41026a200241d0006a41026a2d00003a0000200241186a200241df006a290000370300200241206a200241e7006a290000370300200241286a200241d0006a411f6a2d00003a0000200220022f00503b012c2002200229005737031041012103200228005321040b200241cc006a41026a22012002412c6a41026a2d00003a0000200241306a41086a2205200241106a41086a290300370300200241306a41106a2206200241106a41106a290300370300200241306a41186a2207200241106a41186a2d00003a0000200220022f012c3b014c200220022903103703302003450d022002410c6a41026a20012d00003a0000200241d0006a41086a2005290300370300200241d0006a41106a2006290300370300200241d0006a41186a20072d00003a0000200220022f014c3b010c20022002290330370350410021010b200020013a0000200020022f010c3b0001200041046a2004360200200041086a2002290350370200200041036a2002410e6a2d00003a0000200041106a200241d0006a41086a290300370200200041186a200241d0006a41106a290300370200200041206a200241d0006a41186a2802003602000c020b200120062006410420064104491b22046b3602042001200520046a3602000b200041023a00000b200241f0006a24000b880a01037f02400240024002400240024002400240024020002d00004101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0920024101742204200320032004491b22044100480d090240024020020d002004102721030c010b200128020020022004102821030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41ff013a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d0920034101742202200420042002491b22024100480d090240024020030d002002102721030c010b200128020020032002102821030b2003450d0320012003360200200141046a2002360200200141086a28020021020b200141086a200241206a360200200320026a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000f0b0240024002400240200041046a280200220241ffff034b0d00200241ef014b0d03200141046a280200200141086a2802002200460d01200128020021030c020b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0b20004101742204200320032004491b22044100480d0b0240024020000d002004102721030c010b200128020020002004102821030b2003450d0620012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fd013a000002400240200141046a2802002203200428020022006b4104490d00200128020021030c010b200041046a22042000490d0b20034101742200200420042000491b22004100480d0b0240024020030d002000102721030c010b200128020020032000102821030b2003450d0720012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20023600000f0b200041016a22032000490d0920004101742204200320032004491b22044100480d090240024020000d002004102721030c010b200128020020002004102821030b2003450d0620012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20023a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0820004101742204200320032004491b22044100480d080240024020000d002004102721030c010b200128020020002004102821030b2003450d0620012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fc013a000002400240200141046a2802002203200428020022006b4102490d00200128020021030c010b200041026a22042000490d0820034101742200200420042000491b22004100480d080240024020030d002000102721030c010b200128020020032000102821030b2003450d0720012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20023b00000f0b20044101102a000b20024101102a000b20044101102a000b20004101102a000b20044101102a000b20044101102a000b20004101102a000b102b000ba60503057f027e037f230041106b22022400200241003a000020022001280200220320012802042204410047220510ce04210202400240024002400240024020042005490d002001200420056b22063602042001200320056a22053602002004450d03024020022d0000220441037122034103460d002004ad210702400240024020030e03000102000b2004410276ad2107420121080c080b200241003a0000200220052006410047220410ce04210320062004490d032001200620046b3602042001200520046a3602002006450d0520033100004208862007844202882107420121080c070b200241003a000e200241003b010c2002410c6a200520064103200641034922031b220410ce041a2001200620046b3602042001200520046a36020020030d04200233010c200231000e421086844208862007844202882107420121080c060b02402004410276220441044b0d000240024020040e050002020201000b200241003602002002200520064104200641044922031b220410ce0421092001200620046b3602042001200520046a36020020030d0520093502002107420121080c070b42002108200242003703002002200520064108200641084922031b220410ce0421092001200620046b3602042001200520046a36020020030d0520092903002107420121080c060b200441046a220a41084b0d0342002107410021030340200241003a0000200220052006410047220410ce04210920062004490d032001200620046b220b3602042001200520046a22053602002006450d0420093100002003410374413871ad86200784210742012108200b2106200341016a22042103200441ff0171200a4f0d060c000b0b20052004103e000b20042006103e000b20042006103e000b420021080b0b2000200737030820002008370300200241106a24000bc10605057f017e017f027e027f230041306b22022400200241003a0018200241186a2001280200220320012802042204410047220510ce041a024002400240024002400240024020042005490d002001200420056b22063602042001200320056a22053602002004450d04024020022d0018220441037122034103460d0002400240024020030e03000102000b2004410276ad21070c060b200241003a0018200241186a20052006410047220310ce041a20062003490d032001200620036b3602042001200520036a3602002006450d0620022d001841087420047241fcff0371410276ad21070c050b200241003a002e200241003b012c2002412c6a200520064103200641034922081b220310ce041a2001200620036b3602042001200520036a36020020080d0520022f012c20022d002e41107472410874200472410276ad21070c040b024020044102762204410c4b0d0002400240024020040e0d00030303010303030303030302000b20024100360218200241186a200520064104200641044922031b220410ce041a2001200620046b3602042001200520046a36020020030d07200235021821070c060b4200210920024200370318200241186a200520064108200641084922031b220410ce041a2001200620046b3602042001200520046a36020020030d07200229031821070c050b420021092002420037032020024200370318200241186a200520064110200641104922031b220410ce041a2001200620046b3602042001200520046a36020020030d06200241206a290300210a20022903182107420121090c070b200441046a220b41104b0d04200241106a210c420021074200210a410021030340200241003a0018200241186a20052006410047220410ce041a20062004490d032001200620046b22083602042001200520046a22053602002006450d05200241086a20023100184200200341037441f8007110d104200c290300200a84210a200229030820078421074201210920082106200341016a22042103200441ff0171200b4f0d070c000b0b20052004103e000b20032006103e000b20042006103e000b4200210a420121090c020b420021090b0b2000200737030820002009370300200041106a200a370300200241306a24000bbd0903017f017e057f230041e0006b220224000240024002400240024002400240024002400240024020002903002203423f560d0002400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d0b20004101742205200420042005491b22054100480d0b0240024020000d002005102721040c010b200128020020002005102821040b2004450d0220012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a2003a74102743a00000c080b200342808001540d062003428080808004540d054108200379a741037622056b4104490d0402400240200141046a280200200141086a2802002204460d00200128020021060c010b200441016a22072004490d0a20044101742206200720072006491b22074100480d0a0240024020040d002007102721060c010b200128020020042007102821060b2006450d0220012006360200200141046a2007360200200141086a28020021040b200141086a2207200441016a360200200620046a411320054102746b3a0000200220002903002203370308200541786a2104200141046a2106034002400240200628020020072802002200460d00200128020021050c010b200041016a22052000490d0b20004101742208200520052008491b22084100480d0b0240024020000d002008102721050c010b200128020020002008102821050b2005450d042001200536020020062008360200200728020021000b2007200041016a360200200520006a2003a73a000020034208882103200441016a22002004492105200021042005450d000b20022003370308200350450d030c070b20054101102a000b20074101102a000b20084101102a000b200241286a41146a4103360200200241346a4104360200200241106a41146a41033602002002200241086a3602402002418883c000360244200241c8006a41146a41003602002002420337021420024190d1c5003602102002410436022c200241b8d6c5003602582002420137024c200241e081c0003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a419083c0001057000b41ec82c0001058000b024002400240200141046a2802002204200141086a28020022006b4104490d00200128020021040c010b200041046a22052000490d0520044101742200200520052000491b22004100480d050240024020040d002000102721040c010b200128020020042000102821040b2004450d0120012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a2003a74102744102723600000c020b20004101102a000b02400240200141046a2802002204200141086a28020022006b4102490d00200128020021040c010b200041026a22052000490d0320044101742200200520052000491b22004100480d030240024020040d002000102721040c010b200128020020042000102821040b2004450d0220012004360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200420006a2003a74102744101723b00000b200241e0006a24000f0b20004101102a000b102b000b6501027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a1091042100200241206a240020000bc20202027f017e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d0120044101200110aa0121000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000b20024180016a240020000f0b2003418001103e000b2003418001103e000b4b02017f017e230041206b2202240020012902002103200241146a20012902083702002002200337020c20022000360208200241b8d6c500360204200241b8d6c500360200200210ab04000b6802017f037e230041306b22012400200029020821022000290210210320002902002104200141146a4100360200200141b8d6c50036021020014201370204200120043703182001200141186a36020020012003370328200120023703202001200141206a1057000b910a03017f027e057f230041e0006b2202240002400240024002400240024002400240024002400240200028020022002903002203423f56200041086a290300220442005220045022051b0d0002400240200141046a280200200141086a2802002200460d00200128020021050c010b200041016a22052000490d0b20004101742206200520052006491b22064100480d0b0240024020000d002006102721050c010b200128020020002006102821050b2005450d0220012005360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200520006a2003a74102743a00000c080b20034280800154410020051b0d06200342808080800454410020051b0d05411020047920037942c0007c20044200521ba741037622066b4104490d0402400240200141046a280200200141086a2802002205460d00200128020021070c010b200541016a22082005490d0a20054101742207200820082007491b22084100480d0a0240024020050d002008102721070c010b200128020020052008102821070b2007450d0220012007360200200141046a2008360200200141086a28020021050b200141086a2208200541016a360200200720056a413320064102746b3a0000200029030021032002200041086a290300220437030820022003370300200641706a2105200141046a2107034002400240200728020020082802002200460d00200128020021060c010b200041016a22062000490d0b20004101742209200620062009491b22094100480d0b0240024020000d002009102721060c010b200128020020002009102821060b2006450d042001200636020020072009360200200828020021000b2008200041016a360200200620006a2003a73a00002003420888200442388684210320044208882104200541016a22002005492106200021052006450d000b2002200337030020022004370308200320048450450d030c070b20064101102a000b20084101102a000b20094101102a000b200241286a41146a4103360200200241346a4105360200200241106a41146a410336020020022002360240200241d081c000360244200241c8006a41146a41003602002002420337021420024190d1c5003602102002410536022c200241b8d6c5003602582002420137024c200241e081c0003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a41e881c0001057000b41b881c0001058000b024002400240200141046a2802002205200141086a28020022006b4104490d00200128020021050c010b200041046a22062000490d0520054101742200200620062000491b22004100480d050240024020050d002000102721050c010b200128020020052000102821050b2005450d0120012005360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200520006a2003a74102744102723600000c020b20004101102a000b02400240200141046a2802002205200141086a28020022006b4102490d00200128020021050c010b200041026a22062000490d0320054101742200200620062000491b22004100480d030240024020050d002000102721050c010b200128020020052000102821050b2005450d0220012005360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200520006a2003a74102744101723b00000b200241e0006a24000f0b20004101102a000b102b000b840605027f027e017f027e027f230041a0016b220224002000280200210002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0220054290ce005441002004501b450d012005a72103412721000c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d022001410141e8d9c5004102200241206a20006a41800120006b10ab0121000c060b41272100200241186a21060340200241106a200520044290ce00420010d4042002200229031022072006290300220842f0b17f427f10d304200241206a20006a2203417c6a200520022903007ca7220941ffff037141e4006e220a41017441fad6c5006a2f00003b00002003417e6a200a419c7f6c20096a41ffff037141017441fad6c5006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000c040b0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d012001410141e8d9c5004102200241206a20006a41800120006b10ab0121000c040b2000418001103e000b2000418001103e000b2007a721030b02400240200341e3004a0d00200321090c010b200241206a2000417e6a22006a2003200341ffff037141e4006e2209419c7f6c6a41ffff037141017441fad6c5006a2f00003b00000b024002402009410a480d00200241206a2000417e6a22006a200941017441fad6c5006a2f00003b00000c010b200241206a2000417f6a22006a200941306a3a00000b2001410141b8d6c5004100200241206a20006a412720006b10ab0121000b200241a0016a240020000ba80301067f230041106b220224002002410036020820024201370300200020021030200041046a20021030200041086a2002103020002d0018210302400240024002400240200228020420022802082204460d00200228020021050c010b200441016a22052004490d0320044101742206200520052006491b22064100480d030240024020040d002006102721050c010b200228020020042006102821050b2005450d0120022006360204200220053602000b2002200441016a360208200520046a20033a0000200028020c21062002200041146a280200220436020c2002410c6a200210300240024020022802042203200228020822056b2004490d00200228020021000c010b200520046a22002005490d0320034101742207200020002007491b22074100480d030240024020030d002007102721000c010b200228020020032007102821000b2000450d022002200736020420022000360200200721030b200020056a2006200410ce041a200128020020012802042000200520046a100302402003450d00200010290b200241106a24000f0b20064101102a000b20074101102a000b102b000be80201097f230041206b22022400200241003602082002420137030020002802002103200220002802082200360210200241106a20021030024002400240024020000d002002280208210420022802042105200228020021060c010b200041246c210720022802042105200228020821000340200241106a2003104f2002280210210802400240200520006b20022802182209490d00200020096a2104200228020021060c010b200020096a22042000490d0420054101742206200420042006491b220a4100480d040240024020050d00200a102721060c010b20022802002005200a102821060b2006450d032002200a36020420022006360200200a21050b20022004360208200620006a2008200910ce041a02402002280214450d00200810290b200341246a2103200421002007415c6a22070d000b0b2001280200200128020420062004100302402005450d00200610290b200241206a24000f0b200a4101102a000b102b000bcd0c02077f017e230041206b22022400200241003602102002420137030802400240024002400240024002400240024002400240024002402001280200220341044b0d0002400240024002400240024020030e050001020304000b410110272203450d06200242818080801037020c20022003360208200341013a0000200141106a28020021032002200141186a2802002204360218200241186a200241086a103002402004450d002003200441286c6a2105034002400240200228020c2206200228021022076b4120490d00200228020821040c010b200741206a22042007490d1420064101742207200420042007491b22084100480d140240024020060d002008102721040c010b200228020820062008102821040b2004450d0a2002200836020c2002200436020820022802102107200821060b200420076a220841186a200341186a290000370000200841106a200341106a290000370000200841086a200341086a2900003700002002200741206a220736021020082003290000370000200341206a29030021090240200620076b41074b0d00200741086a22082007490d1420064101742207200820082007491b22074100480d140240024020060d002007102721040c010b200420062007102821040b2004450d0b2002200736020c20022004360208200228021021070b2002200741086a360210200420076a20093700002005200341286a2203470d000b0b200220012903082209370318200241186a21070c040b410110272203450d08200242818080801037020c20022003360208200341023a00002001290308210902400240200228020c2207200228021022036b4108490d00200341086a2104200228020821070c010b200341086a22042003490d1120074101742206200420042006491b22064100480d110240024020070d002006102721070c010b200228020820072006102821070b2007450d0a2002200636020c200220073602080b20022004360210200720036a2009370000200141186a28020021032002200141206a2802002204360218200241186a200241086a103002402004450d002003200441286c6a2105034002400240200228020c2206200228021022076b4120490d00200228020821040c010b200741206a22042007490d1320064101742207200420042007491b22084100480d130240024020060d002008102721040c010b200228020820062008102821040b2004450d0d2002200836020c2002200436020820022802102107200821060b200420076a220841186a200341186a290000370000200841106a200341106a290000370000200841086a200341086a2900003700002002200741206a220736021020082003290000370000200341206a29030021090240200620076b41074b0d00200741086a22082007490d1320064101742207200820082007491b22074100480d130240024020060d002007102721040c010b200420062007102821040b2004450d0e2002200736020c20022004360208200228021021070b2002200741086a360210200420076a20093700002005200341286a2203470d000b0b200220012903102209370318200241186a21070c030b410110272203450d0b200242818080801037020c20022003360208200341033a0000200220012903082209370318200241186a21070c020b410110272203450d0b200242818080801037020c20022003360208200341043a0000200220012903082209370318200241186a21070c010b410110272203450d0b200242818080801037020c20022003360208200341053a0000200220012903082209370318200241186a21070b02400240200228020c2204200228021022036b4108490d00200228020821040c010b200341086a22062003490d0d20044101742203200620062003491b22034100480d0d0240024020040d002003102721040c010b200228020820042003102821040b2004450d0c2002200336020c2002200436020820072903002109200228021021030b2002200341086a360210200420036a20093700000b20002002290308370200200041086a200241086a41086a280200360200200241206a24000f0b41014101102a000b20084101102a000b20074101102a000b41014101102a000b20064101102a000b20084101102a000b20074101102a000b41014101102a000b41014101102a000b41014101102a000b20034101102a000b102b000bcd0a04037f037e027f017e230041c0006b220724002004a7210802400240024002400240024002400240024020014201510d0041012109024020084101460d00427f200320067c200220057c220a2002542208ad7c220b2008200b200354200b2003511b22081b210b427f200a20081b210a4200210c4100210d0c040b2002200556200320065620032006511b450d01200320067d2002200554ad7d210b200220057d210a4200210c0c020b4101210d024020084101470d00427f200320067c200220057c22012002542208ad7c22022008200220035420022003511b22081b210b427f200120081b210a410021094201210c0c040b200741086a200420052006420120022003105e200741186a290300210b2007290310210a2007290308210c0c070b200620037d2005200254ad7d210b200520027d210a4201210c0b410021094101210d0b2001500d0042002101200741306a41086a220842003703002007420037033041b18ac0004116200741306a1004200741206a41086a20082903003703002007200729033037032020074100360230200741206a4110200741306a1005210e0240024020072802302208417f470d004200210f0c010b2007420037033820074200370330200741306a200e2008411020084110491b10ce041a2008410f4d0d02200741386a290300210f20072903302101200e10290b200741306a41086a220842003703002007420037033041b18ac0004116200741306a1004200741206a41086a20082903003703002007200729033037032020074200200f20037d2001200254ad7d2203200120027d22022001562003200f562003200f511b22081b37033820074200200220081b370330200741206a4110200741306a411010030b2004500d020c010b418f89c3004133104e000b2009450d0142002103200741306a41086a220842003703002007420037033041b18ac0004116200741306a1004200741206a41086a20082903003703002007200729033037032020074100360230200741206a4110200741306a1005210902400240024020072802302208417f470d00420021020c010b2007420037033820074200370330200741306a20092008411020084110491b10ce041a2008410f4d0d01200741386a290300210220072903302103200910290b200741306a41086a220842003703002007420037033041b18ac0004116200741306a1004200741206a41086a20082903003703002007200729033037032020074200200220067d2003200554ad7d2204200320057d2205200356200420025620042002511b22081b37033820074200200520081b370330200741206a4110200741306a411010030c020b418f89c3004133104e000b200d450d0042002102200741306a41086a220842003703002007420037033041b18ac0004116200741306a1004200741206a41086a20082903003703002007200729033037032020074100360230200741206a4110200741306a1005210902400240024020072802302208417f470d00420021030c010b2007420037033820074200370330200741306a20092008411020084110491b10ce041a2008410f4d0d01200741386a290300210320072903302102200910290b200741306a41086a220842003703002007420037033041b18ac0004116200741306a1004200741206a41086a2008290300370300200720072903303703202007427f200320067c200220057c22052002542208ad7c22022008200220035420022003511b22081b3703382007427f200520081b370330200741206a4110200741306a411010030c010b418f89c3004133104e000b2000200a3703082000200c370300200041106a200b370300200741c0006a24000b890604077f017e017f047e230041e0006b220324002003200236021020032001280200220236020820032002200128020841246c22016a220436020c2003200341086a41086a360214024002400240200141ed00490d00200341386a41086a210103402003200241246a360208200341386a200341146a20021060200341186a41086a2202200141086a2204290300370300200341186a41106a2205200141106a2206290300370300200341186a41186a2207200141186a220829030037030020032001290300370318200341186a21092003290338220a4205520d0220032003280208220b41246a360208200341386a200341146a200b1060200220042903003703002005200629030037030020072008290300370300200320012903003703182003290338220a4205520d0220032003280208220b41246a360208200341386a200341146a200b1060200220042903003703002005200629030037030020072008290300370300200320012903003703182003290338220a4205520d0220032003280208220b41246a360208200341386a200341146a200b1060200220042903003703002005200629030037030020072008290300370300200320012903003703182003290338220a4205520d02200328020c2204200328020822026b41ec004b0d000b0b024020022004460d00200341386a41086a210103402003200241246a360208200341386a200341146a20021060200341186a41086a200141086a290300370300200341186a41106a200141106a290300370300200341186a41186a200141186a2903003703002003200129030037031802402003290338220a4205510d00200341186a21090c030b20032802082202200328020c470d000b0b200042053703000c010b200341386a41186a200941186a290300220c370300200341386a41106a200941106a290300220d370300200341386a41086a200941086a290300220e37030020032009290300220f3703382000200a3703002000200f370308200041106a200e370300200041186a200d370300200041206a200c3703000b200341e0006a24000be00802047f037e230041206b220324002001280200280200220128020421042001280200210102400240024002400240024002400240024002400240024020022d00000e050001020304000b200241016a21024100210520010e0406040507060b200241086a210641012105200241016a210220010e0405030406050b200241086a2106200241016a21024102210520010e0404020305040b200241086a2106200241016a21024103210520010e0403010204030b41042105200241046a210220010e0402000103020b20054102470d04024020022004470d00200621020c040b200228000021012006210220012004280000470d040c030b20054103470d03024020022004470d00200621020c030b200228000021012006210220012004280000460d020c030b20054101470d02024020022004470d00200621020c020b200228000021012006210220012004280000470d020c010b20054104470d010b2002280200210120032002280208220236020c20032001360208200341003a0010200341106a20012002410047220510ce041a024020022005490d002003200220056b220436020c2003200120056a22013602082002450d0120032d0010417f6a220241044b0d010240024002400240024002400240024020020e050001020304000b200341106a200341086a104120032802102202450d08200329021421074200210820034200370310200341106a20032802082204200328020c2205410820054108491b220110ce041a2003200520016b36020c2003200420016a3602082007a72101200541074b0d052001450d08200210290c080b20034200370310200341106a20012004410820044108491b220210ce041a2003200420026b36020c2003200120026a360208200441074d0d0720032903102107200341106a200341086a104120032802102205450d072003290214210820034200370310200341106a20032802082204200328020c2202410820024108491b220110ce041a2003200220016b36020c2003200420016a3602082008a72104200241074b0d032004450d07200510290c070b20034200370310200341106a20012004410820044108491b220210ce041a2003200420026b36020c2003200120026a360208200441074d0d0620032903102107420221080c040b20034200370310200341106a20012004410820044108491b220210ce041a2003200420026b36020c2003200120026a360208200441074d0d0520032903102107420321080c030b20034200370310200341106a20012004410820044108491b220210ce041a2003200420026b36020c2003200120026a360208200441074d0d0420032903102107420421080c020b2008422088210920032903102208422088a721012008a72102420121080c010b2007422088a72105200329031021070b2000200436021c200020013602142000200737030820002008370300200041206a2009370200200041186a2005360200200041106a20023602000c020b20052002103e000b200042053703000b200341206a24000bec0301097f230041106b2202240020002802002103200220002802082204360204200241046a2001103002400240024002400240200141046a2802002205200141086a28020022066b2004490d00200128020021050c010b200620046a22072006490d0320054101742206200720072006491b22064100480d030240024020050d002006102721050c010b200128020020052006102821050b2005450d0120012005360200200141046a2006360200200141086a28020021060b200141086a2207200620046a360200200520066a2003200410ce041a200028020c21062002200041146a2802002200360208200241086a2001103002402000450d0020062000410c6c6a2108200141046a21090340200628020021032002200641086a280200220036020c2002410c6a200110300240024020092802002205200728020022046b2000490d00200128020021050c010b200420006a220a2004490d0520054101742204200a200a2004491b22044100480d050240024020050d002004102721050c010b200128020020052004102821050b2005450d042001200536020020092004360200200728020021040b2007200420006a360200200520046a2003200010ce041a2006410c6a22062008470d000b0b200241106a24000f0b20064101102a000b20044101102a000b102b000be23101077f23004180016b22082400024002402002410c6a280200200241106a28020010062209417f460d00410c1027220a0d01410c4104102a000b1063000b200a2009360208200a4281808080103702000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002404101450d00200a410141016a3602004101417e460d00200a410141027236020041041027220b450d01200b200a360200200a280208210c41031027220d450d02200d41026a41002d009cb0453a0000200d41002f009ab0453b000041061027220e450d03200e41046a41002f00a0f4423b0000200e410028009cf442360000412010272209450d042009200c36021c2009410136021820094286808080e0003702102009200e36020c20094283808080303702042009200d360200200a200a280200417f6a220d3602000240200d0d00200a2802081007200a200a280204417f6a220d360204200d0d00200a10290b41031027220d450d05200d41026a41002d009cb0453a0000200d41002f009ab0453b000041031027220e450d06200e41026a41002d009fb0453a0000200e41002f009db0453b00002009412041c00010282209450d072009410636023c2009410036023820094283808080303702302009200e36022c20094283808080303702242009200d36022041031027220d450d08200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410f1027220e450d09200e41076a41002900af8845370000200e41002900a88845370000200941c00041800110282209450d0a2009410736025c200941003602582009428f808080f0013702502009200e36024c20094283808080303702442009200d36024041031027220d450d0b200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410f1027220e450d0c200e41076a41002900be8845370000200e41002900b788453700002009410836027c200941003602782009428f808080f0013702702009200e36026c20094283808080303702642009200d36026041031027220d450d0d200d41026a41002d009cb0453a0000200d41002f009ab0453b000041081027220e450d0e200e42e5f0d1fbb5ac98b6ec00370000200941800141800210282209450d0f2009410936029c012009410036029801200942888080808001370290012009200e36028c012009428380808030370284012009200d3602800141031027220d450d10200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410a1027220e450d11200e41086a41002f00d688453b0000200e41002900ce88453700002009410a3602bc01200941003602b8012009428a808080a0013702b0012009200e3602ac0120094283808080303702a4012009200d3602a00141031027220d450d12200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410a1027220e450d13200e41086a41002f00e088453b0000200e41002900d888453700002009410b3602dc01200941003602d8012009428a808080a0013702d0012009200e3602cc0120094283808080303702c4012009200d3602c00141031027220d450d14200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410a1027220e450d15200e41086a41002f00ea88453b0000200e41002900e288453700002009410c3602fc01200941003602f8012009428a808080a0013702f0012009200e3602ec0120094283808080303702e4012009200d3602e00141031027220d450d16200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410b1027220e450d17200e41076a41002800f38845360000200e41002900ec8845370000200941800241800410282209450d182009410d36029c0220094100360298022009428b808080b001370290022009200e36028c022009428380808030370284022009200d3602800241031027220d450d19200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410d1027220e450d1a200e41056a41002900fc8845370000200e41002900f788453700002009410e3602bc02200941003602b8022009428d808080d0013702b0022009200e3602ac0220094283808080303702a4022009200d3602a00241031027220d450d1b200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410c1027220e450d1c200e41086a410028008c8945360000200e410029008489453700002009410f3602dc02200941003602d8022009428c808080c0013702d0022009200e3602cc0220094283808080303702c4022009200d3602c00241031027220d450d1d200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410b1027220e450d1e200e41076a41002800978945360000200e41002900908945370000200941103602fc02200941003602f8022009428b808080b0013702f0022009200e3602ec0220094283808080303702e4022009200d3602e00241031027220e450d1f200e41026a41002d009cb0453a0000200e41002f009ab0453b000041151027220d450d20200d410d6a41002900a88945370000200d41086a41002900a38945370000200d410029009b89453700002009411136029c03200941003602980320094295808080d002370290032009200d36028c032009428380808030370284032009200e3602800341031027220d450d21200d41026a41002d009cb0453a0000200d41002f009ab0453b0000410a1027220e450d22200e41086a41002f00b889453b0000200e41002900b08945370000200941123602bc03200941003602b8032009428a808080a0013702b0032009200e3602ac0320094283808080303702a4032009200d3602a00341031027220d450d23200d41026a41002d009cb0453a0000200d41002f009ab0453b000041071027220e450d24200e41036a41002800bd8945360000200e41002800ba8945360000200941133602dc03200941003602d80320094287808080f0003702d0032009200e3602cc0320094283808080303702c4032009200d3602c00341031027220e450d25200e41026a41002d009cb0453a0000200e41002f009ab0453b000041111027220d450d26200d41106a41002d00d189453a0000200d41086a41002900c98945370000200d41002900c18945370000200941143602fc03200941003602f8032009429180808090023702f0032009200d3602ec0320094283808080303702e4032009200e3602e00341031027220d450d27200d41026a41002d009cb0453a0000200d41002f009ab0453b000041101027220e450d28200e41086a41002900da8945370000200e41002900d2894537000020094180044180081028220c450d29200c411536029c04200c410036029804200c4290808080800237029004200c200e36028c04200c42838080803037028404200c200d36028004410310272209450d2a200941026a41002d009cb0453a0000200941002f009ab0453b000041101027220d450d2b200d41086a41002900ea8945370000200d41002900e28945370000200c41163602bc04200c41003602b804200c429080808080023702b004200c200d3602ac04200c4283808080303702a404200c20093602a00441031027220d450d2c200d41026a41002d009cb0453a0000200d41002f009ab0453b0000411110272209450d2d200941106a41002d00828a453a0000200941086a41002900fa8945370000200941002900f28945370000200c41173602dc04200c41003602d804200c429180808090023702d004200c20093602cc04200c4283808080303702c404200c200d3602c00441031027220d450d2e200d41026a41002d009cb0453a0000200d41002f009ab0453b0000411610272209450d2f2009410e6a41002900918a45370000200941086a410029008b8a45370000200941002900838a45370000200c41183602fc04200c41003602f804200c4296808080e0023702f004200c20093602ec04200c4283808080303702e404200c200d3602e00441031027220d450d30200d41026a41002d009cb0453a0000200d41002f009ab0453b0000411210272209450d31200941106a41002f00a98a453b0000200941086a41002900a18a45370000200941002900998a45370000200c411936029c05200c410036029805200c4292808080a00237029005200c200936028c05200c42838080803037028405200c200d36028005410310272209450d32200941026a41002d009cb0453a0000200941002f009ab0453b0000410b1027220d450d33200d41076a41002800b28a45360000200d41002900ab8a45370000200c411a3602bc05200c41003602b805200c428b808080b0013702b005200c200d3602ac05200c4283808080303702a405200c20093602a005410310272209450d34200941026a41002d009cb0453a0000200941002f009ab0453b000041101027220d450d35200d41086a41002900be8a45370000200d41002900b68a45370000200c411b3602dc05200c41003602d805200c429080808080023702d005200c200d3602cc05200c4283808080303702c405200c20093602c0052005417f4c0d364101210902402005450d00200510272209450d380b20092004200510ce042109200841086a41186a2005360200200841086a41146a2005360200200841086a410c6a200641086a28020036020020082003360208200841003602302008200736022c2008200a360228200820093602182008200629020037020c20082001280200360224200241146a28020021042002411c6a2802002107200841003602482008420137034020084117360278200841f8006a200841c0006a1030410021010340200c20016a2205280200210e2008200541086a2802002209360278200841f8006a200841c0006a1030024002402008280244220d2008280248220a6b2009490d002008280240210d0c010b200a20096a2206200a490d3f200d4101742203200620062003491b22064100480d3f02400240200d0d0020061027210d0c010b2008280240200d20061028210d0b200d450d3a200820063602442008200d3602400b2008200a20096a360248200d200a6a200e200910ce041a2005410c6a28020021032008200541146a280200220d360278200841f8006a200841c0006a1030024002402008280244220a2008280248220e6b200d490d00200828024021090c010b200e200d6a2209200e490d3f200a4101742206200920092006491b22064100480d3f02400240200a0d002006102721090c010b2008280240200a2006102821090b2009450d3b20082006360244200820093602402006210a0b2008200e200d6a22063602482009200e6a2003200d10ce041a02400240200541186a2802004101460d0002400240200a2006460d00200a210d0c010b200a41016a220d200a490d41200a410174220e200d200d200e491b220d4100480d4102400240200a0d00200d102721090c010b2009200a200d102821090b2009450d3e2008200d360244200820093602400b2008200641016a220a360248200920066a41013a000020082005411c6a2802002205360278200841f8006a210e0c010b02400240200a2006460d00200a210d0c010b200a41016a220d200a490d40200a410174220e200d200d200e491b220d4100480d4002400240200a0d00200d102721090c010b2009200a200d102821090b2009450d3e2008200d360244200820093602400b2008200641016a220a360248200920066a41023a000020082005411c6a2802002205360278200841f8006a210e0b0240200d200a6b41034b0d00200a41046a2205200a490d3f200d4101742206200520052006491b22054100480d3f02400240200d0d002005102721090c010b2009200d2005102821090b2009450d3e2008200536024420082009360240200e28020021050b2008200a41046a3602482009200a6a2005360000200141206a220141e005470d000b2008280244210a4102210902400240411c200420072008280240220e2008280248200841086a1008220541036a220d41024b0d0002400240200d0e03010200010b410021090b0240200a450d00200e10290b2009450d01200841c0006a41306a200841086a41306a280200360200200841c0006a41286a200841086a41286a290300370300200841c0006a41206a200841086a41206a290300370300200841c0006a41186a200841086a41186a290300370300200841c0006a41106a200841086a41106a290300370300200841c0006a41086a200841086a41086a290300370300200820082903083703402000200841c0006a2009107b4100210e410121060c420b41041027220d450d3f200b280200220928020041016a220641014d0d0120092006360200200d20093602000240200a450d00200e10290b2002280204210e20022802002106200841003602482008420137034020084100360278200841f8006a200841c0006a10302008280240210a2008280244210120082802482103410a107c2209450d4002400240024002400240024020052006200e200a20032009410a200841086a100941036a220e41034b0d0041012106200e0e0402000001020b41c0cdc1001058000b2008410936027c2008200941016a36027820092d0000220e41014b0d0102400240200e0e020100010b200841c0006a200841f8006a107d2008280240417e714104460d020b410021060b2009102902402001450d00200a10290b4103210920060d010c020b200910292001450d00200a10290b410221090b200841c0006a41306a200841086a41306a280200360200200841c0006a41286a200841086a41286a290300370300200841c0006a41206a200841086a41206a290300370300200841c0006a41186a200841086a41186a290300370300200841c0006a41106a200841086a41106a290300370300200841c0006a41086a200841086a41086a290300370300200820082903083703402000200841c0006a2009107b2005100a200d28020022092009280200417f6a3602000240200d28020022092802000d0020092802081007200d28020022092009280204417f6a360204200d28020022092802040d00200910290b200d10294101210e410021060c410b200041a083c00036020420004102360200200041086a41103602000240200828020c2209450d00200841086a41086a280200450d00200910290b0240200828021c450d00200828021810290b200828022822092009280200417f6a3602000240200828022822092802000d0020092802081007200828022822092009280204417f6a360204200828022822092802040d00200910290b024020082802302209450d00200841346a280200450d00200910290b4100210a03400240200c200a6a220941046a280200450d00200928020010290b0240200941106a280200450d002009410c6a28020010290b200a41206a220a41e005470d000b200c1029200b28020022092009280200417f6a3602000240200b28020022092802000d0020092802081007200b28020022092009280204417f6a360204200b28020022092802040d00200910290b200b10290c410b00000b41044104102a000b41034101102a000b41064101102a000b41204104102a000b41034101102a000b41034101102a000b41c0004104102a000b41034101102a000b410f4101102a000b4180014104102a000b41034101102a000b410f4101102a000b41034101102a000b41084101102a000b4180024104102a000b41034101102a000b410a4101102a000b41034101102a000b410a4101102a000b41034101102a000b410a4101102a000b41034101102a000b410b4101102a000b4180044104102a000b41034101102a000b410d4101102a000b41034101102a000b410c4101102a000b41034101102a000b410b4101102a000b41034101102a000b41154101102a000b41034101102a000b410a4101102a000b41034101102a000b41074101102a000b41034101102a000b41114101102a000b41034101102a000b41104101102a000b4180084104102a000b41034101102a000b41104101102a000b41034101102a000b41114101102a000b41034101102a000b41164101102a000b41034101102a000b41124101102a000b41034101102a000b410b4101102a000b41034101102a000b41104101102a000b1039000b20054101102a000b20064101102a000b20064101102a000b200d4101102a000b200d4101102a000b20054101102a000b102b000b41044104102a000b410a4101102a000b4100210a03400240200c200a6a220941046a280200450d00200928020010290b0240200941106a280200450d002009410c6a28020010290b200a41206a220a41e005470d000b200c1029200b28020022092009280200417f6a3602000240200b28020022092802000d0020092802081007200b28020022092009280204417f6a360204200b28020022092802040d00200910290b200b1029410021092006410047200e720d002005100a0340200d20096a220a28020022052005280200417f6a3602000240200a28020022052802000d0020052802081007200a28020022052005280204417f6a360204200a280200220a2802040d00200a10290b200941046a22094104470d000b200d10290b20084180016a24000b0a0041b083c0001058000b5101027e024002402003450d002002280200450d010b4182abc10041f403104e000b2001280224220342002003290308220420023502047d2205200520045622021b37030820004105410420021b3602000b9d0f05047f027e027f017e027f230041d00c6b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320022802042105200241246a2802002106200241346a28020021030240200241146a2802002207450d004105210220012802002802202802502802bc012003490d070b200441306a4200370300200441286a4200370300200441206a420037030020012802242202420020022903082208427f200128021c2903482209420586200942ffffffffffffffff07832009521b7d22092009200856220a1b3703082004420037031841052102200a0d060240024020012802202802082005200441186a4120101241026a220a41024b0d00200a0e03080001080b4194c0c5001058000b024002400240024020070d004100210b0c010b200441086a200128021c29034842002003ad220c420010d3042001280224220a4200200a2903082209427f200429030820042903104200521b7d22082008200956220a1b370308200a0d090240024020030d00410021034101210b4200210c0c010b0240024020034100480d0020031027220b0d0120034101102a000b102b000b200b21054100210a024020034102490d00200b41002003417f6a220a10cd04200a6a21050b200541003a0000200a41016a21030b02400240024020012802202802082006200b2003101241026a220a41024b0d00200a0e03010002010b4194c0c5001058000b200c50450d020c0a0b200b450d09200c2003ad4220868421090b20012802002103200441386a41186a2201200441186a41186a290300370300200441386a41106a220a200441186a41106a290300370300200441386a41086a2205200441186a41086a2903003703002004200429031837033820032802202107200b450d0120072802502802bc012009422088a74f0d012009a7450d080b200b10290c070b200441d8006a41186a2001290300370300200441d8006a41106a200a290300370300200441d8006a41086a200529030037030020042004290338370358200728021c0d042007417f36021c200441b0016a200741f4006a290000370300200441a8016a200741ec006a290000370300200441a0016a200741e4006a2900003703002004200729005c3703980102400240200741206a220d280200220a418883c000460d00200741246a28020021060c010b41002106200441f0096a410041e00210cd041a200441d0016a410041a00810cd041a41880b1027220a450d06200a41003b0106200a4100360200200a41086a200441f0096a41e00210ce041a200a41e8026a200441d0016a41a00810ce041a200741246a41003602002007200a3602200b024002400340200a2f0106220e4105742105410021024100210302400240034020052002460d0120044198016a200a20026a41086a412010d0042201450d02200241206a2102200341016a21032001417f4a0d000b2003417f6a210e0b2006450d022006417f6a2106200a200e4102746a41880b6a280200210a0c010b0b200741286a2101410121020c010b200441f8006a41186a20044198016a41186a290300370300200441f8006a41106a20044198016a41106a290300370300200441f8006a41086a20044198016a41086a2903003703002004200429039801370378200741286a210141002106200e2103410021020b0240024020020d002004418c0a6a200441f8006a41086a290300370200200441940a6a200441f8006a41106a2903003702002004419c0a6a200441f8006a41186a290300370200200420013602800a200420033602fc092004200d3602f8092004200a3602f409200420063602f009200420042903783702840a200441f0016a20042903c001370300200441f8016a200441c0016a41086a29030037030020044184026a4200370200200442003703e801200442003703d0012004418883c00036028002200441003a008c022004418d026a20042900980137000020044195026a20044198016a41086a2900003700002004419d026a20044198016a41106a290000370000200441a5026a20044198016a41186a290000370000200441ac026a200441b7016a280000360000200441f0096a200441d0016a10de0121020c010b200441e8016a4200370300200441e4016a418883c000360200200441003602f001200441003602e001200442003703d8012004418883c0003602d401200441003602d001200a200341e0006c6a41e8026a2102200441d0016a10d6010b200441d0016a41186a200441d8006a41186a290300370300200441d0016a41106a200441d8006a41106a290300370300200441d0016a41086a200441d8006a41086a290300370300200420042903583703d0012004200937029c012004200b36029801200441f0096a200241306a200441d0016a20044198016a10df01024020042802f009450d0020042802f4092202450d00200441f8096a280200450d00200210290b2007200728021c41016a36021c410421020c060b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b41c8a8c1004110200441d0016a41f0a8c10010a201000b41880b4108102a000b20002002360200200441d00c6a24000b900302017f027e230041c0006b22042400024002402003450d0020022802000d0020022802042103200441186a4200370300200441106a4200370300200441086a420037030020012802242202420020022903082205427f200128021c2903482206420586200642ffffffffffffffff07832006521b7d2206200620055622021b3703082004420037030002400240024020020d00024002402001280220280208200320044120101241026a220241024b0d0020020e03020001020b4194c0c5001058000b200441206a20012802002802202202411c6a200241dc006a200241106a410020022802101b200410dd012004280220450d01200441306a41086a2203200441206a41086a28020036020020042004290320370330200141106a21020240200141146a280200450d00200228020010290b20022004290330370200200241086a2003280200360200410021010c020b200041053602000c030b200141186a4100360200410121010b20004100360200200020013602040c010b4182abc10041f403104e000b200441c0006a24000bb40d06027f017e047f027e027f027e230041b0016b220424000240024002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241286a2903002106200241346a2802002107200241c4006a2802002108200241d4006a2802002109200241e4006a280200210a200441206a200128021c2903484200200241146a2802002202ad420010d3042001280224220342002003290308220b427f200429032020042903284200521b7d220c200c200b5622031b37030820030d0d0240024020020d0041002102410121034100210d0c010b20024100480d0b200210272203450d082003210e4100210d024020024102490d00200341002002417f6a220d10cd04200d6a210e0b200e41003a0000200d41016a210d0b024002400240200128022028020820052003200d101241026a220541024b0d0020050e03010002010b4194c0c5001058000b2002450d0e200310290c0e0b2003450d0d20044180016a200d4120200d412049220e1b22056a41004100412020056b2005411f4b1b10cd041a20044180016a2003200510ce041a02400240200e0d00200441306a41186a20044180016a41186a290000370300200441306a41106a20044180016a41106a290000370300200441306a41086a20044180016a41086a290000370300200420042900800137033002402002450d00200310290b200441106a200128021c29034842002008ad420010d3042001280224220242002002290308220b427f200429031020042903184200521b7d220c200c200b5622021b37030820020d0f0240024020080d004100210841012102410021030c010b20084100480d0d200810272202450d0b2002210541002103024020084102490d00200241002008417f6a220310cd0420036a21050b200541003a0000200341016a21030b024002402001280220280208200720022003101241026a220541024b0d0020050e03010003010b4194c0c5001058000b2008450d0f200210290c0f0b2002450d0e200310290c0e0b20020d090c0d0b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b20024101102a000b20084101102a000b2004420037038801200442003703800120044180016a20022003411020034110491b10ce041a02402003410f4b0d002008450d04200210290c040b20044188016a290300210f200429038001211002402008450d00200210290b2004200128021c2903484200200aad420010d3042001280224220242002002290308220b427f200429030020042903084200521b7d220c200c200b5622021b37030820020d030240200a0d004100210a41012102410021030c030b200a4100480d00200a102722020d01200a4101102a000b102b000b41012103200221050240200a4102490d0020024100200a417f6a220310cd0420036a2105200a21030b200541003a00000b0240024002402001280220280208200920022003101241026a220541024b0d0020050e03010002010b4194c0c5001058000b200a450d01200210290c010b2002450d00200141186a4100360200200141146a280200210d200128021021082001420137021020012802242205290308220c210b0240024002402006500d002006210b200c2006540d010b2005200c200b7d3703082005290310210c200441d0006a41186a200541186a2903003703002004200b3703582004200b3703502004200c3703602001280200280220210720044180016a41186a200441306a41186a29030037030020044180016a41106a200441306a41106a29030037030020044180016a41086a200441306a41086a2903003703002004200429033037038001200441003602a8012004200d3602a401200420083602a001200441f0006a200720044180016a2010200f200441d0006a20022003200441a0016a10e101200441f0006a41086a290300210b2004280274210d200428027021082005200429035820052903087c3703084101210320084101460d01200d450d010240200141146a2203280200450d00200128021010290b2001200d3602102003200b370200410021030c010b41012103200d450d00200810290b0240200a450d00200210290b20004100360200200020033602040c010b200041053602000b200441b0016a24000bfe0f06027f017e047f027e027f027e230041e0016b22042400024002400240024002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042105200241286a2903002106200241346a2802002107200241c4006a2802002108200241d4006a2802002109200241e4006a280200210a200441286a200128021c2903484200200241146a2802002202ad420010d3042001280224220342002003290308220b427f200429032820042903304200521b7d220c200c200b5622031b37030820030d0a0240024020020d0041002102410121034100210d0c010b20024100480d0f200210272203450d082003210e4100210d024020024102490d00200341002002417f6a220d10cd04200d6a210e0b200e41003a0000200d41016a210d0b024002400240200128022028020820052003200d101241026a220541024b0d0020050e03010002010b4194c0c5001058000b2002450d0b200310290c0b0b2003450d0a200441f8006a200d4120200d412049220e1b22056a41004100412020056b2005411f4b1b10cd041a200441f8006a2003200510ce041a02400240200e0d00200441386a41186a200441f8006a41186a290000370300200441386a41106a200441f8006a41106a290000370300200441386a41086a200441f8006a41086a2900003703002004200429007837033802402002450d00200310290b200441186a200128021c29034842002008ad420010d3042001280224220242002002290308220b427f200429031820042903204200521b7d220c200c200b5622021b37030820020d0c0240024020080d004100210841012102410021030c010b20084100480d11200810272202450d0b2002210541002103024020084102490d00200241002008417f6a220310cd0420036a21050b200541003a0000200341016a21030b024002402001280220280208200720022003101241026a220541024b0d0020050e03010003010b4194c0c5001058000b2008450d0c200210290c0c0b2002450d0b200310290c0b0b20020d090c0a0b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b20024101102a000b20084101102a000b200442003703c001200442003703b801200441b8016a20022003411020034110491b10ce041a02402003410f4b0d002008450d01200210290c010b200441c0016a290300210f20042903b801211002402008450d00200210290b200441086a200128021c2903484200200aad420010d3042001280224220242002002290308220b427f200429030820042903104200521b7d220c200c200b5622021b37030820020d0002400240200a0d004100210a41012102410021030c010b200a4100480d05200a10272202450d0641012103200221050240200a4102490d0020024100200a417f6a220310cd0420036a2105200a21030b200541003a00000b0240024002402001280220280208200920022003101241026a220541024b0d0020050e03010002010b4194c0c5001058000b200a450d01200210290c010b2002450d00200141186a410036020020012802242205290308220c210b02402006500d004101210d2006210b200c2006540d030b2005200c200b7d3703082005290310210c20044198016a41186a200541186a2903003703002004200b3703a0012004200b370398012004200c3703a801200441b8016a20012802002802202010200f20044198016a200441386a2002200310da014101210d20042d00b8014101460d01200441f8006a41186a200441d1016a290000220b370300200441f8006a41106a200441c9016a290000220c370300200441f8006a41086a200441c1016a2900002206370300200441d8006a41086a22032006370300200441d8006a41106a220d200c370300200441d8006a41186a2208200b370300200420042900b901220b370378200520042903a00120052903087c3703082004200b370358200441b8016a41186a2008290300370300200441b8016a41106a200d290300370300200441b8016a41086a2003290300370300200420042903583703b80102400240200141146a2802002205200141186a28020022036b4120490d00200128021021050c010b200341206a220d2003490d0520054101742203200d200d2003491b22034100480d050240024020050d002003102721050c010b200128021020052003102821050b2005450d0420012005360210200141146a2003360200200141186a28020021030b200141186a200341206a360200200520036a220341186a200441b8016a41186a290300370000200341106a200441b8016a41106a290300370000200341086a200441b8016a41086a290300370000200320042903b8013700004100210d0c020b200041053602000c050b200520042903a00120052903087c370308200441d8006a41086a200441f8006a41086a290300370300200441d8006a41106a200441f8006a41106a290300370300200441d8006a41186a200441f8006a41186a290300370300200420042903783703580b0240200a450d00200210290b200041003602002000200d3602040c030b20034101102a000b102b000b200a4101102a000b200441e0016a24000bc70403027f027e057f230041106b22042400024002400240024002402003450d0020022802000d0020034101460d0120022802100d01200228020421052004200128021c2903184200200241146a2802002203ad420010d30420012802242202420020022903082206427f200429030020042903084200521b7d2207200720065622021b370308024020020d0020012802042102200141003602042002450d0302400240200141086a290200220642ffffffff0f560d000240024020032006422088a722084b0d002003200820032008491b21030c010b024002402006a7220920086b200320086b220a490d00200821090c010b2008200a6a220b2008490d092009410174220c200b200b200c491b220b4100480d090240024020090d00200b102721020c010b20022009200b102821020b2002450d082006422088a72109200bad21060b200220096a210b0240200a4102490d00200b410020032008417f7322086a10cd041a2002200920036a20086a22096a210b0b200b41003a0000200941016a21030b024002402001280220280208200520022003101241026a220841024b0d0020080e03010003010b4194c0c5001058000b2006a7450d02200210290c020b41d08bc3001058000b2006a72108024020012802282205450d002001412c6a280200450d00200510290b20012002360228200141306a20033602002001412c6a20083602000b20004105360200200441106a24000f0b4182abc10041f403104e000b4182abc10041f403104e000b41f6aec10041fd00104e000b200b4101102a000b102b000bf00101037f41002104200141186a4100360200200128020021050240024002400240200141146a28020022064120490d00200128021021060c010b200641017422044120200441204b1b22044100480d020240024020060d002004102721060c010b200128021020062004102821060b2006450d0120012006360210200141146a2004360200200141186a28020021040b200141186a200441206a360200200620046a220141186a2005413c6a290000370000200141106a200541346a290000370000200141086a2005412c6a29000037000020012005290024370000200041043602000f0b20044101102a000b102b000bf60101037f41002104200141186a4100360200200128020028022021050240024002400240200141146a28020022064120490d00200128021021060c010b200641017422044120200441204b1b22044100480d020240024020060d002004102721060c010b200128021020062004102821060b2006450d0120012006360210200141146a2004360200200141186a28020021040b200141186a200441206a360200200620046a220141186a200541f4006a290000370000200141106a200541ec006a290000370000200141086a200541e4006a2900003700002001200529005c370000200041043602000f0b20044101102a000b102b000bd50102027f027e41002104200141186a41003602002001280224220541186a2903002106200529031021070240024002400240200141146a28020022054110490d00200128021021050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102721050c010b200128021020052004102821050b2005450d0120012005360210200141146a2004360200200141186a28020021040b200141186a200441106a360200200520046a2201200637000820012007370000200041043602000f0b20044101102a000b102b000bc20103017f017e017f41002104200141186a4100360200200128022429030821050240024002400240200141146a28020022064108490d00200128021021060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102721060c010b200128021020062004102821060b2006450d0120012006360210200141146a2004360200200141186a28020021040b200141186a200441086a360200200620046a2005370000200041043602000f0b20044101102a000b102b000b9d04020b7f027e230041206b22042400200141186a41003602000240024002402001280200280220220528021c41016a220641004c0d00200541dc006a21072005200636021c200541206a2108200541246a28020021090240024003402008280200220a41086a210b200a2f0106220c41057421084100210d0240024003402008450d012007200b412010d004220e450d02200841606a2108200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a210c0b2009450d022009417f6a2109200a200c4102746a41880b6a21080c010b0b200a200d41e0006c6a220841e8026a280200450d00200841f8026a290300210f200841f0026a29030021100c010b200441086a2005412c6a2802002007200541306a28020028021c110200200441106a290300210f200528021c2106200429030821100b20052006417f6a36021c02400240200141146a280200220b200141186a28020022086b4110490d002001280210210b0c010b200841106a220d2008490d03200b4101742208200d200d2008491b22084100480d0302400240200b0d0020081027210b0c010b2001280210200b20081028210b0b200b450d022001200b360210200141146a2008360200200141186a28020021080b200141186a200841106a360200200b20086a2208200f3700082008201037000020004104360200200441206a24000f0b41d8a8c1004118200441186a4180a9c10010a201000b20084101102a000b102b000bd50102027f027e41002104200141186a41003602002001280200220541086a2903002106200529030021070240024002400240200141146a28020022054110490d00200128021021050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102721050c010b200128021020052004102821050b2005450d0120012005360210200141146a2004360200200141186a28020021040b200141186a200441106a360200200520046a2201200637000820012007370000200041043602000f0b20044101102a000b102b000bf30403047f027e017f230041306b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0141052105200241146a2802002203200128021c220628026c4b0d06200228020421072004200629034842002003ad420010d30420012802242202420020022903082208427f200429030020042903084200521b7d2209200920085622021b37030820020d060240024020030d004100210341012102410021060c010b20034100480d04200310272202450d05410121062002210a024020034102490d00200241002003417f6a220610cd0420066a210a200321060b200a41003a00000b0240024002402001280220280208200720022006101241026a220741024b0d0020070e03010002010b4194c0c5001058000b2003450d070c060b2002450d06200141186a22054100360200200441106a2002200610db0102400240200141146a2802002206200528020022056b4120490d00200128021021060c010b200541206a22072005490d0420064101742205200720072005491b22054100480d040240024020060d002005102721060c010b200128021020062005102821060b2006450d0320012006360210200141146a2005360200200141186a28020021050b200141186a200541206a360200200620056a220141186a200441106a41186a290300370000200141106a200441106a41106a290300370000200141086a200441106a41086a290300370000200120042903103700004104210520030d050c060b4182abc10041f403104e000b4182abc10041f403104e000b20054101102a000b102b000b20034101102a000b200210290b20002005360200200441306a24000bc20103017f017e017f41002104200141186a4100360200200128020029031021050240024002400240200141146a28020022064108490d00200128021021060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102721060c010b200128021020062004102821060b2006450d0120012006360210200141146a2004360200200141186a28020021040b200141186a200441086a360200200620046a2005370000200041043602000f0b20044101102a000b102b000bee0704027f027e037f027e230041f0036b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441206a200128021c2903484200200241146a2802002202ad420010d30420012802242203420020032903082206427f200429032020042903284200521b7d2207200720065622031b3703084105210820030d060240024020020d004100210241012103410021090c010b20024100480d05200210272203450d06410121092003210a024020024102490d00200341002002417f6a220910cd0420096a210a200221090b200a41003a00000b024002400240024002402001280220280208200520032009101241026a220541024b0d0020050e03010002010b4194c0c5001058000b20020d010c090b2003450d08200420093602bc01200420033602b801200441c8026a200441b8016a103c024020042802c80222054112460d00200441c0016a200441c8026a41047241840110ce041a20042005360230200441306a410472200441c0016a41840110ce041a02402002450d00200310290b200441003602d002200442013703c802200441306a200441c8026a103220042802d0022103024020042802cc02450d0020042802c80210290b200128022422022903102206200241186a2903002207844200510d05200441106a2003ad42004280c8afa025420010d30420042004290310220b4280a094a58d1d7c220c200441106a41086a290300200c200b54ad7c2006200710d40420024200200229030822062004290300427f200441086a290300501b7d220720072006561b37030820072006580d02200441306a103d0c090b2002450d080b200310290c070b20012802002102200441c0016a200441306a41880110ce041a200441e0026a2002280220220241f4006a290000370300200441d8026a200241ec006a290000370300200441c8026a41086a200241e4006a2900003703002004200229005c3703c802200441e8026a200441c0016a41880110ce041a0240200241cc006a2802002201200241c8006a280200470d00200141016a22032001490d0520014101742208200320032008491b2203ad42a8017e2206422088a70d052006a722084100480d050240024020010d002008102721010c010b2002280244200141a8016c2008102821010b2001450d0420022001360244200241c8006a2003360200200228024c21010b2002280244200141a8016c6a200441c8026a41a80110ce041a2002200228024c41016a36024c410421080c060b4182abc10041f403104e000b4182abc10041f403104e000b41fcecc2001058000b20084108102a000b102b000b20024101102a000b20002008360200200441f0036a24000b1600200041003602002000200141186a2802003602040bab0202057f027e230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d02410521030240200141186a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042107200128021021082004200128021c29035042002005ad420010d30420012802242202420020022903082209427f200429030020042903084200521b7d220a200a20095622021b37030820020d000240024020012802202802082007200820066a2005101341026a220241024b0d0020020e03020001020b41fcc0c5001058000b410421030b20002003360200200441106a24000f0b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000bd30b05047f027e037f017e047f23004190016b2204240002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d03200241246a2802002105200241346a280200210602400240024002400240200241146a2802002203450d0020022802042107200441306a200128021c29034842002003ad420010d30420012802242202420020022903082208427f200429033020042903384200521b7d22092009200856220a1b37030841052102200a0d0e20034100480d0a20031027220a450d0b200a210b4100210c024020034102490d00200a41002003417f6a220c10cd04200c6a210b0b200b41003a0000024020012802202802082007200a200c41016a220c101241026a220341024b0d0020030e03040002040b4194c0c5001058000b4101210c410021074100210b0c010b2004200c3602742004200a360270200441c0006a200441f0006a102d2004280240220c450d01200441c8006a28020021072004280244210b200a10292007200128021c28025c4b0d0b0b200c2007410041202007676b10e001024020074102490d00200c21022007210303402002200241206a220a412010d004450d0c200a21022003417f6a220341024f0d000b0b200441206a200128021c29034842002006ad220d420010d30420012802242202420020022903082208427f200429032020042903284200521b7d2209200920085622021b37030820020d0a0240024020060d0041002106410121024100210a0c010b20064100480d08200610272202450d0a4101210a20022103024020064102490d00200241002006417f6a220310cd0420036a21032006210a0b200341003a00000b024002400240200128022028020820052002200a101241026a220341024b0d0020030e03010002010b4194c0c5001058000b2006450d0b200210290c0b0b2002450d0a2004200128021c220529032842002007ad420010d304200441106a20052903204200200d420010d30420012802242103427f2109024020042903184200520d0020042903084200520d002004290310220820042903007c220d2008540d00427f200d20052903307c22082008200d541b21090b200342002003290308220820097d220920092008561b37030820092008580d012006450d0a200210290c0a0b200a10290c0a0b200441f0006a41086a22052001280200280220220141e4006a290000370300200441f0006a41106a220e200141ec006a290000370300200441f0006a41186a220f200141f4006a2900003703002004200129005c3703700240200141c0006a28020022032001413c6a280200470d00200341016a22102003490d0620034101742211201020102011491b2210ad42e8007e2208422088a70d062008a722114100480d060240024020030d002011102721030c010b2001280238200341e8006c2011102821030b2003450d05200120033602382001413c6a2010360200200128024021030b2001280238200341e8006c6a220341053a000020032004290370370001200341096a2005290300370000200341116a200e290300370000200341196a200f290300370000200341216a20042f006d3b0000200341236a200441ef006a2d00003a00002003412c6a200a360000200341286a2006360000200341246a2002360000200341306a2004290340370300200341386a200441c0006a41086a290300370300200341c0006a200441c0006a41106a290300370300200341c8006a200441c0006a41186a290300370300200341d0006a200441e0006a290300370300200341e0006a2007360200200341dc006a200b3602002003200c3602582001200128024041016a360240410421020c090b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b4182abc10041f403104e000b20114108102a000b102b000b20034101102a000b20064101102a000b41052102200b450d00200c10290b2000200236020020044190016a24000bef0a03027f027e057f230041f00b6b22042400024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441086a200128021c2903484200200241146a2802002202ad420010d30420012802242203420020032903082206427f200429030820042903104200521b7d2207200720065622031b3703084105210820030d040240024020020d004100210241012103410021090c010b0240024020024100480d002002102722030d0120024101102a000b102b000b410121092003210a024020024102490d00200341002002417f6a220910cd0420096a210a200221090b200a41003a00000b024002400240024002402001280220280208200520032009101241026a220541024b0d0020050e03010002010b4194c0c5001058000b20020d010c070b2003450d062004420037037820044200370370200441f0006a20032009411020094110491b10ce041a2009410f4b0d012002450d060b200310290c050b200441f8006a29030021062004290370210702402002450d00200310290b2001280200280220220528021c0d022005417f36021c200441d0006a200541f4006a290000370300200441c8006a200541ec006a290000370300200441c0006a200541e4006a2900003703002004200529005c37033802400240200541206a220b2802002208418883c000460d00200541246a280200210a0c010b4100210a20044190096a410041e00210cd041a200441f0006a410041a00810cd041a41880b10272208450d04200841003b010620084100360200200841086a20044190096a41e00210ce041a200841e8026a200441f0006a41a00810ce041a200541246a4100360200200520083602200b02400240034020082f0106220c4105742109410021024100210102400240034020092002460d01200441386a200820026a41086a412010d0042203450d02200241206a2102200141016a21012003417f4a0d000b2001417f6a210c0b200a450d02200a417f6a210a2008200c4102746a41880b6a28020021080c010b0b200541286a2103410121020c010b200441186a41186a200441386a41186a290300370300200441186a41106a200441386a41106a290300370300200441186a41086a200441386a41086a29030037030020042004290338370318200541286a21034100210a200c2101410021020b0240024020020d00200441ac096a200441186a41086a290300370200200441b4096a200441186a41106a290300370200200441bc096a200441186a41186a290300370200200420033602a0092004200136029c092004200b3602980920042008360294092004200a36029009200420042903183702a40920044190016a200429036037030020044198016a200441e0006a41086a290300370300200441a4016a42003702002004420037038801200442003703702004418883c0003602a001200441003a00ac01200441ad016a2004290038370000200441b5016a200441386a41086a290000370000200441bd016a200441386a41106a290000370000200441c5016a200441386a41186a290000370000200441cc016a200441d7006a28000036000020044190096a200441f0006a10de0121020c010b20044188016a420037030020044184016a418883c00036020020044100360290012004410036028001200442003703782004418883c000360274200441003602702008200141e0006c6a41e8026a2102200441f0006a10d6010b200241286a2006370300200241206a2007370300200242013703182005200528021c41016a36021c410421080c040b4182abc10041f403104e000b4182abc10041f403104e000b41c8a8c1004110200441f0006a41f0a8c10010a201000b41880b4108102a000b20002008360200200441f00b6a24000bad04020b7f027e230041206b22042400200141186a41003602000240024002402001280200280220220528021c41016a220641004c0d00200541dc006a21072005200636021c200541206a2108200541246a28020021090240024003402008280200220a41086a210b200a2f0106220c41057421084100210d0240024003402008450d012007200b412010d004220e450d02200841606a2108200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a210c0b2009450d022009417f6a2109200a200c4102746a41880b6a21080c010b0b200a200d41e0006c6a22084180036a280200220b450d0020084190036a290300210f20084188036a29030021100c010b20042005412c6a2802002007200541306a280200280214110200200441106a290300210f200528021c2106200429030821102004280200210b0b20052006417f6a36021c02400240200141146a280200220d200141186a28020022086b4110490d002001280210210d0c010b200841106a220e2008490d03200d4101742208200e200e2008491b22084100480d0302400240200d0d0020081027210d0c010b2001280210200d20081028210d0b200d450d022001200d360210200141146a2008360200200141186a28020021080b200141186a200841106a360200200d20086a2208200f427f200b1b37000820082010427f200b1b37000020004104360200200441206a24000f0b41d8a8c1004118200441186a4180a9c10010a201000b20084101102a000b102b000b8d0303027f027e037f230041206b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d01200228020421052004200128021c2903484200200241146a2802002202ad420010d30420012802242203420020032903082206427f200429030020042903084200521b7d2207200720065622081b3703084105210320080d030240024020020d004100210241012108410021090c010b0240024020024100480d002002102722080d0120024101102a000b102b000b410121092008210a024020024102490d00200841002002417f6a220910cd0420096a210a200221090b200a41003a00000b0240024002402001280220280208200520082009101241026a220141024b0d0020010e03010002010b4194c0c5001058000b2002450d040c030b2008450d03200441106a2008200910dc01024020042802100d002004280214200441186a28020010100b4104210320020d020c030b4182abc10041f403104e000b4182abc10041f403104e000b200810290b20002003360200200441206a24000bc20103017f017e017f41002104200141186a4100360200200128020029031821050240024002400240200141146a28020022064108490d00200128021021060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102721060c010b200128021020062004102821060b2006450d0120012006360210200141146a2004360200200141186a28020021040b200141186a200441086a360200200620046a2005370000200041043602000f0b20044101102a000b102b000bdf05020a7f017e230041c0006b220424002004200136020c2004200041b8d6c50020011b3602082004200441086a102e02402004280200450d00024002400240024002400240024002400240200428020422054180022005418002491b22060d00410821070c010b2006410474220110272207450d010b02402005450d00200441206a4104722108410021094100210a410021000340200441206a200441086a107d200441306a41086a220b200841086a2802003602002004200829020037033002402004280220220c4104470d002006450d0a200710290c0a0b200041016a2101200441106a41086a220d200b28020036020020042004290330370310024020002006470d002009200120012009491b220641ffffffff00712006470d052006410474220b4100480d050240024020000d00200b102721070c010b2007200a200b102821070b2007450d040b2007200a6a2200200c360200200041046a20042903103702002000410c6a200d280200360200200941026a2109200a41106a210a2001210020052001470d000b0b2007450d07200441206a20022007200520031103002004410036023820044201370330200428022021004101102721010240024020004105460d002001450d05200141003a000020044281808080103702342004200136023020014101410210282101024020004104470d002001450d07200141003a00012004428280808020370234200420013602304202210e0c020b2001450d07200141013a0001200442828080802037023420042001360230200441206a200441306a10fe012004350238210e200428023021010c010b2001450d07200141013a00002004428180808010370234200420013602304201210e0b2001ad422086200e84210e02402006450d00200710290b200441c0006a2400200e0f0b20014108102a000b200b4108102a000b102b000b41014101102a000b41024101102a000b41024101102a000b41014101102a000b41cdccc10041f000104e000b920201027f20012802282103024002400240200241ff017122024103470d0020030d01200041003602000c020b2001412c6a2802002104024020024102470d002003450d00200141306a280200210220002003360204200041013602002000410c6a2002360200200041086a20043602000c020b200041a1a6c10036020420004102360200200041086a41103602002003450d012004450d01200310290c010b41b4a6c1001058000b024020012802042200450d00200141086a280200450d00200010290b0240200141146a280200450d00200128021010290b200128022022012001280200417f6a2200360200024020000d002001280208100720012001280204417f6a220036020420000d00200110290b0b0700200010b4040b890401057f230041106b22022400200241003a0008200241086a2001280200220320012802042204410047220510ce041a0240024020042005490d002001200420056b22063602042001200320056a2205360200024020040d00200041043602000c020b024020022d0008417f6a220441034b0d00024002400240024020040e0400010203000b20024100360208200241086a20052006410420064104491b220410ce041a2001200620046b3602042001200520046a3602000240200641034b0d00200041043602000c060b20002002280208360204200041003602000c050b20024200370308200241086a20052006410820064108491b220410ce041a2001200620046b3602042001200520046a3602000240200641074b0d00200041043602000c050b200041086a2002290308370300200041013602000c040b20024100360208200241086a20052006410420064104491b220410ce041a2001200620046b3602042001200520046a3602000240200641034b0d00200041043602000c040b20002002280208360204200041023602000c030b20024200370308200241086a20052006410820064108491b220410ce041a2001200620046b3602042001200520046a3602000240200641074b0d00200041043602000c030b200041086a2002290308370300200041033602000c020b200041043602000c010b20052004103e000b200241106a24000be40301027f230041e0006b22032400200341003a0005024002402000413f4b0d00200320004102743a0000410121040c010b02400240200041808001490d0020004180808080044f0d01200341033a0005200320004106763a000120032000410e763a0002200320004116763a0003200320004102744102723a0000410421040c020b200320004106763a000141022104200341013a0005200320004102744101723a00000c010b200341043a0005200341033a0000200320003a0001200320004108763a0002200320004110763a0003200320004118763a0004410521040b200320043a0005024002402001280200220028020822012002490d0020002802002100200320023602082003200436020c20042002470d0120002003200210ce041a200341e0006a24000f0b20022001107f000b200341286a41146a4103360200200341346a411d360200200341106a41146a41033602002003200341086a36024020032003410c6a360244200341c8006a41146a41003602002003420337021420034190d1c5003602102003411d36022c200341b8d6c5003602582003420137024c200341e4d1c5003602482003200341286a3602202003200341c8006a3602382003200341c4006a3602302003200341c0006a360228200341106a41a0d2c5001057000b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c200241c4d8c500360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41d4d8c5001057000bb90201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210420034120710d012004ad4101200110aa0121000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000b20024180016a240020000f0b2004418001103e000b2004418001103e000b11002000280200200028020420011082010bbe0f020d7f017e230041206b220324004101210402400240200228021841222002411c6a2802002802101104000d000240024020010d00410021050c010b200020016a21062000210741002105410021080240034020072109200741016a210a02400240024020072c0000220b417f4a0d0002400240200a2006470d004100210c200621070c010b20072d0001413f71210c200741026a220a21070b200b411f7121040240200b41ff0171220b41df014b0d00200c200441067472210b0c020b0240024020072006470d004100210d2006210e0c010b20072d0000413f71210d200741016a220a210e0b200d200c41067472210c0240200b41f0014f0d00200c2004410c7472210b0c020b02400240200e2006470d004100210b200a21070c010b200e41016a2107200e2d0000413f71210b0b200c4106742004411274418080f0007172200b72220b418080c400470d020c040b200b41ff0171210b0b200a21070b4102210a024002400240024002400240200b41776a220c411e4d0d00200b41dc00470d010c020b41f400210e02400240200c0e1f05010202000202020202020202020202020202020202020202030202020203050b41f200210e0c040b41ee00210e0c030b02400240200b10bd040d0002400240200b41808004490d00024002400240200b418080084f0d00200b4180fe0371410876210f41e1edc500210c410021040340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d06200e2104200d210c200d41a7eec500470d010c060b200e2004490d02200e41a6014b0d03200441a7eec5006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c080b0b200e2104200d210c200d41a7eec500470d000c050b0b200b41ef83384b0d04200b41e28b746a41e28d2c490d04200b419fa8746a419f18490d04200b41dee2746a410e490d04200b41feffff0071419ef00a460d04200b41a9b2756a4129490d04200b41cb91756a410a4b0d090c040b2004200e103e000b200e41a601107f000b200b4180fe0371410876210f41b0e8c500210c41002104024002400340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d03200e2104200d210c200d4182e9c500470d010c030b0240200e2004490d00200e41a5024b0d0220044182e9c5006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c070b0b200e2104200d210c200d4182e9c500470d010c030b0b2004200e103e000b200e41a502107f000b200b41ffff0371210441a7ebc500210a4101210e02400340200a41016a210d02400240200a2d0000220c411874411875220f4100480d00200d210a0c010b200d41e1edc500460d02200f41ff0071410874200a2d000172210c200a41026a210a0b02402004200c6b22044100480d00200e410173210e200a41e1edc500470d010b0b200e410171450d020c070b41c8dac5001058000b200b41ffff0371210441cdefc500210a4101210e0340200a41016a210d02400240200a2d0000220c411874411875220f4100480d00200d210a0c010b200d41e5f2c500460d03200f41ff0071410874200a2d000172210c200a41026a210a0b02402004200c6b22044100480d00200e410173210e200a41e5f2c500470d010b0b200e4101710d050b200b41017267410276410773ad4280808080d0008421104103210a0c020b41c8dac5001058000b0b200b210e0b2003200136020420032000360200200320053602082003200836020c0240024020082005490d0002402005450d0020052001460d00200520014f0d01200020056a2c000041bf7f4c0d010b02402008450d0020082001460d00200820014f0d01200020086a2c000041bf7f4c0d010b2002280218200020056a200820056b200228021c28020c110500450d01410121040c060b20032003410c6a3602182003200341086a36021420032003360210200341106a10c404000b0340200a210c4101210441dc0021054101210a024002400240024002400240200c0e0402010500020b02400240024002402010422088a741ff01710e06050302010006050b201042ffffffff8f60834280808080308421104103210a41f50021050c070b201042ffffffff8f60834280808080208421104103210a41fb0021050c060b200e2010a7220c410274411c7176410f71220a413072200a41d7006a200a410a491b21050240200c450d002010427f7c42ffffffff0f832010428080808070838421100c050b201042ffffffff8f60834280808080108421100c040b201042ffffffff8f608321104103210a41fd0021050c040b4100210a200e21050c030b4101210a0240200b418001490d004102210a200b418010490d0041034104200b41808004491b210a0b200a20086a21050c040b201042ffffffff8f60834280808080c0008421100b4103210a0b20022802182005200228021c2802101104000d050c000b0b200820096b20076a210820062007470d000b0b2005450d0020052001460d00200520014f0d02200020056a2c000041bf7f4c0d020b410121042002280218200020056a200120056b200228021c28020c1105000d0020022802184122200228021c28021011040021040b200341206a240020040f0b200020012005200110ba04000bfb0304027f027e017f017e230041e0006b22042400024002400240411410272205450d00200541106a41002800bb8c40360000200541086a41002900b38c40370000200541002900ab8c4037000020054114413410282205450d01200520012900003700142005412c6a200141186a290000370000200541246a200141106a2900003700002005411c6a200141086a290000370000200441186a20054134108401200441186a41106a290300210620042903202107200428021821082005102942002109200441306a20012007420020081b220720027c22022006420020081b20037c2002200754ad7c108501200441306a41106a290300210220042903382103024020042903304200520d00200321090c030b200441b18ac0004116108601200441106a29030021062004290308210720042802002105200441306a41086a220142003703002004420037033041b18ac0004116200441306a1004200441d0006a41086a200129030037030020042004290330370350200442002006420020051b220620027d2007420020051b2202200354ad7d2207200220037d2203200256200720065620072006511b22051b37033820044200200320051b370330200441d0006a4110200441306a41101003420021020c020b41144101102a000b41344101102a000b2000200937030020002002370308200441e0006a24000ba10204017f017e037f027e230041c0006b2203240042002104200341206a41186a22054200370300200341206a41106a22064200370300200341206a41086a220742003703002003420037032020012002200341206a1000200341186a2005290300370300200341106a2006290300370300200341086a2007290300370300200320032903203703002003410036022020034120200341206a1005210202400240024020032802202201417f470d000c010b2003420037032820034200370320200341206a20022001411020014110491b10ce041a2001410f4d0d01200341286a29030021082003290320210920021029420121040b2000200937030820002004370300200041106a2008370300200341c0006a24000f0b418f89c3004133104e000bdb0605027f027e017f017e047f230041b0016b220424000240024002400240411410272205450d00200541106a41002800bb8c40360000200541086a41002900b38c40370000200541002900ab8c4037000020054114413410282205450d01200520012900003700142005412c6a200141186a290000370000200541246a200141106a2900003700002005411c6a200141086a290000370000200441086a20054134108401200441086a41106a29030021062004290310210720042802082108200510292006420020081b21092007420020081b2106024002400240200242ffffe883b1de1656200342005220035022051b0d002006200984500d010b4101210802402002428080e983b1de1654410020051b0d00411410272205450d0541002108200541106a41002800bb8c40360000200541086a41002900b38c40370000200541002900ab8c4037000020054114413410282205450d06200520012900003700142005412c6a200141186a220a290000370000200541246a200141106a2900003700002005411c6a200141086a290000370000200441206a41186a220b4200370300200441206a41106a220c4200370300200441206a41086a220d42003703002004420037032020054134200441206a100020044190016a41186a200b29030037030020044190016a41106a200c29030037030020044190016a41086a200d290300370300200420042903203703900120044190016a412041b8d6c50041004100100b210b20051029200b417f470d002001108701200441d8006a2003370300200441d0006a200237030041002108200441206a41086a41003a0000200441296a2001290000370000200441316a200141086a290000370000200441396a200141106a290000370000200441c1006a200a290000370000200441023a002041b8d6c5004100200441206a1088010b200120022003108901200041106a200920037d2006200254ad7d200320097d2002200654ad7d2006200256200920035620092003511b22051b3703002000200620027d200220067d20051b370308200020083a001820002005ad3703000c010b20004200370300200041013a0018200041106a4200370300200041086a42003703000b200441b0016a24000f0b41144101102a000b41344101102a000b41144101102a000b41344101102a000be70104017f017e017f027e230041206b2203240042002104200341106a41086a220542003703002003420037031020012002200341106a1004200341086a2005290300370300200320032903103703002003410036021020034110200341106a1005210202400240024020032802102201417f470d000c010b2003420037031820034200370310200341106a20022001411020014110491b10ce041a2001410f4d0d01200341186a29030021062003290310210720021029420121040b2000200737030820002004370300200041106a2006370300200341206a24000f0b418f89c3004133104e000ba10703047f017e067f230041a0016b22012400200141186a41f8f3c200411310b50120012802182102200128021c210302400240412010272204450d00200420002900002205370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a29000037000020042d000121062004102920014190016a20064108742005a7220441c0017172410676220610cc0102402004413f7122042001280298014f0d00200141086a20012802900120044105746a22041095012001290308200141086a41086a290300844200520d0020042000290000370000200441186a200041186a290000370000200441106a200041106a290000370000200441086a200041086a290000370000200141206a41086a20014190016a41086a28020036020020012001290390013703202006200141206a10fe020c020b2003410020021b21040240200128029401450d0020012802900110290b200141206a200410cc01024020012802282206413f4d0d000340200441016a210402402001280224450d00200128022010290b200141206a200410cc0120012802282206413f4b0d000b0b2001280220210220012802242107200141206a41186a2208200041186a290000370300200141206a41106a2209200041106a290000370300200141206a41086a220a200041086a29000037030020012000290000370320200641016a2103024020072006470d00024020064101742207200320032007491b2207410574220b4100480d000240024020060d00200b102721020c010b20022006410574200b102821020b20020d01200b4101102a000b102b000b200620044106746a210b200220064105746a22062001290320370000200641186a2008290300370000200641106a2009290300370000200641086a200a2903003700000240200341c000470d00200141206a41086a220642003703002001420037032041f8f3c2004113200141206a100420014190016a41086a200629030037030020012001290320370390012001200441016a36022020014190016a4110200141206a410410030b2001200336022820012007360224200120023602202004200141206a10fe02200141206a41086a2000290000370300200141206a41106a200041086a290000370300200141206a41186a200041106a290000370300200141c0006a200041186a2900003703002001200b360224200141013a002041b8d6c5004100200141206a1088010c010b41204101102a000b200141a0016a24000b942603087f047e037f230041c0036b22032400200341003602b80141ff88c3004110200341b8016a100521040240024020032802b8012205417f460d002004450d0041002106200341003602b801200341b8016a20042005410420054104491b10ce041a0240200541034d0d0020032802b8012107200410290c020b418f89c3004133104e000b410121060b4101210841002104410021050240024002400240024002400240024002400240024002400240024002402001450d00200141057422044100480d09200410272208450d012001410574220941606a410576210a410021040340200341b8016a41186a200020046a220541186a290000220b370300200341b8016a41106a200541106a290000220c370300200341b8016a41086a200541086a290000220d37030020032005290000220e3703b801200820046a220541186a200b370000200541106a200c370000200541086a200d3700002005200e3700002009200441206a2204470d000b200a41016a2105200121040b200341a4016a2007360200200320063602a001200341306a200241f00010ce041a200341b0016a2005360200200341ac016a2004360200200320083602a801200341286a4187cec500411110b501024002400240024002400240200328022c410020032802281b220f41016a2205200f490d00200341d0026a41086a22044200370300200342003703d0024187cec5004111200341d0026a100420034188036a41086a22082004290300370300200320032903d00237038803200320053602b80120034188036a4110200341b8016a41041003200341b8016a200341306a41880110ce041a20044200370300200342003703d002418890c300410d200341d0026a100420082004290300370300200320032903d00237038803200341003602d00220034188036a4110200341d0026a100521050240024020032802d0022204417f460d0020050d010b200341003602c802200342013703c0020c090b200320043602c802200320043602c402200320053602c0022004450d08200320043602d402200320053602d002200341206a200341d0026a102e2003280220450d07410121052003280224220841016a22092008490d070240200841c000490d0041022105200841808001490d00410441052008418080808004491b21050b410121080240200941c000490d0041022108200941808001490d00410441052009418080808004491b21080b024020082005460d002004200820056b6a2204417f4c0d100240024020040d00410121020c010b200410272202450d030b200320043602a803200320043602a403200320023602a0032003200341a0036a3602d0022009200341d0026a2008107e20042008490d0320032802a80322092004490d0420032802c80222092005490d0520032802a003210220032802c00221062003200420086b22043602b0032003200920056b22093602b40320042009470d06200220086a200620056a200410ce041a200341b8016a200341a0036a10980320032802a803210820032802a403210520032802a003210420032802c402450d0b20032802c00210290c0b0b2003200341c0026a3602d0022009200341d0026a2005107e200341b8016a200341c0026a10980320032802c802210820032802c402210520032802c00221040c0a0b200341306a1099030c0a0b20044101102a000b20082004103e000b20042009107f000b20052009103e000b20034188036a41146a410336020020034194036a411d360200200341f0026a41146a41033602002003200341b0036a3602b8032003200341b4036a3602bc03200341d0026a41146a4100360200200342033702f40220034190d1c5003602f0022003411d36028c03200341b8d6c5003602e002200342013702d402200341e4d1c5003602d002200320034188036a360280032003200341d0026a360298032003200341bc036a360290032003200341b8036a36028803200341f0026a41a0d2c5001057000b20044101102a000b410021040c010b200341003602d802200342013703d002200341013602880320034188036a200341d0026a10300240024020032802a8024101460d000240024020032802d40220032802d8022204460d0020032802d00221050c010b200441016a22052004490d0820044101742208200520052008491b22084100480d080240024020040d002008102721050c010b20032802d00220042008102821050b2005450d0d200320083602d402200320053602d00220032802d80221040b2003200441016a3602d802200520046a41003a000020032802ac0221080240024020032802d402220520032802d80222046b4104490d0020032802d00221050c010b200441046a22092004490d0820054101742204200920092004491b22044100480d080240024020050d002004102721050c010b20032802d00220052004102821050b2005450d0c200320043602d402200320053602d00220032802d80221040b2003200441046a3602d802200520046a20083600000c010b0240024020032802d40220032802d8022204460d0020032802d00221050c010b200441016a22052004490d0720044101742208200520052008491b22084100480d070240024020040d002008102721050c010b20032802d00220042008102821050b2005450d0a200320083602d402200320053602d00220032802d80221040b2003200441016a3602d802200520046a41013a00000b200341b8016a200341d0026a109d0220032802b0022104200320032802b80222053602880320034188036a200341d0026a103002402005450d002005410574210220032802d402210920032802d8022105034002400240200920056b4120490d0020032802d00221080c010b200541206a22082005490d0820094101742205200820082005491b22064100480d080240024020090d002006102721080c010b20032802d00220092006102821080b2008450d0a200320063602d402200320083602d00220032802d8022105200621090b200820056a220841086a200441086a290000370000200841106a200441106a290000370000200841186a200441186a2900003700002003200541206a22053602d80220082004290000370000200441206a2104200241606a22020d000b0b20032802d802210820032802d402210520032802d002210420032802c402450d010b20032802c00210290b024020040d00200341b8016a1099030c010b200341d0026a41086a22094200370300200342003703d002418890c300410d200341d0026a100420034188036a41086a2009290300370300200320032903d0023703880320034188036a411020042008100302402005450d00200410290b200341b8016a109903200341106a41888dc300410d1094012001450d002003290318420020032802101b210c2001410574211003402003200f3602f8022003200c3703f002024002400240024002400240024002400240024002400240024002400240411210272204450d00200441106a41002f00a590433b0000200441086a410029009d9043370000200441002900959043370000200341b8016a41186a22084200370300200341b8016a41106a22094200370300200341b8016a41086a22024200370300200342003703b80120044112200341b8016a1000200341d0026a41186a22062008290300370300200341d0026a41106a22012009290300370300200341d0026a41086a22072002290300370300200320032903b8013703d002412010272205450d01200520032903d002370000200541186a2006290300370000200541106a2001290300370000200541086a200729030037000020041029200842003703002009420037030020024200370300200342003703b80120004120200341b8016a1000200620082903003703002001200929030037030020072002290300370300200320032903b8013703d0022005412041c00010282204450d02200420032903d002370020200441386a2006290300370000200441306a2001290300370000200441286a2007290300370000200341003602b801200441c000200341b8016a10052105024020032802b8012208417f470d00200341003602c802200342013703c0020c0d0b200320083602c802200320083602c402200320053602c0022008450d0c200320083602bc01200320053602b801200341086a200341b8016a102e024020032802080d00410021050c0e0b41002105200328020c220941016a22062009490d0d41012105410121020240200941c000490d0041022102200941808001490d00410441052009418080808004491b21020b0240200641c000490d0041022105200641808001490d00410441052006418080808004491b21050b024020052002460d002008200520026b6a2208417f4c0d150240024020080d00410121090c010b200810272209450d050b200320083602a803200320083602a403200320093602a0032003200341a0036a3602b8012006200341b8016a2005107e20082005490d0520032802a80322092008490d0620032802c80222092002490d0720032802a003210620032802c00221012003200820056b22083602b0032003200920026b22093602b40320082009470d08200620056a200120026a200810ce041a20032903f002210b0240024020032802a403220820032802a80322056b4108490d0020032802a00321080c010b200541086a22092005490d1520084101742205200920092005491b22054100480d150240024020080d002005102721080c010b20032802a00320082005102821080b2008450d0a200320053602a403200320083602a00320032802a80321050b2003200541086a3602a803200820056a200b37000020032802f80221090240024020032802a403220820032802a80322056b4104490d0020032802a00321080c010b200541046a22022005490d1520084101742205200220022005491b22054100480d150240024020080d002005102721080c010b20032802a00320082005102821080b2008450d0b200320053602a403200320083602a00320032802a80321050b2003200541046a3602a803200820056a200936000020032802a803211120032802a403210a20032802a003210520032802c402450d0f20032802c00210290c0f0b2003200341c0026a3602b8012006200341b8016a2002107e20032903f002210b0240024020032802c402220820032802c80222056b4108490d0020032802c00221080c010b200541086a22092005490d1420084101742205200920092005491b22054100480d140240024020080d002005102721080c010b20032802c00220082005102821080b2008450d0b200320053602c402200320083602c00220032802c80221050b2003200541086a3602c802200820056a200b37000020032802f80221090240024020032802c402220820032802c80222056b4104490d0020032802c00221080c010b200541046a22022005490d1420084101742205200220022005491b22054100480d140240024020080d002005102721080c010b20032802c00220082005102821080b2008450d0c200320053602c402200320083602c00220032802c80221050b2003200541046a3602c802200820056a200936000020032802c802211120032802c402210a20032802c00221050c0e0b41124101102a000b41204101102a000b41c0004101102a000b20084101102a000b20052008103e000b20082009107f000b20022009103e000b20034188036a41146a410336020020034194036a411d360200200341d0026a41146a41033602002003200341b0036a3602b8032003200341b4036a3602bc03200341b8016a41146a4100360200200342033702d40220034190d1c5003602d0022003411d36028c03200341b8d6c5003602c801200342013702bc01200341e4d1c5003602b801200320034188036a3602e0022003200341b8016a360298032003200341bc036a360290032003200341b8036a36028803200341d0026a41a0d2c5001057000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b200341003602c001200342013703b801200341013602d002200341d0026a200341b8016a103020032903f002210b0240024020032802bc01220820032802c00122096b4108490d0020032802b80121050c010b200941086a22052009490d0720084101742202200520052002491b22024100480d070240024020080d002002102721050c010b20032802b80120082002102821050b2005450d05200320023602bc01200320053602b801200221080b2003200941086a22023602c001200520096a200b37000020032802f802210602400240200820026b41034d0d002008210a0c010b200241046a22012002490d0720084101742207200120012007491b220a4100480d070240024020080d00200a102721050c010b20052008200a102821050b2005450d062003200a3602bc01200320053602b8010b20032009410c6a22113602c001200520026a20063600000b20032802c402450d0020032802c00210290b024020050d00200410290c020b200441c0002005201110030240200a450d00200510290b200041206a210020041029201041606a22100d000b0b200341c0036a24000f0b20024101102a000b200a4101102a000b102b000b1039000b20064101102a000b20084101102a000b20044101102a000b20084101102a000bfb1603067f027e037f230041a0026b22032400024002400240024002400240024002400240024002400240411410272204450d00200441106a41002800bb8c40360000200441086a41002900b38c40370000200441002900ab8c4037000020044114413410282204450d01200420002900003700142004412c6a200041186a290000370000200441246a200041106a2900003700002004411c6a200041086a290000370000200341c8016a41186a22054200370300200341c8016a41106a22064200370300200341c8016a41086a22074200370300200342003703c80120044134200341c8016a1000200341c8006a41186a2005290300370300200341c8006a41106a2006290300370300200341c8006a41086a2007290300370300200320032903c801370348200320013703c801200320023703d001200341c8006a4120200341c8016a4110100320041029200142ffffe883b1de165620024200522002501b0d07411410272204450d02200441106a41002800bb8c40360000200441086a41002900b38c40370000200441002900ab8c4037000020044114413410282204450d03200420002900003700142004412c6a200041186a290000370000200441246a200041106a2900003700002004411c6a200041086a290000370000200341c8016a41186a22054200370300200341c8016a41106a22064200370300200341c8016a41086a22074200370300200342003703c80120044134200341c8016a1000200341c8006a41186a2005290300370300200341c8006a41106a2006290300370300200341c8006a41086a2007290300370300200320032903c801370348200341306a200341c8006a108a01200341306a41106a2903002101200329033821022003280230210820041029410e10272204450d04200441066a41002900dd8c40370000200441002900d78c403700002004410e412e10282204450d052004200029000037000e200441266a200041186a2900003700002004411e6a200041106a290000370000200441166a200041086a290000370000200341c8016a41186a22054200370300200341c8016a41106a22064200370300200341c8016a41086a22074200370300200342003703c8012004412e200341c8016a1000200341c8006a41186a2005290300370300200341c8006a41106a2006290300370300200341c8006a41086a2007290300370300200320032903c801370348200341c8006a4120100c2004102902402002200184500d002008450d00200341186a41b18ac0004116108601200341186a41106a29030021092003290320210a20032802182104200341b8016a41086a22054200370300200342003703b80141b18ac0004116200341b8016a1004200341c8016a41086a2005290300370300200320032903b8013703c801200342002009420020041b220920017d200a420020041b2201200254ad7d220a200120027d2202200156200a200956200a2009511b22041b37035020034200200220041b370348200341c8016a4110200341c8006a411010030b2000108b01200341c8006a2000108c0102400240024020032d004822044103714103460d0020040e03020001020b20040d08200341fc006a280200450d08200341f8006a28020010290c080b20040d07200341fc006a280200450d07200341f8006a28020010290c070b200341fc006a2802002104200341f8006a280200220520034180016a280200100d2004450d06200510290c060b41144101102a000b41344101102a000b41144101102a000b41344101102a000b410e4101102a000b412e4101102a000b02400240024002400240411710272204450d002004410f6a41002900af9342370000200441086a41002900a89342370000200441002900a0934237000020044117413710282204450d01200420002900003700172004412f6a200041186a290000370000200441276a200041106a2900003700002004411f6a200041086a290000370000200341c8016a41186a22054200370300200341c8016a41106a22064200370300200341c8016a41086a22074200370300200342003703c80120044137200341c8016a1000200341c8006a41186a2005290300370300200341c8006a41106a2006290300370300200341c8006a41086a2007290300370300200320032903c801370348200341c8006a4120100c2004102920034190026a2000108d01200341c8006a20032802900222042003280298022207108e0120032d00484101470d0320042007100c200341c8016a41386a220720034181016a290000370300200341c8016a41306a2208200341f9006a290000370300200341c8016a41286a220b200341f1006a290000370300200341c8016a41206a200341e9006a2900003703002005200341e1006a2900003703002006200341d9006a290000370300200341c8016a41086a2205200341d1006a290000370300200320032900493703c8010240200328029402450d00200410290b200341c8006a41386a2007290300370300200341c8006a41306a2008290300370300200341c8006a41286a200b290300370300200341c8006a41206a220c200341c8016a41206a290300370300200341c8006a41186a200341c8016a41186a290300370300200341c8006a41106a200341c8016a41106a290300370300200341c8006a41086a2005290300370300200320032903c801370348200341c8006a210b4120417f4a210d41042105410a2106034002400240200641766a2204410a4b0d00200b21070240024020040e0b0102020202020202020200010b200c21070b200d450d05024041200d0041012108410021040c020b0240412010272208450d00412021040c020b41204101102a000b410121084100210441b8d6c50021070b20082007200410ce0421072003200436029c02200320043602980220032007360294022003200636029002200341b8016a20034190026a108f0120032802b801220620032802c001100c024020032802bc01450d00200610290b02402004450d00200710290b024020054108460d00200541d0e3c1006a2802002106200541046a21050c010b0b200341013a008f02200341b8016a41086a22044200370300200342003703b80141a7c8c500410f200341b8016a100420034190026a41086a2004290300370300200320032903b8013703900220034190026a41102003418f026a410110030c040b41174101102a000b41374101102a000b1039000b200328029402450d00200410290b411810272204450d01200441106a41002900cf8c40370000200441086a41002900c78c40370000200441002900bf8c4037000020044118413810282204450d0220042000290000370018200441306a200041186a290000370000200441286a200041106a290000370000200441206a200041086a290000370000200320044138108401200341106a290300210220032802002105200329030821012004102902402001200284500d0020050d010b411310272204450d032004410f6a41002800d68d43360000200441086a41002900cf8d43370000200441002900c78d4337000020044113413310282204450d04200420002900003700132004412b6a200041186a2206290000370000200441236a200041106a22072900003700002004411b6a200041086a2208290000370000200341c8006a41186a220b4200370300200341c8006a41106a220d4200370300200341c8006a41086a220542003703002003420037034820044133200341c8006a1000200341c8016a41186a200b290300370300200341c8016a41106a200d290300370300200341c8016a41086a2005290300370300200320032903483703c801200341c8016a4120100c20041029200541013a0000200341d1006a2000290000370000200341d9006a2008290000370000200341e1006a2007290000370000200341e9006a2006290000370000200341023a004841b8d6c5004100200341c8006a1088010b200341a0026a24000f0b41184101102a000b41384101102a000b41134101102a000b41334101102a000bb00104037f017e017f027e230041106b22022400200241003602002001412020021005210302400240024020022802002204417f470d00420021050c010b2002420037030820024200370300200220032004411020044110491b10ce0421062004410f4d0d01200641086a2903002107200629030021082003102920014120100c420121050b2000200537030020002008370308200041106a2007370300200241106a24000f0b418f89c3004133104e000b930b01087f23004180016b22012400024002400240024002400240024002400240410e10272202450d00200241066a41002900c7a244370000200241002900c1a2443700002002410e412e10282202450d012002200029000037000e200241266a200041186a2900003700002002411e6a200041106a290000370000200241166a200041086a290000370000200141c0006a41186a22034200370300200141c0006a41106a22044200370300200141c0006a41086a22054200370300200142003703402002412e200141c0006a1000200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a20052903003703002001200129034037032020014100360260200141206a4120200141e0006a100521050240024020012802602203417f460d00200141c0006a2003412020034120491b22046a41004100412020046b2004411f4b1b10cd041a200141c0006a2005200410ce041a2003411f4d0d04200141e0006a41186a2203200141c0006a41186a290300370300200141e0006a41106a2204200141c0006a41106a290300370300200141e0006a41086a2206200141c0006a41086a2903003703002001200129034037036020051029200141186a22052003290300370300200141106a22072004290300370300200141086a2208200629030037030020012001290360370300200141206a4120100c2002102920032005290300370300200420072903003703002006200829030037030020012001290300370360410e10272202450d05200241066a410029009fa34437000020024100290099a3443700002002410e412e10282202450d062002200129036037000e200241266a200141e0006a41186a2903003700002002411e6a200141e0006a41106a290300370000200241166a200141e0006a41086a290300370000200141c0006a41186a22034200370300200141c0006a41106a22044200370300200141c0006a41086a22054200370300200142003703402002412e200141c0006a1000200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a200529030037030020012001290340370320200141206a4120100c200210290c010b200210290b410d10272202450d05200241056a41002900aca344370000200241002900a7a3443700002002410d412d10282202450d062002200029000037000d200241256a200041186a2900003700002002411d6a200041106a290000370000200241156a200041086a290000370000200141c0006a41186a22034200370300200141c0006a41106a22044200370300200141c0006a41086a22054200370300200142003703402002412d200141c0006a1000200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a200529030037030020012001290340370320200141206a4120100c20021029411210272202450d07200241106a41002f00c4a3443b0000200241086a41002900bca344370000200241002900b4a34437000020024112413210282202450d08200220002900003700122002412a6a200041186a290000370000200241226a200041106a2900003700002002411a6a200041086a290000370000200141c0006a41186a22034200370300200141c0006a41106a22044200370300200141c0006a41086a220542003703002001420037034020024132200141c0006a1000200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a200529030037030020012001290340370320200141206a4120100c20021029200010c903200010ca0320014180016a24000f0b410e4101102a000b412e4101102a000b418f89c3004133104e000b410e4101102a000b412e4101102a000b410d4101102a000b412d4101102a000b41124101102a000b41324101102a000bce0d04067f017e037f087e230041f0006b22022400024002400240024002400240411710272203450d002003410f6a41002900af9342370000200341086a41002900a89342370000200341002900a0934237000020034117413710282203450d01200320012900003700172003412f6a200141186a290000370000200341276a200141106a2900003700002003411f6a200141086a290000370000200241286a41186a22014200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820034137200241286a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903283703002002410036022820024120200241286a100521010240024020022802282204417f460d002001450d002002200136022020022004360224200241003a0028200241286a20012004410047220510ce041a20042005490d042002200420056b22063602242002200120056a22053602202004450d0720022d0028220441014b0d0702400240024020040e020001000b200241286a200241206a104420022802282207450d09200229022c210820024100360228200241286a2002280220220920022802242204410420044104491b220610ce041a2002200420066b22053602242002200920066a220a3602200240200441034b0d002008a7450d0a0c090b20022802282109200241286a2005412020054120491b22046a41004100412020046b2004411f4b1b10cd041a200241286a200a200410ce041a2002200520046b22063602242002200a20046a220b360220024002402005411f4b0d00410021040c010b2002200228002b36006b20022002280228360268200220022802683602602002200228006b360063200241376a290000210c200229002f210d200229003f210e20022d0047210a410121040b2002200228006336002b20022002280260360228024020040d002008a70d090c0a0b2002200228002b36005b200220022802283602582002420037033020024200370328200241286a200b2006411020064110491b220510ce041a2002200620056b22043602242002200b20056a220b36022002402006410f4b0d002008a70d090c0a0b200241286a41086a290300210f2002290328211020024200370328200241286a200b2004410820044108491b220610ce041a2002200420066b22053602242002200b20066a22063602200240200441074d0d0020022903282111200241003a0028200241286a20062005410047220410ce041a20052004490d082002200520046b220b3602242002200620046a220436022002402005450d0020022d0028220541014b0d00420021120240024020050e020100010b20024200370328200241286a2004200b4108200b41084922061b220510ce041a2002200b20056b3602242002200420056a36022020060d0120022903282113420121120b2002200228005b36005320022002280258360250200220022802503602282002200228005336002b200220022800493602682002200241cc006a28000036006b410021040c030b2008a70d090c0a0b2008a70d080c090b41002107200241286a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241286a2005200410ce041a2002200620046b3602242002200520046a360220024002402006411f4b0d00420021120c010b2002200228002b36006b20022002280228360268200220022802683602602002200228006b360063200241376a290000210f200229002f2110200229003f211120023100472112410121070b2002200228006336002b200220022802603602282007450d082002200228002b36005b200220022802283602582002200228005b36005320022002280258360250200220022802503602682002200228005336006b2002200241cc006a28000036002b20022002280049360228410121040b2002200228006b36006320022002280268360260200220022802283602582002200228002b36005b20011029200041106a200f370000200041086a2010370000200041cf006a200c370000200041c7006a200d370000200020043a000020002002280260360001200041046a20022800633600002000413c6a2009360000200041346a2008370000200041306a2007360000200041286a2013370000200041206a2012370000200041186a2011370000200041c0006a2002280258360000200041c3006a200228005b360000200041df006a200a3a0000200041d7006a200e3700000c010b200041023a00000b20031029200241f0006a24000f0b41174101102a000b41374101102a000b20052004103e000b20042005103e000b200710290b418f89c3004133104e000be80501067f230041c0006b2202240002400240024002400240411010272203450d00200341086a41002900c5cc41370000200341002900bdcc41370000200242908080808002370204200220033602002002410d360220200241206a20021030024002400240024020022802042204200228020822056b410d490d002005410d6a2103200228020021060c010b2005410d6a22032005490d0120044101742206200320032006491b22074100480d010240024020040d002007102721060c010b200228020020042007102821060b2006450d042002200736020420022006360200200721040b20022003360208200620056a2205410029009ecc41370000200541056a41002900a3cc41370000200241206a2006200310830220022802282203417f4c0d04200228022021050240024020030d00410121070c010b200310272207450d0620072005200310ce041a0b02402004450d00200610290b02402002280224450d00200510290b412010272206450d0620062001290000370000200641186a200141186a290000370000200641106a200141106a290000370000200641086a200141086a290000370000200241206a41186a22014200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020064120200241206a1000200241186a2001290300370300200241106a2004290300370300200241086a20052903003703002002200229032037030020034101742201200341206a220420042001491b22054100480d000240024020030d002005102721010c010b200720032005102821010b20010d0120054101102a000b102b000b200120036a22032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a29030037000020061029200020043602082000200536020420002001360200200241c0006a24000f0b41104101102a000b20074101102a000b1039000b20034101102a000b41204101102a000bd60503097f017e027f23004180026b220324002003410036024020012002200341c0006a10052102024002400240024020032802402204417f460d0020020d010b200041003a00000c010b20032004412020044120491b22056a41004100412020056b2005411f4b1b10cd041a20032002200510ce0421012004411f4d0d0120014180016a41086a2206200141086a220729000037030020014180016a41106a2208200141106a220929000037030020014180016a41186a220a200141186a220b29000037030020012001290000220c3703c0012001200c370380012001200420056b220d4120200d4120491b22046a41004100412020046b2004411f4b1b10cd041a2001200220056a200410ce042101200d411f4d0d01200141a0016a41086a22042007290000370300200141a0016a41106a22052009290000370300200141a0016a41186a220d200b290000370300200141c0006a41186a220e200a290300370300200141c0006a41106a220a2008290300370300200141c0006a41086a2208200629030037030020012001290000220c3703c0012001200c3703a0012001200129038001370340200141c0006a41386a2206200d290300370300200141c0006a41306a220d2005290300370300200141c0006a41286a22052004290300370300200120012903a001370360200141386a22042006290300370300200141306a2206200d290300370300200141286a220d2005290300370300200141206a22052001290360370300200b200e2903003703002009200a290300370300200720082903003703002001200129034037030020021029200041013a0000200041396a2004290300370000200041316a2006290300370000200041296a200d290300370000200041216a2005290300370000200041196a200b290300370000200041116a2009290300370000200041096a2007290300370000200020012903003700010b20034180026a24000f0b418f89c3004133104e000ba00701097f230041c0006b22022400024002400240024002400240411010272203450d00200341086a4100290081e241370000200341002900f9e141370000200242908080808002370204200220033602002002410d360220200241206a20021030024002400240024020022802042204200228020822056b410d490d002005410d6a2103200228020021060c010b2005410d6a22032005490d0120044101742206200320032006491b22074100480d010240024020040d002007102721060c010b200228020020042007102821060b2006450d042002200736020420022006360200200721040b20022003360208200620056a2205410029009ecc41370000200541056a41002900a3cc41370000200241206a2006200310830220022802282203417f4c0d04200228022021050240024020030d00410121080c010b200310272208450d0620082005200310ce041a0b02402004450d00200610290b02402002280224450d00200510290b200241003602282002420137032020012802002104410410272206450d062006200436000020024284808080c000370224200220063602202001280204210720022001410c6a28020022013602002002200241206a10300240024020022802242205200228022822046b2001490d00200228022021060c010b200420016a22062004490d0120054101742209200620062009491b22094100480d010240024020050d002009102721060c010b200228022020052009102821060b2006450d082002200936022420022006360220200921050b200620046a2007200110ce041a200241206a41186a22074200370300200241206a41106a22094200370300200241206a41086a220a4200370300200242003703202006200420016a200241206a1000200241186a2007290300370300200241106a2009290300370300200241086a200a29030037030020022002290320370300200341206a22012003490d0020034101742204200120012004491b22074100480d000240024020030d002007102721040c010b200820032007102821040b20040d0120074101102a000b102b000b200420036a22032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a29030037000002402005450d00200610290b200020013602082000200736020420002004360200200241c0006a24000f0b41104101102a000b20074101102a000b1039000b20034101102a000b41044101102a000b20094101102a000bb80304027f027e017f017e230041206b22052400024002400240411410272206450d00200641106a41002800bb8c40360000200641086a41002900b38c40370000200641002900ab8c4037000020064114413410282206450d01200620012900003700142006412c6a200141186a290000370000200641246a200141106a2900003700002006411c6a200141086a290000370000200541086a20064134108401200541086a41106a29030021072005290310210820052802082109200610294101210602402008420020091b220820027d220a2008562007420020091b220720037d2008200254ad7d220820075620082007511b4101470d00200041bf88c000360204200041086a411d3602000c030b024002400240200a428080e983b1de165441002008501b0d00200520012004200a200810910120052802002206450d022005280204210120002006360204200041086a20013602000c010b200041dc88c000360204200041086a411a3602000b410121060c030b2001200a2008108901200041106a2003370300200041086a2002370300410021060c020b41144101102a000b41344101102a000b20002006360200200541206a24000b8d0304027f017e027f017e230041c0006b22052400024002400240200241ff0171417e6a220641024b0d000240024020060e03000201000b200541106a20011092012005290310200358200541186a290300220720045820072004511b0d010c020b200541206a20011092012005290320200356200541286a290300220720045620072004511b0d010b200541306a20011093010240200528023822010d0002402005280234450d00200528023010290b410021010c020b200541888dc300410d1094012005290308420020052802001b2107200141286c210620052802342108200528023022092101024002400240034002402007200141106a2903005a0d002001290300200358200141086a290300220a200458200a2004511b0d00200141206a2d000020027141ff0171200241ff0171460d020b200141286a2101200641586a22060d000b4100210120080d010c020b41ec87c00021012008450d010b200910290b413121060c010b41c687c0002101412621060b2000200636020420002001360200200541c0006a24000b820804067f027e017f077e230041a0016b220224000240024002400240411010272203450d00200341086a41002900ab8d40370000200341002900a38d4037000020034110413010282203450d0120032001290000370010200341286a200141186a290000370000200341206a200141106a290000370000200341186a200141086a29000037000020024180016a41186a2204420037030020024180016a41106a2205420037030020024180016a41086a2206420037030020024200370380012003413020024180016a1000200241e0006a41186a2004290300370300200241e0006a41106a2005290300370300200241e0006a41086a200629030037030020022002290380013703602002410036028001200241e0006a412020024180016a100521040240024002402002280280012205417f460d002004450d002002420037038801200242003703800120024180016a20042005411020054110491b220610ce041a02402005410f4d0d0020024180016a41086a2207290300210820022903800121092002420037038801200242003703800120024180016a200420066a220a200520066b2205411020054110491b220610ce041a2005410f4d0d002007290300210b200229038001210c200242003703800120024180016a200a20066a200520066b2205410820054108491b10ce041a200541074b0d020b418f89c3004133104e000b200310294200210c4200210b0c010b200229038001210d2004102920031029411410272203450d03200341106a41002800bb8c40360000200341086a41002900b38c40370000200341002900ab8c4037000020034114413410282203450d04200320012900003700142003412c6a200141186a290000370000200341246a200141106a2900003700002003411c6a200141086a290000370000200241c8006a20034134108401200241c8006a41106a290300210e2002290350210f2002280248210120031029200241386a41888dc300410d10940142002110200241186a200b420042002002290340420020022802381b2211200d7d220d200d2011561b220d420010d304200241286a200d4200200c420010d304200241086a42004200200c420010d304200e420020011b210b200f420020011b210d4200210c02402002290310200229032084420052200241286a41086a290300220f200229030820022903187c7c220e200f54720d002008200e20022903282210200954200e200854200e2008511b22031b200e7d2009201020031b220e201054ad7d210c200e20107d21100b200c200b200d201056200b200c56200b200c511b22031b210b2010200d20031b210c0b2000200c3703002000200b370308200241a0016a24000f0b41104101102a000b41304101102a000b41144101102a000b41344101102a000bd408040e7f047e017f017e230041f0006b220224000240024002400240024002400240410e10272203450d00200341066a41002900dd8c40370000200341002900d78c403700002003410e412e10282204450d012004200129000037000e200441266a200141186a2900003700002004411e6a200141106a290000370000200441166a200141086a290000370000200241386a41186a22014200370300200241386a41106a22034200370300200241386a41086a22054200370300200242003703382004412e200241386a1000200241106a41186a2001290300370300200241106a41106a2003290300370300200241106a41086a20052903003703002002200229033837031020024100360238200241106a4120200241386a100521060240024020022802382207417f460d002002200736023420022006360230200241086a200241306a102e2002280208450d0802400240200228020c220841e600200841e600491b22090d004108210a0c010b200941286c22011027220a450d050b02402008450d002002280230210b20022802342103200241ec006a210c4100210d4100210e4100210f034020024200370338200241386a200b2003410820034108491b220510ce041a2002200320056b22013602342002200b20056a220536023002400240200341074d0d00200229033821102002420037034020024200370338200241386a20052001411020014110491b220b10ce041a20022001200b6b220336023420022005200b6a22053602302001410f4d0d00200241386a41086a29030021112002290338211220024200370338200241386a20052003410820034108491b220b10ce041a20022003200b6b220136023420022005200b6a220b360230200341074d0d0020022903382113200241003a0038200241386a200b2001410047220510ce041a20012005490d092002200120056b22033602342002200b20056a220b36023020010d010b2009450d0b200a10290c0b0b200f41016a2105200220022800693602602002200c28000036006320022d003821142002200228006336003b20022002280260360238200220022802383602582002200228003b36005b0240200f2009470d00200d20052005200d491b2209ad42287e2215422088a70d0a2015a722014100480d0a02400240200f0d0020011027210a0c010b200a200e20011028210a0b200a450d090b200a200e6a220141206a20143a00002001201137030820012012370300200141186a2010370300200141106a2013370300200141216a2002280258360000200141246a200228005b360000200d41026a210d200e41286a210e2005210f20082005470d000b0b200a450d082008ad4220862009ad84211002402007450d00200610290b200020103702042000200a3602000c010b20004100360208200042083702000b20041029200241f0006a24000f0b410e4101102a000b412e4101102a000b20014108102a000b20052001103e000b20014108102a000b102b000b418f89c3004133104e000bcc0104017f017e017f017e230041206b2203240042002104200341106a41086a220542003703002003420037031020012002200341106a1004200341086a2005290300370300200320032903103703002003410036021020034110200341106a1005210202400240024020032802102201417f470d000c010b20034200370310200341106a20022001410820014108491b10ce041a200141074d0d012003290310210620021029420121040b2000200637030820002004370300200341206a24000f0b418f89c3004133104e000bba0304027f027e017f027e230041306b220224000240024002400240411410272203450d00200341106a41002800bb8c40360000200341086a41002900b38c40370000200341002900ab8c4037000020034114413410282203450d01200320012900003700142003412c6a200141186a290000370000200341246a200141106a2900003700002003411c6a200141086a290000370000200241186a20034134108401200241186a41106a2903002104200229032021052002280218210620031029411810272203450d02200341106a41002900cf8c40370000200341086a41002900c78c40370000200341002900bf8c4037000020034118413810282203450d0320032001290000370018200341306a200141186a290000370000200341286a200141106a290000370000200341206a200141086a290000370000200220034138108401200241106a290300210720022903082108200228020021012003102920002008420020011b22082005420020061b7c220537030020002007420020011b2004420020061b7c2005200854ad7c370308200241306a24000f0b41144101102a000b41344101102a000b41184101102a000b41384101102a000bef0e06017f037e017f017e017f067e230041e0016b220724004200210842002109024020050d0020074190016a2006ad42004280c8afa025420010d30420074198016a290300200729039001220a4280a094a58d1d7c2208200a54ad7c21090b200741c0016a41086a22054200370300200742003703c00141d8cdc500411b200741c0016a1004200741a0016a41086a2005290300370300200720072903c0013703a00141002106200741003602d001200741a0016a4110200741d0016a1005210b024002400240024020072802d0012205417f470d004200210a0c010b200742003703d001200741d0016a200b2005410820054108491b10ce041a200541074d0d0120072903d001210c200b1029200c200c423f87220a7c200a85210a200c42005521060b2007418094ebdc033602a4012007200a200a428094ebdc037f220c4280ec94a37c7e7ca722053602a00120074180016a417f2004418094ebdc032004418094ebdc03491b2204417f417f2004ad200ca7417f200c428080808010541bad7e220aa7200a422088a71b220b200741a0016a2005418094ebdc034b4102746a28020022052004418094ebdc036e220d6c2005ad2004200d4180ec94a37c6c6aad7e428094ebdc0380a76a6a22052005200b491b22056a220b200b2004491b4100200420056b2205200520044b1b20061bad420042e807420010d30441012104200741a0016a2003427f20082007290380017c220a20017c220c200c200a542205200920074180016a41086a2903007c200a200854ad7c220820027c2005ad7c220a200854200a2008511b22051b220e427f200a20051b220f4101109001024020072802a0014101470d00200041003a00010c020b200741a0016a41106a290300210a200741386a200741a0016a41086a290300220242004204420010d304200741286a420042002002420010d304200741c8006a2007290338200741386a41086a2903002208200a42028620072903287c7c220c4205420010d40420072903302109200741c8006a41086a290300210120072903482110200741a0016a109701200741f0006a200741a0016a42b3e6cc99b3e6cc99332010200a200a42ffffffffffffffff3f8352200942005272200c2008547222041b22082002200820025442b3e6cc99b3e6cc9933200120041b220c200a54200c200a511b22041b2208200c200a20041b220c108301200741f0006a41086a290300211020072903702109200741d8006a41b18ac0004116108601200820097d200920087d20092008582010200c582010200c5122041b22051b2111200c20107d2008200954ad7d2010200c7d2009200854ad7d20051b2112200a200c7d2002200854ad7d2101200220087d210a200741d8006a41106a2903004200200728025822051b21022007290360420020051b21130240024020092008562010200c5620041b0d00200741d0016a41086a22044200370300200742003703d00141b18ac0004116200741d0016a1004200741c0016a41086a2004290300370300200720072903d0013703c00120074200200220127d2013201154ad7d2208201320117d220c201356200820025620082002511b22041b3703d80120074200200c20041b3703d001200741d0016a21040c010b200741d0016a41086a22044200370300200742003703d00141b18ac0004116200741d0016a1004200741c0016a41086a2004290300370300200720072903d0013703c0012007427f200220127c201320117c220c2013542204ad7c22082004200820025420082002511b22041b3703d8012007427f200c20041b3703d001200741d0016a21040b200741c0016a4110200441101003200741a0016a109801200741186a200741a0016a200a2001108301200741186a41086a290300210c20072903182108200741b18ac0004116108601200a20087d2008200a7d2008200a58200c200158200c20015122041b22051b21102001200c7d200a200854ad7d200c20017d2008200a54ad7d20051b2113200741106a2903004200200728020022051b21092007290308420020051b2102024002402008200a56200c20015620041b0d00200741d0016a41086a22044200370300200742003703d00141b18ac0004116200741d0016a1004200741c0016a41086a2004290300370300200720072903d0013703c00120074200200920137d2002201054ad7d2208200220107d220a200256200820095620082009511b22041b3703d80120074200200a20041b3703d001200741d0016a21040c010b200741d0016a41086a22044200370300200742003703d00141b18ac0004116200741d0016a1004200741c0016a41086a2004290300370300200720072903d0013703c0012007427f200920137c200220107c220a2002542204ad7c22082004200820095420082009511b22041b3703d8012007427f200a20041b3703d001200741d0016a21040b200741c0016a4110200441101003200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a200e427f200f501b370300410021040c010b418f89c3004133104e000b200020043a0000200741e0016a24000b840201067f230041c0006b2201240002400240410410272202450d00200241edde91e30636000020024104410c10282202450d01200242f0f2bda1a7ee9cb9f900370004200141346a42003702002001413c6a4100360200200141206a41086a2203200241086a2800003602002001420037022c200141106a2204200141206a41106a290300370300200141186a2205200141206a41186a290300370300200141086a220620032903003703002001200229000037030020021029200041186a2005290300370000200041106a2004290300370000200041086a200629030037000020002001290300370000200141c0006a24000f0b41044101102a000b410c4101102a000bc60502057f017e230041d0006b22012400200141306a41086a220242003703002001420037033041dbecc2004111200141306a1004200141086a22032002290300370300200120012903303703002001410036023020014110200141306a10052104024002400240024020012802302205417f460d00200141306a2005412020054120491b22026a41004100412020026b2002411f4b1b10cd041a200141306a2004200210ce041a2005411f4d0d01200141106a41186a2205200141306a41186a290000370300200141106a41106a2202200141306a41106a290000370300200141106a41086a2203200141306a41086a2900003703002001200129003037031020041029200041186a2005290300370000200041106a2002290300370000200041086a2003290300370000200020012903103700000c030b200242003703002001420037033041aa8dc300410d200141306a100420032002290300370300200120012903303703002001410036023020014110200141306a100521020240024020012802302205417f460d002001200536021420012002360210200141306a200141106a104320012802302204450d03200129023421062005450d01200210290c010b41042104420021060b20004200370000200041186a4200370000200041106a4200370000200041086a420037000002402006422088a72200450d00200041246c21052004210003400240024020002d0000220241034b0d0002400240024020020e0404000102040b2000410c6a280200450d03200041086a28020010290c030b2000410c6a280200450d02200041086a28020010290c020b2000410c6a280200450d01200041086a28020010290c010b200041086a280200450d00200041046a28020010290b200041246a21002005415c6a22050d000b0b2006a7450d02200410290c020b418f89c3004133104e000b418f89c3004133104e000b200141d0006a24000b130020004102360204200041b48dc0003602000b3400200041f8f3c10036020420004100360200200041146a4105360200200041106a41b49cc000360200200041086a42083702000b3701017f02404110102722020d0041104101102a000b2002420037000820024200370000200042908080808002370204200020023602000bbd0b03057f027e037f230041e0016b2203240002400240024002400240024002400240411810272204450d00200441106a41002900cf8c40370000200441086a41002900c78c40370000200441002900bf8c4037000020044118413810282204450d0120042000290000370018200441306a200041186a290000370000200441286a200041106a290000370000200441206a200041086a290000370000200341c0016a41186a22054200370300200341c0016a41106a22064200370300200341c0016a41086a22074200370300200342003703c00120044138200341c0016a1000200341d0006a41186a2005290300370300200341d0006a41106a2006290300370300200341d0006a41086a2007290300370300200320032903c001370350200320013703c001200320023703c801200341d0006a4120200341c0016a41101003200410290240200142ffffe883b1de165620024200522002501b0d00411810272204450d03200441106a41002900cf8c40370000200441086a41002900c78c40370000200441002900bf8c4037000020044118413810282204450d0420042000290000370018200441306a200041186a290000370000200441286a200041106a290000370000200441206a200041086a290000370000200341c0016a41186a22054200370300200341c0016a41106a22064200370300200341c0016a41086a22074200370300200342003703c00120044138200341c0016a1000200341d0006a41186a2005290300370300200341d0006a41106a2006290300370300200341d0006a41086a2007290300370300200320032903c001370350200341386a200341d0006a108a01200341386a41106a290300210120032802382105200329034021022004102902402002200184500d002005450d00200341206a41b18ac0004116108601200341206a41106a29030021082003290328210920032802202104200341d0006a41086a220542003703002003420037035041b18ac0004116200341d0006a1004200341c0016a41086a2005290300370300200320032903503703c001200342002008420020041b220820017d2009420020041b2201200254ad7d2209200120027d2202200156200920085620092008511b22041b37035820034200200220041b370350200341c0016a4110200341d0006a411010030b411410272204450d05200441106a41002800bb8c40360000200441086a41002900b38c40370000200441002900ab8c4037000020044114413410282204450d06200420002900003700142004412c6a200041186a290000370000200441246a200041106a2900003700002004411c6a200041086a290000370000200341086a20044134108401200341086a41106a290300210220032802082105200329031021012004102902402001200284500d0020050d010b411310272204450d072004410f6a41002800d68d43360000200441086a41002900cf8d43370000200441002900c78d4337000020044113413310282204450d08200420002900003700132004412b6a200041186a2206290000370000200441236a200041106a22072900003700002004411b6a200041086a220a290000370000200341d0006a41186a220b4200370300200341d0006a41106a220c4200370300200341d0006a41086a220542003703002003420037035020044133200341d0006a1000200341c0016a41186a200b290300370300200341c0016a41106a200c290300370300200341c0016a41086a2005290300370300200320032903503703c001200341c0016a4120100c20041029200541013a0000200341d9006a2000290000370000200341e1006a200a290000370000200341e9006a2007290000370000200341f1006a2006290000370000200341023a005041b8d6c5004100200341d0006a1088010b200341e0016a24000f0b41184101102a000b41384101102a000b41184101102a000b41384101102a000b41144101102a000b41344101102a000b41134101102a000b41334101102a000b130020004105360204200041c0adc0003602000bcb0201057f230041c0006b22012400024002400240411b10272202450d00200241176a4100280081b140360000200241106a41002900fab040370000200241086a41002900f2b040370000200241002900eab0403700002002411b413610282203450d012003200036001b200141206a41186a22024200370300200141206a41106a22004200370300200141206a41086a22044200370300200142003703202003411f200141206a1000200141186a22052002290300370300200141106a2000290300370300200141086a200429030037030020012001290320370300412010272202450d0220022001290300370000200241186a2005290300370000200241106a200141106a290300370000200241086a200141086a2903003700002003102920024120100e20021029200141c0006a24000f0b411b4101102a000b41364101102a000b41204101102a000bd50204037f027e017f017e230041306b22042400200441206a200110950102400240024002402004290320200441206a41086a29030084500d00411410272205450d0241002106200541106a41002800bb8c40360000200541086a41002900b38c40370000200541002900ab8c4037000020054114413410282205450d03200520012900003700142005412c6a200141186a290000370000200541246a200141106a2900003700002005411c6a200141086a290000370000200441086a20054134108401200441086a41106a290300210720042903102108200428020821092005102920012008420020091b220820027c220a2007420020091b20037c200a200854ad7c108901200041106a2003370300200041086a20023703000c010b2000419d88c000360204200041086a4122360200410121060b20002006360200200441306a24000f0b41144101102a000b41344101102a000be61805057f027e047f0a7e027f23004190036b22042400200441f0006a2001108c010240024020042d00702205417f6a41ff017141024f0d00200041003a0000200041086a200441f0006a41e00010ce041a0c010b200441d0016a41086a2206200441f0006a41c8006a290300370300200441d0016a41106a2207200441f0006a41d0006a290300370300200441d0016a41186a2208200441f0006a41d8006a2903003703002004200441f0006a41c0006a2903003703d001200441f0006a41106a2903002109200441f0006a41086a290300210a200441f0006a413c6a280200210b200441f0006a41386a280200210c200441a4016a280200210d200441f0006a41306a280200210e200441f0006a41286a290300210f200441f0006a41206a2903002110200441f0006a41186a2903002111200441e0006a41888dc300410d1094010240024002400240024002400240024002400240024002400240420042002004290368420020042802601b221220027d220220022012561b220220117d221320132002561b2214500d00411410272206450d02200641106a41002800bb8c40360000200641086a41002900b38c40370000200641002900ab8c4037000020064114413410282206450d03200620012900003700142006412c6a200141186a290000370000200641246a200141106a2900003700002006411c6a200141086a290000370000200441c8006a20064134108401200441386a20042903504200200428024822071b2202200441c8006a41106a290300420020071b221542e807420010d404200610294200200bad2213200429033822167d221720172013564200200441386a41086a2903002013201654ad7c7d22134200522013501b22061b22164200201320061b221384500d0402400240024002402002429080e983b1de165441002015501b0d00200441206a201642028620134202862016423e8884201442ffffffff0f8342ffffffff0f2014428080808010541b420010d304200441306a2001410842002002200242f0ff96fccea1697c2213200a200a201356200920152013200254ad7c427f7c22135620092013511b22061b22142004290320221620142016542013200920061b2214200441206a41086a29030022135420142013511b22061b22177d2218201820025620152014201320061b22147d2002201754ad7d220220155620022015511b22071b4200200220071b10910120042802300d010240024020060d002003450d010b20044190026a20012017201441081090012004280290024101460d0c20044190026a41106a290300211420044190026a41086a22072903002102200441086a41b18ac0004116108601200441086a41106a2903002115200429031021172004280208210820074200370300200442003703900241b18ac000411620044190026a1004200441f0026a41086a200729030037030020042004290390023703f002200442002015420020081b221520147d2017420020081b2214200254ad7d2217201420027d2202201456201720155620172015511b22071b3703980220044200200220071b37039002200441f0026a411020044190026a411010030b20060d0120030d03200041003a0008200041023a0000200041186a2009370000200041106a200a370000200041c4006a200b360000200041c0006a200c3600002000413c6a200d360000200041386a200e360000200041306a200f370000200041286a2010370000200041206a2011370000200041c8006a20042903d001370000200041d0006a200441d8016a290300370000200041d8006a200441d0016a41106a290300370000200041e0006a200441d0016a41186a290300370000200541037122004103460d0520000e03110505110b411710272206450d082006410f6a41002900af9342370000200641086a41002900a89342370000200641002900a0934237000020064117413710282206450d09200620012900003700172006412f6a200141186a290000370000200641276a200141106a2900003700002006411f6a200141086a29000037000020044190026a41186a2201420037030020044190026a41106a220b420037030020044190026a41086a2203420037030020044200370390022006413720044190026a1000200441f0026a41186a2001290300370300200441f0026a41106a200b290300370300200441f0026a41086a200329030037030020042004290390023703f002200441f0026a4120100c20061029200e200c100d200041023a0008200041013a00000c010b2004410036029002200e200c20044190026a100f2108200428029002220b417f460d0a200441f0026a41186a200441d0016a41186a290300370300200441f0026a41106a200441d0016a41106a290300370300200441f0026a41086a200441d0016a41086a290300370300200420042903d0013703f002200441003602980220044201370390022004200b3602f001200441f0016a20044190026a10300240024002400240200428029402220720042802980222066b200b490d0020042802900221030c010b2006200b6a22032006490d0120074101742219200320032019491b22194100480d010240024020070d002019102721030c010b20042802900220072019102821030b2003450d0e20042019360294022004200336029002201921070b200320066a2008200b10ce041a024002402006200b6a22060d00410121190c010b20064100480d01200610272219450d0f20192003200610ce041a0b02402007450d00200310290b20064101742203200641206a220720072003491b221a4100480d000240024020060d00201a102721030c010b20192006201a102821030b20030d01201a4101102a000b102b000b200320066a220620042903f002370000200641186a200441f0026a41186a290300370000200641106a200441f0026a41106a290300370000200641086a200441f0026a41086a29030037000020044190026a41186a2206420037030020044190026a41106a2219420037030020044190026a41086a221a420037030020044200370390022003200720044190026a1000200441f0016a41186a22072006290300370300200441f0016a41106a22062019290300370300200441f0016a41086a2219201a29030037030020042004290390023703f00120031029200441a9026a2007290300370000200441a1026a200629030037000020044199026a2019290300370000200420042903f00137009102200441013a009002200120044190026a10a101200e200c100d200041013a0000200041086a20044190026a41e00010ce041a200b450d00200810290b200d450d0c200e10290c0c0b200441cc026a200b360200200441c8026a200c360200200441c4026a200d360200200441c0026a200e360200200441b8026a200f370300200441b0026a201037030020044190026a41186a2012370300200441d0026a20042903d001370300200441d8026a200441d0016a41086a290300370300200441e0026a200441d0016a41106a290300370300200441e8026a200441d0016a41186a29030037030020044190026a41106a200920137d200a201654ad7d370300200441003a0090022004200a20167d37039802200120044190026a10a101200041023a0000200041086a20044190026a41e00010ce041a0c0b0b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041c4006a200b360000200041c0006a200c3600002000413c6a200d360000200041386a200e360000200041306a200f370000200041286a2010370000200041206a2011370000200041c8006a20042903d001370000200041d0006a2006290300370000200041d8006a2007290300370000200041e0006a20082903003700000c0a0b200d450d0b0c0a0b41144101102a000b41344101102a000b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041c4006a200b360000200041c0006a200c3600002000413c6a200d360000200041386a200e360000200041306a200f370000200041286a2010370000200041206a2011370000200041c8006a20042903d001370000200041d0006a200441d8016a290300370000200041d8006a200441d0016a41106a290300370000200041e0006a200441d0016a41186a2903003700000c060b41174101102a000b41374101102a000b20042004290294023703f00241a1b1c00041fe00200441f0026a41e88cc00010a201000b41b0cfc5004138104e000b20194101102a000b20064101102a000b0240200541037122004103460d0020000e03020000020b200d450d010b200e10290b20044190036a24000bb10201047f230041c0006b2202240002400240411710272203450d002003410f6a41002900af9342370000200341086a41002900a89342370000200341002900a0934237000020034117413710282203450d01200320002900003700172003412f6a200041186a290000370000200341276a200041106a2900003700002003411f6a200041086a290000370000200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034137200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a20052903003703002002200229032037030020024120360224200220023602202001200241206a10dc0220031029200241c0006a24000f0b41174101102a000b41374101102a000b810101017f230041c0006b220424002004200136020c2004200036020820042003360214200420023602102004412c6a41023602002004413c6a411e3602002004420237021c200441b481c600360218200441023602342004200441306a3602282004200441106a3602382004200441086a360230200441186a41c881c6001057000b130020004101360204200041a0b2c0003602000b3400200041d4f4c10036020420004100360200200041146a4103360200200041106a41bcb3c000360200200041086a42083702000b130020004101360204200041c0b6c0003602000bf51007017f017e047f017e037f067e057f23004190016b22032400200341086a41888dc300410d1094012003290310210420032802082105200341286a427f370300200341186a41286a41023a0000200341186a41186a2002370300200341386a20002900003703002003427f3703204201210220034201370318200341e8006a200110930120032802682106200328026c2107024002400240024002400240024020032802702208450d002004420020051b210902400240200341e8006a41186a220a2000460d0020034189016a210b200841286c210c42012102200621050340200541086a2903002104200541106a290300210d200541186a290300210e2005290300210f200341e8006a41206a200541206a290300370300200341e8006a41186a200e370300200341e8006a41106a200d370300200341e8006a41086a20043703002003200f37036802400240200a2900002000290000510d00200329037822042009580d012003200b2800003602602003200b41036a280000360063200541286a2105200341f0006a290300210d2003290368210e20032d008801210c0c060b20032903182104420021022003420037031820044201520d00200341186a41186a29030021102003290328211120032903202112200541286a21050c030b200541286a2105200c41586a220c0d000c030b0b200841286c210c200341186a41186a29030021102003290328211120032903202112200329031821022006210502400340200541086a2903002104200541106a290300210d200541186a290300210e2005290300210f200341e8006a41206a200541206a290300370300200341e8006a41186a200e370300200341e8006a41106a200d370300200341e8006a41086a2004370300200342003703182003200f37036820024201510d01200541286a210542002102200c41586a220c0d000c030b0b200541286a21050b200341f0006a2903002202201120122003290368220454201120025420112002511b220c1b210d20042012200c1b210e20032903782202201020102002541b210420032d008801410272210c420021020c010b41002108024020070d00410021134108210b410821050c020b200610294108210b41002113410821050c010b200329038001210f2003200328006336005b200320032802603602582003200328005b36005320032003280258360250200320032802503602482003200328005336004b41281027220b450d03200b200e370300200b200c3a0020200b200f370318200b2004370310200b2003280248360021200b200d370308200b41246a200328004b3600000240024020052006200841286c6a220a470d0041012108410121130c010b200341e8006a41186a210c20034189016a221441036a211541012108410121130340024002400240200c2000470d00200341186a41186a290300210d200329032821042003290320210e200329031821020340200341e8006a41206a200541206a290300370300200c200541186a290300370300200341e8006a41106a200541106a290300370300200341e8006a41086a200541086a290300370300200320052903003703682003420037031820024201510d0242002102200a200541286a2205470d000c050b0b02400340200341e8006a41206a200541206a290300370300200c200541186a290300370300200341e8006a41106a200541106a290300370300200341e8006a41086a2216200541086a2903003703002003200529030037036802400240200c2900002000290000510d00200329037822042009580d012003201428000036026020032015280000360063200541286a21052016290300210f2003290368210e20032d00880121170c050b20032903182104420021022003420037031820044201510d020b200a200541286a2205460d050c000b0b200341186a41186a290300210d200329032821042003290320210e0b200541286a2105200341e8006a41086a29030022022004200e2003290368221154200420025420042002511b22161b210f2011200e20161b210e20032903782202200d200d2002541b210420032d0088014102722117420021020b200329038001210d2003200328006336005b20032003280260360258200320032802583602502003200328005b3600532003200328005336006b20032003280250360268024020132008470d00200841016a22162008490d0720084101742213201620162013491b2213ad42287e2211422088a70d072011a722164100480d070240024020080d0020161027210b0c010b200b200841286c20161028210b0b200b450d040b200b200841286c6a221620173a00202016200f3703082016200e3703002016200d3703182016200437031020162003280268360021201641246a200328006b360000200841016a21082005200a470d000b0b02402007450d00200610290b200b21050b024020024201520d00200341e8006a41206a200341206a220041206a290300370300200341e8006a41186a200041186a290300370300200341e8006a41106a200041106a290300370300200341e8006a41086a200041086a29030037030020032000290300370368024020132008470d00200841016a22052008490d0520084101742200200520052000491b2213ad42287e2202422088a70d052002a722004100480d050240024020080d002000102721050c010b200b200841286c2000102821050b2005450d030b2005200841286c6a22002003290368370300200041206a200341e8006a41206a290300370300200041186a200341e8006a41186a290300370300200041106a200341e8006a41106a290300370300200041086a200341e8006a41086a290300370300200841016a21080b200320083602702003201336026c200320053602682001200341e8006a10a70120034190016a24000f0b20164108102a000b20004108102a000b41284108102a000b102b000b9c0802087f027e230041d0006b220224000240024002400240024002400240410e10272203450d00200341066a41002900dd8c40370000200341002900d78c403700002003410e412e10282204450d012004200029000037000e200441266a200041186a2900003700002004411e6a200041106a290000370000200441166a200041086a290000370000200241286a41186a22004200370300200241286a41106a22034200370300200241286a41086a22054200370300200242003703282004412e200241286a1000200241086a41186a2000290300370300200241086a41106a2003290300370300200241086a41086a20052903003703002002200229032837030820024100360230200242013703282001280200210520022001280208220036024c200241cc006a200241286a10300240024020000d0020022802302106200228022c2100200228022821070c010b200041286c2108200228022c210020022802302106034002400240200020066b4108490d00200641086a2107200228022821030c010b200641086a22072006490d0920004101742203200720072003491b22094100480d090240024020000d002009102721030c010b200228022820002009102821030b2003450d052002200936022c20022003360228200921000b20022007360230200320066a200541186a290000370000200541086a290300210a2005290300210b02400240200020076b4110490d00200741106a21060c010b200741106a22062007490d0920004101742209200620062009491b22094100480d090240024020000d002009102721030c010b200320002009102821030b2003450d062002200936022c20022003360228200921000b200320076a2207200a3700082007200b37000020022006360230200541106a290300210a0240200020066b41074b0d00200641086a22072006490d0920004101742209200720072009491b22074100480d090240024020000d002007102721030c010b200320002007102821030b2003450d072002200736022c200220033602280b2002200641086a360230200320066a200a37000002400240200228022c220020022802302203460d00200228022821070c010b200341016a22002003490d0920034101742206200020002006491b22004100480d090240024020030d002000102721070c010b200228022820032000102821070b2007450d082002200036022c200220073602280b2002200341016a2206360230200720036a200541206a2d00003a0000200541286a2105200841586a22080d000b0b200241086a412020072006100302402000450d00200710290b200410290240200141046a280200450d00200128020010290b200241d0006a24000f0b410e4101102a000b412e4101102a000b20094101102a000b20094101102a000b20074101102a000b20004101102a000b102b000bc10f07017f017e057f047e017f057e047f230041b0016b22062400200641086a41888dc300410d1094012006290310210720062802082108200641286a2003370300200641186a41286a20053a0000200641186a41186a22052004370300200641386a2209200029000037030020062002370320420121032006420137031820064188016a2001109301200628028801210a200628028c01210b024002400240024002400240024002400240200628029001220c450d002007420020081b210d2005290300210e2006290328210f2006290320211020062903182103024020064188016a41186a22112000470d00200c41286c2108200a41286a21050340200641f8006a41086a200941086a2903003703002006200929030037037820034201510d03200541286a210542002103200841586a22080d000b42002103200642003703180c010b200c41286c21082003210220102112200f2113200e2114200a21050340200541086a2903002104200541106a2903002107200541186a29030021152005290300211620064188016a41206a200541206a29030037030020064188016a41186a201537030020064188016a41106a2217200737030020064188016a41086a2004370300200620163703880102400240024020112900002000290000510d00200629039801200d560d0120022104420021020c020b200641f8006a41086a200941086a2903003703002006200929030037037842002103420021104200210f4200210e420021042012210720132115201421160c010b200641f8006a41086a201141086a29030037030020062011290300370378201729030021162006290390012115200629038801210720022104420121020b20024201510d03200541286a210520042102200841586a22080d000b200641306a200e37030020062003370318200620103703202006200f3703280b410021170240200b0d004100211841082119410821050c040b200a10294108211941002118410821050c030b42002104200642003703180c010b200641306a2014370300200620043703182006201237032020062013370328200541286a2105200721102015210f2016210e0b200641c8006a41086a2208200641f8006a41086a29030037030020062006290378370348412810272219450d0420192006290348370318201920103703002019200f370308201941206a2008290300370300201941106a200e370300024002402005200a200c41286c6a2211470d0041012117410121180c010b20064188016a41186a210820042102410121174101211803400240024020082000460d0020022103034020064188016a41206a200541206a2903003703002008200541186a29030037030020064188016a41106a220c200541106a29030037030020064188016a41086a200541086a290300370300200620052903003703880102400240024020082900002000290000510d00200629039801200d560d0120032102420021030c020b200641f8006a41086a200941086a290300370300420021042006420037031820062009290300370378420021022012210720132115201421160c010b200641f8006a41086a200841086a29030037030020062008290300370378200c29030021162006290390012115200629038801210720032102420121030b024020034201510d00200221032011200541286a2205470d010c050b0b200541286a21050c010b02400340200641f8006a41086a200941086a290300370300200642003703182006200929030037037820024201510d01420021022011200541286a2205470d000b420021040c030b200541286a210542002104420021022012210720132115201421160b200641d8006a41086a200641f8006a41086a290300220337030020062006290378220e37035820064188016a41086a221a20033703002006200e37038801024020182017470d00201741016a220c2017490d0620174101742218200c200c2018491b2218ad42287e2203422088a70d062003a7220c4100480d060240024020170d00200c102721190c010b2019201741286c200c102821190b2019450d040b2019201741286c6a220c2015370308200c2007370300200c200629038801370318200c41106a2016370300200c41206a201a290300370300201741016a211720052011470d000b0b0240200b450d00200a10290b20042103201921050b024020034201520d0020064188016a41206a200641206a220941206a29030037030020064188016a41186a200941186a29030037030020064188016a41106a200941106a29030037030020064188016a41086a200941086a2903003703002006200929030037038801024020182017470d00201741016a22052017490d0420174101742209200520052009491b2218ad42287e2202422088a70d042002a722094100480d040240024020170d002009102721050c010b2019201741286c2009102821050b2005450d030b2005201741286c6a2209200629038801370300200941206a20064188016a41206a290300370300200941186a20064188016a41186a290300370300200941106a20064188016a41106a290300370300200941086a20064188016a41086a290300370300201741016a21170b20062017360290012006201836028c012006200536028801200120064188016a10a701200641b0016a24000f0b200c4108102a000b20094108102a000b102b000b41284108102a000bb20201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad4101200110aa0121000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000b20024180016a240020000f0b2004418001103e000b2004418001103e000bd50203027f017e037f230041306b22032400412721040240024020004290ce005a0d00200021050c010b412721040340200341096a20046a2206417c6a200020004290ce0080220542f0b17f7e7ca7220741ffff037141e4006e220841017441fad6c5006a2f00003b00002006417e6a2008419c7f6c20076a41ffff037141017441fad6c5006a2f00003b00002004417c6a2104200042ffc1d72f5621062005210020060d000b0b02402005a7220641e3004c0d00200341096a2004417e6a22046a2005a7220741ffff037141e4006e2206419c7f6c20076a41ffff037141017441fad6c5006a2f00003b00000b024002402006410a480d00200341096a2004417e6a22046a200641017441fad6c5006a2f00003b00000c010b200341096a2004417f6a22046a200641306a3a00000b2002200141b8d6c5004100200341096a20046a412720046b10ab012104200341306a240020040be40501057f024002402001450d00412b418080c4002000280200220641017122011b2107200120056a21080c010b200541016a210820002802002106412d21070b0240024020064104710d00410021020c010b4100210902402003450d002003210a200221010340200920012d000041c00171418001466a2109200141016a2101200a417f6a220a0d000b0b200820036a20096b21080b410121010240024020002802084101460d00200020072002200310b9040d012000280218200420052000411c6a28020028020c1105000f0b02402000410c6a280200220920084b0d00200020072002200310b9040d012000280218200420052000411c6a28020028020c1105000f0b0240024020064108710d00200920086b210941002101024002400240410120002d0030220a200a4103461b0e0402000100020b20092101410021090c010b20094101762101200941016a41017621090b200141016a210103402001417f6a2201450d0220002802182000280204200028021c280210110400450d000b41010f0b41012101200041013a003020004130360204200020072002200310b9040d01200920086b210941002101024002400240410120002d0030220a200a4103461b0e0402000100020b20092101410021090c010b20094101762101200941016a41017621090b200141016a2101024003402001417f6a2201450d0120002802182000280204200028021c280210110400450d000b41010f0b2000280204210a41012101200028021820042005200028021c28020c1105000d01200941016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110400450d000c020b0b2000280204210a41012101200020072002200310b9040d00200028021820042005200028021c28020c1105000d00200941016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110400450d000b0b20010bb80405027f027e017f027e017f230041c0006b22042400024002400240024002400240411410272205450d00200541106a41002800bb8c40360000200541086a41002900b38c40370000200541002900ab8c4037000020054114413410282205450d01200520012900003700142005412c6a200141186a290000370000200541246a200141106a2900003700002005411c6a200141086a290000370000200441286a20054134108401200441286a41106a290300210620042903302107200428022821082005102902402007420020081b220720025422052006420020081b220620035420062003511b450d0041cbb9c0002105411521010c060b200441206a20014104200720027d2207200620037d2005ad7d2206109101200428022022050d04411810272208450d0241002105200841106a41002900cf8c40370000200841086a41002900c78c40370000200841002900bf8c4037000020084118413810282208450d0320082001290000370018200841306a200141186a290000370000200841286a200141106a290000370000200841206a200141086a290000370000200441086a20084138108401200441086a41106a29030021092004290310210a2004280208210b200810292001200a4200200b1b220a20027c220220094200200b1b20037c2002200a54ad7c109c012001200720061089010c050b41144101102a000b41344101102a000b41184101102a000b41384101102a000b200428022421010b2000200136020420002005360200200441c0006a24000bf10306027f027e017f027e017f017e230041306b220324000240024002400240411810272204450d00200441106a41002900cf8c40370000200441086a41002900c78c40370000200441002900bf8c4037000020044118413810282204450d0120042000290000370018200441306a200041186a290000370000200441286a200041106a290000370000200441206a200041086a290000370000200341186a20044138108401200341186a41106a2903002105200329032021062003280218210720041029411410272204450d02200441106a41002800bb8c40360000200441086a41002900b38c40370000200441002900ab8c4037000020044114413410282204450d03200420002900003700142004412c6a200041186a290000370000200441246a200041106a2900003700002004411c6a200041086a290000370000200320044134108401200341106a2903002108200329030821092003280200210a20041029200020094200200a1b220920012006420020071b220620062001562005420020071b220520025620052002511b22041b22017c220b20084200200a1b2002200520041b22027c200b200954ad7c1089012000200620017d200520027d2006200154ad7d109c01200341306a24000f0b41184101102a000b41384101102a000b41144101102a000b41344101102a000b130020004101360204200041e0b9c0003602000b13002000410236020420004198bbc0003602000b3101017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242e5003700000bfa0405037f017e037f017e067f230041206b2202240002400240024002400240200141106a2802002203417f4c0d0020012802082104200129030021050240024020030d00410121060c010b200310272206450d020b20062004200310ce0421072001411c6a2802002208ad420c7e2209422088a70d002009a72204417f4c0d002001280214210a0240024020040d004104210b0c010b20041027220b450d030b0240024020080d004100210c0c010b200a2008410c6c6a210d4100210c200b21060340200a41086a2802002204417f4c0d02200a280200210e0240024020040d004101210f0c010b20041027220f450d060b200f200e200410ce04210e200641086a2004360200200641046a20043602002006200e3602002006410c6a2106200c41016a210c200a410c6a220a200d470d000b0b200241086a2001412c6a290200370300200241106a200141346a290200370300200241186a2001413c6a29020037030020022001290224370300200141d0006a2802002204417f4c0d00200128024821062001280220210a0240024020040d004101210e0c010b20041027220e450d050b200e2006200410ce0421062000200a3602202000411c6a200c360200200041186a2008360200200041146a200b360200200041106a20033602002000410c6a20033602002000200736020820002005370300200041d0006a2004360200200041cc006a200436020020002006360248200020022903003702242000412c6a200241086a290300370200200041346a200241106a2903003702002000413c6a200241186a290300370200200241206a24000f0b1039000b20034101102a000b20044104102a000b20044101102a000b20044101102a000bdf0401077f230041c0006b2203240002400240024002400240411b10272204450d00200441176a4100280081b140360000200441106a41002900fab040370000200441086a41002900f2b040370000200441002900eab0403700002004411b413610282204450d012004200136001b200341186a22014200370300200341106a22054200370300200341086a22064200370300200342003703002004411f20031000200341206a41186a22072001290300370300200341206a41106a2005290300370300200341206a41086a200629030037030020032003290300370320412010272201450d0220012003290320370000200141186a2007290300370000200141106a200341206a41106a2205290300370000200141086a200341206a41086a220629030037000020041029412010272204450d0320042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a290000370000200341186a22024200370300200341106a22074200370300200341086a22084200370300200342003703002004412020031000200341206a41186a220920022903003703002005200729030037030020062008290300370300200320032903003703202001412041c00010282201450d0420012003290320370020200141386a2009290300370000200141306a200341306a290300370000200141286a200341286a29030037000020041029200042c0808080800837020420002001360200200341c0006a24000f0b411b4101102a000b41364101102a000b41204101102a000b41204101102a000b41c0004101102a000bd30102027f027e200028022021020240024002400240410410272203450d00200320023600002000280224210220034104410810282203450d0120032002360004200041086a29030021042000290300210520034108411810282203450d0220032005370008200341106a2004370000200041186a29030021042000290310210520034118413010282200450d0320002005370018200041206a200437000020012802002001280204200041281003200010290f0b41044101102a000b41084101102a000b41184101102a000b41304101102a000bb6750b097f027e087f017e047f017e017f027e027f017e127f230041b0036b22012400024002400240024020004280e101824200520d00200141f8006a4194c1c500411410b5012001280278450d00200128027c2202450d0020014180026a41086a22034200370300200142003703800241d1c2c000410f20014180026a100420014190036a41086a2003290300370300200120012903800237039003200141003602800220014190036a411020014180026a1005210302400240024002400240024002400240024002402001280280022204417f460d002003450d00200120043602f402200120033602f00220014180026a200141f0026a10412001280280022205450d0220014188026a280200210620012802840221072004450d01200310290c010b4108210541002106410021070b20014180026a41086a22034200370300200142003703800241e0c2c000411420014180026a100420014190036a41086a2003290300370300200120012903800237039003200141003602800220014190036a411020014180026a10052103024002402001280280022204417f460d002003450d00200120033602f002200120043602f402200142003703800220014180026a20032004410820044108491b220810ce041a2001200420086b22093602f4022001200320086a22083602f002200441074d0d03200129038002210a200141003602800220014180026a20082009410420094104491b220410ce041a2001200920046b3602f4022001200820046a3602f002200941034d0d03200128028002210420014180026a200141f0026a102d2001280280022209450d03200129028402210b200310292004200b422088a76b20066a2103200ba7450d01200910290c010b200141e8006a41888dc300410d1094012001290370420020012802681b210a41002104200621030b200320024f0d020c030b418f89c3004133104e000b418f89c3004133104e000b0240200420024f0d00200420026b220220066a220320024f0d022005200341286c6a290320210a0c010b200141d8006a4184c3c00041141094012001290360420020012802581b200a7c210a0b200a42ffe0017c220a200a4280e101827d210a02402007450d00200510290b200a2000520d0420014180026a41086a22024200370300200142003703800241d1c2c000410f20014180026a100420014190036a41086a2002290300370300200120012903800237039003200141003602800220014190036a411020014180026a100521020240024002402001280280022203417f460d002002450d00200120033602f402200120023602f00220014180026a200141f0026a1041200128028002220c450d0220014188026a280200210d200128028402210e2003450d01200210290c010b4108210c4100210d4100210e0b200141d0006a4194c1c500411410b5012001280254210f20012802502110200141c0006a41888dc300410d1094012001290348420020012802401b210a0240024002400240200d41286c2202450d00200c41206a290300200a580d010b4101211141002108410021120c010b20014180026a41186a2203200c41186a29030037030020014180026a41106a2204200c41106a29030037030020014180026a41086a2206200c41086a2903003703002001200c29030037038002412010272211450d012011200129038002370000201141186a2003290300370000201141106a2004290300370000201141086a20062903003700000240200c20026a200c41286a2202470d0041012108410121120c010b200d41286c41586a210641202104410121034101210803400240200241206a290300200a580d00200321120c020b200141f0026a41186a2207200241186a290300370300200141f0026a41106a2209200241106a290300370300200141f0026a41086a2205200241086a290300370300200120022903003703f0020240024020082003460d00200321120c010b200341016a22122003490d0a20034101742213201220122013491b221241ffffff3f712012470d0a201241057422134100480d0a0240024020030d002013102721110c010b201120034105742013102821110b20110d0020134101102a000b200241286a2102201120046a220320012903f002370000200341186a2007290300370000200341106a2009290300370000200341086a2005290300370000200441206a2104200841016a210820122103200641586a22060d000b0b02400240024002400240200f410020101b220f200d20086b22034d0d00200141306a4198c3c000411c1094012001290338210b2001290330211420014180026a41086a22024200370300200142003703800241e0c2c000411420014180026a100420014190036a41086a200229030037030020012001290380023703900320014100360288022001420137038002410810272202450d012001428880808080013702840220012002360280022002200b42002014a71b200a7c37000020024108411010282202450d0220014290808080c001370284022002200f20036b22103600082001200236028002200120083602f002200141f0026a20014180026a1030024002400240024020080d002001280288022103200128028402210720012802800221090c010b20084105742105410020012802880222036b2106200128028002210920012802840221072011210203400240200720066a411f4b0d00200341206a22042003490d1120074101742213200420042013491b22044100480d110240024020070d002004102721090c010b200920072004102821090b2009450d03200421070b200920036a22042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a290000370000200641606a2106200341206a2103200241206a2102200541606a22050d000b2001200736028402200120033602880220012009360280020b20014190036a411020092003100302402007450d00200910290b02402012450d00201110290b200141a8036a4200370300200141a0036a420037030020014198036a42003703002001420037039003201041066a2212ad42307e220a422088a7450d010c100b20044101102a000b200aa72202417f4c0d0e0240024020020d0041082111410821020c010b200210272211450d04201121020b20014180026a41186a220920014190036a41186a29030037030020014180026a41106a220520014190036a41106a29030037030020014180026a41086a20014190036a41086a29030037030020012001290390033703800220124102490d04200f20086a200d6b41056a21030340200141f0026a41186a22042009290300370300200141f0026a41106a22062005290300370300200141f0026a41086a220720014180026a41086a29030037030020012001290380023703f0022002420037030820024200370300200241106a20012903f002370300200241186a2007290300370300200241206a2006290300370300200241286a2004290300370300200241306a21022003417f6a22030d000b201041056a21030c080b2012450d09201110290c090b41084101102a000b41104101102a000b20024108102a000b4100210320120d030c040b41204101102a000b418f89c3004133104e000b41f4c2c000200320061037000b20024200370308200242003703002002200129038002370310200241186a20014188026a290300370300200241206a20014190026a290300370300200241286a20014180026a41186a290300370300200341016a21030b200120033602f802200120123602f402200120113602f00220014180026a41086a22024200370300200142003703800241b4c3c000411320014180026a100420014190036a41086a20022903003703002001200129038002370390032001411036028402200120014190036a36028002200141f0026a20014180026a103402402012450d00201110290b200141083a00800220022010360200200141023a00840241b8d6c500410020014180026a1088010b200e450d00200c10290b20014180026a41086a22024200370300200142003703800241e0c2c000411420014180026a100420014190036a41086a2002290300370300200120012903800237039003200141003602800220014190036a411020014180026a100521022001280280022203417f460d012002450d01200120023602f002200120033602f402200142003703800220014180026a20022003410820034108491b220610ce041a2001200320066b22043602f4022001200220066a22063602f0020240024002400240024002400240200341074d0d002001200420044104200441044922031b22076b3602f4022001200620076a3602f00220030d00200129038002210a20014180026a200141f0026a102d2001280280022215450d00200128028402211620021029200a2000520d0520014180026a41086a22024200370300200142003703800241e0c2c000411420014180026a100420014190036a41086a2002290300370300200120012903800237039003200141003602800220014190036a411020014180026a10052102024002400240024002400240024002400240024002402001280280022203417f460d002002450d00200120023602d001200120033602d401200142003703800220014180026a20022003410820034108491b220610ce041a2001200320066b22043602d4012001200220066a22063602d00102400240200341074d0d00200141003602800220014180026a20062004410420044104491b220310ce041a2001200420036b3602d4012001200620036a3602d001200441034d0d00200128028002211720014180026a200141d0016a102d20012802800222180d010b418f89c3004133104e000b20012902840221192002102920014190036a4110100c20014180026a41086a22024200370300200142003703800241b4c3c000411320014180026a100420014190036a41086a2002290300370300200120012903800237039003200141003602800220014190036a411020014180026a10052102024002402001280280022203417f460d002002450d00200120033602f402200120023602f00220014180026a200141f0026a1047200128028002221a450d03200129028402211b02402003450d00200210290b20014190036a4110100c0c010b4200211b4108211a0b200141206a41888dc300410d1094012001290328211c2001280220211d200141106a4184c3c00041141094012001280210211e2001290318211f201a201b422088a7222041306c6a21030240024020170d004100210941002106410021040c010b2017417f6a2106410021040240201a2003460d000240201a202041306c6a220241506a2203290300200341086a2903008450450d00410121090c020b20014190036a41186a200241606a220241186a29000037030020014190036a41106a200241106a29000037030020014190036a41086a200241086a2900003703002001200229000037039003410121040b410021090b20014189026a20014190036a41086a29030037000020014191026a20014190036a41106a29030037000020014199026a20014190036a41186a290300370000200120043a0080022001200129039003370081024101210f20014180026a41017221020240024020040d00200141f0026a41186a200241186a290000370300200141f0026a41106a200241106a2900003703004100212141012122410021230c010b20024280809aa6eaafe301420010ad01200141f0026a41186a200241186a290000370300200141f0026a41106a200241106a290000370300200141f0026a41086a200241086a290000370300200120022900003703f002412010272222450d03202220012903f002370000202241186a200141f0026a41186a2211290300370000202241106a200141f0026a41106a2213290300370000202241086a200141f0026a41086a220c290300370000410020066b211220014180026a41017221024102210641202104410121234101212102400340201220236a4101460d01200941ff01710d01201a2003460d01200341506a2207290300200741086a29030084500d012011200341606a220341186a29000022003703002013200341106a290000220a370300200c200341086a290000220b3703002001200329000022143703f00220022014370000200241086a2203200b370000200241106a2209200a370000200241186a22052000370000200141013a00800220024280809aa6eaafe301420010ad0120014190036a41186a2005290000220037030020014190036a41106a2009290000220a37030020014190036a41086a2003290000220b3703002001200229000022143703900320014180026a41186a2209200037030020014180026a41106a2205200a37030020014180026a41086a2208200b3703002001201437038002024020232021470d00202341016a22032023490d162006200320032006491b222141ffffff3f712021470d16202141057422034100480d160240024020230d002003102721220c010b202220042003102821220b2022450d100b202220046a2203200129038002370000200341186a2009290300370000200341106a2005290300370000200341086a2008290300370000200641026a2106200441206a2104202341016a212341002109200721030c000b0b202220046a210f2023450d0020014180026a41086a21052022210c034020014190016a200c10b60102402001280290014101470d002001280298012104200141b0016a10b70120012802b0012110024020012802b8012202450d00200241216c2103201041016a21022004410876210841012004411f7174210d20044105764107712212417f73210e034002402002417f6a2d00004101470d0020014180026a41186a200241186a220629000037030020014180026a41106a200241106a22072900003703002005200241086a22092900003703002001200229000037038002200120083602a00220014190036a20014180026a10b8010240201220012802980322044f0d002004200e6a221120044f0d0a200128029003221320114102746a280200200d7121040240200128029403450d00201310290b2004450d0120014180026a200210b90102402001290380024201510d00411310272204450d0c2004410f6a41002800f9c340360000200441086a41002900f2c340370000200441002900eac34037000020044113413310282204450d0d200420022900003700132004412b6a2006290000370000200441236a20072900003700002004411b6a2009290000370000200141f0026a41186a22064200370300200141f0026a41106a22074200370300200141f0026a41086a22094200370300200142003703f00220044133200141f0026a1000200141d0016a41186a2006290300370300200141d0016a41106a2007290300370300200141d0016a41086a2009290300370300200120012903f0023703d001200141d0016a4120100c200410290c020b200141086a41a8c1c500411110b5012001200128020c41016a410120012802081b3602ac02411310272204450d0d2004410f6a41002800f9c340360000200441086a41002900f2c340370000200441002900eac34037000020044113413310282204450d0e200420022900003700132004412b6a2006290000370000200441236a20072900003700002004411b6a2009290000370000200141f0026a41186a22064200370300200141f0026a41106a22074200370300200141f0026a41086a22094200370300200142003703f00220044133200141f0026a1000200141d0016a41186a2006290300370300200141d0016a41106a2007290300370300200141d0016a41086a2009290300370300200120012903f0023703d00120014120360294032001200141d0016a36029003200520014190036a10b301200410290c010b200128029403450d0020012802900310290b200241216a21022003415f6a22030d000b0b20012802b401450d00201010290b200f200c41206a220c470d000b0b20014180026a41086a22024200370300200142003703800241d1c2c000410f20014180026a100420014190036a41086a2002290300370300200120012903800237039003200141003602800220014190036a411020014180026a10052102024002402001280280022203417f460d002002450d00200120033602f402200120023602f00220014180026a200141f0026a10412001280280022224450d0a20014188026a280200210920012802840221252003450d01200210290c010b4100212541082124410021090b20014101360280022019422088a72207450d0a4100212641002127024020072024200941286c6a220620246b41286e2202200220074b1b2202450d00200241057422034100480d13200310272204450d0a2001200436028002200221270b20242102200721042001280280022228210303400240200620026b41f8004b0d0020062002460d112024200941286c6a2108410121060240034020032002290000370000200341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200420062205460d01200541016a2106200341206a21032008200241286a2202470d000b0b202620056a21260c110b20032002290000370000200341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000024020044101470d00202641017221260c110b20032002290028370020200341386a200241c0006a290000370000200341306a200241386a290000370000200341286a200241306a29000037000020044102460d0f20032002290050370040200341d8006a200241e8006a290000370000200341d0006a200241e0006a290000370000200341c8006a200241d8006a29000037000020044103460d0e20032002290078370060200341f8006a20024190016a290000370000200341f0006a20024188016a290000370000200341e8006a20024180016a290000370000202641046a212620034180016a2103200241a0016a21022004417c6a22040d000c100b0b02402016450d00201510290b41fdc3c000410f1010418cc4c000413510100c120b418f89c3004133104e000b41204101102a000b41f4c2c000201120041037000b41134101102a000b41334101102a000b41134101102a000b41334101102a000b418f89c3004133104e000b20034101102a000b410021272001280280022128410021260c040b418f89c3004133104e000b20034101102a000b202641037221260c010b202641027221260b201f4200201e1b201c4200201d1b7c21142024200941286c6a21100240024002400240024002400240024002402007450d0020102024460d01200741016a2103200941286c2104202421020340200141f0026a41186a200241186a290300370300200141f0026a41106a200241106a290300370300200141f0026a41086a200241086a290300370300200120022903003703f0022003417f6a2203450d04200241286a2102200441586a22040d000b201021020c020b20102024470d040b202421020b2022200f460d01202241086a2900002100202241106a290000210a2022290000210b20014190036a41186a202241186a29000037030020014190036a41106a200a37030020014190036a41086a20003703002001200b37039003202241206a210441022106201421000c040b200241206a290300210020014180026a41186a200141f0026a41186a29030037030020014180026a41106a200141f0026a41106a29030037030020014180026a41086a200141f0026a41086a290300370300200120012903f00237038002200241286a21020c020b200141003602880120014208370380012025450d03202410290c030b20014180026a41186a202441186a29030037030020014180026a41106a202441106a29030037030020014180026a41086a202441086a2903003703002001202429030037038002202441286a2102202429032021000b20014190036a41186a20014180026a41186a29030037030020014190036a41106a20014180026a41106a29030037030020014190036a41086a20014180026a41086a29030037030020012001290380023703900341002106202221040b417f417f201020026b41286d2203200f20046b4105766a220720072003491b220341016a220720072003491b220ead42287e220a422088a70d05200aa72203417f4c0d050240024002400240024002400240024020030d00410821124108211e0c010b200310272212450d012012211e0b2012200129039003370300201241186a20014190036a41186a290300370300201241106a20014190036a41106a290300370300201241086a20014190036a41086a290300370300201e200037032002402006450d0002402004200f470d00410121290c050b200441086a2900002100200441106a290000210a2004290000210b20014190036a41186a200441186a29000037030020014190036a41106a200a37030020014190036a41086a20003703002001200b37039003200441206a21040c020b024020022010470d0002402004200f460d00200441086a2900002100200441106a290000210a2004290000210b20014190036a41186a200441186a29000037030020014190036a41106a200a37030020014190036a41086a20003703002001200b37039003200441206a21040c030b410121290c040b20014180026a41186a200241186a220329030037030020014180026a41106a200241106a220629030037030020014180026a41086a200241086a2207290300370300200120022903003703800220014190036a41086a200729030037030020014190036a41106a200629030037030020014190036a41186a200329030037030020012002290300370390032002290320210041002111200241286a21020c020b20034108102a000b41022111201421000b410221074102210341282106034020014180026a41186a220920014190036a41186a221329030037030020014180026a41106a220520014190036a41106a220c29030037030020014180026a41086a220820014190036a41086a220d290300370300200120012903900337038002024020032229417f6a2203200e470d002003417f417f201020026b41286d220e200f20046b4105766a221d201d200e491b220e41016a221d201d200e491b6a220e2003490d082007200e200e2007491b220ead42287e220a422088a70d08200aa722034100480d080240024020294101470d002003102721120c010b201220062003102821120b2012450d032012211e0b201e20066a2203200129038002370300200341186a2009290300370300200341106a2005290300370300200341086a2008290300370300200341206a20003703000240024002400240201141ff01710e03010200010b2004200f460d04200441086a2900002100200441106a290000210a2004290000210b2013200441186a290000370300200c200a370300200d20003703002001200b37039003200441206a21044201210a41022111201421000c020b024020102002470d004102211102402004200f470d004200210a0c030b200441086a2900002100200441106a290000210a2004290000210b2013200441186a290000370300200c200a370300200d20003703002001200b37039003200441206a21044201210a201421000c020b2009200241186a22032903003703002005200241106a22092903003703002008200241086a22052903003703002001200229030037038002200529030021002009290300210a2002290300210b20132003290300370300200c200a370300200d20003703002001200b37039003200229032021004201210a41002111200241286a21020c010b20102002460d022013200241186a290300370300200c200241106a290300370300200d200241086a2903003703002001200229030037039003200229032021004201210a41012111200241286a21020b200741026a2107202941016a2103200641286a2106200a4200520d000b0b02402025450d00202410290b2001200e360284012001201e36028001200120293602880120294115490d012029410176222aad42287e2200422088a70d072000a72202417f4c0d0702400240024020020d004108212b410821050c010b20021027222b450d01202b21050b201e41586a212c201e41a87f6a212d4104210c4100212e410021092029211d0340201d21064100211d4101210702402006417f6a222f450d00024002400240024002400240201e202f41286c6a41206a290300200641286c2202201e6a41506a2903002200540d002006417e6a2107202d20026a21034100211d410021020340024020072002470d00200621070c080b200241016a210220002003290300220a5a2104200341586a2103200a210020040d000b200241016a21072002417f7320066a21040c010b202d200641056c41037422126a2102202f210402400340024020044101470d00410021040c020b2004417f6a210420002002290300220a542103200241586a2102200a210020030d000b0b20062004490d01200620294b0d03200620046b22074101762208450d00202c20126a2102201e200441286c6a2103034020014180026a41206a2212200341206a221129030037030020014180026a41186a2213200341186a220d29030037030020014180026a41106a220e200341106a220f29030037030020014180026a41086a2210200341086a221d2903003703002001200329030037038002200241206a22242903002100200241186a2225290300210a200241106a2230290300210b200241086a2231290300211420032002290300370300201d2014370300200f200b370300200d200a3703002011200037030020242012290300370300202520132903003703002030200e290300370300203120102903003703002002200129038002370300200241586a2102200341286a21032008417f6a22080d000b0b024020040d002004211d0c050b0240200741094d0d002004211d0c050b200620294b0d01201e200441286c6a2112034020062004417f6a221d490d0402402006201d6b22074102490d00201e200441286c6a220241206a2203290300201e201d41286c6a221141206a220829030022005a0d00200141f0026a41186a2213201141186a220d290300370300200141f0026a41106a220e201141106a220f290300370300200141f0026a41086a2210201141086a2224290300370300200120112903003703f002201120022903003703002024200241086a290300370300200f200241106a290300370300200d200241186a29030037030020082003290300370300024020074103490d00202f210320122108201141f0006a29030020005a0d00024003402008220241206a200241c8006a290300370300200241186a200241c0006a290300370300200241106a200241386a290300370300200241086a200241306a2903003703002002200241286a220829030037030020042003417f6a2203460d01200241f0006a2903002000540d000b0b200241286a21020b200220012903f00237030020022000370320200241186a2013290300370300200241106a200e290300370300200241086a20102903003703000b201d450d05201241586a2112201d21042007410a4f0d050c000b0b20042006103e000b20062004417f6a221d490d010b20062029107f000b201d2006103e000b024002400240202e2009470d00202e41016a2202202e490d0a202e4101742203200220022003491b220241ffffffff01712002470d0a200241037422034100480d0a02400240202e0d0020031027210c0c010b200c202e41037420031028210c0b200c450d012002212e0b200c20094103746a220220073602042002201d360200200941016a220d2109200d4102490d0103400240024002400240200c200d2211417f6a220d4103746a2202280200450d002011410374200c6a220741746a2802002206200228020422034d0d0041022109201141024d0d06200c2011417d6a22024103746a2802042204200320066a4d0d0141032109201141034d0d06200741646a280200200420066a4d0d01201121090c060b20114103490d0120022802042103200c2011417d6a22024103746a28020421040b20042003490d010b2011417e6a21020b0240024002400240024002402011200241016a22244d0d00201120024d0d01200c20024103746a220e2802042225200e2802006a2202200c20244103746a220f2802002210490d02200220294b0d03200e41046a2130201e201041286c6a2212200f280204221341286c22036a2107200241286c2104200220106b220920136b220220134f0d04202b2007200241286c220310ce041a200520036a21060240024020134101480d00200241014e0d010b20072102200521030c060b202c20046a21042007210203402004200241586a2209200641586a2208200641786a290300200241786a2903005422071b2203290300370300200441206a200341206a290300370300200441186a200341186a290300370300200441106a200341106a290300370300200441086a200341086a2903003703002006200820071b2106024020122009200220071b2202490d00200521030c070b200441586a21042005210320052006490d000c060b0b41d8e3c100202420111037000b41d8e3c100200220111037000b20102002103e000b20022029107f000b202b2012200310ce041a200520036a21060240024020134101480d00200920134a0d010b20122102200521030c010b201e20046a210820052103201221020340200220072003200741206a290300200341206a2903005422091b2204290300370300200241206a200441206a290300370300200241186a200441186a290300370300200241106a200441106a290300370300200241086a200441086a2903003703002003200341286a20091b2103200241286a2102200741286a200720091b220720084f0d01200620034b0d000b0b20022003200620036b220420044128706b10ce041a2030202520136a360200200e2010360200200f200f41086a2024417f7320116a41037410cf041a200d2109200d41014d0d020c000b0b20034104102a000b201d0d000b0240202e450d00200c10290b202a450d03202b10290c030b20024108102a000b20034108102a000b20294102490d002029417f6a2104201e202941286c6a2107410021090340024002400240202920042202417f6a2204490d00202920046b22034102490d02201e200241286c6a220241206a2206290300201e200441286c6a220541206a220829030022005a0d02200141f0026a41186a2212200541186a2211290300370300200141f0026a41106a2213200541106a220c290300370300200141f0026a41086a220d200541086a220e290300370300200120052903003703f00220052002290300370300200e200241086a290300370300200c200241106a2903003703002011200241186a2903003703002008200629030037030020034103490d012009210620072103200541f0006a29030020005a0d0103402003220241586a22032002290300370300200341206a200241206a290300370300200341186a200241186a290300370300200341106a200241106a290300370300200341086a200241086a2903003703002006417f6a2206450d02200241286a2103200241c8006a29030020005a0d020c000b0b20042029103e000b200220012903f00237030020022000370320200241186a2012290300370300200241106a2013290300370300200241086a200d2903003703000b200941016a2109200741586a210720040d000b0b20014180026a41086a22024200370300200142003703800241d1c2c000410f20014180026a100420014190036a41086a20022903003703002001200129038002370390032001411036028402200120014190036a3602800220014180016a20014180026a102f410021042001280284012109200128028001210702400240200128028801220241286c22030d004101210e4100210f0c010b200341286d220f41ffffff3f71200f470d03200f41057422034100480d0320031027220e0d0020034101102a000b02402002450d00200241286c210641002104200e2102200721030340200341086a2900002100200341106a290000210a2003290000210b200241186a200341186a290000370000200241106a200a370000200241086a20003700002002200b370000200441016a2104200241206a2102200341286a2103200641586a22060d000b0b02402009450d00200710290b20282026200e200410ba0120014180026a41086a22024200370300200142003703800241d8c3c000411220014180026a100420014190036a41086a2002290300370300200120012903800237039003200141003602800220014190036a411020014180026a1005210202400240024002400240024002402001280280022203417f460d002002450d00200120033602f402200120023602f00220014180026a200141f0026a102d200128028002221d450d0220014188026a280200211320012802840221242003450d01200210290c010b410021244101211d410021130b200141e8016a4200370300200141e0016a4200370300200141d8016a4200370300200142003703d001201341ffffff3f712013470d0920134105742202417f4c0d090240024020020d00410121120c010b200210272212450d020b20014180026a41186a2204200141d0016a41186a29030037030020014180026a41106a2206200141d0016a41106a29030037030020014180026a41086a2207200141d0016a41086a290300370300200120012903d0013703800220134102490d022013417f6a21032012210203402002200129038002370000200241186a2004290300370000200241106a2006290300370000200241086a2007290300370000200241206a21022003417f6a22030d000b2013417f6a21110c030b418f89c3004133104e000b20024101102a000b41002111201221022013450d010b2002200129038002370000200241186a20014180026a41186a290300370000200241106a20014180026a41106a290300370000200241086a20014180026a41086a290300370000201141016a21110b201a202041306c6a2102201ba7210d410021100240024002400240024002400240034002402017450d002002201a460d02200241506a2202290300200241086a29030084500d0203402017417f6a2217450d01201a2002460d03200241506a2103200241506a21022003290300200341086a2903008450450d000c030b0b2002201a460d0102400340200241506a22042903002100200441086a290300210a20014190036a41186a2206200241606a220341186a29030037030020014190036a41106a2207200341106a29030037030020014190036a41086a2209200341086a29030037030020012003290300370390032000200a84500d0120014180026a41186a2203200629030037030020014180026a41106a2205200729030037030020014180026a41086a22082009290300370300200120012903900337038002200141f0016a20014180026a10b601200141d0016a41186a220c2006290300370300200141d0016a41106a22062007290300370300200141d0016a41086a2207200929030037030020012001290390033703d001024020012802f0014101460d0020042102201a2004470d010c040b0b20014190016a41086a2209200729030037030020014190016a41106a2207200629030037030020014190016a41186a2206200c290300370300200120012903d00122003703b001200120003703900120012802f8012104200320062903003703002005200729030037030020082009290300370300200120012903900137038002201120044d0d03200241506a2102201220044105746a2204200129038002370000200441186a2003290300370000200441106a2005290300370000200441086a2008290300370000201041016a2110410021170c010b0b200141b0016a41086a200141f0026a41086a290300370300200141b0016a41106a200141f0026a41106a290300370300200141b0016a41186a200141f0026a41186a290300370300200120012903f0023703b0010b0240200d450d00201a10290b02402011201341ffffff3f712202200220114b1b2207450d00201d210220122103410021060340024020022003460d0020022003412010d004450d00411610272204450d042004410e6a41002900c9c240370000200441086a41002900c3c240370000200441002900bbc24037000020044116413610282204450d05200420022900003700162004412e6a200241186a290000370000200441266a200241106a2900003700002004411e6a200241086a290000370000200141f0026a41186a22094200370300200141f0026a41106a22054200370300200141f0026a41086a22084200370300200142003703f00220044136200141f0026a1000200141d0016a41186a2009290300370300200141d0016a41106a2005290300370300200141d0016a41086a2008290300370300200120012903f0023703d001200141d0016a4120100c200410290b200241206a2102200341206a2103200641016a22062007490d000b0b201220114105746a21022011210920114104490d0320014180026a41206a2105200141c0026a210820014180026a41e0006a210c20014180036a210d20014198026a210420014190026a210620014188026a2107200221032011210903402004420037030020064200370300200742003703002001420037038002024020052003460d00200341606a20014180026a412010d004450d002009417f6a21030c060b2004420037030020064200370300200742003703002001420037038002024020082003460d00200341406a20014180026a412010d004450d002009417e6a21030c060b20044200370300200642003703002007420037030020014200370380020240200c2003460d00200341a07f6a20014180026a412010d004450d002009417d6a21030c060b2004420037030020064200370300200742003703002001420037038002200341807f6a210202400240200d2003460d00200220014180026a412010d0040d010b2009417c6a210920022103200220126b41e0004b0d010c050b0b2009417c6a21030c040b41c8c3c000200420111037000b41164101102a000b41364101102a000b20022012460d012009417f6a210320014180026a41206a210420014198026a210620014190026a210720014188026a210903402006420037030020074200370300200942003703002001420037038002024020042002460d00200241606a20014180026a412010d0040d020b2003417f6a21032012200241606a2202470d000c020b0b200341016a22022011201120024b1b21110b2001419c026a202636020020014180026a41186a202736020020014194026a202836020020014180026a41106a20233602002001418c026a2021360200200141083a00800220014180026a41086a22022022360200200141033a00840241b8d6c500410020014180026a10880120024200370300200142003703800241d8c3c000411220014180026a100420014190036a41086a200229030037030020012001290380023703900320014100360288022001420137038002200120113602f002200141f0026a20014180026a10300240024020110d002001280288022103200128028402210720012802800221090c010b20114105742105410020012802880222036b2106200128028002210920012802840221072012210203400240200720066a411f4b0d00200341206a22042003490d0520074101742208200420042008491b22044100480d050240024020070d002004102721090c010b200920072004102821090b2009450d04200421070b200920036a22042002290000370000200441186a200241186a290000370000200441106a200241106a290000370000200441086a200241086a290000370000200641606a2106200341206a2103200241206a2102200541606a22050d000b2001200736028402200120033602880220012009360280020b20014190036a411020092003100302402007450d00200910290b02402013450d00201210290b20014180026a41086a22024200370300200142003703800241dfc1c500411620014180026a100420014190036a41086a22032002290300370300200120012903800237039003200120103602800220014190036a411020014180026a41041003200141a8c1c500411110b501200128020021042001280204210620024200370300200142003703800241a8c1c500411120014180026a1004200320022903003703002001200129038002370390032001200641016a410120041b3602800220014190036a411020014180026a4104100302402024450d00201d10290b0240200f450d00200e10290b2019a7450d00201810290b2016450d02201510290c020b20044101102a000b102b000b200141b0036a24000f0b1039000bc60101027f230041206b22032400200341106a41086a220442003703002003420037031020012002200341106a1004200341086a200429030037030020032003290310370300410021022003410036021020034110200341106a1005210402400240024020032802102201417f470d000c010b20034100360210200341106a20042001410420014104491b10ce041a200141034d0d012003280210210120041029410121020b2000200136020420002002360200200341206a24000f0b418f89c3004133104e000bdb0201047f230041c0006b2202240002400240411610272203450d002003410e6a41002900c9c240370000200341086a41002900c3c240370000200341002900bbc24037000020034116413610282203450d01200320012900003700162003412e6a200141186a290000370000200341266a200141106a2900003700002003411e6a200141086a290000370000200241206a41186a22014200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034136200241206a1000200241186a2001290300370300200241106a2004290300370300200241086a200529030037030020022002290320370300200241206a2002412010bb010240024020022802204101460d00200041003602000c010b20002002290320370200200041086a200241206a41086a2802003602000b20031029200241c0006a24000f0b41164101102a000b41364101102a000bed02030a7f017e017f230041206b220124002001410010bc01200141106a410110bc0102400240024020012802182202450d004102210320012802042104200128020821050340200128021421062001280210210702400240200420056b200241216c220841216d2209490d00200520096a2109200128020021020c010b200520096a22092005490d0420044101742202200920092002491b220aad42217e220b422088a70d04200ba7220c4100480d040240024020040d00200c102721020c010b2001280200200441216c200c102821020b2002450d0320012002360200200a21040b2002200541216c6a2007200810ce041a02402006450d00200710290b200141106a200310bc01200341016a210320092105200128021822020d000b20012004360204200120093602080b02402001280214450d00200128021010290b20002001290300370200200041086a200141086a280200360200200141206a24000f0b200c4101102a000b102b000bd60302047f017e230041d0006b220224000240024002400240411310272203450d002003410f6a41002800d0c440360000200341086a41002900c9c440370000200341002900c1c44037000020034113413310282203450d01200320012900003700132003412b6a200141186a290000370000200341236a200141106a2900003700002003411b6a200141086a290000370000200128022021042003413341e60010282201450d0220012004360033200241306a41186a22034200370300200241306a41106a22044200370300200241306a41086a220542003703002002420037033020014137200241306a1000200241086a41186a2003290300370300200241086a41106a2004290300370300200241086a41086a20052903003703002002200229033037030820024100360230200241086a4120200241306a100521040240024020022802302203417f460d002002200336022c20022004360228200241306a200241286a104520022802302205450d052002290234210602402003450d00200410290b20002006370204200020053602000c010b20004100360208200042043702000b20011029200241d0006a24000f0b41134101102a000b41334101102a000b41e6004101102a000b418f89c3004133104e000b8f0502087f047e230041c0006b2202240002400240411310272203450d002003410f6a41002800f9c340360000200341086a41002900f2c340370000200341002900eac34037000020034113413310282203450d01200320012900003700132003412b6a200141186a290000370000200341236a200141106a2900003700002003411b6a200141086a290000370000200241206a41186a22014200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034133200241206a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002002410036022020024120200241206a1005210102400240024020022802202204417f460d002001450d0020024100360220200241206a20012004410420044104491b220510ce041a0240200441034d0d002002280220210620024100360220200241206a200120056a2207200420056b2204410420044104491b220510ce041a200441034d0d00200228022021082002420037032820024200370320200241206a200720056a2207200420056b2204411020044110491b220510ce041a2004410f4d0d00200241286a2209290300210a2002290320210b2002420037032820024200370320200241206a200720056a200420056b2204411020044110491b10ce041a2004410f4b0d020b418f89c3004133104e000b4200210a0c010b2009290300210c2002290320210d20011029200041206a200c370300200041186a200d370300200041106a200a3703002000200b3703082000412c6a2008360200200041286a20063602004201210a0b2000200a37030020031029200241c0006a24000f0b41134101102a000b41334101102a000b9411030e7f077e017f230022042105200441c0016b4160712204240002400240024002400240024002400240200141ffffff3f712001470d0020014105742206417f4c0d000240024020060d00410121070c010b200610272207450d020b410021084100210602402001450d0020014105742109416020006b210a2007210620002108034020062008290000370000200641186a200841186a290000370000200641106a200841106a290000370000200641086a200841086a290000370000200641206a2106200841206a2108200941606a22090d000b200020014105746a200a6a41057641016a2106200121080b20042006360218200420083602142004200736021020072006410041202006676b10e00120044180016a41086a220642003703002004420037038001419acec200411d20044180016a1004200441a0016a41086a200629030037030020042004290380013703a0012004410036028001200441a0016a411020044180016a10052108024002402004280280012206417f460d00200420063602442004200836024020044180016a200441c0006a102d200428028001220b450d0420044188016a2802002109200428028401210c2006450d01200810290c010b4101210b410021094100210c0b2009410574220a450d07200441a0016a411472210d200441a0016a410872210e200b21080340200441206a41186a220f200841186a290000370300200441206a41106a2210200841106a290000370300200441206a41086a2211200841086a29000037030020042008290000370320200441c0006a200441206a10f202200441003602a80120042903582112200420042903b801221337035820042903502114200420042903b001221537035020042903402116200420042903a00137034020042903482117200420042903a80122183703482015422088a721002018422088a721012013a721072018a7210902402017a72206450d00200420163703a001200420173703a801200420143703b001200420123703b801200420062014a74105746a36028c01200420063602880120042017422088a73602840120042006360280012004200441106a36029001200441f0006a20044180016a104b200e41086a200441f0006a41086a2219280200360200200e200429037037020020042014422088a722062012422088a74105746a36028c01200420063602880120042012a73602840120042006360280012004200441106a36029001200441f0006a20044180016a104b200d41086a2019280200360200200d200429037037020020042903a801211720042903a001211420042903b801211820042903b001211202402009450d0002402001450d00200910290b2007450d00200010290b20042014370340200420173703482017422088a72101200420123703502012422088a72100200420183703582017a721092018a721070b411a102721060240024020090d002006450d06200641186a41002f00cfce423b0000200641106a41002900c7ce42370000200641086a41002900bfce42370000200641002900b7ce423700002006411a413a10282206450d072006200429032037001a200641326a200f2903003700002006412a6a2010290300370000200641226a2011290300370000200441a0016a41186a22094200370300200441a0016a41106a22014200370300200441a0016a41086a22074200370300200442003703a0012006413a200441a0016a100020044180016a41186a200929030037030020044180016a41106a200129030037030020044180016a41086a2007290300370300200420042903a0013703800120044180016a4120100c200610290c010b2006450d07200641186a41002f00cfce423b0000200641106a41002900c7ce42370000200641086a41002900bfce42370000200641002900b7ce423700002006411a413a10282206450d082006200429032037001a200641326a200f2903003700002006412a6a2010290300370000200641226a2011290300370000200441a0016a41186a220f4200370300200441a0016a41106a22104200370300200441a0016a41086a22114200370300200442003703a0012006413a200441a0016a100020044180016a41186a200f29030037030020044180016a41106a201029030037030020044180016a41086a2011290300370300200420042903a00137038001200441203602a401200420044180016a3602a001200441c0006a200441a0016a10db022006102902402001450d00200910290b2007450d00200010290b200841206a2108200a41606a220a0d000c080b0b1039000b20064101102a000b418f89c3004133104e000b411a4101102a000b413a4101102a000b411a4101102a000b413a4101102a000b0240200c450d00200b10290b200441003602a801200442013703a001200420033602800120044180016a200441a0016a1030024002400240024020030d0020042802a801210620042802a401210120042802a00121070c010b20034105742100410020042802a80122066b210920042802a001210720042802a401210103400240200120096a411f4b0d00200641206a22082006490d042001410174220a20082008200a491b22084100480d040240024020010d002008102721070c010b200720012008102821070b2007450d03200821010b200720066a22082002290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200941606a2109200641206a2106200241206a2102200041606a22000d000b200420013602a401200420063602a801200420073602a0010b20044180016a41086a22024200370300200442003703800141d692c200411b20044180016a1004200441a0016a41086a200229030037030020042004290380013703a001200441a0016a411020072006100302402001450d00200710290b02402004280214450d00200428021010290b200524000f0b20084101102a000b102b000bcb0101037f230041106b22032400410021042003410036020c200120022003410c6a1005210102400240200328020c2202417f460d002001450d0020034100360204200341046a200120024104200241044922051b220410ce041a20050d012003280204210520034100360208200341086a200120046a200220046b2204410420044104491b10ce041a200441034d0d012003280208210420011029200041086a200436020020002005360204410121040b20002004360200200341106a24000f0b418f89c3004133104e000b830802117f017e23004190016b22022400024002400240024002400240410e10272203450d00200341066a41002900dac440370000200341002900d4c4403700002003410e411c10282204450d012004200136000e200241306a41186a22034200370300200241306a41106a22014200370300200241306a41086a220542003703002002420037033020044112200241306a1000200241086a41186a2003290300370300200241086a41106a2001290300370300200241086a41086a20052903003703002002200229033037030820024100360270200241086a4120200241f0006a100521060240024020022802702207417f460d002002200736022c200220063602282002200241286a102e2002280200450d07024002402002280204220841fc00200841fc00491b22090d004101210a0c010b200941216c22031027220a450d050b02402008450d0020022802282105200228022c21034100210b4100210c4100210d0340200241003a0030200241306a20052003410047220110ce041a20032001490d072002200320016b220e36022c2002200520016a22053602280240024002402003450d0020022d0030220141014b0d004100210f200e21030240024020010e020100010b200241306a200e4120200e4120491b22016a41004100412020016b2001411f4b1b10cd041a200241306a2005200110ce041a2002200e20016b220336022c2002200520016a2205360228200e411f4d0d01200241f0006a41186a200241306a41186a290300370300200241f0006a41106a200241306a41106a290300370300200241f0006a41086a200241306a41086a290300370300200220022903303703704101210f0b200d41016a210e200241d0006a41186a2210200241f0006a41186a290300370300200241d0006a41106a2211200241f0006a41106a290300370300200241d0006a41086a2212200241f0006a41086a29030037030020022002290370370350200d2009470d020240200b200e200e200b491b2209ad42217e2213422088a70d002013a7220141004e0d020b102b000b2009450d0b200a10290c0b0b02400240200d0d0020011027210a0c010b200a200c20011028210a0b200a450d090b200a200c6a2201200f3a0000200141016a2002290350370000200141096a2012290300370000200141116a2011290300370000200141196a2010290300370000200b41026a210b200c41216a210c200e210d2008200e470d000b0b200a450d072008ad4220862009ad84211302402007450d00200610290b200020133702042000200a3602000c010b20004100360208200042013702000b2004102920024190016a24000f0b410e4101102a000b411c4101102a000b20034101102a000b20012003103e000b20014101102a000b418f89c3004133104e000b13002000410a360204200041b8c5c0003602000b340020004187f4c10036020420004100360200200041146a4110360200200041106a41d4ebc000360200200041086a42073702000b3001017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241003600000b13002000410a360204200041a487c1003602000b3101017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241c0003600000b3201017f02404108102722020d0041084101102a000b2000428880808080013702042000200236020020024280e1013700000b3001017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241013600000b3001017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241063600000b3d01017f02404110102722020d0041104101102a000b200242003700082002428080d287e2bc2d370000200042908080808002370204200020023602000b3d01017f02404110102722020d0041104101102a000b200242003700082002428080e983b1de16370000200042908080808002370204200020023602000b3e01017f02404110102722020d0041104101102a000b2002420037000820024280809aa6eaafe301370000200042908080808002370204200020023602000bf10901047f230041206b220224000240024002400240024002400240024002400240024002400240024002402001280200417f6a220341094b0d0020030e0a0102030405060708090a010b419498c1001058000b2001410c6a2802002203417f4c0d0a200128020421044101210502402003450d00200310272205450d0c0b20052004200310ce0421052000410c6a2003360200200041086a20033602002000200536020420004101360200200041106a20012902103703000c090b2001410c6a2802002203417f4c0d09200128020421050240024020030d00410121040c010b200310272204450d0c0b20042005200310ce0421052000410c6a2003360200200041086a20033602002000200536020420004102360200200041106a20012902103703000c080b200128020421054101210302400240200141086a22042d00004101460d002002411e6a200441036a2d00003a0000200241086a200141186a290200370300200241106a200141206a290200370300200241186a200141286a2d00003a0000200220042f00013b011c2002200141106a2902003703002001410c6a2802002104410021030c010b2001410c6a28020021040b20002005360204200020022f011c3b0009200041086a20033a00002000410c6a2004360200200041106a20022903003702002000412c6a200129022c3702002000410b6a2002411e6a2d00003a0000200041186a200241086a290300370200200041206a200241106a290300370200200041286a200241186a280200360200200041033602000c070b20004104360200200020012802043602040c060b20004105360200200020012802043602040c050b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002105410021030c010b200141086a28020021050b200020033a0004200020022f011c3b0005200041306a2001290330370300200041086a20053602002000410c6a2002290300370200200041386a200141386a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602002001280228210120004106360200200041286a20013602000c040b20004107360200200020012802043602040c030b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002101410021030c010b200141086a28020021010b200020033a0004200020022f011c3b000520004108360200200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c020b20004109360200200041086a200141086a2903003703000c010b2000410a360200200041086a200141086a2903003703000b200241206a24000f0b1039000b20034101102a000b20034101102a000bd8a60104197f037e0b7f0a7e230041d0046b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e0b000102030405060708090a000b200341fc026a4101360200200342013702ec02200341ccfdc4003602e802200341023602ac04200341c4fdc4003602a8042003200341a8046a3602f802200341e8026a41f098c1001057000b200141086a2802002104200128020421050240024020022d00000d004101210620022d00014101460d010b41d588c3002107412a210841002109410121062004450d32200510290c320b200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241086a2d00002114200241066a2f01002115200241056a2d00002116200241046a2d00002117200241026a2f010021182001410c6a2802002119200141146a280200211a200141106a280200211b20032002411a6a29010037038003200320073a00ff02200320083a00fe02200320093b01fc022003200a3a00fb022003200b3a00fa022003200c3b01f8022003200d3a00f7022003200e3a00f6022003200f3b01f402200320103a00f302200320173a00ea02200320183b01e802200320132012410874201141187472723600ef02200320162015410874722014411874723600eb02200320193602b004200320043602ac04200320053602a804200341086a200341e8026a200341a8046a201b201a10cb01200328020c210820032802082107410021090c310b200141086a28020021042001280204210541d588c3002107412a210820022d00000d2f20022d00014101470d2f2002411a6a290100211c200241196a2d00002107200241186a2d00002108200241166a2f01002106200241156a2d00002109200241146a2d0000210a200241126a2f0100210b200241116a2d0000210c200241106a2d0000210d2002410e6a2f0100210e2002410d6a2d0000210f2002410c6a2d000021102002410a6a2f01002111200241096a2d00002112200241086a2d00002113200241066a2f01002114200241056a2d00002115200241046a2d00002116200241026a2f010021172001410c6a2802002118200141146a2802002119200141106a280200211a410d10272202450d08200241056a410029008599413700002002410029008099413700002002410d412d10282202450d092002201c370025200220073a0024200220083a0023200220063b0021200220093a00202002200a3a001f2002200b3b001d2002200c3a001c2002200d3a001b2002200e3b00192002200f3a00182002201141087420104118747220127236001420022014410874201572201341187472360010200220163a000f200220173b000d200341e8026a41186a22074200370300200341e8026a41106a22084200370300200341e8026a41086a22064200370300200342003703e8022002412d200341e8026a1000200341a8046a41186a2007290300370300200341a8046a41106a2008290300370300200341a8046a41086a2006290300370300200320032903e8023703a804200341003602e802200341a8046a4120200341e8026a100521090240024020032802e8022207417f460d0041002106200341e8026a2007412020074120491b22086a41004100412020086b2008411f4b1b10cd041a200341e8026a2009200810ce041a2007411f4b0d01418f89c3004133104e000b2002102941959bc4002107410b21080c300b20032f01e802210720032d00ea02210820032900eb02211c20032d00f302210a20032902f402211d20032802fc02210b200329038003211e20091029200210292003201e370380032003200b3602fc022003201d3702f4022003200a3a00f3022003201c3700eb02200320083a00ea02200320073b01e802200320183602b004200320043602ac04200320053602a804200341106a200341e8026a200341a8046a201a201910cb012003280214210820032802102107410121090c300b200141216a290000211c200141206a2d0000210a2001411d6a2f0000210b2001411c6a2d0000210c200141196a2f0000210d200141186a2d0000210e200141156a2f0000210f200141146a2d00002110200141106a28020021112001410c6a2802002105200141086a2d00002117200141306a280200211f2001412c6a280200212020012d001f211220012d001b211320012d0017211420012d000b211520012f00092116200128020421212002411a6a290100211d200241196a2d00002118200241186a2d00002119200241166a2f0100211a200241156a2d0000211b200241146a2d00002122200241126a2f01002123200241116a2d00002124200241106a2d000021252002410e6a2f010021262002410d6a2d00002127200241046a2d00002128200241026a2f01002129412a210441d588c30021070240024020022d0000450d004101210641002108410021090c010b41012106410021084100210920022d00014101470d002002410c6a2d000021082002410a6a2f01002109200241096a2d00002104200241066a2f0100410874200241056a2d000072200241086a2d0000411874722107410021060b200941ffff0371410874200841187472200441ff017172210820060d2d2003201d3703d002200320183a00cf02200320193a00ce022003201a3b01cc022003201b3a00cb02200320223a00ca02200320233b01c802200320243a00c702200320253a00c602200320263b01c402200320273a00c302200320083600bf02200320073600bb02200320283a00ba02200320293b01b8020240201741ff01714101470d00200341e8026a200541067610cc0120032802e80221070240024020032802f0022005413f7122024b0d00410021020c010b200720024105746a2202290018211c20022d0017210a20022d0016211220022f0014210b20022d0013210c20022d0012211320022f0010210d20022d000f210e20022d000e211420022f000c210f20022d000b2110200228000721112002280003210520022d0002211520022f00002116410121020b024020032802ec02450d00200710290b2002450d2d0b2003201c3703f0032003200a3a00ef03200320123a00ee032003200b3b01ec032003200c3a00eb03200320133a00ea032003200d3b01e8032003200e3a00e703200320143a00e6032003200f3b01e403200320103a00e303200320113600df03200320053600db03200320153a00da03200320163b01d803200341e8026a41086a22024200370300200342003703e80241e0c2c0004114200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d8020240200341d8026a411041b8d6c50041004100100b417f460d00418d99c1002107412621080c2e0b200341e8026a200341b8026a10b901024020032903e8024201510d0041b399c1002107411821080c2e0b200341e8026a200341d8036a10b901024020032903e8024201510d0041969ac1002107412c21080c2e0b20034190036a280200210c20034180016a41a8c1c500411110b50141e199c10021074116210820032802840141002003280280011b201f470d2d0240200c41016a201f490d0041f799c1002107411f21080c2e0b200341e8026a202141067610bc01410021072021413f71220220032802f0024f0d2020032802e802200241216c6a22022d00004101470d2020022f00012106200241196a290000211c200241186a2d00002109200241176a2d00002104200241156a2f00002105200241146a2d0000210a200241136a2d0000210b200241116a2f0000210d200241106a2d0000210e2002410f6a2d0000210f2002410d6a2f000021102002410c6a2d00002111200241086a2800002113200241046a2800002112200241036a2d00002102410121070c210b41d588c3002107412a210820022d00000d2c20022d00014101470d2c20012802042116200241196a2d00002107200241186a2d00002108200241166a2f01002106200241156a2d00002109200241146a2d00002104200241126a2f01002105200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002114200241026a2f0100211520032002411a6a29010037039804200320073a009704200320083a009604200320063b019404200320093a009304200320043a009204200320053b0190042003200a3a008f042003200b3a008e042003200c3b018c042003200d3a008b04200320143a008204200320153b01800420032010200f41087472200e41187472360087042003201320124108747220114118747236008304200341e8026a41086a22024200370300200342003703e80241e0c2c0004114200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d8020240200341d8026a411041b8d6c50041004100100b417f460d0041a99bc1002107411e21080c2d0b411310272202450d082002410f6a41002800f9c340360000200241086a41002900f2c340370000200241002900eac34037000020024113413310282202450d092002200329038004370013411821082002412b6a20034180046a41186a290300370000200241236a20034180046a41106a2903003700002002411b6a20034180046a41086a290300370000200341e8026a41186a22074200370300200341e8026a41106a22064200370300200341e8026a41086a22094200370300200342003703e80220024133200341e8026a1000200341a8046a41186a2007290300370300200341a8046a41106a2006290300370300200341a8046a41086a2009290300370300200320032903e8023703a804200341a8046a412041b8d6c50041004100100b21072002102902402007417f470d0041c79bc10021070c2d0b200341a8046a201641067610bc01410021072016413f71220220032802b0044f0d1d20032802a804200241216c6a22022d00004101470d1d20022f00012106200241196a290000211c200241186a2d00002109200241176a2d00002104200241156a2f00002105200241146a2d0000210a200241136a2d0000210b200241116a2f0000210c200241106a2d0000210d2002410f6a2d0000210e2002410d6a2f0000210f2002410c6a2d00002110200241086a2800002112200241046a2800002111200241036a2d00002102410121070c1e0b200128020421052002411a6a290100211c200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d00002113200241046a2d00002114200241026a2f0100211541d588c3002107412a21040240024020022d0000450d004101210641002108410021090c010b41012106410021084100210920022d00014101470d002002410c6a2d000021092002410a6a2f01002108200241096a2d00002104200241066a2f0100410874200241056a2d000072200241086a2d0000411874722107410021060b200841ffff0371410874200441ff017172200941187472210820060d2b2003201c370398042003200a3a0097042003200b3a0096042003200c3b0194042003200d3a0093042003200e3a0092042003200f3b019004200320103a008f04200320113a008e04200320123b018c04200320133a008b0420032008360087042003200736008304200320143a008204200320153b018004411610272202450d092002410e6a41002900c9c240370000200241086a41002900c3c240370000200241002900bbc24037000020024116413610282202450d0a20022003290380043700162002412e6a20034180046a41186a290300370000200241266a20034180046a41106a290300370000411e21082002411e6a20034180046a41086a290300370000200341e8026a41186a22074200370300200341e8026a41106a22064200370300200341e8026a41086a22094200370300200342003703e80220024136200341e8026a1000200341a8046a41186a2007290300370300200341a8046a41106a2006290300370300200341a8046a41086a2009290300370300200320032903e8023703a804200341a8046a412041b8d6c50041004100100b21062002102941df9bc10021072006417f470d2b200341a8016a41dfc1c500411610b50120032802ac01210820032802a8012106200341e8026a41086a22024200370300200342003703e80241d8c3c0004112200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a100521070240024020032802e8022209417f460d002007450d00200320093602ac04200320073602a804200341e8026a200341a8046a102d20032802e802220b450d0d200341f0026a280200210220032802ec02210c2009450d01200710290c010b4100210c4101210b410021020b02400240024002402008410020061b220d2005470d0020022005460d010b41fd9bc100210741162108200220054d0d0120034180036a4200370300200341f8026a4200370300200341f0026a4200370300200342003703e802200b20054105746a2206200341e8026a460d002006200341e8026a412010d0040d010b200341a0016a20034180046a4280809aa6eaafe301420010ac0120032802a001450d0141939cc1002107411e21080b200c450d2c200b10290c2c0b20034198016a41a8c1c500411110b501200328029c0121062003280298012109411610272207450d0c2007410e6a41002900c9c240370000200741086a41002900c3c240370000200741002900bbc24037000020074116413610282207450d0d20072003290380043700162007412e6a20034180046a41186a290300370000200741266a20034180046a41106a2903003700002007411e6a20034180046a41086a290300370000200341e8026a41186a22084200370300200341e8026a41106a22044200370300200341e8026a41086a220a4200370300200342003703e80220074136200341e8026a1000200341a8046a41186a2008290300370300200341a8046a41106a2004290300370300200341a8046a41086a200a290300370300200320032903e8023703a804410410272208450d0e20082006410020091b36000020084104410810282208450d0f20082005360004200341a8046a412020084108100320081029200710290240024020022005460d00200341e8026a41186a220820034180046a41186a290300370300200341e8026a41106a220620034180046a41106a290300370300200341e8026a41086a220920034180046a41086a29030037030020032003290380043703e802200220054d0d12200b20054105746a220720032903e802370000200741186a2008290300370000200741106a2006290300370000200741086a20092903003700000c010b200341e8026a41186a220720034180046a41186a290300370300200341e8026a41106a220820034180046a41106a290300370300200341e8026a41086a220620034180046a41086a29030037030020032003290380043703e8020240200c2005470d00200541016a22022005490d2b20054101742209200220022009491b220c41ffffff3f71200c470d2b200c41057422024100480d2b0240024020050d0020021027210b0c010b200b200541057420021028210b0b200b450d180b200b20054105746a220220032903e802370000200241186a2007290300370000200241106a2008290300370000200241086a2006290300370000200541016a21020b200341e8026a41086a22074200370300200342003703e80241d8c3c0004112200341e8026a1004200341d8026a41086a2007290300370300200320032903e8023703d802200341003602f002200342013703e802200320023602a804200341a8046a200341e8026a103002400240024020020d0020032802f002210720032802ec02210920032802e80221040c010b20024105742105410020032802f00222076b210620032802e802210420032802ec022109200b210203400240200920066a411f4b0d00200741206a22082007490d2d2009410174220a20082008200a491b22084100480d2d0240024020090d002008102721040c010b200420092008102821040b2004450d03200821090b200420076a22082002290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200641606a2106200741206a2107200241206a2102200541606a22050d000b200320093602ec02200320073602f002200320043602e8020b200341d8026a411020042007100302402009450d00200410290b0240200c450d00200b10290b200341e8026a41086a22024200370300200342003703e80241dfc1c5004116200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802410121062003200d41016a3602e802200341d8026a4110200341e8026a410410030c190b20084101102a000b200141386a290300211c200141306a290300211d2001411d6a290000212a2001411c6a2d00002116200141196a2f00002117200141186a2d00002118200141156a2f00002119200141146a2d0000211a200141116a2f0000211b200141106a2d000021222001410c6a2802002123200141086a2802002105200141286a280200211f20012d001b212420012d0017212520012d0013212620012d0007212720012f0005212820012d000421292002411a6a290100211e200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d00002113200241046a2d00002114200241026a2f0100211541d588c3002107412a21040240024020022d0000450d004101210641002108410021090c010b41012106410021084100210920022d00014101470d002002410c6a2d000021092002410a6a2f01002108200241096a2d00002104200241066a2f0100410874200241056a2d000072200241086a2d0000411874722107410021060b200841ffff0371410874200441ff017172200941187472210820060d2a2003201e3703f0032003200a3a00ef032003200b3a00ee032003200c3b01ec032003200d3a00eb032003200e3a00ea032003200f3b01e803200320103a00e703200320113a00e603200320123b01e403200320133a00e303200320083600df03200320073600db03200320143a00da03200320153b01d8030240201d201c8450450d0041ef9cc100210741d00021080c2b0b0240202941ff01714101470d00200341e8026a200541067610cc0120032802e80221070240024020032802f0022005413f7122024b0d00410021020c010b200720024105746a2202290018212a20022d0017211620022d0016212420022f0014211720022d0013211820022d0012212520022f0010211920022d000f211a20022d000e212620022f000c211b20022d000b2122200228000721232002280003210520022d0002212720022f00002128410121020b024020032802ec02450d00200710290b2002450d2a0b2003202a37039804200320163a009704200320243a009604200320173b019404200320183a009304200320253a009204200320193b0190042003201a3a008f04200320263a008e042003201b3b018c04200320223a008b0420032023360087042003200536008304200320273a008204200320283b0180044111210820034198026a41a8c1c500411110b50141de9cc1002107200328029c0241002003280298021b201f470d2a200341e8026a41086a22024200370300200342003703e80241e0c2c0004114200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a100521020240024020032802e8022207417f460d002002450d002003200720074108200741084922081b22066b22073602ac042003200220066a22063602a804024020080d002003200720074104200741044922081b22096b3602ac042003200620096a3602a80420080d00200341e8026a200341a8046a102d20032802e802220a0d020b418f89c3004133104e000b41b19cc1002107412d21080c2b0b20032902ec02212b2002102920034190026a41cdc1c500411210b50120034180026a20032802940241002003280290021bad42004280a094a58d1d420010d304411410272202450d1020034180026a41086a290300211e200329038002212a200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d11200220032903d8033700142002412c6a200341f0036a290300370000200241246a200341d8036a41106a2903003700002002411c6a200341d8036a41086a290300370000200341e8016a20024134108401200341e8016a41106a290300212c20032903f001212d20032802e801210720021029202d420020071b202a54202c420020071b222c201e54202c201e511b450d1941f09dc1002107412e21080c1a0b4101210620022d000120022d0000720d1720012802042102200341e8026a41086a22074200370300200342003703e8024194c1c5004114200341e8026a1004200341d8026a41086a2007290300370300200320032903e8023703d802200320023602e802200341d8026a4110200341e8026a410410030c160b024020022d000120022d000072450d0041ad88c3002107412821080c290b200141086a28020021070240024020012d00044101460d00200141106a2d00002108200141146a2d00002106200141186a2d000021092001411c6a2d0000210420012f0005210220012d00072105200128020c210a20012f0011210b20012d0013210c20012f0015210d20012d0017210e20012f0019210f20012d001b2110200129001d211c0c010b200341e8026a200741067610cc0120032802e80221110240024020032802f0022007413f7122024b0d00410021120c010b201120024105746a2202290018211c20022d0017210420022d0016211020022f0014210f20022d0013210920022d0012210e20022f0010210d20022d000f210620022d000e210c20022f000c210b20022d000b21082002280007210a2002280003210720022d0002210520022f00002102410121120b024020032802ec02450d00201110290b2012450d280b2003201c3703d002200320043a00cf02200320103a00ce022003200f3b01cc02200320093a00cb022003200e3a00ca022003200d3b01c802200320063a00c7022003200c3a00c6022003200b3b01c402200320083a00c3022003200a3600bf02200320073600bb02200320053a00ba02200320023b01b802200341e8026a41086a22024200370300200342003703e80241d1c2c000410f200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a100521020240024020032802e8022207417f460d002002450d00200320073602ac04200320023602a804200341e8026a200341a8046a104120032802e8022208450d12200341f0026a280200210920032802ec02210d2007450d01200210290c010b4100210d41082108410021090b024002400240200941286c2206450d00410021070340200341e8026a41206a200820076a220241206a290300370300200341e8026a41186a200241186a290300370300200341e8026a41106a200241106a290300370300200341e8026a41086a200241086a290300370300200320022903003703e802200341e8026a200341b8026a412010d0040d022006200741286a2207470d000b0b4100210a200341003602b004200342083703a8044108210b0240200d0d004100210c0c020b200810294100210c0c010b20034180046a41086a200341e8026a41086a290300221c370300200341d8036a41086a2206201c370300200341d8036a41106a2204200341e8026a41106a290300370300200341d8036a41186a2205200341e8026a41186a290300370300200341d8036a41206a220a200341e8026a41206a290300370300200320032903e802221c370380042003201c3703d80341281027220b450d12200b20032903d803370300200b41206a200a290300370300200b41186a2005290300370300200b41106a2004290300370300200b41086a200629030037030002400240200941286c41586a2007470d004101210a4101210c0c010b200241286a210f2008200941286c6a220541586a21104101210a4101210c0340200f210202400340200341e8026a41206a2207200241206a290300370300200341e8026a41186a2206200241186a290300370300200341e8026a41106a2209200241106a290300370300200341e8026a41086a2204200241086a290300370300200320022903003703e802200341e8026a200341b8026a412010d0040d012005200241286a2202470d000c030b0b200341a8046a41206a2007290300221c37030020034180046a41086a2004290300221d37030020034180046a41106a2009290300221e37030020034180046a41186a2006290300222a37030020034180046a41206a201c370300200320032903e802222b370380042007201c3703002006202a3703002009201e3703002004201d3703002003202b3703e8020240200c200a470d00200a41016a220c200a490d2a200a410174220e200c200c200e491b220cad42287e221c422088a70d2a201ca7220e4100480d2a02400240200a0d00200e1027210b0c010b200b200a41286c200e1028210b0b200b450d160b200241286a210f200b200a41286c6a220e20032903e802370300200e41206a2007290300370300200e41186a2006290300370300200e41106a2009290300370300200e41086a2004290300370300200a41016a210a20102002470d000b0b0240200d450d00200810290b2003200a3602b0042003200c3602ac042003200b3602a8040b200341e8026a41086a22024200370300200342003703e80241d1c2c000410f200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341103602ec022003200341d8026a3602e802200341a8046a200341e8026a102f410021080240200a41286c22020d0041012104410021090c150b200241286d220941ffffff3f712009470d26200941057422024100480d262002102722040d1420024101102a000b4101210620022d000120022d0000720d15200141086a290300211c200341e8026a41086a22024200370300200342003703e8024198c3c000411c200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d8022003201c3703e802200341d8026a4110200341e8026a410810030c140b4101210620022d000120022d0000720d14200141086a290300211c200341e8026a41086a22024200370300200342003703e8024184c3c0004114200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d8022003201c3703e802200341d8026a4110200341e8026a410810030c130b410d4101102a000b412d4101102a000b41134101102a000b41334101102a000b41164101102a000b41364101102a000b418f89c3004133104e000b41164101102a000b41364101102a000b41044101102a000b41084101102a000b41c8c3c000200520021037000b41144101102a000b41344101102a000b418f89c3004133104e000b41284108102a000b200e4108102a000b20024101102a000b0240200a450d00200a41286c21064100210820042102200b21070340200741086a290000211c200741106a290000211d2007290000211e200241186a200741186a290000370000200241106a201d370000200241086a201c3700002002201e370000200841016a2108200241206a2102200741286a2107200641586a22060d000b0b0240200c450d00200b10290b200341e8026a41186a200341b8026a41186a290300370300200341e8026a41106a200341b8026a41106a290300370300200341e8026a41086a200341b8026a41086a290300370300200320032903b8023703e80241012106200341e8026a41012004200810ba012009450d00200410290b410021070c070b41ad88c300210741282108410121090c130b200341e8026a41086a22024200370300200342003703e80241b4c3c0004113200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a1005210202400240024002400240024002400240024020032802e8022207417f460d002002450d00200320073602ac04200320023602a804200341e8026a200341a8046a104720032802e802220c450d03200341f0026a280200210f20032802ec02211102402007450d00200210290b200f450d0541c19ec100210741232108200c290300201d54200c41086a290300222c201c54202c201c511b450d07200341e8026a41086a22024200370300200342003703e80241d1c2c000410f200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a1005210220032802e8022207417f460d012002450d01200320073602ac04200320023602a804200341e8026a200341a8046a104120032802e8022204450d04200341f0026a280200210520032802ec02210b2007450d02200210290c020b41bf9dc1002107413121080c080b4100210b41082104410021050b2004200541286c6a21092004210241002107024003400240200920026b41f8004b0d0020092002460d062004200541286c6a2109034020034180046a2002460d032007200220034180046a412010d00422064100476a21072006450d032009200241286a2202470d000c070b0b200220034180046a460d012007200220034180046a412010d00422064100476a21072006450d01200241286a220620034180046a460d012007200620034180046a412010d00422064100476a21072006450d01200241d0006a220620034180046a460d012007200620034180046a412010d00422064100476a21072006450d01200241f8006a220620034180046a460d01200241a0016a21022007200620034180046a412010d00422064100476a210720060d000b0b2007202b422088a7490d0341e49ec100210741362108200b450d04200410290c040b418f89c3004133104e000b418f89c3004133104e000b41f4c2c000410041001037000b0240200b450d00200410290b200341a8026a10b701200341e8026a20034180046a10b60120032802e8024101460d01024020032802ac02450d0020032802a80210290b419e9ec10021070b2011450d01200c10290c010b20032802a802212602400240024002400240024020032802b00222020d004200212e4200212f0c010b20032802ec022106200241216c2107202641016a2102200341f0026a2802002208410876210941012008411f7174210d20084105764107712204417f73210e20034188036a21054200212e4200212f034002402002417f6a2d00004101470d00200341e8026a200210b90120032903e8024201520d002003280290032006490d0020052903002130200341e8026a41106a2903002131200329038003213220032903f0022133200341e0016a41a8c1c500411110b501200341a8046a41186a200241186a290000370300200341a8046a41106a200241106a290000370300200341a8046a41086a200241086a290000370300200320022900003703a804200320093602c804200341b8026a200341a8046a10b8014200212c4200212d0240200420032802c00222084f0d002008200e6a220b20084f0d04203020317c203220337c222c203254ad7c420020032802b802200b4102746a280200200d7122081b212d202c420020081b212c0b024020032802bc02450d0020032802b80210290b202d202f7c202c202e7c222e202c54ad7c212f0b200241216a21022007415f6a22070d000b0b200c200f41306c6a2106200c210202400240024002400240024002400240024003400240200620026b4190014b0d00024020022006460d00034041012108200241106a220220034180046a460d04200220034180046a412010d004450d04200241206a22022006470d000b0b41002108202e201d85202f201c858450450d0220034180046a41186a290300211e20034190046a290300212a20034188046a290300212c200329038004212d200c201c370308200c201d370300200c202d370310200c41186a202c370300200c41206a202a370300200c41286a201e370300200f4115490d0c200f4101762221ad42307e221c422088a70d1c201ca72202417f4c0d1c20020d03410821254108210b0c040b41012108200241106a220720034180046a460d01200720034180046a412010d004450d01200241c0006a220720034180046a460d01200720034180046a412010d004450d01200241f0006a220720034180046a460d01200720034180046a412010d004450d01200241a0016a220720034180046a460d01200241c0016a2102200720034180046a412010d0040d000b0b411410272202450d07200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d06200220032903d8033700142002412c6a200341d8036a41186a290300370000200241246a200341d8036a41106a2903003700002002411c6a200341d8036a41086a290300370000200341c8016a20024134108401200341c8016a41106a290300211c20032903d001211d20032802c801210720021029200341d8036a201d420020071b221d202a201d201d202a56201c420020071b222c201e56202c201e511b22021b221c7d202c201e202c20021b222d7d201d201c54ad7d1089010240202a201c7d222c201e202d7d202a201c54ad7d221d84500d00411810272202450d06200241106a41002900cf8c40370000200241086a41002900c78c40370000200241002900bf8c4037000020024118413810282202450d05200220032903d803370018200241306a200341d8036a41186a290300370000200241286a200341d8036a41106a290300370000200241206a200341d8036a41086a290300370000200341b0016a20024138108401200341b0016a41106a290300212a20032903b801211e20032802b001210720021029200341d8036a201e420020071b221e202c201e201e202c56202a420020071b222a201d56202a201d511b22021b222c7d202a201d202a20021b221d7d201e202c54ad7d109c01201d202d7c202c201c7c222a202c54ad7c211e0b200341e8026a41086a22024200370300200342003703e80241b18ac0004116200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a100521070240024020032802e8022202417f470d004200211c4200211d0c010b200342003703f002200342003703e802200341e8026a20072002411020024110491b10ce041a2002410f4d0d04200341f0026a290300211d20032903e802211c200710290b200341e8026a41086a22024200370300200342003703e80241b18ac0004116200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d80220034200201d201e7d201c202a54ad7d221e201c202a7d222a201c56201e201d56201e201d511b22021b3703f00220034200202a20021b3703e802200341d8026a4110200341e8026a41101003419a9fc10041b09fc10020081b21074116410f20081b2108410121020c0b0b200210272225450d012025210b0b200c41506a2128200c41306a211f200c41f07e6a2129410421124100212741002105200f2117034020172104410021174101210902402004417f6a2208450d00024002400240024002400240200c200841306c6a2202290300200441306c220e200c6a41a07f6a2207290300221d54200241086a290300221e200741086a290300221c54201e201c511b0d002004417e6a210d2029200e6a2102410021174100210703400240200d2007470d00200421090c080b201d2002290300222a5a2108201c200241086a290300221e512106201c201e5a2109200241506a2102200741016a2107202a211d201e211c2008200920061b0d000b200741016a21092007417f7320046a21080c010b2029200e6a210202400340024020084101470d00410021080c020b201d2002290300222a542107201c200241086a290300221e512106201c201e542109200241506a21022008417f6a2108202a211d201e211c2007200920061b0d000b0b20042008490d012004200f4b0d03200420086b22094101762206450d002028200e6a2102200c200841306c6a21070340200341e8026a41286a220d200741286a220e290300370300200341e8026a41206a2210200741206a2213290300370300200341e8026a41186a2214200741186a2215290300370300200341e8026a41106a2216200741106a2217290300370300200341e8026a41086a2218200741086a2219290300370300200320072903003703e802200241086a221a290300211c200241106a221b290300211d200241186a2222290300211e200241206a2223290300212a200241286a2224290300212c20072002290300370300200e202c3703002013202a3703002015201e3703002017201d3703002019201c3703002024200d2903003703002023201029030037030020222014290300370300201b2016290300370300201a2018290300370300200220032903e802370300200741306a2107200241506a21022006417f6a22060d000b0b024020080d00200821170c050b0240200941094d0d00200821170c050b2004200f4b0d01200420086b2106201f200841306c6a210d034020042008417f6a2217490d040240200420176b22094102490d00200c200841306c6a2202290300200c201741306c6a2208290300221e5a200241086a2207290300221d200841086a220e290300221c5a201d201c511b0d00200341e8026a41186a2213200841286a2210290300370300200341e8026a41106a2214200841206a2215290300370300200341e8026a41086a2216200841186a2218290300370300200320082903103703e80220082002290300370300200e2007290300370300200841106a200241106a2903003703002018200241186a2903003703002015200241206a2903003703002010200241286a29030037030041012107024020094103490d002008290360201e5a200841e8006a290300221d201c5a201d201c511b0d004102210e200d211003402010220241506a22072002290300370300200741286a200241286a290300370300200741206a200241206a290300370300200741186a200241186a290300370300200741106a200241106a290300370300200741086a200241086a2903003703002006200e2207460d01200741016a210e200241306a2210290300201e5a200241386a290300221d201c5a201d201c511b450d000b0b2002201e3703002002201c3703082008200741306c6a220241286a2013290300370300200241206a2014290300370300200241186a2016290300370300200220032903e8023703100b2017450d05200d41506a210d200641016a2106201721082009410a4f0d050c000b0b20082004103e000b20042008417f6a2217490d010b2004200f107f000b20172004103e000b02400240024020272005470d00202741016a22022027490d1c20274101742207200220022007491b220241ffffffff01712002470d1c200241037422074100480d1c0240024020270d002007102721120c010b201220274103742007102821120b2012450d01200221270b201220054103746a2202200936020420022017360200200541016a2213210520134102490d010340024002400240024020122013220e417f6a22134103746a2202280200450d00200e41037420126a220941746a2802002206200228020422074d0d0041022105200e41024d0d062012200e417d6a22024103746a2802042208200720066a4d0d0141032105200e41034d0d06200941646a280200200820066a4d0d01200e21050c060b200e4103490d01200228020421072012200e417d6a22024103746a28020421080b20082007490d010b200e417e6a21020b024002400240024002400240200e200241016a22184d0d00200e20024d0d01201220024103746a2214280204221920142802006a2202201220184103746a22152802002216490d022002200f4b0d03201441046a211a200c201641306c6a220d2015280204221041306c22076a2106200241306c2108200220166b220420106b220220104f0d0420252006200241306c220710ce041a200b20076a21090240024020104101480d00200241014e0d010b20062102200b21070c060b202820086a21082006210203402008200241506a2206200941506a22042004290300200629030054200441086a290300221c200641086a290300221d54201c201d511b22051b2207290300370300200841086a200741086a290300370300200841106a200741106a290300370300200841186a200741186a290300370300200841206a200741206a290300370300200841286a200741286a2903003703002009200420051b21090240200d2006200220051b2202490d00200b21070c070b200841506a2108200b2107200b2009490d000c060b0b41d8e3c1002018200e1037000b41d8e3c1002002200e1037000b20162002103e000b2002200f107f000b2025200d200710ce041a200b20076a21090240024020104101480d00200420104a0d010b200d2102200b21070c010b200c20086a2105200b2107200d210203402002200620072006290300200729030054200641086a290300221c200741086a290300221d54201c201d511b22041b2208290300370300200241086a200841086a290300370300200241106a200841106a290300370300200241186a200841186a290300370300200241206a200841206a290300370300200241286a200841286a2903003703002007200741306a20041b2107200241306a2102200641306a200620041b220620054f0d01200920074b0d000b0b20022007200920076b220820084130706b10ce041a201a201920106a360200201420163602002015201541086a2018417f73200e6a41037410cf041a20132105201341014d0d020c000b0b20074104102a000b20170d000b02402027450d00201210290b2021450d08202510290c080b20024108102a000b418f89c3004133104e000b41384101102a000b41184101102a000b41344101102a000b41144101102a000b41f4c2c000200b20081037000b200f4102490d00200f417f6a2108200c200f41306c6a21044101210603400240024002400240200f20082202417f6a2208490d00200f20086b22074102490d03200c200241306c6a2202290300200c200841306c6a2209290300221e5a200241086a2205290300221d200941086a220b290300221c5a201d201c511b0d03200341e8026a41186a220d200941286a220e290300370300200341e8026a41106a2210200941206a2212290300370300200341e8026a41086a2213200941186a2214290300370300200320092903103703e80220092002290300370300200b2005290300370300200941106a200241106a2903003703002014200241186a2903003703002012200241206a290300370300200e200241286a2903003703004101210520074103490d022009290360201e5a200941e8006a290300221d201c5a201d201c511b0d02410021052004210703402007220241506a22072002290300370300200741286a200241286a290300370300200741206a200241206a290300370300200741186a200241186a290300370300200741106a200241106a290300370300200741086a200241086a29030037030020062005220b460d02200b417f6a2105200241306a2207290300201e5a200241386a290300221d201c5a201d201c511b0d020c000b0b2008200f103e000b4102200b6b21050b2002201e3703002002201c3703082009200541306c6a220241286a200d290300370300200241206a2010290300370300200241186a2013290300370300200220032903e8023703100b200441506a21042006417f6a210620080d000b0b2003200f3602b004200320113602ac042003200c3602a804200341e8026a41086a22024200370300200342003703e80241b4c3c0004113200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341103602ec022003200341d8026a3602e802200341a8046a200341e8026a103402402011450d00200c10290b41002102410021070b024020032802ac02450d00202610290b0240024020020d00202ba7450d120c010b02402011450d00200c10290b202ba7450d110b200a10290c100b202ba7450d0f200a10290c0f0b0b024020032802ac04450d0020032802a80410290b024020070d0041919bc10021070c0e0b2003201c37038003200320093a00ff02200320043a00fe02200320053b01fc022003200a3a00fb022003200b3a00fa022003200c3b01f8022003200d3a00f7022003200e3a00f6022003200f3b01f402200320103a00f302200320123600ef02200320113600eb02200320023a00ea02200320063b01e8020240200341e8026a20034180046a412010d0040d0020034180046a201610cd0120034180046a428080e983b1de16420010ad01200342f0f2bda9c6add9b1f4003703d80220034188016a41888dc300410d109401200320032903900142002003280288011b3703b802200341a8046a20034180046a10930120032802ac04210720032802a804210220032802b0042108200341bc046a200341d8026a36020020032002200841286c6a3602b404200320023602b004200320073602ac04200320023602a8042003200341b8026a3602b804200341d8036a200341a8046a104a200341a8046a41086a200341d8036a41086a280200360200200320032903d8033703a80420034180046a200341a8046a10a701410021070c0e0b41f89ac1002107411921080c0d0b0b024020032802ec02450d0020032802e80210290b024020070d0041cb99c10021070c0c0b2003201c37039804200320093a009704200320043a009604200320053b0194042003200a3a0093042003200b3a0092042003200d3b0190042003200e3a008f042003200f3a008e04200320103b018c04200320113a008b0420032013360087042003201236008304200320023a008204200320063b018004200341e8026a202041067610bc0141002107024002402020413f71220220032802f0024f0d0020032802e802200241216c6a22022d00004101470d0020022f00012108200241196a290000211c200241186a2d00002106200241176a2d00002109200241156a2f00002104200241146a2d00002105200241136a2d0000210a200241116a2f0000210b200241106a2d0000210d2002410f6a2d0000210e2002410d6a2f0000210f2002410c6a2d00002110200241086a2800002112200241046a2800002111200241036a2d00002102410121070c010b0b024020032802ec02450d0020032802e80210290b024020070d0041e49ac1002107411421080c0c0b2003201c3703c004200320063a00bf04200320093a00be04200320043b01bc04200320053a00bb042003200a3a00ba042003200b3b01b8042003200d3a00b7042003200e3a00b6042003200f3b01b404200320103a00b304200320123600af04200320113600ab04200320023a00aa04200320083b01a804024020034180046a200341b8026a412010d004450d0041c29ac1002107411221080c0c0b0240200341a8046a200341d8036a412010d004450d0041d49ac1002107411021080c0c0b200341e8026a41186a2213200341d8036a41186a2214290300370300200341e8026a41106a2215200341d8036a41106a2216290300370300200341e8026a41086a2217200341d8036a41086a2218290300370300200320032903d8033703e802410021022003410036028803200341d8026a200341e8026a10b8010240024020032802e00222050d004101210e4100210f0c010b4100210d4100210f4101210e4100211103402005417f4c0d0a20032802dc02211220032802d80221100240024020051027220a450d00024002400240200541027422020d00410021040c010b201020026a210b410021042010210903402009280200210702404120102722020d0041204101102a000b200941046a210920022007411f763a001f200220074101713a000020022007411e764101713a001e20022007411d764101713a001d20022007411c764101713a001c20022007411b764101713a001b20022007411a764101713a001a200220074119764101713a0019200220074118764101713a0018200220074117764101713a0017200220074116764101713a0016200220074115764101713a0015200220074114764101713a0014200220074113764101713a0013200220074112764101713a0012200220074111764101713a0011200220074110764101713a001020022007410f764101713a000f20022007410e764101713a000e20022007410d764101713a000d20022007410c764101713a000c20022007410b764101713a000b20022007410a764101713a000a200220074109764101713a0009200220074108764101713a00082002200741ff017122074107763a0007200220074106764101713a0006200220074105764101713a0005200220074104764101713a0004200220074103764101713a0003200220074102764101713a0002200220074101764101713a00014100210702400240024002400340200741206a220841034d0d010240200220076a2208411f6a2d0000450d002007411f6a21060c040b02402008411e6a2d0000450d002007411e6a21060c040b02402008411d6a2d00000d002007417c6a21072008411c6a2d00000d030c010b0b2007411d6a21060c020b03402008450d03200220086a21072008417f6a220621082007417f6a2d0000450d000c020b0b200741206a21060b200641016a22082006490d000240200520046b2008412020084120491b22074f0d00200420076a22072004490d1220054101742206200720072006491b22074100480d120240024020050d0020071027210a0c010b200a200520071028210a0b200a450d04200721050b200a20046a2106410021070240034020074120460d01200620076a200220076a2d00004101713a00002008200741016a2207470d000b0b200420076a21040b200210292009200b470d000b0b02402012450d00201010290b0240200f200d6b2004490d00200d20046a21020c030b200d20046a2202200d490d0e200f4101742207200220022007491b22074100480d0e02400240200f0d0020071027210e0c010b200e200f20071028210e0b0240200e450d002007210f0c030b20074101102a000b20074101102a000b20054101102a000b200e200d6a200a200410ce041a02402005450d00200a10290b201320142903003703002015201629030037030020172018290300370300200320032903d8033703e8022003201141016a221136028803200341d8026a200341e8026a10b8012002210d20032802e00222050d000b0b024020032802dc02450d0020032802d80210290b200341e8026a41086a22074200370300200342003703e80241d8c3c0004112200341e8026a1004200341d8026a41086a2007290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a100521070240024020032802e8022206417f460d002007450d00200320063602ac02200320073602a802200341e8026a200341a8026a102d20032802e802220a450d03200341f0026a280200210820032802ec02210b2006450d01200710290c010b4101210a410021084100210b0b02400240200841ffffff3f7122072002200220074b1b2208450d004100210720034180036a2106200341f8026a2109200341f0026a2104200a210203400240200e20076a2d0000450d00200642003703002009420037030020044200370300200342003703e802200341e8026a2002460d002002200341e8026a412010d004450d00200341e8026a200210b6014101210520032802e8024101470d0020032802ec02200c4d0d030b200241206a2102200741016a22072008490d000b0b410021050b0240200b450d00200a10290b0240200f450d00200e10290b200341b8026a200341d8036a20051b22072021202020051b10cd01200342f0f2bda9c6add9b1f4003703a002200341f0006a41888dc300410d10940120032003290378420020032802701b3703a802200341e8026a200710930120032802ec02210820032802e802210220032802f0022106200341fc026a200341a0026a36020020032002200641286c6a3602f402200320023602f002200320083602ec02200320023602e8022003200341a8026a3602f802200341d8026a200341e8026a104a200341e8026a41086a200341d8026a41086a280200360200200320032903d8023703e8022007200341e8026a10a701024002402005450d00411810272202450d04200241106a41002900cf8c40370000200241086a41002900c78c40370000200241002900bf8c4037000020024118413810282202450d05200220032903b802370018200241306a200341d0026a290300370000200241286a200341b8026a41106a290300370000200241206a200341b8026a41086a290300370000200341186a20024138108401200341186a41106a290300211e2003290320211d20032802182107200210294200211c200341b8026a201d420020071b221d201d428080e983b1de16201d428080e983b1de16544100201e420020071b222a501b22021b221e7d202a202a420020021b222b7d201d201e54ad7d109c01200341e8026a41086a22024200370300200342003703e80241b18ac0004116200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d802200341003602e802200341d8026a4110200341e8026a100521070240024020032802e8022202417f470d004200211d0c010b200342003703f002200342003703e802200341e8026a20072002411020024110491b10ce041a2002410f4d0d07200341f0026a290300211d20032903e802211c200710290b200341e8026a41086a22024200370300200342003703e80241b18ac0004116200341e8026a1004200341d8026a41086a2002290300370300200320032903e8023703d80220034200201d202b7d201c201e54ad7d222a201c201e7d221e201c56202a201d56202a201d511b22021b3703f00220034200201e20021b3703e802200341d8026a4110200341e8026a41101003200341013a00ec02200341083a00e802200341e8026a4105722102200341e8026a21080c010b200341e0006a200341b8026a109501024002402003290360200341e0006a41086a29030084500d00411810272202450d08200241106a41002900cf8c40370000200241086a41002900c78c40370000200241002900bf8c4037000020024118413810282202450d09200220032903d803370018200241306a200341f0036a290300370000200241286a200341d8036a41106a290300370000200241206a200341d8036a41086a290300370000200341c8006a20024138108401200341c8006a41106a290300211d2003290350211c2003280248210720021029411410272202450d0a200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c40370000200241144134102822020d0141344101102a000b419d88c0002107412221080c0d0b200220032903b8023700142002412c6a200341b8026a41186a290300370000200241246a200341b8026a41106a2903003700002002411c6a200341b8026a41086a290300370000200341306a20024134108401200341306a41106a290300212a2003290338211e2003280230210820021029200341b8026a201e420020081b222b201c420020071b221c428080e983b1de16201c428080e983b1de16544100201d420020071b221d501b22021b221e7c222c202a420020081b201d420020021b222a7c202c202b54ad7c108901200341d8036a201c201e7d201d202a7d201c201e54ad7d109c01200341f5026a200341d8036a41086a290300370000200341fd026a200341d8036a41106a29030037000020034185036a200341d8036a41186a290300370000200341003a00ec02200341083a00e802200320032903d8033700ed022003418d036a2102200341e8026a21080b200220032903b802370000200241186a200341b8026a41186a290300370000200241106a200341b8026a41106a290300370000200241086a200341b8026a41086a2903003700004100210741b8d6c50041002008108801410121060b410121090c0c0b418f89c3004133104e000b41184101102a000b41384101102a000b418f89c3004133104e000b41184101102a000b41384101102a000b41144101102a000b1039000b102b000b4184efc2002107411521080b41012106410121090c010b41012109410021062004450d00200510290b02402001280200417f6a220241014b0d000240024020020e020001000b2009450d01200141086a280200450d01200128020410290c010b2006450d00200141086a280200450d00200128020410290b2000200836020420002007360200200341d0046a24000b110020012000280200200028020410e9030bae2505077f047e037f027e067f23004180026b22052400200541e0016a41086a22064200370300200542003703e00141d8c3c0004112200541e0016a1004200541f8006a41086a2006290300370300200520052903e00137037820054100360248200541f8006a4110200541c8006a1005210602400240024002400240024002400240024002400240024002400240024002400240024002400240024020052802482207417f460d002006450d00200520073602e401200520063602e001200541c8006a200541e0016a102d20052802482208450d02200541d0006a2802002109200528024c210a2007450d01200610290c010b41012108410021094100210a0b200541e0016a41086a22074200370300200542003703e0014114210641e0c2c0004114200541e0016a1004200541f8006a41086a2007290300370300200520052903e0013703780240200541f8006a411041b8d6c50041004100100b417f460d0041bf9fc1002107412e21060c120b200541c0006a41a8c1c500411110b50141ed9fc10021072005280244410020052802401b2003470d11024020090d004181a0c100210741c10021060c120b02402009200241086a280200220b4f0d0041c2a0c1002107413c21060c120b200541306a2001109501200541306a41086a290300210c2005290330210d200541c8006a200110b9010240024020052903484201510d00411410272207450d03200741106a41002800bb8c40360000200741086a41002900b38c40370000200741002900ab8c403700004134210620074114413410282207450d04200720012900003700142007412c6a200141186a290000370000200741246a200141106a2900003700002007411c6a200141086a290000370000200541186a20074134108401200541186a41106a290300210e200528021821092005290320210f2007102941a2a1c1002107200f428180e983b1de16544100200e501b0d132009450d13200541e0016a2004410676220910bc0141002106024020052802e8012004413f7122074d0d004101410220052802e001200741216c6a2d00001b21060b024020052802e401450d0020052802e00110290b20064102490d01200541f8006a200910bc01200541e0016a41186a2204200141186a290000370300200541e0016a41106a2210200141106a290000370300200541e0016a41086a2211200141086a290000370300200520012900003703e001200528028001220620074d0d0520052802782212200741216c6a220641013a0000200620052903e001370001200641096a2011290300370000200641116a2010290300370000200641196a2004290300370000410e10272206450d06200641066a41002900dac440370000200641002900d4c4403700002006410e411c10282206450d072006200936000e200541e0016a41186a22074200370300200541e0016a41106a22094200370300200541e0016a41086a22044200370300200542003703e00120064112200541e0016a1000200541c0016a41186a2007290300370300200541c0016a41106a2009290300370300200541c0016a41086a2004290300370300200520052903e0013703c001200541203602e4012005200541c0016a3602e001200541f8006a200541e0016a103520061029200528027c450d0d201210290c0d0b200541d8006a290300210f2005290350210e200541c0016a200441067610bc01410021092004413f71220620052802c8014f0d0e20052802c001200641216c6a22072d00004101470d0e200541b2016a200741036a2d00003a000020054198016a41086a200741146a290000370300200541a5016a200741196a290000370000200520072f00013b01b00120052007410c6a29000037039801200741086a2800002106200741046a2800002107410121090c0f0b200541106a41b9c1c500411410b50120054198016a2005280214410020052802101b220910bc010240024020052802a00122060d00200541e0016a2001428080d287e2bc2d4200410810900120052802e0014101470d0120052802e801210620052802e4012107200528029c01450d1320052802980110290c130b200541c0016a41186a200141186a290000370300200541c0016a41106a200141106a290000370300200541c0016a41086a200141086a290000370300200520012900003703c001200541c0016a2107200d210e200641c000460d0b0c0a0b200541e0016a41106a290300211320052903e8012114200541e0016a41086a22074200370300200542003703e00141b18ac0004116200541e0016a1004200541f8006a41086a2007290300370300200520052903e001370378200541003602e001200541f8006a4110200541e0016a1005210720052802e0012204417f460d072007450d07200542003703e801200542003703e001200541e0016a20072004411020044110491b10ce041a2004410f4d0d06200541e8016a290300210f20052903e001210e200710290c080b418f89c3004133104e000b41144101102a000b41344101102a000b41c8c3c000200720061037000b410e4101102a000b411c4101102a000b418f89c3004133104e000b4200210e4200210f0b200541e0016a41086a22074200370300200542003703e00141b18ac0004116200541e0016a1004200541f8006a41086a2007290300370300200520052903e00137037820054200200f20137d200e201454ad7d2213200e20147d2214200e562013200f562013200f511b22071b3703e80120054200201420071b3703e001200541f8006a4110200541e0016a41101003200541c0016a41186a200141186a290000370300200541c0016a41106a200141106a290000370300200541c0016a41086a200141086a290000370300200520012900003703c001200c200d428080aef89dc3527c220e200d54ad7c427f7c210c200541c0016a21070b200541e0016a41186a200741186a290000370300200541e0016a41106a200741106a290000370300200541e0016a41086a200741086a290000370300200520072900003703e00102400240200528029c012006460d0020052802980121070c010b200641016a22072006490d0720064101742204200720072004491b2204ad42217e220d422088a70d07200da722104100480d070240024020060d002010102721070c010b200528029801200641216c2010102821070b2007450d032005200436029c0120052007360298010b2007200641216c6a220741013a0000200720052903e001370001200741096a200541e0016a41086a2204290300370000200741116a200541e0016a41106a290300370000200741196a200541f8016a2903003700002005200641016a3602a00102402006413f470d0020044200370300200542003703e00141b9c1c5004114200541e0016a1004200541f8006a41086a2004290300370300200520052903e0013703782005200941016a3602e001200541f8006a4110200541e0016a410410030b200e210d0b200541e0016a41086a20054198016a41086a28020036020020052005290398013703e0012009200541e0016a10ce010b4200210e200541086a2001428080e983b1de16420010ac01024020052802082207450d00200528020c21060c060b200541cdc1c500411210b5012005280200210620052802042107200541e0016a41086a22094200370300200542003703e00141cdc1c5004112200541e0016a1004200541f8006a41086a2009290300370300200520052903e0013703782005200741016a410120061b3602e001200541f8006a4110200541e0016a410410034200210f0c030b20104101102a000b0b024020052802c401450d0020052802c00110290b0240024020090d00410121094113210641fea0c10021070c010b20054194016a41026a200541b0016a41026a2d00003a0000200541c0016a41086a20054198016a41086a290300370300200541c0016a410d6a20054198016a410d6a290000370000200520052f01b0013b01940120052005290398013703c001410021090b20054190016a41026a220420054194016a41026a2d00003a0000200541f8006a41086a2210200541c0016a41086a290300370300200541f8006a41106a200541c0016a41106a290300370300200520052f0194013b019001200520052903c00137037820090d02200541f3016a2010290300370000200541f8016a20054185016a290000370000200520052f0190013b01e001200520063600e701200520073600e301200520052903783700eb01200520042d00003a00e201200541e0016a2001460d00200541e0016a2001412010d004450d004191a1c1002107411121060c020b200542f0f2bda9c6add9b1f4003703b801200541b8016a2001200d200c427f410e10a801200541e0006a200c3703002005200d3703582005200f3703502005200e3703482005200336026c20052003360268024002400240411310272206450d002006410f6a41002800f9c340360000200641086a41002900f2c340370000200641002900eac340370000024020064113413310282206450d00200620012900003700132006412b6a200141186a290000370000200641236a200141106a2900003700002006411b6a200141086a290000370000200541e0016a41186a22074200370300200541e0016a41106a22034200370300200541e0016a41086a22094200370300200542003703e00120064133200541e0016a1000200541c0016a41186a2007290300370300200541c0016a41106a2003290300370300200541c0016a41086a2009290300370300200520052903e0013703c001200541203602e4012005200541c0016a3602e001200541c8006a200541e0016a10b301200610292002280204211020022802002103024002400240200b41057622150d0041042116410421170c010b2015410274220610272216450d01201621170b200b450d030240024020150d00410410272216450d0141012115201621170b20174100360200200b417f6a210941012118410021024100210602400340024002400240024002400240024002400240201820024d0d00201720024102746a22072007280200200320066a2d00002006411f71746a360200024020092006460d00200641016a2206411f710d0920152018470d08201541016a22072015490d1220154101742204200720072004491b220741ffffffff03712007470d122007410274220441004e0d070c120b02402010450d00200310290b410021190340200541c8006a41186a2207200141186a290000370300200541c8006a41106a2203200141106a290000370300200541c8006a41086a2209200141086a290000370300200520012900003703482018410820184108491b2202410274221110272206450d0220062017201110ce042112411310272206450d032006410f6a41002800d0c440360000200641086a41002900c9c440370000200641002900c1c44037000020064113413310282206450d04200620052903483700132006412b6a2007290300370000200641236a20032903003700002006411b6a20092903003700002006413341e6001028221a450d05201820026b2118201720116a2117201a2019360033200541e0016a41186a22064200370300200541e0016a41106a22074200370300200541e0016a41086a22034200370300200542003703e001201a4137200541e0016a1000200541c0016a41186a2006290300370300200541c0016a41106a2007290300370300200541c0016a41086a2003290300370300200520052903e0013703c00141002106200541003602e801200542013703e00120052002360278200541f8006a200541e0016a1030410020052802e80122046b210720052802e40121090340200420066a2103201220066a280200210b02400240200920076a4104490d0020052802e00121020c010b200341046a22022003490d1420094101742210200220022010491b22104100480d140240024020090d002010102721020c010b20052802e00120092010102821020b2002450d08200520103602e401200520023602e001201021090b2005200341046a3602e801200220046a20066a200b3600002007417c6a21072011200641046a2206470d000b200541c0016a41202002200420066a100302402009450d00200210290b201a102920121029201941016a211920180d000b2015450d10201610290c100b41c8c3c000200220181037000b20114104102a000b41134101102a000b41334101102a000b41e6004101102a000b20104101102a000b0240024020150d002004102721160c010b201620154102742004102821160b2016450d0320162117200721150b201720184102746a4100360200200241016a2102201841016a21180b200b20064b0d000b41f4c2c0002006200b1037000b20044104102a000b41044104102a000b20064104102a000b41334101102a000b41134101102a000b2010450d00200310290b410021070240200a450d00200810290b0c020b102b000b0240200a450d00200810290b200241046a280200450d00200228020010290b200020063602042000200736020020054180026a24000bed0202047f017e230041d0006b22022400024002400240410f10272203450d00200341076a41002900f3ec42370000200341002900ecec423700002003410f411e10282203450d012003200136000f200241306a41186a22014200370300200241306a41106a22044200370300200241306a41086a220542003703002002420037033020034113200241306a1000200241086a41186a2001290300370300200241086a41106a2004290300370300200241086a41086a20052903003703002002200229033037030820024100360230200241086a4120200241306a100521040240024020022802302201417f460d002002200136022c20022004360228200241306a200241286a102d20022802302205450d042002290234210602402001450d00200410290b20002006370204200020053602000c010b20004100360208200042013702000b20031029200241d0006a24000f0b410f4101102a000b411e4101102a000b418f89c3004133104e000bee08010c7f23004190016b22022400200241086a2001410676220310bc01024002400240024002400240200228021022042001413f7122014d0d002002280208200141216c6a220141003a000020012002290028370001200141096a200241286a41086a2204290000370000200141116a200241286a41106a2205290000370000200141196a200241286a41186a22062900003700002004200241086a41086a280200360200200220022903083703282003200241286a10ce01200241cdc1c500411210b5012002280200210120022802042103200442003703002002420037032841cdc1c5004112200241286a1004200241f0006a41086a220720042903003703002002200229032837037020022003417f6a417f20011b360228200241f0006a4110200241286a410410032006200041186a22082900003703002005200041106a22092900003703002004200041086a220a2900003703002002410036024820022000290000370328200241186a200241286a10b80102402002280220450d00410021030340200241d0006a41186a220b2008290000370300200241d0006a41106a220c2009290000370300200241d0006a41086a220d200a29000037030020022000290000370350411310272201450d032001410f6a41002800d0c440360000200141086a41002900c9c440370000200141002900c1c44037000020014113413310282201450d04200120022903503700132001412b6a200b290300370000200141236a200c2903003700002001411b6a200d2903003700002001413341e60010282201450d05200120033600332006420037030020054200370300200442003703002002420037032820014137200241286a1000200241f0006a41186a2006290300370300200241f0006a41106a20052903003703002007200429030037030020022002290328370370200241f0006a4120100c20011029200341016a21030240200228021c450d00200228021810290b20062008290000370300200520092900003703002004200a2900003703002002200336024820022000290000370328200241186a200241286a10b80120022802200d000b0b0240200228021c450d00200228021810290b411310272201450d042001410f6a41002800f9c340360000200141086a41002900f2c340370000200141002900eac34037000020014113413310282201450d05200120002900003700132001412b6a200041186a290000370000200141236a200041106a2900003700002001411b6a200041086a290000370000200241286a41186a22034200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820014133200241286a1000200241f0006a41186a2003290300370300200241f0006a41106a2004290300370300200241f0006a41086a200529030037030020022002290328370370200241f0006a4120100c2001102920024190016a24000f0b41c8c3c000200120041037000b41134101102a000b41334101102a000b41e6004101102a000b41134101102a000b41334101102a000b830201047f230041c0006b2202240002400240410e10272203450d00200341066a41002900dac440370000200341002900d4c4403700002003410e411c10282203450d012003200036000e200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034112200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a20052903003703002002200229032037030020024120360224200220023602202001200241206a1035200310290240200141046a280200450d00200128020010290b200241c0006a24000f0b410e4101102a000b411c4101102a000be80102027f027e230041206b2203240002400240411410272204450d00200441106a41002800bb8c40360000200441086a41002900b38c40370000200441002900ab8c4037000020044114413410282204450d01200420022900003700142004412c6a200241186a290000370000200441246a200241106a2900003700002004411c6a200241086a290000370000200341086a20044134108401200341086a41106a290300210520032903102106200328020821022004102920002005420020021b37030820002006420020021b370300200341206a24000f0b41144101102a000b41344101102a000bef0101057f230041c0006b220524000240024020030d00200041003602000c010b2003280208210620032802002103200541206a41186a22074200370300200541206a41106a22084200370300200541206a41086a220942003703002005420037032020044120200541206a1000200541186a2007290300370300200541106a2008290300370300200541086a200929030037030020052005290320370300200541003602202003200620054120200541206a10012104024020052802202203417f460d002000200336020420002004360200200041086a20033602000c010b200041003602000b200541c0006a24000bfd0101057f23004190016b22032400200341086a2002108c010240024020032d000822024102470d00200041003a00000c010b200341f0006a200341c8006a290300370300200341f8006a2204200341d0006a29030037030020034180016a2205200341d8006a29030037030020034188016a2206200341e0006a2903003703002003200341c0006a29030037036802402002450d00200041003a00000c010b2003413c6a2802002102200341386a280200210720002003290370370001200041013a0000200041196a2006290300370000200041116a2005290300370000200041096a20042903003700002002450d00200710290b20034190016a24000baf0201047f230041c0006b2202240002400240411710272203450d002003410f6a41002900af9342370000200341086a41002900a89342370000200341002900a0934237000020034117413710282203450d01200320012900003700172003412f6a200141186a290000370000200341276a200141106a2900003700002003411f6a200141086a290000370000200241206a41186a22014200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034137200241206a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002002412041b8d6c50041004100100b210120031029200241c0006a24002001417f470f0b41174101102a000b41374101102a000b840102017f037e230041e0006b2203240020032002108c010240024020032d000022024102470d00420021040c010b2002410173ad2104200341106a2903002105200341086a290300210620020d00200341346a280200450d00200341306a28020010290b2000200637030820002004370300200041106a2005370300200341e0006a24000be6230a057f047e0c7f067e057f027e047f037e017f037e230041f0046b22022400200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b200241e4006a20042f0106360200200241c8006a41186a4100360200200241dc006a2004360200200220033602682002410036025842002107200242003703502002200136024c20024100360248200241b0016a200241c8006a10d5010240024020022903d00122084202520d00420021094200210a0c010b200241b0016a41c0006a210b200241b0016a41386a210c200241b0016a410472210d2002418d026a210e200241b0016a41086a210320024190036a41386a210f200241e0016a2110200241f8016a211141808bc20041f88ac2006b200241e8036a6b200241e8036a41206a6a410f6a211242002107420021094200210a034020024190016a41186a2205200241b0016a41186a220129030037030020024190016a41106a2206200241b0016a41106a220429030037030020024190016a41086a22132003290300370300200241f0006a41086a2214200e41086a290000370300200241f0006a41106a2215200e41106a290000370300200241f0006a41186a2216200e41186a290000370300200220022903b001370390012002200e290000370370201029030021172011290300211820022903d801211920022903f001211a20022903e801211b200229038002211c200228028802211d20022d008c02211e200241b0026a41186a221f2005290300370300200241b0026a41106a22202006290300370300200241b0026a41086a2206201329030037030020022002290390013703b002200241d0026a41186a22052016290300370300200241d0026a41106a22132015290300370300200241d0026a41086a22152014290300370300200220022903703703d002024002400240024002400240024002400240024020084201520d00200241b0016a200241b0026a2019201710850120022d00c8012114200241306a200a2007200920022903b00120022903b8012004290300105e200241306a41106a2903002109200229033821072002290330210a20140d010b02400240024002400240201d0d00201b4201510d00201e41ff01714101470d010b200241b0016a200241b0026a108c010240024020022d00b0012214417f6a221641014b0d00024020160e020002000b20140d0620022802e401450d0620022802e00110290c060b200241f0026a41086a2214200b41086a290300370300200241f0026a41106a2216200b41106a290300370300200241f0026a41186a2221200b41186a2903003703002002200b2903003703f0022004290300212220022903b801212320022802ec01212420022802e801212520022802e401212620022802e001212720022903d801212820022903c801212920022903d00122174202510d042025417f4c0d020240024020250d00410121060c010b202510272206450d0420062027202510ce041a0b200f20022903f002370300200f41086a2014290300370300200f41106a2016290300370300200f41186a20212903003703002002202337039003200220243602c403200220253602c003200220253602bc03200220063602b803200220283703b003200220293703a003200220223703980320022017420151ad222a3703a8032025212b2025211f2029212c2023212d2022212e202421140c070b024020140d0020022802e401450d0020022802e00110290b420221170c030b201ca7210402400240201c422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b200241003602d001200241003602c801200241003602c001200242003703b801200220013602b401200241003602b001200220043602c401200220042f01063602cc01200241b0016a10d6010c0b0b1039000b20254101102a000b201e41ff01710d010b201ca7210402400240201c422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b2002201d3602d001200241003602c801200241003602c001200242003703b801200220013602b401200241003602b001200220043602c401200220042f01063602cc01200241b0016a10d6010c070b200241206a419188c5004117109401200228022021142002290328210820034200370300200242003703b001419188c5004117200241b0016a1004200241e8036a41086a22162003290300370300200220022903b0013703e8032002200842017c420120141b22083703b001200241e8036a4110200241b0016a41081003412010272214450d03201420022903b002370000201441186a201f290300370000201441106a2020290300370000201441086a20062903003700002014412041c00010282214450d0220142008370020200142003703002004420037030020034200370300200242003703b00120144128200241b0016a1000200241e8036a41186a2001290300370300200241e8036a41106a200429030037030020162003290300370300200220022903b0013703e803413710272206450d01200642bac6a1cbc68dd9aff300370000200642f4dec98bf6ac999de400370008200641e5cc85ab073600102006413a3a0016200641ece8013b0014200620022903e803370017200620022f01f0033b001f200620022801f203360021200620022f01f6033b0025200620022d00f8033a0027200620022d00f9033a0028200620022d00fa033a0029200620022d00fb033a002a200620022d00fc033a002b200620022d00fd033a002c200620022d00fe033a002d200620022d00ff033a002e200620022d0080043a002f200620022d0081043a0030200620022d0082043a0031200620022d0083043a0032200620022d0084043a0033200620022d0085043a0034200620022d0086043a0035200620022d0087043a003620141029200241106a41888dc300410d1094012002290318210820022802102116200f20022903d00237000041082114200f41086a200241d0026a41086a290300370000200f41106a2013290300370000200f41186a2005290300370000427f212d2002427f370398032002427f37039003200241083602c403200220123602c0034137212b200241373602bc03200220063602b8034200212a200242003703a80320022008420020161b222c3703a0032012211f427f212e0b0240201b4201520d002002201a370390032002201837039803201a212d2018212e0b0240201e41ff0171450d00200f20022903d002370000200f41186a2005290300370000200f41106a2013290300370000200f41086a20152903003700000b0240201d450d00200241888dc300410d1094014201212a200242013703a80320022002290308420020022802001b3703b0030b201ca7210502400240201c422088a722150d00200521130c010b2015211620052113034020132802ec0321132016417f6a22160d000b0340200520052f01064102746a41ec036a28020021052015417f6a22150d000b0b20052f010621152002201d3602880420022015360284042002410036028004200220053602fc03200241003602f803200242003703f003200220133602ec03200241003602e803200241b0016a200241e8036a10d70120022802b0014101470d04034020024190046a41186a200d41186a290200221c37030020024190046a41106a200d41106a290200220837030020024190046a41086a200d41086a290200221b3703002002200d29020022193703900420022802d401210520022802d801212020022802dc012113200241b0046a41186a201c370300200241b0046a41106a2008370300200241b0046a41086a201b370300200220193703b004200142003703002004420037030020034200370300200242003703b001200241b0046a4120200241b0016a1000200241d0046a41186a22162001290300370300200241d0046a41106a221d2004290300370300200241d0046a41086a221e2003290300370300200220022903b0013703d004200241003602b0012006201f200241d0046a4120200241b0016a10012121024020022802b0012215417f460d00201420156b21142015450d00202110290b024002402005450d00200142003703002004420037030020034200370300200242003703b001200241b0046a4120200241b0016a100020162001290300370300201d2004290300370300201e2003290300370300200220022903b0013703d0042006201f200241d0046a4120200520131011201420136a21142020450d01200510290c010b200142003703002004420037030020034200370300200242003703b001200241b0046a4120200241b0016a100020162001290300370300201d2004290300370300201e2003290300370300200220022903b0013703d0042006201f200241d0046a412010020b200241b0016a200241e8036a10d70120022802b0014101470d040c000b0b41374101102a000b41c0004101102a000b41204101102a000b200220143602c4030b200241e8036a10d601200241e8036a41186a2204200241f0026a41186a290300370300200241e8036a41106a2201200241f0026a41106a290300370300200241e8036a41086a2205200241f0026a41086a290300370300200220022903f0023703e8030240024020174202510d00200c20022903e803370300200c41086a2005290300370300200c41106a2001290300370300200c41186a2004290300370300200220233703b001200220243602e401200220263602dc01200220273602d801200220283703d001200220173703c801200220293703c001200220223703b801200220253602e0014101210402402025201f470d000240024020272006460d0020272006202510d0040d0220242014470d020c010b20242014470d010b200c200f412010d0040d002023202d852022202e85844200520d002029202c520d002017a72201202aa7470d002001410146202820022903b003527121040b02402026450d00202710290b20044102460d002004450d010b200320024190036a41d80010ce041a200241003a00b001200241b0026a200241b0016a10d8010c010b202b450d00200610290b200241b0016a200241c8006a10d50120022903d00122084202520d000b0b200241c8006a10d90102400240024002400240200a500d004200211c200241b0016a41086a22044200370300200242003703b00141b18ac0004116200241b0016a100420024190036a41086a2004290300370300200220022903b00137039003200241003602b00120024190036a4110200241b0016a100521010240024020022802b0012204417f470d00420021080c010b200242003703b801200242003703b001200241b0016a20012004411020044110491b10ce041a2004410f4d0d02200241b8016a290300210820022903b001211c200110290b200241b0016a41086a22044200370300200242003703b00141b18ac0004116200241b0016a100420024190036a41086a2004290300370300200220022903b0013703900320024200200820097d201c200754ad7d221b201c20077d2219201c56201b200856201b2008511b22041b3703b80120024200201920041b3703b001200241b0016a21040c030b2007200984500d0141eca9c1001058000b418f89c3004133104e000b4200211c200241b0016a41086a22044200370300200242003703b00141b18ac0004116200241b0016a100420024190036a41086a2004290300370300200220022903b00137039003200241003602b00120024190036a4110200241b0016a100521010240024020022802b0012204417f470d00420021080c010b200242003703b801200242003703b001200241b0016a20012004411020044110491b10ce041a2004410f4d0d02200241b8016a290300210820022903b001211c200110290b200241b0016a41086a22044200370300200242003703b00141b18ac0004116200241b0016a100420024190036a41086a2004290300370300200220022903b00137039003200220083703b8012002201c3703b001200241b0016a21040b20024190036a4110200441101003200241f0046a24000f0b418f89c3004133104e000bf90503087f017e017f23004180026b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241186a2206200520034105746a220741206a290000370300200241106a2208200741186a290000370300200241086a2209200741106a2900003703002002200741086a290000370300200241206a2005200341e0006c6a41e8026a41e00010ce041a2001200341016a36020c200120043602082001200536020420024180016a41186a200629030037030020024180016a41106a200829030037030020024180016a41086a2009290300370300200220022903003703800120024180016a41206a200241206a41e00010ce041a200020024180016a41800110ce041a0c020b200042023703200c010b2001280200210702400240200528020022030d002004ad210a410021030c010b200741016a210720053301044220862004ad84210a0b20051029200aa7210402400240200a422088a7220620032f01064f0d00200321050c010b034002400240200328020022050d002004ad210a410021050c010b200741016a210720033301044220862004ad84210a0b20031029200aa7210420052103200a422088a7220620052f01064f0d000b0b200241186a2208200520064105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220b200341106a2900003703002002200341086a290000370300200241206a2005200641e0006c6a41e8026a41e00010ce041a200641027420056a418c0b6a280200210302402007417f6a2205450d00034020032802880b21032005417f6a22050d000b0b2001410036020c20012004360208200120033602042001410036020020024180016a41186a200829030037030020024180016a41106a200929030037030020024180016a41086a200b290300370300200220022903003703800120024180016a41206a200241206a41e00010ce041a200020024180016a41800110ce041a0b20024180026a24000bb00101037f230041306b220124002001200010d701024020012802004101470d000340024020012802242202450d002001280228450d00200210290b2001200010d70120012802004101460d000b0b024020002802042202418883c000460d0020022802002103200210292003450d0020032802002100200310292000450d00024020002802002202450d000340200010292002210020022802002203210220030d000b0b200010290b200141306a24000bdd0605057f047e017f017e047f23004190016b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241e0006a41186a200520034105746a220641206a2900002207370300200241e0006a41106a200641186a2900002208370300200241e0006a41086a200641106a29000022093703002002200641086a290000220a370360200241306a41086a20052003410c6c6a220641f0026a280200220b360200200641e8026a290200210c2001200341016a36020c20012004360208200120053602042002200c3703302000200a3702042000410c6a2009370200200041146a20083702002000411c6a2007370200200041246a200c3702002000412c6a200b360200200041013602000c020b200041003602000c010b2001280200210602400240200528020022030d002004ad210c410021030c010b200641016a210620053301044220862004ad84210c0b20051029200ca7210402400240200c422088a7220b20032f01064f0d00200321050c010b034002400240200328020022050d002004ad210c410021050c010b200641016a210620033301044220862004ad84210c0b20031029200ca7210420052103200c422088a7220b20052f01064f0d000b0b200241306a41186a220d2005200b4105746a220341206a290000370300200241306a41106a220e200341186a290000370300200241306a41086a220f200341106a2900003703002002200341086a290000370330200241d0006a41086a22102005200b410c6c6a220341f0026a2802003602002002200341e8026a290200370350200b41027420056a41f0036a280200210302402006417f6a2205450d00034020032802ec0321032005417f6a22050d000b0b2001410036020c200120043602082001200336020420014100360200200241e0006a41186a200d290300220c370300200241e0006a41106a200e2903002207370300200241e0006a41086a200f290300220837030020024188016a201028020022033602002000200229033022093702042000410c6a2008370200200041146a20073702002000411c6a200c370200200041246a2002290350220c3702002000412c6a2003360200200220093703602002200c37038001200041013602000b20024190016a24000bd00201047f230041c0006b2202240002400240411710272203450d002003410f6a41002900af9342370000200341086a41002900a89342370000200341002900a0934237000020034117413710282203450d01200320002900003700172003412f6a200041186a290000370000200341276a200041106a2900003700002003411f6a200041086a290000370000200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034137200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a20052903003703002002200229032037030020024120360224200220023602202001200241206a10dc0220031029024020012d00000d00200141346a280200450d00200141306a28020010290b200241c0006a24000f0b41174101102a000b41374101102a000bca0201067f230041b0016b22012400200141086a200010d501024020012903284202510d000340200128026021022001280258210302400240200128025c22040d00200321050c010b2004210620032105034020052802ec0321052006417f6a22060d000b0340200320032f01064102746a41ec036a28020021032004417f6a22040d000b0b200120023602a801200141003602a001200141003602980120014200370390012001200536028c0120014100360288012001200336029c01200120032f01063602a40120014188016a10d601200141086a200010d50120012903284202520d000b0b024020002802042203418883c000460d0020032802002104200310292004450d0020042802002105200410292005450d00024020052802002203450d000340200510292003210520032802002204210320040d000b0b200510290b200141b0016a24000b821e04027f027e097f027e230041c00d6b220824000240024002402001280234200128025022092802b801460d00200442002004290308220a200941c0006a2903007d220b200b200a5622091b3703082009450d01200041013a0000200041086a412a360200200041046a419cb5c3003602000c020b200041013a0000200041086a4124360200200041046a41d3b4c3003602000c010b200841106a41186a200141f4006a290000370300200841106a41106a200141ec006a290000370300200841106a41086a200141e4006a2900003703002008200129005c370310200841c0026a41186a22094200370300200841c0026a41106a220c4200370300200841c0026a41086a220d4200370300200842003703c00220062007200841c0026a1000200841e00a6a41186a2009290300370300200841e00a6a41106a200c290300370300200841e00a6a41086a200d290300370300200820082903c0023703e00a024002400240024002400240024002400240412010272209450d0020092005290000370000200941186a200541186a290000370000200941106a200541106a290000370000200941086a200541086a2900003700002009412041c00010282209450d01200920082903e00a370020200941386a200841e00a6a41186a290300370000200941306a200841e00a6a41106a290300370000200941286a200841e00a6a41086a290300370000200941c00041800110282209450d0220092008290310370040200941d8006a200841106a41186a290300370000200941d0006a200841106a41106a290300370000200941c8006a200841106a41086a290300370000200841c0026a41186a220c4200370300200841c0026a41106a220d4200370300200841c0026a41086a220e4200370300200842003703c002200941e000200841c0026a1000200841306a41186a220f200c290300370300200841306a41106a220c200d290300370300200841306a41086a220d200e290300370300200820082903c00237033020091029200841c4016a200d290300370200200841cc016a200c290300370200200841d4016a200f290300370200200841e0006a41c8006a4200370300200841a0016a42808080808001370300200841e0006a41306a41f8b4c3003602002008418c016a2001411c6a221036020020084184016a420037020020084180016a2211418883c000360200200820082903303702bc0120084208370398012008410036027c20084100360270200820012802583602b801200820012903503703b0012008200128023441016a360294012001290300210a200820012903083703682008200a370360200841e0016a41186a200541186a290000370300200841e0016a41106a200541106a290000370300200841e0016a41086a200541086a2900003703002008410136027c200820052900003703e0012010200841306a10e40121092008200828027c417f6a220c36027c024020090d00200c0d042008417f36027c200841a0026a41186a200841306a41186a290300370300200841a0026a41106a200841306a41106a290300370300200841a0026a41086a200841306a41086a290300370300200820082903303703a00202400240200828028001220f418883c000460d0020082802840121120c010b41002112200841e00a6a410041e00210cd041a200841c0026a410041a00810cd041a41880b1027220f450d06200f41003b0106200f4100360200200f41086a200841e00a6a41e00210ce041a200f41e8026a200841c0026a41a00810ce041a20084100360284012008200f360280010b200841e0006a411c6a2113024002400340200f41086a210c200f2f0106221441057421094100210d024003402009450d01200841a0026a200c412010d004220e450d03200941606a2109200d41016a210d200c41206a210c200e417f4a0d000b200d417f6a21140b02402012450d002012417f6a2112200f20144102746a41880b6a280200210f0c010b0b20084180026a41186a200841a0026a41186a290300220a37030020084180026a41106a200841a0026a41106a290300220b37030020084180026a41086a200841a0026a41086a2903002215370300200820082903a002221637038002200841fc0a6a2015370200200841840b6a200b3702002008418c0b6a200a370200200820084188016a3602f00a200820143602ec0a200820113602e80a2008200f3602e40a200841003602e00a200820163702f40a200841f4026a4200370200200841003a00fc02200842003703c0022008418883c0003602f002200842003703d802200841e00a6a200841c0026a10de0121090c010b200f200d41e0006c6a41e8026a21090b200841f8016a290300210a20094201370318200941013a003c200941286a427f370300200941206a427f3703002009413d6a20082903e001370000200941d5006a200a370000200941cd006a200841f0016a290300370000200941c5006a200841e8016a2903003700002008200828027c41016a36027c200841086a20044101200841106a200841306a20022003200841e0006a10a20302402008280208220f450d00200828020c21010c0a0b200841c0026a200520082802b801280200108402024020082802c0024101470d00200841c8026a280200210120082802c402210f0c0a0b200841a0026a41186a200841c0026a410472220941186a280200220c360200200841e00a6a41106a200941086a290200370300200841e00a6a41186a220d200941106a290200370300200841800b6a200c360200200841063602e40a200841bd8fc5003602e00a200820092902003703e80a20082802b40121092008200841e0006a3602e0022008290360210a2008290368210b200841ec026a200841106a41086a290300370200200841f4026a200841106a41106a290300370200200841fc026a200841106a41186a290300370200200820033703c802200820023703c0022008200b3703d8022008200a3703d002200820082903103702e40220084100360288022008420137038002200841a0026a2009200841e00a6a200841c0026a2006200720084180026a2004106220082802a0020e03070608070b41f7a5c100210f412a21010c080b41204101102a000b41c0004101102a000b4180014101102a000b41c8a8c1004110200841c0026a41f0a8c10010a201000b41880b4108102a000b200841a0026a41086a280200450d0020082802a40210290b200841c0026a41086a200841106a41086a290300370300200841c0026a41106a200841106a41106a290300370300200841c0026a41186a200841106a41186a290300370300200841a0026a41086a200841306a41086a290300370300200841a0026a41106a200841306a41106a290300370300200841a0026a41186a200841306a41186a290300370300200820082903103703c002200820082903303703a0020240024020082802a0012209200828029c01460d00200828029801210c0c010b02400240200941016a220c2009490d002009410174220d200c200c200d491b220dad42e8007e2202422088a70d002002a7220e4100480d000240024020090d00200e1027210c0c010b200828029801200941e8006c200e1028210c0b200c450d012008200d36029c012008200c3602980120082802a00121090c020b102b000b200e4108102a000b200c200941e8006c6a220941013a0000200920082903c002370001200941096a200841c0026a41086a220c290300370000200941116a200841c0026a41106a290300370000200941196a200841c0026a41186a290300370000200941216a20082903a002370000200941296a200841a0026a41086a290300370000200941316a200841a0026a41106a290300370000200941396a200841a0026a41186a290300370000200941d0006a2008418f026a290000370000200941c9006a20084180026a41086a290000370000200941c1006a200829008002370000200941e0006a410036020020094201370358200820082802a00141016a220d3602a0010240200841e00a6a41186a280200450d00200841f40a6a280200102920082802a001210d0b200c201341086a290200370300200841d0006a41086a200841cc026a280200360200200820132902003703c002200820082902c40237035020082802ac01210e20082802a801210520082802a4012109200828029c012104200828029801210c02402008280270220f450d00200841f4006a280200450d00200f10290b200841e00a6a41086a200841d0006a41086a280200220f3602002008200829035022023703e00a200841c0026a41086a200f360200200820023703c0022010200841c0026a10e6012008200c200d41e8006c6a3602cc022008200c3602c802200820043602c4022008200c3602c002200141386a200841c0026a102c20082009200e41a8016c6a3602cc02200820093602c802200820053602c402200820093602c002200141c4006a200841c0026a1026200041196a200841c8006a290300370000200041116a200841c0006a290300370000200041096a200841306a41086a29030037000020002008290330370001200041003a00000c020b200841a0026a41086a280200210120082802a402210f200d280200450d00200841f40a6a28020010290b024020082802702209450d00200841f4006a280200450d00200910290b2008280288012105200828028001210902400240200828028401220d0d002009210c0c010b200d210e2009210c0340200c2802880b210c200e417f6a220e0d000b0340200920092f01064102746a41880b6a2802002109200d417f6a220d0d000b0b200841dc026a20092f0106360200200841d8026a4100360200200841d4026a2009360200200820053602e002200841003602d002200842003703c8022008200c3602c402200841003602c002200841c0026a10d901024020082802a001220c450d002008280298012109200c41e8006c210c03400240200941dc006a280200450d00200941d8006a28020010290b024020092d00004105490d00200941286a280200450d00200941246a28020010290b200941e8006a2109200c41987f6a220c0d000b0b0240200828029c01450d0020082802980110290b024020082802ac012209450d00200941a8016c210c20082802a40141206a210903402009103d200941a8016a2109200c41d87e6a220c0d000b0b024020082802a801450d0020082802a40110290b200041086a2001360200200041046a200f360200200041013a00000b200841c00d6a24000bff18012e7f230041b00d6b220324002003200236020420032001360200200341086a41086a220142003703002003420037030841e28fc3004115200341086a1004200341900d6a41086a2001290300370300200320032903083703900d200341e80c6a200341900d6a10ba02024002400240024020032802ec0c22040d0041012104410021050c010b20032802f00c2105200341e80c6a410c6a28020022020d010b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20032c00e80c2101200341086a410041e00c10cd041a200441206a21064100210741002108410021094100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f41002120410021214100212241002123410021244100212541002126200420024105746a22272128200421294100212a41d100212b02400340202a212c0240024002402001450d00024020042027460d00200141016a212d20282102202921010340202720022001200246222e1b210220272028202e1b212820042001202e1b222e41206a2101202d417f6a222d0d000c030b0b200141016a2101034020282029460d05202941206a21292001417f6a22010d000b202941606a212e202921010c010b024020292028460d00202941206a21012029212e0c020b20042027460d0320272128200621012004212e0b202e450d020b200121292003280204212d2003280200212f200341003602980d200342013703900d02400240024002400240410110272201450d002001202c3a000020034281808080103702940d200320013602900d2003202d36028c0d2003418c0d6a200341900d6a10300240024020032802940d220220032802980d22306b202d490d0020032802900d21010c010b2030202d6a22012030490d042002410174222a20012001202a491b222a4100480d040240024020020d00202a102721010c010b20032802900d2002202a102821010b2001450d022003202a3602940d200320013602900d202a21020b20032030202d6a222a3602980d200120306a202f202d10ce041a024002402002202a6b4120490d00202a41206a21300c010b202a41206a2230202a490d042002410174222d20302030202d491b222d4100480d040240024020020d00202d102721010c010b20012002202d102821010b2001450d032003202d3602940d200320013602900d202d21020b2001202a6a222d202e290000370000202d41186a202e41186a290000370000202d41106a202e41106a290000370000202d41086a202e41086a290000370000200341900d6a41186a222e4200370300200341900d6a41106a222d4200370300200341900d6a41086a222a4200370300200342003703900d20012030200341900d6a1000200341e80c6a41186a2230202e290300370300200341e80c6a41106a222e202d290300370300200341e80c6a41086a222d202a290300370300200320032903900d3703e80c02402002450d00200110290b202b417f6a212b202c41016a212a200341086a202c4103704105746a220120032903e80c370000200141186a2030290300370000200141106a202e290300370000200141086a202d290300370000410021020340202c202c41036e222e417d6c6a4102470d05200341086a20026a220141df006a2d0000222d2001411f6a2d0000220771202d2007722001413f6a2d00007172211e200141de006a2d0000222d2001411e6a2d0000220771202d2007722001413e6a2d00007172211d200141dd006a2d0000222d2001411d6a2d0000220771202d2007722001413d6a2d00007172211c200141dc006a2d0000222d2001411c6a2d0000220771202d2007722001413c6a2d00007172211b200141db006a2d0000222d2001411b6a2d0000220771202d2007722001413b6a2d00007172211a200141da006a2d0000222d2001411a6a2d0000220771202d2007722001413a6a2d000071722119200141d9006a2d0000222d200141196a2d0000220771202d200772200141396a2d000071722118200141d8006a2d0000222d200141186a2d0000220771202d200772200141386a2d000071722117200141d7006a2d0000222d200141176a2d0000220771202d200772200141376a2d000071722116200141d6006a2d0000222d200141166a2d0000220771202d200772200141366a2d000071722115200141d5006a2d0000222d200141156a2d0000220771202d200772200141356a2d000071722114200141d4006a2d0000222d200141146a2d0000220771202d200772200141346a2d000071722113200141d3006a2d0000222d200141136a2d0000220771202d200772200141336a2d000071722112200141d2006a2d0000222d200141126a2d0000220771202d200772200141326a2d000071722111200141d1006a2d0000222d200141116a2d0000220771202d200772200141316a2d000071722110200141d0006a2d0000222d200141106a2d0000220771202d200772200141306a2d00007172210f200141cf006a2d0000222d2001410f6a2d0000220771202d2007722001412f6a2d00007172210e200141ce006a2d0000222d2001410e6a2d0000220771202d2007722001412e6a2d00007172210d200141cd006a2d0000222d2001410d6a2d0000220771202d2007722001412d6a2d00007172210c200141cc006a2d0000222d2001410c6a2d0000220771202d2007722001412c6a2d00007172210b200141cb006a2d0000222d2001410b6a2d0000220771202d2007722001412b6a2d00007172210a200141ca006a2d0000222d2001410a6a2d0000220771202d2007722001412a6a2d000071722109200141c9006a2d0000222d200141096a2d0000220771202d200772200141296a2d000071722108200141c8006a2d0000222d200141086a2d0000220771202d200772200141286a2d000071722107200141c7006a2d0000222d200141076a2d0000221f71202d201f72200141276a2d00007172211f200141c6006a2d0000222d200141066a2d0000222071202d202072200141266a2d000071722120200141c5006a2d0000222d200141056a2d0000222171202d202172200141256a2d000071722121200141c4006a2d0000222d200141046a2d0000222271202d202272200141246a2d000071722122200141c3006a2d0000222d200141036a2d0000222371202d202372200141236a2d000071722123200141c2006a2d0000222d200141026a2d0000222471202d202472200141226a2d000071722124200141c1006a2d0000222d200141016a2d0000222571202d202572200141216a2d000071722125200141c0006a2d0000222d20012d0000222671202d202672200141206a2d000071722126200241800c460d05200341086a2002202e410574202c41096e41e0006c6b6a6a220141ff006a201e3a0000200141fe006a201d3a0000200141fd006a201c3a0000200141fc006a201b3a0000200141fb006a201a3a0000200141fa006a20193a0000200141f9006a20183a0000200141f8006a20173a0000200141f7006a20163a0000200141f6006a20153a0000200141f5006a20143a0000200141f4006a20133a0000200141f3006a20123a0000200141f2006a20113a0000200141f1006a20103a0000200141f0006a200f3a0000200141ef006a200e3a0000200141ee006a200d3a0000200141ed006a200c3a0000200141ec006a200b3a0000200141eb006a200a3a0000200141ea006a20093a0000200141e9006a20083a0000200141e8006a20073a0000200141e7006a201f3a0000200141e6006a20203a0000200141e5006a20213a0000200141e4006a20223a0000200141e3006a20233a0000200141e2006a20243a0000200141e1006a20253a0000200141e0006a20263a0000202e212c200241e0006a220241e00c470d000c050b0b41014101102a000b202a4101102a000b202d4101102a000b102b000b41002101202b0d000b0b2000201e3a001f2000201d3a001e2000201c3a001d2000201b3a001c2000201a3a001b200020193a001a200020183a0019200020173a0018200020163a0017200020153a0016200020143a0015200020133a0014200020123a0013200020113a0012200020103a00112000200f3a00102000200e3a000f2000200d3a000e2000200c3a000d2000200b3a000c2000200a3a000b200020093a000a200020083a0009200020073a00082000201f3a0007200020203a0006200020213a0005200020223a0004200020233a0003200020243a0002200020253a0001200020263a00000b02402005450d00200410290b200341b00d6a24000b850804057f017e017f017e02400240024002402002450d00410020016b410020014103711b2103200241796a4100200241074b1b210441002105034002400240200120056a2d000022064118744118752207417f4a0d0042808080801021080240200641a6d4c5006a2d0000417e6a220941024d0d0042808080808020210a0c070b0240024002400240024020090e03000102000b200541016a22062002490d024200210a0c090b4200210a200541016a220920024f0d08200120096a2d0000210902400240200641a07e6a2206410d4b0d000240024020060e0e0002020202020202020202020201000b200941e0017141a001460d0242808080808020210a0c0c0b02402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141a001490d0142808080808020210a0c0b0b02402007411f6a41ff0171410b4b0d0002402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141c001490d0142808080808020210a0c0b0b0240200941ff017141bf014d0d0042808080808020210a0c0b0b0240200741fe017141ee01460d0042808080808020210a0c0b0b2009411874411875417f4c0d0042808080808020210a0c0a0b42002108200541026a220620024f0d09200120066a2d000041c00171418001460d020c070b4200210a200541016a220920024f0d07200120096a2d0000210902400240200641907e6a220641044b0d000240024020060e050002020201000b200941f0006a41ff01714130490d0242808080808020210a0c0b0b02402009411874411875417f4c0d0042808080808020210a0c0b0b200941ff0171419001490d0142808080808020210a0c0a0b0240200941ff017141bf014d0d0042808080808020210a0c0a0b02402007410f6a41ff017141024d0d0042808080808020210a0c0a0b2009411874411875417f4c0d0042808080808020210a0c090b200541026a220620024f0d07200120066a2d000041c00171418001470d0642002108200541036a220620024f0d08200120066a2d000041c00171418001460d01428080808080e000210a42808080801021080c080b42808080808020210a4280808080102108200120066a2d000041c00171418001470d070b200641016a21050c010b0240200320056b4103710d000240200520044f0d000340200120056a220641046a280200200628020072418081828478710d01200541086a22052004490d000b0b200520024f0d010340200120056a2c00004100480d022002200541016a2205470d000c040b0b200541016a21050b20052002490d000b0b20002001360204200041086a2002360200200041003602000f0b428080808080c000210a42808080801021080c010b420021080b2000200a2008842005ad84370204200041013602000ba00501097f230041206b22052400024002400240200128020041016a220641004c0d0020012006360200200141086a2802002107200141046a220821060340200628020022092f0106220a410574210b410021064100210c0240024002400340200b2006460d0102402002200920066a41086a412010d004220d0d00410021060c030b200641206a2106200c41016a210c200d417f4a0d000b200c417f6a210a0b20070d014101210641002107200a210c0b200541186a200c360200200541146a2008360200200541086a41086a20093602002005200736020c2005200636020820060d032009200c41e0006c6a2206419c036a280200210720064198036a2208210602400340200628020022092f0106220a410574210b410021064100210c02400240024002400340200b2006460d0102402004200920066a41086a412010d004220d0d00410021060c030b200641206a2106200c41016a210c200d417f4a0d000b200c417f6a210a0b20070d014101210641002107200a210c0b200541186a200c360200200541086a410c6a2008360200200541106a20093602002005200736020c2005200636020820060d0702400240200941e8026a2206200c410c6c6a280200220d0d004100210c0c010b2006200c410c6c6a2802082206417f4c0d02024020060d004101210c0c010b20061027220c450d04200c200d200610ce041a0b200020063602042000200c360200200041086a20063602000c080b2007417f6a21072009200a4102746a41ec036a21060c010b0b1039000b20064101102a000b2007417f6a21072009200a4102746a41880b6a21060c000b0b41d8a8c1004118200541086a4180a9c10010a201000b20002001280210200220032004200141146a28020028020c1106000b20012001280200417f6a360200200541206a24000b8f1901187f230041d0116b2202240020002802102203200328020041016a360200200028020c21042000280208210520002802042103200241206a41186a22062000412c6a290000370300200241206a41106a2207200041246a290000370300200241206a41086a22082000411c6a29000037030020022000290014370320200241a0026a200141e00010ce041a024002400240024020032f01062201410b490d00200241b0036a410041e00210cd041a20024198066a410041a00810cd041a0240024041880b10272209450d00200941003b010620094100360200200941086a200241b0036a41e00210ce042101200941e8026a20024198066a41a00810ce042106200220032f00c8013b01ac032002200341ca016a2d00003a00ae03200220032900db01370398032002200341e0016a29000037009d03200341cb016a280000210a200341cf016a280000210b200341d3016a280000210c200341d7016a280000210d20024198066a200341a8076a41e00010ce041a2001200341e8016a20032f010641796a220041057410ce042101200620034188086a200041e0006c10ce042106200341063b0106200920003b0106200220022f01ac033b019403200220022d00ae033a0096032002200229039803370380032002200229009d0337008503200241b0036a20024198066a41e00010ce041a0240024020044107490d00200441057420016a41c07e6a2001200441796a22074105746a2201200041ffff037120076b41057410cf041a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200441e0006c20066a220041c07b6a200041e07a6a220e200941066a22002f010020076b41e0006c10cf041a200e200241a0026a41e00010ce041a0c010b200341086a20044105746a220141206a2001200341066a22002f010020046b41057410cf041a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200341e8026a200441e0006c6a220e41e0006a200e20002f010020046b41e0006c10cf041a200e200241a0026a41e00010ce041a0b20024188026a41026a220420022d0096033a0000200020002f010041016a3b0100200220022f0194033b01880220022002290380033703800120022002290085033700850120024190016a200241b0036a41e00010ce041a2002411c6a41026a220f20042d00003a0000200220022f0188023b011c2002200229038001370308200220022900850137000d200241206a20024190016a41e00010ce041a20032802002206450d0320032f0104211020024198066a410272211103402002419c026a41026a2212200f2d00003a0000200220022f011c3b019c0220022002290308370388022002200229000d37008d02200241a0026a200241206a41e00010ce041a201041ffff0371210702400240024020062f01062203410b490d002011410041b20b10cd041a41b80b10272201450d0520014100360200200141046a20024198066a41b40b10ce041a200220062f00c8013b01ac032002200641ca016a2d00003a00ae03200220062900db01370398032002200641e0016a29000037009d03200641cb016a2800002113200641cf016a2800002114200641d3016a2800002115200641d7016a280000211620024198066a200641a8076a41e00010ce041a200141086a200641e8016a20062f0106220041796a220341057410ce042117200141e8026a20064188086a200341e0006c10ce042118200141880b6a200641a40b6a2000417a6a220841027410ce042119200641063b0106200120033b010602402008450d00410021032019210003402000280200220420033b010420042001360200200041046a21002008200341016a2203470d000b0b200241b0036a20024198066a41e00010ce041a200220022d00ae0322033a009603200220022f01ac0322003b0194032002200229009d033700850320022002290398033703800320024194066a41026a220820033a0000200220003b01940620022002290380033703800120022002290085033700850120024198066a200241b0036a41e00010ce041a201041ffff037122004107490d0120172007417a6a22044105746a2017200741796a22034105746a220020012f010620036b41057410cf041a200041186a200229008d023700002000200d36000f2000200c36000b2000200b3600072000200a360003200041026a20122d00003a0000200020022f019c023b00002000200229038802370013200741e0006c20186a220041c07b6a200041e07a6a220020012f010620036b41e0006c10cf041a2000200241a0026a41e00010ce041a200120012f010641016a22003b01062007410274220a20196a416c6a201920044102746a2210200041ffff0371220720046b41027410cf041a2010200936020020072004490d022001200a6a41f00a6a2100034020002802002204200341016a22033b010420042001360200200041046a210020032007490d000c030b0b200641086a2200200741016a22044105746a200020074105746a2200200320076b220141057410cf041a2000200d36000f2000200c36000b2000200b3600072000200a360003200041026a2002419c026a41026a2d00003a0000200020022f019c023b00002000200229038802370013200041186a200229008d023700002006200741e0006c6a220041c8036a200041e8026a2200200141e0006c10cf041a2000200241a0026a41e00010ce041a2006200341016a22033b01062007410274200641880b6a22006a41086a200020044102746a2200200341ffff037120046b41027410cf041a20002009360200201041ffff037120062f010622034f0d07200920043b010420092006360200200420034f0d072003417f6a210120062004417f6a22034102746a41900b6a2100034020002802002204200341026a3b010420042006360200200041046a21002001200341016a2203470d000c080b0b200641086a2203200741016a22044105746a200320074105746a220320062f0106221020076b221941057410cf041a2003200d36000f2003200c36000b2003200b3600072003200a360003200341026a20122d00003a0000200320022f019c023b00002003200229038802370013200341186a200229008d02370000200641e8026a200741e0006c6a220341e0006a2003201941e0006c10cf041a2003200241a0026a41e00010ce041a2006201041016a22033b010620074102742219200641880b6a22106a41086a201020044102746a2210200341ffff037120046b41027410cf041a20102009360200200020062f010622044f0d00200620196a418c0b6a2103034020032802002200200741016a22073b010420002006360200200341046a210320042007470d000b0b20024184026a41026a220320082d00003a0000200220022f0194063b01840220022002290380013703f00120022002290085013700f50120024190016a20024198066a41e00010ce041a200f20032d00003a0000200220022f0184023b011c200220022903f001370308200220022900f50137000d200241206a20024190016a41e00010ce041a0240200628020022030d002013210a2016210d2015210c2014210b200121090c050b20062f010421102013210a2016210d2015210c2014210b20032106200121090c000b0b41880b4108102a000b41b80b4108102a000b200320044105746a220041286a200041086a2210200120046b41057410cf041a200041206a2006290300370000200041186a2007290300370000200041106a2008290300370000201020022903203700002003200441e0006c6a220041c8036a200041e8026a220e20032f010620046b41e0006c10cf041a200e200241a0026a41e00010ce041a200320032f010641016a3b01060c010b20024198066a410272410041b20b10cd041a41b80b10272203450d0120034100360200200341046a20024198066a41b40b10ce041a2003200528020022003602880b200520033602002005200528020441016a360204200041003b010420002003360200200320032f010622044105746a220041086a20022f011c3b00002000410a6a2002411c6a41026a2d00003a0000200041176a200d360000200041136a200c3600002000410f6a200b3600002000410b6a200a3600002000411b6a2002290308370000200041206a200229000d3700002003200441e0006c6a41e8026a200241206a41e00010ce041a200341880b6a200441016a22004102746a2009360200200320003b0106200920003b0104200920033602000b200241d0116a2400200e0f0b41b80b4108102a000bc31e03087f037e127f23004180076b22042400200441e0006a41186a200241186a290000370300200441e0006a41106a200241106a290000370300200441e0006a41086a200241086a2900003703002004200229000037036002400240024002400240024002400240024020012802002205418883c000460d00200128020421060c010b41002106200441e8026a410041e00210cd041a200441c0016a410041840110cd041a41ec0310272205450d01200541003b010620054100360200200541086a200441e8026a41e00210ce041a200541e8026a200441c0016a41840110ce041a20014100360204200120053602000b02400340200541086a2107200541066a210820052f0106220941057421024100210a0240024003402002450d01200441e0006a2007412010d004220b450d02200241606a2102200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200520094102746a41ec036a28020021050c010b0b200441e8026a41086a22022005200a410c6c6a220741f0026a220a2802003602002004200741e8026a22072902003703e80220072003290200370200200a200341086a280200360200200441c0016a41086a20022802002202360200200420042903e802220c3703c0012000410c6a20023602002000200c370204200041013602000c060b200441086a41186a220b200441e0006a41186a2202290300370300200441086a41106a200441e0006a41106a2207290300220c370300200441086a41086a200441e0006a41086a220a290300220d37030020042004290360220e3703082001200128020841016a3602082007200c370300200a200d3703002002200b2903003703002004200e370360200441d8026a41086a2206200341086a280200360200200420032902003703d802024020082f01002203410b490d00200441e8026a410041e00210cd041a200441c0016a410041840110cd041a41ec031027220f450d02200f41003b0106200f4100360200200f41086a200441e8026a41e00210ce042107200f41e8026a200441c0016a41840110ce04210a200441e8026a41086a220b200541b8036a280200360200200420052900db013703a8012004200541e0016a2900003700ad01200420052902b0033703e802200420052f00c8013b01bc012004200541ca016a2d00003a00be01200541cb016a2800002110200541cf016a2800002111200541d3016a2800002112200541d7016a28000021132007200541e8016a20052f010641796a220241057410ce042107200a200541bc036a2002410c6c10ce04210a200541063b0106200f20023b0106200420042f01bc013b01a401200420042d00be013a00a601200420042903a8013703c001200420042900ad013700c501200441286a41086a200b280200360200200420042903e8023703280240024020094107490d00200941057420076a41c07e6a2007200941796a220b4105746a2207200241ffff0371200b6b41057410cf041a200741186a200441e0006a41186a290300370000200741106a200441e0006a41106a290300370000200741086a200441e0006a41086a290300370000200720042903603700002009410c6c200a6a220241b87f6a200241ac7f6a2202200f41066a22082f0100200b6b410c6c10cf041a200241086a200441d8026a41086a280200360200200220042903d8023702000c010b200541086a20094105746a220241206a200220082f010020096b41057410cf041a200241186a200441e0006a41186a290300370000200241106a200441e0006a41106a290300370000200241086a200441e0006a41086a29030037000020022004290360370000200541e8026a2009410c6c6a2202410c6a200220082f010020096b410c6c10cf041a200241086a200441d8026a41086a280200360200200220042903d8023702000b200820082f010041016a3b010020044198016a41026a220220042d00a6013a0000200441c8026a41086a2214200441286a41086a280200360200200420042f01a4013b019801200420042903c001370350200420042900c501370055200420042903283703c8022004413c6a41026a221520022d00003a0000200420042f0198013b013c2004200429005537002d20042004290350370328200441c0006a41086a22162014280200360200200420042903c80237034020052802002206450d0420052f01042103200441e8026a4102722117034020044194016a41026a221820152d00003a0000200420042f013c3b019401200420042903283703602004200429002d37006520044198016a41086a221920162802003602002004200429034037039801200341ffff0371210502400240024020062f01062202410b490d002017410041960410cd041a419c041027220b450d07200b4100360200200b41046a200441e8026a41980410ce041a200420062f00c8013b01bc012004200641ca016a2d00003a00be012004200641db016a2900003703a8012004200641e0016a2900003700ad01200641cb016a280000211a200641cf016a280000211b200641d3016a280000211c200641d7016a280000211d200441e8026a41086a221e200641b8036a2802003602002004200641b0036a2902003703e802200b41086a200641e8016a20062f0106220741796a220241057410ce04211f200b41e8026a200641bc036a2002410c6c10ce042120200b41ec036a20064188046a2007417a6a220941027410ce042108200641063b0106200b20023b010602402009450d00410021022008210703402007280200220a20023b0104200a200b360200200741046a21072009200241016a2202470d000b0b200441d8026a41086a2202201e280200360200200420042d00be0122073a00a601200420042f01bc01220a3b01a401200420042903a8013703c001200420042900ad013700c501200420042903e8023703d802200441c4026a41026a220920073a00002004200a3b01c402200420042903c0013703e802200420042900c5013700ed0220142002280200360200200420042903d8023703c802200341ffff037122074107490d01201f2005417a6a220a4105746a201f200541796a22024105746a2207200b2f010620026b41057410cf041a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20182d00003a0000200720042f0194013b0000200720042903603700132005410c6c20206a220741b87f6a200741ac7f6a2207200b2f0106220320026b410c6c10cf041a200741086a20192802003602002007200429039801370200200b200341016a22073b01062005410274221020086a416c6a2008200a4102746a2203200741ffff03712205200a6b41027410cf041a2003200f3602002005200a490d02200b20106a41d4036a210703402007280200220a200241016a22023b0104200a200b360200200741046a210720022005490d000c030b0b200641086a2207200541016a220a4105746a200720054105746a2207200220056b41057410cf041a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20044194016a41026a2d00003a0000200720042f0194013b00002007200429036037001320062005410c6c6a220241f4026a200241e8026a220720062f0106220b20056b410c6c10cf041a200241f0026a20044198016a41086a28020036020020072004290398013702002006200b41016a22023b01062005410274200641ec036a22076a41086a2007200a4102746a2207200241ffff0371220b200a6b41027410cf041a2007200f360200200341ffff0371200b4f0d082006200a417f6a22024102746a41f0036a210703402007280200220a200241016a22023b0104200a2006360200200741046a21072002200b490d000c090b0b200641086a2202200541016a22034105746a200220054105746a220220062f010620056b41057410cf041a200241186a20042900653700002002201336000f2002201236000b2002201136000720022010360003200241026a20182d00003a0000200220042f0194013b000020022004290360370013200641e8026a2005410c6c6a2202410c6a200220062f0106220a20056b410c6c10cf041a200241086a201928020036020020022004290398013702002006200a41016a22023b010620054102742210200641ec036a220a6a41086a200a20034102746a2208200241ffff0371220a20036b41027410cf041a2008200f3602002007200a4f0d00200620106a41f0036a2102034020022802002207200541016a22053b010420072006360200200241046a2102200a2005470d000b0b20044190016a41026a220220092d00003a000020044180016a41086a22072014280200360200200420042f01c402220a3b019001200420042903e802370350200420042900ed02370055200420042903c80237038001201520022d00003a00002004200a3b013c2004200429005537002d200420042903503703282016200728020036020020042004290380013703400240200628020022020d00201a2110201d2113201c2112201b2111200b210f0c060b20062f01042103201a2110201d2113201c2112201b211120022106200b210f0c000b0b200520094105746a220b41286a200b41086a2201200320096b41057410cf041a200b41206a2002290300370000200b41186a2007290300370000200b41106a200a2903003700002001200429036037000020052009410c6c6a220241f4026a200241e8026a220720052f010620096b410c6c10cf041a200241f0026a2006280200360200200720042903d802370200200520052f010641016a3b01060c040b41ec034104102a000b41ec034104102a000b419c044104102a000b200441e8026a410272410041960410cd041a419c0410272202450d0220024100360200200241046a200441e8026a41980410ce041a2002200128020022073602ec03200120023602002001200128020441016a360204200741003b010420072002360200200220022f0106220a4105746a220741086a20042f013c3b00002007410a6a2004413c6a41026a2d00003a0000200741176a2013360000200741136a20123600002007410f6a20113600002007410b6a20103600002007411b6a2004290328370000200741206a200429002d3700002002200a410c6c6a220741f0026a200441c0006a41086a280200360200200741e8026a2004290340370200200241ec036a200a41016a22074102746a200f360200200220073b0106200f20073b0104200f20023602000b200041003602000b20044180076a24000f0b419c044104102a000bde2003167f037e067f230041c0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006712109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110db032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200a200a417f6a220d2000200a4105746a2000200d4105746a412010d004220e410048220f1b2210200a41016a2211200d200a200f1b220a200020114105746a2000200a4105746a412010d00441004822111b220a2000200a4105746a200020104105746a412010d00422104100481b210a200c200c417f6a220d2000200c4105746a2000200d4105746a412010d004221241004822131b2214200c4101722215200d200c20131b220c200020154105746a2000200c4105746a412010d00422134100481b220c2000200c4105746a200020144105746a412010d00422144100481b210c200b200b417f6a220d2000200b4105746a2000200d4105746a412010d004221541004822161b2217200b41016a2218200d200b20161b220b200020184105746a2000200b4105746a412010d004220d4100481b220b2000200b4105746a200020174105746a412010d00422164100481b210b41024101200f1b200e411f7620111b2010411f766a2012411f766a2013411f766a2014411f766a2015411f766a200d411f766a2016411f766a210d0b2000200c4105746a2000200a4105746a412010d004220f411f76200d6a2000200b4105746a2000200a200c200f410048220f1b220e4105746a412010d0042210411f766a210d2000200b200e20104100481b220b4105746a2000200c200a200f1b22194105746a412010d004417f4c0d01200b21190c020b2000200110dc030c0f0b200d41016a220d410c490d0002402001410176220b450d00200020014105746a41606a210a2000210c0340200441206a41186a220d200c41186a220f290000370300200441206a41106a220e200c41106a2210290000370300200441206a41086a2211200c41086a22122900003703002004200c290000370320200a41086a2213290000211a200a41106a2214290000211b200a41186a2215290000211c200c200a290000370000200f201c3700002010201b3700002012201a3700002015200d2903003700002014200e29030037000020132011290300370000200a2004290320370000200a41606a210a200c41206a210c200b417f6a220b0d000b0b20012019417f736a21194101210a0c010b200d45210a0b02402009417f73200a45724101710d002000200110dd030d0d0b2002450d02201920014f0d0102402002200020194105746a220a412010d00441004e0d0020002108200121070c040b200441206a41186a2212200041186a220e290000370300200441206a41106a2213200041106a2210290000370300200441206a41086a2214200041086a221129000037030020042000290000370320200a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2000200a290000370000200e201c3700002010201b3700002011201a370000200d2012290300370000200b2013290300370000200c2014290300370000200a2004290320370000200441c0016a41186a2217200e290000370300200441c0016a41106a22182010290000370300200441c0016a41086a22192011290000370300200420002900003703c001200041606a2115200041206a21164100210c2001210b03400240200c200b417f6a220d4f0d002016200c4105746a210a0340200441c0016a200a412010d004417f4c0d01200a41206a210a200d200c41016a220c470d000b200d210c0b2015200b4105746a210a02400340200c200b417f6a220b4f0d01200441c0016a200a412010d004210d200a41606a220f210a200d4100480d000b20122016200c4105746a220a41186a220d2900003703002013200a41106a221d2900003703002014200a41086a22062900003703002004200a290000370320200f41286a221e290000211a200f41306a221f290000211b200f41386a2220290000211c200a200f41206a220f290000370000200d201c370000201d201b3700002006201a37000020202012290300370000201f2013290300370000201e2014290300370000200f2004290320370000200c41016a210c0c010b0b200020042903c001370000200e2017290300370000201020182903003700002011201929030037000002402001200c41016a220a490d002000200a4105746a21002001200a6b220141154f0d010c0c0b0b200a2001103e000b41ec81c500201920011037000b2007450d010b201920074f0d01200441206a41186a2216200841186a221e290000370300200441206a41106a2217200841106a221f290000370300200441206a41086a2218200841086a222029000037030020042008290000370320200820194105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200441186a2205201e290000370300200441106a2209201f290000370300200441086a2221202029000037030020042008290000370300200841206a21014100211d2007417f6a220d450d022001210a0340200a2004412010d00441004e0d03200a41206a210a200d201d41016a221d470d000b200d211d0c020b41b481c500410041001037000b41c481c500201920071037000b200820074105746a210c200d210b02400340200c2100200b220a201d4d22060d01200a417f6a210b200041606a220c2004412010d004417f4a0d000b0b0240200a201d490d00200d200a490d0241800121144100210f410021124100210d4100211141800121152001201d4105746a2222210103400240200020016b220a419fc0004b22190d00200a410576220a41807f6a200a2012200f492011200d49220c72220b1b210a0240200b450d002015200a200c1b2115200a2014200c1b21140c010b200a200a41017622156b21140b02402011200d470d00024020150d00200441c0006a220d21110c010b4100210a200441c0006a2211210d2001210c0340200d200a3a0000200d200c2004412010d004417f73411f766a210d200c41206a210c2015200a41016a220a470d000b0b02402012200f470d00024020140d00200441c0016a220f21120c010b200041606a210a4100210c200441c0016a2212210f0340200f200c3a0000200f200a2004412010d004411f766a210f200a41606a210a2014200c41016a220c470d000b0b0240200f20126b220a200d20116b220c200c200a4b1b2213450d002016200120112d00004105746a220a41186a2900003703002017200a41106a2900003703002018200a41086a2900003703002004200a290000370320200120112d00004105746a220a200020122d0000417f734105746a220c290000370000200a41186a200c41186a290000370000200a41106a200c41106a290000370000200a41086a200c41086a290000370000024020134101460d004100210a034020002012200a6a220e2d0000417f734105746a220c20012011200a6a41016a22102d00004105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200120102d00004105746a220c2000200e41016a2d0000417f734105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200a41026a210c200a41016a220b210a200c2013490d000b2012200b6a21122011200b6a21110b200020122d0000417f734105746a220a2004290320370000200a41186a2016290300370000200a41106a2017290300370000200a41086a2018290300370000201241016a2112201141016a21110b200020144105746b20002012200f461b2100200120154105746a20012011200d461b210120190d000b024002402011200d4f0d002000210a034020162001200d417f6a220d2d00004105746a220c41186a220b2900003703002017200c41106a220f2900003703002018200c41086a22002900003703002004200c290000370320200a41606a220a41086a220e290000211a200a41106a2210290000211b200a41186a2212290000211c200c200a290000370000200b201c370000200f201b3700002000201a3700002012201629030037000020102017290300370000200e2018290300370000200a20042903203700002011200d490d000c020b0b2001210a2012200f4f0d000340200f417f6a220f2d0000210c2016200a41186a220b2900003703002017200a41106a220d2900003703002018200a41086a22012900003703002004200a2900003703202000200c417f734105746a220c41086a220e290000211a200c41106a2210290000211b200c41186a2211290000211c200a200c290000370000200b201c370000200d201b3700002001201a3700002011201629030037000020102017290300370000200e2018290300370000200c2004290320370000200a41206a210a2012200f490d000b0b20082004290300370000201e2005290300370000201f2009290300370000202020212903003700002007200a20226b410576201d6a22014d0d032016201e2900003703002017201f2900003703002018202029000037030020042008290000370320200820014105746a220a41086a220c290000211a200a41106a220b290000211b200a41186a220d290000211c2008200a290000370000201e201c370000201f201b3700002020201a370000200d2016290300370000200b2017290300370000200c2018290300370000200a2004290320370000200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41206a2100024002402001200c417f6a220c490d002000200c200a200310e001200821000c010b200820012002200310e001200a2102200c21010b200b200d4f2105200141154f0d010c050b0b201d200a103e000b200a200d107f000b41c481c500200120071037000b41d481c5001058000b20014102490d00200041606a210f4101210b0340200b410574210a200b417f6a210c200b41016a210b02402000200a6a220a2000200c4105746a220d412010d004417f4a0d00200441c0016a41186a220e200a41186a2210290000370300200441c0016a41106a2211200a41106a2212290000370300200441c0016a41086a2213200a41086a22142900003703002004200a2900003703c001200a200d2900003700002014200d41086a2900003700002012200d41106a2900003700002010200d41186a2900003700004100210d0240200c450d00200f210a03400240200441c0016a200a412010d0044100480d00200c210d0c020b200a41206a200a290000370000200a41386a200a41186a290000370000200a41306a200a41106a290000370000200a41286a200a41086a290000370000200a41606a210a200c417f6a220c0d000b0b2000200d4105746a220a20042903c001370000200a41186a200e290300370000200a41106a2011290300370000200a41086a20132903003700000b200f41206a210f200b2001470d000b0b200441c0026a24000bf51602097f027e23004180046b2209240020092004370310200920033703082009200536021c2009200736022420092006360220024002400240024002400240024002400240024002402001280234200128025022062802b801460d002005420020052903082203200641386a2903007d2204200420035622061b37030802400240024020060d00200941d8006a20024200410110a00120094194016a280200210a200941d8006a41386a280200210b20092d0060220641037122054103460d0120050e03020102020b200041fab6c30036020420004101360200200041086a41233602000c030b2000419db7c30036020420004101360200200041086a411936020020060d02200a450d02200b10290c020b20094198016a2802002105200941286a41186a220c200141f4006a290000370300200941286a41106a220d200141ec006a290000370300200941286a41086a220e200141e4006a2900003703002009200129005c3703284100210f41002107024020060d002005417f4c0d030240024020050d00410121070c010b200510272207450d052007200b200510ce041a0b200a450d00200b10290b200941a0016a420037030020094198016a4280808080800137030020094188016a41f8b4c300360200200941d8006a412c6a2001411c6a2210360200200941d8006a41246a4200370200200941f8006a418883c000360200200941d8006a41186a2005360200200941ec006a2005360200200941d8006a41e4006a200241086a290000370200200941d8006a41ec006a200241106a290000370200200941d8006a41f4006a200241186a29000037020020094208370390012009410036027420092007360268200920022900003702b401200920012802583602b001200920012903503703a8012009200128023441016a36028c01200129030021032009200129030837036020092003370358200941d8016a41246a200e290300370200200941d8016a412c6a200d2903003702002009418c026a200c290300370200200941d8016a41186a200841086a280200360200200920023602e001200920092903283702f401200920082902003703e8012009200941206a3602e40120092009411c6a3602dc012009200941086a3602d801200941d8016a411c6a210d0240024002400240024020092903082203200941086a41086a290300220484500d002009200928021c4100200d200220032004200941d8006a10a203200928020022020d012009280274210f20092802e00121020b200f41016a220541004c0d08200941d8016a41106a2111200941d8006a411c6a210e20092005360274200941d8006a41206a2105200941fc006a280200210b0240024003402005280200220a41086a2108200a2f0106220c4105742105410021060240024003402005450d0120022008412010d0042207450d02200541606a2105200641016a2106200841206a21082007417f4a0d000b2006417f6a210c0b200b450d02200b417f6a210b200a200c4102746a41880b6a21050c010b0b200941a0036a2208200a200641e0006c6a220541ad036a290000370300200941a8036a2206200541b5036a290000370300200941b0036a2207200541bd036a2900003703002009200541a5036a29000037039803200541a4036a2d00004101470d00200941a1026a2008290300370000200941a9026a2006290300370000200941b1026a2007290300370000200941013a0098022009200929039803370099022009200f3602740c010b20094198026a200928028401200220092802880128021011020020092009280274417f6a3602744101210620092d0098024101470d040b200941c0026a41186a200941b1026a290000370300200941c0026a41106a200941a9026a290000370300200941c0026a41086a200941a1026a29000037030020092009290099023703c00220094198036a200941c0026a20092802b001280200108402410121062009280298034101470d0220094198036a41086a2802002101200928029c0321020c010b200928020421010b200941ec016a280200450d0b20092802e80110290c0b0b200941e0036a41186a220820094198036a410472220541186a2802002207360200200941e0026a41106a200541086a290200370300200941e0026a41186a200541106a29020037030020094180036a2007360200200941043602e402200941b98fc5003602e002200920052902003703e80220092802ac0121052008200d41186a2900002203370300200941e0036a41106a200d41106a2900002204370300200941e0036a41086a2208200d41086a2900002212370300200941c4036a2012370200200941cc036a2004370200200941d4036a20033702002009200d29000022033703e003200920033702bc0320092802d801220741086a29030021032009200941d8006a3602b803200729030021042009290358211220092903602113200920033703a0032009200437039803200920133703b003200920123703a80320092802e40122072802042102200728020021072008201141086a280200360200200920112902003703e00320094188036a2005200941e0026a20094198036a20072002200941e0036a20092802dc01280200106241002102410021072009280288030e03070609070b410021070240200941ec016a280200450d0020092802e80110290b410021020c070b200041d1b6c30036020420004101360200200041086a41293602000b200841046a280200450d08200828020010290c080b1039000b20054101102a000b41d8a8c1004118200941e0026a4180a9c10010a201000b20094194036a280200210720094190036a2802002102200928028c0321060b200941f8026a280200450d00200941f4026a28020010290b20094198036a41086a220a200e41086a290200370300200941c8006a41086a220b20094198036a410c6a2802003602002009200e290200370398032009200929029c0337034820092802a401210c20092802a001210d200928029c012105200928029801210f200928029401210e2009280290012108024020092802682211450d00200928026c450d00201110290b200a200b280200220b36020020092009290348220337039803200941d8006a41086a200b360200200920033703582010200941d8006a10e60120092008200f41e8006c6a360264200920083602602009200e36025c20092008360258200141386a200941d8006a102c20092005200c41a8016c6a360264200920053602602009200d36025c20092005360258200141c4006a200941d8006a10262000410c6a2007360200200041086a200236020020002006360204200041003602000c020b20094190036a2802002101200928028c032102200941f8026a280200450d00200941f4026a28020010290b024020092802682205450d00200928026c450d00200510290b200941f8006a2802002105200928028001210a02400240200928027c22060d00200521080c010b2006210720052108034020082802880b21082007417f6a22070d000b0340200520052f01064102746a41880b6a28020021052006417f6a22060d000b0b200941b4036a20052f0106360200200941b0036a4100360200200941ac036a20053602002009200a3602b803200941003602a803200942003703a0032009200836029c03200941003602980320094198036a10d90102402009280298012208450d002009280290012105200841e8006c210803400240200541dc006a280200450d00200541d8006a28020010290b024020052d00004105490d00200541286a280200450d00200541246a28020010290b200541e8006a2105200841987f6a22080d000b0b0240200928029401450d0020092802900110290b024020092802a4012205450d00200541a8016c2108200928029c0141206a210503402005103d200541a8016a2105200841d87e6a22080d000b0b024020092802a001450d00200928029c0110290b200041086a200136020020002002360204200041013602000b20094180046a24000bcd0202097f027e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d0120022008412010d004220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a220541e8026a280200450d00200541f8026a290300210c200541f0026a290300210d0c010b200341086a20012802102002200141146a28020028021c110200200341106a290300210c200128020021042003290308210d0b20012004417f6a3602002000200c3703082000200d370300200341206a24000f0b41d8a8c1004118200341186a4180a9c10010a201000b940301097f230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a280200210602400240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d0120022008412010d004220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b200341086a22082007200a41e0006c6a220541ad036a290000370300200341106a220a200541b5036a290000370300200341186a220b200541bd036a2900003703002003200541a5036a290000370300200541a4036a2d00004101460d010b200020012802102002200141146a280200280210110200200128020021040c010b200041013a000020002003290300370001200041096a2008290300370000200041116a200a290300370000200041196a200b2903003700000b20012004417f6a360200200341206a24000f0b41d8a8c100411820034180a9c10010a201000b950201097f230041106b220224000240200028020041016a220341004c0d0020002003360200200041046a2104200041086a28020021050240024003402004280200220641086a210720062f01062208410574210441002109024003402004450d0120012007412010d004220a450d03200441606a2104200941016a2109200741206a2107200a417f4a0d000b2009417f6a21080b02402005450d002005417f6a2105200620084102746a41880b6a21040c010b0b20002802102001200041146a2802002802181104002104200028020021030c010b2006200941e0006c6a41a4036a2d000041014621040b20002003417f6a360200200241106a240020040f0b41d8a8c1004118200241086a4180a9c10010a201000bde0202097f037e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d0120022008412010d004220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a22054180036a290300220ca7450d0020054190036a290300210d20054188036a290300210e0c010b200320012802102002200141146a280200280214110200200341106a290300210d200128020021042003290308210e2003290300210c0b20012004417f6a360200200041106a200d3703002000200e3703082000200c370300200341206a24000f0b41d8a8c1004118200341186a4180a9c10010a201000b961208057f017e107f047e017f017e0a7f047e230041800d6b22022400024020002802000d002000417f360200200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b200241246a20042f0106360200200241086a41186a4100360200200241086a41146a20043602002002200336022820024100360218200242003703102002200136020c2002410036020820024180026a200241086a10d501024020022903a00222074202510d002000410c6a2108200041046a2109200241a00a6a41146a210a200241a00a6a41206a210b20024180026a4104722104200241dd026a210c200241bd026a210d200241fd026a210e200241c8026a210f200241b0026a211020024180026a41286a21110340200241d0006a41086a220120024180026a41086a2212290300370300200241d0006a41106a220520024180026a41106a2213290300370300200241d0006a41186a220620024180026a41186a2214290300370300200241306a41086a2215200c41086a290000370300200241306a41106a2216200c41106a290000370300200241306a41186a2217200c41186a29000037030020022002290380023703502002200c290000370330200f29030021182010290300211920022903c002211a20022903a802211b20022d00dc02211c20022903b802211d20022802d002210320022802d402211e20022802d802211f2002412c6a41026a200e41026a2d000022203a00002002200e2f000022213b012c200241f8006a41086a22222015290300370300200241f8006a41106a22232016290300370300200241f8006a41186a22242017290300370300200241f4006a41026a222520203a000020022002290330370378200220213b017420024198016a41186a2221200629030037030020024198016a41106a2226200529030037030020024198016a41086a2227200129030037030020022002290350370398010240024002400240024020092802002216418883c000460d00200028020821170c010b200241a00a6a410041e00210cd041a20024180026a410041a00810cd041a41880b10272216450d0141002117201641003b010620164100360200201641086a200241a00a6a41e00210ce041a201641e8026a20024180026a41a00810ce041a20004100360208200020163602040b0340201641086a210520162f01062220410574210141002106024003402001450d0120024198016a2005412010d0042215450d04200141606a2101200641016a2106200541206a21052015417f4a0d000b2006417f6a21200b02402017450d002017417f6a2117201620204102746a41880b6a28020021160c010b0b200241d0016a41186a20212903002228370300200241d0016a41106a20262903002229370300200241d0016a41086a2027290300222a3703002002200229039801222b3703d001200a202b370200200a41086a202a370200200a41106a2029370200200a41186a2028370200200220083602b00a200220203602ac0a200220093602a80a200220163602a40a200241003602a00a20112018370300201320193703002002201a3703a0022002201b370388022002201c3a00bc022002201f3602b8022002201e3602b402200220033602b0022002201d370398022002200737038002200d2002290378370000200d41086a2022290300370000200d41106a2023290300370000200d41186a2024290300370000200c20022f01743b0000200c41026a20252d00003a0000200241a00a6a20024180026a10de011a0c020b41880b4108102a000b2016200641e0006c6a220641f0026a22012001290300201b20075022011b370300200641f8026a22052005290300201920011b370300200641e8026a22052005290300200720011b370300200241a00a6a41186a22152024290300370300200241a00a6a41106a22162023290300370300200241a00a6a41086a22172022290300370300200220022903783703a00a200641a4036a22052d000021202014200641bd036a22222900003703002013200641b5036a22232900003703002012200641ad036a22132900003703002002200641a5036a2224290000370380022027200241a00a6a20024180026a201c41ff0171410146221c1b220141086a2900003703002026200141106a2900003703002021200141186a2900003703002002200129000037039801200541012020201c1b3a0000202420022903980137000020132027290300370000202320262903003700002022202129030037000020064188036a2201201a2001290300201da722011b37030020064190036a22052018200529030020011b37030020064180036a2205201d200529030020011b37030002400240201e0d00200321010c010b201e210520032101034020012802ec0321012005417f6a22050d000b0340200320032f01064102746a41ec036a2802002103201e417f6a221e0d000b0b20032f010621052002201f3602b801200220053602b401200241003602b001200220033602ac01200241003602a801200242003703a0012002200136029c01200241003602980120024180026a20024198016a10d70102402002280280024101470d0020064198036a21030340200241a00a6a41286a200441286a280200360200200b200441206a2902003703002015200441186a22012902003703002016200441106a22052902003703002017200441086a2206290200370300200220042902003703a00a200241d0016a41186a2001290000370300200241d0016a41106a2005290000370300200241d0016a41086a2006290000370300200220042900003703d001200241f0016a41086a200b41086a2802003602002002200b2902003703f001200241c0016a2003200241d0016a200241f0016a10df01024020022802c001450d0020022802c4012201450d0020022802c801450d00200110290b20024180026a20024198016a10d7012002280280024101460d000b0b20024198016a10d6010b20024180026a200241086a10d50120022903a00222074202520d000b0b200241086a10d9012000200028020041016a360200200241800d6a24000f0b41c8a8c100411020024180026a41f0a8c10010a201000bd80202027f017e0240024002400240024002400240024002400240024002400240024020012802000e0400010203000b41012102410110272201450d05200141003a0000410121030c040b410110272202450d05200241013a00002001290308210420024101410910282202450d0620022004370001200129031021044112210320024109411210282201450d07200120043700090c020b41012102410110272201450d07200141023a0000410121030c020b410110272202450d07200241033a00002001290308210420024101410910282202450d0820022004370001200129031021044112210320024109411210282201450d09200120043700090b411121020b2000200236020820002003360204200020013602000f0b41014101102a000b41014101102a000b41094101102a000b41124101102a000b41014101102a000b41014101102a000b41094101102a000b41124101102a000b130020004101360204200041f4afc1003602000b3400200041f4b0c10036020420004100360200200041146a4105360200200041106a4184b1c100360200200041086a420f3702000b2501017f230041206b22022400200242003703082000200241086a10e701200241206a24000b820603037f027e017f230041206b220424004101210502402001a722064101470d002000427f2000290300220720027c220820082007542205200041086a2209290300220720037c2005ad7c220820075420082007511b22051b3703002009427f200820051b370300410021050b024002400240024020014201560d00024020060e020400040b2005450d0342002107200441106a41086a220042003703002004420037031041b18ac0004116200441106a1004200441086a2000290300370300200420042903103703002004410036021020044110200441106a100521050240024020042802102200417f470d00420021010c010b2004420037031820044200370310200441106a20052000411020004110491b10ce041a2000410f4d0d02200441186a290300210120042903102107200510290b200441106a41086a220042003703002004420037031041b18ac0004116200441106a1004200441086a2000290300370300200420042903103703002004427f200120037c200720027c22032007542200ad7c22022000200220015420022001511b22001b3703182004427f200320001b37031020044110200441106a411010030c030b42002107200441106a41086a220042003703002004420037031041b18ac0004116200441106a1004200441086a2000290300370300200420042903103703002004410036021020044110200441106a100521050240024020042802102200417f470d00420021010c010b2004420037031820044200370310200441106a20052000411020004110491b10ce041a2000410f4d0d02200441186a290300210120042903102107200510290b200441106a41086a220042003703002004420037031041b18ac0004116200441106a1004200441086a2000290300370300200420042903103703002004427f200120037c200720027c22032007542200ad7c22022000200220015420022001511b22001b3703182004427f200320001b37031020044110200441106a411010030c020b418f89c3004133104e000b418f89c3004133104e000b200441206a24000b130020004103360204200041f0b7c1003602000b3400200041bff4c10036020420004100360200200041146a4103360200200041106a41d8bec100360200200041086a42083702000b130020004104360204200041f0c2c1003602000b3201017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241a0c21e3600000b3201017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242c0f0003700000b3201017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241d086033600000ba70201047f23004190016b2202240002400240411210272203450d00200341106a41002f00c0a7413b0000200341086a41002900b8a741370000200341002900b0a74137000020034112412410282203450d0120032001360012200241086a41186a22014200370300200241086a41106a22044200370300200241086a41086a220542003703002002420037030820034116200241086a1000200241f0006a41186a2001290300370300200241f0006a41106a2004290300370300200241f0006a41086a200529030037030020022002290308370370200241086a200241f0006a10f3010240024020022903084201510d00200042003703000c010b2000200241086a41e80010ce041a0b2003102920024190016a24000f0b41124101102a000b41244101102a000bcb0706047f017e027f017e047f027e230041c0016b22022400200241003602a00120014120200241a0016a10052101024002400240024020022802a0012203417f460d0020010d010b200042003703000c010b200241a0016a2003412020034120491b22046a41004100412020046b2004411f4b1b10cd041a200241a0016a2001200410ce041a2003411f4d0d01200241206a41086a200241a0016a41086a2205290000370300200241206a41106a200241a0016a41106a290000370300200241206a41186a200241a0016a41186a290000370300200220022900a001220637036020022006370320200242003703a801200242003703a001200241a0016a200120046a2207200320046b2203411020034110491b220810ce041a2003410f4d0d012005290300210620022903a0012109200241a0016a200320086b2204412020044120491b22036a41004100412020036b2003411f4b1b10cd041a200241a0016a200720086a220a200310ce041a2004411f4d0d01200241c0006a41086a220b200241a0016a41086a2208290000370300200241c0006a41106a220c200241a0016a41106a2205290000370300200241c0006a41186a220d200241a0016a41186a2207290000370300200220022900a001220e3703602002200e3703402002420037036820024200370360200241e0006a200a20036a200420036b2203411020034110491b10ce041a2003410f4d0d012008200241206a41086a2903003703002005200241206a41106a2903003703002007200241206a41186a29030037030020024180016a41086a2204200b29030037030020024180016a41106a220a200c29030037030020024180016a41186a220b200d290300370300200220022903203703a0012002200229034037038001200241e0006a41086a2203290300210e2002290360210f20032008290300370300200241e0006a41106a22082005290300370300200241e0006a41186a22052007290300370300200241086a22072004290300370300200241106a2204200a290300370300200241186a220a200b290300370300200220022903a001370360200220022903800137030020011029200041206a200e370300200041186a200f370300200041106a20063703002000200937030820004201370300200041286a2002290360370300200041306a2003290300370300200041386a2008290300370300200041c0006a2005290300370300200041c8006a2002290300370300200041d0006a2007290300370300200041d8006a2004290300370300200041e0006a200a2903003703000b200241c0016a24000f0b418f89c3004133104e000bc30701087f230041e00b6b220424000240024020002802000d002000417f360200200441286a41186a200141186a290000370300200441286a41106a200141106a290000370300200441286a41086a200141086a290000370300200420012900003703280240024020002802042205418883c000460d00200041086a28020021060c010b4100210620044180096a410041e00210cd041a200441e0006a410041a00810cd041a41880b10272205450d02200541003b010620054100360200200541086a20044180096a41e00210ce041a200541e8026a200441e0006a41a00810ce041a200041086a4100360200200020053602040b200041046a210702400240034020052f010622084105742109410021014100210a02400240034020092001460d01200441286a200520016a41086a412010d004220b450d02200141206a2101200a41016a210a200b417f4a0d000b200a417f6a21080b2006450d022006417f6a2106200520084102746a41880b6a28020021050c010b0b2000410c6a210b410121010c010b200441086a41186a200441286a41186a290300370300200441086a41106a200441286a41106a290300370300200441086a41086a200441286a41086a290300370300200420042903283703082000410c6a210b410021062008210a410021010b0240024020010d002004419c096a200441086a41086a290300370200200441a4096a200441086a41106a290300370200200441ac096a200441086a41186a2903003702002004200b360290092004200a36028c09200420073602880920042005360284092004200636028009200420042903083702940920044180016a200429035037030020044188016a200441d0006a41086a29030037030020044194016a420037020020044200370378200442003703602004418883c00036029001200441003a009c012004419d016a2004290028370000200441a5016a200441286a41086a290000370000200441ad016a200441286a41106a290000370000200441b5016a200441286a41186a290000370000200441bc016a200441c7006a28000036000020044180096a200441e0006a10de0121010c010b200441f8006a4200370300200441f4006a418883c000360200200441003602800120044100360270200442003703682004418883c000360264200441003602602005200a41e0006c6a41e8026a2101200441e0006a10d6010b200141106a200337030020012002370308200142013703002000200028020041016a360200200441e00b6a24000f0b41c8a8c1004110200441e0006a41f0a8c10010a201000b41880b4108102a000bad2304017f027e147f047e230041a0056b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e0400010203000b200341c4046a4101360200200342013702b404200341ccfdc4003602b0042003410236028c01200341c4fdc40036028801200320034188016a3602c004200341b0046a41c0c9c1001057000b200141306a2903002104200141286a2903002105200341fc006a41026a200141076a2d00003a0000200341e0006a41086a200141186a290200370300200341e0006a410d6a2001411d6a290000370000200320012f00053b017c2003200141106a29020037036041d588c3002106412a210720022d00000d1520022d00014101470d15200141086a28020021062001410c6a280200210720012d00042101200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241086a2d00002115200241066a2f01002116200241056a2d00002117200241046a2d00002118200241026a2f0100211920032002411a6a2901003703c003200320083a00bf03200320093a00be032003200a3b01bc032003200b3a00bb032003200c3a00ba032003200d3b01b8032003200e3a00b7032003200f3a00b603200320103b01b403200320113a00b303200320183a00aa03200320193b01a803200320142013410874722012411874723600af03200320172016410874722015411874723600ab0320034188046a41026a2202200341fc006a41026a2d00003a0000200320032f017c3b018804200341b0046a41086a2208200341e0006a41086a290300370300200341b0046a410d6a2209200341e0006a410d6a290000370000200320032903603703b0040240200141ff01714101460d0020034184046a41026a20022d00003a0000200341c8026a41086a2008290300370300200341c8026a410d6a2009290000370000200320032f0188043b018404200320032903b0043703c8020c130b20034190046a200641067610cc012003280290042102024002402003280298042006413f7122014b0d00410021010c010b20034184046a41026a200220014105746a220141026a2d00003a0000200341d0026a200141136a290000370300200341d5026a200141186a290000370000200320012f00003b0184042003200129000b3703c8022001280007210720012800032106410121010b0240200328029404450d00200210290b20010d1241012101411521074184efc20021060c130b41a584c2002106410e210720022d00004101470d14200241086a2802004102490d14200241046a28020041ff01710d1420012802042102411210272201450d01200141106a41002f00c0a7413b0000200141086a41002900b8a741370000200141002900b0a74137000020014112412410282201450d0220012002360012200341b0046a41186a22024200370300200341b0046a41106a22064200370300200341b0046a41086a22074200370300200342003703b00420014116200341b0046a100020034190046a41186a200229030037030020034190046a41106a200629030037030020034190046a41086a2007290300370300200320032903b00437039004200341b0046a20034190046a10f301024020032903b00442015222020d0020034190046a4120100c0b20032802b8042106200341a8036a200341bc046a41dc0010ce041a20020d03200341c8026a200341a8036a41dc0010ce041a20011029200341e8016a200341c8026a41dc0010ce041a200320063602880120034188016a410472200341e8016a41dc0010ce041a20034188016a41186a2903002104200329039801211a411810272201450d04200141106a41002900cf8c40370000200141086a41002900c78c40370000200141002900bf8c4037000020014118413810282201450d052001200341a8016a2202290000370018200141306a200241186a290000370000200141286a200241106a290000370000200141206a200241086a290000370000200341c8006a20014138108401200341c8006a41106a290300211b2003290350211c2003280248210620011029420021052002201c420020061b221c201a201c201c201a56201b420020061b221b200456201b2004511b22011b221a7d201b2004201b20011b221d7d201c201a54ad7d109c01200341b0046a41086a22014200370300200342003703b00441b18ac0004116200341b0046a1004200341c8026a41086a2001290300370300200320032903b0043703c802200341003602b004200341c8026a4110200341b0046a100521020240024020032802b0042201417f470d00420021040c010b200342003703b804200342003703b004200341b0046a20022001411020014110491b10ce041a2001410f4d0d07200341b8046a290300210420032903b0042105200210290b200341b0046a41086a22014200370300200342003703b00441b18ac0004116200341b0046a1004200341c8026a41086a2001290300370300200320032903b0043703c802200342002004201d7d2005201a54ad7d221c2005201a7d221b200556201c200456201c2004511b22011b3703b80420034200201b20011b3703b004200341c8026a4110200341b0046a41101003410021060c130b41a584c2002106410e210720022d00004101470d13200241086a2802004104490d13200241046a28020041ff01710d1320012802042106411210272201450d06200141106a41002f00c0a7413b0000200141086a41002900b8a741370000200141002900b0a74137000020014112412410282201450d0720012006360012200341b0046a41186a22024200370300200341b0046a41106a22074200370300200341b0046a41086a22084200370300200342003703b00420014116200341b0046a100020034190046a41186a200229030037030020034190046a41106a200729030037030020034190046a41086a2008290300370300200320032903b0043703900420034190046a412041b8d6c50041004100100b2102200110292002417f460d0f200341b0046a41086a22014200370300200342003703b004418486c5004112200341b0046a1004200341c8026a41086a2001290300370300200320032903b0043703c80241002102200341003602b004200341c8026a4110200341b0046a1005210720032802b0042201417f460d092003200136028c012003200736028801200341b0046a20034188016a104520032802b004220c450d08200341b8046a280200210220032902b404210520032802b404210d02402001450d00200710290b2005a72005422088a72201470d0b0c0a0b41124101102a000b41244101102a000b200110290c0c0b41184101102a000b41384101102a000b418f89c3004133104e000b41124101102a000b41244101102a000b418f89c3004133104e000b4104210c410021010b200141016a22072001490d0320014101742208200720072008491b220d41ffffffff0371200d470d03200d41027422074100480d030240024020010d0020071027210c0c010b200c200141027420071028210c0b200c450d01200221010b200c20014102746a2006360200200341b0046a41086a22014200370300200342003703b004418486c5004112200341b0046a1004200341c8026a41086a2001290300370300200320032903b0043703c802200341003602b804200342013703b0042003200241016a22013602880120034188016a200341b0046a103002400240200120024f0d0020032802b804210920032802b404210820032802b00421020c010b410020032802b80422016b2106200241027441046a210a20032802b4042108200c210703402007280200210b02400240200820066a4104490d0020032802b00421020c010b200141046a22022001490d0520084101742209200220022009491b22094100480d050240024020080d002009102721020c010b20032802b00420082009102821020b2002450d04200320093602b404200320023602b004200921080b200741046a21072003200141046a22093602b804200220016a200b3600002006417c6a210620092101200a417c6a220a0d000b0b200341c8026a411020022009100302402008450d00200210290b41002106200d450d06200c10290c060b20074104102a000b20094101102a000b102b000b41eac9c1002106411921070c030b20034190046a41026a20034184046a41026a2d00003a0000200341b0046a41086a200341c8026a41086a290300370300200341b0046a410d6a200341c8026a410d6a290000370000200320032f0184043b019004200320032903c8023703b004410021010b20034184016a41026a220220034190046a41026a2d00003a000020034188016a41086a2208200341b0046a41086a29030037030020034188016a41106a200341b0046a41106a290300370300200320032f0190043b018401200320032903b0043703880120010d01200341306a2005200442c0843d420010d404200341206a2003290330221c200341306a41086a290300221b42c0fb42427f10d304200341106a201c201b42d08603420010d30420034180016a41026a20022d00003a0000200341e8016a41086a2008290300370300200341e8016a410d6a220220034188016a410d6a290000370000200320032f0184013b01800120032003290388013703e801200341c0006a200341a8036a2003290310221b200520032903207c42148042ffffffff0f837c221c428080e983b1de16201c428080e983b1de1656200341106a41086a290300201c201b54ad7c221c420052201c501b22011b221b201c420020011b221c10ac0102402003280240450d0041d0c9c1002106411a21070c020b200341086a41ee85c500411610b501200328020c210120032802082108200341b0046a41086a22094200370300200342003703b00441ee85c5004116200341b0046a1004200341c8026a41086a220a2009290300370300200320032903b0043703c80220032001410020081b220841016a3602b004200341c8026a4110200341b0046a4104100320034188016a41086a200341a8036a41086a29030037030020034188016a41106a200341a8036a41106a29030037030020034188016a41186a200341a8036a41186a290300370300200a200341e8016a41086a290300370300200341c8026a410d6a2002290000370000200320032903a80337038801200320032f0180013b018804200320034182016a2d00003a008a04200320032903e8013703c802411210272201450d02200141106a41002f00c0a7413b0000200141086a41002900b8a741370000200141002900b0a74137000020014112412410282202450d0320022008360012200341b0046a41186a22014200370300200341b0046a41106a22094200370300200341b0046a41086a220a4200370300200342003703b00420024116200341b0046a100020034190046a41186a200129030037030020034190046a41106a200929030037030020034190046a41086a200a290300370300200320032903b00437039004412010272201450d042001200329038801370000200141186a20034188016a41186a290300370000200141106a20034188016a41106a290300370000200141086a20034188016a41086a2903003700002001412041c00010282201450d0520012005370020200141286a2004370000200141c00041800110282201450d062001201b370050200120032f0188043b00302001200736003720012006360033200120032903c80237003b200141d8006a201c370000200141326a20032d008a043a0000200141c3006a200341c8026a41086a290300370000200141c8006a200341d5026a29000037000020034190046a4120200141e00010032001102920021029200341bc046a200836020041002106200341b0046a41086a41003a00002003410a3a00b00441b8d6c5004100200341b0046a1088010b0b2000200736020420002006360200200341a0056a24000f0b41124101102a000b41244101102a000b41204101102a000b41c0004101102a000b4180014101102a000bf90a03027f017e077f230041d0006b22042400200441306a41086a220542003703002004420037033041c1c8c100411d200441306a1004200441206a41086a20052903003703002004200429033037032002400240024002400240024002400240024002400240200441206a411041b8d6c50041004100100b417f470d00200441106a41888dc300410d1094012004290318420020042802101b210602402002a74101470d0020044184ccc100411a109401024020042903082006580d0020042802000d0b0b200441306a41086a22054200370300200442003703304184ccc100411a200441306a1004200441206a41086a2005290300370300200420042903303703202004200620014201867c370330200441206a4110200441306a410810030b200028020821052000280204210720002802002108200441306a41086a220042003703002004420037033041c1c8c100411d200441306a1004200441206a41086a2000290300370300200420042903303703202004410036023820044201370330410810272200450d01200442888080808001370234200420003602302000200637000020004108411010282200450d02200442908080808002370234200020013700082004200036023020042005360244200441c4006a200441306a103002402005450d002008200541286c6a21092004280234210a2004280238210b20082100034002400240200a200b6b4120490d00200b41206a21052004280230210c0c010b200b41206a2205200b490d0b200a410174220c20052005200c491b220d4100480d0b02400240200a0d00200d1027210c0c010b2004280230200a200d1028210c0b200c450d062004200d3602342004200c360230200d210a0b200c200b6a220b41186a200041186a290000370000200b41106a200041106a290000370000200b41086a200041086a29000037000020042005360238200b2000290000370000200041206a29030021010240200a20056b41074b0d00200541086a220b2005490d0b200a410174220d200b200b200d491b220b4100480d0b02400240200a0d00200b1027210c0c010b200c200a200b1028210c0b200c450d072004200b3602342004200c360230200b210a0b2004200541086a220b360238200c20056a20013700002009200041286a2200470d000b0b2004280234210c200428023821000240024020024201510d0002400240200c2000460d00200428023021050c010b200041016a22052000490d0b2000410174220c20052005200c491b220c4100480d0b0240024020000d00200c102721050c010b20042802302000200c102821050b2005450d082004200c360234200420053602300b2004200041016a220a360238200520006a41003a00000c010b02400240200c2000460d00200428023021050c010b200041016a22052000490d0a2000410174220c20052005200c491b220c4100480d0a0240024020000d00200c102721050c010b20042802302000200c102821050b2005450d082004200c360234200420053602300b2004200041016a220b360238200520006a41013a00000240200c200b6b41074b0d00200b41086a220a200b490d0a200c410174220d200a200a200d491b220a4100480d0a02400240200c0d00200a102721050c010b2005200c200a102821050b2005450d092004200a36023420042005360230200a210c0b2004200041096a220a3602382005200b6a20033700000b200441206a41102005200a10030240200c450d00200510290b2007450d0a200810290c0a0b200041046a280200450d09200028020010290c090b41084101102a000b41104101102a000b200d4101102a000b200b4101102a000b200c4101102a000b200c4101102a000b200a4101102a000b102b000b200041046a280200450d00200028020010290b200441d0006a24000b02000ba80102027f047e230041c0006b21020240200128020022032001280204470d00200041003602000f0b2001200341e0006a360200200241086a200341c8006a2900002204370300200241106a200341d0006a2900002205370300200241186a200341d8006a29000022063703002002200341c0006a290000220737030020002003360200200020073700042000410c6a2004370000200041146a20053700002000411c6a20063700000b290020004101360204200041086a200128020420012802006b41e0006e2201360200200020013602000bd10304037f027e067f027e23004180016b210302402001280200220420012802042205460d002001200441e0006a360200200341206a41186a200441d8006a2900002206370300200341206a41106a200441d0006a2900002207370300200341106a22082007370300200341086a2209200441c8006a290000370300200341186a220a20063703002003200441c0006a290000370300200341e0006a41186a220b200a290300370300200341e0006a41106a220c2008290300370300200341e0006a41086a220d20092903003703002003200329030037036002402002450d00200541a07f6a2105034020052004460d022001200441c0016a360200200441a0016a2900002106200441b8016a2900002107200441b0016a290000210e200341206a41086a200441a8016a290000220f3703002009200f3703002008200e370300200a20073703002003200637032020032006370300200b200a290300370300200c2008290300370300200d200929030037030020032003290300370360200441e0006a21042002417f6a22020d000b0b20002004360200200020032903603702042000410c6a200d290300370200200041146a200c2903003702002000411c6a200b2903003702000f0b200041003602000bf60505097f017e017f017e037f23004180026b2202240020024100360218200241186a2001280200220320012802042204410420044104491b220510ce041a2001200420056b22063602042001200320056a2205360200024002400240200441034b0d00200041003602000c010b20022802182107200242003702042002418883c000360200200241086a210802402007450d00200241a0016a41027221094100210a034020024200370318200241186a20052006410820064108491b220410ce041a2001200620046b3602042001200520046a36020002400240200641074d0d002002290318210b200241186a200110442002280218220c0d010b2000410036020020022802002002280204200228020810fc010c030b200229021c210d2002200b370310024002402002280200220e418883c000460d002002280204210f0c010b2009410041da0010cd041a200241186a410041840110cd041a41e4011027220e450d044100210f200e4100360200200e41046a200241a0016a41dc0010ce041a200e41e0006a200241186a41840110ce041a200241003602042002200e3602000b200a41016a210a024002400340200e41086a2105200e2f01062210410374210641002104024003402006450d01200241106a2005410810d0042203450d03200641786a2106200441016a2104200541086a21052003417f4a0d000b2004417f6a21100b0240200f450d00200f417f6a210f200e20104102746a41e4016a280200210e0c010b0b2002200b37022c20022008360228200220103602242002200e36021c20024100360218200220023602202002200d3702a4012002200c3602a001200241186a200241a0016a10fd010c010b200e2004410c6c6a220641e4006a220528020021042005200d370200200641e0006a220528020021062005200c3602002006450d002004450d00200610290b200a2007460d0120012802002105200128020421060c000b0b20002002290300370200200041086a20082802003602000b20024180026a24000f0b41e4014104102a000bd90303027f017e027f02402001450d00034020002802e40121002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d0020002001410c6c6a220441e4006a2902002105200441e0006a2802002104200141016a21010c010b02400240200028020022010d002003ad210541002106410021010c010b20003301044220862003ad842105410121060b200010292005a72103024002402005422088a7220720012f01064f0d00200121040c010b034002400240200128020022040d002003ad2105410021040c010b200641016a210620013301044220862003ad8421050b200110292005a72103200421012005422088a7220720042f01064f0d000b0b200741027420046a41e8016a280200210020042007410c6c6a220141e4006a2902002105200141e0006a280200210402402006417f6a2201450d00034020002802e40121002001417f6a22010d000b0b410021010b2004450d012002417f6a210202402005a7450d00200410290b20020d000b0b02402000418883c000460d0020002802002101200010292001450d0020012802002104200110292004450d00024020042802002201450d000340200410292001210420012802002200210120000d000b0b200410290b0be71207027f017e057f027e017f017e0a7f230041b0036b2202240020002802102203200328020041016a36020020002902142104200028020c2103200028020821052000280200210620002802042100200241f0016a41086a2207200141086a280200360200200220012902003703f001024002400240024020002f01062201410b490d00200241d0026a410272410041da0010cd041a200241386a410041840110cd041a0240024041e40110272208450d0020084100360200200841046a200241d0026a41dc0010ce041a200841e0006a200241386a41840110ce042107200241386a41086a2209200041b0016a280200360200200220002902a8013703382000413c6a330000210a2000413e6a310000210b20002d003f210c2000350038210d200841086a200041c0006a20002f010641796a220141037410ce04210e2007200041b4016a2001410c6c10ce042107200041063b0106200820013b0106200241d0026a41086a2009280200360200200220022903383703d002200d200a200b4210868442208684210a0240024020034107490d002003410374200e6a41506a200e200341796a22094103746a220e200141ffff037120096b41037410cf041a200e20043700002003410c6c20076a220341b87f6a200341ac7f6a2203200841066a22012f010020096b410c6c10cf041a200341086a200241f0016a41086a280200360200200320022903f0013702000c010b200041086a20034103746a220741086a2007200041066a22012f010020036b41037410cf041a20072004370000200041e0006a2003410c6c6a2207410c6a200720012f010020036b410c6c10cf041a200741086a200241f0016a41086a280200360200200720022903f0013702000b200120012f010041016a3b0100200241286a41086a220f200241d0026a41086a22102802002203360200200241086a221120033602002002200c3a0017200220022903d00222043703282002200a3e02102002200a4230883c00162002200a4220883d011420022004370300200229031021042000280200220c450d0320002f01042112200241d0026a410272211303402002200641016a22063602202002200c360224200f201128020036020020022002290300370328201241ffff03712109024002400240200c2f01062200410b490d002013410041da0010cd041a200241f0016a200241d0026a41dc0010ce041a200241386a410041b40110cd041a41940210272207450d0520074100360200200741046a200241f0016a41dc0010ce041a200741e0006a200241386a41b40110ce042103200c41386a290000210a200241386a41086a2214200c41b0016a2802003602002002200c41a8016a290200370338200741086a200c41c0006a200c2f0106220141796a220041037410ce0421152003200c41b4016a2000410c6c10ce042116200741e4016a200c4180026a2001417a6a220e41027410ce042117200c41063b0106200720003b01060240200e450d00410021002017210303402003280200220120003b010420012007360200200341046a2103200e200041016a2200470d000b0b20102014280200220036020020022002290338220b3703d002201420003602002002200b370338201241ffff037122034107490d0120152009417a6a22034103746a2015200941796a22004103746a220120072f010620006b41037410cf041a200120043700002009410c6c20166a220141b87f6a200141ac7f6a220120072f0106220e20006b410c6c10cf041a200141086a200f280200360200200120022903283702002007200e41016a22013b01062009410274221220176a416c6a201720034102746a220e200141ffff0371220920036b41027410cf041a200e200836020020092003490d02200720126a41cc016a2103034020032802002201200041016a22003b010420012007360200200341046a210320002009490d000c030b0b200c41086a2201200941016a22034103746a200120094103746a2201200020096b220741037410cf041a20012004370000200c2009410c6c6a220141ec006a200141e0006a220e2007410c6c10cf041a200141e8006a200241286a41086a280200360200200e2002290328370200200c200041016a22003b01062009410274200c41e4016a22016a41086a200120034102746a2201200041ffff0371220720036b41027410cf041a20012008360200201241ffff037120074f0d07200c2003417f6a22004102746a41e8016a2103034020032802002201200041016a22003b01042001200c360200200341046a210320002007490d000c080b0b200c41086a2200200941016a220e4103746a200020094103746a2200200c2f0106220120096b221241037410cf041a20002004370000200c41e0006a2009410c6c6a2200410c6a20002012410c6c10cf041a200041086a200f28020036020020002002290328370200200c200141016a22003b010620094102742217200c41e4016a22016a41086a2001200e4102746a2212200041ffff03712201200e6b41027410cf041a20122008360200200320014f0d00200c20176a41e8016a2100034020002802002203200941016a22093b01042003200c360200200041046a210020012009470d000b0b200241106a41086a2014280200220036020020112000360200200220022903382204370310200220043703000240200c28020022000d0020072108200a21040c050b200c2f010421122000210c200a2104200721080c000b0b41e4014104102a000b4194024104102a000b200020034103746a220941106a200941086a2209200120036b41037410cf041a2009200437000020002003410c6c6a220141ec006a200141e0006a220920002f010620036b410c6c10cf041a200141e8006a2007280200360200200920022903f001370200200020002f010641016a3b01060c010b200241d0026a410272410041da0010cd041a200241f0016a200241d0026a41dc0010ce041a200241386a410041b40110cd041a41940210272200450d0120004100360200200041046a200241f0016a41dc0010ce041a200041e0006a200241386a41b40110ce0421012000200528020022033602e401200520003602002005200528020441016a360204200341003b010420032000360200200120002f01062203410c6c6a22012002290300370200200020034103746a41086a2004370000200141086a200241086a280200360200200041e4016a200341016a22034102746a2008360200200020033b0106200820033b0104200820003602000b200241b0036a24000f0b4194024104102a000b840b02037f017e024002400240024002400240024002400240024002400240024020002802000e0400010203000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0c20024101742204200320032004491b22044100480d0c0240024020020d002004102721030c010b200128020020022004102821030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d0c20024101742200200420042000491b22004100480d0c0240024020020d002000102721020c010b200128020020022000102821020b2002450d0520012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0b20024101742204200320032004491b22044100480d0b0240024020020d002004102721030c010b200128020020022004102821030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d0b20024101742200200320032000491b22004100480d0b0240024020020d002000102721020c010b200128020020022000102821020b2002450d0620012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0a20024101742204200320032004491b22044100480d0a0240024020020d002004102721030c010b200128020020022004102821030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d0a20024101742200200420042000491b22004100480d0a0240024020020d002000102721020c010b200128020020022000102821020b2002450d0720012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0920024101742204200320032004491b22044100480d090240024020020d002004102721030c010b200128020020022004102821030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41043a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d0920024101742200200320032000491b22004100480d090240024020020d002000102721020c010b200128020020022000102821020b2002450d0820012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b20044101102a000b20004101102a000b20044101102a000b20004101102a000b20044101102a000b20004101102a000b20044101102a000b20004101102a000b102b000b130020004101360204200041d8cdc1003602000b340020004180f4c10036020420004100360200200041146a4107360200200041106a41a4d1c100360200200041086a42073702000b130020004101360204200041f8dcc1003602000bff0101057f230041106b2202240020024100360208200242013703002002410d36020c2002410c6a20021030024002400240024020022802042203200228020822046b410d490d002004410d6a2105200228020021030c010b2004410d6a22052004490d0220034101742206200520052006491b22064100480d020240024020030d002006102721030c010b200228020020032006102821030b2003450d0120022006360204200220033602000b20022005360208200320046a2204410029009ecc41370000200441056a41002900a3cc4137000020002002290300370200200041086a2002280208360200200241106a24000f0b20064101102a000b102b000ba504010b7f230041106b220324002003420037030820012002200341086a102020032003290308370300200120026a21040240024002400240200241086a220520024f0d00200341086a2106200321074100210841002105410121094100210a0340200841017421022006200741016a220b6b210c034020072d00002107024002400240024020082005470d002008417f417f200c200420016b6a22052005200c491b220541016a220d200d2005491b6a22052008490d072002200520052002491b22054100480d070240024020080d002005102721090c010b200920082005102821090b2009450d010b200920086a20073a00000240024002400240200a41ff01710e03010300010b20042001460d010c050b0240200b2006460d004100210a0c040b20042001470d040b200841016a21080c090b4101210a200b2006470d01200841016a21080c080b20054101102a000b200841016a2108200b21070c020b200841016a21084102210a200241026a21022001220741016a21010c000b0b0b410121092005450d0120054100480d002005102722090d0120054101102a000b102b000b410021080340200920086a200320086a2d00003a0000200841016a22084108470d000b024020020d00410821080c010b200920086a2107410021080340200720086a200120086a2d00003a00002002200841016a2208470d000b200420016b41086a21080b200020083602082000200536020420002009360200200341106a24000bad10030a7f027e047f23004190016b22032400024002400240024002400240411410272204450d00200441106a410028009c9342360000200441086a410029009493423700002004410029008c934237000020044114413410282204450d01200420012900003700142004412c6a200141186a290000370000200441246a200141106a2900003700002004411c6a200141086a290000370000200341e8006a41186a22054200370300200341e8006a41106a22064200370300200341e8006a41086a220742003703002003420037036820044134200341e8006a1000200341c0006a41186a2005290300370300200341c0006a41106a2006290300370300200341c0006a41086a20072903003703002003200329036837034020034100360268200341c0006a4120200341e8006a1005210820032802682209417f460d042008450d042003200936022420032008360220200341106a200341206a102e2003280210450d0320032802142105200341086a200341206a102e2003280208450d03200328020c21072003200341206a102e2003280200450d032003280204210a200341003a0068200341e8006a2003280220220b20032802242206410047220c10ce041a2006200c490d0220032006200c6b3602242003200b200c6a3602202006450d0320032d0068220c41014b0d034100210602400240200c0e020100010b410121060b200341e8006a200341206a10442003280268220c450d032003413c6a41026a220b2003418c016a41026a2d00003a0000200320032f008c013b013c200329026c220d422088210e02402009450d00200810290b200ea72108200da72109200341e8006a41026a200b2d00003a0000200320032f013c3b01680c050b41144101102a000b41344101102a000b200c2006103e000b418f89c3004133104e000b410221060b200410290240024020064102470d004101210441a2e1c1002105411121070c010b200341c0006a41026a200341e8006a41026a2d00003a0000200320032f01683b0140410021040b2003411c6a41026a200341c0006a41026a2d00003a0000200320032f01403b011c024002402004450d002000200536020420004101360200200041086a20073602000c010b2003418c016a41026a220b2003411c6a41026a2d00003a0000200320032f011c3b018c01024002400240024002400240024002400240200228025820054b0d0020092102200c21040c010b411510272204450d012004410d6a41002900ce9242370000200441086a41002900c99242370000200441002900c1924237000020044115413510282204450d02200420012900003700152004412d6a200141186a290000370000200441256a200141106a2900003700002004411d6a200141086a290000370000200341e8006a41186a22054200370300200341e8006a41106a22064200370300200341e8006a41086a220742003703002003420037036820044135200341e8006a1000200341c0006a41186a2005290300370300200341c0006a41106a2006290300370300200341c0006a41086a20072903003703002003200329036837034020034100360268200341c0006a4120200341e8006a1005210502400240024020032802682206417f460d002005450d002003200636022420032005360220200341e8006a200341206a10442003280268220f450d06200329026c210d02402006450d00200510290b20041029200341e8006a200f200d422088a72002108502200da72110200341e8006a41086a2802002107200328026c210520032802684101470d022000200536020420004101360200200041086a20073602002010450d01200f10290c010b20041029200041086a411a360200200041b3e1c100360204200041013602000b2009450d09200c10290c090b200341c0006a41026a221120034187016a2d00003a0000200320032f0085013b014020034184016a2d0000210620034180016a2802002108200341fc006a2802002102200341f8006a2802002104200341f4006a280200210a02402009450d00200c10290b2003418c016a41026a20112d00003a0000200320032f01403b018c012008417f4c0d044101210c02402008450d0020081027220c450d06200c2004200810ce041a0b200341206a41146a2008360200200341206a41106a20083602002003200a36022820032007360224200320053602202003200c36022c2003200641ff01714101463a0038411410272209450d06200941106a410028009c9342360000200941086a410029009493423700002009410029008c934237000020094114413410282209450d07200920012900003700142009412c6a200141186a290000370000200941246a200141106a2900003700002009411c6a200141086a290000370000200341e8006a41186a22014200370300200341e8006a41106a22114200370300200341e8006a41086a221242003703002003420037036820094134200341e8006a1000200341c0006a41186a2001290300370300200341c0006a41106a2011290300370300200341c0006a41086a2012290300370300200320032903683703402003412036026c2003200341c0006a360268200341206a200341e8006a105b2009102902402008450d00200c10290b2010450d00200f10290b20002005360204200020032f018c013b001d200041003602002000411c6a20063a0000200041186a2008360200200041146a2002360200200041106a20043602002000410c6a200a360200200041086a20073602002000411f6a200b2d00003a00000c070b41154101102a000b41354101102a000b418f89c3004133104e000b1039000b20084101102a000b41144101102a000b41344101102a000b20034190016a24000b9e6a04147f027e0d7f027e230041c0046b22042400200441b0036a20012002200310ff02200441b0036a41086a280200210520042802b40321060240024020042802b0034101470d002000200636020420004101360200200041086a20053602000c010b200441c4036a2802002207412c6c2108200441c8036a2802002109200441c0036a280200210a200441bc036a280200210b4100210c4100210102400340024020082001470d000c020b200b20016a21022001412c6a220d210120022d00004102470d000b200441d8006a200b200d6a41586a1080032004280258210c200428025c21010b4100210e20014100200c1b210f2007412c6c2108200c41b8d6c500200c1b21104100210102400340024020082001470d000c020b200b20016a21022001412c6a220d210120022d00004108470d000b200441d0006a200b200d6a41586a1080032004280250210e200428025421010b4100211120014100200e1b21122007412c6c2108200e41b8d6c500200e1b210d4100210102400340024020082001470d000c020b200b20016a21022001412c6a220c210120022d00004104470d000b200441c8006a200b200c6a41586a10800320042802482111200428024c21010b4100210e2001410020111b21132007412c6c2108201141b8d6c50020111b21144100210102400340024020082001470d000c020b200b20016a21022001412c6a220c210120022d00004103470d000b200441c0006a200b200c6a41586a1080032004280240210e200428024421010b4100211541002102024020014100200e1b2201450d00200141286c2108200e41b8d6c500200e1b41186a2101410021020340200220012d0000456a2102200141286a2101200841586a22080d000b0b200d201241146c6a21114100211202400240024003400240200d2011470d0020122015714101710d0341bb91c50041c38fc500201241017122011b2108411c411e20011b21010c020b41e18fc500210841382101200d41086a280200417c6a220e41024b0d01200d280200210c024002400240200e0e03000401000b41012115200c41b98fc500460d01200c28000041e3c2b1e306460d010c030b41012112200c41bd8fc500460d00200c41bd8fc500410610d0040d020b0240200d410c6a280200450d0041df90c5002108411321010c020b0240200d41106a280200220120026b220c20014d0d0041f290c5002108412a21010c020b41b990c5002108412621012013200c4d0d012014200c4102746a220c450d01419990c500210841202101200f200c280200220c4d0d012010200c4104746a220c450d01419c91c5002108411f2101200c2802080d01200d41146a210d200c2d000d4104460d000b0b200020083602040c010b2007412c6c2108410021010240034020082001460d01200b20016a21022001412c6a220d210120022d00004106470d000b200441386a200b200d6a41586a108003200428023c450d00200041878dc500360204411f21010c010b2007412c6c21082003280268210c410021010240034020082001460d01200b20016a21022001412c6a220d210120022d00004105470d000b200441306a200b200d6a41586a22011080030240200428023441014d0d0041182101200041a68dc5003602040c020b200441286a2001108003200428022c450d0020042802282201450d002001280200200c4d0d0041222101200041be8dc5003602040c010b2007412c6c2108410021010240034020082001460d01200b20016a21022001412c6a220d210120022d00004107470d000b200441206a200b200d6a41586a1080032004280220220120042802244104746a2108034020012008460d012001450d012001410c6a2102200141106a210120022d0000410271450d000b41322101200041ca8ec5003602040c010b2007412c6c2108410021010240034020082001460d01200b20016a21022001412c6a220d210120022d0000410b470d000b200b200d6a220141606a2802002202450d00200141586a280200220d200241186c6a210c0340200d220241186a210d2002280208410374210120022802002102024003402001450d01200141786a210120022d00042108200241086a21022008410271450d000b41312101200041998ec5003602040c030b200d200c470d000b0b2007412c6c2108410021010240034020082001460d01200b20016a21022001412c6a220d210120022d00004102470d000b200441186a200b200d6a41586a108003200428021c2201450d002004280218220220014104746a211103402002450d01200241106a210e200420022d000d22083a00b0032002280200220120022802086a210c410021024100200441b0036a20084104461b210d024003400240024002400240200241ff01710e03000102000b2001200c460d014100210220012108200141016a21010c020b2001200c460d034101210220012108200141016a21010c010b200d450d0241022102200d21084100210d0b20082d0000410271450d000b41392101200041e08dc5003602040c030b200e2102200e2011470d000b0b2007412c6c21084100210c4100210102400340024020082001470d000c020b200b20016a21022001412c6a220d210120022d00004102470d000b200441106a200b200d6a41586a1080032004280210210c200428021421010b4100210e20014100200c1b210f2007412c6c2108200c41b8d6c500200c1b21104100210102400340024020082001470d000c020b200b20016a21022001412c6a220d210120022d00004103470d000b200441086a200b200d6a41586a1080032004280208210e200428020c21010b200e41b8d6c500200e1b220220014100200e1b41286c6a210d4100211302400240024003400240024002400240024002400240024002400240024002400240024002400240024002400240024002402002200d460d00412d210141dff5c200210820022802084103470d1102402002280200220c419ab0c500460d00200c419ab0c500410310d0040d120b200241286a21114115210c41d8f4c200210e4114210141cbf5c200210802400240024020022d00180e040014011b000b4136210c41a2f4c200210e200f200228021c22014d0d1a201020014104746a2214450d1a2002280214210c200228020c210220092d00700d01200c410b470d01413821014193f5c2002108200241ab8ac500460d13200241ab8ac500410b10d004450d130c160b412f2101418cf6c200210820022802144106470d120240200228020c220c419cf4c200460d00200c419cf4c200410610d0040d130b02402013450d00411f2101200041bbf6c2003602040c1b0b2002411c6a2113201121020c160b4126210141edf4c2002108200c417d6a220c41134b0d110240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200c0e14002a2a2a0e042a062d0b0a2a011110172a2a0c15000b2002419db0c500460d292002419db0c500410310d004450d29419db0c5002002410310d0040d2941011027220e450d19200e41003a0000024020142d000c41e000470d0020142802084101470d002014280200211241002102034020024101460d03200e20026a2108201220026a210c200241016a2102200c2d000020082d0000460d000b0b200e1029200041edf4c2003602040c310b200241a888c500460d0141a888c5002002410f10d004450d010240200241b788c500460d0041b788c5002002410f10d0040d290b410110272212450d1a201241003a000020142d000c41e000470d2a20142802084101470d2a2014280200211541002102034020024101460d04201220026a210c201520026a210e200241016a2102200e2d0000200c2d0000460d000c2b0b0b20142d000d2101200e10292011210220014104460d2b0c2d0b41041027220e450d17200e4100360000024020142d000c41e000470d0020142802084104470d002014280200211241002102034020024104460d23200e20026a2108201220026a210c200241016a2102200c2d000020082d0000460d000b0b200e1029200041edf4c2003602040c2e0b0240200241c688c500460d00200229000042e5f0d1fbb5ac98b6ec00520d260b410710272212450d1820124100360003201241013a0002201241003b000020142d000c41e000470d2620142802084107470d262014280200211541002102034020024107460d03201220026a210c201520026a210e200241016a2102200e2d0000200c2d0000460d000c270b0b20142d000d220c4104460d262012102920112102200c41fb0171450d280c240b200241ce88c500460d0141ce88c5002002410a10d004450d01200241d888c500460d0241d888c5002002410a10d004450d020240200241e288c500460d0041e288c5002002410a10d0040d070b4126210c41edf4c200210e20142d000c41e000470d2a20142802080d2a2011210220142d000d4104460d270c2a0b20142d000d220c4104460d232012102920112102200c41fb0171450d260c220b410710272212450d1520124100360003201241013a0002201241003b0000024020142d000c41e000470d0020142802084107470d0020142802002115410021020340024020024107470d0020142d000d220c4104460d022012102920112102200c41fb0171450d280c240b201220026a210c201520026a210e200241016a2102200e2d0000200c2d0000460d000b0b20121029200041edf4c2003602040c290b41021027220e450d15200e41003b0000024020142d000c41e000470d0020142802084102470d002014280200211241002102034020024102460d1e200e20026a2108201220026a210c200241016a2102200c2d000020082d0000460d000b0b200e1029200041edf4c2003602040c280b0240200241f788c500460d0041f788c5002002410d10d0040d200b4126210c41edf4c200210e20142d000c41e000470d2620142802080d262011210220142d000d4104460d230c260b02402002418489c500460d00418489c5002002410c10d0040d1f0b4126210c41edf4c200210e20142d000c41e000470d2520142802080d252011210220142d000d4104460d220c250b02402002419b89c500460d00419b89c5002002411510d0040d1e0b4126210c41edf4c200210e20142d000c41e000470d2420142802080d242011210220142d000d4104460d210c240b0240200241b089c500460d0041b089c5002002410a10d0040d1d0b41021027220e450d12200e41003b0000024020142d000c41e000470d0020142802084102470d002014280200211241002102034020024102460d03200e20026a2108201220026a210c200241016a2102200c2d000020082d0000460d000b0b200e1029200041edf4c2003602040c240b0240200241ba89c500460d0041ba89c5002002410710d0040d1c0b4126210c41edf4c200210e20142d000c41e000470d2220142802080d222011210220142d000d4104460d1f0c220b20142d000d2101200e10292011210220014104460d1e0c200b200241c189c500460d0141c189c5002002411110d004450d010240200241f289c500460d0041f289c5002002411110d0040d1a0b41041027220e450d12200e4100360000024020142d000c41e000470d0020142802084104470d002014280200211241002102034020024104460d07200e20026a2108201220026a210c200241016a2102200c2d000020082d0000460d000b0b200e1029200041edf4c2003602040c210b200241d289c500460d0141d289c5002002411010d004450d01200241e289c500460d0241e289c5002002411010d004450d020240200241b68ac500460d0041b68ac5002002411010d0040d190b4126210c41edf4c200210e20142d000c41e000470d1f20142802080d1f2011210220142d000d4104460d1c0c1f0b41021027220e450d0e200e41003b0000024020142d000c41e000470d0020142802084102470d002014280200211241002102034020024102460d16200e20026a2108201220026a210c200241016a2102200c2d000020082d0000460d000b0b200e1029200041edf4c2003602040c1f0b4126210c41edf4c200210e20142d000c41e000470d1d20142802080d1d20142d000d22014104460d1d20112102200141fb0171450d1a0c1b0b41031027220e450d0d200e41003a0002200e41003b0000024020142d000c41e000470d0020142802084103470d002014280200211241002102034020024103460d15200e20026a2108201220026a210c200241016a2102200c2d000020082d0000460d000b0b200e1029200041edf4c2003602040c1d0b0240200241838ac500460d0041838ac5002002411610d0040d150b410210272212450d0e201241003b0000024020142d000c41e000470d0020142802084102470d002014280200211541002102034020024102460d04201220026a210c201520026a210e200241016a2102200e2d0000200c2d0000460d000b0b201210290c140b20142d000d2101200e10292011210220014104460d170c190b0240200241998ac500460d0041998ac5002002411210d0040d130b4126210c41edf4c200210e20142d000c41e000470d1920142802080d192011210220142d000d4104460d160c190b20142d000d2101201210292011210220014104460d150c170b024020130d0041002116410021170c100b024020132802040d00200041daf6c200360204413221010c190b024020132802002216201341086a28020022174d0d002000418cf7c20036020441c90021010c190b201720032802644d0d0f200041d5f7c20036020441c10021010c180b41014101102a000b41044101102a000b41014101102a000b41074101102a000b41074101102a000b41024101102a000b41024101102a000b41024101102a000b41034101102a000b41044101102a000b41024101102a000b20142d000d2101200e10292011210220014104460d080c0a0b20142d000d2101200e10292011210220014104460d070c090b20142d000d2101200e10292011210220014104460d060c080b20142d000d2101200e10292011210220014104460d050c070b20092903082118200441b8036a220242003703002004418883c0003602b4032009290310211920042018a7417f2018428080808010541b3602c00320042019a7417f2019428080808010541b3602b003200441b0036a4104722201410d1081032001410c108103200141071081032001410f108103200441b0036a410c6a220128020021132002280200211120042802c003211a20042802b403210c20042802b003211b200441c0036a220820073602002001200a3602002004200b3602b803200420053602b403200420063602b003200441e0006a200441b0036a108203024002400240410110272201450d00200141003a0000200420042f01b003220d3b01a002200841e0083b01002002428180808010370300200420013602b403200441013602b0032004200d3b01c203200441e0006a200441b0036a108303210b0240410310272202450d00200241026a41002d009cb0453a0000200241002f009ab0453b00000240410310272208450d00200841026a41002d009fb0453a0000200841002f009db0453b000002400240024002400240024002400240200441f4006a280200220d200441e0006a41106a2802002201470d00200141016a220d2001490d012001410174220e200d200d200e491b220dad42287e2218422088a70d012018a7220e4100480d010240024020010d00200e102721010c010b200428026c200141286c200e102821010b2001450d072004200d3602702004200136026c2004280274210d0b200428026c200d41286c6a220141003a00182001200836020c2001428380808030370204200120023602002001411c6a200b360200200141106a4283808080303702002004200428027441016a360274200441b0036a200441e0006a418c0110ce041a200441f0016a200441b0036a108403200441f0016a41106a280200220f412c6c210120042802f801220e41586a210202400340410021082001450d01200141546a2101200241286a210d2002412c6a220b2102200d2d00004103470d000b200b41086a2802002201450d00200141286c2102200b28020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200f412c6c2101200e41586a21022008417f6a210d02400340410021082001450d01200141546a2101200241286a210b2002412c6a22072102200b2d00004103470d000b200741086a2802002201450d00200141286c2102200728020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200f412c6c2101200e41606a21020240034041002107024020010d00410021010c020b200141546a2101200241206a210b2002412c6a22142102200b2d00004104470d000b201428020021010b0240024002400240200f450d00200120086a211c200e200f412c6c6a211d4100211e4100211403400240200e2d000041786a220141034b0d00024002400240024020010e0403010200030b200e28020c2201450d03200e280204220b200141186c6a211f0340201421200240200b22212802144104742202450d00202128020c21010340024020012d0000410b470d00200141046a2208280200220b200d490d002008200b41016a3602000b200141106a2101200241706a22020d000b0b02400240024002400240024002400240024002400240410810272201450d002001428080808010370200410410272222450d012021410c6a21082022410036020020212802142223450d0241002102410121122023210b4101210f4101211541012114024003402002200b4f0d01200241016a210502400240024002400240024002400240200828020020024104746a2d0000220b417e6a220241044b0d0020020e050101010302010b200b1085032124200c210b201121250340200b410c6a2107200b41086a2126200b2f010621104100210202400240034020102002460d01202620026a2106200741086a2107200241016a210202404100417f410120062d00002206202441ff0171220a4b1b2006200a461b41016a0e03000301000b0b2002417f6a21100b024020250d00201b210b0c070b2025417f6a2125200b20104102746a41ec006a280200210b0c010b0b201b210b20072802000e0404100304040b200b1085032124200c210b2011212502400340200b410c6a2107200b41086a2126200b2f010621104100210202400240034020102002460d01202620026a2106200741086a2107200241016a210202404100417f410120062d00002206202441ff0171220a4b1b2006200a461b41016a0e03000301000b0b2002417f6a21100b024020250d00201b210b0c030b2025417f6a2125200b20104102746a41ec006a280200210b0c010b0b201b210b024020072802000e0401110001010b200741046a280200210b0b2014417f6a220220144f0d0f200220144b0d0f200f202220024102746a28020022024d0d0f200120024103746a22072802042202200b6a220b2002490d0f2007200b360204024002402012200f460d00201221100c010b201241016a22022012490d1e2012410174220b20022002200b491b221041ffffffff01712010470d1e201041037422024100480d1e0240024020120d002002102721010c010b200120124103742002102821010b2001450d0c0b2001200f4103746a22024101360204200220053602000240024020152014460d00201521060c010b201541016a22022015490d1e2015410174220b20022002200b491b220641ffffffff03712006470d1e200641027422024100480d1e0240024020150d002002102721220c010b202220154102742002102821220b2022450d0d0b200f41016a2102202220144102746a200f360200201441016a21140c050b2014450d0e2014417f6a21140c030b2014450d0d024002402012200f460d00201221100c010b201241016a22022012490d1c2012410174220b20022002200b491b221041ffffffff01712010470d1c201041037422024100480d1c0240024020120d002002102721010c010b200120124103742002102821010b2001450d0c0b2001200f4103746a22024101360204200220053602000240024020152014417f6a220b460d00201521060c010b20154101742202201420142002491b220641ffffffff03712006470d1c200641027422024100480d1c0240024020150d002002102721220c010b202220154102742002102821220b2022450d0d0b200f41016a21022022200b4102746a200f3602000c030b200741046a280200210b0b2014417f6a220220144f0d0b200220144b0d0b200f202220024102746a28020022024d0d0b200120024103746a22072802042202200b6a220b2002490d0b2007200b3602040b20122110200f2102201521060b20052023460d0a2021280214210b201021122002210f20062115200521020c000b0b41a0b0c5002002200b1037000b41084104102a000b41044104102a000b200141086a210741012106410121100c060b20024104102a000b20024104102a000b20024104102a000b20024104102a000b02402012450d00200110290b4101211e024020150d00202021140c080b20221029202021140c070b2002450d01200120024103746a21070b20012114410121020340200129020021182004412d3a00b003200420184220883e02b403200820022018a76a220b417f6a200441b0036a1086032004410b3a00b0032004200d3602b4032008200b200441b0036a108603200241026a21022007200141086a2201470d000b201421010b02402010450d00200110290b02402006450d00202210290b202141186a210b02400240201a450d0020212802142202450d00202128020c210120024104742102410021080340024020012d0000412c470d002001410b3a0000200141046a201c360200200841016a21080b200141106a2101200241706a22020d000b4101211420080d010b202021140b200b201f470d000c040b0b200e2802042201200d490d02200e200141016a3602040c020b200e28020c2201450d01200e280204220b2001411c6c6a21070340200b2201411c6a210b024020012802182202450d0020012802102101200241027421020340024020012802002208200d490d002001200841016a3602000b200141046a21012002417c6a22020d000b0b200b2007460d020c000b0b200e28020c2201450d00200141146c2102200e28020441106a2101034002402001417c6a2802000d0020012802002208200d490d002001200841016a3602000b200141146a21012002416c6a22020d000b0b200e412c6a220e201d470d000b201e4101710d0220144101710d01200428028002210720042802f801210e0b200441fc016a280200211220042802f401211420042802f001210f410021100c020b200441b0036a41106a200441f0016a41106a280200360200200441b0036a41086a200441f0016a41086a290300370300200420042903f0013703b003200441a0026a200441b0036a108203411010272202450d07200241063a0000410110272201450d06200141003a000041011027220b450d05200b20012d00003a000020011029411010272208450d04200841063a000041f00010272201450d03200141063a00602001412c3b01502001200d3602442001410b3a0040200141d8003a00302001201a3602242001412d3a0020200141003602142001410f3a0010200141003602042001410f3a0000024020082d00004109470d00200828020841ffffffff0371450d00200828020410290b20081029024020022d00004109470d00200228020841ffffffff0371450d00200228020410290b20021029200441d4036a4287808080f000370200200441d0036a2001360200200441cc036a4100360200200441b0036a410c6a4281808080800c370200200441b8036a4101360200200441003602dc03200442043702c4032004200b3602b403200441013602b003200441a0026a200441b0036a108703200441b0036a200441a0026a418c0110ce041a20044188026a200441b0036a10840320044188026a410c6a280200211220044198026a2802002107200428028802210f200428028c022114200428029002210e410021100c010b200441fc016a280200211220042802f801210e02402004280280022207450d002007412c6c2102200e2101034020011088032001412c6a2101200241546a22020d000b0b41012110411a211441fc8ec500210f02402012450d00200e10290b0b02402011450d000340200c28026c210c2011417f6a22110d000b0b4100210841002101024003402013450d01024002402001200c2f01064f0d00200c20014103746a41146a2902002118200141016a21010c010b02400240200c28020022010d002008ad21184100210d410021010c010b200c3301044220862008ad8421184101210d0b200c10292018a72108024002402018422088a7220b20012f01064f0d00200121020c010b034002400240200128020022020d002008ad2118410021020c010b200d41016a210d20013301044220862008ad8421180b200110292018a72108200221012018422088a7220b20022f01064f0d000b0b200b41027420026a41f0006a280200210c2002200b4103746a41146a29020021180240200d417f6a2201450d000340200c28026c210c2001417f6a22010d000b0b410021010b2013417f6a21132018a74103470d000b0b0240200c418883c000460d00200c2802002101200c10292001450d0020012802002102200110292002450d00024020022802002201450d000340200210292001210220012802002208210120080d000b0b200210290b02402010450d002000200f36020420004101360200200041086a20143602000c160b200441a0026a41106a2007360200200441a0026a410c6a20123602002004200e3602a802200420143602a4022004200f3602a002200441b0036a200441a0026a2009280260108903024020042802b0034101470d000240200441b0036a41086a280200450d0020042802b40310290b200041968fc50036020420004101360200200041086a41233602000c160b200441c4036a2802002102200441b0036a41106a2802002112200441b0036a410c6a2802002110200441b8036a280200210d20042802b4032108200328025821032004410036029002200442013703880202400240410410272201450d002004410436028c022004200428029002220b41046a3602900220042001360288022001200b6a200836000002400240200428028c02220820042802900222016b4104490d0020042802880221080c010b200141046a220b2001490d0320084101742201200b200b2001491b22014100480d030240024020080d002001102721080c010b20042802880220082001102821080b2008450d022004200136028c02200420083602880220042802900221010b2004200141046a36029002200820016a200d36000020102002412c6c22016a210d024020020d00201021010c0e0b200141546a2113200441b0036a4101722102200441b0036a41276a210b200441b0036a41206a210c200441b0036a41186a210e200441b0036a41106a2107200441b0036a41086a211120102101034020012d00002108200b200141286a280000360000200c200141216a290000370300200e200141196a2900003703002007200141116a2900003703002011200141096a2900003703002004200141016a2900003703b00302402008410f470d002001412c6a21010c0f0b200441a0026a41276a2214200b280000360000200441a0026a41206a220f200c290300370300200441a0026a41186a200e2903002218370300200441a0026a41106a20072903002219370300200441a0026a41086a20112903002227370300200420042903b00322283703a00220022028370000200241086a2027370000200241106a2019370000200241186a2018370000200241206a200f290300370000200241276a2014280000360000200420083a00b003200441e0006a200441b0036a20044188026a108a0320042d00602208411a470d0d201341546a21132001412c6a2201200d470d000b200d21010c0d0b41044101102a000b20014101102a000b102b000b41f0004108102a000b41104108102a000b41014101102a000b41014101102a000b41104108102a000b200e4104102a000b41034101102a000b41034101102a000b41014101102a000b200428026421152004280268210302402013450d002001412c6a2101200441b0036a4101722102200441b0036a41276a210c200441b0036a41206a210e200441b0036a41186a2107200441b0036a41106a2111200441b0036a41086a2113034020012d0000210b200c200141286a280000360000200e200141216a2900003703002007200141196a2900003703002011200141116a2900003703002013200141096a2900003703002004200141016a2900003703b003200b410f460d01200441a0026a41276a2214200c280000360000200441a0026a41206a220f200e290300370300200441a0026a41186a20072903002218370300200441a0026a41106a20112903002219370300200441a0026a41086a20132903002227370300200420042903b00322283703a00220022028370000200241086a2027370000200241106a2019370000200241186a2018370000200241206a200f290300370000200241276a20142800003600002004200b3a00b003200441b0036a1088032001412c6a2201200d470d000b0b02402012450d00201010290b0240200428028c02450d0020042802880210290b024020084105470d002003450d00201510290b200041d791c50036020420004101360200200041086a41253602000c0a0b02402001200d460d00200441b0036a4101722102200441b0036a41276a210b200441b0036a41206a210c200441b0036a41186a210e200441b0036a41106a2107200441b0036a41086a2111034020012d00002108200b200141286a280000360000200c200141216a290000370300200e200141196a2900003703002007200141116a2900003703002011200141096a2900003703002004200141016a2900003703b0032008410f460d01200441a0026a41276a2213200b280000360000200441a0026a41206a2214200c290300370300200441a0026a41186a200e2903002218370300200441a0026a41106a20072903002219370300200441a0026a41086a20112903002227370300200420042903b00322283703a00220022028370000200241086a2027370000200241106a2019370000200241186a2018370000200241206a2014290300370000200241276a2013280000360000200420083a00b003200441b0036a1088032001412c6a2201200d470d000b0b02402012450d00201010290b2004280288022101200429028c0221182000411c6a41003a0000200041146a2018370200200041106a20013602002000410c6a2017360200200041086a2016360200200020033602042000411d6a20042f00f0013b0000200041003602002000411f6a200441f2016a2d00003a00000c090b200020083602040c070b20121029200041edf4c2003602040c060b20121029200041edf4c2003602040c050b02400240200241ec88c500460d0041ec88c5002002410b10d0040d010b4126210c41edf4c200210e20142d000c41e000470d0420142802080d042011210220142d000d4104460d010c040b024002402002419089c500460d00419089c5002002410b10d0040d010b4126210c41edf4c200210e20142d000c41e000470d0420142802080d042011210220142d000d4104460d010c040b0240200241ab8ac500460d0041ab8ac5002002410b10d0040d020b0240024041021027220c450d00200c41003b0000024020142d000c41e000470d0020142802084102470d002014280200210e41002101034020014102460d03200c20016a2102200e20016a2108200141016a210120082d000020022d0000460d000b0b200c10290c030b41024101102a000b20142d000d2101200c10292011210220014104460d000c020b0b41262101200041edf4c2003602040c020b4126210c41edf4c200210e0b200c21012000200e3602040b20004101360200200041086a200136020002402007450d00200b2007412c6c6a2100200b210c0340200c220d412c6a210c02400240200d2d00002201410d4b0d00024002400240024002400240024002400240024002400240024020010e0e0001020304050607080e090a0b0c000b200d41086a280200450d0d200d41046a28020010290c0d0b0240200d41086a280200450d00200d41046a28020010290b200d41146a280200450d0c200d41106a28020010290c0c0b0240200d410c6a2802002202450d00200d41046a28020021012002410474210203400240200141046a280200450d00200128020010290b200141106a2101200241706a22020d000b0b200d41086a280200450d0b200d28020410290c0b0b0240200d410c6a2802002202450d00200d41046a2802002101200241286c210203400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200241586a22020d000b0b200d41086a280200450d0a200d28020410290c0a0b200d41086a280200450d09200d41046a28020010290c090b200d41086a280200450d08200d41046a28020010290c080b200d41086a280200450d07200d41046a28020010290c070b0240200d410c6a2802002201450d00200d41046a280200220820014104746a210e0340024020082802082202450d0020082802002101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b200841106a21010240200841046a280200450d00200828020010290b200121082001200e470d000b0b200d41086a280200450d06200d28020410290c060b0240200d410c6a2802002202450d00200d41046a2802002101200241146c210203400240200141046a280200450d00200128020010290b200141146a21012002416c6a22020d000b0b200d41086a280200450d05200d28020410290c050b0240200d410c6a2802002201450d00200d41046a28020022082001411c6c6a210e034002402008410c6a2802002202450d0020082802042101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b0240200841086a280200450d00200828020410290b2008411c6a21010240200841146a280200450d00200828021010290b200121082001200e470d000b0b200d41086a280200450d04200d28020410290c040b0240200d410c6a2802002201450d00200d41046a2802002208200141186c6a210e03400240200841046a280200450d00200828020010290b0240200841146a2802002202450d00200828020c2101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b200841186a21010240200841106a280200450d00200828020c10290b200121082001200e470d000b0b200d41086a280200450d03200d28020410290c030b0240200d410c6a2802002201450d00200d41046a28020022082001411c6c6a210e034002402008410c6a2802002202450d0020082802042101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b0240200841086a280200450d00200828020410290b2008411c6a21010240200841146a280200450d00200828021010290b200121082001200e470d000b0b200d41086a280200450d02200d28020410290c020b0240200d41046a2d0000220141024b0d0002400240024020010e03000102000b200d410c6a280200450d04200d41086a28020010290c040b0240200d41146a2802002202450d00200d410c6a28020021012002410c6c21020340024020012802002208450d00200141046a280200450d00200810290b2001410c6a2101200241746a22020d000b0b200d41106a280200450d03200d28020c10290c030b0240200d41146a2802002201450d00200d410c6a280200220720014104746a211103402007220e41106a21070240200e2802042201450d000240200e410c6a2802002202450d002002410c6c21020340024020012802002208450d00200141046a280200450d00200810290b2001410c6a2101200241746a22020d000b0b200e41086a280200450d00200e28020410290b20072011470d000b0b200d41106a280200450d02200d28020c10290c020b200d410c6a280200450d01200d41086a28020010290c010b0240200d41086a280200450d00200d41046a28020010290b0240200d41146a2802002201450d00200d41186a280200450d00200110290b200d41246a280200450d00200d41206a28020010290b200c2000470d000b0b200a450d00200b10290b200441c0046a24000bb21c05017f027e037f027e097f23004180066b220224004202210302400240024002400240024002400240024002400240200129036822044202520d00200241186a20014198016a41880110ce041a0c010b20024186026a200141036a2d00003a0000200241e8016a41086a200141146a290200370300200241e8016a410d6a200141196a290000370000200220012f00013b0184022002200129020c3703e80120012d000021052001280204210620012802082107200241c0026a200141dc006a290000370300200241b8026a200141d4006a290000370300200241b0026a200141cc006a290000370300200241a8026a200141c4006a290000370300200241a0026a2001413c6a29000037030020024188026a41106a200141346a29000037030020024188026a41086a2001412c6a2900003703002002200129002437038802200241c8026a41086a20014188016a290300370300200241c8026a41106a20014190016a290300370300200220014180016a2903003703c802200141f8006a290300210820012903702109200241086a41888dc300410d10940142002103024020044201520d002009500d022002290310420020022802081b2203200820082003541b2203200320087d2009827d21030b41101027220a450d02200a41086a41002900bf8d43370000200a41002900b78d43370000200a411041201028220a450d03200a2003370010200241e0056a41186a220b4200370300200241e0056a41106a220c4200370300200241e0056a41086a220d4200370300200242003703e005200a4118200241e0056a1000200241c0056a41186a200b290300370300200241c0056a41106a200c290300370300200241c0056a41086a200d290300370300200220022903e0053703c005200241c0056a412041b8d6c50041004100100b210b200a102902400240200b417f470d004101210a411f210b41afb8c300210c0c010b200241b8036a2003108702200241be056a20022d00ba033a0000200241e8056a200241cb036a290000370300200241ed056a200241b8036a41186a290000370000200220022f01b8033b01bc05200220022900c3033703e00520022800bb03210c20022800bf03210b4100210a0b200241b8056a41026a220d200241bc056a41026a220e2d00003a000020024190056a41086a220f200241e0056a41086a221029030037030020024190056a41106a200241e0056a41106a290300370300200220022f01bc053b01b805200220022903e005370390050240200a450d002002419c036a41026a200241b4056a41026a2d00003a000020024180036a41086a200241a0036a41086a29030037030020024180036a41106a200241a0036a41106a290300370300200220022f01b4053b019c03200220022903a00337038003200041086a200b3602002000200c3602042000410136020020014198016a103d0c0a0b200241a0036a410d6a221120024190056a410d6a290000370000200241a0036a41086a220a200f2903003703002002419c036a41026a220f200d2d00003a000020024180036a41086a220d200a29030037030020024180036a41106a200241a0036a41106a290300370300200220022f01b8053b019c03200220022903900537038003200241fc026a41026a220a200f2d00003a0000200220022f019c033b01fc02200241e0026a410d6a220f20024180036a410d6a290000370000200241e0026a41086a2212200d29030037030020022002290380033703e002200241b8036a20014198016a41880110ce041a200241b8036a4198016a2008370300200241c8046a2009370300200241f7046a200b360000200241f3046a200c360000200241d8046a220b20022903c802370300200241e0046a200241c8026a41086a290300370300200241e8046a200241c8026a41106a290300370300200241f2046a200a2d00003a0000200241fb046a20022903e00237000020024183056a201229030037000020024188056a200f290000370000200220043703c004200220022f01fc023b01f004200e20024184026a41026a2d00003a00002010200241e8016a41086a290300370300200241e0056a410d6a2201200241e8016a410d6a290000370000200220022f0184023b01bc05200220022903e8013703e005024002400240200541ff01714101470d0020024180036a200641067610cc01200228028003210a024002402002280288032006413f7122014b0d00410021010c010b200241b8056a41026a200a20014105746a220141026a2d00003a0000200241a8036a200141136a290000370300200241ad036a200141186a290000370000200220012f00003b01b8052002200129000b3703a0032001280007210720012800032106410121010b0240200228028403450d00200a10290b20010d01410121014184efc2002106411521070c020b200241b8056a41026a200241bc056a41026a2d00003a0000200241a0036a41086a200241e0056a41086a29030037030020112001290000370000200220022f01bc053b01b805200220022903e0053703a0030b20024180036a41026a200241b8056a41026a2d00003a0000200241e0056a41086a200241a0036a41086a290300370300200241e0056a410d6a200241a0036a410d6a290000370000200220022f01b8053b018003200220022903a0033703e005410021010b200241b4056a41026a220a20024180036a41026a2d00003a0000200241c0056a41086a220c200241e0056a41086a290300370300200241c0056a41106a200241e0056a41106a290300370300200220022f0180033b01b405200220022903e0053703c00502402001450d002000200636020420004101360200200041086a2007360200200241b8036a103d0c0a0b200241a3056a200c290300370000200241a8056a200241cd056a290000370000200220022f01b4053b01900520022007360097052002200636009305200220022903c00537009b052002200a2d00003a009205200241003602e805200242013703e005200241b8036a200241e0056a10320240024020022903c0044201510d000240024020022802e40520022802e8052201460d0020022802e005210a0c010b200141016a220a2001490d0a20014101742206200a200a2006491b22064100480d0a0240024020010d0020061027210a0c010b20022802e005200120061028210a0b200a450d07200220063602e4052002200a3602e00520022802e80521010b2002200141016a3602e805200a20016a41003a00000c010b20022903d00420022903c8042204420c882203420120034201561b8021030240024020022802e405220a20022802e80522016b4102490d0020022802e005210a0c010b200141026a22062001490d09200a4101742201200620062001491b22014100480d0902400240200a0d0020011027210a0c010b20022802e005200a20011028210a0b200a450d07200220013602e4052002200a3602e00520022802e80521010b2002200141026a3602e805200a20016a2003a741047420047aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000b200b200241e0056a10542002200241e0046a3602c005200241c0056a200241e0056a10590240024020022802e405220c20022802e805220a6b4120490d0020022802e00521010c010b200a41206a2201200a490d08200c410174220a20012001200a491b22064100480d0802400240200c0d002006102721010c010b20022802e005200c2006102821010b2001450d07200220063602e405200220013602e00520022802e805210a2006210c0b2001200a6a2206200241f0046a220b290000370000200641186a200b41186a290000370000200641106a200b41106a290000370000200641086a200b41086a29000037000002400240200a41206a220a4180024b0d0002402001200a20024188026a20024190056a10140d004101210a0c020b2001200a20024188026a20024190056a101545210a0c010b200241e0056a41186a22064200370300200241e0056a41106a220b4200370300200241e0056a41086a220d4200370300200242003703e0052001200a200241e0056a1000200241c0056a41186a2006290300370300200241c0056a41106a200b290300370300200241c0056a41086a200d290300370300200220022903e0053703c0050240200241c0056a412020024188026a20024190056a10140d004101210a0c010b200241c0056a412020024188026a20024190056a101545210a0b0240200c450d00200110290b200a450d08200241c8016a41186a20024190056a41186a290300370300200241c8016a41106a20024190056a41106a290300370300200241c8016a41086a20024190056a41086a290300370300200241a0016a41086a200241d0046a290300370300200241a0016a41106a200241d8046a290300370300200241a0016a41186a200241e0046a290300370300200241c0016a200241e8046a29030037030020022002290390053703c8012002200241c8046a2903003703a00120022903c0042103200241186a200241b8036a41880110ce041a0b200041086a20022903c801370300200041286a2003370300200041306a20022903a001370300200041206a200241c8016a41186a290300370300200041186a200241c8016a41106a290300370300200041106a200241c8016a41086a290300370300200041386a200241a0016a41086a290300370300200041c0006a200241a0016a41106a290300370300200041c8006a200241a0016a41186a290300370300200041d0006a200241a0016a41206a290300370300200041d8006a200241186a41880110ce041a2000410036020020024180066a24000f0b41a8cec5001058000b41104101102a000b41204101102a000b20064101102a000b20014101102a000b20064101102a000b102b000b200041a981c20036020420004101360200200041086a411a360200200241b8036a103d0b20024180066a24000bfb0301067f230041e0006b22022400024002400240411010272203450d00200341086a41002900bf8d43370000200341002900b78d4337000020034110412010282203450d0120032001370010200241c0006a41186a22044200370300200241c0006a41106a22054200370300200241c0006a41086a220642003703002002420037034020034118200241c0006a1000200241186a2004290300370300200241106a2005290300370300200241086a2006290300370300200220022903403703002002410036024020024120200241c0006a100521060240024020022802402204417f460d00200241c0006a2004412020044120491b22056a41004100412020056b2005411f4b1b10cd041a200241c0006a2006200510ce041a2004411f4d0d04200241206a41186a2204200241c0006a41186a290000370300200241206a41106a2205200241c0006a41106a290000370300200241206a41086a2207200241c0006a41086a2900003703002002200229004037032020061029200041186a2004290300370000200041106a2005290300370000200041086a2007290300370000200020022903203700000c010b200041186a4200370000200041106a4200370000200041086a4200370000200042003700000b20031029200241e0006a24000f0b41104101102a000b41204101102a000b418f89c3004133104e000bf70603057f027e067f230041c0016b22022400200242003703800120024180016a2001280200220320012802042204410820044108491b220510ce041a2001200420056b22063602042001200320056a220536020002400240200441074b0d00200042003703000c010b2002290380012107200242003703800120024180016a20052006410820064108491b220410ce041a2001200620046b22033602042001200520046a22053602000240200641074d0d00200229038001210820024180016a2003412020034120491b22046a41004100412020046b2004411f4b1b10cd041a20024180016a2005200410ce041a2001200320046b22063602042001200520046a220536020002402003411f4b0d00200042003703000c020b200241e0006a41186a220320024180016a41186a2209290000370300200241e0006a41106a220a20024180016a41106a220b290000370300200241e0006a41086a220c20024180016a41086a220d290000370300200220022900800137036020024180016a200641c000200641c000491b22046a4100410041c00020046b2004413f4b1b10cd041a20024180016a2005200410ce041a2001200620046b3602042001200520046a36020002402006413f4b0d00200042003703000c020b200241386a220120024180016a41386a290000370300200241306a220420024180016a41306a290000370300200241286a220520024180016a41286a290000370300200241206a220620024180016a41206a290000370300200241186a220e2009290000370300200241106a2209200b290000370300200241086a220b200d290000370300200241c0006a41086a220d200c290300370300200241c0006a41106a220c200a290300370300200241c0006a41186a220a2003290300370300200220022900800137030020022002290360370340200041106a200837030020002007370308200041186a2002290340370300200041206a200d290300370300200041286a200c290300370300200041306a200a290300370300200041386a2002290300370300200041c0006a200b290300370300200041c8006a2009290300370300200041d0006a200e290300370300200041d8006a2006290300370300200041e0006a2005290300370300200041e8006a2004290300370300200041f0006a2001290300370300200042013703000c010b200042003703000b200241c0016a24000b860204017f017e037f017e230041c0006b2203240042002104200341206a41186a22054200370300200341206a41106a22064200370300200341206a41086a220742003703002003420037032020012002200341206a1000200341186a2005290300370300200341106a2006290300370300200341086a2007290300370300200320032903203703002003410036022020034120200341206a1005210202400240024020032802202201417f470d000c010b20034200370320200341206a20022001410820014108491b10ce041a200141074d0d012003290320210820021029420121040b2000200837030820002004370300200341c0006a24000f0b418f89c3004133104e000bc80101027f230041206b22022400200241106a41086a220342003703002002420037031020002001200241106a1004200241086a2003290300370300200220022903103703002002410036021020024110200241106a10052101024002400240024020022802102200417f470d00410221000c010b200241003a0010200241106a20012000410047220310ce041a20002003490d012000450d0220022d001021002001102920024110100c0b200241206a240020000f0b20032000103e000b418f89c3004133104e000b870802087f0a7e230041e0026b22022400200241386a2001280200200128020428020c1100000240024020022903384201520d0020024198026a4101722103200241386a41086a2104200241ab016a21050340200241a8016a41186a2206200441186a290000370300200241a8016a41106a2207200441106a290000370300200241a8016a41086a2208200441086a290000370300200220042900003703a80120024198026a200241a8016a108c02024002400240024020022d0098024101460d00200241003602e8010c010b200241c0026a41186a200341186a290000370300200241c0026a41106a200341106a290000370300200241c0026a41086a200341086a290000370300200220032900003703c002200241c8016a200241c0026a108d0220022802e80122090d010b4200210a4200210b0c010b200241c8016a41086a290300210b20022903c801210a20022802ec01450d00200910290b20024198026a41086a2008290300220c37030020024198026a41106a2007290300220d37030020024198026a41186a2006290300220e370300200220022903a801220f37039802200241c8016a41086a2207200c370300200241c8016a41106a2208200d370300200241c8016a41186a2209200e3703002002200f3703c801200241206a41b18ac0004116108601200241106a2002290328200241206a41106a290300427f420010d4042002200a200b20022903104200200228022022061b220c4201200c420156200241106a41086a290300420020061b220c420052200c501b22061b200c420020061b10d404024002402002290300220c50450d00410221060c010b200241c0026a41186a2009290300370300200241c0026a41106a2008290300370300200241c0026a41086a2007290300370300200220022903c8013703c002200220022800a8013602a001200220052800003600a3014200211041002106200c2111200a2112200b21130b20024180016a41086a200241c0026a41086a29030037030020024180016a41106a200241c0026a41106a29030037030020024180016a41186a200241c0026a41186a290300370300200220022903c00237038001200220022802a001360278200220022800a30136007b024020064102460d002000201137031020004200370308200042003703002000200229038001370320200020063a004020002002280278360041200041186a2010370300200041d0006a2013370300200041c8006a2012370300200041c4006a200228007b360000200041286a20024188016a290300370300200041306a20024190016a290300370300200041386a20024180016a41186a2903003703000c030b200241386a2001280200200128020428020c11000020022903384201510d000b0b200041023a00400b200241e0026a24000bbd0402087f047e230041e0006b22022400024002400240410e10272203450d00200341066a41002900c7a244370000200341002900c1a2443700002003410e412e10282203450d012003200129000037000e200341266a200141186a2900003700002003411e6a200141106a290000370000200341166a200141086a290000370000200241206a41186a22014200370300200241206a41106a22044200370300200241206a41086a22054200370300200242003703202003412e200241206a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002002410036024020024120200241c0006a100521050240024020022802402201417f460d00200241206a2001412020014120491b22046a41004100412020046b2004411f4b1b10cd041a200241206a2005200410ce041a2001411f4d0d04200241c0006a41186a2201200241206a41186a2204290300370300200241c0006a41106a2206200241206a41106a2207290300370300200241c0006a41086a2208200241206a41086a2209290300370300200220022903203703402005102920042001290300220a37030020072006290300220b37030020092008290300220c37030020022002290340220d370320200041013a00002000200d370001200041096a200c370000200041116a200b370000200041196a200a3700000c010b200041003a00000b20031029200241e0006a24000f0b410e4101102a000b412e4101102a000b418f89c3004133104e000bee05010c7f230041d0016b2202240002400240024002400240410e10272203450d00200341066a410029009fa34437000020034100290099a3443700002003410e412e10282203450d012003200129000037000e200341266a200141186a2900003700002003411e6a200141106a290000370000200341166a200141086a290000370000200241f8006a41186a22014200370300200241f8006a41106a22044200370300200241f8006a41086a22054200370300200242003703782003412e200241f8006a1000200241d8006a41186a2001290300370300200241d8006a41106a2004290300370300200241d8006a41086a20052903003703002002200229037837035820024100360278200241d8006a4120200241f8006a1005210420022802782201417f460d03200220013602cc01200220043602c801200241f8006a200241c8016a10d3032002280298012205450d02200241386a41186a2206200241f8006a41186a290300370300200241386a41106a2207200241f8006a41106a290300370300200241386a41086a2208200241f8006a41086a290300370300200241086a41086a2209200241f8006a412c6a290200370300200241086a41106a220a200241f8006a41346a290200370300200241086a41186a220b200241f8006a413c6a290200370300200241286a220c200241f8006a41c4006a290200370300200241306a220d200241f8006a41cc006a280200360200200220022903783703382002200229029c0137030802402001450d00200410290b200020022903383703002000200536022020002002290308370224200041186a2006290300370300200041106a2007290300370300200041086a20082903003703002000412c6a2009290300370200200041346a200a2903003702002000413c6a200b290300370200200041c4006a200c290300370200200041cc006a200d2802003602000c040b410e4101102a000b412e4101102a000b418f89c3004133104e000b200041003602200b20031029200241d0016a24000b8e0a03077f037e047f230041d0016b22022400200241b0016a41186a22034200370300200241b0016a41106a22044200370300200241b0016a41086a22054200370300200242003703b001200241b0016a2001280200220620012802042207412020074120491b220810ce041a2001200720086b3602042001200620086a360200024002402007411f4b0d00410021070c010b20024190016a41186a2003290300220937030020024190016a41106a2004290300220a37030020024190016a41086a2005290300220b370300200241f0006a41086a200b370300200241f0006a41106a200a370300200241f0006a41186a2009370300200220022903b00122093703900120022009370370410121070b200241b0016a41186a2208200241f0006a41186a290300370300200241b0016a41106a2206200241f0006a41106a290300370300200241b0016a41086a2203200241f0006a41086a290300370300200220022903703703b0010240024020070d00200041003602080c010b200241306a41186a2008290300370300200241306a41106a2006290300370300200241306a41086a2003290300370300200220022903b00137033020022001105202402002290300a70d00200041003602080c010b20022903082109200241b0016a41186a22044200370300200241b0016a41106a22054200370300200241b0016a41086a220c4200370300200242003703b001200241b0016a2001280200220320012802042207412020074120491b220810ce041a2001200720086b22063602042001200320086a220836020002402007411f4b0d00200041003602080c010b200241d0006a41086a200c290300370300200241d0006a41106a2005290300370300200241d0006a41186a2004290300370300200220022903b001370350200241b0016a2006412020064120491b22076a41004100412020076b2007411f4b1b10cd041a200241b0016a2008200710ce041a2001200620076b3602042001200820076a36020002402006411f4b0d00200041003602080c010b200241f0006a41086a2203200241b0016a41086a2207290300370300200241f0006a41106a2204200241b0016a41106a2208290300370300200241f0006a41186a2205200241b0016a41186a2206290300370300200220022903b001370370200241106a200110430240200228021022010d00200041003602080c010b2007200241306a41086a2903003703002008200241306a41106a2903003703002006200241306a41186a29030037030020024190016a41086a220c200241d0006a41086a29030037030020024190016a41106a220d200241d0006a41106a29030037030020024190016a41186a220e200241d0006a41186a290300370300200220022903303703b00120022002290350370390012002290214210a200241106a41186a220f2005290300370300200241106a41106a22052004290300370300200241106a41086a22042003290300370300200220022903703703102000200a37020c2000200136020820002009370300200041146a20022903b0013702002000411c6a2007290300370200200041246a20082903003702002000412c6a2006290300370200200041346a2002290390013702002000413c6a200c290300370200200041c4006a200d290300370200200041cc006a200e290300370200200041ec006a200f290300370200200041e4006a2005290300370200200041dc006a2004290300370200200041d4006a20022903103702000b200241d0016a24000bcb2a04057f027e027f047e230041e0046b22022400200241003a00d402200241d4026a2001280200220320012802042204410047220510ce041a0240024002400240024002400240024002400240024020042005490d002001200420056b22063602042001200320056a2205360200024020040d00200041123a00000c0b0b024020022d00d402220441104b0d000240024002400240024002400240024002400240024002400240024002400240024020040e11000102030405060708090a0b0c0d0e0f10000b200241d8036a2001103c20022802d8032104200241d4026a200241d8036a41047241840110ce041a024020044112470d00200041123a00000c1c0b200241d0016a200241d4026a41840110ce041a41880110272205450d1220052004360200200541046a200241d0016a41840110ce041a20022001105302402002290300a70d00200041123a00002005103d200510290c1c0b200241106a290300210720022903082108200041013a0000200020022f00b0013b0001200041086a2008370300200041046a2005360200200041186a2002290358370300200041106a2007370300200041036a200241b2016a2d00003a0000200041206a200241d8006a41086a290300370300200041286a200241d8006a41106a290300370300200041306a200241d8006a41186a2903003703000c1b0b200241186a2001102e024020022802180d00200041123a00000c1b0b200228021c2101200041023a0000200020022f00d4023b0001200041046a2001360200200041086a20022903d803370300200041036a200241d4026a41026a2d00003a0000200041106a200241d8036a41086a290300370300200041186a200241d8036a41106a290300370300200041206a200241d8036a41186a290300370300200041286a200241d8036a41206a290300370300200041306a200241d8036a41286a2903003703000c1a0b200241206a2001102e024020022802200d00200041123a00000c1a0b20022802242106200241003a00d402200241d4026a2001280200220320012802042204410047220510ce041a20042005490d112001200420056b3602042001200320056a360200024002402004450d0020022d00d402220141ff007122044106490d010b200041123a00000c1a0b200041033a0000200041046a2006360200200041026a20043a0000200020014107763a0001200041086a20022903d803370300200041106a200241d8036a41086a290300370300200041186a200241d8036a41106a290300370300200041206a200241d8036a41186a290300370300200041286a200241d8036a41206a290300370300200041306a200241d8036a41286a2903003703000c190b200241286a2001102e024020022802280d00200041123a00000c190b200228022c2106200241003a00d402200241d4026a2001280200220320012802042204410047220510ce041a20042005490d112001200420056b3602042001200320056a360200024002402004450d0020022d00d402220141ff007122044106490d010b200041123a00000c190b200041043a0000200041046a2006360200200041026a20043a0000200020014107763a0001200041086a20022903d803370300200041106a200241d8036a41086a290300370300200041186a200241d8036a41106a290300370300200041206a200241d8036a41186a290300370300200041286a200241d8036a41206a290300370300200041306a200241d8036a41286a2903003703000c180b200241d8036a2001103c20022802d8032104200241d4026a200241d8036a41047241840110ce041a024020044112470d00200041123a00000c180b200241d0016a200241d4026a41840110ce041a41880110272205450d1120052004360200200541046a200241d0016a41840110ce041a200241003a00d402200241d4026a2001280200220920012802042204410047220310ce041a20042003490d122001200420036b22063602042001200920036a2203360200024002402004450d0020022d00d402220a4103490d010b200041123a00000c170b200242003703d803200241d8036a20032006410820064108491b220410ce041a2001200620046b22093602042001200320046a22043602000240200641074b0d00200041123a00000c170b20022903d8032107200242003703d803200241d8036a20042009410820094108491b220310ce041a2001200920036b3602042001200420036a3602000240200941074b0d00200041123a00000c170b200041106a20022903d803370300200041086a2007370300200041046a20053602002000200a3a0001200041053a0000200041186a2002290358370300200041206a200241d8006a41086a290300370300200041286a200241d8006a41106a290300370300200041306a200241d8006a41186a2903003703000c170b200241003602d402200241d4026a20052006410420064104491b220410ce041a2001200620046b3602042001200520046a3602000240200641034b0d00200041123a00000c170b20022802d4022101200041063a0000200020022f00d0013b0001200041046a2001360200200041086a20022903d803370300200041036a200241d2016a2d00003a0000200041106a200241d8036a41086a290300370300200041186a200241d8036a41106a290300370300200041206a200241d8036a41186a290300370300200041286a200241d8036a41206a290300370300200041306a200241d8036a41286a2903003703000c160b200241d8036a2001103c20022802d8032101200241d4026a200241d8036a41047241840110ce041a024020014112470d00200041123a00000c160b200241d0016a200241d4026a41840110ce041a41880110272204450d1120042001360200200441046a200241d0016a41840110ce041a200041073a0000200020022f00b0013b0001200041036a200241b2016a2d00003a0000200041046a2004360200200041086a2002290358370300200041106a200241d8006a41086a290300370300200041186a200241d8006a41106a290300370300200041206a200241d8006a41186a290300370300200041286a200241d8006a41206a290300370300200041306a200241d8006a41286a2903003703000c150b200241d8036a2001103c20022802d8032101200241d4026a200241d8036a41047241840110ce041a024020014112470d00200041123a00000c150b200241d0016a200241d4026a41840110ce041a41880110272204450d1120042001360200200441046a200241d0016a41840110ce041a200041083a0000200020022f00b0013b0001200041036a200241b2016a2d00003a0000200041046a2004360200200041086a2002290358370300200041106a200241d8006a41086a290300370300200041186a200241d8006a41106a290300370300200041206a200241d8006a41186a290300370300200041286a200241d8006a41206a290300370300200041306a200241d8006a41286a2903003703000c140b41002109200241d4026a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241d4026a2005200410ce041a2001200620046b22033602042001200520046a220436020002402006411f4d0d00200241d0016a41186a200241d4026a41186a2900002207370300200241d0016a41106a200241d4026a41106a2900002208370300200241d0016a41086a200241d4026a41086a290000220b370300200241d8006a41086a200b370300200241d8006a41106a2008370300200241d8006a41186a2007370300200220022900d40222073703d00120022007370358410121090b200241d8036a41186a2205200241d8006a41186a290300370300200241d8036a41106a2206200241d8006a41106a290300370300200241d8036a41086a220a200241d8006a41086a290300370300200220022903583703d803024020090d00200041123a00000c140b200241b0016a41186a2005290300370300200241b0016a41106a2006290300370300200241b0016a41086a200a290300370300200220022903d8033703b001200242003703d803200241d8036a20042003410820034108491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341074b0d00200041123a00000c140b20022903d8032107200242003703d803200241d8036a20042006410820064108491b220510ce041a2001200620056b3602042001200420056a3602000240200641074b0d00200041123a00000c140b20024190016a41086a200241b0016a41086a290300220837030020024190016a41106a200241b0016a41106a290300220b37030020024190016a41186a200241b0016a41186a290300220c370300200220022903b001220d3703900120022903d803210e200041093a00002000200d370001200041096a2008370000200041116a200b370000200041196a200c370000200041216a200228008901360000200041246a2002418c016a280000360000200041306a200e370300200041286a20073703000c130b41002103200241d4026a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241d4026a2005200410ce041a2001200620046b3602042001200520046a36020002402006411f4d0d00200241d0016a41186a200241d4026a41186a2900002207370300200241d0016a41106a200241d4026a41106a2900002208370300200241d0016a41086a200241d4026a41086a290000220b370300200241d8006a41086a200b370300200241d8006a41106a2008370300200241d8006a41186a2007370300200220022900d40222073703d00120022007370358410121030b200241d8036a41186a2201200241d8006a41186a290300370300200241d8036a41106a2204200241d8006a41106a290300370300200241d8036a41086a2205200241d8006a41086a290300370300200220022903583703d803024020030d00200041123a00000c130b200241b0016a41186a20012903002207370300200241b0016a41106a20042903002208370300200241b0016a41086a2005290300220b370300200220022903d803220c3703b0012000410a3a00002000200c370001200041096a200b370000200041116a2008370000200041196a2007370000200041216a200229009001370000200041296a20024190016a41086a290000370000200041306a2002419f016a2900003700000c120b200241306a2001102e024020022802300d00200041123a00000c120b200228023421012000410b3a0000200020022f00d4023b0001200041046a2001360200200041086a20022903d803370300200041036a200241d6026a2d00003a0000200041106a200241d8036a41086a290300370300200041186a200241d8036a41106a290300370300200041206a200241d8036a41186a290300370300200041286a200241d8036a41206a290300370300200041306a200241d8036a41286a2903003703000c110b200241c8006a2001105202402002290348a70d00200041123a00000c110b20022903502107200241c0006a2001102e024020022802400d00200041123a00000c110b20022802442104200241386a2001102e024020022802380d00200041123a00000c110b200228023c21012000410c3a0000200020022f00d4023b0001200041106a2007370300200041086a2001360200200041046a2004360200200041186a20022903d803370300200041036a200241d6026a2d00003a0000200041206a200241d8036a41086a290300370300200041286a200241d8036a41106a290300370300200041306a200241d8036a41186a2903003703000c100b200241d4026a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241d4026a2005200410ce041a2001200620046b3602042001200520046a36020002402006411f4b0d00200041123a00000c100b200241d8006a41086a200241d4026a41086a2900002208370300200241d8006a41106a200241d4026a41106a290000220b370300200241d8006a41186a200241d4026a41186a290000220c370300200220022900d40222073703d803200220073703582000410d3a000020002007370001200041096a2008370000200041116a200b370000200041196a200c370000200041216a20022900b001370000200041296a200241b0016a41086a290000370000200041306a200241bf016a2900003700000c0f0b2000410e3a00000c0e0b200241d4026a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241d4026a2005200410ce041a2001200620046b3602042001200520046a36020002402006411f4b0d00200041123a00000c0e0b200241d8006a41086a200241d4026a41086a2900002208370300200241d8006a41106a200241d4026a41106a290000220b370300200241d8006a41186a200241d4026a41186a290000220c370300200220022900d40222073703d803200220073703582000410f3a000020002007370001200041096a2008370000200041116a200b370000200041196a200c370000200041216a20022900b001370000200041296a200241b0016a41086a290000370000200041306a200241b0016a410f6a2900003700000c0d0b200241d4026a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241d4026a2005200410ce041a2001200620046b22033602042001200520046a220436020002402006411f4b0d00200041123a00000c0d0b200241d8006a41086a200241d4026a41086a290000370300200241d8006a41106a200241d4026a41106a290000370300200241d8006a41186a200241d4026a41186a290000370300200220022900d40222073703d80320022007370358200241003a00d402200241d4026a20042003410047220510ce041a20032005490d0a2001200320056b3602042001200420056a360200024002402003450d0020022d00d40222014106490d010b200041123a00000c0d0b200241b0016a41186a200241d8006a41186a2903002207370300200241b0016a41106a200241d8006a41106a2903002208370300200241b0016a41086a200241d8006a41086a290300220b37030020022002290358220c3703b001200041103a00002000200c370001200041096a200b370000200041116a2008370000200041196a2007370000200041216a20013a0000200041226a2002290190013701002000412a6a20024190016a41086a290100370100200041306a2002419e016a2901003701000c0c0b200041113a00000c0b0b200041123a00000c0a0b20052004103e000b4188014108102a000b20052004103e000b20052004103e000b4188014108102a000b20032004103e000b4188014108102a000b4188014108102a000b20052003103e000b2005103d200510290b200241e0046a24000b890a02057f047e230041d0036b22022400200241003a00c802200241c8026a2001280200220320012802042204410047220510ce041a02400240024002400240024020042005490d002001200420056b22063602042001200320056a2205360200024020040d00200041053a00000c060b02400240024020022d00c802220441034b0d0002400240024020040e0400010204000b200241c0016a2001102d20022802c00122010d04200041053a00000c0a0b200241c8026a2001103c20022802c8022101200241c0016a200241c8026a41047241840110ce041a024020014112470d00200041053a00000c0a0b200241386a200241c0016a41840110ce041a41880110272204450d0520042001360200200441046a200241386a41840110ce041a200041023a0000200020022f00353b0001200041036a200241356a41026a2d00003a0000200041046a2004360200200041086a2002290214370200200041106a200241146a41086a290200370200200041186a200241146a41106a290200370200200041206a200241146a41186a2902003702000c090b20022001102e024020022802000d00200041053a00000c090b20022802042105200241c8026a2001103c20022802c8022101200241c0016a200241c8026a41047241840110ce041a024020014112470d00200041053a00000c090b200241386a200241c0016a41840110ce041a41880110272204450d0520042001360200200441046a200241386a41840110ce041a200041033a0000200020022f00353b0001200041036a200241376a2d00003a0000200041086a2004360200200041046a20053602002000410c6a2002290214370200200041146a200241146a41086a2902003702002000411c6a200241246a290200370200200041246a2002412c6a2802003602000c080b200041053a00000c070b200241c8026a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200241c8026a2005200410ce041a2001200620046b3602042001200520046a3602002006411f4d0d05200241c0016a41186a200241c8026a41186a290000370300200241c0016a41106a200241c8026a41106a290000370300200241c0016a41086a200241c8026a41086a290000370300200220022900c8023703c001200241086a2001102e024020022802080d00200041053a00000c070b200228020c2106200241003a00c802200241c8026a2001280200220320012802042204410047220510ce041a20042005490d042001200420056b3602042001200320056a360200024020040d00200041053a00000c070b200241386a41086a200241c0016a41086a2903002207370300200241386a41106a200241c0016a41106a2903002208370300200241386a41186a200241c0016a41186a2903002209370300200220022903c001220a37033820022d00c8022101200041043a00002000200a370001200041096a2007370000200041116a2008370000200041196a2009370000200041246a2006360200200041216a20013a00000c060b20022902c4012107200041013a0000200020022f00383b0001200041086a2007370000200041046a2001360000200041106a20022902c802370200200041036a2002413a6a2d00003a0000200041186a200241c8026a41086a290200370200200041206a200241c8026a41106a2902003702000c050b20052004103e000b4188014108102a000b4188014108102a000b20052004103e000b200041053a00000b200241d0036a24000bc12308057f017e017f027e017f037e087f027e230041f0056b22022400200241003a0070200241f0006a2001280200220320012802042204410047220510ce041a02400240024002400240024020042005490d002001200420056b22063602042001200320056a2205360200024020040d00200041073a00000c060b02400240024002400240024020022d0070220441054b0d000240024002400240024020040e06000102030406000b200241d8026a200110f10220024180056a200241d8026a41f00010ce041a200220022800c9033602d0032002200241cc036a2800003600d303024020022d00c80322014102470d00200041073a00000c100b200241e8016a20024180056a41f00010ce041a200220022800d3033600e304200220022802d0033602e004200241f7006a200241e8016a41f00010ce041a200041013a0000200041016a200241f0006a41f70010ce041a200041f8006a20013a0000200041f9006a20022802e004360000200041fc006a20022800e3043600000c0f0b200241086a2001105202402002290308a70d00200041073a00000c0f0b20022903102107200241f0006a20011044200228027022010d05200041073a00000c0e0b200241f0006a2001105020024180056a41086a2204200241f9006a29000037030020024180056a41106a220520024181016a29000037030020024180056a41186a220320024189016a29000037030020024180056a411f6a220620024190016a2800003600002002200229007137038005024020022d007022084102470d00200041073a00000c0e0b200241e8016a411f6a2006280000360000200241e8016a41186a2003290300370300200241e8016a41106a2005290300370300200241e8016a41086a200429030037030020022002290380053703e801200241286a2001105302402002290328a70d00200041073a00000c0e0b200241286a41106a290300210720022903302109200241186a2001105202402002290318a70d00200041073a00000c0e0b2002290320210a200241f0006a20011044200228027022010d05200041073a00000c0d0b200241d0006a2001105302402002290350a70d00200041073a00000c0d0b200241e0006a290300210720022903582109200241c0006a2001105202402002290340a70d00200041073a00000c0d0b2002290348210a20024180056a41186a2206420037030020024180056a41106a2208420037030020024180056a41086a220b4200370300200242003703800520024180056a2001280200220320012802042204412020044120491b220510ce041a2001200420056b3602042001200320056a360200024002402004411f4b0d00410021040c010b200241e8016a41186a2006290300220c370300200241e8016a41106a2008290300220d370300200241e8016a41086a200b290300220e370300200241d0036a41086a200e370300200241d0036a41106a200d370300200241d0036a41186a200c3703002002200229038005220c3703e8012002200c3703d003410121040b200241f0006a41186a2205200241d0036a41186a290300370300200241f0006a41106a2203200241d0036a41106a290300370300200241f0006a41086a2206200241d0036a41086a290300370300200220022903d003370370024020040d00200041073a00000c0d0b200241e0046a41186a2005290300370300200241e0046a41106a2003290300370300200241e0046a41086a2006290300370300200220022903703703e004200241f0006a20011044200228027022010d05200041073a00000c0c0b20024180056a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a20024180056a2005200410ce041a2001200620046b22033602042001200520046a220436020002402006411f4b0d00200041073a00000c0c0b200241e0046a41086a20024180056a41086a290000370300200241e0046a41106a20024180056a41106a290000370300200241e0046a41186a20024180056a41186a29000037030020022002290080052207370370200220073703e004200241003a0070200241f0006a20042003410047220510ce041a20032005490d072001200320056b22063602042001200420056a22043602002003450d0820022d0070220541014b0d08410021030240024020050e020100010b20024180056a2006412020064120491b22056a41004100412020056b2005411f4b1b10cd041a20024180056a2004200510ce041a2001200620056b3602042001200420056a3602002006411f4d0d09200241f0006a41086a20024180056a41086a2900002207370300200241d0036a41186a20024180056a41186a290000370300200241d0036a41106a20024180056a41106a290000370300200241d0036a41086a200737030020022002290080052207370370200220073703d003410121030b200241a0046a41086a2201200241d0036a41086a290300370300200241a0046a41106a2204200241d0036a41106a290300370300200241a0046a41186a2205200241d0036a41186a290300370300200241c0046a41086a2206200241e0046a41086a290300370300200241c0046a41106a2208200241e0046a41106a290300370300200241c0046a41186a220b200241e0046a41186a290300370300200220022903d0033703a004200220022903e0043703c004200041053a0000200041216a20033a0000200020022903c004370001200041096a2006290300370000200041116a2008290300370000200041196a200b290300370000200041226a20022903a0043700002000412a6a2001290300370000200041326a20042903003700002000413a6a2005290300370000200041f8006a2002418e036a290100370100200041f2006a20024188036a290100370100200041ea006a20024180036a290100370100200041e2006a200241f8026a290100370100200041da006a200241d8026a41186a290100370100200041d2006a200241d8026a41106a290100370100200041ca006a200241d8026a41086a290100370100200041c2006a20022901d8023701000c0b0b200041073a00000c0a0b20024180056a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a20024180056a2005200410ce041a2001200620046b22033602042001200520046a22053602002006411f4d0d08200241e0046a41086a20024180056a41086a2208290000370300200241e0046a41106a20024180056a41106a220b290000370300200241e0046a41186a20024180056a41186a220f29000037030020022002290080052207370370200220073703e00420024180056a2003412020034120491b22046a41004100412020046b2004411f4b1b10cd041a20024180056a2005200410ce041a2001200320046b22063602042001200520046a220436020002402003411f4b0d00200041073a00000c0a0b200241d0036a41086a2008290000370300200241d0036a41106a200b290000370300200241d0036a41186a200f29000037030020022002290080053703d003200242003703e002200242003703d802200241d8026a20042006411020064110491b220510ce041a2001200620056b3602042001200420056a36020002402006410f4b0d00200041073a00000c0a0b200241e0026a290300210720022903d8022109200241e8006a2001102e02402002280268450d0002400240200228026c22104180012010418001491b220b0d004101210f0c010b200b41057422041027220f450d090b02402010450d00200241d8026a41186a2111200241d8026a41106a2112200241d8026a41086a21134100210841002103410021050340201142003703002012420037030020134200370300200242003703d802200241d8026a2001280200221420012802042204412020044120491b220610ce041a2001200420066b3602042001201420066a36020002402004411f4b0d00200b450d03200f10290c030b200541016a2104200241f0006a41186a22062011290300370300200241f0006a41106a22142012290300370300200241f0006a41086a22152013290300370300200220022903d80237037002402005200b470d0002402008200420042008491b220b41ffffff3f71200b470d00200b41057422164100480d000240024020050d0020161027210f0c010b200f200320161028210f0b200f0d0120164101102a000b102b000b200f20036a22052002290370370000200541186a2006290300370000200541106a2014290300370000200541086a2015290300370000200841026a2108200341206a21032004210520102004470d000b0b200f0d040b200041073a00000c090b20022902742109200041023a0000200020022f0080053b0001200041106a2007370300200041086a2009370000200041046a2001360000200041036a20024180056a41026a2d00003a0000200041186a200241d8026a41e80010ce041a0c080b200241d0036a41086a2204200241e8016a41086a290300370300200241d0036a41106a2205200241e8016a41106a290300370300200241d0036a41186a2203200241e8016a41186a290300370300200241d0036a411f6a2206200241e8016a411f6a280000360000200220022903e8013703d0032002290274210c200041033a0000200020022f00e0043b0001200041036a200241e2046a2d00003a0000200041046a20083a0000200041c0006a2007370300200041386a2009370300200041c8006a200a3703002000412c6a200c370200200041286a2001360200200041056a20022903d0033700002000410d6a2004290300370000200041156a20052903003700002000411d6a2003290300370000200041246a2006280000360000200041f8006a200241d8026a41286a290300370300200041f0006a200241f8026a290300370300200041e8006a200241d8026a41186a290300370300200041e0006a200241d8026a41106a290300370300200041d8006a200241d8026a41086a290300370300200041d0006a20022903d8023703000c070b200241c0046a41086a200241e0046a41086a290300220c370300200241c0046a41106a200241e0046a41106a290300220d370300200241c0046a41186a200241e0046a41186a290300220e370300200220022903e00422173703c00420022902742118200041386a2007370300200041306a2009370300200041043a000020002017370001200041096a200c370000200041116a200d370000200041196a200e370000200041216a20022f00a0043b0000200041236a200241a2046a2d00003a0000200041c0006a200a370300200041286a2018370000200041246a2001360000200041c8006a20022903d802370300200041d0006a200241d8026a41086a290300370300200041d8006a200241d8026a41106a290300370300200041e0006a200241d8026a41186a290300370300200041e8006a200241f8026a290300370300200041f0006a200241d8026a41286a290300370300200041f8006a200241d8026a41306a2903003703000c060b200241c0046a41186a2201200241e0046a41186a290300370300200241c0046a41106a2204200241e0046a41106a290300370300200241c0046a41086a2205200241e0046a41086a290300370300200241a0046a41086a2203200241d0036a41086a290300370300200241a0046a41106a2206200241d0036a41106a290300370300200241a0046a41186a2208200241d0036a41186a290300370300200220022903e0043703c004200220022903d0033703a004200041063a0000200020022903c004370001200041096a2005290300370000200041116a2004290300370000200041196a2001290300370000200041216a20022903a004370000200041296a2003290300370000200041316a2006290300370000200041396a2008290300370000200041c1006a20022f009d043b0000200041c3006a2002419f046a2d00003a0000200041d8006a2007370300200041d0006a2009370300200041c8006a2010ad422086200bad84370000200041c4006a200f360000200041f8006a200241f8036a41186a290300370300200041f0006a200241f8036a41106a290300370300200041e8006a200241f8036a41086a290300370300200041e0006a20022903f8033703000c050b20052004103e000b20052003103e000b200041073a00000c020b20044101102a000b200041073a00000b200241f0056a24000ba30b01077f230041106b2202240002400240024002400240024002400240024020002d0000417f6a220341034b0d00024002400240024020030e0400010203000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0c20034101742205200420042005491b22054100480d0c0240024020030d002005102721040c010b200128020020032005102821040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210320022000410c6a280200220036020c2002410c6a200110302000450d0320004105742106200141046a210703400240024020072802002204200528020022006b4120490d00200128020021040c010b200041206a22082000490d0d20044101742200200820082000491b22004100480d0d0240024020040d002000102721040c010b200128020020042000102821040b2004450d072001200436020020072000360200200528020021000b2005200041206a360200200420006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2103200641606a22060d000c040b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0b20034101742205200420042005491b22054100480d0b0240024020030d002005102721040c010b200128020020032005102821040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000280204200110320c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a20034101742205200420042005491b22054100480d0a0240024020030d002005102721040c010b200128020020032005102821040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041046a200110302000280208200110320c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0920034101742205200420042005491b22054100480d090240024020030d002005102721040c010b200128020020032005102821040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d0920044101742203200520052003491b22034100480d090240024020040d002003102721040c010b200128020020042003102821040b2004450d0720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a29000037000020032000290001370000200041246a2001103002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0920034101742205200420042005491b22054100480d090240024020030d002005102721040c010b200128020020032005102821040b2004450d0820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00213a00000b200241106a24000f0b20054101102a000b20004101102a000b20054101102a000b20054101102a000b20054101102a000b20034101102a000b20054101102a000b102b000bf71802047f017e20002802582102024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141046a2802002203200141086a28020022046b4104490d00200128020021030c010b200441046a22052004490d1320034101742204200520052004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200320046a20023600002000290300210602400240200141046a2802002203200528020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0220012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290308210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0320012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290310210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0420012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290318210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0520012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290320210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0620012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290328210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0720012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290330210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0820012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290338210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0920012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290340210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0a20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290348210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0b20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290350210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0c20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a2006370000200028025c210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0d20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280260210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0e20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280264210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d0f20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280268210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d1320034101742204200220022004491b22044100480d130240024020030d002004102721030c010b200128020020032004102821030b2003450d1020012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a200536000002400240200141046a28020020022802002204460d00200128020021030c010b200441016a22032004490d1320044101742202200320032002491b22024100480d130240024020040d002002102721030c010b200128020020042002102821030b2003450d1120012003360200200141046a2002360200200141086a28020021040b200141086a2202200441016a360200200320046a20002d00703a0000200028026c210302400240200141046a2802002204200228020022006b4104490d00200128020021040c010b200041046a22022000490d1320044101742200200220022000491b22004100480d130240024020040d002000102721040c010b200128020020042000102821040b2004450d1220012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20033600000f0b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20024101102a000b20004101102a000b102b000bb01405167f017e017f027e037f230041206b220224000240024020014115490d0002402001410176220341ffffff3f712003470d0020034105742204417f4c0d0041012105024002402004450d00200410272205450d010b200041606a2106200041a07f6a210741042108410021094100210a2001210b034002400240200b220c417f6a220d0d004101210e4100210b0c010b0240024002400240024002402000200d4105746a200c410574220f20006a41406a412010d0044100480d004102200c6b210d2007200f6a21044101210e03400240200d200e6a4101470d004100210b200c210e0c080b200e41016a210e200441206a2004412010d0042110200441606a21042010417f4a0d000b200c200e6b210d0c010b2007200f6a2104024003400240200d4101470d004100210d0c020b200d417f6a210d200441206a2004412010d0042110200441606a210420104100480d000b0b200c200d490d01200c20014b0d03200c200d6b220e4101762211450d002006200f6a21042000200d4105746a21100340200241186a220f201041186a2212290000370300200241106a2213201041106a2214290000370300200241086a2215201041086a221629000037030020022010290000370300200441086a22172900002118200441106a2219290000211a200441186a220b290000211b201020042900003700002012201b3700002014201a37000020162018370000200b200f290300370000201920132903003700002017201529030037000020042002290300370000200441606a2104201041206a21102011417f6a22110d000b0b0240200d0d00200d210b0c050b0240200e41094d0d00200d210b0c050b200c20014b0d01200c200d6b21112000200d4105746a210f0340200c200d417f6a220b490d040240200c200b6b220e4102490d002000200d4105746a22042000200b4105746a220d412010d004417f4a0d00200d2900002118200d2004290000370000200241186a2215200d41186a2210290000370300200241106a2216200d41106a2212290000370300200241086a2217200d41086a22132900003703002013200441086a2900003700002012200441106a2900003700002010200441186a29000037000020022018370300410121140240200e4103490d00200d41c0006a2002412010d004417f4a0d0041022110200f210402400340200441186a200441386a290000370000200441106a200441306a290000370000200441086a200441286a2900003700002004200441206a221229000037000020112010460d01200441c0006a21132010211420122104201041016a211020132002412010d004417f4a0d020c000b0b201021140b200d20144105746a22042002290300370000200441186a2015290300370000200441106a2016290300370000200441086a20172903003700000b200b450d05200f41606a210f201141016a2111200b210d200e410a4f0d050c000b0b200d200c103e000b200c200d417f6a220b490d010b200c2001107f000b200b200c103e000b0240024002402009200a470d0002400240200941016a22042009490d0020094101742210200420042010491b220441ffffffff01712004470d002004410374221041004e0d010b102b000b0240024020090d002010102721080c010b200820094103742010102821080b2008450d01200421090b2008200a4103746a2204200e3602042004200b360200200a41016a2215210a20154102490d0103400240024002400240200820152213417f6a22154103746a2204280200450d00201341037420086a221141746a280200220e200428020422104d0d004102210a201341024d0d0620082013417d6a22044103746a280204220d2010200e6a4d0d014103210a201341034d0d06201141646a280200200d200e6a4d0d012013210a0c060b20134103490d012004280204211020082013417d6a22044103746a280204210d0b200d2010490d010b2013417e6a21040b0240024002400240024002402013200441016a221c4d0d00201320044d0d01200820044103746a2216280204221d20162802006a22042008201c4103746a22172802002219490d02200420014b0d03201641046a211e200020194105746a22122017280204221441057422106a210e2004410574210d200420196b220a20146b220420144f0d042005200e2004410574221010ce04220f20106a21110240024020144101480d00200441014e0d010b200e2104200f21100c060b2006200d6a210d200e21040340200d200441606a220e201141606a220a200a200e412010d004410048220c1b2210290000370000200d41186a201041186a290000370000200d41106a201041106a290000370000200d41086a201041086a2900003700002011200a200c1b211102402012200e2004200c1b2204490d00200f21100c070b200d41606a210d200f2110200f2011490d000c060b0b41d8e3c100201c20131037000b41d8e3c100200420131037000b20192004103e000b20042001107f000b20052012201010ce04220f20106a21110240024020144101480d00200a20144a0d010b20122104200f21100c010b2000200d6a210c200f21102012210403402004200e2010200e2010412010d004410048220a1b220d290000370000200441186a200d41186a290000370000200441106a200d41106a290000370000200441086a200d41086a2900003700002010201041206a200a1b2110200441206a2104200e41206a200e200a1b220e200c4f0d01201120104b0d000b0b20042010201120106b41607110ce041a201e201d20146a360200201620193602002017201741086a201c417f7320136a41037410cf041a2015210a201541014d0d020c000b0b20104104102a000b200b0d000b02402009450d00200810290b2003450d03200510290c030b20044101102a000b1039000b20014102490d002001417f6a2110200141057420006a41206a210c410121110340024002400240024020102204417f6a221020014b0d00200120106b220d4102490d03200020044105746a2204200020104105746a220a412010d004417f4a0d03200a2900002118200a2004290000370000200241186a2212200a41186a220e290000370300200241106a2213200a41106a220f290000370300200241086a2214200a41086a22082900003703002008200441086a290000370000200f200441106a290000370000200e200441186a2900003700002002201837030041012104200d4103490d02200a41c0006a2002412010d004417f4a0d024100210f200c21040340200441406a220d200441606a220e290000370000200d41186a200e41186a290000370000200d41106a200e41106a290000370000200d41086a200e41086a2900003700002011200f220d460d02200d417f6a210f20042002412010d004210e200441206a2104200e417f4a0d020c000b0b20102001103e000b4102200d6b21040b200a20044105746a22042002290300370000200441186a2012290300370000200441106a2013290300370000200441086a20142903003700000b200c41606a210c2011417f6a211120100d000b0b200241206a24000be91a03037f027e067f230041f0016b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e12000102030405060708090a0b0c0d0e0f1011000b200241e8006a200141086a10960220004100360200200041106a200241e8006a41086a290300370300200041086a20022903683703000c110b109702000b20004102360200200041086a200141086a2903003703000c0f0b200241e8006a200141046a1038200041033602002000410c6a200241f0006a280200360200200020022903683702040c0e0b109802000b0240024002400240200141086a280200417f6a220341014b0d0020030e020102010b41e4bdc0001058000b41012103024002402001410c6a22042d00004101460d00200241026a200441036a2d00003a0000200241f0006a2001411c6a290200370300200241e8006a41106a200141246a29020037030020024180016a2001412c6a2d00003a0000200220042f00013b01002002200141146a290200370368200141106a2802002104410021030c010b200141106a28020021040b200241246a41026a200241026a2d00003a0000200241286a41086a200241e8006a41086a290300370300200241286a41106a200241e8006a41106a290300370300200241286a41186a200241e8006a41186a280200360200200220022f01003b012420022002290368370328200141386a29030021052001290330210641012107200241106a21010c010b41012103024002402001410c6a22042d00004101460d00200241ee016a200441036a2d00003a0000200241f0006a2001411c6a290200370300200241e8006a41106a200141246a29020037030020024180016a2001412c6a2d00003a0000200220042f00013b01ec012002200141146a290200370368200141106a2802002104410021030c010b200141106a28020021040b41022107200241246a41026a200241ec016a41026a2d00003a0000200241286a41086a200241e8006a41086a290300370300200241286a41106a200241e8006a41106a290300370300200241286a41186a200241e8006a41186a280200360200200220022f01ec013b012420022002290368370328200220012903303703102002200141386a290300370318200141c8006a290300210520012903402106200221010b20012006370300200120053703082000410c6a20033a0000200041086a2007360200200020022f01243b000d2000410f6a200241266a2d00003a0000200041106a2004360200200041146a20022903283702002000411c6a200241286a41086a290300370200200041246a200241286a41106a2903003702002000412c6a200241c0006a280200360200200041386a200241106a41086a290300370300200041306a2002290310370300200041c0006a2002290300370300200041c8006a200241086a290300370300200041053602000c0c0b200241e8006a200141086a10990220004106360200200041386a200241e8006a41306a290300370300200041306a200241e8006a41286a290300370300200041286a200241e8006a41206a290300370300200041206a200241e8006a41186a290300370300200041186a200241e8006a41106a290300370300200041106a200241e8006a41086a290300370300200041086a20022903683703000c0b0b200241e8006a41186a200141286a290000370300200241e8006a41106a200141206a290000370300200241f0006a200141186a290000370300200241e8006a41286a200141386a290000370300200241e8006a41306a200141c0006a290000370300200241e8006a41386a200141c8006a2900003703002002200141106a2900003703682002200141306a290000370388012001410c6a2802002203417f4c0d0b0240024020030d00410121010c010b20012802042104200310272201450d0d20012004200310ce041a0b200241286a41386a2204200241e8006a41386a290300370300200241286a41306a2207200241e8006a41306a290300370300200241286a41286a2208200241e8006a41286a290300370300200241286a41206a2209200241e8006a41206a290300370300200241286a41186a220a200241e8006a41186a290300370300200241286a41106a220b200241e8006a41106a290300370300200241286a41086a220c200241e8006a41086a290300370300200220022903683703282000410c6a2003360200200041086a200336020020002001360204200041106a2002290328370200200041186a200c290300370200200041206a200b290300370200200041286a200a290300370200200041306a2009290300370200200041386a2008290300370200200041c0006a2007290300370200200041c8006a2004290300370200200041073602000c0a0b200241e8006a200141086a109a0220004108360200200041386a200241e8006a41306a290300370300200041306a200241e8006a41286a290300370300200041286a200241e8006a41206a290300370300200041206a200241e8006a41186a290300370300200041186a200241e8006a41106a290300370300200041106a200241e8006a41086a290300370300200041086a20022903683703000c090b200241e8006a200141046a109b0220004109360200200041246a20024188016a2903003702002000411c6a20024180016a290300370200200041146a200241f8006a2903003702002000410c6a200241f0006a290300370200200020022903683702040c080b200241e8006a200141046a109b022000410a360200200041246a20024188016a2903003702002000411c6a20024180016a290300370200200041146a200241f8006a2903003702002000410c6a200241f0006a290300370200200020022903683702040c070b200241e8006a200141086a10c8012000410b360200200041c0006a200241e8006a41386a290300370300200041386a200241e8006a41306a290300370300200041306a200241e8006a41286a290300370300200041286a200241e8006a41206a290300370300200041206a200241e8006a41186a290300370300200041186a200241e8006a41106a290300370300200041106a200241e8006a41086a290300370300200041086a20022903683703000c060b2000410c360200200041086a200141086a2903003703000c050b2001410c6a2802002203417f4c0d050240024020030d00410121010c010b20012802042104200310272201450d0820012004200310ce041a0b200020013602042000410d3602002000410c6a2003360200200041086a20033602000c040b024002400240024002400240200141086a280200417f6a220341024b0d0020030e03010203010b4190a9c1001058000b200141386a2903002105200141306a290300210641012103024002402001410c6a2d00004101460d00200241f0006a2001411c6a290200370300200241e8006a41106a200141246a29020037030020024180016a2001412c6a2d00003a00002002200141146a29020037036820012f000d2001410f6a2d0000411074722104200141106a2802002101410021030c010b200141106a28020021010b200241286a41186a200241e8006a41186a280200360200200241286a41106a200241e8006a41106a290300370300200241286a41086a200241e8006a41086a29030037030020022002290368370328410121070c030b2001410c6a28020022034108762104410221070c010b2001410c6a28020022034108762104410321070b0b2000410e360200200041386a2005370300200041306a2006370300200041106a2001360200200041086a2007360200200041146a20022903283702002000410c6a2004410874200341ff0171723602002000411c6a200241286a41086a290300370200200041246a200241286a41106a2903003702002000412c6a200241c0006a2802003602000c030b200241e8006a200141086a109c02200041086a200241e8006a41800110ce041a2000410f3602000c020b02400240024002402001280204417f6a220341014b0d0020030e020102010b41f8e2c1001058000b41880110272203450d072003200141086a280200109502410121010c010b4101210302400240200141086a2d00004101460d00200241e8006a41086a200141186a290200370300200241e8006a41106a200141206a290200370300200241e8006a41186a200141286a2d00003a00002002200141106a29020037036820012f00092001410b6a2d00004110747241087421072001410c6a2802002104410021030c010b2001410c6a2802002104410021070b200241286a41186a200241e8006a41186a280200360200200241286a41106a200241e8006a41106a290300370300200241286a41086a200241e8006a41086a2903003703002002200229036837032820032007722103410221010b20002001360204200041103602002000410c6a2004360200200041086a2003360200200041106a2002290328370200200041186a200241286a41086a290300370200200041206a200241286a41106a290300370200200041286a200241286a41186a2802003602000c010b200241e8006a200141086a10b101200041086a200241e8006a41d80010ce041a200041113602000b200241f0016a24000f0b1039000b20034101102a000b20034101102a000b4188014108102a000bac0703037f017e077f0240024002400240024002400240024002400240024002400240024002402001280200417f6a220241054b0d0020020e06010203040506010b41b48ec3001058000b200041013602000f0b2001410c6a2802002202417f4c0d040240024020020d00410121010c010b20012802042103200210272201450d0620012003200210ce041a0b20002001360204200041023602002000410c6a2002360200200041086a20023602000f0b20004103360200200041086a200141086a2903003703000f0b2001410c6a2802002202417f4c0d020240024020020d00410121010c010b20012802042103200210272201450d0520012003200210ce041a0b20002001360204200041043602002000410c6a2002360200200041086a20023602000f0b2001410c6a2802002204ad42187e2205422088a70d012005a72203417f4c0d01200128020421020240024020030d00410421060c010b200310272206450d050b0240024020040d00410021070c010b2002200441186c6a210841002107200621010340200241086a2802002203417f4c0d03200228020021090240024020030d004101210a0c010b20031027220a450d080b200a2009200310ce04210a200241146a2802002209417f4c0d032002410c6a280200210b0240024020090d004101210c0c010b20091027220c450d090b200c200b200910ce04210b200141146a2009360200200141106a20093602002001410c6a200b360200200141086a2003360200200141046a20033602002001200a360200200141186a2101200741016a2107200241186a22022008470d000b0b20002006360204200041053602002000410c6a2007360200200041086a20043602000f0b2001410c6a280200220cad420c7e2205422088a70d002005a72202417f4c0d00200128020421030240024020020d00410421080c010b200210272208450d070b02400240200c0d00410021090c010b2003200c410c6c6a210b41002109200821020340200341086a2802002201417f4c0d02200328020021070240024020010d004101210a0c010b20011027220a450d0a0b200a2007200110ce042107200241086a2001360200200241046a2001360200200220073602002002410c6a2102200941016a21092003410c6a2203200b470d000b0b20002008360204200041063602002000410c6a2009360200200041086a200c3602000f0b1039000b20024101102a000b20024101102a000b20034104102a000b20034101102a000b20094101102a000b20024104102a000b20014101102a000b0a0041dc8dc3001058000b0a004198eec2001058000bbf0c03047f017e057f230041206b2202240002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410c4b0d0020030e0d0102030405060708090a0b0c0d010b41e8fcc4001058000b4101210302400240200141046a2d00004101460d002002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002104410021030c010b200141086a28020021040b200041286a2001290328370300200041046a20033a0000200041056a20022f011c3b0000200041086a20043602002000410c6a2002290300370200200041306a200141306a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a28020036020020012d00012101200041013a0000200020013a00010c0c0b200041023a0000200041106a200141106a290300370300200041086a200141086a2903003703000c0b0b200041033a0000200041106a200141106a290300370300200041086a200141086a2903003703000c0a0b200041043a00000c090b200041053a0000200041106a200141106a290300370300200041086a200141086a290300370300200041186a200141186a2802003602000c080b2001410c6a2802002205ad42247e2206422088a70d082006a72204417f4c0d08200141046a28020021030240024020040d00410421070c010b200410272207450d0a0b0240024020050d00410021040c010b200541246c2108410021042002411e6a21092007210103400240024020032d00004101460d002009200341036a2d00003a0000200341046a280000210a200341016a2f0000210b200241086a200341106a290000370300200241106a200341186a290000370300200241186a200341206a2d00003a00002002200b3b011c2002200341086a2900003703004100210b0c010b200341046a280200210a4101210b0b200341246a21032001200b3a0000200141046a200a360200200141016a20022f011c3b0000200141036a20092d00003a0000200141086a2002290300370200200141106a200241086a290300370200200141186a200241106a290300370200200141206a200241186a280200360200200141246a2101200441016a21042008415c6a22080d000b0b200041063a00002000410c6a2004360200200041086a2005360200200041046a20073602000c070b200041073a00000c060b200041083a0000200020012d00013a00010c050b4101210302400240200141046a2d00004101460d002002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002101410021030c010b200141086a28020021010b200041093a0000200041046a20033a0000200041056a20022f011c3b0000200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c040b2000410a3a0000200041046a200141046a2802003602000c030b2000410b3a00000c020b2000410c3a0000200041046a200141046a2802003602000c010b2001410c6a280200220841ffffff3f712008470d0120084105742203417f4c0d01200141046a280200210a0240024020030d004101210b0c010b20031027220b450d040b0240024020080d0041002108410021010c010b200841057421044160200a6b2109200b2101200a2103034020012003290000370000200141186a200341186a290000370000200141106a200341106a290000370000200141086a200341086a290000370000200141206a2101200341206a2103200441606a22040d000b200a20084105746a20096a41057641016a21010b2000410d3a00002000410c6a2001360200200041086a2008360200200041046a200b3602000b200241206a24000f0b1039000b20044104102a000b20034101102a000be50701017f024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220241104b0d0020020e110102030405060708090a0b0c0d0e0f1011010b41c499c4001058000b41880110272202450d102002200141046a28020010c103200041046a2002360200200041013a0000200041106a200141106a290300370300200041086a200141086a2903003703000f0b200041023a0000200041046a200141046a2802003602000f0b200041033a0000200041046a200141046a280200360200200041026a200141026a2d00003a0000200020012d00014101713a00010f0b200041043a0000200041046a200141046a280200360200200041026a200141026a2d00003a0000200020012d00014101713a00010f0b41880110272202450d0d2002200141046a28020010c103200041046a2002360200200041053a0000200041106a200141106a290300370300200041086a200141086a290300370300200020012d00013a00010f0b200041063a0000200041046a200141046a2802003602000f0b41880110272202450d0c2002200141046a28020010c103200041073a0000200041046a20023602000f0b41880110272202450d0c2002200141046a28020010c103200041083a0000200041046a20023602000f0b200041093a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041306a200141306a290300370300200041286a200141286a2903003703000f0b2000410a3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b2000410b3a0000200041046a200141046a2802003602000f0b2000410c3a0000200041106a200141106a290300370300200041046a200141046a2902003702000f0b2000410d3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b2000410e3a00000f0b2000410f3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b200041103a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00003a00000f0b200041113a00000f0b4188014108102a000b4188014108102a000b4188014108102a000b4188014108102a000beb0301067f024002400240024002400240024020012d0000417f6a220241034b0d0020020e0401020304010b41c893c2001058000b2001410c6a280200220341ffffff3f712003470d0320034105742202417f4c0d03200141046a28020021040240024020020d00410121050c010b200210272205450d050b0240024020030d0041002103410021010c010b20034105742106416020046b21072005210120042102034020012002290000370000200141186a200241186a290000370000200141106a200241106a290000370000200141086a200241086a290000370000200141206a2101200241206a2102200641606a22060d000b200420034105746a20076a41057641016a21010b200041013a00002000410c6a2001360200200041086a2003360200200041046a20053602000f0b200141046a10f7022101200041023a0000200041046a20013602000f0b200141046a2802002102200041086a200141086a10f702360200200041046a2002360200200041033a00000f0b200041043a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a280200360200200041216a200141216a2d00004100473a00000f0b1039000b20024101102a000ba60f05027f017e027f027e017f230041c0006b22022400024002400240024002400240024002400240024002400240024020012d0000417f6a220341054b0d0020030e06010203040506010b4190e1c2001058000b200041f9006a2002280020360000200041086a200141086a290300370300200041fc006a200241236a280000360000200041106a200141106a290300370300200041186a200141186a290300370300200041206a200141206a290300370300200041286a200141286a290300370300200041306a200141306a290300370300200041386a200141386a290300370300200041c0006a200141c0006a290300370300200041c8006a200141c8006a290300370300200041d0006a200141d0006a290300370300200041d8006a200141d8006a290300370300200041e0006a200141e0006a290300370300200041e8006a200141e8006a290300370300200041f0006a200141f0006a290300370300200041f8006a200141f8006a2d00004100473a0000200041013a00000c050b2001410c6a2802002203417f4c0d05200141106a29030021040240024020030d00410121010c010b200141046a2802002105200310272201450d0720012005200310ce041a0b200041023a00002000410c6a2003360200200041086a2003360200200041046a2001360200200041106a20043703000c040b4101210502400240200141046a2d00004101460d00200241026a200141076a2d00003a0000200241206a41086a200141146a290000370300200241306a2001411c6a290000370300200241386a200141246a2d00003a00002002200141056a2f00003b010020022001410c6a290000370320200141086a2800002106410021050c010b200141086a28020021060b200141306a2802002203417f4c0d04200141c0006a290300210420012903382107200129034821080240024020030d00410121010c010b20012802282109200310272201450d0720012009200310ce041a0b200041c0006a2004370300200041386a2007370300200041046a20053a0000200041056a20022f01003b0000200041086a20063602002000410c6a2002290320370200200041c8006a2008370300200041306a20033602002000412c6a2003360200200041286a2001360200200041076a200241026a2d00003a0000200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a280200360200200041033a00000c030b200141386a2903002104200141306a2903002107200141c0006a2903002108200241386a200141196a290000370300200241306a200141116a290000370300200241286a200141096a290000370300200220012900013703202001412c6a2802002203417f4c0d030240024020030d00410121010c010b200141246a2802002105200310272201450d0720012005200310ce041a0b20002002290320370001200041043a0000200041386a2004370300200041306a2007370300200041c0006a20083703002000412c6a2003360200200041286a2003360200200041246a2001360200200041096a200241286a290300370000200041116a200241306a290300370000200041196a200241386a2903003700000c020b200241186a2205200141196a290000370300200241106a2206200141116a290000370300200241086a2209200141096a29000037030020022001290001370300410021030240200141216a2d00004101470d00200241206a41186a2001413a6a290000370300200241206a41106a200141326a290000370300200241206a41086a2001412a6a2900003703002002200141226a290000370320410121030b20002002290300370001200041216a20033a0000200041226a2002290320370000200041196a2005290300370000200041116a2006290300370000200041096a20092903003700002000412a6a200241206a41086a290300370000200041326a200241206a41106a2903003700002000413a6a200241206a41186a290300370000200041053a00000c010b200241186a200141196a290000370300200241106a200141116a290000370300200241086a200141096a29000037030020022001290001370300200241206a41186a200141396a290000370300200241206a41106a200141316a290000370300200241206a41086a200141296a2900003703002002200141216a290000370320200141cc006a280200220341ffffff3f712003470d0120034105742205417f4c0d01200141d8006a2903002104200141d0006a2903002107200141c4006a28020021010240024020050d00410121060c010b200510272206450d060b20062001200341057410ce042101200041d8006a2004370300200041d0006a2007370300200041cc006a2003360200200041c8006a2003360200200041c4006a2001360200200041196a200241186a290300370000200041116a200241106a290300370000200041096a200241086a29030037000020002002290300370001200041216a2002290320370000200041296a200241206a41086a290300370000200041316a200241206a41106a290300370000200041396a200241206a41186a290300370000200041063a00000b200241c0006a24000f0b1039000b20034101102a000b20034101102a000b20034101102a000b20054101102a000bc9b30103047f027e057f230041106b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00002203410d4b0d000240024002400240024002400240024002400240024002400240024020030e0e000102030405060708090a0b0c0d000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a20034101742205200420042005491b22054100480d5a0240024020030d002005102721040c010b200128020020032005102821040b2004450d0f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200141046a280200210420052802002103024020002d00014101460d000240024020042003460d00200128020021000c010b200341016a22002003490d5b20034101742204200020002004491b22044100480d5b0240024020030d002004102721000c010b200128020020032004102821000b2000450d1120012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c0e0b0240024020042003460d00200128020021000c010b200341016a22002003490d5a20034101742204200020002004491b22044100480d5a0240024020030d002004102721000c010b200128020020032004102821000b2000450d1120012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5920034101742205200420042005491b22054100480d590240024020030d002005102721040c010b200128020020032005102821040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5920034101742205200420042005491b22054100480d590240024020030d002005102721040c010b200128020020032005102821040b2004450d1220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5920044101742203200520052003491b22034100480d590240024020040d002003102721040c010b200128020020042003102821040b2004450d1320012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041086a220441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000200320042900003700002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d5920034101742200200520052000491b22004100480d590240024020030d002000102721030c010b200128020020032000102821030b2003450d1420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5820034101742205200420042005491b22054100480d580240024020030d002005102721040c010b200128020020032005102821040b2004450d1420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a000020002d0008220341024b0d0b02400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a20034101742205200420042005491b22054100480d5a0240024020030d002005102721040c010b200128020020032005102821040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5a20044101742203200520052003491b22034100480d5a0240024020040d002003102721040c010b200128020020042003102821040b2004450d1820012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a29030021062000290330210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5a20034101742200200420042000491b22004100480d5a0240024020030d002000102721030c010b200128020020032000102821030b2003450d1920012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5920034101742205200420042005491b22054100480d590240024020030d002005102721040c010b200128020020032005102821040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5920044101742203200520052003491b22034100480d590240024020040d002003102721040c010b200128020020042003102821040b2004450d1a20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5820034101742205200420042005491b22054100480d580240024020030d002005102721040c010b200128020020032005102821040b2004450d1a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5820044101742203200520052003491b22034100480d580240024020040d002003102721040c010b200128020020042003102821040b2004450d1b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5820044101742203200520052003491b22034100480d580240024020040d002003102721040c010b200128020020042003102821040b2004450d1c20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041296a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041d8006a29030021062000290350210702400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d5820044101742203200520052003491b22034100480d580240024020040d002003102721040c010b200128020020042003102821040b2004450d1d20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a2203200637000820032007370000200041e8006a29030021062000290360210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5820034101742200200420042000491b22004100480d580240024020030d002000102721030c010b200128020020032000102821030b2003450d1e20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5720034101742205200420042005491b22054100480d570240024020030d002005102721040c010b200128020020032005102821040b2004450d1e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002d0008220341024b0d0a02400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5920034101742205200420042005491b22054100480d590240024020030d002005102721040c010b200128020020032005102821040b2004450d2120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041186a29030021062000290310210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5920034101742200200420042000491b22004100480d590240024020030d002000102721030c010b200128020020032000102821030b2003450d2220012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5820034101742205200420042005491b22054100480d580240024020030d002005102721040c010b200128020020032005102821040b2004450d2220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5820044101742203200520052003491b22034100480d580240024020040d002003102721040c010b200128020020042003102821040b2004450d2320012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200028022c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d5820034101742200200520052000491b22004100480d580240024020030d002000102721030c010b200128020020032000102821030b2003450d2420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5720034101742205200420042005491b22054100480d570240024020030d002005102721040c010b200128020020032005102821040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5720044101742203200520052003491b22034100480d570240024020040d002003102721040c010b200128020020042003102821040b2004450d2520012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041386a29030021062000290330210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5720034101742200200420042000491b22004100480d570240024020030d002000102721030c010b200128020020032000102821030b2003450d2620012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5620034101742205200420042005491b22054100480d560240024020030d002005102721040c010b200128020020032005102821040b2004450d2620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5620034101742205200420042005491b22054100480d560240024020030d002005102721040c010b200128020020032005102821040b2004450d2720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d5620034101742200200520052000491b22004100480d560240024020030d002000102721030c010b200128020020032000102821030b2003450d2820012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c090b02400240200141046a2208280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d5520034101742209200520052009491b22094100480d550240024020030d002009102721050c010b200128020020032009102821050b2005450d2820012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41053a000020002d00082203410a4b0d080240024002400240024002400240024002400240024020030e0b000102030405060708090a000b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5f20034101742209200520052009491b22094100480d5f0240024020030d002009102721050c010b200128020020032009102821050b2005450d3320012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41003a0000200028020c21090240024020082802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5f20054101742203200a200a2003491b22034100480d5f0240024020050d002003102721050c010b200128020020052003102821050b2005450d3420012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2009360000200041186a2903002106200029031021070240024020082802002203200428020022006b4110490d00200128020021030c010b200041106a22052000490d5f20034101742200200520052000491b22004100480d5f0240024020030d002000102721030c010b200128020020032000102821030b2003450d3520012003360200200141046a2000360200200141086a28020021000b2004200041106a360200200320006a22012006370008200120073700000c120b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5e20034101742209200520052009491b22094100480d5e0240024020030d002009102721050c010b200128020020032009102821050b2005450d3520012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41013a0000200028020c21090240024020082802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5e20054101742203200a200a2003491b22034100480d5e0240024020050d002003102721050c010b200128020020052003102821050b2005450d3620012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2009360000200041286a2903002106200029032021070240024020082802002205200428020022036b4110490d00200128020021050c010b200341106a22092003490d5e20054101742203200920092003491b22034100480d5e0240024020050d002003102721050c010b200128020020052003102821050b2005450d3720012005360200200141046a2003360200200141086a28020021030b200141086a220b200341106a360200200520036a2203200637000820032007370000200028021021032002200041186a280200220036020c2002410c6a200110302000450d1120004105742109200141046a210c03400240024020082802002205200428020022006b4120490d00200128020021050c010b200041206a220a2000490d5f20054101742200200a200a2000491b22004100480d5f0240024020050d002000102721050c010b200128020020052000102821050b2005450d3920012005360200200c2000360200200b28020021000b2004200041206a360200200520006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2103200941606a22090d000c120b0b02400240200828020020042802002200460d00200128020021030c010b200041016a22032000490d5d20004101742205200320032005491b22054100480d5d0240024020000d002005102721030c010b200128020020002005102821030b2003450d3820012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c100b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5c20034101742209200520052009491b22094100480d5c0240024020030d002009102721050c010b200128020020032009102821050b2005450d3820012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41033a0000200028020c21090240024020082802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5c20054101742203200a200a2003491b22034100480d5c0240024020050d002003102721050c010b200128020020052003102821050b2005450d3920012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200936000020002d0009220041024b0d0f02400240024020000e03000102000b02400240200828020020042802002200460d00200128020021030c010b200041016a22032000490d5e20004101742205200320032005491b22054100480d5e0240024020000d002005102721030c010b200128020020002005102821030b2003450d3c20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41003a00000c110b02400240200828020020042802002200460d00200128020021030c010b200041016a22032000490d5d20004101742205200320032005491b22054100480d5d0240024020000d002005102721030c010b200128020020002005102821030b2003450d3c20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41013a00000c100b02400240200828020020042802002200460d00200128020021030c010b200041016a22032000490d5c20004101742205200320032005491b22054100480d5c0240024020000d002005102721030c010b200128020020002005102821030b2003450d3c20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c0f0b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5b20034101742209200520052009491b22094100480d5b0240024020030d002009102721050c010b200128020020032009102821050b2005450d3c20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41043a0000200028020c21050240024020082802002203200428020022006b4104490d00200128020021030c010b200041046a22082000490d5b20034101742200200820082000491b22004100480d5b0240024020030d002000102721030c010b200128020020032000102821030b2003450d3d20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0e0b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5a20034101742209200520052009491b22094100480d5a0240024020030d002009102721050c010b200128020020032009102821050b2005450d3d20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41053a0000200028020c21050240024020082802002203200428020022006b4104490d00200128020021030c010b200041046a22082000490d5a20034101742200200820082000491b22004100480d5a0240024020030d002000102721030c010b200128020020032000102821030b2003450d3e20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0d0b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5920034101742209200520052009491b22094100480d590240024020030d002009102721050c010b200128020020032009102821050b2005450d3e20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41063a0000200028020c21050240024020082802002203200428020022006b4104490d00200128020021030c010b200041046a22082000490d5920034101742200200820082000491b22004100480d590240024020030d002000102721030c010b200128020020032000102821030b2003450d3f20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0c0b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5820034101742209200520052009491b22094100480d580240024020030d002009102721050c010b200128020020032009102821050b2005450d3f20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41073a0000200028020c21090240024020082802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5820054101742203200a200a2003491b22034100480d580240024020050d002003102721050c010b200128020020052003102821050b2005450d4020012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200936000002400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5820034101742208200520052008491b22084100480d580240024020030d002008102721050c010b200128020020032008102821050b2005450d4120012005360200200141046a2008360200200141086a28020021030b2004200341016a360200200520036a20002d00093a00000c0b0b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5720034101742209200520052009491b22094100480d570240024020030d002009102721050c010b200128020020032009102821050b2005450d4120012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41083a00000240024020082802002205200428020022036b4120490d00200128020021050c010b200341206a22092003490d5720054101742203200920092003491b22034100480d570240024020050d002003102721050c010b200128020020052003102821050b2005450d4220012005360200200141046a2003360200200141086a28020021030b2004200341206a360200200520036a220341186a200041096a220541186a290000370000200341106a200541106a290000370000200341086a200541086a290000370000200320052900003700000240024020082802002205200428020022036b4120490d00200128020021050c010b200341206a22082003490d5720054101742203200820082003491b22034100480d570240024020050d002003102721050c010b200128020020052003102821050b2005450d4320012005360200200141046a2003360200200141086a28020021030b2004200341206a360200200520036a220141186a200041296a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c0a0b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5620034101742209200520052009491b22094100480d560240024020030d002009102721050c010b200128020020032009102821050b2005450d4320012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41093a00000240024020082802002205200428020022036b4120490d00200128020021050c010b200341206a22082003490d5620054101742203200820082003491b22034100480d560240024020050d002003102721050c010b200128020020052003102821050b2005450d4420012005360200200141046a2003360200200141086a28020021030b2004200341206a360200200520036a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c090b02400240200828020020042802002203460d00200128020021050c010b200341016a22052003490d5520034101742209200520052009491b22094100480d550240024020030d002009102721050c010b200128020020032009102821050b2005450d4420012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a410a3a00000240024020082802002205200428020022036b4120490d00200128020021050c010b200341206a22092003490d5520054101742203200920092003491b22034100480d550240024020050d002003102721050c010b200128020020052003102821050b2005450d4520012005360200200141046a2003360200200141086a28020021030b2004200341206a360200200520036a220341186a200041096a220541186a290000370000200341106a200541106a290000370000200341086a200541086a290000370000200320052900003700000240024020082802002205200428020022036b4120490d00200128020021050c010b200341206a22092003490d5520054101742203200920092003491b22034100480d550240024020050d002003102721050c010b200128020020052003102821050b2005450d4620012005360200200141046a2003360200200141086a28020021030b2004200341206a360200200520036a220341186a200041296a220541186a290000370000200341106a200541106a290000370000200341086a200541086a29000037000020032005290000370000200029035021060240024020082802002203200428020022006b4108490d00200128020021030c010b200041086a22052000490d5520034101742200200520052000491b22004100480d550240024020030d002000102721030c010b200128020020032000102821030b2003450d4720012003360200200141046a2000360200200141086a28020021000b2004200041086a360200200320006a20063700000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5420034101742205200420042005491b22054100480d540240024020030d002005102721040c010b200128020020032005102821040b2004450d4720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a0000200041046a2001109e020c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5320034101742205200420042005491b22054100480d530240024020030d002005102721040c010b200128020020032005102821040b2004450d4720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200041046a2001109e020c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5220034101742205200420042005491b22054100480d520240024020030d002005102721040c010b200128020020032005102821040b2004450d4720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a0000024002400240024020002d00040e0400010203000b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5520034101742205200420042005491b22054100480d550240024020030d002005102721040c010b200128020020032005102821040b2004450d4b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5520044101742203200520052003491b22034100480d550240024020040d002003102721040c010b200128020020042003102821040b2004450d4c20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041056a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5520044101742203200520052003491b22034100480d550240024020040d002003102721040c010b200128020020042003102821040b2004450d4d20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041256a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c080b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5420034101742205200420042005491b22054100480d540240024020030d002005102721040c010b200128020020032005102821040b2004450d4d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d5420044101742203200520052003491b22034100480d540240024020040d002003102721040c010b200128020020042003102821040b2004450d4e20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041056a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c070b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5320034101742205200420042005491b22054100480d530240024020030d002005102721040c010b200128020020032005102821040b2004450d4e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000280208210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d5320034101742200200520052000491b22004100480d530240024020030d002000102721030c010b200128020020032000102821030b2003450d4f20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c060b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5220034101742205200420042005491b22054100480d520240024020030d002005102721040c010b200128020020032005102821040b2004450d4f20012004360200200141046a2005360200200141086a28020021030b200141086a2208200341016a360200200420036a41033a0000200028020821032002200041106a280200220436020c2002410c6a2001103002402004450d0020044105742109200141046a210a034002400240200a2802002205200828020022046b4120490d00200128020021050c010b200441206a220b2004490d5420054101742204200b200b2004491b22044100480d540240024020050d002004102721050c010b200128020020052004102821050b2005450d5220012005360200200a2004360200200828020021040b2008200441206a360200200520046a220441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a29000037000020042003290000370000200341206a2103200941606a22090d000b0b2000280214210320022000411c6a280200220036020c2002410c6a200110302000450d0520004105742108200141086a2105200141046a210903400240024020092802002204200528020022006b4120490d00200128020021040c010b200041206a220a2000490d5320044101742200200a200a2000491b22004100480d530240024020040d002000102721040c010b200128020020042000102821040b2004450d522001200436020020092000360200200528020021000b2005200041206a360200200420006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2103200841606a22080d000c060b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d800120034101742205200420042005491b22054100480d80010240024020030d002005102721040c010b200128020020032005102821040b2004450d5220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000280204220341024b0d0402400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d820120034101742205200420042005491b22044100480d82010240024020030d002004102721050c010b200128020020032004102821050b2005450d5520012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41003a0000200028020821032002200041106a280200220036020c2002410c6a200110302000450d062003200041286c6a210a200141046a210503400240024020052802002208200428020022006b4120490d00200128020021080c010b200041206a22092000490d830120084101742200200920092000491b22004100480d83010240024020080d002000102721080c010b200128020020082000102821080b2008450d572001200836020020052000360200200428020021000b2004200041206a360200200820006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a29030021060240024020052802002208200428020022006b4108490d00200128020021080c010b200041086a22092000490d830120084101742200200920092000491b22004100480d83010240024020080d002000102721080c010b200128020020082000102821080b2008450d582001200836020020052000360200200428020021000b2004200041086a360200200820006a2006370000200a200341286a2203470d000c070b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d810120004101742204200320032004491b22044100480d81010240024020000d002004102721030c010b200128020020002004102821030b2003450d5720012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c050b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d800120004101742204200320032004491b22044100480d80010240024020000d002004102721030c010b200128020020002004102821030b2003450d5720012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d7f20034101742205200420042005491b22054100480d7f0240024020030d002005102721040c010b200128020020032005102821040b2004450d5720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a000020002d0008220341044b0d030240024002400240024020030e050001020304000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d830120034101742205200420042005491b22054100480d83010240024020030d002005102721040c010b200128020020032005102821040b2004450d5c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d830120034101742200200520052000491b22004100480d83010240024020030d002000102721030c010b200128020020032000102821030b2003450d5d20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d820120034101742205200420042005491b22054100480d82010240024020030d002005102721040c010b200128020020032005102821040b2004450d5d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a29030021062000290310210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d820120034101742200200420042000491b22004100480d82010240024020030d002000102721030c010b200128020020032000102821030b2003450d5e20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d810120034101742205200420042005491b22054100480d81010240024020030d002005102721040c010b200128020020032005102821040b2004450d5e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028022c210802400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d810120044101742203200520052003491b22034100480d81010240024020040d002003102721040c010b200128020020042003102821040b2004450d5f20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2008360000200041386a29030021062000290330210702400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d810120044101742203200520052003491b22034100480d81010240024020040d002003102721040c010b200128020020042003102821040b2004450d6020012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a220320063700082003200737000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d810120044101742203200520052003491b22034100480d81010240024020040d002003102721040c010b200128020020042003102821040b2004450d6120012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d800120034101742205200420042005491b22054100480d80010240024020030d002005102721040c010b200128020020032005102821040b2004450d6120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041186a29030021062000290310210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d800120034101742200200420042000491b22004100480d80010240024020030d002000102721030c010b200128020020032000102821030b2003450d6220012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d7f20034101742205200420042005491b22054100480d7f0240024020030d002005102721040c010b200128020020032005102821040b2004450d6220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041186a29030021062000290310210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d7f20034101742200200420042000491b22004100480d7f0240024020030d002000102721030c010b200128020020032000102821030b2003450d6320012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d7e20034101742205200420042005491b22054100480d7e0240024020030d002005102721040c010b200128020020032005102821040b2004450d6320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a000020002d0008220341054b0d0202400240024002400240024020030e06000102030405000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d830120034101742205200420042005491b22054100480d83010240024020030d002005102721040c010b200128020020032005102821040b2004450d6920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d830120044101742203200520052003491b22034100480d83010240024020040d002003102721040c010b200128020020042003102821040b2004450d6a20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d830120044101742203200520052003491b22034100480d83010240024020040d002003102721040c010b200128020020042003102821040b2004450d6b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041296a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200041d8006a29030021062000290350210702400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d830120034101742200200420042000491b22004100480d83010240024020030d002000102721030c010b200128020020032000102821030b2003450d6c20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012006370008200120073700000c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d820120034101742205200420042005491b22054100480d82010240024020030d002005102721040c010b200128020020032005102821040b2004450d6c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d820120044101742203200520052003491b22034100480d82010240024020040d002003102721040c010b200128020020042003102821040b2004450d6d20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d820120044101742203200520052003491b22034100480d82010240024020040d002003102721040c010b200128020020042003102821040b2004450d6e20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041296a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d810120034101742205200420042005491b22054100480d81010240024020030d002005102721040c010b200128020020032005102821040b2004450d6e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d810120044101742203200520052003491b22034100480d81010240024020040d002003102721040c010b200128020020042003102821040b2004450d6f20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041096a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d800120034101742205200420042005491b22054100480d80010240024020030d002005102721040c010b200128020020032005102821040b2004450d6f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d800120034101742200200520052000491b22004100480d80010240024020030d002000102721030c010b200128020020032000102821030b2003450d7020012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d7f20034101742205200420042005491b22054100480d7f0240024020030d002005102721040c010b200128020020032005102821040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d7f20044101742203200520052003491b22034100480d7f0240024020040d002003102721040c010b200128020020042003102821040b2004450d7120012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a2900003700002003200429000037000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d7f20034101742205200420042005491b22054100480d7f0240024020030d002005102721040c010b200128020020032005102821040b2004450d7220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00293a00000c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d7e20034101742205200420042005491b22054100480d7e0240024020030d002005102721040c010b200128020020032005102821040b2004450d7220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d7e20044101742203200520052003491b22034100480d7e0240024020040d002003102721040c010b200128020020042003102821040b2004450d7320012004360200200141046a2003360200200141086a28020021030b200141086a2205200341206a360200200420036a220341186a200041096a220441186a290000370000200341106a200441106a290000370000200341086a200441086a29000037000020032004290000370000200028022c21082002200041346a280200220036020c2002410c6a2001103002400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d7e20044101742203200520052003491b22034100480d7e0240024020040d002003102721040c010b200128020020042003102821040b2004450d7420012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a2008200010ce041a0c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d7d20034101742205200420042005491b22054100480d7d0240024020030d002005102721040c010b200128020020032005102821040b2004450d7420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410c3a0000200041026a2104200141046a280200210820052802002103024020002d00014101460d000240024020082003460d00200128020021000c010b200341016a22002003490d7e20034101742205200020002005491b22054100480d7e0240024020030d002005102721000c010b200128020020032005102821000b2000450d7620012000360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200020036a41003a000002400240200141046a28020020052802002200460d00200128020021030c010b200041016a22032000490d7e20004101742205200320032005491b22054100480d7e0240024020000d002005102721030c010b200128020020002005102821030b2003450d7720012003360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200320006a20042d00003a00000c020b0240024020082003460d00200128020021000c010b200341016a22002003490d7d20034101742205200020002005491b22054100480d7d0240024020030d002005102721000c010b200128020020032005102821000b2000450d7720012000360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200020036a41013a000002400240200141046a2802002203200528020022006b4120490d00200128020021030c010b200041206a22052000490d7d20034101742200200520052000491b22004100480d7d0240024020030d002000102721030c010b200128020020032000102821030b2003450d7820012003360200200141046a2000360200200141086a28020021000b200141086a200041206a360200200320006a220141186a200441186a290000370000200141106a200441106a290000370000200141086a200441086a290000370000200120042900003700000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d7c20034101742205200420042005491b22054100480d7c0240024020030d002005102721040c010b200128020020032005102821040b2004450d7820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410d3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d7c20034101742205200420042005491b22054100480d7c0240024020030d002005102721040c010b200128020020032005102821040b2004450d7920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000290308210602400240200141046a2802002204200528020022036b4108490d00200128020021040c010b200341086a22052003490d7c20044101742203200520052003491b22034100480d7c0240024020040d002003102721040c010b200128020020042003102821040b2004450d7a20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341086a360200200420036a200637000002400240200141046a2802002204200528020022036b4120490d00200128020021040c010b200341206a22052003490d7c20044101742203200520052003491b22034100480d7c0240024020040d002003102721040c010b200128020020042003102821040b2004450d7b20012004360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200420036a220141186a200041106a220041186a290000370000200141106a200041106a290000370000200141086a200041086a290000370000200120002900003700000b200241106a24000f0b20054101102a000b20044101102a000b20044101102a000b20054101102a000b20054101102a000b20034101102a000b20004101102a000b20054101102a000b20054101102a000b20034101102a000b20004101102a000b20054101102a000b20034101102a000b20054101102a000b20034101102a000b20034101102a000b20034101102a000b20004101102a000b20054101102a000b20054101102a000b20004101102a000b20054101102a000b20034101102a000b20004101102a000b20054101102a000b20034101102a000b20004101102a000b20054101102a000b20054101102a000b20004101102a000b20094101102a000b20094101102a000b20034101102a000b20004101102a000b20094101102a000b20034101102a000b20034101102a000b20004101102a000b20054101102a000b20094101102a000b20034101102a000b20054101102a000b20054101102a000b20054101102a000b20094101102a000b20004101102a000b20094101102a000b20004101102a000b20094101102a000b20004101102a000b20094101102a000b20034101102a000b20084101102a000b20094101102a000b20034101102a000b20034101102a000b20094101102a000b20034101102a000b20094101102a000b20034101102a000b20034101102a000b20004101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20034101102a000b20034101102a000b20054101102a000b20034101102a000b20054101102a000b20004101102a000b20054101102a000b20044101102a000b20004101102a000b102b000b20054101102a000b20044101102a000b20004101102a000b20004101102a000b20044101102a000b20044101102a000b20054101102a000b20054101102a000b20004101102a000b20054101102a000b20004101102a000b20054101102a000b20034101102a000b20034101102a000b20034101102a000b20054101102a000b20004101102a000b20054101102a000b20004101102a000b20054101102a000b20054101102a000b20034101102a000b20034101102a000b20004101102a000b20054101102a000b20034101102a000b20034101102a000b20054101102a000b20034101102a000b20054101102a000b20004101102a000b20054101102a000b20034101102a000b20054101102a000b20054101102a000b20034101102a000b20034101102a000b20054101102a000b20054101102a000b20054101102a000b20054101102a000b20004101102a000b20054101102a000b20054101102a000b20034101102a000b20034101102a000b102b000bde1f01047f0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d0000220241054b0d0002400240024002400240024020020e06000102030405000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d1c20024101742204200320032004491b22044100480d1c0240024020020d002004102721030c010b200128020020022004102821030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41003a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1c20034101742202200420042002491b22024100480d1c0240024020030d002002102721030c010b200128020020032002102821030b2003450d0820012003360200200141046a2002360200200141086a28020021020b200141086a2204200241206a360200200320026a220241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a290000370000200220002900013700002000280244210502400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d1c20034101742202200420042002491b22024100480d1c0240024020030d002002102721030c010b200128020020032002102821030b2003450d0920012003360200200141046a2002360200200141086a28020021020b200141086a2204200241046a360200200320026a200536000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1c20034101742202200420042002491b22024100480d1c0240024020030d002002102721030c010b200128020020032002102821030b2003450d0a20012003360200200141046a2002360200200141086a28020021020b200141086a2204200241206a360200200320026a220241186a200041216a220341186a290000370000200241106a200341106a290000370000200241086a200341086a290000370000200220032900003700002000280248210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d1c20024101742200200420042000491b22004100480d1c0240024020020d002000102721020c010b200128020020022000102821020b2002450d0b20012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d1b20024101742204200320032004491b22044100480d1b0240024020020d002004102721030c010b200128020020022004102821030b2003450d0b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1b20034101742202200420042002491b22024100480d1b0240024020030d002002102721030c010b200128020020032002102821030b2003450d0c20012003360200200141046a2002360200200141086a28020021020b200141086a2204200241206a360200200320026a220241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a2900003700002002200029000137000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1b20034101742202200420042002491b22024100480d1b0240024020030d002002102721030c010b200128020020032002102821030b2003450d0d20012003360200200141046a2002360200200141086a28020021020b200141086a2204200241206a360200200320026a220241186a200041216a220341186a290000370000200241106a200341106a290000370000200241086a200341086a2900003700002002200329000037000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d1b20024101742204200320032004491b22044100480d1b0240024020020d002004102721030c010b200128020020022004102821030b2003450d0e20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00413a00002000280244210502400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d1b20034101742202200420042002491b22024100480d1b0240024020030d002002102721030c010b200128020020032002102821030b2003450d0f20012003360200200141046a2002360200200141086a28020021020b200141086a2204200241046a360200200320026a20053600002000280248210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d1b20024101742200200420042000491b22004100480d1b0240024020020d002000102721020c010b200128020020022000102821020b2002450d1020012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d1a20024101742204200320032004491b22044100480d1a0240024020020d002004102721030c010b200128020020022004102821030b2003450d1020012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1a20034101742202200420042002491b22024100480d1a0240024020030d002002102721030c010b200128020020032002102821030b2003450d1120012003360200200141046a2002360200200141086a28020021020b200141086a200241206a360200200320026a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d1920024101742204200320032004491b22044100480d190240024020020d002004102721030c010b200128020020022004102821030b2003450d1120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1920034101742202200420042002491b22024100480d190240024020030d002002102721030c010b200128020020032002102821030b2003450d1220012003360200200141046a2002360200200141086a28020021020b200141086a200241206a360200200320026a220141186a200041196a290000370000200141106a200041116a290000370000200141086a200041096a290000370000200120002900013700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d1820024101742204200320032004491b22044100480d180240024020020d002004102721030c010b200128020020022004102821030b2003450d1220012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41043a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1820034101742202200420042002491b22024100480d180240024020030d002002102721030c010b200128020020032002102821030b2003450d1320012003360200200141046a2002360200200141086a28020021020b200141086a2204200241206a360200200320026a220241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a2900003700002002200029000137000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d1820024101742204200320032004491b22044100480d180240024020020d002004102721030c010b200128020020022004102821030b2003450d1420012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20002d00213a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d1720024101742204200320032004491b22044100480d170240024020020d002004102721030c010b200128020020022004102821030b2003450d1420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41053a000002400240200141046a2802002203200428020022026b4120490d00200128020021030c010b200241206a22042002490d1720034101742202200420042002491b22024100480d170240024020030d002002102721030c010b200128020020032002102821030b2003450d1520012003360200200141046a2002360200200141086a28020021020b200141086a2204200241206a360200200320026a220241186a200041196a290000370000200241106a200041116a290000370000200241086a200041096a2900003700002002200029000137000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d1720024101742204200320032004491b22044100480d170240024020020d002004102721030c010b200128020020022004102821030b2003450d1620012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20002d00213a00000b0f0b20044101102a000b20024101102a000b20024101102a000b20024101102a000b20004101102a000b20044101102a000b20024101102a000b20024101102a000b20044101102a000b20024101102a000b20004101102a000b20044101102a000b20024101102a000b20044101102a000b20024101102a000b20044101102a000b20024101102a000b20044101102a000b20044101102a000b20024101102a000b20044101102a000b102b000b130020004102360204200041bce4c1003602000b130020004102360204200041d0cbc5003602000b130020004101360204200041e0e7c2003602000b1300200041033602042000419085c0003602000b130020004103360204200041a89ec4003602000b130020004101360204200041ccc8c5003602000b13002000410b3602042000418ccbc3003602000b130020004106360204200041808bc2003602000b130020004104360204200041f8bec0003602000b130020004103360204200041f8c1c5003602000b130020004105360204200041dca1c1003602000b130020004106360204200041b484c2003602000b130020004101360204200041f888c0003602000bb10501027f4190ce0021024100210302400240024002400240024002400240024002400240024002400240024002400240024020012802000e1200110c0c1101020304090a0b11110d110e11000b417f2102200141086a280200417f6a220141054b0d0e41012103024002400240024020010e06140001020303140b41c0843d21020c120b4190ce0021020c120b41c09a0c21020c110b4190ce0021020c100b200141086a280200417f6a220141014b0d0d41c0843d21024100210320010e020f030f0b200141086a2d0000417f6a2201410c4b0d0c41a0c21e21024100210302400240024020010e0d111100000101111101020c0c0c110b4180b51821020c0f0b41b0e32d21020c0e0b4101210341f0930921020c0e0b41f0930921020c0c0b200141086a2d0000417f6a220141104b0d0a41c096b10221024100210320010e110c0c010100000c0c0101070702020203030c0b4101210341a0c21e21020c0b0b41c09a0c21020c090b41a08d0621020c080b41a0c21e21020c070b20012d0004417f6a220141034b0d054101210341a08d0621020240024020010e0409090001090b41c096b10221020c080b41c09a0c21020c070b20012d0004417f6a220141034b0d044101210341a08d0621020240024020010e0408080001080b41c096b10221020c070b41c09a0c21020c060b200141086a280200417f6a220141094b0d0341a0cb98012102410021030240024020010e0a07070700070102020202070b41d0a5cc0021020c050b4180ade20421020c040b410121034190ce0021020c040b200141086a280200417f6a220141024b0d0141a0c21e210241002103024020010e03040000040b4101210341a08d0621020c030b410121032001280204417f6a220141014b0d0041c0843d210220010e020200020b4190ce0021020b410021030b200020033a0004200020023602000be4910108017f017e097f017e037f017e0e7f067e230041a0076b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e12000102030405060708090a0b0c0f10111213000b200141106a29030021042001410c6a280200210520022d0001210620022d000021020240024002400240024002400240024002400240200141086a28020022070e0700010203040607000b20034194036a41013602002003420137028403200341ccfdc40036028003200341023602dc06200341c4fdc4003602d8062003200341d8066a3602900320034180036a4190b8c3001057000b4100210841ad88c3004100200220067241ff01711b21094128210a4101210b0c4a0b2004a7210702400240200241ff01710d004101210b200641ff01714101460d010b41d588c3002109412a210a4101210b410021082007450d4a0c490b20070d020c470b4101210b0240200220067241ff0171450d0041ad88c30021094128210a410021080c490b410810272202450d192002200437000041a0b8c300410a200241081003200210290c460b2004a721070240200220067241ff0171450d0041ad88c30021094128210a4101210b4100210820070d470c480b41aab8c300410520052004422088a710034101210b2007450d450b200510290c440b2004422088a721092004a7210a0240200220067241ff0171450d0002402009450d00200941186c21082005210203400240200241046a280200450d00200228020010290b0240200241106a280200450d002002410c6a28020010290b200241186a2102200841686a22080d000b0b41ad88c30021094101210c4100210d200a0d020c430b0240200941186c2202450d00200520026a21082005210203402002280200200241086a2802002002410c6a280200200241146a2802001003200241186a22022008470d000b0b02402009450d00200941186c21082005210203400240200241046a280200450d00200228020010290b0240200241106a280200450d002002410c6a28020010290b200241186a2102200841686a22080d000b0b4101210c200a450d41200510290c410b2004422088a721092004a7210a200220067241ff0171450d0102402009450d002009410c6c21082005210203400240200241046a280200450d00200228020010290b2002410c6a2102200841746a22080d000b0b41ad88c30021094100210c4101210d200a450d410b200510290c400b02402009410c6c2202450d00200520026a21082005210203402002280200200241086a280200100c2002410c6a22022008470d000b0b02402009450d002009410c6c21082005210203400240200241046a280200450d00200228020010290b2002410c6a2102200841746a22080d000b0b4101210d200a450d3d200510290c3d0b10ae02000b418988c30021094124210a4101210820022d00000d2a20022d000141ff01714102470d2a200141086a290300210420034190056a41086a22024200370300200342003703900541bdcbc500411320034190056a100420034190046a41086a200229030037030020032003290390053703900420034190046a411041b8d6c50041004100100b417f470d12200341186a41ceecc200410d109401024002402003290320500d002003280218450d00200341086a41ceecc200410d109401200329031042b9067c42b90620032802081b2004560d010b20034190056a41086a22024200370300200342003703900541ceecc200410d20034190056a100420034190046a41086a22062002290300370300200320032903900537039004200320043703800320034190046a411020034180036a4108100341012108200341013a00800320024200370300200342003703900541bdcbc500411320034190056a10042006200229030037030020032003290390053703900420034190046a411020034180036a410110030c0b0b41e8ebc2001058000b20034188036a2001410c6a2802003602002003200129020437038003200341286a20034180036a20022d000020022d000110af02200328022c210a200328022821094100210b410121080c3f0b10b002000b200341fc026a41026a22062001410f6a2d00003a0000200341f0046a41086a2207200141206a290300370300200341f0046a410d6a2209200141256a290000370000200320012f000d3b01fc022003200141186a2903003703f004200141386a290300210e200141306a2903002104200141146a280200210f200141106a28020021082001410c6a2d0000211020022d0001211120022d0000210a024002400240200141086a2802000e03000102000b20034180036a41146a41013602002003420137028403200341ccfdc40036028003200341023602dc06200341c4fdc4003602d8062003200341d8066a3602900320034180036a41c0bec0001057000b2002411a6a2901002112200241196a2d00002113200241186a2d00002114200241166a2f01002115200241156a2d00002116200241146a2d00002117200241126a2f0100210b200241116a2d00002105200241106a2d0000210c2002410e6a2f0100210d2002410d6a2d000021182002410c6a2d000021192002410a6a2f0100211a200241096a2d0000211b200241086a2d0000211c200241066a2f0100211d200241056a2d0000211e200241046a2d0000211f200241026a2f0100212020034188046a41026a20062d00003a000020034198066a41086a200729030037030020034198066a410d6a2009290000370000200320032f01fc023b018804200320032903f004370398064101210241d588c300210941002106412a210702400240200a41ff0171450d004100210a0c010b4100210a201141ff01714101470d00201d410874201e72201c41187472210941002102201b2107201a21062019210a0b200641ffff0371410874200741ff017172200a41187472210a20020d32200320123703e805200320133a00e705200320143a00e605200320153b01e405200320163a00e305200320173a00e2052003200b3b01e005200320053a00df052003200c3a00de052003200d3b01dc05200320183a00db052003200a3600d705200320093600d3052003201f3a00d205200320203b01d005200341b8066a41026a220220034188046a41026a2d00003a0000200320032f0188043b01b80620034180036a41086a20034198066a41086a29030037030020034180036a410d6a220620034198066a410d6a2900003700002003200329039806370380030240201041ff01714101460d00200341c8066a41026a20022d00003a0000200341b0046a41086a20034180036a41086a290300370300200341b0046a410d6a2006290000370000200320032f01b8063b01c80620032003290380033703b0040c2e0b20034190046a200841067610cc012003280290042106024002402003280298042008413f7122024b0d00410021020c010b200341c8066a41026a200620024105746a220241026a2d00003a0000200341b8046a200241136a290000370300200341bd046a200241186a290000370000200320022f00003b01c8062003200229000b3703b0042002280007210f20022800032108410121020b0240200328029404450d00200610290b20020d2d410121024115210f4184efc20021080c2e0b200141c8006a2903002112200141c0006a290300212120034198066a41026a20062d00003a0000200341d8066a41086a2007290300370300200341d8066a410d6a2009290000370000200320032f01fc023b019806200320032903f0043703d80602402011200a7241ff0171450d0041ad88c30021094128210a410121084101210b0c3e0b200341b8066a41026a220220034198066a41026a2d00003a000020034180036a41086a2206200341d8066a41086a29030037030020034180036a410d6a2207200341d8066a410d6a290000370000200320032f0198063b01b806200320032903d806370380030240201041ff01714101460d00200341c8066a41026a20022d00003a0000200341b0046a41086a2006290300370300200341b0046a410d6a2007290000370000200320032f01b8063b01c80620032003290380033703b0040c2b0b200341d0056a200841067610cc0120032802d00521060240024020032802d8052008413f7122024b0d00410021020c010b200341c8066a41026a200620024105746a220241026a2d00003a0000200341b8046a200241136a290000370300200341bd046a200241186a290000370000200320022f00003b01c8062003200229000b3703b0042002280007210f20022800032108410121020b024020032802d405450d00200610290b20020d2a410121024184efc20021084115210f0c2b0b20034180036a41306a200141386a29030037030020034180036a41286a200141306a29030037030020034180036a41206a200141286a29030037030020034180036a41186a200141206a29030037030020034180036a41106a200141186a29030037030020034180036a41086a200141106a2903003703002003200141086a29030037038003200341d8066a41206a200241206a290200370300200341d8066a41186a200241186a290200370300200341d8066a41106a200241106a290200370300200341d8066a41086a200241086a290200370300200320022902003703d80620034190026a20034180036a200341d8066a10b102200328029402210a20032802900221094100210f410121084101210b0c3d0b200141086a280200210c2001280204210d200341d8066a2001410c6a41c40010ce041a2002411a6a2901002104200241196a2d00002106200241186a2d00002107200241166a2f01002111200241156a2d0000210f200241146a2d00002110200241126a2f01002113200241116a2d00002114200241106a2d000021152002410e6a2f010021162002410d6a2d000021172002410c6a2d0000210b2002410a6a2f01002105200241096a2d00002118200241086a2d00002119200241066a2f0100211a200241056a2d0000211b200241046a2d0000211c200241026a2f0100211d20022d0001210820022d00002102200341e8046a20034194076a290200370300200341e0046a2003418c076a290200370300200341d8046a20034184076a290200370300200341d0046a200341fc066a290200370300200341b0046a41186a200341f4066a290200370300200341b0046a41106a200341d8066a41146a290200370300200341b0046a41086a200341d8066a410c6a290200370300200320032902dc063703b00441d588c3002109412a210a20020d26200841ff01714101470d26200320043703a805200320063a00a705200320073a00a605200320113b01a4052003200f3a00a305200320103a00a205200320133b01a005200320143a009f05200320153a009e05200320163b019c05200320173a009b052003201c3a0092052003201d3b01900520032005410874201872200b41187472360097052003201a410874201b722019411874723600930520034180036a20034190056a108d0220032802a0032202450d0e200341d0056a41106a20034180036a41386a290300370300200341d0056a41086a20034180036a41306a290300370300200341d0056a41186a200341c0036a290300370300200341d0056a41206a200341c8036a28020036020020034190046a41086a200341dc056a29020037030020034190046a41106a2208200341e4056a29020037030020034190046a41186a200341ec056a290200370300200320034180036a41286a2903003703d005200320032902d40537039004024020032802a403450d00200210290b200341f0046a41086a20034190046a41086a290300370300200341f0046a41106a2008290300370300200341f0046a41186a20034190046a41186a29030037030020032003290390043703f00420034190056a41386a200341b0046a41386a29030037030020034190056a41306a200341b0046a41306a29030037030020034190056a41286a200341b0046a41286a29030037030020034190056a41206a200341b0046a41206a29030037030020034190056a41186a200341b0046a41186a29030037030020034190056a41106a200341b0046a41106a29030037030020034190056a41086a200341b0046a41086a290300370300200320032903b0043703900520034198066a200341f0046a108d0120034180036a200328029806220220032802a006108e010240024020032d0080034101460d00200341003a00d0050c010b200341d0056a20034180036a41c10010ce041a0b0240200328029c06450d00200210290b20034190056a41206a2105200341f1056a2118200341d0056a410172211941042109410a2107034002400240200741766a2213410a4b22160d0020034190056a21060240024020130e0b0102020202020202020200010b200521060b0240412010272208450d0020082006290000370000200841186a200641186a290000370000200841106a200641106a290000370000200841086a200641086a29000037000041202102410021150c020b41204101102a000b4101211541b8d6c500210641002102410121080b200320023602c406200320023602c006200320083602bc06200320073602b806200341c8066a200341b8066a108f0120032802d006210a20032802c806211120034100360280032011200a20034180036a1005211002400240200328028003220a417f460d0020034190046a200a4120200a4120491b220f6a410041004120200f6b200f411f4b1b10cd041a20034190046a2010200f10ce041a200a411f4d0d1220034180036a41186a220a20034190046a41186a29030037030020034180036a41106a220f20034190046a41106a29030037030020034180036a41086a221420034190046a41086a2903003703002003200329039004370380032010102920034198066a41186a2210200a29030037030020034198066a41106a2217200f29030037030020034198066a41086a220b2014290300370300200320032903800337039806024020032802cc06450d00201110290b02402002450d00200810290b200a2010290300370300200f20172903003703002014200b29030037030020032003290398063703800320034180036a200341f0046a412010d004450d0141b0e2c10021094118210a0c290b024020032802cc06450d00201110290b2002450d00200810290b0240024020032d00d0054101470d004100210841b8d6c500210a024020160d000240024020130e0b0002020202020202020201000b412021082019210a0c010b412021082018210a0b024020022008470d002006200a460d022006200a200210d004450d020b0240024020080d00410121110c010b200810272211450d142011200a200810ce041a0b2003200836028c0320032008360288032003201136028403200320073602800320034198066a20034180036a108f01200328029806220a20032802a006100c0240200328029c06450d00200a10290b2008450d00201110290b4101210a024020150d0020021027220a450d14200a2006200210ce041a0b2003200236028c0320032002360288032003200a36028403200320073602800320034198066a20034180036a108f0120032802a00621072003280298062106412010272208450d14200820032903f004370000200841186a200341f0046a41186a290300370000200841106a200341f0046a41106a290300370000200841086a200341f0046a41086a29030037000020062007200841201003200810290240200328029c06450d00200610290b2002450d00200a10290b024020094108460d00200941d0e3c1006a2802002107200941046a21090c010b0b20034180036a200341f0046a108d0120032802880321062003280280032108412010272202450d132002200329039005370000200241186a20034190056a41186a290300370000200241106a20034190056a41106a290300370000200241086a20034190056a41086a2903003700002002412041c00010282202450d14200220032903b005370020200241386a20034190056a41386a290300370000200241306a20034190056a41306a290300370000200241286a20034190056a41286a29030037000020082006200241c0001003200210290240200328028403450d00200810290b200341013a00800320034190056a41086a22024200370300200342003703900541a7c8c500410f20034190056a100420034190046a41086a200229030037030020032003290390053703900420034190046a411020034180036a41011003410021090240200c450d00200d10290b0c270b20034180036a41306a200141386a29030037030020034180036a41286a200141306a29030037030020034180036a41206a200141286a29030037030020034180036a41186a200141206a29030037030020034180036a41106a200141186a29030037030020034180036a41086a200141106a2903003703002003200141086a29030037038003200341d8066a41206a200241206a290200370300200341d8066a41186a200241186a290200370300200341d8066a41106a200241106a290200370300200341d8066a41086a200241086a290200370300200320022902003703d80620034198026a20034180036a200341d8066a10b202200328029c02210a200328029802210941002113410121084101210b4101210f410121100c3d0b200341d8066a41206a200141246a290200370300200341d8066a41186a2001411c6a290200370300200341d8066a41106a200141146a290200370300200341d8066a41086a2001410c6a290200370300200320012902043703d80620034180036a41206a200241206a29020037030020034180036a41186a200241186a29020037030020034180036a41106a200241106a29020037030020034180036a41086a200241086a2902003703002003200229020037038003200341a0026a200341d8066a20034180036a10b30220032802a402210a20032802a002210941002114410121084101210b4101210f41012110410121130c3d0b200341d8066a41206a200141246a290200370300200341d8066a41186a2001411c6a290200370300200341d8066a41106a200141146a290200370300200341d8066a41086a2001410c6a290200370300200320012902043703d80620034180036a41206a200241206a29020037030020034180036a41186a200241186a29020037030020034180036a41106a200241106a29020037030020034180036a41086a200241086a2902003703002003200229020037038003200341a8026a200341d8066a20034180036a10b40220032802ac02210a20032802a802210941002115410121084101210b4101210f4101211041012113410121140c3d0b20034180036a41386a200141c0006a29030037030020034180036a41306a200141386a29030037030020034180036a41286a200141306a29030037030020034180036a41206a200141286a29030037030020034180036a41186a200141206a29030037030020034180036a41106a200141186a29030037030020034180036a41086a200141106a2903003703002003200141086a29030037038003200341d8066a41206a200241206a290200370300200341d8066a41186a200241186a290200370300200341d8066a41106a200241106a290200370300200341d8066a41086a200241086a290200370300200320022902003703d806200341b0026a20034180036a200341d8066a10c90120032802b402210a20032802b002210941002116410121084101210b4101210f410121104101211341012114410121150c3d0b418988c30021094124210a4101210820022d00000d2020022d000141ff01714102470d20200141086a290300210420034190056a41086a22024200370300200342003703900541a18ac000411020034190056a100420034190046a41086a200229030037030020032003290390053703900420034190046a411041b8d6c50041004100100b417f470d10200341b8026a41888dc300410d10940120032903c002420020032802b8021b2004540d0120034190056a41086a22024200370300200342003703900541a18ac000411020034190056a100420034190046a41086a2002290300370300200320032903900537039004200320043703800320034190046a411020034180036a410810030b410021094101210b0c350b41f08bc0001058000b200141086a2802002106200128020421070240024020022d00000d004101210820022d000141ff01714101460d010b41d588c3002109412a210a41002117410121082006450d1d200710290c1d0b200241096a280000210a2006450d1b200710290c1b0b20034180036a41306a200141386a29030037030020034180036a41286a200141306a29030037030020034180036a41206a200141286a29030037030020034180036a41186a200141206a29030037030020034180036a41106a200141186a29030037030020034180036a41086a200141106a2903003703002003200141086a29030037038003200341d8066a41206a200241206a290200370300200341d8066a41186a200241186a290200370300200341d8066a41106a200241106a290200370300200341d8066a41086a200241086a290200370300200320022902003703d806200341c8026a20034180036a200341d8066a10f50120032802cc02210a20032802c8022109410121084101210b0c320b20034180036a200141086a41800110ce041a200341d8066a41206a200241206a290200370300200341d8066a41186a200241186a290200370300200341d8066a41106a200241106a290200370300200341d8066a41086a200241086a290200370300200320022902003703d806200341d0026a20034180036a200341d8066a10b50220032802d402210a20032802d002210941002106410121084101210b4101210f4101211041012113410121144101211541012116410121170c390b200141086a280200210820012802042106200341f0046a41086a22092001411c6a290200370300200341f0046a410d6a220a200141216a2900003700002003200141146a2902003703f0042002411a6a2901002104200241196a2d00002111200241186a2d0000210f200241166a2f01002110200241156a2d00002113200241146a2d00002114200241126a2f01002115200241116a2d00002116200241106a2d000021172002410e6a2f0100210b2002410d6a2d000021052002410c6a2d0000210c2002410a6a2f0100210d200241096a2d00002118200241086a2d00002119200241066a2f0100211a200241056a2d0000211b200241046a2d0000211c200241026a2f0100211d20022d0001210720022d0000210202400240024020060e03000201000b20034180036a41146a41013602002003420137028403200341ccfdc40036028003200341023602dc06200341c4fdc4003602d8062003200341d8066a3602900320034180036a4194e6c1001057000b200141106a28020021202001410c6a280200211f20034198066a410d6a200a29000037000020034198066a41086a2009290300370300200320032903f0043703980641012106412a210a4100211e41d588c300210902400240200241ff0171450d00410021020c010b41002102200741ff01714101470d00201a410874201b72201941187472210941002106200c211e200d21022018210a0b200241ffff0371410874201e41187472200a41ff017172210a20060d16200320043703e805200320113a00e7052003200f3a00e605200320103b01e405200320133a00e305200320143a00e205200320153b01e005200320163a00df05200320173a00de052003200b3b01dc05200320053a00db052003200a3600d705200320093600d3052003201c3a00d2052003201d3b01d00520034190056a41086a22024200370300200342003703900541a4e6c100410820034190056a1004200341d8066a41086a200229030037030020032003290390053703d8062003410036028003200341d8066a411020034180036a10052102024002402003280280032206417f460d002002450d0020034180036a2006412020064120491b22076a41004100412020076b2007411f4b1b10cd041a20034180036a2002200710ce041a2006411f4d0d0e20034190046a41186a220620034180036a41186a220729000037030020034190046a41106a220920034180036a41106a220a29000037030020034190046a41086a221120034180036a41086a220f2900003703002003200329008003370390042002102920072006290300370300200a2009290300370300200f20112903003703002003200329039004370380030c010b20034188036a420037030020034190036a420037030020034198036a420037030020034200370380030b0240200341d0056a20034180036a412010d004450d0041ace6c10021094131210a0c170b20034180036a410d6a220220034198066a410d6a29000037000020034180036a41086a220620034198066a41086a2903003703002003200329039806370380030240200841ff01714101460d0020034190056a410d6a200229000037000020034190056a41086a2006290300370300200320032903800337039005200841087621080c140b20034190046a201f41067610cc01200328029004210602400240200328029804201f413f7122024b0d00410021020c010b20034198056a200620024105746a220241136a2900003703002003419d056a200241186a2900003700002003200229000b3703900520022f0000200241026a2d0000411074722108200228000721202002280003211f410121020b0240200328029404450d00200610290b20020d1341012106411521204184efc200211f0c140b4101210641d588c30021094100210a412a211e02400240200241ff0171450d00410021020c010b41002102200741ff01714101470d00201a410874201b722019411874722109410021062018211e200d210a200c21020b200a41ffff0371410874201e41ff017172200241187472210a20060d112003201c3a00d2052003201d3b01d005200320043703e805200320113a00e7052003200f3a00e605200320103b01e405200320133a00e305200320143a00e205200320153b01e005200320163a00df05200320173a00de052003200b3b01dc05200320053a00db052003200a3600d705200320093600d30520034190056a41086a22024200370300200342003703900541a4e6c100410820034190056a1004200341d8066a41086a200229030037030020032003290390053703d8062003410036028003200341d8066a411020034180036a10052102024002402003280280032206417f460d002002450d0020034180036a2006412020064120491b22076a41004100412020076b2007411f4b1b10cd041a20034180036a2002200710ce041a2006411f4d0d0e20034190046a41186a220620034180036a41186a220729000037030020034190046a41106a220920034180036a41106a220a29000037030020034190046a41086a221120034180036a41086a220f2900003703002003200329008003370390042002102920072006290300370300200a2009290300370300200f20112903003703002003200329039004370380030c010b20034188036a420037030020034190036a420037030020034198036a420037030020034200370380030b0240200341d0056a20034180036a412010d004450d0041dde6c10021094122210a0c120b20034180036a200841880110ce041a41002109200341003b01d806200341d8026a20034180036a200341d8066a10ad020240024020032802d80222020d00410121020c010b200220032802dc021010410021020b200320023a0082032003410c3b01800341b8d6c500410020034180036a108801200810290c140b200141d4006a2802002110200141d0006a280200211320022d0001210820022d00002102200341d8066a200141086a41c80010ce041a02400240024020020d00200841ff01714102460d010b02402010450d00201310290b0240200341e4066a280200450d0020032802e00610290b200341ec066a28020021060240200341f4066a2802002202450d002002410c6c21082006210203400240200241046a280200450d00200228020010290b2002410c6a2102200841746a22080d000b0b418988c3002109200341f0066a280200450d01200610290c010b200341f0026a4193c8c500411410b50120034180036a20032802f402410020032802f0021b2214200341fc066a221510b201200328028003220820032802880341b8d6c50041004100100b21020240200328028403450d00200810290b02402002417f470d00200341e0026a41888dc300410d10940120034188036a20032903e802420020032802e0021b37030020034180036a41106a20032902fc0637030020034198036a20034184076a290200370300200341a0036a2003418c076a290200370300200341a8036a20034194076a2902003703002003410d3a00800341b8d6c500410020034180036a1088012003410036028803200342013703800320032802e00621072003200341d8066a41106a28020022023602d005200341d0056a20034180036a103002400240200328028403220620032802880322086b2002490d0020032802800321060c010b200820026a22092008490d122006410174220a20092009200a491b22094100480d120240024020060d002009102721060c010b20032802800320062009102821060b2006450d0f200320093602840320032006360280030b2003200820026a36028803200620086a2007200210ce041a200341ec066a28020021082003200341f4066a28020022023602d005200341d0056a20034180036a10300240024020020d002003280288032111200328028403210920032802800321070c010b20082002410c6c6a210f03402008280200210a2003200841086a28020022023602d005200341d0056a20034180036a103002400240200328028403220920032802880322066b2002490d0020032802800321070c010b200620026a22072006490d1420094101742211200720072011491b22114100480d140240024020090d002011102721070c010b20032802800320092011102821070b2007450d1220032011360284032003200736028003201121090b2003200620026a221136028803200720066a200a200210ce041a2008410c6a2208200f470d000b0b200341d0056a2014201510b20120032802d805210f20032802d005210a20034100360288032003420137038003200320113602900520034190056a20034180036a103002400240200328028403220620032802880322086b2011490d0020032802800321020c010b200820116a22022008490d1220064101742214200220022014491b22144100480d120240024020060d002014102721020c010b20032802800320062014102821020b2002450d1120032014360284032003200236028003201421060b200220086a2007201110ce041a200a200f2002200820116a100302402006450d00200210290b024020032802d405450d00200a10290b2009450d00200710290b02402010450d00201310290b0240200341e4066a280200450d0020032802e00610290b200341ec066a28020021060240200341f4066a2802002202450d002002410c6c21082006210203400240200241046a280200450d00200228020010290b2002410c6a2102200841746a22080d000b0b41002109200341f0066a280200450d00200610290b4124210a41002111410121084101210b4101210f41012110410121134101211441012115410121164101211741012106410121070c380b41084101102a000b41a0ebc2001058000b4189e2c10021094127210a0c170b418f89c3004133104e000b20084101102a000b20024101102a000b41204101102a000b41204101102a000b41c0004101102a000b41dc8ac0001058000b418f89c3004133104e000b418f89c3004133104e000b20094101102a000b20114101102a000b20144101102a000b102b000b2008103d200810290c030b20034180036a410d6a20034190056a410d6a29000037000020034180036a41086a20034190056a41086a290300370300200320032903900537038003410021060b200341d8066a41086a220220034180036a41086a290300370300200341d8066a41106a20034180036a41106a29030037030020032003290380033703d80602402006450d002020210a201f21090c020b200341b0046a410d6a200341d8066a410d6a290000370000200341b0046a41086a2002290300370300200320032903d8063703b00420034190056a41086a22064200370300200342003703900541a4e6c100410820034190056a10042002200629030037030020032003290390053703d8062003410036028003200341d8066a411020034180036a10052102024002402003280280032206417f460d002002450d0020034180036a2006412020064120491b22076a41004100412020076b2007411f4b1b10cd041a20034180036a2002200710ce041a2006411f4d0d0420034190046a41186a220620034180036a41186a220729000037030020034190046a41106a220920034180036a41106a220a29000037030020034190046a41086a221120034180036a41086a220f2900003703002003200329008003370390042002102920072006290300370300200a2009290300370300200f20112903003703002003200329039004370380030c010b20034188036a420037030020034190036a420037030020034198036a420037030020034200370380030b200341d8066a41186a20034180036a41186a2903002204370300200341d8066a41106a20034180036a41106a290300220e370300200341d8066a41086a220220034180036a41086a22062903002212370300200320032903800322213703d8062003418a036a201237010020034192036a200e3701002003419a036a20043701002003418c023b01800320032021370182034100210941b8d6c500410020034180036a10880120034180036a410d6a2207200341b0046a410d6a2900003700002006200341b0046a41086a290300370300200320032903b0043703800320034190056a41086a220a4200370300200342003703900541a4e6c100410820034190056a10042002200a29030037030020032003290390053703d806412010272202450d03200220083b0000200220203600072002201f360003200220032903800337000b200241026a20084110763a0000200241136a2006290300370000200241186a2007290000370000200341d8066a4110200241201003200210290b0b41002107410121084101210b4101210f41012110410121134101211441012115410121164101211741012106410121110c230b418f89c3004133104e000b41204101102a000b410021174101210b4101210f4101211041012113410121144101211541012116410121064101210741012111410021090c200b4101210b4101210f41012110410121134101211441012115410121160c1d0b4101210b0c150b200c450d00200d10290b41002110410121084101210b4101210f0c150b200341d0056a41026a200341c8066a41026a2d00003a000020034180036a41086a200341b0046a41086a29030037030020034180036a410d6a200341b0046a410d6a290000370000200320032f01c8063b01d005200320032903b00437038003410021020b2003418c046a41026a2206200341d0056a41026a2d00003a000020034190056a41086a220720034180036a41086a29030037030020034190056a41106a20034180036a41106a290300370300200320032f01d0053b018c0420032003290380033703900520020d0220034193036a200729030037000020034198036a2003419d056a290000370000200320032f018c043b0180032003200f360087032003200836008303200320032903900537008b03200320062d00003a00820302400240024002400240411410272202450d00200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d0120022003290380033700142002412c6a20034198036a290300370000200241246a20034180036a41106a2903003700002002411c6a20034180036a41086a290300370000200341f8016a20024134108401200341f8016a41106a2903002122200329038002212320032802f8012108200210292023420020081b222320045422062022420020081b2222200e542022200e5122021b0d0220232004562022200e5620021b450d04200341e0016a41b18ac0004116108601200341f0016a290300212420032903e801212520032802e001210220034190056a41086a22084200370300200342003703900541b18ac000411620034190056a100420034190046a41086a2008290300370300200320032903900537039004200342002024420020021b22242006ad200e20227d7c7c2025420020021b2222202320047d222554ad7d2223202220257d2225202256202320245620232024511b22021b3703d80520034200202520021b3703d005200341d0056a21020c030b41144101102a000b41344101102a000b200341c8016a41b18ac0004116108601200341d8016a290300212420032903d001212520032802c801210220034190056a41086a22084200370300200342003703900541b18ac000411620034190056a100420034190046a41086a20082903003703002003200329039005370390042003427f2024420020021b2224200e20227d2004202354ad7d7c2025420020021b2222200420237d7c22232022542202ad7c22222002202220245420222024511b22021b3703d8052003427f202320021b3703d005200341d0056a21020b20034190046a41102002411010030b20034180036a2004200e10890102400240024002400240411810272202450d00200241106a41002900cf8c40370000200241086a41002900c78c40370000200241002900bf8c4037000020024118413810282202450d012002200329038003370018200241306a20034198036a290300370000200241286a20034180036a41106a290300370000200241206a20034180036a41086a290300370000200341b0016a20024138108401200341b0016a41106a290300210420032903b801210e20032802b001210820021029200e420020081b220e20215422062004420020081b2204201254200420125122021b0d02200e202156200420125620021b450d0420034198016a41b18ac0004116108601200341a8016a290300212220032903a0012123200328029801210220034190056a41086a22084200370300200342003703900541b18ac000411620034190056a100420034190046a41086a2008290300370300200320032903900537039004200342002022420020021b22222006ad201220047d7c7c2023420020021b2204200e20217d222354ad7d220e200420237d2223200456200e202256200e2022511b22021b3703d80520034200202320021b3703d005200341d0056a21020c030b41184101102a000b41384101102a000b20034180016a41b18ac000411610860120034190016a29030021222003290388012123200328028001210220034190056a41086a22084200370300200342003703900541b18ac000411620034190056a100420034190046a41086a20082903003703002003200329039005370390042003427f2022420020021b2222201220047d2021200e54ad7d7c2023420020021b22042021200e7d7c220e2004542202ad7c22042002200420225420042022511b22021b3703d8052003427f200e20021b3703d005200341d0056a21020b20034190046a41102002411010030b20034180036a20212012109c010c040b20034190046a41026a200341c8066a41026a2d00003a000020034180036a41086a200341b0046a41086a29030037030020034180036a410d6a200341b0046a410d6a290000370000200320032f01c8063b019004200320032903b00437038003410021020b2003418c046a41026a220620034190046a41026a2d00003a000020034190056a41086a220720034180036a41086a29030037030020034190056a41106a20034180036a41106a290300370300200320032f0190043b018c042003200329038003370390052002450d010b200f210a20082109410121084101210b0c0e0b200341eb066a2007290300370000200341f0066a2003419d056a290000370000200320032f018c043b01d8062003200f3600df06200320083600db0620032003290390053700e306200320062d00003a00da06411410272202450d02200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d03200220032903d0053700142002412c6a200341e8056a290300370000200241246a200341d0056a41106a2903003700002002411c6a200341d0056a41086a290300370000200341e8006a20024134108401200341e8006a41106a2903002121200329037021222003280268210820021029411410272202450d04200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d05200220032903d8063700142002412c6a200341f0066a290300370000200241246a200341d8066a41106a2903003700002002411c6a200341d8066a41086a290300370000200341d0006a20024134108401200341d0006a41106a2903002124200329035821252003280250210620021029024020044280a094a58d1d7c22122004542202200e2002ad7c2223200e54201220045a1b450d004128210a41d0bec0002109410121084101210b0c0e0b02402022420020081b222220127d22262022562021420020081b222120237d2022201254ad7d221220215620122021511b450d00411d210a41e8b5c3002109410121084101210b0c0e0b2024420020061b21212025420020061b21220240200442ffffe883b1de1656200e420052200e501b0d00202220218450450d00411f210a4185b6c3002109410121084101210b0c0e0b200341c8006a200341d0056a4102202620121091010240200328024822090d000240202220047c222320225422022021200e7c2002ad7c222220215420222021511b450d00412d210a41a4b6c3002109410121084101210b0c0f0b200341d0056a200341d8066a412010d004450d01200341d0056a20262012108901411410272202450d07200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d08200220032903d8063700142002412c6a200341d8066a41186a2208290300370000200241246a200341d8066a41106a2903003700002002411c6a200341d8066a41086a29030037000020034180036a41186a2206420037030020034180036a41106a2207420037030020034180036a41086a2209420037030020034200370380032002413420034180036a100020034190046a41186a200629030037030020034190046a41106a200729030037030020034190046a41086a200929030037030020032003290380033703900420034190046a412041b8d6c50041004100100b21062002102902402006417f470d00200341d8066a108701200341b8036a2022370300200341b0036a202337030020034180036a41086a41003a000020034189036a20032903d80637000020034191036a200341d8066a41086a29030037000020034199036a200341e8066a290300370000200341a1036a2008290300370000200341023a00800341b8d6c500410020034180036a1088010b200341d8066a20232022108901200341306a41b18ac0004116108601200341306a41106a2903002112200329033821212003280230210220034190056a41086a22064200370300200342003703900541b18ac000411620034190056a100420034190046a41086a2006290300370300200320032903900537039004200342002012420020021b22222021420020021b22124280a094a58d1d54ad7d222120124280e0ebdaf2627c22232012562021202256201242ff9f94a58d1d561b22021b3703880320034200202320021b3703800320034190046a411020034180036a41101003200341e8036a4200370300200341e0036a4280a094a58d1d370300200341d8036a200e370300200341d0036a200437030020034180036a41086a41023a000020034189036a20032903d00537000020034191036a200341d0056a41086a29030037000020034199036a200341d0056a41106a290300370000200341a1036a200341d0056a41186a290300370000200341a9036a20032903d806370000200341b1036a200341d8066a41086a290300370000200341b9036a200341d8066a41106a290300370000200341c1036a2008290300370000200341023a00800341b8d6c500410020034180036a1088010c010b200328024c210a410121084101210b0c0d0b410021090b410121084101210b0c0b0b41144101102a000b41344101102a000b41144101102a000b41344101102a000b41144101102a000b41344101102a000b4100210c410021090c010b4100210d410021090b4128210a4101210b4100210802402007417f6a220241054b0d004101210f410121104101211341012114410121154101211641012117410121064101210741012111024002400240024020020e06100010010203100b4100210841000d062004a70d050c060b4100210841000d052004a70d040c050b200d450d0402402004422088a72202450d00200241186c21062005210203400240200241046a280200450d00200228020010290b0240200241106a280200450d002002410c6a28020010290b200241186a2102200641686a22060d000b0b2004a70d030c040b200c450d0302402004422088a72202450d002002410c6c21062005210203400240200241046a280200450d00200228020010290b2002410c6a2102200641746a22060d000b0b2004a70d020c030b02402004422088a72202450d002002410c6c21062005210203400240200241046a280200450d00200228020010290b2002410c6a2102200641746a22060d000b0b2004a70d010c020b410021084101210f410121104101211341012114410121154101211641012117410121064101210741012111410021090c0a0b200510290b4101210f0b410121100b410121130b410121140b410121150b410121160b410121170b410121060b41012107410121110b024002402001280200220241104b0d000240024002400240024002400240024002400240024020020e11000c0c010c0c0203040506070c080c090a000b2008450d0b0240200141086a280200220241054b0d0002400240024020020e060f0f000f01020f0b200141106a280200450d0e2001410c6a28020010290c0e0b200141106a280200450d0d2001410c6a28020010290c0d0b0240200141146a2802002208450d002001410c6a2802002102200841186c210803400240200241046a280200450d00200228020010290b0240200241106a280200450d002002410c6a28020010290b200241186a2102200841686a22080d000b0b200141106a280200450d0c200128020c10290c0c0b0240200141146a2802002208450d002001410c6a28020021022008410c6c210803400240200241046a280200450d00200228020010290b2002410c6a2102200841746a22080d000b0b200141106a280200450d0b200128020c10290c0b0b200b450d0a02402001410c6a2802002202450d0020012802042207200241f8006c6a211103400240200741106a2802002208450d0020072802082102200841246c210803400240024020022d0000220641034b0d0002400240024020060e0404000102040b2002410c6a280200450d03200241086a28020010290c030b2002410c6a280200450d02200241086a28020010290c020b2002410c6a280200450d01200241086a28020010290c010b200241086a280200450d00200241046a28020010290b200241246a21022008415c6a22080d000b0b200741f8006a210202402007410c6a280200450d00200728020810290b2002210720022011470d000b0b200141086a280200450d0a200128020410290c0a0b200f450d090240200141086a2d00002202410c4b0d0020024106470d0a200141106a280200450d0a2001410c6a28020010290c0a0b200141106a280200450d092001410c6a28020010290c090b2010450d08200141086a280200450d08200128020410290c080b2013450d07200141086a2d0000417f6a220241074b0d07024002400240024020020e08000b0b0b010b0203000b2001410c6a2202280200103d200228020010290c0a0b2001410c6a2202280200103d200228020010290c090b2001410c6a2202280200103d200228020010290c080b2001410c6a2202280200103d200228020010290c070b2014450d0620012d0004417f6a220241024b0d0602400240024020020e03000102000b2001410c6a280200450d08200141086a28020010290c080b200141086a2202280200103d200228020010290c070b2001410c6a2202280200103d200228020010290c060b2015450d0520012d0004417f6a220241024b0d0502400240024020020e03000102000b2001410c6a280200450d07200141086a28020010290c070b200141086a2202280200103d200228020010290c060b2001410c6a2202280200103d200228020010290c050b2016450d04200141086a280200417f6a220241014b0d040240024020020e020001000b200141106a280200450d052001410c6a28020010290c050b200141106a280200450d042001410c6a28020010290c040b2017450d03200141086a280200450d03200128020410290c030b2006450d020240200141086a2d0000220241054b0d0002400240024020020e06060600010206060b200141106a280200450d052001410c6a28020010290c050b200141346a280200450d04200141306a28020010290c040b200141306a280200450d032001412c6a28020010290c030b200141d0006a280200450d02200141cc006a28020010290c020b2007450d0120012802044101470d01200141086a2202280200103d200228020010290c010b2011450d000240200141146a280200450d00200141106a28020010290b0240200141246a2802002208450d002001411c6a28020021022008410c6c210803400240200241046a280200450d00200228020010290b2002410c6a2102200841746a22080d000b0b0240200141206a280200450d00200128021c10290b200141d4006a280200450d00200141d0006a28020010290b2000200a36020420002009360200200341a0076a24000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccfdc4003602002000410236021c200041c4fdc4003602182000200041186a360210200041908fc3001057000be42107067f017e017f017e017f027e137f230041e0026b22042400200128020821052001280204210620012802002107418988c30021084124210902400240200241ff01710d00200341ff01714102470d0020044188016a41086a22014200370300200442003703880141fcc7c500411720044188016a1004200441186a41086a200129030037030020042004290388013703182004410036028801200441186a411020044188016a10052101024002400240024002400240024002402004280288012202417f460d002001450d00200441003a00880120044188016a20012002410047220310ce041a20022003490d042002450d0120042d00880121022001102920024102460d002002410171450d0041f086c3002108411c21090c080b200441013a00c00220044188016a41086a22014200370300200442003703880141fcc7c500411720044188016a1004200441186a41086a220220012903003703002004200429038801370318200441186a4110200441c0026a41011003200441086a41888dc300410d1094012004290310210a20042802082103200142003703002004420037038801418bf4c200411120044188016a10042002200129030037030020042004290388013703182004410036028801200441186a411020044188016a10052101024002402004280288012202417f460d002001450d00200420023602c402200420013602c00220044188016a200441c0026a1046200428028801220b450d04200429028c01210c2002450d01200110290c010b4108210b4200210c0b02400240200ca7200c422088a72201470d00200141016a22022001490d012001410174220d20022002200d491bad220e42c8007e220f422088a70d01200fa722024100480d010240024020010d0020021027210b0c010b200b200141c8006c20021028210b0b200b450d03200c42808080807083200e84210c0b200b200141c8006c6a220141003a00002001200a420020031b220e37030820012004280018360001200141046a200441186a41036a2800003600002001200429038801370310200141186a20044188016a41086a290300370300200141206a20044188016a41106a290300370300200141286a20044188016a41186a290300370300200141306a20044188016a41206a290300370300200141386a20044188016a41286a290300370300200141c0006a20044188016a41306a290300370300200c4280808080107c210a2007200541f8006c6a2110024020050d00200721110c070b200441ff016a2112200441b7016a2113200441ef006a2114200441276a2115200441dc016a211620044188016a41346a21172004419c016a211820044188016a410c6a2119200441b6026a211a200441a2026a41046a211b2007211103402011280208211c2011290300210c20044188016a2011410c6a41ec0010ce041a201141f8006a2111201c450d07200441186a20044188016a41ec0010ce041a2004201c360290012004200c370388012019200441186a41ec0010ce041a200441003602b002200442013703a80202400240024002400240412010272201450d00200442a080808080043702ac02200420013602a80220012018290000370000200141086a201841086a290000370000200141106a201841106a290000370000200141186a201841186a29000037000020044188016a200441a8026a10540240024020042802ac02220220042802b00222036b4120490d00200341206a210120042802a80221050c010b200341206a22012003490d0720024101742205200120012005491b220d4100480d070240024020020d00200d102721050c010b20042802a8022002200d102821050b2005450d022004200d3602ac02200420053602a802200d21020b200420013602b002200520036a22032017290000370000200341086a201741086a290000370000200341106a201741106a290000370000200341186a201741186a2900003700000240200220016b411f4b0d00200141206a22032001490d072002410174220d20032003200d491b22034100480d070240024020020d002003102721050c010b200520022003102821050b2005450d03200420033602ac02200420053602a8020b200520016a220541086a201641086a290000370000200541106a201641106a290000370000200541186a201641186a2900003700002004200141206a3602b002200520162900003700002004200428029801221d3602c002200441c0026a200441a8026a103002400240201d0d0020042802b002210520042802ac02210820042802a80221020c010b201d41246c210920042802ac02210820042802b0022101201c21030340200441c0026a2003104f20042802c002211e02400240200820016b20042802c802220d490d002001200d6a210520042802a80221020c010b2001200d6a22052001490d0920084101742202200520052002491b221f4100480d090240024020080d00201f102721020c010b20042802a8022008201f102821020b2002450d062004201f3602ac02200420023602a802201f21080b200420053602b002200220016a201e200d10ce041a024020042802c402450d00201e10290b200341246a2103200521012009415c6a22090d000b0b200441c0026a41186a22034200370300200441c0026a41106a220d4200370300200441c0026a41086a221e4200370300200442003703c00220022005200441c0026a100020044180026a41186a2220200329030037030020044180026a41106a2221200d29030037030020044180026a41086a2222201e290300370300200420042903c0023703800202402008450d00200210290b200c50450d04418c87c3002108411021090c0b0b41204101102a000b200d4101102a000b20034101102a000b201f4101102a000b0240200c200e580d00419c87c3002108411821090c070b200441c0026a200c427f7c1087020240200441c0026a2018412010d004450d0041b487c3002108411921090c070b0240200c200e5a0d0041cd87c3002108412621090c070b200b200a422088a7220241c8006c221f6a2105200b2101024002400240024002400240201f41d901490d00200b21010340024020012d00004101470d0020122001460d07200141016a20044180026a412010d004450d070b0240200141c8006a22082d00004101470d0020132001460d03200141c9006a20044180026a412010d004450d030b024020014190016a22082d00004101470d0020142001460d0420014191016a20044180026a412010d004450d040b0240200141d8016a22082d00004101470d0020152001460d06200141d9016a20044180026a412010d004450d060b2005200141a0026a22016b41d8014b0d000b0b20052001470d02410021010c040b200821010c030b200821010c020b0340024020012d00004101470d0020122001460d03200141016a20044180026a412010d004450d030b2005200141c8006a2201470d000b410021010c010b200821010b200441c0026a200c108702200441c0026a20044180026a412010d004210541f387c30021084116210920010d062005450d06200441c0026a109801200441c0026a410210960320034200370300200d4200370300201e4200370300200442003703c002200441c0026a4101109603201e2022290300370300200d20212903003703002003202029030037030020042004290380023703c00202400240200aa72002470d00200241016a22012002490d0320024101742205200120012005491bad220c42c8007e220f422088a70d03200fa722014100480d030240024020020d0020011027210b0c010b200b201f20011028210b0b200b450d01200a42808080807083200c84210a0b200b201f6a220141013a0000200141096a201e290300370000200120042903c0023700012003290300210c200d290300210f200141003a0021200141116a200f370000200141196a200c370000200120042900a80237002c200141346a200441a8026a41086a2900003700002001413a6a201a290000370000200120042801a202360142200141c6006a201b2f01003b01000240201d450d00201d41246c2105201c210103400240024020012d0000220241034b0d0002400240024020020e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012005415c6a22050d000b0b0240200428029401450d00201c10290b200a4280808080107c210a20112010470d010c090b0b20014108102a000b102b000b418f89c3004133104e000b20024108102a000b418f89c3004133104e000b20032002103e000b0240201d450d00201d41246c2105201c210103400240024020012d0000220241034b0d0002400240024020020e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012005415c6a22050d000b0b0240200428029401450d00201c10290b024020112010460d00034020112802082203450d012011410c6a280200210d0240201141106a2802002201450d00200141246c21052003210103400240024020012d0000220241034b0d0002400240024020020e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012005415c6a22050d000b0b201141f8006a21110240200d450d00200310290b20112010470d000b0b02402006450d00200710290b200aa7450d03200b10290c030b20112010460d00034020112802082203450d012011410c6a280200210d0240201141106a2802002201450d00200141246c21052003210103400240024020012d0000220241034b0d0002400240024020020e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012005415c6a22050d000b0b201141f8006a21110240200d450d00200310290b20112010470d000b0b02402006450d00200710290b20044188016a41086a220142003703002004420037038801418bf4c200411120044188016a1004200441186a41086a200129030037030020042004290388013703184100210820044100360290012004420137038801200b200a422088a720044188016a109203200428028c012101200441186a41102004280288012205200428029001100302402001450d00200510290b0240200aa7450d00200b10290b0c010b02402005450d002007200541f8006c6a210d2007210303400240200341106a2802002205450d0020032802082101200541246c210503400240024020012d0000220241034b0d0002400240024020020e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012005415c6a22050d000b0b200341f8006a210102402003410c6a280200450d00200328020810290b200121032001200d470d000b0b2006450d00200710290b2000200936020420002008360200200441e0026a24000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccfdc4003602002000410236021c200041c4fdc4003602182000200041186a360210200041f4eec2001057000b83d50106017f037e0c7f017e157f057e23004190056b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0e000102030405060708090a0b0c0d000b2003419c046a41013602002003420137028c04200341ccfdc40036028804200341023602fc01200341c4fdc4003602f8012003200341f8016a3602980420034188046a41d4fdc4001057000b200141306a2903002104200141286a29030021052002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d00002110200241046a2d00002111200241026a2f010021122001411d6a29000021132001411c6a2d000021142001411b6a2d00002115200141196a2f00002116200141186a2d00002117200141176a2d00002118200141156a2f00002119200141146a2d0000211a200141136a2d0000211b200141116a2f0000211c200141106a2d0000211d2001410c6a280200211e200141086a280200211f200141076a2d00002120200141056a2f00002121200141046a2d0000212220012d00012123412a212441d588c30021250240024020022d0000450d004101212641002127410021280c010b41012126410021274100212820022d00014101470d002002410c6a2d000021272002410a6a2f01002128200241096a2d00002124200241066a2f0100410874200241056a2d000072200241086a2d0000411874722125410021260b202841ffff0371410874202741187472202441ff017172212420260d4f410e10272202450d3f200241066a41002900c7a244370000200241002900c1a2443700002002410e412e10282202450d3e20022006370026200220073a0025200220083a0024200220093b00222002200a3a00212002200b3a00202002200c3b001e2002200d3a001d2002200e3a001c2002200f3b001a200220103a00192002202436001520022025360011200220113a0010200220123b000e200341f0046a41186a22264200370300200341f0046a41106a22274200370300200341f0046a41086a22284200370300200342003703f0042002412e200341f0046a1000200341e8036a41186a2026290300370300200341e8036a41106a2027290300370300200341e8036a41086a2028290300370300200320032903f0043703e803200341e8036a412041b8d6c50041004100100b21262002102902402026417f460d0041aefec4002125411421240c500b0240202241ff01714101470d0020034188046a201f41067610cc01200328028804212602400240200328029004201f413f7122024b0d00410021020c010b202620024105746a2202290018211320022d0017211420022d0016211520022f0014211620022d0013211720022d0012211820022f0010211920022d000f211a20022d000e211b20022f000c211c20022d000b211d2002280007211e2002280003211f20022d0002212020022f00002121410121020b0240200328028c04450d00202610290b2002450d4f0b2003201337039002200320143a008f02200320153a008e02200320163b018c02200320173a008b02200320183a008a02200320193b0188022003201a3a0087022003201b3a0086022003201c3b0184022003201d3a0083022003201e3600ff012003201f3600fb01200320203a00fa01200320213b01f801410e10272202450d3d200241066a410029009fa34437000020024100290099a3443700002002410e412e10282202450d3c200220032903f80137000e200241266a200341f8016a41186a2903003700002002411e6a200341f8016a41106a290300370000200241166a200341f8016a41086a290300370000200341f0046a41186a22264200370300200341f0046a41106a22274200370300200341f0046a41086a22284200370300200342003703f0042002412e200341f0046a1000200341e8036a41186a2026290300370300200341e8036a41106a2027290300370300200341e8036a41086a2028290300370300200320032903f0043703e803200341e8036a412041b8d6c50041004100100b2126200210292026417f470d4d02402005428080e983b1de165441002004501b450d0041fdfdc4002125413121240c500b20034188046a41186a200341f8016a41186a29030037030020034188046a41106a200341f8016a41106a29030037030020034188046a41086a200341f8016a41086a290300370300200320032903f80137038804410e10272202450d3b200241066a41002900c7a244370000200241002900c1a2443700002002410e412e10282202450d3a20022006370026200220073a0025200220083a0024200220093b00222002200a3a00212002200b3a00202002200c3b001e2002200d3a001d2002200e3a001c2002200f3b001a200220103a00192002202436001520022025360011200220113a0010200220123b000e200341f0046a41186a22264200370300200341f0046a41106a22274200370300200341f0046a41086a22284200370300200342003703f0042002412e200341f0046a1000200341e8036a41186a2026290300370300200341e8036a41106a2027290300370300200341e8036a41086a2028290300370300200320032903f0043703e803412010272226450d392026200329038804370000202641186a20034188046a41186a290300370000202641106a20034188046a41106a290300370000202641086a20034188046a41086a290300370000200341e8036a41202026412010032026102920021029410d10272202450d38200241056a41002900aca344370000200241002900a7a3443700002002410d412d10282202450d3720022006370025200220073a0024200220083a0023200220093b00212002200a3a00202002200b3a001f2002200c3b001d2002200d3a001c2002200e3a001b2002200f3b0019200220103a00182002202436001420022025360010200220113a000f200220123b000d200341f0046a41186a22264200370300200341f0046a41106a22274200370300200341f0046a41086a22284200370300200342003703f0042002412d200341f0046a1000200341e8036a41186a2026290300370300200341e8036a41106a2027290300370300200341e8036a41086a2028290300370300200320032903f0043703e803024002400240024002400240202341037122264103460d0020260e03010203010b200341e8036a41204101410010030c040b410021270c020b410121270c010b410221270b200320273a00f004410110272226450d37202620273a0000200341e8036a4120202641011003202610290b20021029411410272202450d35200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d342002200637002c200220073a002b200220083a002a200220093b00282002200a3a00272002200b3a00262002200c3b00242002200d3a00232002200e3a00222002200f3b0020200220103a001f2002202436001b20022025360017200220113a0016200220123b0014200320024134108401200341106a2903002113200329030821292003280200212620021029200341cc046a2006370200200341cb046a20073a0000200341ca046a20083a0000200341c8046a20093b0100200341c7046a200a3a0000200341c6046a200b3a0000200341c4046a200c3b0100200341c3046a200d3a0000200341c2046a200e3a0000200341c0046a200f3b0100200341bf046a20103a0000200341bb046a2024360000200341b7046a2025360000200341b6046a20113a0000200341b0046a4100360200200341a0046a2013420020261b220620042029420020261b2213200554200620045420062004511b22021b2206370300200320123b01b404200342083703a80420032013200520021b22133703980420032006370390042003201337038804200341f8016a20034188046a10d803200341ac046a280200450d4c20032802a80410290c4c0b20022d00000d4a20022d00014101470d4a200141106a2903002106200141086a2903002113200241196a2d00002125200241186a2d00002124200241166a2f01002126200241156a2d00002127200241146a2d00002128200241126a2f01002107200241116a2d00002108200241106a2d000021092002410e6a2f0100210a2002410d6a2d0000210b2002410c6a2d0000210c2002410a6a2f0100210d200241096a2d0000210e200241086a2d0000210f200241066a2f01002110200241056a2d00002111200241046a2d00002112200241026a2f0100211f20032002411a6a29010037038004200320253a00ff03200320243a00fe03200320263b01fc03200320273a00fb03200320283a00fa03200320073b01f803200320083a00f703200320093a00f6032003200a3b01f4032003200b3a00f303200320123a00ea032003201f3b01e8032003200e200d410874200c41187472723600ef0320032011201041087472200f411874723600eb0320034188046a200341e8036a108c02024020032d0088044101460d0041d2fec4002125410b21240c4f0b2003200329028c0437006b200320032d008b043a006a200320032f0089043b01682003200341a1046a2900003703800120032003419d046a28000036027c200320034195046a290000370274200320034188046a410c6a22022d00003a007320034188046a200341e8006a108d0220032802a8042224450d49200341f0046a41086a20034188046a41346a2902002204370300200341b0016a41086a22262004370300200341b0016a41106a222720034188046a413c6a290200370300200341b0016a41186a222820034188046a41c4006a2902003703002003200341b4046a29020022043703f004200320043703b001200341d4046a280200210720034188046a41286a2802002108200235020021042003280288042102200329028c042105200329039804212920032802ac042125200341f8016a41186a20034188046a41186a290300222a370300200341f8016a410c6a20043e0200200341f8016a41286a20083602002003419c026a20253602002003202937038802200320053702fc012003202436029802200320023602f801200341f8016a41c4006a2028290300370200200341f8016a413c6a2027290300370200200341f8016a41346a2026290300370200200320032903b0013702a402200320073602c402411410272202450d32200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d31200220032903e8033700142002412c6a200341e8036a41186a290300370000200241246a200341e8036a41106a2903003700002002411c6a200341e8036a41086a290300370000200341186a20024134108401200341186a41106a29030021052003290320210420032802182124200210292004420020241b220420032903f801222b7d222c2004562005420020241b2205200341f8016a41086a290300222d7d2004202b54ad7d220420055620042005511b450d470c480b200141106a2903002113200141086a29030021042002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d00002110200241046a2d00002111200241026a2f01002112412a212441d588c30021250240024020022d0000450d004101212641002127410021280c010b41012126410021274100212820022d00014101470d002002410c6a2d000021272002410a6a2f01002128200241096a2d00002124200241066a2f0100410874200241056a2d000072200241086a2d0000411874722125410021260b202841ffff0371410874202741187472202441ff017172212420260d4d2003200637038001200320073a007f200320083a007e200320093b017c2003200a3a007b2003200b3a007a2003200c3b01782003200d3a00772003200e3a00762003200f3b0174200320103a00732003202436006f2003202536006b200320113a006a200320123b016820034188046a200341e8006a108d0220032802a8042226450d48200341f0046a41086a20034188046a41346a2902002206370300200341b0016a41086a22242006370300200341c0016a222720034188046a413c6a290200370300200341b0016a41186a222820034188046a41c4006a2902003703002003200341b4046a29020022063703f004200320063703b001200341d4046a280200210720034188046a41286a280200212520034188046a410c6a35020021292003280288042108200329028c04212b200329039804210620032802ac042102200341f8016a41186a20034188046a41186a2903002205370300200341f8016a410c6a20293e0200200341f8016a41286a20253602002003419c026a200236020020032006370388022003202b3702fc012003202636029802200320083602f801200341f8016a41c4006a2028290300370200200341f8016a413c6a2027290300370200200341f8016a41346a2024290300370200200320032903b0013702a402200320073602c40202400240024002402025411f4b0d00200620042006200454200520135420052013511b22241b22042005201320241b221384500d03200341f8016a41186a4200200520137d2006200454ad7d2229200620047d222b428080e983b1de165441002029501b22241b37030020034200202b20241b37038802200341306a4189c7c500411210b501200328023421272003280230212820252002470d02200241016a22072002490d4920024101742208200720072008491b2207ad42187e2229422088a70d492029a7220841004e0d010c490b41ddfec4002125412321242002450d50202610290c500b0240024020020d002008102721260c010b2026200241186c2008102821260b2026450d312003200736029c0220032026360298020b2026202541186c6a22022005201320241b37030820022006200420241b3703002002202741a0056a41a00520281b360210200320032802a00241016a3602a002200341e8006a200341f8016a10d803200328029c0221020b2002450d4a20032802980210290c4a0b41d588c3002125412a212420022d00000d4c20022d00014101470d4c200241196a2d00002125200241186a2d00002124200241166a2f01002126200241156a2d00002127200241146a2d00002128200241126a2f01002107200241116a2d00002108200241106a2d000021092002410e6a2f0100210a2002410d6a2d0000210b2002410c6a2d0000210c2002410a6a2f0100210d200241096a2d0000210e200241086a2d0000210f200241066a2f01002110200241056a2d00002111200241046a2d00002112200241026a2f0100211f20032002411a6a2901003703c801200320253a00c701200320243a00c601200320263b01c401200320273a00c301200320283a00c201200320073b01c001200320083a00bf01200320093a00be012003200a3b01bc012003200b3a00bb01200320123a00b2012003201f3b01b0012003200e200d410874200c41187472723600b70120032011201041087472200f411874723600b30120034188046a200341b0016a108d0220032802a8042207450d47200341c8026a41086a200341bc046a290200370300200341c8026a41106a200341c4046a290200370300200341c8026a41186a200341cc046a2902003703002003200341b4046a2902003703c80220034188046a41186a2903002129200341b0046a280200210920034194046a3502002106200329039804212b20032802ac04210a2003350288042104200329028c042113200341c8006a4189c7c500411210b501410021282006422086201342208884210620042013422086842113024002400240200941186c2202450d00200328024c410020032802481b2126200720026a2127200941186c41686a2125200721020340200241086a2903002105200229030021042026200241106a2802002224490d024200200620057d2013200454ad7d2205201320047d2204201356200520065620052006511b22241b21064200200420241b2113202541686a2125200241186a22022027470d000b0b410821080240200a0d00410021240c020b20071029410021240c010b411810272208450d2e2008200437030020082024360210200820053703080240024020250d0041012128410121240c010b200241186a210b200941186c20076a41686a210c41012128410121240340200b210202400340200241086a2903002105200229030021042026200241106a2802002225490d014200200620057d2013200454ad7d2205201320047d2204201356200520065620052006511b22251b21064200200420251b2113200241186a22022027470d000c030b0b024020242028470d00202841016a22242028490d4820284101742209202420242009491b2224ad42187e222c422088a70d48202ca722094100480d480240024020280d002009102721080c010b2008202841186c2009102821080b2008450d300b200241186a210b2008202841186c6a220920053703082009200437030020092025360210202841016a2128200c2002470d000b0b200a450d00200710290b200341b0046a2028360200200341ac046a20243602002003202b3703980420034188046a41186a2029370300200341cc046a200341c8026a41186a290300370200200341c4046a200341d8026a290300370200200341bc046a200341d0026a2903003702002003201337038804200320032903c8023702b404200320083602a80420032006370390040240202b2029844200520d002028450d0a0b200341b0016a20034188046a10d8030c430b200141106a2903002113200141086a2903002104200141186a280200211f2002411a6a2901002106200241196a2d00002107200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d00002110200241046a2d00002111200241026a2f0100211241d588c3002125412a21240240024020022d0000450d004101212641002127410021280c010b41012126410021274100212820022d00014101470d002002410c6a2d000021282002410a6a2f01002127200241096a2d00002124200241066a2f0100410874200241056a2d000072200241086a2d0000411874722125410021260b202741ffff0371410874202441ff017172202841187472212420260d4b2003200637038003200320073a00ff02200320083a00fe02200320093b01fc022003200a3a00fb022003200b3a00fa022003200c3b01f8022003200d3a00f7022003200e3a00f6022003200f3b01f402200320103a00f302200320243600ef02200320253600eb02200320113a00ea02200320123b01e80220034188046a200341e8026a108d0220032802a8042202450d46200341f0046a41086a20034188046a41346a2902002206370300200341b0016a41086a22252006370300200341b0016a41106a222420034188046a413c6a290200370300200341b0016a41186a222720034188046a41c4006a290200370300200320034188046a412c6a29020022063703f004200320063703b001200341d4046a280200212820034188046a41286a280200210720034188046a410c6a35020021062003280288042108200329028c042105200329039804212920032802ac042126200341f8016a41186a20034188046a41186a290300370300200341f8016a410c6a20063e0200200341f8016a41286a20073602002003419c026a20263602002003202937038802200320053702fc012003200236029802200320083602f801200341f8016a41c4006a2027290300370200200341f8016a413c6a2024290300370200200341f8016a41346a2025290300370200200320032903b0013702a402200320283602c4020240201f410a4b0d00200341f8016a412c6a222510ca0320032013370358200320043703502003201f360260411210272202450d2b200241106a41002f0088a3443b0000200241086a4100290080a344370000200241002900f8a24437000020024112413210282202450d2a200220252900003700122002412a6a202541186a290000370000200241226a202541106a2900003700002002411a6a202541086a290000370000200341f0046a41186a22244200370300200341f0046a41106a22264200370300200341f0046a41086a22274200370300200342003703f00420024132200341f0046a1000200341e8036a41186a2024290300370300200341e8036a41106a2026290300370300200341e8036a41086a2027290300370300200320032903f0043703e8032003410036028804200341e8036a412020034188046a10052124024002402003280288042226417f460d002024450d00200320263602f404200320243602f00420034188046a200341f0046a10af0320032d00a00422254102460d2b200341b0016a41186a2227200341b9046a290000370300200341b0016a41106a2207200341b1046a290000370300200341b0016a41086a2208200341a9046a290000370300200341e8006a41086a2209200341ca046a290100370300200341e8006a41106a220a200341d2046a290100370300200341e8006a41186a220b200341da046a290100370300200320032900a1043703b0012003200341c2046a290100370368200341c1046a2d0000212802402026450d00202410290b200341c8026a41086a2008290300370300200341c8026a41106a2007290300370300200341c8026a41186a202729030037030020034188036a41086a200929030037030020034188036a41106a200a29030037030020034188036a41186a200b290300370300200320032903b0013703c80220032003290368370388030c010b200341f0046a41186a22244200370300200341f0046a41106a22264200370300200341f0046a41086a22274200370300200342003703f00441b3a4c400411a200341f0046a1000200341e8036a41186a2024290300370300200341e8036a41106a2026290300370300200341e8036a41086a2027290300370300200320032903f0043703e8032003410036028804200341e8036a412020034188046a100521240240024002402003280288042226417f460d002024450d00200341f0046a2026412020264120491b22276a41004100412020276b2027411f4b1b10cd041a200341f0046a2024202710ce041a2026411f4d0d2c200341b0016a41186a2226200341f0046a41186a290300370300200341b0016a41106a2227200341f0046a41106a290300370300200341b0016a41086a2228200341f0046a41086a290300370300200320032903f0043703b00120241029200341a8036a41186a20262903002206370300200341a8036a41106a20272903002213370300200341a8036a41086a20282903002204370300200320032903b00122053703a803200341c8036a41186a2006370300200341c8036a41106a2013370300200341c8036a41086a2004370300200320053703c8034112102722240d0141124101102a000b200341f0046a41186a22244200370300200341f0046a41106a22264200370300200341f0046a41086a22274200370300200342003703f00441b3a4c400411a200341f0046a1000200341e8036a41186a2024290300370300200341e8036a41106a2026290300370300200341e8036a41086a2027290300370300200320032903f0043703e803412010272224450d2a20242025290000370000202441186a202541186a290000370000202441106a202541106a290000370000202441086a202541086a290000370000200341e8036a412020244120100320241029410021280c010b202441106a41002f0088a3443b0000202441086a4100290080a344370000202441002900f8a24437000020244112413210282224450d28202420032903c8033700122024412a6a200341c8036a41186a290300370000202441226a200341c8036a41106a2903003700002024411a6a200341c8036a41086a290300370000200341f0046a41186a22264200370300200341f0046a41106a22274200370300200341f0046a41086a22284200370300200342003703f00420244132200341f0046a1000200341e8036a41186a2026290300370300200341e8036a41106a2027290300370300200341e8036a41086a2028290300370300200320032903f0043703e8032003410036028804200341e8036a412020034188046a100521262003280288042227417f460d262026450d262003202736026c2003202636026820034188046a200341e8006a10af0320032d00a00422284102460d2720034188046a41086a290300210620032903880421132003280298042107200341b0016a200341a1046a41c70010ce041a02402027450d00202610290b200341e8006a200341b0016a41c10010ce041a200320283a00880420034188046a410172200341e8006a41c10010ce041a200341cc016a200341aa046a410020032d00a9044101461b360200200320063703b801200320133703b001200320253602c801200320073602c001200341f0046a41186a22264200370300200341f0046a41106a22274200370300200341f0046a41086a22284200370300200342003703f00420244132200341f0046a1000200341e8036a41186a2026290300370300200341e8036a41106a2027290300370300200341e8036a41086a2028290300370300200320032903f0043703e8032003410036027020034201370368200341b0016a41106a200341e8006a10302003200341b0016a3602f004200341f0046a200341e8006a10590240024020032802c80122070d00200341003a00f00402400240200328026c222720032802702207460d00200328026821260c010b200741016a22262007490d4920074101742227202620262027491b22274100480d490240024020070d002027102721260c010b200328026820072027102821260b2026450d282003202736026c200320263602680b2003200741016a2228360270202620076a41003a00000c010b200341013a00f00402400240200328026c20032802702227460d00200328026821260c010b202741016a22262027490d4820274101742228202620262028491b22284100480d480240024020270d002028102721260c010b200328026820272028102821260b2026450d262003202836026c200320263602680b2003202741016a360270202620276a41013a000002400240200328026c2208200328027022286b411f4d0d00200821270c010b202841206a22272028490d4820084101742209202720272009491b22274100480d480240024020080d002027102721260c010b202620082027102821260b2026450d252003202736026c200320263602680b202620286a220841086a200741086a290000370000200841106a200741106a290000370000200841186a200741186a2900003700002003202841206a2228360270200820072900003700000b0240024020032802cc0122070d00200341003a00f004024020272028470d00202741016a22072027490d4920274101742208200720072008491b22074100480d490240024020270d002007102721260c010b202620272007102821260b2026450d252003200736026c200320263602680b2003202841016a360270202620286a41003a000020032802702128200328026c2127200328026821260c010b200341013a00f004024020272028470d00202741016a22082027490d4820274101742209200820082009491b22084100480d480240024020270d002008102721260c010b202620272008102821260b2026450d232003200836026c200320263602680b2003202841016a360270202620286a41013a000002400240200328026c2227200328027022286b4120490d00200328026821260c010b202841206a22262028490d4820274101742208202620262008491b22084100480d480240024020270d002008102721260c010b200328026820272008102821260b2026450d222003200836026c20032026360268200821270b202620286a220841086a200741086a290000370000200841106a200741106a290000370000200841186a200741186a2900003700002003202841206a2228360270200820072900003700000b200341e8036a412020262028100302402027450d00202610290b20241029200341f0046a41186a22244200370300200341f0046a41106a22264200370300200341f0046a41086a22274200370300200342003703f00441b3a4c400411a200341f0046a1000200341e8036a41186a2024290300370300200341e8036a41106a2026290300370300200341e8036a41086a2027290300370300200320032903f0043703e803412010272224450d1f20242025290000370000202441186a202541186a290000370000202441106a202541106a290000370000202441086a202541086a290000370000200341e8036a41202024412010032024102920034188036a41086a200341c8036a41086a29030037030020034188036a41106a200341c8036a41106a29030037030020034188036a41186a200341c8036a41186a290300370300200320032903c80337038803410121280b410021250b20034188046a41086a200341c8026a41086a29030037030020034188046a41106a200341c8026a41106a29030037030020034188046a41186a200341c8026a41186a290300370300200341b0016a41086a20034188036a41086a290300370300200341b0016a41106a20034188036a41106a290300370300200341b0016a41186a20034188036a41186a290300370300200320032903c8023703880420032003290388033703b001200341f0046a41186a22244200370300200341f0046a41106a22264200370300200341f0046a41086a22274200370300200342003703f00420024132200341f0046a1000200341e8036a41186a2024290300370300200341e8036a41106a2026290300370300200341e8036a41086a2027290300370300200320032903f0043703e8032003410036027020034201370368200341d0006a41106a200341e8006a10302003200341d0006a3602f004200341f0046a200341e8006a10590240024020254101460d00200341003a00f00402400240200328026c222420032802702227460d00200328026821250c010b202741016a22252027490d4720274101742224202520252024491b22244100480d470240024020270d002024102721250c010b200328026820272024102821250b2025450d1f2003202436026c200320253602680b2003202741016a2226360270202520276a41003a00000c010b200341013a00f00402400240200328026c20032802702224460d00200328026821250c010b202441016a22252024490d4620244101742226202520252026491b22264100480d460240024020240d002026102721250c010b200328026820242026102821250b2025450d1d2003202636026c200320253602680b2003202441016a360270202520246a41013a000002400240200328026c2227200328027022266b411f4d0d00202721240c010b202641206a22242026490d4620274101742207202420242007491b22244100480d460240024020270d002024102721250c010b202520272024102821250b2025450d1c2003202436026c200320253602680b202520266a222741086a20034188046a41086a290300370000202741106a20034188046a41106a290300370000202741186a20034188046a41186a2903003700002003202641206a222636027020272003290388043700000b02400240202841ff01714101460d00200341003a00f004024020242026470d00202441016a22272024490d4720244101742228202720272028491b22274100480d470240024020240d002027102721250c010b202520242027102821250b2025450d1c2003202736026c200320253602680b2003202641016a360270202520266a41003a000020032802702126200328026c2124200328026821250c010b200341013a00f004024020242026470d00202441016a22272024490d4620244101742228202720272028491b22274100480d460240024020240d002027102721250c010b202520242027102821250b2025450d1a2003202736026c200320253602680b2003202641016a360270202520266a41013a000002400240200328026c2224200328027022266b4120490d00200328026821250c010b202641206a22252026490d4620244101742227202520252027491b22274100480d460240024020240d002027102721250c010b200328026820242027102821250b2025450d192003202736026c20032025360268202721240b202520266a222741086a200341b0016a41086a290300370000202741106a200341b0016a41106a290300370000202741186a200341b0016a41186a2903003700002003202641206a2226360270202720032903b0013700000b200341e8036a412020252026100302402024450d00202510290b20021029200328029c02450d4920032802980210290c490b4180ffc4002125411b21242026450d4b200210290c4b0b2001410c6a2802002109200141086a2802002108200141046a28020021282002411a6a2901002106200241196a2d0000210a200241186a2d0000210b200241166a2f0100210c200241156a2d0000210d200241146a2d0000210e200241126a2f0100210f200241116a2d00002110200241106a2d000021112002410e6a2f010021122002410d6a2d0000211f200241046a2d00002114200241026a2f0100211541d588c3002125412a21240240024020022d0000450d004101212641002127410021070c010b41012126410021274100210720022d00014101470d002002410c6a2d000021072002410a6a2f01002127200241096a2d00002124200241066a2f0100410874200241056a2d000072200241086a2d0000411874722125410021260b202741ffff0371410874202441ff017172200741187472212420260d40200320063703c0032003200a3a00bf032003200b3a00be032003200c3b01bc032003200d3a00bb032003200e3a00ba032003200f3b01b803200320103a00b703200320113a00b603200320123b01b4032003201f3a00b303200320243600af03200320253600ab03200320143a00aa03200320153b01a80320034188046a200341a8036a108d02024020032802a804220a0d004110212441c2fec40021250c410b200341f0046a41086a20034188046a41346a2902002206370300200341b0016a41086a22022006370300200341c0016a222520034188046a413c6a290200370300200341b0016a41186a222420034188046a41c4006a290200370300200320034188046a412c6a29020022063703f004200320063703b001200341d4046a280200212620034188046a41286a280200212720034188046a410c6a35020021062003280288042107200329028c042113200329039804210420032802ac04210b200341f8016a41186a20034188046a41186a290300370300200341f8016a410c6a20063e0200200341f8016a41286a2027360200200341f8016a41246a200b3602002003200437038802200320133702fc012003200a36029802200320073602f801200341f8016a41c4006a2024290300370200200341f8016a413c6a2025290300370200200341f8016a41346a2002290300370200200320032903b0013702a402200320263602c40220090d3e41ba80c500212541172124410121020c3f0b20022d00000d4520022d00014101470d45200241196a2d00002125200241186a2d00002124200241166a2f01002126200241156a2d00002127200241146a2d00002128200241126a2f01002107200241116a2d00002108200241106a2d000021092002410e6a2f0100210a2002410d6a2d0000210b2002410c6a2d0000210c2002410a6a2f0100210d200241096a2d0000210e200241086a2d0000210f200241066a2f01002110200241056a2d00002111200241046a2d00002112200241026a2f0100211f20032002411a6a29010037038001200320253a007f200320243a007e200320263b017c200320273a007b200320283a007a200320073b0178200320083a0077200320093a00762003200a3b01742003200b3a0073200320123a006a2003201f3b01682003200e200d41087472200c4118747236006f20032011201041087472200f4118747236006b20034188046a200341e8006a108d0220032802a8042202450d44200341f0046a41086a20034188046a41346a2902002206370300200341b0016a41086a22242006370300200341c0016a222620034188046a413c6a290200370300200341b0016a41186a222720034188046a41c4006a290200370300200320034188046a412c6a29020022063703f004200320063703b001200341d4046a280200212820034188046a41286a280200210720034188046a410c6a35020021062003280288042108200329028c042113200329039804210420032802ac042125200341f8016a41186a20034188046a41186a290300370300200341f8016a410c6a20063e0200200341f8016a41286a20073602002003419c026a20253602002003200437038802200320133702fc012003200236029802200320083602f801200341f8016a41c4006a2027290300370200200341f8016a413c6a2026290300370200200341f8016a41346a2024290300370200200320032903b0013702a402200320283602c402200341f8016a412c6a222410c903202410ca032025450d46200210290c460b20022d00000d4420022d00014101470d4420012d00012114200241196a2d00002125200241186a2d00002124200241166a2f01002126200241156a2d00002127200241146a2d00002128200241126a2f01002107200241116a2d00002108200241106a2d000021092002410e6a2f0100210a2002410d6a2d0000210b2002410c6a2d0000210c2002410a6a2f0100210d200241096a2d0000210e200241086a2d0000210f200241066a2f01002110200241056a2d00002111200241046a2d00002112200241026a2f0100211f20032002411a6a2901003703c801200320253a00c701200320243a00c601200320263b01c401200320273a00c301200320283a00c201200320073b01c001200320083a00bf01200320093a00be012003200a3b01bc012003200b3a00bb01200320123a00b2012003201f3b01b0012003200e200d41087472200c411874723600b70120032011201041087472200f411874723600b30120034188046a200341b0016a108d0220032802a8042226450d43200341f8016a41086a200341bc046a29020037030020034188026a200341c4046a290200370300200341f8016a41186a200341cc046a2902003703002003200341b4046a2902003703f80120032802ac042127410d10272202450d12200241056a41002900aca344370000200241002900a7a3443700002002410d412d10282202450d11200220032903f80137000d200241256a200341f8016a41186a2903003700002002411d6a200341f8016a41106a290300370000200241156a200341f8016a41086a290300370000200341f0046a41186a22254200370300200341f0046a41106a22244200370300200341f0046a41086a22284200370300200342003703f0042002412d200341f0046a1000200341e8036a41186a2025290300370300200341e8036a41106a2024290300370300200341e8036a41086a2028290300370300200320032903f0043703e803024002400240024002400240201441037122254103460d0020250e03010203010b200341e8036a41204101410010030c040b410021240c020b410121240c010b410221240b200320243a00f004410110272225450d11202520243a0000200341e8036a4120202541011003202510290b200210292027450d45202610290c450b2001411d6a29000021132001411c6a2d000021142001411b6a2d00002115200141196a2f00002116200141186a2d00002117200141176a2d00002118200141156a2f00002119200141146a2d0000211a200141136a2d0000211b200141116a2f0000211c200141106a2d0000211d2001410c6a280200211e200141086a2802002107200141076a2d00002120200141056a2f00002121200141046a2d000021222002411a6a2901002106200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d00002111200241046a2d00002112200241026a2f0100211f41d588c3002125412a21240240024020022d0000450d004101212641002127410021280c010b41012126410021274100212820022d00014101470d002002410c6a2d000021282002410a6a2f01002127200241096a2d00002124200241066a2f0100410874200241056a2d000072200241086a2d0000411874722125410021260b202741ffff0371410874202441ff017172202841187472212420260d47200320063703e002200320083a00df02200320093a00de022003200a3b01dc022003200b3a00db022003200c3a00da022003200d3b01d8022003200e3a00d7022003200f3a00d602200320103b01d402200320113a00d302200320243600cf02200320253600cb02200320123a00ca022003201f3b01c80220034188046a200341c8026a108c0241012126024020032d0088044101460d0041d2fec4002125410b2124410121270c490b2003200329028c043700eb02200320032d008b043a00ea02200320032f0089043b01e8022003200341a1046a2900003703800320032003419d046a2800003602fc02200320034195046a2900003702f402200320034194046a2d00003a00f3020240202241ff01714101470d0020034188046a200741067610cc012003280288042125024002402003280290042007413f7122024b0d00410021020c010b202520024105746a2202290018211320022d0017211420022d0016211520022f0014211620022d0013211720022d0012211820022f0010211920022d000f211a20022d000e211b20022f000c211c20022d000b211d2002280007211e2002280003210720022d0002212020022f00002121410121020b0240200328028c04450d00202510290b2002450d470b200320133703a003200320143a009f03200320153a009e03200320163b019c03200320173a009b03200320183a009a03200320193b0198032003201a3a0097032003201b3a0096032003201c3b0194032003201d3a0093032003201e36008f032003200736008b03200320203a008a03200320213b018803410e10272202450d0e200241066a410029009fa34437000020024100290099a3443700002002410e412e10282202450d0d200220032903880337000e200241266a20034188036a41186a2903003700002002411e6a20034188036a41106a290300370000200241166a20034188036a41086a290300370000200341f0046a41186a22254200370300200341f0046a41106a22244200370300200341f0046a41086a22264200370300200342003703f0042002412e200341f0046a1000200341e8036a41186a2025290300370300200341e8036a41106a2024290300370300200341e8036a41086a2026290300370300200320032903f0043703e803200341e8036a412041b8d6c50041004100100b2125200210292025417f470d4520034188036a200341e8026a412010d004450d44410e10272202450d0c200241066a41002900c7a244370000200241002900c1a2443700002002410e412e10282202450d0b200220032903c80237000e200241266a200341c8026a41186a2903003700002002411e6a200341c8026a41106a290300370000200241166a200341c8026a41086a290300370000200341f0046a41186a22254200370300200341f0046a41106a22244200370300200341f0046a41086a22264200370300200342003703f0042002412e200341f0046a1000200341e8036a41186a2025290300370300200341e8036a41106a2024290300370300200341e8036a41086a2026290300370300200320032903f0043703e803412010272225450d0a2025200329038803370000202541186a20034188036a41186a290300370000202541106a20034188036a41106a290300370000202541086a20034188036a41086a290300370000200341e8036a41202025412010032025102920021029410e10272202450d09200241066a410029009fa34437000020024100290099a3443700002002410e412e10282202450d08200220032903e80237000e200241266a200341e8026a41186a2903003700002002411e6a200341e8026a41106a290300370000200241166a200341e8026a41086a290300370000200341f0046a41186a22254200370300200341f0046a41106a22244200370300200341f0046a41086a22264200370300200342003703f0042002412e200341f0046a1000200341e8036a41186a2025290300370300200341e8036a41106a2024290300370300200341e8036a41086a2026290300370300200320032903f0043703e8032003410036028804200341e8036a412020034188046a10052126024002402003280288042224417f470d00410021250c010b200320243602542003202636025020034188046a200341d0006a10d30320032802a8042225450d08200341f0046a41186a20034188046a41186a290300370300200341f0046a41106a20034188046a41106a290300370300200341f0046a41086a20034188046a41086a290300370300200341f8016a41086a200341b4046a290200370300200341f8016a41106a200341bc046a290200370300200341f8016a41186a200341c4046a290200370300200341f8016a41206a200341cc046a290200370300200341a0026a200341d4046a28020036020020032003290388043703f004200320032902ac043703f80102402024450d00202610290b200341e8036a4120100c0b200341c8036a41186a2224200341f0046a41186a290300370300200341c8036a41106a2226200341f0046a41106a290300370300200341c8036a41086a2227200341f0046a41086a290300370300200341b0016a41086a2228200341f8016a41086a290300370300200341b0016a41106a2207200341f8016a41106a290300370300200341b0016a41186a2208200341f8016a41186a290300370300200341b0016a41206a2209200341f8016a41206a290300370300200341b0016a41286a220a200341f8016a41286a280200360200200320032903f0043703c803200320032903f8013703b001024020250d00200210290c450b200341a8036a41186a220b2024290300370300200341a8036a41106a22242026290300370300200341a8036a41086a22262027290300370300200341e8006a41086a22272028290300370300200341e8006a41106a22282007290300370300200341e8006a41186a22072008290300370300200341e8006a41206a22082009290300370300200341e8006a41286a2209200a280200360200200320032903c8033703a803200320032903b0013703682002102920034188046a41186a200b29030037030020034188046a41106a202429030037030020034188046a41086a2026290300370300200341ac046a2003290368370200200341b4046a2027290300370200200341bc046a2028290300370200200341c4046a2007290300370200200341cc046a2008290300370200200341d4046a2009280200360200200320032903a80337038804200320253602a804410e10272202450d06200241066a410029009fa34437000020024100290099a3443700002002410e412e10282202450d05200220032903880337000e200241266a20034188036a41186a2903003700002002411e6a20034188036a41106a290300370000200241166a20034188036a41086a290300370000200341f0046a41186a22254200370300200341f0046a41106a22244200370300200341f0046a41086a22264200370300200342003703f0042002412e200341f0046a1000200341e8036a41186a2025290300370300200341e8036a41106a2024290300370300200341e8036a41086a2026290300370300200320032903f0043703e803200341203602fc012003200341e8036a3602f80120034188046a200341f8016a10c7032002102920032802ac04450d4420032802a80410290c440b4101212620022d000120022d0000720d39200141046a280200210220034188046a41086a22254200370300200342003703880441bdc6c500411620034188046a1004200341f8016a41086a202529030037030020032003290388043703f8012003200236028804200341f8016a411020034188046a410410030c380b024020022d000120022d000072450d0041ad88c3002125412821240c460b41012126200341013a00b00120034188046a41086a22024200370300200342003703880441d7c7c500411320034188046a1004200341f8016a41086a200229030037030020032003290388043703f801200341f8016a4110200341b0016a410110030c370b4101212620022d000120022d0000720d37200141046a280200210220034188046a41086a22254200370300200342003703880441f0c6c500411920034188046a1004200341f8016a41086a202529030037030020032003290388043703f8012003200236028804200341f8016a411020034188046a410410030c360b200141086a2802002108200141046a2802002109024020022d000120022d000072450d0041ad88c30021254128212441002127410121262008450d45200910290c450b2001410c6a280200210220034188046a41086a22254200370300200342003703880441d180c500411520034188046a1004200341f8016a41086a202529030037030020032003290388043703f80120034100360290042003420137038804200320023602b001200341b0016a20034188046a10300240024020020d002003280290042124200328028c04212620032802880421270c010b200241057421282003280288042127200328028c042126200328029004212520092102034002400240202620256b4120490d00202541206a21240c010b202541206a22242025490d3e20264101742207202420242007491b22074100480d3e0240024020260d002007102721270c010b202720262007102821270b02402027450d00200721260c010b20074101102a000b202720256a22252002290000370000202541186a200241186a290000370000202541106a200241106a290000370000202541086a200241086a29000037000020242125200241206a2102202841606a22280d000b2003202636028c04200320243602900420032027360288040b200341f8016a411020272024100302402026450d00202710290b410121262008450d34200910290c340b200341f8016a41186a200341b4046a220241186a290000370300200341f8016a41106a200241106a290000370300200341f8016a41086a200241086a290000370300200342f3e885db96cddbb3203703c803200320022900003703f801200341386a41888dc300410d10940120032003290340420020032802381b3703e803200341e8006a200341f8016a109301200328026c21252003280268210220032802702124200341fc006a200341c8036a36020020032002202441286c6a360274200320023602702003202536026c200320023602682003200341e8036a360278200341f0046a200341e8006a104a200341e8006a41086a200341f0046a41086a280200360200200320032903f004370368200341f8016a200341e8006a10a701200341f8016a108b010c390b412e4101102a000b410e4101102a000b418f89c3004133104e000b412e4101102a000b410e4101102a000b41204101102a000b412e4101102a000b410e4101102a000b412e4101102a000b410e4101102a000b41014101102a000b412d4101102a000b410d4101102a000b20274101102a000b20274101102a000b20274101102a000b20244101102a000b20264101102a000b20244101102a000b41204101102a000b20084101102a000b20084101102a000b20074101102a000b20274101102a000b20284101102a000b20274101102a000b419bffc400419f01104e000b418f89c3004133104e000b41324101102a000b41204101102a000b418f89c3004133104e000b418f89c3004133104e000b41324101102a000b41124101102a000b20094108102a000b41184108102a000b20084108102a000b41344101102a000b41144101102a000b41344101102a000b41144101102a000b41014101102a000b412d4101102a000b410d4101102a000b41204101102a000b412e4101102a000b410e4101102a000b412e4101102a000b410e4101102a000b412e4101102a000b410e4101102a000b41002127410021250c0f0b41002125410121270c0e0b41ad88c300212541282124410121270c0d0b0240024002400240200941246c22240d0020282102410021260c010b200341c8026a41026a2225202841036a2d00003a0000200341e8036a41086a2227202841146a290000370300200341e8036a410d6a2207202841196a290000370000200320282f00013b01c8022003202829000c3703e803202841246a2102024020282d0000220c4102470d00410021260c010b2028280008210d2028280004212620034188036a41026a20252d00003a0000200341e8006a41086a2027290300370300200341e8006a410d6a2007290000370000200320032f01c8023b018803200320032903e8033703680240200c4101460d00200341e8026a41026a20034188036a41026a2d00003a0000200341f0046a41086a200341e8006a41086a290300370300200341f0046a410d6a200341e8006a410d6a290000370000200320032f0188033b01e802200320032903683703f0040c020b200341c8036a202641067610cc0120032802c80321270240024020032802d0032026413f7122254b0d00410021250c010b200341e8026a41026a202720254105746a222541026a2d00003a0000200341f8046a202541136a290000370300200341fd046a202541186a290000370000200320252f00003b01e8022003202529000b3703f0042025280007210d20252800032126410121250b024020032802cc03450d00202710290b20250d014184efc20021260b410121254100210c410021240c010b20034188046a410d6a2225200341f0046a410d6a29000037000020034188046a41086a2227200341f0046a41086a290300370300200341d0006a41026a2207200341e8026a41026a2d00003a0000200341b0016a41086a220c2027290300370300200341b0016a410d6a22272025290000370000200320032f01e8023b0150200320032903f0043703b00102400240412010272225450d00202520032f01503b00002025200d36000720252026360003202520032903b00137000b202541026a20072d00003a0000202541136a200c290300370000202541186a2027290000370000024002400240202820246a221e2002470d00201e21020c010b200341c8026a41026a2226202841276a2d00003a0000200341e8036a41086a2227202841386a290000370300200341e8036a410d6a22072028413d6a290000370000200320282f00253b01c802200320282900303703e803202841c8006a210220282d0024220c4102470d010b200341023a0088044101210c41002126410121240c030b202828002c21152028280028212420034188036a41026a20262d00003a0000200341e8006a41086a2027290300370300200341e8006a410d6a2007290000370000200320032f01c8023b018803200320032903e8033703680240200c4101460d00200341e8026a41026a20034188036a41026a2d00003a0000200341f0046a41086a200341e8006a41086a290300370300200341f0046a410d6a200341e8006a410d6a290000370000200320032f0188033b01e802200320032903683703f0040c020b200341c8036a202441067610cc0120032802c80321260240024020032802d0032024413f7122244b0d0041002127200d21150c010b200341e8026a41026a202620244105746a222441026a2d00003a0000200341f8046a202441136a290000370300200341fd046a202441186a290000370000200320242f00003b01e8022003202429000b3703f0042024280007211520242800032124410121270b024020032802cc03450d00202610290b20270d0120034190046a41153602004184efc200212620034184efc20036028c044101210c200341013a008804410121240c020b41204101102a000b20034194046a221020032903f00437020020034188046a41086a2015360200200341a1046a2202200341f0046a410d6a22192900003700002003419c046a200341f0046a41086a2207290300370200200341b0016a41086a221120034191046a290000370300200341b0016a41186a22122002290000370300200341b0016a41106a221f20034199046a2900003703002003202436028c04200320032f01e8023b0089042003200341e8026a41026a221a2d00003a008b0420032003290089043703b001200941246c41b87f6a211d20034188046a41017221264102210f4120210e4102210c41002127410121240340200341f0046a41186a220d2012290300370300200341f0046a41106a2214201f29030037030020072011290300370300200320032903b0013703f0040240200c417f6a2024470d00200f200c200c200f491b222441ffffff3f712024470d06202441057422024100480d062025200e2002102822250d0020024101102a000b2025200e6a220220032903f004370000200241186a200d290300370000200241106a2014290300370000200241086a20072903003700000240024002400240202741f803460d00201d2027470d01201e21020c020b202820276a41c8006a21020c010b200341c8026a41026a2214202820276a220241cb006a2d00003a0000200341e8036a41086a2216200241dc006a290000370300200341e8036a410d6a2217200241e1006a2900003700002003200241c9006a2f00003b01c8022003200241d4006a2900003703e803200241c8006a2d000022184102470d01200241ec006a21020b200341023a008804410021260c020b200241d0006a280000211b200241cc006a280000210d20034188036a41026a221c20142d00003a0000200341e8006a41086a22142016290300370300200341e8006a410d6a22162017290000370000200320032f01c8023b018803200320032903e8033703680240024020184101460d00201a201c2d00003a00002007201429030037030020192016290000370000200320032f0188033b01e802200320032903683703f004201b21150c010b200341c8036a200d41067610cc01200d413f7121144100211620032802c8032117024020032802d00320144d0d00201a201720144105746a220d41026a2d00003a00002007200d41136a2900003703002019200d41186a2900003700002003200d2f00003b01e8022003200d29000b3703f004200d2800072115200d280003210d410121160b024020032802cc03450d00201710290b20160d0020034115360290044184efc200212620034184efc20036028c04200341013a008804200241ec006a21020c020b202620032f01e8023b0000201020032903f004370000202641026a201a2d00003a0000201041086a20072903003700002010410d6a201929000037000020032015360290042003200d36028c04200341003a0088042011202641086a290000370300201f202641106a2900003703002012202641186a290000370300200320262900003703b001200f41026a210f200e41206a210e200c41016a210c202741246a21270c000b0b0240024020260d004100210d0c010b4101210d02402024450d00202510290b20262125411521240b200341f8016a412c6a21072028200941246c6a21270240034020272002460d0120022d00002126200241246a210220264102470d000b0b02402008450d00202810290b0240200d450d00410021020c010b200710c9032003200c36025820032024360254200320253602500240024002400240024002400240024002400240024002400240411210272202450d00200241106a41002f00f6a2443b0000200241086a41002900eea244370000200241002900e6a24437000020024112413210282209450d01200920072900003700122009412a6a200741186a290000370000200941226a200741106a2900003700002009411a6a200741086a290000370000200341f0046a41186a22024200370300200341f0046a41106a22254200370300200341f0046a41086a22244200370300200342003703f00420094132200341f0046a1000200341e8036a41186a2002290300370300200341e8036a41106a2025290300370300200341e8036a41086a2024290300370300200320032903f0043703e8032003410036028804200341e8036a412020034188046a10052102024002402003280288042226417f460d002002450d00200320263602ec04200320023602e804200341e8026a200341e8046a102d0240024020032802e802220e450d0020032802ec02212720034188046a200341e8046a10940320032d00880422254102470d012027450d00200e10290b418f89c3004133104e000b200341b0016a41186a2228200341a1046a290000370300200341b0016a41106a220720034199046a290000370300200341b0016a41086a220820034191046a290000370300200341e8006a41086a220a200341b2046a290100370300200341e8006a41106a220b200341ba046a290100370300200341e8006a41186a220c200341c2046a29010037030020032003290089043703b0012003200341aa046a290100370368200341a9046a2d00002124200341f0046a41086a220d2008290300370300200341f0046a41106a22082007290300370300200341f0046a41186a22072028290300370300200341c8036a41086a2228200a290300370300200341c8036a41106a220a200b290300370300200341c8036a41186a220b200c290300370300200320032903b0013703f004200320032903683703c80302402026450d00200210290b200341c8026a41086a200d290300370300200341c8026a41106a2008290300370300200341c8026a41186a200729030037030020034188036a41086a202829030037030020034188036a41106a200a29030037030020034188036a41186a200b290300370300200320032903f0043703c802200320032903c803370388032027450d01200e10290c010b200341f0046a41186a22024200370300200341f0046a41106a22254200370300200341f0046a41086a22244200370300200342003703f00441c6a3c400411a200341f0046a1000200341e8036a41186a2002290300370300200341e8036a41106a2025290300370300200341e8036a41086a2024290300370300200320032903f0043703e8032003410036028804200341e8036a412020034188046a100521020240024002402003280288042225417f460d002002450d00200341f0046a2025412020254120491b22246a41004100412020246b2024411f4b1b10cd041a200341f0046a2002202410ce041a2025411f4d0d06200341b0016a41186a2225200341f0046a41186a290300370300200341b0016a41106a2224200341f0046a41106a290300370300200341b0016a41086a2226200341f0046a41086a290300370300200320032903f0043703b00120021029200341c8036a41186a20252903002206370300200341c8036a41106a20242903002213370300200341c8036a41086a20262903002204370300200320032903b00122053703c803200341e8006a41186a2006370300200341e8006a41106a2013370300200341e8006a41086a2004370300200320053703684112102722020d0141124101102a000b200341f0046a41186a22024200370300200341f0046a41106a22254200370300200341f0046a41086a22244200370300200342003703f00441c6a3c400411a200341f0046a1000200341e8036a41186a2002290300370300200341e8036a41106a2025290300370300200341e8036a41086a2024290300370300200320032903f0043703e803412010272202450d0620022007290000370000200241186a200741186a290000370000200241106a200741106a290000370000200241086a200741086a290000370000200341e8036a412020024120100320021029410021240c010b200241106a41002f00f6a2443b0000200241086a41002900eea244370000200241002900e6a2443700002002411241321028220a450d06200a2003290368370012200a412a6a200341e8006a41186a290300370000200a41226a200341e8006a41106a290300370000200a411a6a200341e8006a41086a290300370000200341f0046a41186a22024200370300200341f0046a41106a22254200370300200341f0046a41086a22244200370300200342003703f004200a4132200341f0046a1000200341e8036a41186a2002290300370300200341e8036a41106a2025290300370300200341e8036a41086a2024290300370300200320032903f0043703e8032003410036028804200341e8036a412020034188046a100521022003280288042224417f460d072002450d07200320243602ec02200320023602e802200341f0046a200341e8026a102d0240024020032802f004220b450d00200341f8046a280200212520032802f404210c200341b0016a200341e8026a10940320032d00b00122264102470d01200c450d00200b10290b418f89c3004133104e000b20034188046a200341b0016a410172222741c10010ce041a200341b0016a20034188046a41c30010ce041a02402024450d00200210290b20034188046a200341b0016a41c30010ce041a200320263a00b001202720034188046a41c10010ce041a20032d00d101210d200341f0046a41186a22024200370300200341f0046a41106a22244200370300200341f0046a41086a22264200370300200342003703f004200a4132200341f0046a1000200341e8036a41186a2002290300370300200341e8036a41106a2024290300370300200341e8036a41086a2026290300370300200320032903f0043703e80320034201370388042003410036029004200320253602f004200341f0046a20034188046a1030024002402025450d0020254105742128410020032802900422256b2126200328028c042127200b2102034002400240202720266a4120490d0020032802880421240c010b202541206a22242025490d1620274101742208202420242008491b22084100480d160240024020270d002008102721240c010b20032802880420272008102821240b2024450d0c2003200836028c042003202436028804200821270b202420256a222441086a200241086a290000370000202441106a200241106a290000370000202441186a200241186a2900003700002003202541206a22253602900420242002290000370000202641606a2126200241206a2102202841606a22280d000c020b0b20032802900421250b200341013a00f00402400240200328028c042025460d0020032802880421020c010b202541016a22022025490d1320254101742224200220022024491b22244100480d130240024020250d002024102721020c010b20032802880420252024102821020b2002450d0a2003202436028c0420032002360288040b2003202541016a36029004200220256a41013a000002400240200328028c04222620032802900422246b411f4d0d00202621250c010b202441206a22252024490d1320264101742227202520252027491b22254100480d130240024020260d002025102721020c010b200220262025102821020b2002450d0b2003202536028c0420032002360288040b200220246a222641086a200741086a290000370000202641106a200741106a290000370000202641186a200741186a2900003700002003202441206a2228360290042026200729000037000002400240200341d2016a4100200d4101461b22260d00200341003a00f0040240024020252028460d00202521080c010b202541016a22262025490d1520254101742227202620262027491b22084100480d150240024020250d002008102721020c010b200220252008102821020b2002450d0e2003200836028c0420032002360288040b2003202441216a222436029004200220286a41003a00000c010b200341013a00f0040240024020252028460d00202521270c010b202541016a22272025490d1420254101742208202720272008491b22274100480d140240024020250d002027102721020c010b200220252027102821020b2002450d0e2003202736028c0420032002360288040b2003202441216a222536029004200220286a41013a000002400240202720256b411f4d0d00202721080c010b202541206a22282025490d1420274101742208202820282008491b22084100480d140240024020270d002008102721020c010b200220272008102821020b2002450d0f2003200836028c0420032002360288040b200220256a222541086a202641086a290000370000202541106a202641106a290000370000202541186a202641186a2900003700002003202441c1006a222436029004202520262900003700000b200341e8036a412020022024100302402008450d00200210290b0240200c450d00200b10290b200a1029200341f0046a41186a22024200370300200341f0046a41106a22254200370300200341f0046a41086a22244200370300200342003703f00441c6a3c400411a200341f0046a1000200341e8036a41186a2002290300370300200341e8036a41106a2025290300370300200341e8036a41086a2024290300370300200320032903f0043703e803412010272202450d0e20022007290000370000200241186a200741186a290000370000200241106a200741106a290000370000200241086a200741086a290000370000200341e8036a41202002412010032002102920034188036a41086a200341e8006a41086a29030037030020034188036a41106a200341e8006a41106a29030037030020034188036a41186a200341e8006a41186a2903003703002003200329036837038803410121240b410021250b20034195046a200341c8026a41086a2903003700002003419d046a200341c8026a41106a290300370000200341a5046a200341c8026a41186a290300370000200341ad046a20243a0000200341ae046a200329038803370100200341b6046a20034188036a41086a290300370100200341be046a20034188036a41106a290300370100200341c6046a20034188036a41186a290300370100200320253a008c04200320032903c80237008d042003200341d0006a36028804200341f0046a41186a22024200370300200341f0046a41106a22254200370300200341f0046a41086a22244200370300200342003703f00420094132200341f0046a1000200341e8036a41186a2002290300370300200341e8036a41106a2025290300370300200341e8036a41086a2024290300370300200320032903f0043703e803200341003602b801200342013703b00120032802502102200320032802582225360268200341e8006a200341b0016a1030024002402025450d0020254105742107410020032802b80122256b212620032802b001212820032802b401212703400240202720266a411f4b0d00202541206a22242025490d1420274101742208202420242008491b22244100480d140240024020270d002024102721280c010b202820272024102821280b2028450d03202421270b202820256a22242002290000370000202441186a200241186a290000370000202441106a200241106a290000370000202441086a200241086a290000370000202641606a2126202541206a2125200241206a2102200741606a22070d000b200320273602b401200320253602b801200320283602b0010b20034188046a410472200341b0016a10c60320032802b4012102200341e8036a412020032802b001222520032802b801100302402002450d00202510290b2009102902402003280254450d00200328025010290b0240200328029c02450d0020032802980210290b4100212641012127410021250c1a0b20244101102a000b41124101102a000b41324101102a000b418f89c3004133104e000b41204101102a000b41324101102a000b419bffc400419f01104e000b20084101102a000b20244101102a000b20254101102a000b20084101102a000b20274101102a000b20084101102a000b41204101102a000b0240200b450d00200a10290b20020d0041012127410021260c0b0b41012127410021262008450d0a202810290c0a0b024020032802ac04450d0020032802a80410290b410021250c080b102b000b20032013202c202c201356200420065620042006511b22021b221320297c220537038802200341f8016a41186a2006200420021b2206202a7c2005201354ad7c37030020032013202b7c22043703f80120032006202d7c2004201354ad7c37038002200341e8006a200341f8016a10d803200328029c0221250b2025450d0220032802980210290c020b41c2fec4002125411021240c040b41d588c3002125412a21240c030b4100212541012126410121270c030b41e4fdc4002125411921240c010b4184efc2002125411521240b41012126410121270b0240024020012d00002202410d4b0d00410120027441be3f710d01024020024106460d002002410d470d012027450d02200141086a280200450d02200141046a28020010290c020b2026450d01200141086a280200450d01200141046a28020010290c010b200141086a280200450d00200141046a28020010290b200020243602042000202536020020034190056a24000bb0c90107017f027e017f017e157f017e027f230041a0086b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e12000102030405060708090b0c0d0e0f101112000b200341b4036a4101360200200342013702a403200341ccfdc4003602a00320034102360264200341c4fdc4003602602003200341e0006a3602b003200341a0036a41a09ac4001057000b200141106a2903002104200141086a2903002105200141046a28020021062002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d00002111200241046a2d00002112200241026a2f01002113024002400240024020022d0000450d002003200737028402200320083a008302200320093a0082022003200a3b018002410121020c010b2002410c6a2d000021142002410a6a2f01002115200241096a2d00002116200241086a2d00002117200241066a2f01002118200241056a2d0000211920022d0001211a200320073703800241012102201a41ff01714101460d010b412a21164100211441d588c300211a410021150c010b2018410874201972201741187472211a410021020b201541ffff0371410874201441187472201641ff017172211420020d5920032007370378200320083a0077200320093a00762003200a3b01742003200b3a00732003200c3a00722003200d3b01702003200e3a006f2003200f3a006e200320103b016c200320113a006b200320143600672003201a360063200320123a0062200320133b01600240200542808084fea6dee1115441002004501b450d0041b09ac400211a410d21140c5a0b200341106a200341e0006a2005200410ac0102402003280210450d0041bd9ac400211a411a21140c5a0b200341086a41b086c500411910b501200328020c210220032802082114200341b8076a41086a221a4200370300200342003703b80741b086c5004119200341b8076a1004200341f0066a41086a2215201a290300370300200320032903b8073703f00620032002410020141b221641016a3602a003200341f0066a4110200341a0036a41041003412010272202450d1120022003290360370000200341b4036a428180808010370200200241186a200341e0006a41186a290300370000200241106a200341e0006a41106a290300370000200241086a200341e0006a41086a290300370000200320053703a003200320023602b003200320043703a8032016200341a0036a10c203201a4200370300200342003703b80741b7d2c3004115200341b8076a10042015201a290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a1005211a0240024020032802a0032208417f460d00201a450d0020032008360284022003201a36028002200341a0036a20034180026a103f20032802a0032214450d14200341a8036a280200210220032802a40321152008450d01201a10290c010b4108211441002102410021150b200341a0036a200610c103200341c0006a41186a2208200341e0006a41186a290300370300200341c0006a41106a2209200341e0006a41106a290300370300200341c0006a41086a220a200341e0006a41086a29030037030020032003290360370340024020152002470d00200241016a221a2002490d4920024101742215201a201a2015491b2215ad42b0017e2207422088a70d492007a7221a4100480d490240024020020d00201a102721140c010b2014200241b0016c201a102821140b2014450d140b2014200241b0016c220b6a200341a0036a41880110ce04221a201636028801201a200329034037028c01201a4194016a200a290300370200201a419c016a2009290300370200201a41a4016a2008290300370200200320153602a403200320143602a0032003200241016a221a3602a803200341b8076a41086a22084200370300200342003703b80741b7d2c3004115200341b8076a1004200341f0066a41086a2008290300370300200320032903b8073703f00620034110360284022003200341f0066a36028002200341a0036a20034180026a10330240201a2002490d00200b41b0016a211a2014210203402002103d200241b0016a2102201a41d07e6a221a0d000b0b02402015450d00201410290b200341b8036a2004370300200341b0036a2005370300200341ac036a201636020041002116200341a8036a41003a0000200341053a00a00341b8d6c5004100200341a0036a1088012006103d200610294101211541012106410121084100211a0c5a0b200141046a280200210a2002411a6a2901002107200241196a2d00002116200241186a2d00002108200241166a2f01002109200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d00002111200241046a2d00002112200241026a2f01002113024002400240024020022d0000450d002003200737028402200320163a008302200320083a008202200320093b018002410121020c010b2002410c6a2d000021142002410a6a2f01002106200241096a2d00002115200241086a2d00002117200241066a2f01002118200241056a2d0000211920022d0001211a200320073703800241012102201a41ff01714101460d010b412a21154100211441d588c300211a410021060c010b2018410874201972201741187472211a410021020b200641ffff0371410874201441187472201541ff017172211420020d5520032007370378200320163a0077200320083a0076200320093b01742003200b3a00732003200c3a00722003200d3b01702003200e3a006f2003200f3a006e200320103b016c200320113a006b200320143600672003201a360063200320123a0062200320133b0160200341a0036a200a10b603024020032802b00322020d0041d79ac400211a41242114410121150c570b200341bc036a2802002116200341a0036a41186a280200211a20032802b4032106200341186a200341e0006a20032902a403220742208620033502a003842204200341ac036a350200422086200742208884220710ac0120032802180d54200341c0006a41186a200341e0006a41186a290300370300200341c0006a41106a2215200341e0006a41106a290300370300200341c0006a41086a2209200341e0006a41086a2903003703002003200329036037034002402006201a460d00200621080c520b200641016a22142006490d4720064101742208201420142008491b220841ffffff3f712008470d47200841057422144100480d470240024020060d002014102721020c010b200220064105742014102821020b20020d5120144101102a000b2002411a6a2901002107200241196a2d0000211a200241186a2d00002114200241166a2f01002106024020022d0000450d0020032007370284022003201a3a008302200320143a008202200320063b0180020c500b200241156a2d00002116200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002117200241026a2f01002118200141026a2d00002119200141046a280200211b20022d0001210220012d0001211c200320073703800241012115200241ff01714101460d060c4f0b2002411a6a2901002107200241196a2d0000211a200241186a2d00002114200241166a2f01002106024020022d0000450d0020032007370284022003201a3a008302200320143a008202200320063b0180020c4f0b200141026a2d00002118200141046a280200211920012d0001211b200241156a2d00002115200241146a2d00002116200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211720022d000121022003200737038002200241ff01714101470d4e200320073703782003201a3a0077200320143a0076200320063b0174200320153a0073200320163a0072200320083b0170200320093a006f2003200a3a006e2003200b3b016c2003200c3a006b200320133a0062200320173b01602003200e410874200d41187472200f7236006720032011410874201272201041187472360063200341a0036a200341e0006a10c30320032d00a0034101470d4d200341ac036a2d00002102200341ad036a2900002107200341b5036a280000211a20032f00a103211420032d00a303210620032902a40321042003200341b9036a2900003703b8032003201a3602b403200320073702ac03200320023a00ab03200320043700a303200320063a00a203200320143b01a003200341a0036a2019201b41ff0171410047201810c403211a41222114410121150c540b2002410c6a2802002109200241086a280200210a200241046a2802002106200141106a2903002105200141086a2903002107200141046a2802002115200241036a2d0000211620012d0001211420022d0000211a20022f0001210820034180026a41086a2002411c6a2802003602002003200241146a290200370380020240024002400240201a4101470d00200641ff01710d01200a2009490d010c020b201a4103460d010b201a20082016411074727241ff01710d010b42002104200341b8076a41086a22024200370300200342003703b80741888dc300410d200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a1005211a024020032802a0032202417f460d00200342003703a003200341a0036a201a2002410820024108491b10ce041a200241074d0d1220032903a0032104201a10290b200341a0036a201541880110ce041a200341e0006a2004200742c0d102200742c0d102561b7c200341a0036a2014200510b503410121060240024020032802604101470d002003280264221a0d010b20151029410021150c4c0b200341e8006a28020021140c4a0b2015103d4128211441ad88c300211a0c490b41a584c200211a410e211420022d0000417f6a220941024b0d51200141046a280200210a410121154101210641012108410121160240024020090e03005701000b200241046a2d00000d5241012115410121064101210841012116200241086a28020041036c2002410c6a280200410174490d560b200341a0036a200a10a703024020032802a8034112470d0041bf9dc400211a410d2114410121150c530b20032802a003210220034180026a200341a0036a410472419c0110ce041a20032002360260200341e0006a41047220034180026a419c0110ce041a200341003602a803200342013703a003200341e0006a41086a2214200341a0036a103220032802a403211a20032802a803210620032802a003210220034180026a41186a2215420037030020034180026a41106a2216420037030020034180026a41086a2208420037030020034200370380022002200620034180026a1000200341c8056a41186a22062015290300370300200341c8056a41106a22152016290300370300200341c8056a41086a2216200829030037030020032003290380023703c8050240201a450d00200210290b200341a0036a41186a2006290300370300200341a0036a41106a2015290300370300200341a0036a41086a2016290300370300200320032903c8053703a003411710272202450d102002410f6a41002900af9b44370000200241086a41002900a89b44370000200241002900a09b4437000020024117413710282202450d11200220032903a0033700172002412f6a200341a0036a41186a2216290300370000200241276a200341a0036a41106a22082903003700002002411f6a200341a0036a41086a29030037000020034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a2215420037030020034200370380022002413720034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c004200341c0046a412041b8d6c50041004100100b211a20021029201a417f460d472014103d41cc9dc400211a41252114410121150c520b200141046a280200210641a584c200211a410e211420022d0000417f6a221541024b0d450240024020150e03004701000b200241086a2802004101742002410c6a280200490d46200241046a28020041ff01710d460b200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341f0066a411041b8d6c50041004100100b417f460d4141d19bc400211a411521140c450b200141046a280200210641a584c200211a410e211420022d0000417f6a221541024b0d3f0240024020150e03004101000b200241046a2d00000d40200241086a28020041036c2002410c6a280200410174490d400b200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341f0066a411041b8d6c50041004100100b417f460d3e41d19bc400211a411521140c3f0b200141306a2903002104200141286a290300210720034190086a200141196a29000037030020034188086a200141116a290000370300200341f8076a41086a200141096a290000370300200320012900013703f8074101211541a584c200211a410e211420022d0000417e6a220641014b0d4f0240024020060e020001000b200241046a2d00000d50200241086a28020041036c2002410c6a280200410174490d500b200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a1005210220032802a003221a417f460d3c2002450d3c2003201a3602dc07200320023602d807200341a0036a200341d8076a103c20032802a0034112460d38200341e0006a200341a0036a41880110ce041a200341003a009f082003419f086a20032802d807221620032802dc072214410047220610ce041a20142006490d0f2003201420066b3602dc072003201620066a3602d807024002402014450d0020032d009f0822064103490d010b200341e0006a103d0c390b2003280260211420034180026a200341e0006a41047241840110ce041a20144112460d38200341c8056a20034180026a41840110ce041a0240201a450d00200210290b200341c0046a200341c8056a41840110ce041a20032014360260200341e0006a410472200341c0046a41840110ce041a20064102460d3941f29bc400211a412a21140c3a0b200320073703b8032003201a3a00b703200320143a00b603200320063b01b403200320163a00b303200320083a00b203200320093b01b0032003200a3a00af032003200b3a00ae032003200c3b01ac032003200d3a00ab03200320173a00a203200320183b01a0032003200f410874200e411874722010723600a703200320124108742013722011411874723600a303200341a0036a201b201c41ff0171410047201910c403211a412221140c4e0b200341f0076a200141196a290000370300200341d8076a41106a200141116a290000370300200341d8076a41086a200141096a290000370300200320012900013703d8074101211541a584c200211a410e211420022d00004101470d4d200241236a2d00002116200241216a2f000021082002411f6a2d000021092002411d6a2f0000210a2002410f6a2d0000210b2002410d6a2f0000210c2002410b6a2d0000210d200241096a2f0000210e200241076a2d0000210f200241056a2f00002110200241246a3502002105200241206a310000211d200241116a2900002107200241106a2d000021112002410c6a2d00002112200241086a2d00002113200241046a2d000021062003200241196a28000036028802200320073703800220064101470d4d200320032902840222043d018808200320113a008308200320044238883c008f08200320044230883c008e08200320044220883d018c08200320044218883c008b08200320044210883c008a08200320073d018408200320074218883c0087082003200c200b411074724108742012723600ff072003200e200d411074724108742013723600fb0720032010200f4110747222023b01f807200320024110763a00fa0720032007a74110763a0086082003201d421886200a200941107472ad42ffffff0783842008201641107472ad42ffffff07834220868420054238868437039008200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a100521020240024020032802a003221a417f460d002002450d002003201a3602bc07200320023602b807200341a0036a200341b8076a103c20032802a0034112460d37200341e0006a200341a0036a41880110ce041a200341003a009f082003419f086a20032802b807221620032802bc072214410047220610ce041a20142006490d102003201420066b3602bc072003201620066a3602b807024002402014450d0020032d009f084103490d010b200341e0006a103d0c380b2003280260211420034180026a200341e0006a41047241840110ce041a20144112460d37200341c8056a20034180026a41840110ce041a0240201a450d00200210290b200341c0046a200341c8056a41840110ce041a200320143602a003200341a0036a410472200341c0046a41840110ce041a2003410036026820034201370360200341a0036a200341e0006a10322003280264211a200328026821062003280260210220034180026a41186a221642003703004110211420034180026a41106a2208420037030020034180026a41086a2209420037030020034200370380022002200620034180026a1000200341e0006a41186a2016290300370300200341e0006a41106a2008290300370300200341e0006a41086a200929030037030020032003290380023703600240201a450d00200210290b200341d8076a200341e0006a412010d0042102200341a0036a103d41d39cc400211a20020d4f200341a0036a200341d8076a10c50320032802a803220b0d01410021024101210b420021070c360b4114211441bf9cc400211a0c4e0b410021020240024020032902ac032207422088a7221a41014b0d00201a0e023601360b0340201a410176221420026a22062002200b20064105746a200341f8076a412010d0044101481b2102201a20146b221a41014b0d000b0b200b20024105746a200341f8076a412010d004221a450d33201a411f7620026a21020c340b4101211520022d000120022d0000720d31200141046a28020010ab030c480b4101211520022d000120022d0000720d30200141086a2802002106200141046a2802002102200341e0006a200141106a290300220710ac03200328026021140240024002402003280268221a20024d0d00201420024190016c6a22162802004112460d01201420024190016c6a4188016a2802002006470d012016103d20164112360200200341a0036a41086a200341e0006a41086a280200360200200320032903603703a003411710272202450d102002410f6a41002900ffd143370000200241086a41002900f8d143370000200241002900f0d14337000020024117412e10282202450d112002200737001720034180026a41186a221a420037030020034180026a41106a2214420037030020034180026a41086a2206420037030020034200370380022002411f20034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2014290300370300200341c0046a41086a200629030037030020032003290380023703c00420034120360284022003200341c0046a36028002200341a0036a20034180026a10312002102920032802a0032114024020032802a8032202450d0020024190016c211a201421020340024020022802004112460d002002103d0b20024190016a2102201a41f07e6a221a0d000b0b20032802a403450d4a201410290c4a0b201a450d010b201a4190016c211a201421020340024020022802004112460d002002103d0b20024190016a2102201a41f07e6a221a0d000b0b02402003280264450d00201410290b41f19dc400211a411221140c4b0b200341e0006a41186a200141196a290000370300200341e0006a41106a200141116a290000370300200341e0006a41086a200141096a29000037030020032001290001370360200241166a2f0100211a200241186a2d00002114200241196a2d000021062002411a6a2901002107024020022d0000450d002003200737028402200320063a008302200320143a0082022003201a3b0180020c450b200241026a2f01002116200241046a2d00002108200241056a2d00002109200241066a2f0100210a200241086a2d0000210b200241096a2d0000210c2002410a6a2f0100210d2002410c6a2d0000210e2002410d6a2d0000210f2002410e6a2f01002110200241106a2d00002111200241116a2d00002112200241126a2f01002113200241146a2d00002117200241156a2d0000211820022d000121022003200737038002200241ff01714101470d44410f10272202450d0e200241076a41002900909d44370000200241002900899d443700002002410f412f10282202450d0f2002200329036037000f200241276a200341e0006a41186a221c2903003700002002411f6a200341e0006a41106a221e290300370000200241176a200341e0006a41086a221f29030037000020034180026a41186a2215420037030020034180026a41106a2219420037030020034180026a41086a221b420037030020034200370380022002412f20034180026a1000200341c0046a41186a2015290300370300200341c0046a41106a2019290300370300200341c0046a41086a201b29030037030020032003290380023703c004200341c0046a412041b8d6c50041004100100b21152002102902402015417f460d0041989dc400211a410f2114410121150c4b0b200341a0036a41186a201c290300370300200341a0036a41106a201e290300370300200341a0036a41086a201f290300370300200320032903603703a003410f10272202450d10200241076a41002900909d44370000200241002900899d443700002002410f412f10282215450d11201520032903a00337000f201541276a200341a0036a41186a2903003700002015411f6a200341a0036a41106a290300370000201541176a200341a0036a41086a29030037000020034180026a41186a2202420037030020034180026a41106a2219420037030020034180026a41086a221b420037030020034200370380022015412f20034180026a1000200341c0046a41186a2002290300370300200341c0046a41106a2019290300370300200341c0046a41086a201b29030037030020032003290380023703c004412010272202450d1220022007370018200220063a0017200220143a00162002201a3b0014200220183a0013200220173a0012200220133b0010200220123a000f200220113a000e200220103b000c2002200f3a000b2002200d410874200c72200e411874723600072002200a410874200972200b41187472360003200220083a0002200220163b0000200341c0046a412020024120100320021029201510294100211a410121150c4a0b2002411a6a2901002107200241196a2d00002114200241186a2d00002106200241166a2f01002115024020022d0000450d002003200737028402200320143a008302200320063a008202200320153b0180020c440b200241156a2d00002116200241146a2d00002108200241126a2f01002109200241116a2d0000210a200241106a2d0000210b2002410e6a2f0100210c2002410d6a2d0000210d2002410c6a2d0000210e2002410a6a2f0100210f200241096a2d00002110200241086a2d00002111200241066a2f01002112200241056a2d00002113200241046a2d00002117200241026a2f0100211820022d000121022003200737038002200241ff01714101470d43410f10272202450d124100211a200241076a41002900909d44370000200241002900899d443700002002410f412f10282202450d1320022007370027200220143a0026200220063a0025200220153b0023200220163a0022200220083a0021200220093b001f2002200a3a001e2002200b3a001d2002200c3b001b2002200d3a001a2002200f410874201072200e4118747236001620022012410874201372201141187472360012200220173a0011200220183b000f20034180026a41186a2214420037030020034180026a41106a2206420037030020034180026a41086a2215420037030020034200370380022002412f20034180026a1000200341c0046a41186a2014290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c004200341c0046a4120100c20021029410121150c460b200341f8076a41186a200141196a290000370300200341f8076a41106a200141116a290000370300200341f8076a41086a200141096a290000370300200320012900013703f8072002411a6a2901002107200241196a2d0000211a200241186a2d00002114200241166a2f01002106024020022d0000450d0020032007370284022003201a3a008302200320143a008202200320063b0180020c430b200241156a2d00002115200241146a2d00002116200241126a2f01002108200241116a2d00002109200241106a2d0000210a2002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241086a2d00002110200241066a2f01002111200241056a2d00002112200241046a2d00002113200241026a2f0100211720022d000121022003200737038002200241ff01714101470d42200320073703e0052003201a3a00df05200320143a00de05200320063b01dc05200320153a00db05200320163a00da05200320083b01d805200320093a00d7052003200a3a00d6052003200b3b01d4052003200c3a00d305200320133a00ca05200320173b01c8052003200e410874200f72200d411874723600cf05200320114108742012722010411874723600cb05200341a0036a200341f8076a10c30320032d00a0034101470d41200320032902a403370063200320032d00a3033a0062200320032f00a1033b01602003200341b9036a2900003703782003200341b5036a2800003602742003200341ad036a29000037026c2003200341ac036a2d00003a006b0240200341e0006a200341c8056a412010d004450d0041a79dc400211a410b2114410121150c490b200341a0036a41186a200341f8076a41186a290300370300200341a0036a41106a200341f8076a41106a290300370300200341a0036a41086a200341f8076a41086a290300370300200320032903f8073703a003410f10272202450d134100211a200241076a41002900909d44370000200241002900899d443700002002410f412f10282202450d14200220032903a00337000f200241276a200341a0036a41186a2903003700002002411f6a200341a0036a41106a290300370000200241176a200341a0036a41086a29030037000020034180026a41186a2214420037030020034180026a41106a2206420037030020034180026a41086a2215420037030020034200370380022002412f20034180026a1000200341c0046a41186a2014290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c004200341c0046a4120100c20021029410121150c480b200141216a2d0000210a200341206a41186a200141196a290000370300200341206a41106a200141116a290000370300200341206a41086a200141096a290000370300200320012900013703202002411a6a2901002107200241196a2d00002116200241186a2d00002108200241166a2f01002109200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d00002111200241046a2d00002112200241026a2f01002113024002400240024020022d0000450d002003200737028402200320163a008302200320083a008202200320093b018002410121020c010b2002410c6a2d000021142002410a6a2f01002106200241096a2d00002115200241086a2d00002117200241066a2f01002118200241056a2d0000211920022d0001211a200320073703800241012102201a41ff01714101460d010b41d588c300211a41002106412a2115410021140c010b2018410874201972201741187472211a410021020b200641ffff0371410874201541ff017172201441187472211420020d46200320143600d7062003201a3600d306200320123a00d206200320133b01d0062003200e3a00df062003200f3a00de06200320103b01dc06200320113a00db06200320163a00e706200320083a00e606200320093b01e4062003200b3a00e3062003200c3a00e2062003200d3b01e006200320073703e806200341f0066a41186a2007370300200341f0066a41106a20032903e006370300200341f0066a41086a200341d0066a41086a290300370300200320032903d0063703f006200341c8056a41186a200341206a41186a290300370300200341c8056a41106a200341206a41106a290300370300200341c8056a41086a200341206a41086a2903003703002003200a3a00e805200320032903203703c805411510272202450d142002410d6a41002900bbd143370000200241086a41002900b6d143370000200241002900aed14337000020024115413510282202450d15200220032903f0063700152002412d6a200341f0066a41186a290300370000200241256a200341f0066a41106a2903003700002002411d6a200341f0066a41086a29030037000020034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a2215420037030020034200370380022002413520034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c004200341003602a003200341c0046a4120200341a0036a1005211a0240024020032802a0032216417f460d00201a450d00200320163602fc072003201a3602f807200341a0036a200341f8076a10fc0220032d00c10322064102460d18200341e0006a41186a2208200341da036a290100370300200341e0006a41106a2209200341d2036a290100370300200341e0006a41086a220a200341ca036a29010037030020034180026a41086a220b200341eb036a29000037030020034180026a41106a220c200341f3036a29000037030020034180026a41186a220d200341fb036a290000370300200320032901c2033703602003200341e3036a29000037038002200341e2036a2d0000211502402016450d00201a10290b200341c0006a41086a200a290300370300200341c0006a41106a2009290300370300200341c0006a41186a2008290300370300200341f8076a41086a200b290300370300200341f8076a41106a200c290300370300200341f8076a41186a200d2903003703002003200329036037034020032003290380023703f8070c010b20034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a221542003703002003420037038002419ad2c300411d20034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c004200341003602a003200341c0046a4120200341a0036a1005211a02400240024020032802a0032206417f460d00201a450d0020034180026a2006412020064120491b22156a41004100412020156b2015411f4b1b10cd041a20034180026a201a201510ce041a2006411f4d0d1b200341a0036a41186a220620034180026a41186a290300370300200341a0036a41106a221520034180026a41106a290300370300200341a0036a41086a221620034180026a41086a29030037030020032003290380023703a003201a102920034198076a41186a2006290300220737030020034198076a41106a2015290300220437030020034198076a41086a20162903002205370300200320032903a003221d37039807200341b8076a41186a2007370300200341b8076a41106a2004370300200341b8076a41086a20053703002003201d3703b80741151027221a0d0141154101102a000b20034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a221542003703002003420037038002419ad2c300411d20034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c00441201027221a450d1b201a20032903f006370000201a41186a200341f0066a41186a290300370000201a41106a200341f0066a41106a290300370000201a41086a200341f0066a41086a290300370000200341c0046a4120201a41201003201a1029410021150c010b201a410d6a41002900bbd143370000201a41086a41002900b6d143370000201a41002900aed143370000201a4115413510282215450d1b201520032903b8073700152015412d6a200341b8076a41186a290300370000201541256a200341b8076a41106a2903003700002015411d6a200341b8076a41086a29030037000020034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a2216420037030020034200370380022015413520034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201629030037030020032003290380023703c004200341003602a003200341c0046a4120200341a0036a1005210820032802a0032209417f460d1d2008450d1d20032009360284022003200836028002200341a0036a20034180026a10fc0220032d00c103220b4102460d1c200341f8076a41186a221a200341a0036a41186a290300370300200341f8076a41106a2206200341a0036a41106a290300370300200341f8076a41086a2216200341a0036a41086a290300370300200320032903a0033703f80720032d00c003210a200341e0006a200341c2036a220c41c10010ce041a02402009450d00200810290b200341d8076a41086a22082016290300370300200341d8076a41106a22092006290300370300200341d8076a41186a220d201a290300370300200320032903f8073703d80720034180026a200341e0006a41c10010ce041a201a200d2903003703002006200929030037030020162008290300370300200320032903d8073703f8072003200b3a00a003200341a0036a41017220034180026a41c10010ce041a200341e0006a41186a201a290300370300200341e0006a41106a2006290300370300200341e0006a41086a2016290300370300200320032903f80737036020032d00c103210920034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a2216420037030020034200370380022015413520034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201629030037030020032003290380023703c00441201027221a450d1e201a2003290360370000201a41186a200341e0006a41186a290300370000201a41106a200341e0006a41106a290300370000201a41086a200341e0006a41086a29030037000002400240200a41054b0d000240024002400240024002400240200a0e06000102030405000b200341003a009f080c050b200341013a009f080c040b200341023a009f080c030b200341033a009f080c020b200341043a009f080c010b200341053a009f080b41c0002106201a412041c0001028221a450d21201a20032d009f083a002041012108200341013a009f08412121160c010b200341013a009f0841000d3b41c000210641202116201a412041c0001028221a450d2120032d009f0821080b201a20166a20083a000002402006201641016a22086b411f4b0d0041000d3b2006410174220a200841206a220b200b200a491b220a4100480d3b201a2006200a1028221a450d2c200a21060b201a20086a220820032903f006370000200841186a200341f0066a41186a290300370000200841106a200341f0066a41106a290300370000200841086a200341f0066a41086a290300370000201641216a210802400240200c410020094101461b22160d0041002116200341003a009f080240024020062008460d00200821060c010b41000d3d20064101742216200641016a220820082016491b22164100480d3d201a200620161028221a450d2420032d009f0821160b201a20066a20163a0000200641016a21060c010b200341013a009f080240024020062008460d004101210a20062109200821060c010b41000d3c20064101742208200641016a220920092008491b22094100480d3c201a200620091028221a450d2420032d009f08210a0b201a20066a200a3a000002402009200641016a22086b411f4b0d0041000d3c2009410174220a200841206a220b200b200a491b220a4100480d3c201a2009200a1028221a0d00200a4101102a000b201a20086a22082016290000370000200841186a201641186a290000370000200841106a201641106a290000370000200841086a201641086a290000370000200641216a21060b200341c0046a4120201a20061003201a10292015102920034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a221542003703002003420037038002419ad2c300411d20034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c00441201027221a450d23201a20032903f006370000201a41186a200341f0066a41186a290300370000201a41106a200341f0066a41106a290300370000201a41086a200341f0066a41086a290300370000200341c0046a4120201a41201003201a1029200341f8076a41086a200341b8076a41086a290300370300200341f8076a41106a200341b8076a41106a290300370300200341f8076a41186a200341b8076a41186a290300370300200320032903b8073703f807410121150b410021060b200341ad036a200341c0006a41086a290300370000200341b5036a200341c0006a41106a290300370000200341bd036a200341c0006a41186a290300370000200341c5036a20153a0000200341c6036a20032903f807370100200341ce036a200341f8076a41086a290300370100200341d6036a200341f8076a41106a290300370100200341de036a200341f8076a41186a290300370100200320063a00a403200320032903403700a5032003200341c8056a3602a00320034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a2215420037030020034200370380022002413520034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c004200341003602682003420137036041201027221a450d22201a20032903c805370000201a41186a200341c8056a41186a290300370000201a41106a200341c8056a41106a290300370000201a41086a200341c8056a41086a290300370000200342a080808080043702642003201a360260024020032d00e805220641054b0d00024002400240024002400240024020060e06000102030405000b200341003a009f080c050b200341013a009f080c040b200341023a009f080c030b200341033a009f080c020b200341043a009f080c010b200341053a009f080b201a412041c0001028221a450d24201a20032d009f083a00202003201a360260200342c080808090043702640b200341a0036a410472200341e0006a10c6032003280264211a200341c0046a412020032802602206200328026810030240201a450d00200610290b20021029200342e4cab5fbb6ccdcb0e3003703900720034190076a200341d0066a427f10a601200341a0036a41086a41083a0000200341a9036a20032903d006370000200341b1036a200341d0066a41086a290300370000200341b9036a200341d0066a41106a290300370000200341c1036a200341d0066a41186a290300370000200341c9036a2003290320370000200341d1036a200341206a41086a290300370000200341d9036a200341206a41106a290300370000200341e1036a200341206a41186a290300370000200341053a00a0034100211a41b8d6c5004100200341a0036a108801410121150c470b2002411a6a2901002107200241196a2d00002116200241186a2d00002108200241166a2f01002109200241156a2d0000210a200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d00002110200241046a2d00002111200241026a2f01002112024002400240024020022d0000450d002003200737028402200320163a008302200320083a008202200320093b018002410121020c010b2002410c6a2d000021142002410a6a2f01002106200241096a2d00002115200241086a2d00002113200241066a2f01002117200241056a2d0000211820022d0001211a200320073703800241012102201a41ff01714101460d010b41d588c300211a41002106412a2115410021140c010b2017410874201872201341187472211a410021020b200641ffff0371410874201541ff017172201441187472211420020d45200320073703b007200320163a00af07200320083a00ae07200320093b01ac072003200a3a00ab072003200b3a00aa072003200c3b01a8072003200d3a00a7072003200e3a00a6072003200f3b01a407200320103a00a3072003201436009f072003201a36009b07200320113a009a07200320123b019807411510272202450d23410d21142002410d6a41002900bbd143370000200241086a41002900b6d143370000200241002900aed14337000020024115413510282202450d2420022003290398073700152002412d6a20034198076a41186a290300370000200241256a20034198076a41106a2903003700002002411d6a20034198076a41086a29030037000020034180026a41186a221a420037030020034180026a41106a2206420037030020034180026a41086a2215420037030020034200370380022002413520034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2006290300370300200341c0046a41086a201529030037030020032003290380023703c004200341c0046a412041b8d6c50041004100100b211a200210290240201a417f470d0041b29dc400211a410121150c470b411510272202450d252002410d6a41002900bbd143370000200241086a41002900b6d143370000200241002900aed14337000020024115413510282202450d2620022003290398073700152002412d6a20034198076a41186a290300370000200241256a20034198076a41106a2903003700002002411d6a20034198076a41086a29030037000020034180026a41186a221a420037030020034180026a41106a2214420037030020034180026a41086a2206420037030020034200370380022002413520034180026a1000200341c0046a41186a201a290300370300200341c0046a41106a2014290300370300200341c0046a41086a200629030037030020032003290380023703c004200341003602a003200341c0046a4120200341a0036a1005211a20032802a0032214417f460d29201a450d29200320143602cc052003201a3602c805200341a0036a200341c8056a10fc0220032d00c10322064102460d27200341e0006a41086a200341ca036a290100370300200341e0006a41106a200341d2036a290100370300200341e0006a41186a200341da036a29010037030020034180026a41086a200341eb036a29000037030020034180026a41106a200341f3036a29000037030020034180026a41186a200341fb036a290000370300200320032901c2033703602003200341e3036a29000037038002200341e2036a2d0000211520032c00c003211602402014450d00201a10290b200341c0046a4120100c0c2a0b41204101102a000b418f89c3004133104e000b201a4108102a000b418f89c3004133104e000b41174101102a000b41374101102a000b20062014103e000b20062014103e000b41174101102a000b412e4101102a000b410f4101102a000b412f4101102a000b410f4101102a000b412f4101102a000b41204101102a000b410f4101102a000b412f4101102a000b410f4101102a000b412f4101102a000b41154101102a000b41354101102a000b418f89c3004133104e000b418f89c3004133104e000b41204101102a000b41354101102a000b418f89c3004133104e000b419bffc400419f01104e000b41204101102a000b41c0004101102a000b41c0004101102a000b20164101102a000b20094101102a000b41204101102a000b41204101102a000b41c0004101102a000b41154101102a000b41354101102a000b41154101102a000b41354101102a000b418f89c3004133104e000b200a4101102a000b41022106410021160b200341d8076a41186a2208200341e0006a41186a290300370300200341d8076a41106a2209200341e0006a41106a290300370300200341d8076a41086a220a200341e0006a41086a290300370300200341b8076a41086a221a20034180026a41086a290300370300200341b8076a41106a220b20034180026a41106a290300370300200341b8076a41186a220c20034180026a41186a290300370300200320032903603703d80720032003290380023703b8072002102941002114024020064102460d00200341c8056a41086a200a290300370300200341c8056a41106a2009290300370300200341c8056a41186a2008290300370300200341f8076a41086a201a290300370300200341f8076a41106a200b290300370300200341f8076a41186a200c290300370300200320032903d8073703c805200320032903b8073703f8074100210202400240024002400240024002400240024002400240201541ff01714101470d00411510272202450d012002410d6a41002900bbd143370000200241086a41002900b6d143370000200241002900aed14337000020024115413510282202450d02200220032903f8073700152002412d6a20034190086a290300370000200241256a20034188086a2903003700002002411d6a200341f8076a41086a2903003700000b0240024020064101470d00411510272214450d042014410d6a41002900bbd143370000201441086a41002900b6d143370000201441002900aed14337000020144115413510282214450d05201420032903c8053700152014412d6a200341c8056a41186a290300370000201441256a200341c8056a41106a2903003700002014411d6a200341c8056a41086a29030037000020034180026a41186a2208420037030020034180026a41106a2209420037030020034180026a41086a220a420037030020034200370380022014413520034180026a1000200341c0046a41186a2008290300370300200341c0046a41106a2009290300370300200341c0046a41086a200a29030037030020032003290380023703c004200341003602a003200341c0046a4120200341a0036a1005210b024020032802a003220c417f460d00200b0d020b41e0a3c40041d300104e000b20034180026a41186a2214420037030020034180026a41106a2208420037030020034180026a41086a220942003703002003420037038002419ad2c300411d20034180026a1000200341c0046a41186a2014290300370300200341c0046a41106a2008290300370300200341c0046a41086a200929030037030020032003290380023703c0040240201541ff01714101460d00200341c0046a4120100c0c0a0b412010272214450d05201420032903f807370000201441186a200341f8076a41186a290300370000201441106a200341f8076a41106a290300370000201441086a200341f8076a41086a290300370000200341c0046a4120201441201003201410290c090b2003200c3602f4062003200b3602f006200341a0036a200341f0066a10fc0220032d00c103220d4102460d0520034180026a41206a220e200341a0036a41206a220f2d00003a000020034180026a41186a2208200341a0036a41186a221029030037030020034180026a41106a2209200341a0036a41106a221129030037030020034180026a41086a220a200341a0036a41086a2212290300370300200320032903a00337038002200341e0006a200341c2036a221341c10010ce041a0240200c450d00200b10290b201320032900603701002012200a2903003703002011200929030037030020102008290300370300200f200e2d00003a0000200341ca036a200341e0006a41086a290000370100200341d2036a200341e0006a41106a290000370100200341da036a200341e0006a41186a29000037010020032003290380023703a0032003200d3a00c103200341e2036a20153a0000200341e3036a20032903f807370000200341eb036a200341f8076a41086a290300370000200341f3036a200341f8076a41106a290300370000200341fb036a200341f8076a41186a2903003700002008420037030020094200370300200a420037030020034200370380022014413520034180026a1000200341c0046a41186a2008290300370300200341c0046a41106a2009290300370300200341c0046a41086a200a29030037030020032003290380023703c0042003410036026820034201370360412010272215450d06201520032903a003370000201541086a200341a0036a41086a290300370000201541106a200341a0036a41106a290300370000201541186a200341a0036a41186a290300370000200342a0808080800437026420032015360260024020032d00c003220841054b0d00024002400240024002400240024020080e06000102030405000b410021080c050b410121080c040b410221080c030b410321080c020b410421080c010b410521080b200320083a0080022015412041c00010282215450d08201520083a0020200342c08080809004370264200320153602600b200341c1036a200341e0006a10c60320032802642115200341c0046a4120200328026022082003280268100302402015450d00200810290b201410294101210b0c090b41154101102a000b41354101102a000b41154101102a000b41354101102a000b41204101102a000b418f89c3004133104e000b41204101102a000b41c0004101102a000b410021144100210b0b0240024002400240024002400240024020020d00410021060c010b20034180026a41186a2215420037030020034180026a41106a2208420037030020034180026a41086a2209420037030020034200370380022002413520034180026a1000200341c0046a41186a2015290300370300200341c0046a41106a2008290300370300200341c0046a41086a200929030037030020032003290380023703c004200341003602a003200341c0046a4120200341a0036a1005210a20032802a003220c417f460d02200a450d022003200c3602f4062003200a3602f006200341a0036a200341f0066a10fc0220032d00c1034102460d0120034180026a41206a220d200341a0036a41206a220e2d00003a000020034180026a41186a2215200341a0036a41186a220f29030037030020034180026a41106a2208200341a0036a41106a221029030037030020034180026a41086a2209200341a0036a41086a2211290300370300200320032903a00337038002200341e0006a200341c2036a221241c10010ce041a0240200c450d00200a10290b2011200929030037030020102008290300370300200f2015290300370300200e200d2d00003a000020032003290380023703a0032012200341e0006a41c10010ce0420032903c805370100200341ca036a200341c8056a41086a290300370100200341d2036a200341c8056a41106a290300370100200341da036a200341c8056a41186a290300370100200320063a00c10320154200370300200842003703002009420037030020034200370380022002413520034180026a1000200341c0046a41186a2015290300370300200341c0046a41106a2008290300370300200341c0046a41086a200929030037030020032003290380023703c0042003410036026820034201370360412010272206450d03200620032903a003370000200641086a200341a0036a41086a290300370000200641106a200341a0036a41106a290300370000200641186a200341a0036a41186a290300370000200342a0808080800437026420032006360260024020032d00c003221541054b0d00024002400240024002400240024020150e06000102030405000b410021150c050b410121150c040b410221150c030b410321150c020b410421150c010b410521150b200320153a0080022006412041c00010282206450d05200620153a0020200342c08080809004370264200320063602600b200341c1036a200341e0006a10c60320032802642106200341c0046a4120200328026022152003280268100302402006450d00201510290b20021029410121060b200b20144572450d040c050b418f89c3004133104e000b41e0a3c40041d300104e000b41204101102a000b41c0004101102a000b201410290b02402002452006720d00200210290b201621140b42002107201a4200370300200342003703b80741888dc300410d200341b8076a1004200341f0066a41086a201a290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a1005211a0240024020032802a0032202417f460d00200342003703a003200341a0036a201a2002410820024108491b10ce041a200241074d0d0120032903a0032107201a10290b200342e4cab5fbb6ccdcb0e300370360200341e0006a20034198076a427f427f2014410274419886c5006a3502004280af1a7e20077c410210a801200341a0036a41086a41093a0000200341a0036a41096a200329039807370000200341b1036a20034198076a41086a290300370000200341b9036a200341a8076a290300370000200341c1036a200341b0076a290300370000200341053a00a0034100211a41b8d6c5004100200341a0036a108801410121150c1c0b418f89c3004133104e000b41ad88c300211a412821140c1a0b41e39cc400211a412621142007a7450d19200b10290c190b200341a0036a41186a200341f8076a41186a290300370300200341a0036a41106a200341f8076a41106a290300370300200341a0036a41086a200341f8076a41086a290300370300200320032903f8073703a00302400240024002400240024020022007422088a722144b0d00024020142007a7470d00201441016a221a2014490d1020144101742206201a201a2006491b221a41ffffff3f71201a470d10201a41057422064100480d100240024020140d0020061027210b0c010b200b201441057420061028210b0b200b450d02201aad21070b200b20024105746a221a41206a201a201420026b41057410cf041a201a41186a200341a0036a41186a290300370000201a41106a200341a0036a41106a290300370000201a41086a200341a0036a41086a290300370000201a20032903a003370000200341b8076a41086a22024200370300200342003703b80741888dc300410d200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a100521020240024020032802a003221a417f460d002002450d00200342003703a003200341a0036a2002201a4108201a4108491b10ce041a201a41074d0d0420032903a00321042002102920044280af1a7c21040c010b4280af1a21040b411310272202450d032002410f6a41002800bb9c44360000200241086a41002900b49c44370000200241002900ac9c443700002002411341331028220c450d04200c20032903d807370013200c412b6a200341d8076a41186a290300370000200c41236a200341d8076a41106a290300370000200c411b6a200341d8076a41086a29030037000020034180026a41186a2202420037030020034180026a41106a221a420037030020034180026a41086a220642003703002003420037038002200c413320034180026a1000200341c0046a41186a2002290300370300200341c0046a41106a201a290300370300200341c0046a41086a200629030037030020032003290380023703c004200341003602a803200342013703a003410810272202450d05200220043700002003428880808080013702a403200320023602a0032003201441016a2202360260200341e0006a200341a0036a103002400240024020020d0020032802a803211a20032802a403211620032802a00321080c010b410020032802a803221a6b2106201441057441206a210920032802a003210820032802a4032116200b210203400240201620066a411f4b0d00201a41206a2214201a490d132016410174220a20142014200a491b22144100480d130240024020160d002014102721080c010b200820162014102821080b2008450d03201421160b2008201a6a22142002290000370000201441186a200241186a290000370000201441106a200241106a290000370000201441086a200241086a290000370000200641606a2106201a41206a211a200241206a2102200941606a22090d000b200320163602a4032003201a3602a803200320083602a0030b2007a72102200341c0046a41202008201a100302402016450d00200810290b200c102902402002450d00200b10290b200341a0036a41086a410a3a0000200341a9036a20032903f807370000200341c9036a20032903d807370000200341b1036a200341f8076a41086a290300370000200341b9036a200341f8076a41106a290300370000200341c1036a200341f8076a41186a290300370000200341d1036a200341d8076a41086a290300370000200341d9036a200341d8076a41106a290300370000200341e1036a200341d8076a41186a290300370000200341053a00a003200341f0036a20043703004100211a41b8d6c5004100200341a0036a108801200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341f0066a4110100c0c1f0b20144101102a000b41d0b1c5001058000b20064101102a000b418f89c3004133104e000b41134101102a000b41334101102a000b41084101102a000b418f89c3004133104e000b418f89c3004133104e000b200341003602a803200342013703a003200341e0006a200341a0036a103220032802a403211a20032802a803211420032802a003210220034180026a41186a2206420037030020034180026a41106a2216420037030020034180026a41086a2208420037030020034200370380022002201420034180026a1000200341a0036a41186a2006290300370300200341a0036a41106a2016290300370300200341a0036a41086a200829030037030020032003290380023703a0030240201a450d00200210290b0240200341f8076a200341a0036a412010d004450d0041e69bc400211a410c21140c010b42002105200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a221a2002290300370300200320032903b8073703f006200341f0066a4110100c20024200370300200342003703b80741888dc300410d200341b8076a1004201a2002290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a1005211a024020032802a0032202417f460d00200342003703a003200341a0036a201a2002410820024108491b10ce041a200241074d0d0220032903a0032105201a10290b200341a0036a200341e0006a41880110ce041a20034180026a2005200742c0d102200742c0d102561b7c200341a0036a4102200410b50302402003280280024101470d00200328028402221a450d0020034188026a28020021140c160b4100211a0c150b200341e0006a103d0c140b418f89c3004133104e000b419c9cc400211a411021140c120b200341003602a803200342013703a0032006200341a0036a103220032802a403211a20032802a803211420032802a003210220034180026a41186a2215420037030020034180026a41106a2216420037030020034180026a41086a2208420037030020034200370380022002201420034180026a1000200341e0006a41186a22142015290300370300200341e0006a41106a2016290300370300200341e0006a41086a200829030037030020032003290380023703600240201a450d00200210290b200341a0036a41186a2014290300370300200341a0036a41106a200341e0006a41106a290300370300200341a0036a41086a200341e0006a41086a290300370300200320032903603703a00320034180026a200341a0036a10c503024002400240200328028802221a450d00200329038002210442002107200341b8076a41086a22024200370300200342003703b80741888dc300410d200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a10052102024020032802a0032214417f460d002002450d00200342003703a003200341a0036a20022014410820144108491b10ce041a201441074d0d0220032903a0032107200210290b02402003418c026a280200450d00201a10290b200720045a0d0041b79bc400211a411a21140c030b200341a0036a200641880110cf041a200341023a00a804200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f00620034100360288022003420137038002200341a0036a20034180026a1032024020032d00a804220241024b0d00024002400240024020020e03000102000b4100211a0c020b4101211a0c010b4102211a0b2003201a3a009f08024002402003280284022003280288022202460d0020032802800221140c010b200241016a221a2002490d0620024101742214201a201a2014491b221a4100480d060240024020020d00201a102721140c010b2003280280022002201a102821140b2014450d032003201a36028402200320143602800220032d009f08211a20032802880221020b2003200241016a36028802201420026a201a3a00000b2003280284022102200341f0066a4110200328028002221a200328028802100302402002450d00201a10290b200341a0036a103d200610294100210841012115410121060c0b0b418f89c3004133104e000b201a4101102a000b2006103d200610294100210841012115410121060c110b200341003602a803200342013703a0032006200341a0036a103220032802a403211a20032802a803211420032802a003210220034180026a41186a2215420037030020034180026a41106a2216420037030020034180026a41086a2208420037030020034200370380022002201420034180026a1000200341e0006a41186a22142015290300370300200341e0006a41106a2016290300370300200341e0006a41086a200829030037030020032003290380023703600240201a450d00200210290b200341a0036a41186a2014290300370300200341a0036a41106a200341e0006a41106a290300370300200341a0036a41086a200341e0006a41086a290300370300200320032903603703a00320034180026a200341a0036a10c5030240200328028802221a450d00200329038002210442002107200341b8076a41086a22024200370300200342003703b80741888dc300410d200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f006200341003602a003200341f0066a4110200341a0036a10052102024020032802a0032214417f460d002002450d00200342003703a003200341a0036a20022014410820144108491b10ce041a201441074d0d0320032903a0032107200210290b02402003418c026a280200450d00201a10290b200720045a0d0041b79bc400211a411a21140c040b200341a0036a200641880110cf041a200341003a00a804200341b8076a41086a22024200370300200342003703b8074188d4c3004116200341b8076a1004200341f0066a41086a2002290300370300200320032903b8073703f00620034100360288022003420137038002200341a0036a20034180026a1032024020032d00a804220241024b0d00024002400240024020020e03000102000b4100211a0c020b4101211a0c010b4102211a0b2003201a3a009f08024002402003280284022003280288022202460d0020032802800221140c010b200241016a221a2002490d0220024101742214201a201a2014491b221a4100480d020240024020020d00201a102721140c010b2003280280022002201a102821140b2014450d042003201a36028402200320143602800220032d009f08211a20032802880221020b2003200241016a36028802201420026a201a3a00000b2003280284022102200341f0066a4110200328028002221a200328028802100302402002450d00201a10290b200341a0036a103d2006102941002106410121150c060b102b000b418f89c3004133104e000b201a4101102a000b2006103d200610294100210641012115410121080c0c0b2016200341c8056a41186a2903003703002008200341c8056a41106a290300370300200341a0036a41086a200341c8056a41086a290300370300200320032903c8053703a003200341013a00f80702400240411710272202450d004100211a2002410f6a41002900af9b44370000200241086a41002900a89b44370000200241002900a09b4437000020024117413710282202450d01200220032903a0033700172002412f6a200341a0036a41186a290300370000200241276a200341a0036a41106a2903003700002002411f6a200341a0036a41086a29030037000020034180026a41186a2206420037030020034180026a41106a2215420037030020034180026a41086a2216420037030020034200370380022002413720034180026a1000200341c0046a41186a2006290300370300200341c0046a41106a2015290300370300200341c0046a41086a201629030037030020032003290380023703c00441012115200341c0046a4120200341f8076a4101100320021029200a10ab032014103d0c090b41174101102a000b41374101102a000b201510294101210641002115410121080c0a0b410121080b410121164100211a0c0a0b41959bc400211a410b2114410121150c060b41d588c300211a412a2114410121150c050b2002201a4105746a22142003290340370000201441186a200341c0006a41186a290300370000201441106a2015290300370000201441086a200929030037000041012115200341a0036a41186a201a41016a360200200341b4036a2008360200200320073703a803200320043703a003200320163602bc03200320023602b003200a200341a0036a10c2030b4100211a0b4101210641012108410121160c050b41fb9ac400211a411a21142006450d0020021029410121150c010b410121150b41012106410121080b410121160c010b2006103d20061029410021164101211541012106410121080b0240024020012d0000417f6a2202410f4b0d00024002400240024020020e1000040404010402030404040405040505000b2016450d04200141046a2202280200103d200228020010290c040b2015450d03200141046a2202280200103d200228020010290c030b2006450d02200141046a2202280200103d200228020010290c020b2008450d01200141046a2202280200103d200228020010290c010b200241074b0d00024002400240024020020e080004040401040203000b200141046a2202280200103d200228020010290c030b200141046a2202280200103d200228020010290c020b200141046a2202280200103d200228020010290c010b200141046a2202280200103d200228020010290b200020143602042000201a360200200341a0086a24000bd75d02157f037e230041d0036b2203240002400240024002400240024002400240024002400240024002400240024002400240024020012d000022040e0500010d0302000b200341b4026a4101360200200342013702a402200341ccfdc4003602a00220034102360274200341c4fdc4003602702003200341f0006a3602b002200341a0026a41bce4c2001057000b200141086a2802002105200141046a2802002106024020022d000120022d000072450d0041ad88c300210741282108410021094101210a02402005450d00200610290b4101210b0c100b2001410c6a280200210c200341a0026a41086a22024200370300200342003703a00241d692c200411b200341a0026a1004200341f0006a41086a2002290300370300200320032903a002370370200341003602a002200341f0006a4110200341a0026a1005210202400240024020032802a0022207417f460d002002450d00200320073602fc01200320023602f801200341a0026a200341f8016a102d20032802a002220d450d02200341a8026a280200210a20032802a402210e2007450d01200210290c010b4101210d4100210a4100210e0b200d200a1094022006200c109402200d4100200a1b210920064100200c1b2108200d41206a200d200a1b2107200641206a2006200c1b21022006200c4105746a210f200d200a4105746a2110410021114100211241012113410021144100211541012116034002400240024002400240024002402009450d0003402008450d02024020092008460d0020092008412010d004220a0d040b410020072007201046220a1b2109410020022002200f46220b1b21082007200741206a200a1b21072002200241206a200b1b210220090d000b0b4100210920080d04201320112006200c10ba0102402012450d00201310290b02402015450d00201610290b02402005450d00200610290b4101210a200e450d16200d10290c160b200341a0026a41186a220a200941186a290000370300200341a0026a41106a220b200941106a290000370300200341a0026a41086a2217200941086a290000370300200320092900003703a002024020122011470d00201141016a22082011490d0a20114101742209200820082009491b221241ffffff3f712012470d0a201241057422084100480d0a0240024020110d002008102721130c010b201320114105742008102821130b2013450d020b201320114105746a220820032903a002370000200841186a200a290300370000200841106a200b290300370000200841086a20172903003700002007200741206a200720104622091b210a410021084100200720091b21090c040b200a417f4a0d02200341a0026a41186a220a200941186a290000370300200341a0026a41106a220b200941106a290000370300200341a0026a41086a2217200941086a290000370300200320092900003703a002024020122011470d00201141016a22092011490d0920114101742212200920092012491b221241ffffff3f712012470d09201241057422094100480d090240024020110d002009102721130c010b201320114105742009102821130b2013450d020b201320114105746a220920032903a002370000200941186a200a290300370000200941106a200b290300370000200941086a20172903003700002007200741206a200720104622091b210a4100200720091b21090c030b20084101102a000b20094101102a000b200341a0026a41186a220a200841186a290000370300200341a0026a41106a220b200841106a290000370300200341a0026a41086a2217200841086a290000370300200320082900003703a0020240024020152014470d00201441016a22082014490d0720144101742215200820082015491b221541ffffff3f712015470d07201541057422084100480d070240024020140d002008102721160c010b201620144105742008102821160b2016450d010b201620144105746a220820032903a002370000200841186a200a290300370000200841106a200b290300370000200841086a2017290300370000410020022002200f46220a1b2108201441016a21142002200241206a200a1b21020c020b20084101102a000b201141016a2111200a21070c000b0b418f89c3004133104e000b200141216a2d0000210e200141246a2802002105200341306a41186a200141196a290000370300200341306a41106a200141116a290000370300200341306a41086a200141096a290000370300200320012900013703302002411a6a2901002118200241196a2d0000210f200241186a2d00002110200241166a2f01002114200241156a2d00002111200241146a2d00002115200241126a2f01002116200241116a2d00002117200241106a2d000021122002410e6a2f010021132002410d6a2d00002106200241046a2d0000210d200241026a2f0100210c41d588c3002107412a21080240024020022d0000450d00410121094100210a4100210b0c010b410121094100210a4100210b20022d00014101470d002002410c6a2d0000210b2002410a6a2f0100210a200241096a2d00002108200241066a2f0100410874200241056a2d000072200241086a2d0000411874722107410021090b200a41ffff0371410874200841ff017172200b411874722108024020090d00200320183703682003200f3a0067200320103a0066200320143b0164200320113a0063200320153a0062200320163b0160200320173a005f200320123a005e200320133b015c200320063a005b20032008360057200320073600532003200d3a00522003200c3b0150200341a0026a41086a22024200370300200342003703a00241d692c200411b200341a0026a1004200341f0006a41086a2002290300370300200320032903a002370370200341003602a002200341f0006a4110200341a0026a10052102024002400240024020032802a0022207417f460d002002450d00200320073602fc01200320023602f801200341a0026a200341f8016a102d20032802a0022208450d02200341a8026a280200210920032802a402210a02402007450d00200210290b20082009200341d0006a10f90221020240200a450d00200810290b2002450d010c030b41014100200341d0006a10f9020d020b41d2e5c2002107411221080c020b418f89c3004133104e000b200341a0026a200341306a10f202024020032802a80222100d0041bfe5c2002107411321080c010b200341b8026a2802002111200341b4026a28020021144110210820032802ac02210b41e4e5c20021070240200520032802a0022217470d00200341bc026a280200210f20032802a40221122010200341a0026a41106a28020022154105746a2109201021024100210802400240024003400240200920026b41e0004b0d0020022009470d02410021160c040b200341d0006a2002460d0220082002200341d0006a412010d00422074100476a21082007450d02200241206a2207200341d0006a460d0220082007200341d0006a412010d00422074100476a21082007450d02200241c0006a2207200341d0006a460d0220082007200341d0006a412010d00422074100476a21082007450d02200241e0006a2207200341d0006a460d0220024180016a210220082007200341d0006a412010d00422074100476a210820070d000c020b0b201020154105746a21090340200341d0006a2002460d0120082002200341d0006a412010d00422074100476a21082007450d01410021162009200241206a2202470d000c020b0b410121160b2014200f4105746a210a201421024100210702400240024003400240200a20026b41e0004b0d002002200a470d02410021090c040b200341d0006a2002460d0220072002200341d0006a412010d00422094100476a21072009450d02200241206a2209200341d0006a460d0220072009200341d0006a412010d00422094100476a21072009450d02200241c0006a2209200341d0006a460d0220072009200341d0006a412010d00422094100476a21072009450d02200241e0006a2209200341d0006a460d0220024180016a210220072009200341d0006a412010d00422094100476a210720090d000c020b0b0340200341d0006a2002460d0120072002200341d0006a412010d00422094100476a21072009450d0141002109200a200241206a2202470d000c020b0b410121090b024002400240024002400240024002400240200e41ff01710d002009450d010c080b20160d07200341a0026a41186a2208200341d0006a41186a290300370300200341a0026a41106a220a200341d0006a41106a290300370300200341a0026a41086a2213200341d0006a41086a290300370300200320032903503703a0020240200b2015460d00200b21160c020b200b41016a2202200b490d0b200b4101742216200220022016491b221641ffffff3f712016470d0b201641057422024100480d0b02400240200b0d002002102721100c010b2010200b4105742002102821100b20100d0120024101102a000b200341a0026a41186a2209200341d0006a41186a290300370300200341a0026a41106a220a200341d0006a41106a290300370300200341a0026a41086a2213200341d0006a41086a290300370300200320032903503703a002024002402011200f460d00201121070c010b201141016a22022011490d0b20114101742207200220022007491b220741ffffff3f712007470d0b200741057422024100480d0b0240024020110d002002102721140c010b201420114105742002102821140b20140d0020024101102a000b2014200f4105746a220220032903a002370000200241186a2009290300370000200241106a200a290300370000200241086a2013290300370000200f41016a210f024002402016450d00201520084d0d0120102015417f6a22154105746a22022900002118200229000821192002290010211a201020084105746a220841186a200241186a2900003700002008201a37001020082019370008200820183700000b200b2116200721110c020b418ce6c200200820151037000b201020154105746a220220032903a002370000200241186a2008290300370000200241106a200a290300370000200241086a2013290300370000201541016a21152009450d00200f20074d0d012014200f417f6a220f4105746a22022900002118200229000821192002290010211a201420074105746a220741186a200241186a2900003700002007201a37001020072019370008200720183700000b200341c5026a2003290330370000200341ad026a200341d0006a41086a290300370000200341b5026a200341d0006a41106a290300370000200341bd026a200341d0006a41186a290300370000200341cd026a200341306a41086a290300370000200341d5026a200341306a41106a290300370000200341dd026a200341306a41186a290300370000200341013a00a402200341063a00a002200320032903503700a502200341ec026a200f360200200341e8026a2015360200200341e5026a200e3a000041b8d6c5004100200341a0026a108801200341a0026a41086a22024200370300200342003703a00241d692c200411b200341a0026a1004200341f0006a41086a2002290300370300200320032903a002370370200341003602a002200341f0006a4110200341a0026a1005210720032802a0022208417f460d022007450d02200320083602fc01200320073602f801200341a0026a200341f8016a102d20032802a002220a450d01200341a8026a280200210220032802a402210902402008450d00200710290b2009450d03200a10290c030b418ce6c2002007200f1037000b418f89c3004133104e000b410021020b024002400240024002400240024002400240024002400240201520124f22070d0041002002200f6b2208200820024b1b2012490d00200341bc026a200f360200200341a0026a41186a2011360200200341a0026a41106a2015360200200341ac026a2016360200200320143602b402200320103602a802200320123602a402200320173602a002411a10272202450d01200241186a41002f00cfce423b0000200241106a41002900c7ce42370000200241086a41002900bfce42370000200241002900b7ce423700002002411a413a10282202450d022002200329033037001a200241326a200341306a41186a2903003700002002412a6a200341306a41106a290300370000200241226a200341306a41086a290300370000200341f8016a41186a22074200370300200341f8016a41106a22084200370300200341f8016a41086a22094200370300200342003703f8012002413a200341f8016a1000200341a8036a41186a2007290300370300200341a8036a41106a2008290300370300200341a8036a41086a2009290300370300200320032903f8013703a803200341203602742003200341a8036a360270200341a0026a200341f0006a10db022002102902402016450d00201010290b20110d060c070b024020070d00200341ad026a200341386a290300370000200341b5026a200341c0006a290300370000200341bd026a200341c8006a290300370000200341033a00a402200341063a00a002200320032903303700a50241b8d6c5004100200341a0026a1088010c050b200341ad026a200341306a41086a290300370000200341b5026a200341306a41106a290300370000200341bd026a200341c8006a290300370000200341023a00a402200341063a00a002200320032903303700a50241b8d6c5004100200341a0026a108801411e10272207450d02200741166a4100290096e542370000200741106a4100290090e542370000200741086a4100290088e54237000020074100290080e5423700002007411e413e10282207450d032007200329033037001e200741366a200341306a41186a220b2903003700002007412e6a200341306a41106a220f290300370000200741266a200341306a41086a2215290300370000200341f8016a41186a22094200370300200341f8016a41106a220a4200370300200341f8016a41086a22084200370300200342003703f8012007413e200341f8016a1000200341a8036a41186a2009290300370300200341a8036a41106a200a290300370300200341a8036a41086a2008290300370300200320032903f8013703a803200341a0026a200341a8036a10fa02024020032802a00222094112470d00200710290c050b200341f0006a200341a0026a410472220a41840110ce041a20071029200320093602a002200a200341f0006a41840110ce041a20034184026a200236020020082012360200200341003a00fc01200341013a00f801200341286a200341a0026a200341f8016a10ad0220032802282102200341ad026a2015290300370000200341b5026a200f290300370000200341bd026a200b290300370000200341c5026a2002453a0000200341043a00a402200341063a00a002200320032903303700a50241b8d6c5004100200341a0026a1088010c040b411a4101102a000b413a4101102a000b411e4101102a000b413e4101102a000b411a10272202450d03200241186a41002f00cfce423b0000200241106a41002900c7ce42370000200241086a41002900bfce42370000200241002900b7ce423700002002411a413a10282202450d042002200329033037001a200241326a200341306a41186a2903003700002002412a6a200341306a41106a290300370000200241226a200341306a41086a290300370000200341f8016a41186a22074200370300200341f8016a41106a22084200370300200341f8016a41086a22094200370300200342003703f8012002413a200341f8016a1000200341a8036a41186a2007290300370300200341a8036a41106a2008290300370300200341a8036a41086a2009290300370300200320032903f8013703a803200341a8036a4120100c20021029200341a0026a41086a22024200370300200342003703a002419acec200411d200341a0026a1004200341f0006a41086a2002290300370300200320032903a002370370200341003602a002200341f0006a4110200341a0026a100521020240024020032802a0022207417f460d002002450d00200320073602fc01200320023602f801200341a0026a200341f8016a102d20032802a0022208450d0720032902a402211802402007450d00200210290b200320183702fc01200320083602f8010c010b2003410036028002200342013703f8010b200341f8016a200341306a1036200341a0026a41086a22024200370300200342003703a002419acec200411d200341a0026a1004200341f0006a41086a2002290300370300200320032903a002370370200341003602a802200342013703a00220032802f8012117200320032802800222023602a803200341a8036a200341a0026a10300240024020020d0020032802a802210720032802a402210a20032802a002210b0c010b2002410574210f410020032802a80222076b210920032802a002210b20032802a402210a2017210203400240200a20096a411f4b0d00200741206a22082007490d0d200a4101742215200820082015491b22084100480d0d02400240200a0d0020081027210b0c010b200b200a20081028210b0b200b450d052008210a0b200b20076a22082002290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200941606a2109200741206a2107200241206a2102200f41606a220f0d000b2003200a3602a402200320073602a8022003200b3602a0020b200341f0006a4110200b200710030240200a450d00200b10290b024020032802fc01450d00201710290b02402016450d00201010290b2011450d010b201410290b410021070c060b20084101102a000b411a4101102a000b413a4101102a000b418f89c3004133104e000b41f4e5c2002107411621080b0240200b450d00201010290b2011450d00201410290b4101210a4101210b410121090c0e0b200141086a2802002109200141046a280200210e2002411a6a2901002118200241196a2d00002110200241186a2d00002114200241166a2f01002111200241156a2d00002115200241146a2d00002116200241126a2f01002117200241116a2d00002112200241106a2d000021132002410e6a2f010021062002410d6a2d0000210d200241046a2d0000210c200241026a2f01002105412a210841d588c30021070240024020022d0000450d004101210a4100210b4100210f0c010b4101210a4100210b4100210f20022d00014101470d002002410c6a2d0000210b2002410a6a2f0100210f200241096a2d00002108200241066a2f0100410874200241056a2d000072200241086a2d00004118747221074100210a0b200f41ffff0371410874200b41187472200841ff0171722108200a0d0820032018370348200320103a0047200320143a0046200320113b0144200320153a0043200320163a0042200320173b0140200320123a003f200320133a003e200320063b013c2003200d3a003b20032008360037200320073600332003200c3a0032200320053b0130200341a0026a41086a22024200370300200342003703a00241d692c200411b200341a0026a1004200341f0006a41086a2002290300370300200320032903a002370370200341003602a002200341f0006a4110200341a0026a10052102024002400240024020032802a0022207417f460d002002450d00200320073602fc01200320023602f801200341a0026a200341f8016a102d20032802a0022208450d02200341a8026a280200210a20032802a402210b02402007450d00200210290b2008200a200341306a10f90221020240200b450d00200810290b2002450d010c030b41014100200341306a10f9020d020b41cce4c2002107411521080c0a0b418f89c3004133104e000b200341003602a802200342013703a0022009200341a0026a103220032802a402210720032802a802210820032802a0022102200341f8016a41186a220a4200370300200341f8016a41106a220b4200370300200341f8016a41086a220f4200370300200342003703f80120022008200341f8016a1000200341d0006a41186a2208200a290300370300200341d0006a41106a220a200b290300370300200341d0006a41086a220b200f290300370300200320032903f80137035002402007450d00200210290b200341a0026a41186a2008290300370300200341a0026a41106a200a290300370300200341a0026a41086a200b290300370300200320032903503703a002024002400240024002400240024002400240411e10272202450d00200241166a4100290096e542370000200241106a4100290090e542370000200241086a4100290088e54237000020024100290080e5423700002002411e413e10282202450d01200220032903a00237001e200241366a200341a0026a41186a2903003700002002412e6a200341a0026a41106a290300370000200241266a200341a0026a41086a290300370000200341f8016a41186a22074200370300200341f8016a41106a22084200370300200341f8016a41086a220a4200370300200342003703f8012002413e200341f8016a1000200341a8036a41186a2007290300370300200341a8036a41106a2008290300370300200341a8036a41086a200a290300370300200320032903f8013703a803200341a8036a412041b8d6c50041004100100b2107200210292007417f470d020240200e4102490d00200341206a419ee5c200412110b5012003280224211520032802202116200341186a419ee5c200412110b50120032802182107200328021c2108200341a0026a41086a22024200370300200342003703a002419ee5c2004121200341a0026a1004200341f0006a41086a220a2002290300370300200320032903a0023703702003200841016a410120071b3602a002200341f0006a4110200341a0026a4104100320024200370300200342003703a002419acec200411d200341a0026a1004200a2002290300370300200320032903a002370370200341003602a002200341f0006a4110200341a0026a1005210220032802a0022207417f460d052002450d05200320073602fc01200320023602f801200341a0026a200341f8016a102d20032802a0022211450d0420032902a402211802402007450d00200210290b200341a0026a41186a200341d0006a41186a290300370300200341a0026a41106a200341d0006a41106a290300370300200341a0026a41086a200341d0006a41086a290300370300200320032903503703a002200341a0026a21072018a72018422088a72202470d080c070b200341a0026a41086a22024200370300200342003703a00241d692c200411b200341a0026a1004200341f0006a41086a2002290300370300200320032903a00237037041002102200341003602a002200341f0006a4110200341a0026a10052108024020032802a0022207417f460d00200320073602fc01200320083602f801200341a0026a200341f8016a102d20032802a002220b450d06200341a8026a280200210220032802a402210a02402007450d00200810290b200a450d00200b10290b200341a0026a200941880110ce041a200341fc006a2002360200200341f0006a41086a4101360200200341003a0074200341013a0070200341106a200341a0026a200341f0006a10ad0220032802102102200341ad026a200341d0006a41086a290300370000200341b5026a200341e0006a290300370000200341bd026a200341e8006a290300370000200341c5026a2002453a0000200341043a00a402200341063a00a002200320032903503700a502200341a0026a21020c080b411e4101102a000b413e4101102a000b41e1e4c2002107411f21080c0e0b418f89c3004133104e000b200341a0026a41186a200341d0006a41186a290300370300200341a0026a41106a200341d0006a41106a290300370300200341a0026a41086a200341d0006a41086a290300370300200320032903503703a002420021184101211141002102200341a0026a21070c010b418f89c3004133104e000b200241016a22082002490d022002410174220a20082008200a491b220841ffffff3f712008470d022008410574220a4100480d020240024020020d00200a102721110c010b20112002410574200a102821110b2011450d032018422088a721022008ad21180b20112002410574220b6a22082007290000370000200841186a200741186a290000370000200841106a200741106a290000370000200841086a200741086a290000370000200341a0026a41086a22074200370300200342003703a002419acec200411d200341a0026a1004200341f0006a41086a2007290300370300200320032903a002370370200341003602a802200342013703a0022003200241016a22073602f801200341f8016a200341a0026a103002400240200720024f0d0020032802a802210720032802a402210b20032802a002210f0c010b410020032802a80222076b210a200b41206a211020032802a002210f20032802a402210b2011210203400240200b200a6a411f4b0d00200741206a22082007490d04200b4101742214200820082014491b22084100480d0402400240200b0d0020081027210f0c010b200f200b20081028210f0b200f450d0b2008210b0b200f20076a22082002290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200a41606a210a200741206a2107200241206a2102201041606a22100d000b2003200b3602a402200320073602a8022003200f3602a0020b200341f0006a4110200f200710030240200b450d00200f10290b02402018a7450d00201110290b200341f0006a41186a200341d0006a41186a290300370300200341f0006a41106a200341d0006a41106a290300370300200341f0006a41086a200341d0006a41086a29030037030020032003290350370370200341a0026a200941880110ce041a411e10272202450d03200241166a4100290096e542370000200241106a4100290090e542370000200241086a4100290088e54237000020024100290080e5423700002002411e413e10282202450d042002200329037037001e200241366a200341f0006a41186a2903003700002002412e6a200341f0006a41106a290300370000200241266a200341f0006a41086a290300370000200341f8016a41186a22074200370300200341f8016a41106a22084200370300200341f8016a41086a220a4200370300200342003703f8012002413e200341f8016a1000200341a8036a41186a2007290300370300200341a8036a41106a2008290300370300200341a8036a41086a200a290300370300200320032903f8013703a8032003410036028002200342013703f801200341a0026a200341f8016a103220032802fc012107200341a8036a412020032802f8012208200328028002100302402007450d00200810290b20021029200341a0026a103d412010272202450d0520022003290330370000200241186a200341306a41186a290300370000200241106a200341306a41106a290300370000200241086a200341306a41086a290300370000200341f0006a41186a200341d0006a41186a290300370300200341f0006a41106a200341d0006a41106a290300370300200341f0006a41086a200341d0006a41086a29030037030020032003290350370370200341bc026a4100360200200341ac026a428180808010370200200342013702b402200320023602a8022003200e3602a40220032015410020161b22083602a002411a10272207450d06200741186a41002f00cfce423b0000200741106a41002900c7ce42370000200741086a41002900bfce42370000200741002900b7ce423700002007411a413a10282207450d072007200329037037001a200741326a200341f0006a41186a2903003700002007412a6a200341f0006a41106a290300370000200741226a200341f0006a41086a290300370000200341f8016a41186a220a4200370300200341f8016a41106a220b4200370300200341f8016a41086a220f4200370300200342003703f8012007413a200341f8016a1000200341a8036a41186a200a290300370300200341a8036a41106a200b290300370300200341a8036a41086a200f290300370300200320032903f8013703a803200341203602fc012003200341a8036a3602f801200341a0026a200341f8016a10db022007102920021029200341ad026a200341306a41086a290300370000200341b5026a200341306a41106a290300370000200341bd026a200341306a41186a290300370000200341c5026a2003290350370000200341cd026a200341d0006a41086a290300370000200341d5026a200341d0006a41106a290300370000200341dd026a200341d0006a41186a290300370000200341ec026a200e360200200341e8026a2008360200200341003a00a402200341063a00a002200320032903303700a502200341a0026a21020b4100210b41b8d6c50041002002108801200910294101210a0c0a0b102b000b200a4101102a000b411e4101102a000b413e4101102a000b41204101102a000b411a4101102a000b413a4101102a000b20084101102a000b2009103d200910294100210b4101210a410121090c040b200141046a280200210941d588c3002107412a210820022d00000d0120022d00014101470d01200241196a2d00002107200241186a2d00002108200241166a2f0100210a200241156a2d0000210b200241146a2d0000210f200241126a2f01002110200241116a2d00002114200241106a2d000021112002410e6a2f010021152002410d6a2d000021162002410c6a2d000021172002410a6a2f01002112200241096a2d00002113200241086a2d00002106200241066a2f0100210d200241056a2d0000210c200241046a2d00002105200241026a2f0100210e20032002411a6a290100370368200320073a0067200320083a00662003200a3b01642003200b3a00632003200f3a0062200320103b0160200320143a005f200320113a005e200320153b015c200320163a005b200320053a00522003200e3b0150200320132012410874201741187472723600572003200c200d41087472200641187472360053200341a0026a41086a22024200370300200342003703a00241d692c200411b200341a0026a1004200341f0006a41086a2002290300370300200320032903a002370370200341003602a002200341f0006a4110200341a0026a10052107024002400240024020032802a0022202417f460d00200320023602fc01200320073602f801200341a0026a200341f8016a102d20032802a0022208450d02200341a8026a280200210a20032802a402210b02402002450d00200710290b2008200a200341d0006a10f90221020240200b450d00200810290b2002450d010c030b41014100200341d0006a10f9020d020b41cce4c2002107411521080c030b418f89c3004133104e000b4100210a200341003602a802200342013703a0022009200341a0026a103220032802a402210720032802a802210820032802a0022102200341f8016a41186a220b4200370300200341f8016a41106a220f4200370300200341f8016a41086a22104200370300200342003703f80120022008200341f8016a1000200341a8036a41186a2208200b290300370300200341a8036a41106a2214200f290300370300200341a8036a41086a220f2010290300370300200320032903f8013703a80302402007450d00200210290b200341a0026a200941880110ce041a200341f0006a410d6a200341d0006a41086a290300370000200341f0006a41156a200341d0006a41106a290300370000200341f0006a411d6a200341d0006a41186a2903003700004101210b200341013a007420032003290350370075200341013a0070200341086a200341a0026a200341f0006a10ad0220032802082102200341a0026a410d6a200f290300370000200341a0026a41156a2014290300370000200341a0026a411d6a2008290300370000200341c5026a2002453a0000200341053a00a402200341063a00a002200320032903a8033700a50241b8d6c5004100200341a0026a108801200910290b41012109410021070c020b2009103d200910294101210b4100210a410121090c010b410021094101210b410021070b02402004410771417f6a220241024b0d0002400240024020020e03000102000b2009450d02200141086a280200450d02200141046a28020010290c020b200a450d01200141046a2802002202103d200210290c010b200b450d00200141086a2802002202103d200210290b2000200836020420002007360200200341d0036a24000b9a6f03197f077e017f23002203210420034180046b4160712205240002400240024002400240024002400240024002400240024002400240024002400240024020012d000022060e0500010d0302000b200541d4026a4101360200200542013702c402200541ccfdc4003602c0022005410236028401200541c4fdc40036028001200520054180016a3602d002200541c0026a41bce4c2001057000b200141086a2802002107200141046a2802002108024020022d000120022d000072450d0041ad88c3002103412821094100210a4101210b02402007450d00200810290b4101210c0c100b2001410c6a280200210d20054180016a41086a22024200370300200542003703800141f192c200411b20054180016a1004200541c0026a41086a200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a100521020240024002402005280280012203417f460d002002450d002005200336029c02200520023602980220054180016a20054198026a102d200528028001220e450d0220054188016a280200210b200528028401210f2003450d01200210290c010b4101210e4100210b4100210f0b200e200b1094022008200d109402200e4100200b1b210a20084100200d1b2109200e41206a200e200b1b2103200841206a2008200d1b21022008200d4105746a2110200e200b4105746a211141002112410021134100211441012115410021164100211741012118034002400240024002400240024002400240024002400240024002400240200a450d0003402009450d020240200a2009460d00200a2009412010d004220b0d040b410020032003201146220b1b210a410020022002201046220c1b21092003200341206a200b1b21032002200241206a200c1b2102200a0d000b0b4100210a20090d0b201341ffffff3f712013470d0220134105742202417f4c0d020240024020020d00410121090c010b200210272209450d040b410021034100210202402013450d00416020156b210a2009210220152103034020022003290000370000200241186a200341186a290000370000200241106a200341106a290000370000200241086a200341086a290000370000200241206a2102200341206a2103201241606a22120d000b201520134105746a200a6a41057641016a2102201321030b20052002360248200520033602442005200936024020092002410041202002676b10e00120054180016a41086a22024200370300200542003703800141e8e6c200411d20054180016a1004200541c0026a41086a200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a10052102024002402005280280012209417f460d002002450d002005200936029c02200520023602980220054180016a20054198026a102d2005280280012219450d0620054188016a2802002103200528028401211a2009450d01200210290c010b41012119410021034100211a0b024020034105742210450d00200541c0026a4114722112200541c0026a410872211b201921030340200541e0006a41186a2211200341186a290000370300200541e0006a41106a2216200341106a290000370300200541e0006a41086a2213200341086a2900003703002005200329000037036020054180016a200541e0006a10fb02200541003602c802200529039801211c200520052903d802221d37039801200529039001211e200520052903d002221f370390012005290380012120200520052903c002370380012005290388012121200520052903c802222237038801201f422088a7210c2022422088a7210a201da7210b2022a7210902402021a72202450d00200520203703c002200520213703c8022005201e3703d0022005201c3703d80220052002201ea74105746a3602a402200520023602a00220052021422088a736029c0220052002360298022005200541c0006a3602a802200541d8036a20054198026a104b201b41086a200541d8036a41086a2223280200360200201b20052903d8033702002005201e422088a72202201c422088a74105746a3602a402200520023602a0022005201ca736029c0220052002360298022005200541c0006a3602a802200541d8036a20054198026a104b201241086a2023280200360200201220052903d80337020020052903c802212120052903c002211e20052903d802212220052903d002211c02402009450d000240200a450d00200910290b200b450d00200c10290b2005201e3703800120052021370388012021422088a7210a2005201c37039001201c422088a7210c20052022370398012021a721092022a7210b0b411a102721020240024020090d002002450d09200241186a41002f009de7423b0000200241106a4100290095e742370000200241086a410029008de74237000020024100290085e7423700002002411a413a10282202450d0a2002200529036037001a200241326a20112903003700002002412a6a2016290300370000200241226a201329030037000020054198026a41186a2209420037030020054198026a41106a220a420037030020054198026a41086a220b420037030020054200370398022002413a20054198026a1000200541d8036a41186a2009290300370300200541d8036a41106a200a290300370300200541d8036a41086a200b29030037030020052005290398023703d803200541d8036a4120100c200210290c010b2002450d0a200241186a41002f009de7423b0000200241106a4100290095e742370000200241086a410029008de74237000020024100290085e7423700002002411a413a10282202450d0b2002200529036037001a200241326a20112903003700002002412a6a2016290300370000200241226a201329030037000020054198026a41186a2211420037030020054198026a41106a2216420037030020054198026a41086a2213420037030020054200370398022002413a20054198026a1000200541d8036a41186a2011290300370300200541d8036a41106a2016290300370300200541d8036a41086a201329030037030020052005290398023703d803200541203602c4022005200541d8036a3602c00220054180016a200541c0026a10db02200210290240200a450d00200910290b200b450d00200c10290b200341206a2103201041606a22100d000b0b0240201a450d00201910290b200541003602c802200542013703c0022005200d3602800120054180016a200541c0026a10300240024002400240200d0d0020052802c802210320052802c402210b20052802c002210c0c010b200d4105742110410020052802c80222036b210a20052802c002210c20052802c402210b2008210203400240200b200a6a411f4b0d00200341206a22092003490d16200b4101742211200920092011491b22094100480d1602400240200b0d0020091027210c0c010b200c200b20091028210c0b200c450d032009210b0b200c20036a22092002290000370000200941186a200241186a290000370000200941106a200241106a290000370000200941086a200241086a290000370000200a41606a210a200341206a2103200241206a2102201041606a22100d000b2005200b3602c402200520033602c8022005200c3602c0020b20054180016a41086a22024200370300200542003703800141f192c200411b20054180016a1004200541c0026a41086a200229030037030020052005290380013703c002200541c0026a4110200c200310030240200b450d00200c10290b02402005280244450d00200528024010290b02402014450d00201510290b02402017450d00201810290b02402007450d00200810290b4101210b200f0d010c1f0b20094101102a000b200e10290c1d0b200541c0026a41186a220b200a41186a290000370300200541c0026a41106a220c200a41106a290000370300200541c0026a41086a221b200a41086a2900003703002005200a2900003703c002024020142013470d00201341016a22092013490d112013410174220a20092009200a491b221441ffffff3f712014470d11201441057422094100480d110240024020130d002009102721150c010b201520134105742009102821150b2015450d090b201520134105746a220920052903c002370000200941186a200b290300370000200941106a200c290300370000200941086a201b2903003700002003200341206a2003201146220a1b210b4100210941002003200a1b210a0c0b0b200b417f4a0d09200541c0026a41186a220b200a41186a290000370300200541c0026a41106a220c200a41106a290000370300200541c0026a41086a221b200a41086a2900003703002005200a2900003703c002024020142013470d00201341016a220a2013490d1020134101742214200a200a2014491b221441ffffff3f712014470d102014410574220a4100480d100240024020130d00200a102721150c010b20152013410574200a102821150b2015450d090b201520134105746a220a20052903c002370000200a41186a200b290300370000200a41106a200c290300370000200a41086a201b2903003700002003200341206a2003201146220a1b210b41002003200a1b210a0c0a0b1039000b20024101102a000b418f89c3004133104e000b411a4101102a000b413a4101102a000b411a4101102a000b413a4101102a000b20094101102a000b200a4101102a000b200541c0026a41186a220b200941186a290000370300200541c0026a41106a220c200941106a290000370300200541c0026a41086a221b200941086a290000370300200520092900003703c0020240024020172016470d00201641016a22092016490d0720164101742217200920092017491b221741ffffff3f712017470d07201741057422094100480d070240024020160d002009102721180c010b201820164105742009102821180b2018450d010b201820164105746a220920052903c002370000200941186a200b290300370000200941106a200c290300370000200941086a201b290300370000410020022002201046220b1b2109201641016a21162002200241206a200b1b21020c020b20094101102a000b201241206a2112201341016a2113200b21030c000b0b418f89c3004133104e000b200141216a2d0000210e200141246a280200210d200541c0006a41186a200141196a290000370300200541c0006a41106a200141116a290000370300200541c0006a41086a200141096a290000370300200520012900013703402002411a6a2901002121200241196a2d00002110200241186a2d00002111200241166a2f01002116200241156a2d00002113200241146a2d00002117200241126a2f01002118200241116a2d00002112200241106a2d0000211b2002410e6a2f010021142002410d6a2d00002115200241046a2d00002123200241026a2f0100210841d588c3002103412a21090240024020022d0000450d004101210a4100210b4100210c0c010b4101210a4100210b4100210c20022d00014101470d002002410c6a2d0000210c2002410a6a2f0100210b200241096a2d00002109200241066a2f0100410874200241056a2d000072200241086a2d00004118747221034100210a0b200b41ffff0371410874200941ff017172200c4118747221090240200a0d0020052021370378200520103a0077200520113a0076200520163b0174200520133a0073200520173a0072200520183b0170200520123a006f2005201b3a006e200520143b016c200520153a006b2005200936006720052003360063200520233a0062200520083b016020054180016a41086a22024200370300200542003703800141f192c200411b20054180016a1004200541c0026a41086a200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a1005210202400240024002402005280280012203417f460d002002450d002005200336029c02200520023602980220054180016a20054198026a102d2005280280012209450d0220054188016a280200210a200528028401210b02402003450d00200210290b2009200a200541e0006a10f90221020240200b450d00200910290b2002450d010c030b41014100200541e0006a10f9020d020b41d2e5c2002103411221090c020b418f89c3004133104e000b200541c0026a200541c0006a10fb02024020052802c80222110d0041bfe5c2002103411321090c010b200541d8026a2802002113200541d4026a28020021164110210920052802cc02210c41e4e5c20021030240200d20052802c0022212470d00200541dc026a280200211020052802c402211b2011200541c0026a41106a28020022174105746a210a201121024100210902400240024003400240200a20026b41e0004b0d002002200a470d02410021180c040b200541e0006a2002460d0220092002200541e0006a412010d00422034100476a21092003450d02200241206a2203200541e0006a460d0220092003200541e0006a412010d00422034100476a21092003450d02200241c0006a2203200541e0006a460d0220092003200541e0006a412010d00422034100476a21092003450d02200241e0006a2203200541e0006a460d0220024180016a210220092003200541e0006a412010d00422034100476a210920030d000c020b0b201120174105746a210a0340200541e0006a2002460d0120092002200541e0006a412010d00422034100476a21092003450d0141002118200a200241206a2202470d000c020b0b410121180b201620104105746a210b201621024100210302400240024003400240200b20026b41e0004b0d002002200b470d024100210a0c040b200541e0006a2002460d0220032002200541e0006a412010d004220a4100476a2103200a450d02200241206a220a200541e0006a460d022003200a200541e0006a412010d004220a4100476a2103200a450d02200241c0006a220a200541e0006a460d022003200a200541e0006a412010d004220a4100476a2103200a450d02200241e0006a220a200541e0006a460d0220024180016a21022003200a200541e0006a412010d004220a4100476a2103200a0d000c020b0b0340200541e0006a2002460d0120032002200541e0006a412010d004220a4100476a2103200a450d014100210a200b200241206a2202470d000c020b0b4101210a0b024002400240024002400240024002400240200e41ff01710d00200a450d010c080b20180d07200541c0026a41186a2209200541e0006a41186a290300370300200541c0026a41106a220b200541e0006a41106a290300370300200541c0026a41086a2214200541e0006a41086a290300370300200520052903603703c0020240200c2017460d00200c21180c020b200c41016a2202200c490d0b200c4101742218200220022018491b221841ffffff3f712018470d0b201841057422024100480d0b02400240200c0d002002102721110c010b2011200c4105742002102821110b20110d0120024101102a000b200541c0026a41186a220a200541e0006a41186a290300370300200541c0026a41106a220b200541e0006a41106a290300370300200541c0026a41086a2214200541e0006a41086a290300370300200520052903603703c0020240024020132010460d00201321030c010b201341016a22022013490d0b20134101742203200220022003491b220341ffffff3f712003470d0b200341057422024100480d0b0240024020130d002002102721160c010b201620134105742002102821160b20160d0020024101102a000b201620104105746a220220052903c002370000200241186a200a290300370000200241106a200b290300370000200241086a2014290300370000201041016a2110024002402018450d00201720094d0d0120112017417f6a22174105746a22022900002121200229000821222002290010211c201120094105746a220941186a200241186a2900003700002009201c37001020092022370008200920213700000b200c2118200321130c020b418ce6c200200920171037000b201120174105746a220220052903c002370000200241186a2009290300370000200241106a200b290300370000200241086a2014290300370000201741016a2117200a450d00201020034d0d0120162010417f6a22104105746a22022900002121200229000821222002290010211c201620034105746a220341186a200241186a2900003700002003201c37001020032022370008200320213700000b200541e5026a2005290340370000200541cd026a200541e0006a41086a290300370000200541d5026a200541e0006a41106a290300370000200541dd026a200541e0006a41186a290300370000200541ed026a200541c0006a41086a290300370000200541f5026a200541c0006a41106a290300370000200541fd026a200541c0006a41186a290300370000200541013a00c402200541073a00c002200520052903603700c5022005418c036a201036020020054188036a201736020020054185036a200e3a000041b8d6c5004100200541c0026a10880120054180016a41086a22024200370300200542003703800141f192c200411b20054180016a1004200541c0026a41086a200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a100521032005280280012209417f460d022003450d022005200936029c02200520033602980220054180016a20054198026a102d200528028001220b450d0120054188016a2802002102200528028401210a02402009450d00200310290b200a450d03200b10290c030b418ce6c200200320101037000b418f89c3004133104e000b410021020b0240024002400240024002400240024002400240024002402017201b4f22030d004100200220106b2209200920024b1b201b490d00200541dc026a2010360200200541c0026a41186a2013360200200541c0026a41106a2017360200200541cc026a2018360200200520163602d402200520113602c8022005201b3602c402200520123602c002411a10272202450d01200241186a41002f009de7423b0000200241106a4100290095e742370000200241086a410029008de74237000020024100290085e7423700002002411a413a10282202450d022002200529034037001a200241326a200541c0006a41186a2903003700002002412a6a200541c0006a41106a290300370000200241226a200541c0006a41086a29030037000020054198026a41186a2203420037030020054198026a41106a2209420037030020054198026a41086a220a420037030020054200370398022002413a20054198026a1000200541d8036a41186a2003290300370300200541d8036a41106a2009290300370300200541d8036a41086a200a29030037030020052005290398023703d80320054120360284012005200541d8036a36028001200541c0026a20054180016a10db022002102902402018450d00201110290b20130d060c070b024020030d00200541cd026a200541c8006a290300370000200541d5026a200541d0006a290300370000200541dd026a200541d8006a290300370000200541033a00c402200541073a00c002200520052903403700c50241b8d6c5004100200541c0026a1088010c050b200541cd026a200541c0006a41086a290300370000200541d5026a200541c0006a41106a290300370000200541dd026a200541d8006a290300370000200541023a00c402200541073a00c002200520052903403700c50241b8d6c5004100200541c0026a108801411e10272203450d02200341166a41002900b5e742370000200341106a41002900afe742370000200341086a41002900a7e7423700002003410029009fe7423700002003411e413e10282203450d032003200529034037001e200341366a200541c0006a41186a220c2903003700002003412e6a200541c0006a41106a2210290300370000200341266a200541c0006a41086a221729030037000020054198026a41186a220a420037030020054198026a41106a220b420037030020054198026a41086a2209420037030020054200370398022003413e20054198026a1000200541d8036a41186a200a290300370300200541d8036a41106a200b290300370300200541d8036a41086a200929030037030020052005290398023703d803200541c0026a200541d8036a10fa02024020052802c002220a4112470d00200310290c050b20054180016a200541c0026a410472220b41840110ce041a200310292005200a3602c002200b20054180016a41840110ce041a200541a4026a20023602002009201b360200200541003a009c02200541023a009802200541386a200541c0026a20054198026a10ad0220052802382102200541cd026a2017290300370000200541d5026a2010290300370000200541dd026a200c290300370000200541e5026a2002453a0000200541043a00c402200541073a00c002200520052903403700c50241b8d6c5004100200541c0026a1088010c040b411a4101102a000b413a4101102a000b411e4101102a000b413e4101102a000b411a10272202450d03200241186a41002f009de7423b0000200241106a4100290095e742370000200241086a410029008de74237000020024100290085e7423700002002411a413a10282202450d042002200529034037001a200241326a200541c0006a41186a2903003700002002412a6a200541c0006a41106a290300370000200241226a200541c0006a41086a29030037000020054198026a41186a2203420037030020054198026a41106a2209420037030020054198026a41086a220a420037030020054200370398022002413a20054198026a1000200541d8036a41186a2003290300370300200541d8036a41106a2009290300370300200541d8036a41086a200a29030037030020052005290398023703d803200541d8036a4120100c2002102920054180016a41086a22024200370300200542003703800141e8e6c200411d20054180016a1004200541c0026a41086a200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a10052102024002402005280280012203417f460d002002450d002005200336029c02200520023602980220054180016a20054198026a102d2005280280012209450d07200529028401212102402003450d00200210290b2005202137029c0220052009360298020c010b200541003602a00220054201370398020b20054198026a200541c0006a103620054180016a41086a22024200370300200542003703800141e8e6c200411d20054180016a1004200541c0026a41086a200229030037030020052005290380013703c002200541003602880120054201370380012005280298022112200520052802a00222023602d803200541d8036a20054180016a10300240024020020d002005280288012103200528028401210b200528028001210c0c010b20024105742110410020052802880122036b210a200528028001210c200528028401210b2012210203400240200b200a6a411f4b0d00200341206a22092003490d0d200b4101742217200920092017491b22094100480d0d02400240200b0d0020091027210c0c010b200c200b20091028210c0b200c450d052009210b0b200c20036a22092002290000370000200941186a200241186a290000370000200941106a200241106a290000370000200941086a200241086a290000370000200a41606a210a200341206a2103200241206a2102201041606a22100d000b2005200b3602840120052003360288012005200c360280010b200541c0026a4110200c200310030240200b450d00200c10290b0240200528029c02450d00201210290b02402018450d00201110290b2013450d010b201610290b410021030c060b20094101102a000b411a4101102a000b413a4101102a000b418f89c3004133104e000b41f4e5c2002103411621090b0240200c450d00201110290b2013450d00201610290b4101210b4101210c4101210a0c0e0b200141086a280200210a200141046a280200210e2002411a6a2901002121200241196a2d00002111200241186a2d00002116200241166a2f01002113200241156a2d00002117200241146a2d00002118200241126a2f01002112200241116a2d0000211b200241106a2d000021142002410e6a2f010021152002410d6a2d00002123200241046a2d00002108200241026a2f0100210d41d588c3002103412a21090240024020022d0000450d004101210b4100210c410021100c010b4101210b4100210c4100211020022d00014101470d002002410c6a2d000021102002410a6a2f0100210c200241096a2d00002109200241066a2f0100410874200241056a2d000072200241086a2d00004118747221034100210b0b200c41ffff0371410874200941ff0171722010411874722109200b0d0820052021370358200520113a0057200520163a0056200520133b0154200520173a0053200520183a0052200520123b01502005201b3a004f200520143a004e200520153b014c200520233a004b2005200936004720052003360043200520083a00422005200d3b014020054180016a41086a22024200370300200542003703800141f192c200411b20054180016a1004200541c0026a41086a200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a1005210202400240024002402005280280012203417f460d002002450d002005200336029c02200520023602980220054180016a20054198026a102d2005280280012209450d0220054188016a280200210b200528028401210c02402003450d00200210290b2009200b200541c0006a10f90221020240200c450d00200910290b2002450d010c030b41014100200541c0006a10f9020d020b41cce4c2002103411521090c0a0b418f89c3004133104e000b200541003602c802200542013703c002200a200541c0026a103220052802c402210320052802c802210920052802c002210220054198026a41186a220b420037030020054198026a41106a220c420037030020054198026a41086a2210420037030020054200370398022002200920054198026a1000200541e0006a41186a2209200b290300370300200541e0006a41106a220b200c290300370300200541e0006a41086a220c2010290300370300200520052903980237036002402003450d00200210290b200541c0026a41186a2009290300370300200541c0026a41106a200b290300370300200541c0026a41086a200c290300370300200520052903603703c002024002400240024002400240024002400240411e10272202450d00200241166a41002900b5e742370000200241106a41002900afe742370000200241086a41002900a7e7423700002002410029009fe7423700002002411e413e10282202450d01200220052903c00237001e200241366a200541c0026a41186a2903003700002002412e6a200541c0026a41106a290300370000200241266a200541c0026a41086a29030037000020054198026a41186a2203420037030020054198026a41106a2209420037030020054198026a41086a220b420037030020054200370398022002413e20054198026a1000200541d8036a41186a2003290300370300200541d8036a41106a2009290300370300200541d8036a41086a200b29030037030020052005290398023703d803200541d8036a412041b8d6c50041004100100b2103200210292003417f470d020240200e4102490d00200541306a41bde7c200412110b5012005280234211720052802302118200541286a41bde7c200412110b50120052802282103200528022c210920054180016a41086a22024200370300200542003703800141bde7c200412120054180016a1004200541c0026a41086a220b200229030037030020052005290380013703c0022005200941016a410120031b36028001200541c0026a411020054180016a4104100320024200370300200542003703800141e8e6c200411d20054180016a1004200b200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a100521022005280280012203417f460d052002450d052005200336029c02200520023602980220054180016a20054198026a102d2005280280012213450d04200529028401212102402003450d00200210290b200541c0026a41186a200541e0006a41186a290300370300200541c0026a41106a200541e0006a41106a290300370300200541c0026a41086a200541e0006a41086a290300370300200520052903603703c002200541c0026a21032021a72021422088a72202470d080c070b20054180016a41086a22024200370300200542003703800141f192c200411b20054180016a1004200541c0026a41086a200229030037030020052005290380013703c002410021022005410036028001200541c0026a411020054180016a1005210902402005280280012203417f460d002005200336029c02200520093602980220054180016a20054198026a102d200528028001220c450d0620054188016a2802002102200528028401210b02402003450d00200910290b200b450d00200c10290b200541c0026a200a41880110ce041a2005418c016a200236020020054180016a41086a4101360200200541003a008401200541023a008001200541206a200541c0026a20054180016a10ad0220052802202102200541cd026a200541e0006a41086a290300370000200541d5026a200541f0006a290300370000200541dd026a200541f8006a290300370000200541e5026a2002453a0000200541043a00c402200541073a00c002200520052903603700c502200541c0026a21020c080b411e4101102a000b413e4101102a000b41e1e4c2002103411f21090c0e0b418f89c3004133104e000b200541c0026a41186a200541e0006a41186a290300370300200541c0026a41106a200541e0006a41106a290300370300200541c0026a41086a200541e0006a41086a290300370300200520052903603703c002420021214101211341002102200541c0026a21030c010b418f89c3004133104e000b200241016a22092002490d022002410174220b20092009200b491b220941ffffff3f712009470d022009410574220b4100480d020240024020020d00200b102721130c010b20132002410574200b102821130b2013450d032021422088a721022009ad21210b20132002410574220c6a22092003290000370000200941186a200341186a290000370000200941106a200341106a290000370000200941086a200341086a29000037000020054180016a41086a22034200370300200542003703800141e8e6c200411d20054180016a1004200541c0026a41086a200329030037030020052005290380013703c002200541003602880120054201370380012005200241016a22033602980220054198026a20054180016a103002400240200320024f0d002005280288012103200528028401210c20052802800121100c010b410020052802880122036b210b200c41206a21112005280280012110200528028401210c2013210203400240200c200b6a411f4b0d00200341206a22092003490d04200c4101742216200920092016491b22094100480d0402400240200c0d002009102721100c010b2010200c2009102821100b2010450d0b2009210c0b201020036a22092002290000370000200941186a200241186a290000370000200941106a200241106a290000370000200941086a200241086a290000370000200b41606a210b200341206a2103200241206a2102201141606a22110d000b2005200c36028401200520033602880120052010360280010b200541c0026a41102010200310030240200c450d00201010290b02402021a7450d00201310290b20054180016a41186a200541e0006a41186a29030037030020054180016a41106a200541e0006a41106a29030037030020054180016a41086a200541e0006a41086a2903003703002005200529036037038001200541c0026a200a41880110ce041a411e10272202450d03200241166a41002900b5e742370000200241106a41002900afe742370000200241086a41002900a7e7423700002002410029009fe7423700002002411e413e10282202450d04200220052903800137001e200241366a20054180016a41186a2903003700002002412e6a20054180016a41106a290300370000200241266a20054180016a41086a29030037000020054198026a41186a2203420037030020054198026a41106a2209420037030020054198026a41086a220b420037030020054200370398022002413e20054198026a1000200541d8036a41186a2003290300370300200541d8036a41106a2009290300370300200541d8036a41086a200b29030037030020052005290398023703d803200541003602a0022005420137039802200541c0026a20054198026a1032200528029c022103200541d8036a4120200528029802220920052802a002100302402003450d00200910290b20021029200541c0026a103d412010272202450d0520022005290340370000200241186a200541c0006a41186a290300370000200241106a200541c0006a41106a290300370000200241086a200541c0006a41086a29030037000020054180016a41186a200541e0006a41186a29030037030020054180016a41106a200541e0006a41106a29030037030020054180016a41086a200541e0006a41086a2903003703002005200529036037038001200541dc026a4100360200200541cc026a428180808010370200200542013702d402200520023602c8022005200e3602c40220052017410020181b22093602c002411a10272203450d06200341186a41002f009de7423b0000200341106a4100290095e742370000200341086a410029008de74237000020034100290085e7423700002003411a413a10282203450d07200320052903800137001a200341326a20054180016a41186a2903003700002003412a6a20054180016a41106a290300370000200341226a20054180016a41086a29030037000020054198026a41186a220b420037030020054198026a41106a220c420037030020054198026a41086a2210420037030020054200370398022003413a20054198026a1000200541d8036a41186a200b290300370300200541d8036a41106a200c290300370300200541d8036a41086a201029030037030020052005290398023703d8032005412036029c022005200541d8036a36029802200541c0026a20054198026a10db022003102920021029200541cd026a200541c0006a41086a290300370000200541d5026a200541c0006a41106a290300370000200541dd026a200541c0006a41186a290300370000200541e5026a2005290360370000200541ed026a200541e0006a41086a290300370000200541f5026a200541e0006a41106a290300370000200541fd026a200541e0006a41186a2903003700002005418c036a200e36020020054188036a2009360200200541003a00c402200541073a00c002200520052903403700c502200541c0026a21020b4100210c41b8d6c50041002002108801200a10294101210b0c0a0b102b000b200b4101102a000b411e4101102a000b413e4101102a000b41204101102a000b411a4101102a000b413a4101102a000b20094101102a000b200a103d200a10294100210c4101210b4101210a0c040b200141046a280200210a41d588c3002103412a210920022d00000d0120022d00014101470d01200241196a2d00002103200241186a2d00002109200241166a2f0100210b200241156a2d0000210c200241146a2d00002110200241126a2f01002111200241116a2d00002116200241106a2d000021132002410e6a2f010021172002410d6a2d000021182002410c6a2d000021122002410a6a2f0100211b200241096a2d00002114200241086a2d00002115200241066a2f01002123200241056a2d00002108200241046a2d0000210d200241026a2f0100210e20052002411a6a290100370378200520033a0077200520093a00762005200b3b01742005200c3a0073200520103a0072200520113b0170200520163a006f200520133a006e200520173b016c200520183a006b2005200d3a00622005200e3b016020052014201b410874201241187472723600672005200820234108747220154118747236006320054180016a41086a22024200370300200542003703800141f192c200411b20054180016a1004200541c0026a41086a200229030037030020052005290380013703c0022005410036028001200541c0026a411020054180016a1005210302400240024002402005280280012202417f460d002005200236029c02200520033602980220054180016a20054198026a102d2005280280012209450d0220054188016a280200210b200528028401210c02402002450d00200310290b2009200b200541e0006a10f90221020240200c450d00200910290b2002450d010c030b41014100200541e0006a10f9020d020b41cce4c2002103411521090c030b418f89c3004133104e000b4100210b200541003602c802200542013703c002200a200541c0026a103220052802c402210320052802c802210920052802c002210220054198026a41186a220c420037030020054198026a41106a2210420037030020054198026a41086a2211420037030020054200370398022002200920054198026a1000200541d8036a41186a2209200c290300370300200541d8036a41106a22162010290300370300200541d8036a41086a2210201129030037030020052005290398023703d80302402003450d00200210290b200541c0026a200a41880110ce041a20054180016a410d6a200541e0006a41086a29030037000020054180016a41156a200541e0006a41106a29030037000020054180016a411d6a200541e0006a41186a2903003700004101210c200541013a0084012005200529036037008501200541023a008001200541186a200541c0026a20054180016a10ad0220052802182102200541c0026a410d6a2010290300370000200541c0026a41156a2016290300370000200541c0026a411d6a2009290300370000200541e5026a2002453a0000200541053a00c402200541073a00c002200520052903d8033700c50241b8d6c5004100200541c0026a108801200a10290b4101210a410021030c020b200a103d200a10294101210c4100210b4101210a0c010b4100210a4101210c410021030b02402006410771417f6a220241024b0d0002400240024020020e03000102000b200a450d02200141086a280200450d02200141046a28020010290c020b200b450d01200141046a2802002202103d200210290c010b200c450d00200141086a2802002202103d200210290b2000200936020420002003360200200424000bc08c0108077f027e0e7f027e027f017e0d7f0b7e230041e00a6b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0700010203040506000b200341e4046a4101360200200342013702d404200341ccfdc4003602d004200341023602b409200341c4fdc4003602b0092003200341b0096a3602e004200341d0046a41ece1c2001057000b200141e0006a2802002104200341b0096a200141086a41d80010ce041a20034188086a41186a200141fc006a28020036020020034188086a41106a200141f4006a29020037030020034188086a41086a200141ec006a2902003703002003200141e4006a29020037038808024020022d000120022d000072450d0041ad88c3002105412821020c220b200341b8076a41086a22024200370300200342003703b80741f987c5004118200341b8076a100420034190046a41086a2002290300370300200320032903b8073703900441002102200341003602d00420034190046a4110200341d0046a10052106024020032802d0042205417f460d002003200536029c062003200636029806200341d0046a20034198066a10f10220032d00c0054102460d0620032802a80521022005450d00200610290b024020022004490d0041fce1c2002105413521020c220b200341dc046a2004360200200341d0046a41086a41033a00002003410b3a00d0044100210541b8d6c5004100200341d0046a108801200341d0046a200341b0096a41d80010ce041a200341b4056a20034188086a41086a290300370200200341bc056a20034188086a41106a290300370200200341c4056a20034188086a41186a280200360200200320043602a80520032003290388083702ac05200341b8076a41086a22024200370300200342003703b80741f987c5004118200341b8076a100420034190046a41086a2002290300370300200320032903b80737039004200341003602a0062003420137039806200341d0046a20034198066a109302200328029c06210220034190046a4110200328029806220420032802a00610032002450d20200410290c200b2001410c6a2802002107200141086a2802002108200141046a2802002109200141106a290300210a2002411a6a290100210b200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d00002115200241046a2d00002116200241026a2f01002117412a210441d588c30021050240024020022d0000450d004101210641002118410021190c010b41012106410021184100211920022d00014101470d002002410c6a2d000021182002410a6a2f01002119200241096a2d00002104200241066a2f0100410874200241056a2d000072200241086a2d0000411874722105410021060b201941ffff0371410874201841187472200441ff017172210220060d1e2003200b3703b0062003200c3a00af062003200d3a00ae062003200e3b01ac062003200f3a00ab06200320103a00aa06200320113b01a806200320123a00a706200320133a00a606200320143b01a406200320153a00a3062003200236009f062003200536009b06200320163a009a06200320173b019806200341b8076a41086a22024200370300200342003703b80741f987c5004118200341b8076a100420034190046a41086a2002290300370300200320032903b80737039004200341003602d00420034190046a4110200341d0046a1005210220032802d0042205417f460d062002450d06200320053602bc07200320023602b807200341d0046a200341b8076a10f10220032d00c00522044102460d0520034188086a200341d0046a41f00010ce041a2003200341d0046a41f4006a28000036009309200320032800c1053602900902402005450d00200210290b200341b0096a20034188086a41f00010ce041a200341b0096a41f4006a200328009309360000200320043a00a00a20032003280290093600a10a0c150b200141c0006a290300211a200141386a290300211b2002411a6a290100210b200241196a2d0000210d200241186a2d0000210f200241166a2f01002110200241156a2d00002111200241146a2d00002112200241126a2f01002113200241116a2d00002114200241106a2d000021152002410e6a2f010021162002410d6a2d00002117200241046a2d00002107200241026a2f0100211c200141306a280200211d2001412c6a2802002108200141286a280200210e2001411d6a290000211e2001411c6a2d0000211f2001411b6a2d00002120200141196a2f00002121200141186a2d00002122200141176a2d00002123200141156a2f00002124200141146a2d00002125200141136a2d00002126200141116a2f00002127200141106a2d000021282001410c6a2802002129200141086a2802002109200141076a2d0000212a200141056a2f0000212b200141046a2d0000210c200141c8006a290300210a412a210441d588c30021050240024020022d0000450d004101210641002118410021190c010b41012106410021184100211920022d00014101470d002002410c6a2d000021182002410a6a2f01002119200241096a2d00002104200241066a2f0100410874200241056a2d000072200241086a2d0000411874722105410021060b201941ffff0371410874201841187472200441ff017172210220060d130240200c41ff01714101470d00200341d0046a200941067610cc0120032802d00421060240024020032802d8042009413f7122044b0d00410021040c010b200620044105746a2204290018211e20042d0017211f20042d0016212020042f0014212120042d0013212220042d0012212320042f0010212420042d000f212520042d000e212620042f000c212720042d000b2128200428000721292004280003210920042d0002212a20042f0000212b410121040b024020032802d404450d00200610290b20040d004184efc2002105411521020c140b2003200b3703c8042003200d3a00c7042003200f3a00c604200320103b01c404200320113a00c304200320123a00c204200320133b01c004200320143a00bf04200320153a00be04200320163b01bc04200320173a00bb04200320023600b704200320053600b304200320073a00b2042003201c3b01b004200341e0016a41e887c500411110940102404280ade20420032903e8017d4280ade20420032802e0011b200a5a0d0041dbeac2002105411b21020c140b200341c8016a41b793c20041111086014200212c0240024020032903d001420120032802c80122021b220b200341d8016a290300420020021b222d8450450d004200212e0c010b200341a8016a202d4200200a420010d304200341b8016a200b4200200a420010d30420034198016a42004200200b420010d304024020032903b00120032903a00184420052200341c0016a290300222c20032903a8012003290398017c7c222e202c5472450d0041f6eac2002105412721020c150b20032903b801212c0b200341d0046a200341b0046a202c202e4108109001024020032802d0044101470d0020032802d804210220032802d40421050c140b200341d0046a41106a290300212e20032903d804212c20034198076a41186a202d3703002003200b3703a8072003200a3703a0072003200a37039807200341b8076a41086a22024200370300200342003703b80741f987c5004118200341b8076a1004200341b0096a41086a2002290300370300200320032903b8073703b009200341003602d004200341b0096a4110200341d0046a1005210220032802d004220f417f460d072002450d072003200f36028c082003200236028808200341d0046a20034188086a10f10220032d00c00522054102460d0620032802bc05210420032802b805210620032802b405211820032802b005211920032802ac05210c20032802a805210d20032903a005210a200329039805210b200329039005212d200329038805212f200329038005213020032903f804213120032903f004213220032903e804213320032903e004213420032903d804213520032903d0042136200320032800c105360298062003200341c4056a28000036009b060240200f450d00200210290b2003200328029806360288082003200328009b0636008b080c120b200141386a290300211e200141306a290300211a200141c0006a290300210a200341f0036a41186a200141196a290000370300200341f0036a41106a200141116a290000370300200341f0036a41086a200141096a290000370300200320012900013703f0032002411a6a290100210b200241196a2d00002108200241186a2d00002109200241166a2f0100210c200241156a2d0000210e200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d00002115200241046a2d00002116200241026a2f010021172001412c6a2802002107200141286a280200210d200141246a280200210f41d588c3002105412a21040240024020022d0000450d004101210641002118410021190c010b41012106410021184100211920022d00014101470d002002410c6a2d000021192002410a6a2f01002118200241096a2d00002104200241066a2f0100410874200241056a2d000072200241086a2d0000411874722105410021060b201841ffff0371410874200441ff017172201941187472210202402006450d00200d0d100c110b2003200b3703c804200320083a00c704200320093a00c6042003200c3b01c4042003200e3a00c304200320103a00c204200320113b01c004200320123a00bf04200320133a00be04200320143b01bc04200320153a00bb04200320023600b704200320053600b304200320163a00b204200320173b01b004200341e0026a41e887c500411110940102404280ade20420032903e8027d4280ade20420032802e0021b200a5a0d0041dbeac2002105411b21020c0f0b200341c8026a41b793c20041111086014200211b0240024020032903d002420120032802c80222021b220b200341d8026a290300420020021b222c8450450d004200212d0c010b200341a8026a202c4200200a420010d304200341b8026a200b4200200a420010d30420034198026a42004200200b420010d304024020032903b00220032903a00284420052200341c0026a290300221b20032903a8022003290398027c7c222d201b5472450d0041f6eac2002105412721020c100b20032903b802211b0b200341d0046a200341b0046a201b202d4108109001024020032802d0044101470d0020032802d804210220032802d40421050c0f0b200341d0046a41106a290300212d20032903d804211b20034198076a41186a202c3703002003200b3703a8072003200a3703a0072003200a37039807200341b8076a41086a22024200370300200342003703b80741f987c5004118200341b8076a1004200341b0096a41086a2002290300370300200320032903b8073703b009200341003602d004200341b0096a4110200341d0046a1005210220032802d004220c417f460d082002450d082003200c36028c082003200236028808200341d0046a20034188086a10f10220032d00c00522054102460d0720032802bc05210420032802b805210620032802b405211820032802b005211920032802ac05210820032802a805210920032903a005210a200329039805210b200329039005212c200329038805212e200329038005212f20032903f804213020032903f004213120032903e804213220032903e004213320032903d804213420032903d0042135200320032800c105360298062003200341c4056a28000036009b060240200c450d00200210290b2003200328029806360288082003200328009b0636008b080c0d0b20034198066a41186a200141196a29000037030020034198066a41106a200141116a29000037030020034198066a41086a200141096a290000370300200320012900013703980620034188086a41206a200141c1006a2d00003a000020034188086a41186a200141396a29000037030020034188086a41106a200141316a29000037030020034188086a41086a200141296a2900003703002003200141216a29000037038808200341d0046a41086a2205200241096a290000370300200341d0046a41106a2204200241116a290000370300200341d0046a41186a2206200241196a290000370300200341d0046a41206a2218200241216a2d00003a0000200341bc076a2219200241266a2f01003b0100200320022900013703d0042003200241226a2801003602b807024020022d00002202450d00200341b0096a41266a20032802b807360100200341bd096a2005290300370000200341c5096a2004290300370000200341cd096a2006290300370000200341d5096a20182d00003a0000200341da096a20192f01003b0100200320023a00b409200320032903d0043700b509200341013a00b00941b1e2c200210541e90021020c1e0b200341b0096a41216a20182d00003a0000200341b0096a41196a2006290300370000200341b0096a41116a2004290300370000200341b0096a41096a2005290300370000200320032903d004220a3700b109200341003a00b00941b1e2c200210541e9002102200aa741ff0171417f6a220441014b0d1d02400240024020040e020100010b20032d0088084101470d1f20034188086a41017221044200210a0c010b20032d0088084101460d1e200341b0096a41027221044202210a0b41002105200341d0046a20034198066a200a410010a00120032d00d0042102024020032d00d8040d002003418c056a280200450d0020034188056a28020010290b200241ff01714101470d1c200341d0046a20044296014200109f01024020032802d0044101470d0020032802d804210220032802d40421050c1e0b200341d0046a41106a290300210b20032903d804211e200341f0026a41b18ac0004116108601200341f0026a41106a290300210a20032903f802211a20032802f0022102200341b8076a41086a22044200370300200342003703b80741b18ac0004116200341b8076a100420034190046a41086a2004290300370300200320032903b807370390042003427f200b200a420020021b220a7c201e201a420020021b220b7c221e200b542202ad7c220b2002200b200a54200b200a511b22021b3703c0072003427f201e20021b3703b80720034190046a4110200341b8076a411010030c1c0b200141d8006a290300210b200141d0006a290300211e200341f0036a41186a200141196a290000370300200341f0036a41106a200141116a290000370300200341f0036a41086a200141096a290000370300200320012900013703f003200341b0046a41186a200141396a290000370300200341b0046a41106a200141316a290000370300200341b0046a41086a200141296a2900003703002003200141216a2900003703b004200141c4006a2802002109200141c8006a2802002108200141cc006a28020021072002411a6a290100210a200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d00002115200241046a2d00002116200241026a2f0100211741d588c3002105412a21040240024020022d0000450d004101210641002118410021190c010b41012106410021184100211920022d00014101470d002002410c6a2d000021192002410a6a2f01002118200241096a2d00002104200241066a2f0100410874200241056a2d000072200241086a2d0000411874722105410021060b201841ffff0371410874200441ff017172201941187472210220060d092003200a3703b0072003200c3a00af072003200d3a00ae072003200e3b01ac072003200f3a00ab07200320103a00aa07200320113b01a807200320123a00a707200320133a00a607200320143b01a407200320153a00a3072003200236009f072003200536009b07200320163a009a07200320173b019807200341d0046a20034198076a108c010240024020032d00d00422054102470d0041012105413421024202210a0c010b20034190096a41086a2204200341e4046a29020037030020034190096a41106a2206200341ec046a28020036020020034188086a41086a2218200341d0046a41306a29030037030020034188086a41106a221920034188056a29030037030020034188086a41186a220c20034190056a29030037030020034188086a41206a220d20034198056a29030037030020034188086a41286a220e200341a0056a29030037030020034188086a41306a220f200341a8056a2903003703002003200341dc046a290200370390092003200341d0046a41286a29030037038808200341d0046a41086a28020021024202210a4202211a024020050d00200341d0046a41206a290300211a20034190046a41106a200628020036020020034190046a41086a200429030037030020034198066a41086a201829030037030020034198066a41106a201929030037030020034198066a41186a200c29030037030020034198066a41206a200d29030037030020034198066a41286a200e29030037030020034198066a41306a200f2903003703002003200329039009370390042003200329038808370398060b0240201a4202520d0041012105413421020c010b20034188086a41106a20034190046a41106a28020036020020034188086a41086a20034190046a41086a290300370300200341d0046a41086a20034198066a41086a290300370300200341d0046a41106a20034198066a41106a290300370300200341d0046a41186a20034198066a41186a290300370300200341d0046a41206a20034198066a41206a290300370300200341d0046a41286a20034198066a41286a290300370300200341d0046a41306a20034198066a41306a29030037030020032003290390043703880820032003290398063703d00441002105201a210a0b200341f0076a41086a220420034188086a41086a290300370300200341f0076a41106a220620034188086a41106a280200360200200341b8076a41086a2218200341d0046a41086a290300370300200341b8076a41106a2219200341d0046a41106a290300370300200341b8076a41186a220c200341d0046a41186a290300370300200341b8076a41206a220d200341d0046a41206a290300370300200341b8076a41286a220e200341d0046a41286a290300370300200341b8076a41306a220f200341d0046a41306a29030037030020032003290388083703f007200320032903d0043703b80702402005450d00419ae3c20021050c0a0b200341b0096a41206a220520032903b807370300200341bc096a2004290300370200200341c4096a2006280200360200200341b0096a41286a2018290300370300200341b0096a41306a2019290300370300200341e8096a200c290300370300200341f0096a200d290300370300200341f8096a200e290300370300200341800a6a200f290300370300200320023602b009200320032903f0073702b4092003200a3703c809200341e0036a41888dc300410d10940120032903e803420020032802e0031b211a200aa74101470d072005290300201a520d0741cee3c2002105412a21020c080b418f89c3004133104e000b418f89c3004133104e000b200341003602880a200341003a00a00a200342908080808080103702940a200342848080808080c00037028c0a200342013703800a200342013703f809200342af013703f00920034287013703e809200342013703e009200342013703d809200342013703d009200342013703c809200342013703c009200342013703b809200342013703b0092003412036029c0a0c0e0b418f89c3004133104e000b4100210d428701212f42af01212d4201210a4104210c41808004211941102118418080012106412021044201210b42012130420121314201213242012133420121344201213542012136410021050c0a0b418f89c3004133104e000b4100210941202104418080012106411021184180800421194104210842af01212c428701212e4201213542012134420121334201213242012131420121304201212f4201210b4201210a410021050c040b200341d0046a200341f0036a108c010240024020032d00d00422024102460d0020020d0120034184056a280200450d0020034180056a28020010290b418ee4c2002105412e21020c010b200320032902d40437009309200320032d00d3043a009209200320032f00d1043b0190092003200341e9046a2900003703a8092003200341e5046a2800003602a4092003200341dd046a29000037029c092003200341dc046a2d00003a009b0920032903c809210a20032903d009211b200320093602b8072003200920074105746a3602bc072003200341b0096a3602c00720034188086a200341b8076a102502400240024002400240024002400240024002400240024002402003280288080d004104210441002105410021060c010b200341d0046a41086a220220034188086a41086a29030037030020032003290388083703d004411010272204450d01200420032903d004370200200441086a200229030037020020034198066a41086a200341b8076a41086a280200360200200320032903b8073703980620034188086a20034198066a102502402003280288080d0041012105410121060c010b41012102410121060340200341d0046a41086a221820034188086a41086a29030037030020032003290388083703d0040240024020062002460d00200241016a21050c010b200241016a22052002490d1820024101742206200520052006491b220641ffffffff00712006470d18200641047422194100480d180240024020020d002019102721040c010b200420024104742019102821040b2004450d040b200420024104746a220220032903d004370200200241086a201829030037020020034188086a20034198066a1025200521022003280288080d000b0b200341e0096a280200210220032802d8092118200341003602d00420182002200341d0046a100f210d20032802d0042218417f460d0220034188086a41186a200341b0046a41186a29030037030020034188086a41106a200341b0046a41106a29030037030020034188086a41086a200341b0046a41086a290300370300200320032903b00437038808200341003602d804200342013703d004200320183602b807200341b8076a200341d0046a10300240024020032802d404220c20032802d80422026b2018490d0020032802d00421190c010b200220186a22192002490d16200c410174220e20192019200e491b220e4100480d1602400240200c0d00200e102721190c010b20032802d004200c200e102821190b2019450d042003200e3602d404200320193602d004200e210c0b201920026a200d201810ce041a02400240200220186a22020d004101210e0c010b20024100480d1620021027220e450d09200e2019200210ce041a0b0240200c450d00201910290b20024101742219200241206a220c200c2019491b220f4100480d150240024020020d00200f102721190c010b200e2002200f102821190b024020190d00200f4101102a000b201920026a2202200329038808370000200241186a20034188086a41186a290300370000200241106a20034188086a41106a290300370000200241086a20034188086a41086a290300370000200341d0046a41186a22024200370300200341d0046a41106a220e4200370300200341d0046a41086a220f4200370300200342003703d0042019200c200341d0046a100020034198066a41186a200229030037030020034198066a41106a200e29030037030020034198066a41086a200f290300370300200320032903d004370398062019102902402018450d00200d10290b024020034198066a20034190096a412010d0040d000240024020050d00410021180c010b200541047421192004410c6a2102410021180340200228020020186a2118200241106a2102201941706a22190d000b0b200320032802e40920186b3602e409411710272202450d052002410f6a41002900af9342370000200241086a41002900a89342370000200241002900a0934237000020024117413710282202450d0620022003290398073700172002412f6a20034198076a41186a290300370000200241276a20034198076a41106a2903003700002002411f6a20034198076a41086a290300370000200341d0046a41186a22184200370300200341d0046a41106a22194200370300200341d0046a41086a220c4200370300200342003703d00420024137200341d0046a1000200341b8076a41186a2018290300370300200341b8076a41106a2019290300370300200341b8076a41086a200c290300370300200320032903d0043703b807200341b8076a4120100c200210292019200b370300200341f8046a201a201b20071b370300200341d0046a41206a4201200a20071b3703002018201a3703002003418c056a20032802e40936020020034190056a20032903b00437030020034198056a200341b0046a41086a290300370300200341a0056a200341b0046a41106a290300370300200341a8056a200341b0046a41186a29030037030020034180056a200341d8096a220229030037030020034188056a200241086a2802003602002003201e3703d804200341003a00d004200341f0036a200341d0046a10d801411410272202450d07200241106a41002800bb8c40360000200241086a41002900b38c40370000200241002900ab8c4037000020024114413410282202450d0820022003290398073700142002412c6a200341b0076a290300370000200241246a20034198076a41106a2903003700002002411c6a20034198076a41086a290300370000200341c8036a20024134108401200341c8036a41106a290300210a20032903d003210b20032802c803211820021029200341d0046a20034198076a4200420010850120032903d004211a200341b0036a41b18ac0004116108601200a420020181b211b200b420020181b212c200341b0036a41106a290300420020032802b00322021b210a20032903b803420020021b210b200341d0046a41106a290300212d20032903d804211e02400240201a4200520d00200341b8076a41086a22024200370300200342003703b80741b18ac0004116200341b8076a100420034190046a41086a2002290300370300200320032903b807370390042003427f200a202d7c200b201e7c221e200b542202ad7c220b2002200b200a54200b200a511b22021b370390082003427f201e20021b3703880820034188086a21020c010b200341b8076a41086a22024200370300200342003703b80741b18ac0004116200341b8076a100420034190046a41086a2002290300370300200320032903b8073703900420034200200a202d7d200b201e54ad7d221a200b201e7d221e200b56201a200a56201a200a511b22021b3703900820034200201e20021b3703880820034188086a21020b20034190046a4110200241101003200341a0036a200341f0036a202c201b108301200341a0036a41086a290300210b20032903a003211e20034188036a41b18ac000411610860120034188036a41106a290300210a200329039003211a2003280288032102200341b8076a41086a22184200370300200342003703b80741b18ac0004116200341b8076a100420034190046a41086a2018290300370300200320032903b807370390042003427f200b200a420020021b220a7c201e201a420020021b220b7c221e200b542202ad7c220b2002200b200a54200b200a511b22021b3703d8042003427f201e20021b3703d00420034190046a4110200341d0046a4110100302402005450d0020054104742105200441046a210203400240200241046a280200450d00200228020010290b200241106a2102200541706a22050d000b0b02402006450d00200410290b4100210502402008450d00200910290b0c0e0b200420054104746a2112024020050d00200421020c0a0b2004210203400240200228020022180d00200241106a21020c0b0b200241046a2802002105200241086a28020021192002410c6a280200210c20032802e009210d20032802d809210e200341d0046a41186a220f4200370300200341d0046a41106a22104200370300200341d0046a41086a22114200370300200342003703d00420184120200341d0046a100020034190046a41186a200f29030037030020034190046a41106a201029030037030020034190046a41086a2011290300370300200320032903d00437039004200e200d20034190046a41202005200c101102402019450d00200510290b200241106a22022012470d000c0b0b0b41104104102a000b20194104102a000b41b0cfc5004138104e000b200e4101102a000b41174101102a000b41374101102a000b41144101102a000b41344101102a000b20024101102a000b20022012460d0003402002280200450d010240200241086a280200450d00200241046a28020010290b200241106a22022012470d000b0b02402006450d00200410290b41f8e3c2002105411621020b200341dc096a280200450d0020032802d80910290b2008450d00200910290b410021084101210641012118410121190c130b200320053a00c005200320043602bc05200320063602b805200320183602b405200320193602b005200320083602ac05200320093602a8052003200a3703a0052003200b370398052003202c370390052003202e370388052003202f37038005200320303703f804200320313703f004200320323703e804200320333703e004200320343703d804200320353703d004200341d0056a420037030020034180066a4200370300200341f0056a4200370300200341e0056a4200370300200341d0046a41f4006a200328008b0836000020034280888080808010370388062003428080e983b1de163703c80520034280a094a58d1d3703f80520034280a094a58d1d3703e80520034280a094a58d1d3703d80520032003280288083600c1052003200341d0046a360294062003200341d0046a3602f00720034188026a41ceecc200410d109401200329039002210a2003280288022102200341f8016a41888dc300410d109401200341e4066a4100360200200341d4066a4200370200200341c8066a41e48cc300360200200341c4066a41b8d6c500360200200341bc066a22044200370200200341b8066a418883c000360200200341fc066a200341b0046a41086a29030037020020034184076a200341c0046a29030037020020034198066a41f4006a200341b0046a41186a290300370200200342083702dc062003428080808080013702cc06200341003602b406200341003602a806200320032903b0043702f40620032802f8012105200329038002210b2003200341f0076a3602f006200320034194066a3602ec062003200341d0046a3602e8062003200b420020051b3703a0062003200a420020021b37039806200341b0096a20034198066a201a201e20034198076a200341f0036a200f200710da0141012112200341b0096a41086a22062802002102024020032802b409410020032d00b0094101461b22050d002006200429020037030020034188086a41086a200341bc096a280200360200200320032902b4063703b009200320032902b40937038808200341d80a6a20034188086a10d40120032802d006220e20032802d806220641e8006c6a210920032802d4062110200e2104024002402006450d00200341b9096a210c200e21040240034020042d0000210620034188086a200441016a41d70010ce041a20064106460d01200441d8006a2800002118200441dc006a2800002119200441e0006a2800002108200320063a00b8092003410b3a00b009200c20034188086a41d70010ce041a20182008200341b0096a10880102402019450d00201810290b200441e8006a22042009470d000c030b0b200441e8006a21040b20042009460d00034020042d000022064106460d01200441286a2800002118200441246a28000021190240200441dc006a280000450d00200441d8006a28000010290b024020064105490d002018450d00201910290b200441e8006a22042009470d000b0b410021122010450d00200e10290b200341b0046a20032903980720032903a00720032903a80720034198076a41186a290300201b202d10f80220032802dc06221120032802e406220641a8016c6a210e20032802e00621132011210402402006450d00200341b9096a2106200341b8076a4102722118200341b0096a4104722110201121040240034020034190046a41186a2208200441186a29030037030020034190046a41106a2209200441106a29030037030020034190046a41086a220c200441086a2903003703002003200429030037039004200441206a280200211920034188086a200441246a41840110ce041a20194112460d01200320193602b009201020034188086a41840110ce041a2018200329039004370000201841086a200c290300370000201841106a2009290300370000201841186a200829030037000020034180023b01b807200341f0016a200341b0096a200341b8076a10ad0220032802f00121192006200329039004370000200641086a200c290300370000200641106a2009290300370000200641186a2008290300370000200341043a00b8092003410b3a00b00920032019453a00d90941b8d6c5004100200341b0096a108801200441a8016a2204200e470d000b200e21040c010b200441a8016a21040b02402004200e460d00200341b0096a41206a210c200341b0096a41246a21100340200341b8076a41186a2218200441186a290300370300200341b8076a41106a2219200441106a290300370300200341b8076a41086a2208200441086a290300370300200320042903003703b807200441206a2802002106200341b0096a200441246a41840110ce041a20064112460d0120034190096a41186a2209201829030037030020034190096a41106a2218201929030037030020034190096a41086a22192008290300370300200320032903b8073703900920034188086a200341b0096a41840110ce041a200341b0096a41186a2009290300370300200341b0096a41106a2018290300370300200341b0096a41086a201929030037030020032003290390093703b009200320063602d009201020034188086a41840110ce041a200c103d200441a8016a2204200e470d000b0b02402013450d00201110290b024020032802a8062204450d00200341ac066a280200450d00200410290b2012450d00200341b8066a280200210420032802c00621080240024020032802bc0622180d00200421060c010b2018211920042106034020062802880b21062019417f6a22190d000b0340200420042f01064102746a41880b6a28020021042018417f6a22180d000b0b200341cc096a20042f0106360200200341c8096a4100360200200341c4096a2004360200200320083602d009200341003602c009200342003703b809200320063602b409200341003602b009200341b0096a10d901024020032802d8062206450d0020032802d0062104200641e8006c210603400240200441dc006a280200450d00200441d8006a28020010290b024020042d00004105490d00200441286a280200450d00200441246a28020010290b200441e8006a2104200641987f6a22060d000b0b20032802d406450d0020032802d00610290b200d450d010b200f10290b410021194101210641012118410121080c0f0b200320053a00c005200320043602bc05200320063602b805200320183602b405200320193602b0052003200c3602ac052003200d3602a8052003200a3703a0052003200b370398052003202d370390052003202f370388052003203037038005200320313703f804200320323703f004200320333703e804200320343703e004200320353703d804200320363703d004200341d0056a420037030020034180066a4200370300200341f0056a4200370300200341e0056a4200370300200341d0046a41f4006a200328008b0836000020034280888080808010370388062003428080e983b1de163703c80520034280a094a58d1d3703f80520034280a094a58d1d3703e80520034280a094a58d1d3703d80520032003280288083600c1052003200341d0046a3602f0072003200341d0046a3602f00320034188016a41ceecc200410d109401200329039001210a2003280288012102200341f8006a41888dc300410d109401200341e4066a4100360200200341d4066a4200370200200341c8066a41e48cc300360200200341c4066a41b8d6c500360200200341bc066a4200370200200341b8066a418883c000360200200341fc066a200341b0046a41086a29030037020020034184076a200341c0046a29030037020020034198066a41f4006a200341c8046a290300370200200342083702dc062003428080808080013702cc06200341003602b406200341003602a806200320032903b0043702f40620032802782105200329038001210b2003200341f0036a3602f0062003200341f0076a3602ec062003200341d0046a3602e8062003200b420020051b3703a0062003200a420020021b370398062003201e3703c8092003201f3a00c709200320203a00c609200320213b01c409200320223a00c309200320233a00c209200320243b01c009200320253a00bf09200320263a00be09200320273b01bc09200320283a00bb09200320293600b709200320093600b3092003202a3a00b2092003202b3b01b009200341003602c007200342013703b80720034188086a20034198066a200341b0096a201b201a20034198076a200e201d200341b8076a10e1014101211220034188086a41086a2802002102200328028c08210502402003280288084101460d0002402002450d00200510290b200341b0096a41086a200341bc066a29020037030020034188086a41086a200341bc096a280200360200200320032902b4063703b009200320032902b40937038808200341d80a6a20034188086a10d40120032802d006220d20032802d806220441e8006c6a210920032802d406210f200d2105024002402004450d00200341b9096a210c200d21050240034020052d0000210420034188086a200541016a41d70010ce041a20044106460d01200541d8006a2800002106200541dc006a2800002118200541e0006a2800002119200320043a00b8092003410b3a00b009200c20034188086a41d70010ce041a20062019200341b0096a10880102402018450d00200610290b200541e8006a22052009470d000c030b0b200541e8006a21050b20052009460d00034020052d000022044106460d01200541286a2800002106200541246a28000021180240200541dc006a280000450d00200541d8006a28000010290b024020044105490d002006450d00201810290b200541e8006a22052009470d000b0b0240200f450d00200d10290b41002105410021120b200341b0046a20032903980720032903a00720032903a80720034198076a41186a290300202c202e10f80220032802dc06221120032802e406220641a8016c6a210f20032802e00621132011210402402006450d00200341b9096a2106200341b8076a4102722118200341b0096a4104722110201121040240034020034190046a41186a2209200441186a29030037030020034190046a41106a220c200441106a29030037030020034190046a41086a220d200441086a2903003703002003200429030037039004200441206a280200211920034188086a200441246a41840110ce041a20194112460d01200320193602b009201020034188086a41840110ce041a2018200329039004370000201841086a200d290300370000201841106a200c290300370000201841186a200929030037000020034180023b01b807200341f0006a200341b0096a200341b8076a10ad02200328027021192006200329039004370000200641086a200d290300370000200641106a200c290300370000200641186a2009290300370000200341043a00b8092003410b3a00b00920032019453a00d90941b8d6c5004100200341b0096a108801200441a8016a2204200f470d000b200f21040c010b200441a8016a21040b02402004200f460d00200341b0096a41206a210d200341b0096a41246a21100340200341b8076a41186a2218200441186a290300370300200341b8076a41106a2219200441106a290300370300200341b8076a41086a2209200441086a290300370300200320042903003703b807200441206a2802002106200341b0096a200441246a41840110ce041a20064112460d0120034190096a41186a220c201829030037030020034190096a41106a2218201929030037030020034190096a41086a22192009290300370300200320032903b8073703900920034188086a200341b0096a41840110ce041a200341b0096a41186a200c290300370300200341b0096a41106a2018290300370300200341b0096a41086a201929030037030020032003290390093703b009200320063602d009201020034188086a41840110ce041a200d103d200441a8016a2204200f470d000b0b02402013450d00201110290b024020032802a8062204450d00200341ac066a280200450d00200410290b2012450d00200341b8066a280200210420032802c00621090240024020032802bc0622180d00200421060c010b2018211920042106034020062802880b21062019417f6a22190d000b0340200420042f01064102746a41880b6a28020021042018417f6a22180d000b0b200341cc096a20042f0106360200200341c8096a4100360200200341c4096a2004360200200320093602d009200341003602c009200342003703b809200320063602b409200341003602b009200341b0096a10d901024020032802d8062206450d0020032802d0062104200641e8006c210603400240200441dc006a280200450d00200441d8006a28020010290b024020042d00004105490d00200441286a280200450d00200441246a28020010290b200441e8006a2104200641987f6a22060d000b0b20032802d406450d0020032802d00610290b41002118410121062008450d0c200e10290c0c0b200341e0006a41e887c500411110940102404280ade20420032903687d4280ade20420032802601b200a5a0d0041dbeac2002105411b21020c090b200341c8006a41b793c20041111086014200211e0240024020032903504201200328024822021b220b200341d8006a290300420020021b221a8450450d004200211b0c010b200341286a201a4200200a420010d304200341386a200b4200200a420010d304200341186a42004200200b420010d30402402003290330200329032084420052200341c0006a290300221e200329032820032903187c7c221b201e5472450d0041f6eac2002105412721020c0a0b2003290338211e0b200341d0046a20034198066a201e201b4108109001024020032802d0044101470d0020032802d804210220032802d40421050c090b200341086a20032903b00942002007ad420010d3044200200a427f200329030820032903104200521b7d221e201e200a5622021b212c200341e0046a290300211b20032903d804211e02402002450d0041cde1c1002105412c21020c070b200341d0046a20092007200341b0096a108502024020032802d0044101470d00200341d8046a280200210220032802d40421050c070b20034190096a41186a2205200341d0046a410472220241186a28020036020020034190096a41106a2204200241106a29020037030020034190096a41086a2218200241086a2902003703002003200229020037039009200341d0046a41186a22024200370300200341d0046a41106a4200370300200341d0046a41086a4200370300200342003703d00420092007200341d0046a1000200341f0036a41026a20032d00d20422193a0000200341b0046a41086a220c200341e3046a290000370300200341b0046a410d6a220d2002290000370000200320032f01d004220e3b01f003200320032900db04222d3703b00420032800d304210620032800d704210220034190046a41026a20193a000020034198076a41086a200c29030037030020034198076a410d6a200d2900003700002003200e3b0190042003202d37039807200341b8076a41186a2005280200360200200341b8076a41106a2004290300370300200341b8076a41086a201829030037030020032003290390093703b807411410272205450d01200541106a410028009c9342360000200541086a410029009493423700002005410029008c934237000020054114413410282205450d02200520032f0190043b00142005200236001b20052006360017200520032903980737001f200541166a20034190046a41026a22042d00003a0000200541276a20034198076a41086a2903003700002005412c6a20034198076a410d6a290000370000200341d0046a41186a22184200370300200341d0046a41106a22194200370300200341d0046a41086a220c4200370300200342003703d00420054134200341d0046a100020034188086a41186a201829030037030020034188086a41106a201929030037030020034188086a41086a200c290300370300200320032903d00437038808200341203602d404200320034188086a3602d004200341b8076a200341d0046a105b200510290240200341b8076a41106a280200450d0020032802c40710290b2004200341f0036a41026a2d00003a0000200341b8076a41086a200341b0046a41086a290300370300200341b8076a410d6a200341b0046a410d6a290000370000200320032f01f0033b019004200320032903b0043703b807411510272205450d032005410d6a41002900ce9242370000200541086a41002900c99242370000200541002900c1924237000020054115413510282205450d04200520032f0190043b00152005200236001c20052006360018200520032903b807370020200541176a20034192046a2d00003a0000200541286a200341b8076a41086a2903003700002005412d6a200341b8076a410d6a290000370000200341d0046a41186a22044200370300200341d0046a41106a22184200370300200341d0046a41086a22194200370300200342003703d00420054135200341d0046a100020034188086a41186a200429030037030020034188086a41106a201829030037030020034188086a41086a2019290300370300200320032903d00437038808200341003602d804200342013703d004200320073602980720034198076a200341d0046a10300240024020032802d404221920032802d80422186b2007490d0020032802d00421040c010b201820076a22042018490d012019410174220c20042004200c491b220c4100480d010240024020190d00200c102721040c010b20032802d0042019200c102821040b2004450d062003200c3602d404200320043602d004200c21190b200420186a2009200710ce041a20034188086a41202004201820076a100302402019450d00200410290b2005102902402008450d00200910290b20034198076a41026a2205200341f0036a41026a2d00003a000020034188086a41086a2204200341b0046a41086a29030037030020034188086a410d6a2218200341b0046a410d6a290000370000200320032f01f0033b019807200320032903b00437038808200341d0046a41086a41023a0000200341e0046a2002360200200341dc046a20063602002003410b3a00d004200341d9046a20032f0198073b0000200341d0046a410b6a20052d00003a0000200341e4046a200329038808370200200341ec046a2004290300370200200341f1046a20182900003700004100210541b8d6c5004100200341d0046a10880120034198066a200a202c200b201a201e201b10f8020c070b102b000b41144101102a000b41344101102a000b41154101102a000b41354101102a000b200c4101102a000b02402008450d00200910290b20034198066a200a202c200b201a201e201b10f8020b41012118410021060c030b41012118410021062008450d02200910290c020b0b41012106410121180b41012119410121080b02400240024020012d0000220441064b0d00024002400240024020040e0706060001020603060b2006450d05200141086a280200450d05200141046a28020010290c050b2018450d042001412c6a280200450d04200141286a28020010290c040b2019450d03200141286a280200450d03200141246a28020010290c030b20080d010c020b200141c8006a280200450d01200141c4006a28020010290c010b200141c8006a280200450d00200141c4006a28020010290b2000200236020420002005360200200341e00a6a24000b3400200041d0f4c10036020420004100360200200041146a4101360200200041106a4180f9c100360200200041086a42043702000b130020004102360204200041dcf4c1003602000b950101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120102722060d0041204101102a000b20062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000bb014030c7f017e017f230041e0006b2201240020014100360208200142043703000240024002400240024002400240024002400240024002400240024002400240200041106a28020041246c22020d004104210341002104410021050c010b20002802082106410421034100210441002107410021050340024020062d00004101470d00200641106a2802002208417f4c0d03200641016a28000021090240024020080d004101210a0c010b200641086a280200210b20081027220a450d05200a200b200810ce041a0b200141c0006a41086a220c200141206a41086a29020037030020012001290220370340024020052007470d00024020042007460d00200421070c010b200441016a220b2004490d1020044101742207200b200b2007491b2207ad42247e220d422088a70d10200da7220b4100480d100240024020040d00200b102721030c010b2003200441246c200b102821030b2003450d062001200736020420012003360200200721040b2003200541246c6a220b2008360210200b200836020c200b200a360208200b2009360001200b41013a0000200b2001290340370214200b411c6a200c2903003702002001200541016a22053602080b200641246a21062002415c6a22020d000b0b2001410036024041ff88c3004110200141c0006a41041003200141c0006a41086a220642003703002001420037034041888dc300410d200141c0006a1004200141206a41086a220b20062903003703002001200129034037032020012000290300220d370340200141206a4110200141c0006a41081003200642003703002001420037034041aa8dc300410d200141c0006a1004200b200629030037030020012001290340370320200141103602442001200141206a3602402001200141c0006a105c200642003703002001420037034041d18fc3004111200141c0006a1004200b200629030037030020012001290340370320200141206a4110200041146a220241201003411010272206450d03200641086a41002900bf8d43370000200641002900b78d433700002006411041201028220b450d04200b200d427f7c370010200141c0006a41186a22084200370300200141c0006a41106a220a4200370300200141c0006a41086a2206420037030020014200370340200b4118200141c0006a1000200141206a41186a2008290300370300200141206a41106a200a290300370300200141206a41086a2208200629030037030020012001290340370320200141206a4120200241201003200b1029200642003703002001420037034041958dc3004115200141c0006a10042008200629030037030020012001290340370320200141206a4110200041d4006a41201003200642003703002001420037034041e28fc3004115200141c0006a10042008200629030037030020012001290340370320200141106a200141206a10ba020240200128021422060d002001410136020c4100210b4100210e410021080c070b2001200636020c20012c001021082001280218210e2001411c6a280200220b41d100490d06200141c0006a41186a220a2000412c6a290000370300200141c0006a41106a2207200041246a290000370300200141c0006a41086a22092000411c6a29000037030020012000290014370340200b20084d0d05200620084105746a22022001290340370000200241186a200a290300370000200241106a2007290300370000200241086a2009290300370000200841187441808080086a41187541d1006f21080c070b1039000b20084101102a000b200b4104102a000b41104101102a000b41204101102a000b41f88fc3002008200b1037000b200141d8006a2000412c6a290000370300200141d0006a200041246a290000370300200141c8006a2000411c6a2900003703002001200029001437034002400240200b200e460d00200128020c21060c010b200b41016a2206200b490d06200b4101742202200620062002491b220e41ffffff3f71200e470d06200e41057422024100480d0602400240200b0d002002102721060c010b200128020c200b4105742002102821060b2006450d022001200636020c0b2006200b4105746a22022001290340370000200241186a200141c0006a41186a290300370000200241106a200141c0006a41106a290300370000200241086a200141c0006a41086a290300370000200b41016a210b0b200141c0006a41086a220242003703002001420037034041e28fc3004115200141c0006a1004200141206a41086a2002290300370300200120012903403703202001410036024820014201370340410110272202450d01200220083a00002001428180808010370244200120023602402001200b360210200b4105742109200141106a200141c0006a103041002001280248220b6b2102200128024021072001280244210a03400240200a20026a411f4b0d00200b41206a2208200b490d06200a410174220c20082008200c491b22084100480d0602400240200a0d002008102721070c010b2007200a2008102821070b2007450d072008210a0b2007200b6a22082006290000370000200841186a200641186a290000370000200841106a200641106a290000370000200841086a200641086a290000370000200241606a2102200b41206a210b200641206a2106200941606a22090d000b200141206a41102007200b10030240200a450d00200710290b0240200e450d00200128020c10290b200141c0006a41086a2206420037030020014200370340418890c300410d200141c0006a1004200141206a41086a2208200629030037030020012001290340370320200141206a4110100c20064200370300200142003703404187cec5004111200141c0006a10042008200629030037030020012001290340370320200141206a4110100c41121027220b450d02200b41106a41002f00a590433b0000200b41086a410029009d9043370000200b41002900959043370000200141c0006a41186a22024200370300200141c0006a41106a220a42003703002006420037030020014200370340200b4112200141c0006a1000200141206a41186a22072002290300370300200141206a41106a200a2903003703002008200629030037030020012001290340370320412010272206450d0320062001290320370000200641186a2007290300370000200641106a200141206a41106a290300370000200641086a200141206a41086a290300370000200b102920064120100e20061029200029030010bb0202402005450d00200541246c210b2003210603400240024020062d0000220841034b0d0002400240024020080e0404000102040b2006410c6a280200450d03200641086a28020010290c030b2006410c6a280200450d02200641086a28020010290c020b2006410c6a280200450d01200641086a28020010290c010b200641086a280200450d00200641046a28020010290b200641246a2106200b415c6a220b0d000b0b02402004450d00200310290b200141e0006a24000f0b20024101102a000b41014101102a000b41124101102a000b41204101102a000b102b000b20084101102a000b9d0202057f017e230041306b220224002002410036022020014110200241206a100521010240024002400240024020022802202203417f460d0020010d010b200041003602040c010b2002200136021020022003360214200241003a0020200241206a20012003410047220410ce041a20032004490d012002200320046b3602142002200120046a3602102003450d0220022d00202103200241206a200241106a102d20022802202204450d022002410c6a41026a2002411d6a41026a2d000022053a0000200220022f001d22063b010c20022902242107200020033a0000200020063b0001200041036a20053a00002000200737020820002004360204200110290b200241306a24000f0b20042003103e000b418f89c3004133104e000b93b10108047f017e207f017e057f037e127f0c7e230041c00c6b2201240020014198056a41086a22024200370300200142003703980541aa8dc300410d20014198056a1004200141d8076a41086a200229030037030020012001290398053703d807200141003602980b200141d8076a4110200141980b6a100521020240024002400240024002400240024002400240024020012802980b2203417f460d002002450d00200120033602bc06200120023602b806200141980b6a200141b8066a104320012802980b2204450d02200129029c0b210502402003450d00200210290b20042005422088a7220641246c22076a2103200421020240200741ed00490d00200141980b6a41086a2108200421020340024020022d00004101470d00200241016a2800002107200241086a28020021092001200241106a2802003602840a200120093602800a0240200741c28289aa04460d00200142003703980b0c010b200141980b6a200141800a6a10880220012903980b4201520d00200141d8076a200841f00010ce041a200141b8066a200141d8076a41f00010ce041a200141b8066a21020c060b0240200241246a2d00004101470d00200241256a28000021072002412c6a28020021092001200241346a2802003602840a200120093602800a0240200741c28289aa04460d00200142003703980b0c010b200141980b6a200141800a6a10880220012903980b4201520d00200141d8076a200841f00010ce041a200141b8066a200141d8076a41f00010ce041a200141b8066a21020c060b0240200241c8006a2d00004101470d00200241c9006a2800002107200241d0006a28020021092001200241d8006a2802003602840a200120093602800a0240200741c28289aa04460d00200142003703980b0c010b200141980b6a200141800a6a10880220012903980b4201520d00200141d8076a200841f00010ce041a200141b8066a200141d8076a41f00010ce041a200141b8066a21020c060b0240200241ec006a2d00004101470d00200241ed006a2800002107200241f4006a28020021092001200241fc006a2802003602840a200120093602800a0240200741c28289aa04460d00200142003703980b0c010b200141980b6a200141800a6a10880220012903980b4201520d00200141d8076a200841f00010ce041a200141b8066a200141d8076a41f00010ce041a200141b8066a21020c060b200320024190016a22026b41ec004b0d000b0b20022003460d012004200641246c6a2103200141980b6a41086a21060340024020022d00004101470d00200241016a2800002107200241086a28020021092001200241106a2802003602840a200120093602800a0240200741c28289aa04460d00200142003703980b0c010b200141980b6a200141800a6a10880220012903980b4201520d00200141d8076a200641f00010ce041a200141b8066a200141d8076a41f00010ce041a200141b8066a21020c050b2003200241246a2202470d000c020b0b42002105410421040b02402005422088a72202450d00200241246c21032004210203400240024020022d0000220741034d0d00200241086a280200450d01200241046a28020010290c010b02400240024020070e0403000102030b2002410c6a280200450d02200241086a28020010290c020b2002410c6a280200450d01200241086a28020010290c010b2002410c6a280200450d00200241086a28020010290b200241246a21022003415c6a22030d000b0b2005a70d020c030b418f89c3004133104e000b20022d002f210720022d002e210920022d002d210620022d002c210820022d002b210a20022d002a210b20022d0029210c20022d0028210d20022d0027210e20022d0026210f20022d0025211020022d0024211120022d0023211220022d0022211320022d0021211420022d0020211520022d001f211620022d001e211720022d001d211820022d001c211920022d001b211a20022d001a211b20022d0019211c20022d0018211d20022d0017211e20022d0016211f20022d0015212020022d0014212120022d0013212220022d0012212320022d0011212420022d0010212520022903002126200141b8046a41e2c5c50041131094010240024020012903c004500d0020012802b8040d010b20014198056a41086a22024200370300200142003703980541e2c5c500411320014198056a1004200141d8076a41086a200229030037030020012001290398053703d807200120263703980b200141d8076a4110200141980b6a410810030b20014198056a41086a22024200370300200142003703980541f5c5c500411020014198056a1004200141d8076a41086a200229030037030020012001290398053703d807200120263703980b200141d8076a4110200141980b6a4108100320024200370300200142003703980541a7c6c500411620014198056a1004200141b8066a41086a200229030037030020012001290398053703b806200141003602980b200141b8066a4110200141980b6a100521020240024020012802980b2203417f460d002002450d00200141980b6a2003412020034120491b22276a41004100412020276b2027411f4b1b10cd041a200141980b6a2002202710ce041a2003411f4d0d04200141d8076a41186a2203200141980b6a41186a2227290000370300200141d8076a41106a2228200141980b6a41106a2229290000370300200141d8076a41086a222a200141980b6a41086a222b290000370300200120012900980b3703d8072002102920272003290300222637030020292028290300222c370300202b202a290300222d370300200120012903d807222e3703980b2026a72102202ca72103202da72127202ea7212820012d00af0b212920012d00ae0b212a20012d00ad0b212b20012d00ac0b212f20012d00ab0b213020012d00aa0b213120012d00a90b213220012d00a70b213320012d00a60b213420012d00a50b213520012d00a40b213620012d00a30b213720012d00a20b213820012d00a10b213920012d009f0b213a20012d009e0b213b20012d009d0b213c20012d009c0b213d20012d009b0b213e20012d009a0b213f20012d00990b21400c010b200141a00b6a4200370300200141a80b6a4200370300200141b00b6a4200370300200142003703980b41002102410021294100212a4100212b4100212f4100213041002131410021324100210341002133410021344100213541002136410021374100213841002139410021274100213a4100213b4100213c4100213d4100213e4100213f41002140410021280b20012002200d733a00b00b20012029200e733a00af0b2001202a200f733a00ae0b2001202b2010733a00ad0b2001202f2011733a00ac0b200120302012733a00ab0b200120312013733a00aa0b200120322014733a00a90b200120032015733a00a80b200120332016733a00a70b200120342017733a00a60b200120352018733a00a50b200120362019733a00a40b20012037201a733a00a30b20012038201b733a00a20b20012039201c733a00a10b20012027201d733a00a00b2001203a201e733a009f0b2001203b201f733a009e0b2001203c2020733a009d0b2001203d2021733a009c0b2001203e2022733a009b0b2001203f2023733a009a0b200120402024733a00990b200120282025733a00980b200120012d00b10b200c733a00b10b200120012d00b20b200b733a00b20b200120012d00b30b200a733a00b30b200120012d00b40b2008733a00b40b200120012d00b50b2006733a00b50b200120012d00b60b2009733a00b60b200120012d00b70b2007733a00b70b20014198056a41086a22024200370300200142003703980541a7c6c500411620014198056a1004200141d8076a41086a200229030037030020012001290398053703d807200141d8076a4110200141980b6a4120100302402005422088a72202450d00200241246c21032004210203400240024020022d0000220741034b0d0002400240024020070e0404000102040b2002410c6a280200450d03200241086a28020010290c030b2002410c6a280200450d02200241086a28020010290c020b2002410c6a280200450d01200241086a28020010290c010b200241086a280200450d00200241046a28020010290b200241246a21022003415c6a22030d000b0b2005a7450d010b200410290b20014198056a41086a220242003703002001420037039805418bf4c200411120014198056a100420014188066a41086a2002290300370300200120012903980537038806200141003602980b20014188066a4110200141980b6a100521020240024020012802980b2203417f460d002002450d00200120033602dc07200120023602d807200141980b6a200141d8076a104620012802980b2204450d03200129029c0b21052003450d01200210290c010b41082104420021050b20042005422088a7220641c8006c22026a21090240200241d9014f0d0041002102200421030c040b200441e0016a21034100210203400240200341a07e6a22072d00004101460d00200341a87e6a29030020005a0d060b0240200741c8006a2d00004101460d00200341f07e6a2903002000540d00200241016a21020c060b024020074190016a2d00004101460d00200341b87f6a2903002000540d00200241026a21020c060b02400240200741d8016a2d00004101460d00200329030020005a0d010b200341a0026a2103200241046a21022009200741a0026a6b41d8014d0d040c010b0b200241036a21020c040b418f89c3004133104e000b418f89c3004133104e000b200341a07e6a21030b20032009460d002004200641c8006c6a21070340024020032d00004101460d00200341086a29030020005a0d020b200241016a21022007200341c8006a2203470d000b0b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200220064b0d000240200620026b2203450d002002450d0020042004200241c8006c6a200341c8006c10cf041a0b200141003a00980b20014198056a41086a22024200370300200142003703980541fcc7c500411720014198056a100420014188066a41086a200229030037030020012001290398053703880620014188066a4110200141980b6a41011003200141d8076a109801200141980b6a41186a200141d8076a41186a290300370300200141980b6a41106a200141d8076a41106a290300370300200141980b6a41086a2202200141d8076a41086a290300370300200120012903d8073703980b200141980b6a411410960302402005a7450d00200410290b20024200370300200142003703980b41f5c5c5004110200141980b6a1004200141e8056a41086a2002290300370300200120012903980b3703e805200141003602980b200141e8056a4110200141980b6a1005210202400240024020012802980b2203417f470d00420021050c010b024020020d00420021050c010b200142003703980b200141980b6a20022003410820034108491b10ce041a200341074d0d0120012903980b2105200210290b42002126200141980b6a41086a22024200370300200142003703980b41e2c5c5004113200141980b6a1004200141e8056a41086a2002290300370300200120012903980b3703e805200141003602980b200141e8056a4110200141980b6a100521020240024020012802980b2203417f460d002002450d00200142003703980b200141980b6a20022003410820034108491b10ce041a200341074d0d0120012903980b2126200210290b4200200520267d222620262005561b42eb02540d07200141b0046a4193c8c500411410b50120012802b404211c20012802b004211d200141980b6a41086a22024200370300200142003703980b41b6c8c5004115200141980b6a1004200141e8056a41086a2002290300370300200120012903980b3703e805200141003602980b200141e8056a4110200141980b6a10052102024002400240024020012802980b2203417f470d00410221190c010b024020020d00410221190c010b200141003a00980b200141980b6a20022003410047220710ce041a20032007490d022003450d0120012d00980b2119200210290b41a7c8c500410f108a02211f200141980b6a41086a22024200370300200142003703980b4190e1c1004112200141980b6a1004200141e8056a41086a2002290300370300200120012903980b3703e805200141003602980b200141e8056a4110200141980b6a1005211a0240024002400240024002400240024002400240024002400240024020012802980b221b417f460d00201a450d002001201b3602dc052001201a3602d805200141a8046a200141d8056a102e20012802a804450d2b0240024020012802ac042218412a2018412a491b22170d004101210e0c010b201741e0006c22021027220e450d0e0b02402018450d00200141980b6a41206a2102200141b8066a41206a210920012802d805210420012802dc0521074100210b4100210a410021080340200141f8046a2007412020074120491b22036a41004100412020036b2003411f4b1b10cd041a200141f8046a2004200310ce041a2001200420036a22063602d805200720036b21040240024002402007411f4b0d00200120043602dc050c010b200141d8046a41186a2210200141f8046a41186a220c290000370300200141d8046a41106a2211200141f8046a41106a220d290000370300200141d8046a41086a2212200141f8046a41086a220f290000370300200120012900f8043703d804200141f8046a2004412020044120491b22036a41004100412020036b2003411f4b1b10cd041a200141f8046a2006200310ce041a2001200620036a22073602d805200420036b210602402004411f4b0d00200120063602dc050c010b20014198056a41086a2213200f29000037030020014198056a41106a2214200d29000037030020014198056a41186a2215200c290000370300200120012900f80422053703b8052001200537039805200141f8046a2006412020064120491b22036a41004100412020036b2003411f4b1b10cd041a200141f8046a2007200310ce041a2001200720036a22043602d805200620036b21072006411f4b0d01200120073602dc050b2017450d2e200e10290c2e0b200841016a2103200141f8086a41086a2206200f290000370300200141f8086a41106a220f200d290000370300200141f8086a41186a220d200c290000370300200141b8066a41186a220c2015290300370300200141b8066a41106a22152014290300370300200141b8066a41086a22142013290300370300200120012900f80422053703b805200120053703f80820012001290398053703b806200920012903f808370000200941086a2006290300370000200941106a200f290300370000200941186a200d290300370000200141800a6a41386a2206200141b8066a41386a290300370300200141800a6a41306a220d200141b8066a41306a290300370300200141800a6a41286a220f200141b8066a41286a290300370300200141800a6a41206a22132009290300370300200141800a6a41186a2216200c290300370300200141800a6a41106a220c2015290300370300200141800a6a41086a22152014290300370300200120012903b8063703800a200141980b6a41186a2010290300370300200141980b6a41106a2011290300370300200141980b6a41086a2012290300370300200120012903d8043703980b200220012903800a370000200241086a2015290300370000200241106a200c290300370000200241186a2016290300370000200241206a2013290300370000200241286a200f290300370000200241306a200d290300370000200241386a2006290300370000200141d8076a200141980b6a41e00010ce041a024020082017470d00200b20032003200b491b2217ad42e0007e2205422088a70d2d2005a722064100480d2d0240024020080d0020061027210e0c010b200e200a20061028210e0b200e450d050b200e200a6a200141d8076a41e00010ce041a200b41026a210b200a41e0006a210a2003210820182003470d000b200120073602dc050b200e450d2b201b450d01201a10290c010b4101210e41002118410021170b4100210702400240201841e0006c22020d004101211b4100211e0c010b200241e0006e221e41057422031027221b450d0b0b0240200e200e20026a22164622140d00201841e0006c210941002107201b2102200e2103034020022003290000370000200241186a200341186a290000370000200241106a200341106a290000370000200241086a200341086a290000370000200741016a2107200241206a2102200341e0006a2103200941a07f6a22090d000b0b200141980b6a41086a22024200370300200142003703980b41abccc1004112200141980b6a1004200141e8056a41086a2002290300370300200120012903980b3703e805200141003602a00b200142013703980b200120073602d807200141d8076a200141980b6a10300240024020070d0020012802a00b2103200128029c0b210420012802980b21060c010b20074105742108410020012802a00b22036b210920012802980b2106200128029c0b2104201b210203400240200420096a411f4b0d00200341206a22072003490d2b2004410174220a20072007200a491b22074100480d2b0240024020040d002007102721060c010b200620042007102821060b2006450d04200721040b200620036a22072002290000370000200741186a200241186a290000370000200741106a200241106a290000370000200741086a200241086a290000370000200941606a2109200341206a2103200241206a2102200841606a22080d000b2001200436029c0b200120033602a00b200120063602980b0b201c4100201d1b2102200141e8056a411020062003100302402004450d00200610290b200141c8046a200241026a10a4030240024020012802c804221a0d00200141980b6a41086a22034200370300200142003703980b41abccc1004112200141980b6a1004200141e8056a41086a2003290300370300200120012903980b3703e805200141003602980b200141e8056a4110200141980b6a100521070240024020012802980b2209417f460d002007450d00200120093602dc07200120073602d807200141980b6a200141d8076a102d20012802980b220f450d0d200141a00b6a2802002103200128029c0b21102009450d01200710290c010b4101210f41002103410021100b201f201f41ff01714102477121114100211c0c010b200141d0046a28020021034101211c20012802cc042110201a210f410121110b200141980b6a41086a22074200370300200142003703980b4193c8c5004114200141980b6a1004200141e8056a41086a2007290300370300200120012903980b3703e805410121122001200241016a22133602980b200141e8056a4110200141980b6a410410034100210b02400240200341057422020d004100211d0c010b2002410575221dad42e0007e2205422088a70d292005a722074100480d29200710272212450d090b0240200f20026a200f460d0020034105742104200141d8076a4101722107200141980b6a41206a21024100210b20122106200f21030340200341086a2900002105200341106a29000021262003290000212c200141b8066a41186a2208200341186a290000370300200141b8066a41106a220a2026370300200141b8066a41086a220c20053703002001202c3703b806200141f8086a200141b8066a108d01200141d8076a20012802f808220d200128028009108e0141002109024020012d00d8074101470d00200141800a6a41386a200741386a290000370300200141800a6a41306a200741306a290000370300200141800a6a41286a200741286a290000370300200141800a6a41206a200741206a290000370300200141800a6a41186a200741186a290000370300200141800a6a41106a200741106a290000370300200141800a6a41086a200741086a290000370300200120072900003703800a410121090b024020012802fc08450d00200d10290b0240024020090d00200141d8076a41386a4200370300200141d8076a41306a4200370300200141d8076a41286a4200370300200141d8076a41206a4200370300200141d8076a41186a4200370300200141d8076a41106a4200370300200141d8076a41086a4200370300200142003703d8070c010b200141d8076a41386a200141800a6a41386a290300370300200141d8076a41306a200141800a6a41306a290300370300200141d8076a41286a200141800a6a41286a290300370300200141d8076a41206a200141800a6a41206a290300370300200141d8076a41186a200141800a6a41186a290300370300200141d8076a41106a200141800a6a41106a290300370300200141d8076a41086a200141800a6a41086a290300370300200120012903800a3703d8070b200341206a2103200220012903d807370000200141980b6a41086a200c290300370300200141980b6a41106a200a290300370300200141980b6a41186a2008290300370300200241086a200141d8076a41086a290300370000200241106a200141d8076a41106a290300370000200241186a200141d8076a41186a290300370000200241206a200141d8076a41206a290300370000200241286a200141d8076a41286a290300370000200241306a200141d8076a41306a290300370000200241386a200141d8076a41386a290300370000200120012903b8063703980b200b41016a210b2006200141980b6a41e00010ce0441e0006a2106200441606a22040d000b0b02402010450d00200f10290b200bad42e0007e2205422088a70d072005a72202417f4c0d070240024020020d004101210c0c010b20021027220c450d070b410021090240200b450d002012200b41e0006c6a2106200141980b6a41c0006a2103200141980b6a41206a210741002109200c2104201221020340200141980b6a41186a200241186a290000370300200141980b6a41106a200241106a290000370300200141980b6a41086a200241086a290000370300200120022900003703980b2007200241206a290000370000200741086a200241286a290000370000200741106a200241306a290000370000200741186a200241386a2900003700002003200241c0006a290000370000200341086a200241c8006a290000370000200341106a200241d0006a290000370000200341186a200241d8006a290000370000200941016a21092004200141980b6a41e00010ce0441e0006a2104200241e0006a22022006470d000b0b200141980b6a41086a22024200370300200142003703980b4190e1c1004112200141980b6a1004200141e8056a41086a2002290300370300200120012903980b3703e805200141003602a00b200142013703980b200120093602d807200141d8076a200141980b6a10300240024020090d0020012802a00b2102200128029c0b210320012802980b21070c010b200c200941e0006c6a210d410020012802a00b22066b210420012802980b2107200128029c0b2103410021090340200620096a210a0240024002400240200320046a411f4b0d00200a41206a2202200a490d2e20034101742208200220022008491b22024100480d2e0240024020030d002002102721070c010b200720032002102821070b2007450d01200221030b200720066a20096a2208200c20096a2202290000370000200841186a200241186a290000370000200841106a200241106a290000370000200841086a200241086a290000370000200320046a41606a411f4b0d02200a41206a220f41206a2208200f490d2d2003410174220f20082008200f491b220841004e0d010c2d0b20024101102a000b0240024020030d002008102721070c010b200720032008102821070b2007450d05200821030b200720066a20096a220841386a200241386a290000370000200841306a200241306a290000370000200841286a200241286a290000370000200841206a200241206a2900003700000240200320046a41406a411f4b0d00200a41c0006a220a41206a2208200a490d2b2003410174220a20082008200a491b22084100480d2b0240024020030d002008102721070c010b200720032008102821070b2007450d06200821030b200720066a20096a220841d8006a200241d8006a290000370000200841d0006a200241d0006a290000370000200841c8006a200241c8006a290000370000200841c0006a200241c0006a290000370000200441a07f6a2104200941e0006a2109200241e0006a200d470d000b2001200336029c0b200120073602980b2001200620096a22023602a00b0b200141e8056a411020072002100302402003450d00200710290b0240200b450d00200c10290b200120113a00d807200141980b6a41086a22024200370300200142003703980b41b6c8c5004115200141980b6a1004200141e8056a41086a2002290300370300200120012903980b3703e805200141e8056a4110200141d8076a410110032001201336029c0b200141043a00980b41b8d6c5004100200141980b6a108801410810272203450d05200320163602042003200e3602002019201941ff017141024771450d110240024020140d002003200e41e0006a360200200141980b6a41186a2202200e41386a290000370300200141980b6a41106a2207200e41306a290000370300200141980b6a41086a2209200e41286a2900003703002001200e290020220537039805200120053703980b200e0d010b2003102941002102410821044108210f410021070c140b200141d8076a41186a2002290300370300200141d8076a41106a2007290300370300200141d8076a41086a2009290300370300200120012903980b3703d807200328020420032802006b41e0006e41016a2202ad42287e2205422088a70d072005a7220710272204450d04200420012903d80737030020044201370320200441186a200141d8076a41186a2213290300370300200441106a200141d8076a41106a2214290300370300200441086a200141d8076a41086a22152903003703000240200328020022072003280204470d00410121072004210f0c130b2003200741e0006a36020020014198056a41086a2218200741286a2900002205370300200141980b6a41186a2206200741386a290000370300200141980b6a41106a2208200741306a290000370300200141980b6a41086a220a200537030020012007290020220537039805200120053703980b4102210741c800210903402013200629030022053703002014200829030022263703002015200a290300222c370300200120012903980b222d3703d807200141f8046a41186a220c2005370300200141f8046a41106a220d2026370300200141f8046a41086a220f202c3703002001202d3703f80402400240024002402007417f6a2002460d00200221100c010b200328020420032802006b41e0006e20026a41016a22102002490d2c20024101742211201020102011491b2210ad42287e2205422088a70d2c2005a722114100480d2c0240024020020d002011102721040c010b2004200241286c2011102821040b2004450d010b200420096a221141606a220220012903f804370300200f2903002105200d2903002126200c290300212c20114201370300200241186a202c370300200241106a2026370300200241086a2005370300200328020022022003280204470d012004210f201021020c150b20114108102a000b2003200241e0006a3602002018200241286a29000022053703002006200241386a2900003703002008200241306a290000370300200a200537030020012002290020220537039805200120053703980b200941286a2109200741016a2107201021020c000b0b20064101102a000b20074101102a000b20084101102a000b20084101102a000b20074108102a000b41084104102a000b20024101102a000b1039000b20074101102a000b418f89c3004133104e000b20034101102a000b20024101102a000b418f89c3004133104e000b20072003103e000b418f89c3004133104e000b418f89c3004133104e000b419cb1c5001058000b200310290c020b200310290b200141b8056a41086a22034200370300200142003703b80541c6c4c500411b200141b8056a1004200141980b6a41086a2003290300370300200120012903b8053703980b200141003602d807200141980b6a4110200141d8076a100521030240024020012802d8072206417f460d002003450d00200120063602bc06200120033602b806200141d8076a200141b8066a104120012802d807220d450d14200141e0076a280200210920012802dc0721102006450d01200310290c010b4108210d41002109410021100b0240024020072009470d00200f200d460d01200741286c41286e22032007200720034b1b210c417f2106200f2103200d21090340200641016a2206200c4f0d02024020032009460d0020032009412010d0040d020b200941206a2108200341206a210a200341286a2103200941286a2109200a2903002008290300510d000b0b200141b8056a41086a22034200370300200142003703b8054199a7c1004117200141b8056a1004200141980b6a41086a2003290300370300200120012903b8053703980b200141003602d807200141980b6a4110200141d8076a1005210302400240024020012802d8072209417f460d002003450d00200142003703d807200141d8076a200320094108200941084922061b220410ce041a024020060d0020012903d8072105200142003703d807200141d8076a200320046a200920046b2209410820094108491b10ce041a200941074b0d020b418f89c3004133104e000b200120073602a00b2001200236029c0b200120043602980b200141980b6a42004200200510f6010c010b20012903d807212620031029200141980b6a4110100c200120073602a00b2001200236029c0b2001200f3602980b200141980b6a20054201202610f6010b2010450d01200d10290c010b02402010450d00200d10290b2002450d00200410290b410810272202450d10200220163602042002200e360200410810272203450d0f20032012200b41e0006c6a220f3602042003201236020020014198046a41c3c5c500410f10940120012903a00442002001280298041b220542017c222d2005540d0e200141b8056a41086a22074200370300200142003703b80541c3c5c500410f200141b8056a1004200141b8066a41086a22092007290300370300200120012903b8053703b8062001202d3703980b200141b8066a4110200141980b6a4108100320014184cac10036029c0b200120023602980b2001200141800a6a3602a00b200141d8056a200141980b6a104c200141980b6a41086a200141d8056a41086a280200360200200120012903d8053703980b20074200370300200142003703b80541d2c5c5004110200141b8056a100420092007290300370300200120012903b8053703b806200141103602dc072001200141b8066a3602d807200141980b6a200141d8076a102f0240200128029c0b450d0020012802980b10290b20014188046a41f5c5c500411010940120012903900421052001280288042102200141f8036a41e2c5c5004113109401024042002005420020021b2226200129038004420020012802f8031b22057d222c202c2026561b42eb02540d00034042002026427f200542eb027c222c202c2005541b22057d222c202c2026561b42ea02560d000b0b200141b8056a41086a22024200370300200142003703b80541e2c5c5004113200141b8056a1004200141b8066a41086a2002290300370300200120012903b8053703b806200120053703980b200141b8066a4110200141980b6a41081003202d42017c2205202d540d0d20024200370300200142003703b8054194c6c5004113200141b8056a100420014188066a41086a2002290300370300200120012903b80537038806200141003602980b20014188066a4110200141980b6a100521020240024020012802980b2207417f460d002002450d00200141f8086a2007412020074120491b22096a41004100412020096b2009411f4b1b10cd041a200141f8086a2002200910ce041a2007411f4d0d0e20014198056a41186a2207200141f8086a41186a29030037030020014198056a41106a2209200141f8086a41106a29030037030020014198056a41086a2204200141f8086a41086a290300370300200120012903f8083703980520021029200141d8076a41186a2007290300370300200141d8076a41106a2009290300370300200141d8076a41086a200429030037030020012001290398053703d8070c010b200141e0076a4200370300200141e8076a4200370300200141f0076a4200370300200142003703d8070b200141d8046a41186a200141d8076a41186a290300370300200141d8046a41106a200141d8076a41106a290300370300200141d8046a41086a200141d8076a41086a290300370300200120012903d8073703d804200141b8056a41086a22024200370300200142003703b80541a7c6c5004116200141b8056a100420014198056a41086a2002290300370300200120012903b80537039805200141003602980b20014198056a4110200141980b6a100521020240024020012802980b2207417f460d002002450d0020014188066a2007412020074120491b22096a41004100412020096b2009411f4b1b10cd041a20014188066a2002200910ce041a2007411f4d0d0d200141b8056a41186a220720014188066a41186a290300370300200141b8056a41106a220920014188066a41106a290300370300200141b8056a41086a220420014188066a41086a29030037030020012001290388063703b80520021029200141f8046a41186a2007290300370300200141f8046a41106a2009290300370300200141f8046a41086a2004290300370300200120012903b8053703f8040c010b20014180056a420037030020014188056a420037030020014190056a4200370300200142003703f8040b200141980b6a41186a200141d8046a41186a290300370300200141980b6a41106a200141d8046a41106a290300370300200141980b6a41086a2209200141d8046a41086a290300370300200141c80b6a200141f8046a41086a290300370300200141d00b6a200141f8046a41106a290300370300200141d80b6a200141f8046a41186a290300370300200120012903d8043703980b200120053703b80b200120012903f8043703c00b200141b8056a41186a22074200370300200141b8056a41106a22044200370300200141b8056a41086a22024200370300200142003703b805200141980b6a41c800200141b8056a1000200141f8086a41186a2007290300370300200141f8086a41106a2004290300370300200141f8086a41086a2002290300370300200120012903b8053703f80820024200370300200142003703b80541a7c6c5004116200141b8056a1004200141b8066a41086a22072002290300370300200120012903b8053703b806200141b8066a411041b3b4c3004120100320024200370300200142003703b8054194c6c5004113200141b8056a100420072002290300370300200120012903b8053703b806200141b8066a4110200141f8086a41201003200141e8056a41186a200141d8076a41186a2903002226370300200141e8056a41106a200141d8076a41106a290300222c370300200141e8056a41086a200141d8076a41086a290300222d370300200120012903d807222e3703e80520014188066a41186a202637030020014188066a41106a202c37030020014188066a41086a202d3703002001202e3703880620024200370300200142003703b8054185c6c500410f200141b8056a100420072002290300370300200120012903b8053703b806200141b8066a411020014188066a4120100320014184cac10036029c0b200120033602980b2001200141800a6a3602a00b200141800a6a200141980b6a104c200141e8036a41e2c5c500411310940120012903f003212620012802e803210420024200370300200142003703b8054194c6c5004113200141b8056a100420092002290300370300200120012903b8053703980b200141003602d807200141980b6a4110200141d8076a100521020240024020012802d8072203417f460d002002450d0020014198056a2003412020034120491b22076a41004100412020076b2007411f4b1b10cd041a20014198056a2002200710ce041a2003411f4d0d0c200141f8046a41186a220320014198056a41186a290300370300200141f8046a41106a220720014198056a41106a290300370300200141f8046a41086a220920014198056a41086a29030037030020012001290398053703f80420021029200141f8086a41186a2003290300370300200141f8086a41106a2007290300370300200141f8086a41086a2009290300370300200120012903f8043703f8080c010b20014180096a420037030020014188096a420037030020014190096a4200370300200142003703f8080b200141d8076a41086a200141f8086a41086a290300370300200141d8076a41106a200141f8086a41106a290300370300200141d8076a41186a200141f8086a41186a290300370300200120012903f8083703d80720012802800a210c20012802840a211020012802880a2107200141003602a00b200142013703980b410110272202450d09200142818080801037029c0b200120023602980b200241013a000020024101410910282202450d0820014289808080900137029c0b200120023602980b200220053700010240200128029c0b220920012802a00b22036b41074b0d00200341086a22062003490d1420094101742208200620062008491b22064100480d140240024020090d002006102721020c010b200220092006102821020b2002450d082001200636029c0b200120023602980b0b2001200341086a3602a00b200220036a427f2026420020041b220542eb027c222620262005541b3700000240200128029c0b220920012802a00b22036b41074b0d00200341086a22042003490d1420094101742206200420042006491b22044100480d140240024020090d002004102721020c010b200220092004102821020b2002450d072001200436029c0b200120023602980b0b2001200341086a3602a00b200220036a42eb02370000200120073602b806200141b8066a200141980b6a10300240024020070d00200128029c0b210920012802a00b21020c010b200c200741286c6a210d410020012802a00b220a6b2104200128029c0b2109410021020340200a20026a210602400240200920046a4120490d0020012802980b21070c010b200641206a22032006490d1620094101742207200320032007491b22034100480d160240024020090d002003102721070c010b20012802980b20092003102821070b2007450d082001200336029c0b200120073602980b200321090b2007200a6a20026a220841186a200c20026a220341186a290000370000200841106a200341106a290000370000200841086a200341086a2900003700002001200641206a220b3602a00b20082003290000370000200341206a29030021050240200920046a41606a41074b0d00200b41086a2208200b490d162009410174220b20082008200b491b22084100480d160240024020090d002008102721070c010b200720092008102821070b2007450d072001200836029c0b200120073602980b200821090b2001200641286a3602a00b2007200a6a20026a41206a2005370000200441586a2104200241286a2102200d200341286a470d000b200a20026a21020b02400240200920026b4120490d0020012802980b21030c010b200241206a22032002490d1420094101742207200320032007491b22074100480d140240024020090d002007102721030c010b20012802980b20092007102821030b2003450d042001200736029c0b200120033602980b0b200320026a220341086a200141d8076a41086a2903003700002001200241206a3602a00b200320012903d807370000200341106a200141d8076a41106a290300370000200341186a200141d8076a41186a290300370000200141c3066a20012802a00b360000200120012903980b3700bb06200141a40b6a200141bf066a290000370000200141c28289aa043600990b200141023a00980b200120012900b80637009d0b200141980b6a10970302402010450d00200c10290b410810272203450d02200320163602042003200e360200410810272207450d012007200f36020420072012360200200141d8036a41888dc300410d10940120012903e003210520012802d8032102200141b8056a41086a22094200370300200142003703b80541d9b0c0004111200141b8056a1004200141980b6a41086a2009290300370300200120012903b8053703980b20012005420020021b3703d807200141980b6a4110200141d8076a41081003200141d0036a4193c8c500411410b50120012802d403210220012802d0032109200141c8036a41d685c500411810b5012002410020091b21020240024020012802c8030d00200141b8056a41086a22094200370300200142003703b80541d685c5004118200141b8056a1004200141980b6a41086a2009290300370300200120012903b8053703980b200120023602d807200141980b6a4110200141d8076a410410030c010b200220012802cc036b4107490d00200141b8056a41086a22094200370300200142003703b80541d685c5004118200141b8056a1004200141980b6a41086a2009290300370300200120012903b8053703980b200120023602d807200141980b6a4110200141d8076a41041003200141c0036a4193c8c500411410b50120012802c403210220012802c0032109200141b8036a41d685c500411810b5012002410020091b2109024020012802b8030d002009109e010c010b20012802bc03220220094f0d0003402002109e012009200241016a2202470d000b0b20071029200310290240201d450d00201210290b0240201a45201c720d0020012802cc04450d00201a10290b0240201e450d00201b10290b2017450d00200e10290b024020004280ce18824200520d000240024041f586c500411f108a02220241ff01714102460d0020024101710d010b200010a503450d01200010a6031a0c010b200010a603450d00200010a5031a0b200141b0036a41e286c500411310b50120012802b403210220012802b0032103200141a8036a41c986c500411910b501024002400240024002402002410020031b220220012802ac03410020012802a8031b22034f0d00200141a40b6a210902400340200141980b6a200210a70320012802a00b22074112470d012003200241016a2202470d000c020b0b20012903980b2105200141b8066a200941940110ce041a200141800a6a200141b8066a41940110ce041a200141a80b6a22092007360200200120053703a00b200120023602980b200141ac0b6a200141800a6a41940110ce04210420052000510d012009103d0b4100212941082128410021070c010b200141f8086a41086a2209200141980b6a41086a290300370300200120012903980b3703f808200141d8076a200441940110ce041a200141b8066a41086a22042009290300370300200120012903f8083703b806200141980b6a200141d8076a41940110ce041a41a80110272228450d02202820012903b80637030020282007360210202841086a2004290300370300202841146a200141980b6a41940110ce041a0240200241016a22022003490d0041012107410121290c010b200141980b6a41106a210c200141980b6a41146a2106200141a40b6a210841012129410121070340200141980b6a200210a703024020012802a00b22094112470d002003200241016a2202470d010c020b20012903980b2105200141b8066a200841940110ce041a200141800a6a200141b8066a41940110ce041a200120093602a80b200120053703a00b200120023602980b2006200141800a6a41940110ce042104024020052000510d00200c103d0c020b20014188066a41086a220a200141980b6a41086a290300370300200120012903980b37038806200141d8076a200441940110ce041a20014198056a41086a220b200a290300370300200120012903880637039805200141980b6a200141d8076a41940110ce041a024020292007470d00202941016a22042029490d172029410174220a20042004200a491b2204ad42a8017e2205422088a70d172005a7220a4100480d170240024020290d00200a102721280c010b2028202941a8016c200a102821280b2028450d03200421290b2028200741a8016c6a2204200129039805370300200441086a200b290300370300200441106a2009360200200441146a200141980b6a41940110ce041a200741016a2107200241016a22022003490d000b0b2028200741a8016c6a2123024020070d002028211e0c140b200141b8066a41086a2127200141980b6a41086a2111200141980b6a4104722102200141c4066a21252028211e0340201e41106a2802002103201e2902082105201e2802002109200141980b6a201e41146a41940110ce041a201e41a8016a211e20034112460d14200141800a6a200141980b6a41940110ce041a200120033602c006200120053703b8062025200141800a6a41940110ce041a200141d8076a200910a80320012802d80721080240024020012802e00722030d00420021414200214242002143420021444200212e420021450c010b200341057421044200212e200821034200214542002143420021444200214142002142034020014198036a200310950120014198036a41086a2903002126200129039803210520022003290000370000200241086a200341086a290000370000200241106a200341106a290000370000200241186a200341186a290000370000200120093602980b20014190036a200141980b6a10a90320012d00900341017121070240024020012d00910322060d00200141d0026a20052026420a420010d40420012903d002222c2105200141d0026a41086a290300222d21260c010b200141f0026a202642002006ad222c420010d30420014180036a20054200202c420010d304200141e0026a420042002005420010d304427f20014180036a41086a290300222c20012903f00220012903e0027c7c222d20012903f80220012903e80284420052202d202c547222061b212d427f20012903800320061b212c0b200341206a21034200202d20071b20447c4200202c20071b224620437c2243204654ad7c2144202d420020071b20427c202c420020071b222c20417c2241202c54ad7c2142202620457c2005202e7c222e200554ad7c2145200441606a22040d000b0b024020012802dc07450d00200810290b200141d8076a200910a80320012802d807210c0240024020012802e00722030d00420021464200214742002148420021494200212d4200214a0c010b200341057421044200212d200c21034200214a42002148420021494200214642002147034020022003290000370000200241086a200341086a2207290000370000200241106a200341106a2206290000370000200241186a200341186a2208290000370000200120093602980b200141c8026a200141980b6a10a90320012d00c802210a20012d00c902210b200141980b6a41186a2008290000370300200141980b6a41106a200629000037030020112007290000370300200120032900003703980b200141a8026a2009200141980b6a200b411010aa03200141a8026a41186a290300204a7c20012903b8022205202d7c222d200554ad7c214a4200200141a8026a41086a2903002205200a41017122071b20497c420020012903a802222620071b222c20487c2248202c54ad7c21492005420020071b20477c2026420020071b220520467c2246200554ad7c2147200341206a2103200441606a22040d000b0b024020012802dc07450d00200c10290b20014198056a41086a22214200370300200142003703980541b18ac000411620014198056a1004200141b8056a41086a2210202129030037030020012001290398053703b805200141003602980b200141b8056a4110200141980b6a100521030240024020012802980b2207417f460d002003450d00200142003703a00b200142003703980b200141980b6a20032007411020074110491b10ce041a02402007410f4d0d002011290300210520012903980b2126200310290c020b418f89c3004133104e000b42002126420021050b02400240202d202e7c222c420288204a20457c202c202d54ad7c222d423e8684222e202c85202d4202882245202d8584500d00202e204584500d00410021030240034020014198026a202c202d200341046a41fe007110d204200341026a2103200129039802222e202c8520014198026a41086a2903002245202d8584500d01202e2045844200520d000b0b20014188026a202c202d200341fe007110d20420012903880220014188026a41086a29030084212e42002145024020030d00202e420052ad212e0c020b202e420052ad212e0340200141e8016a202c202d41002003417e6a2207200720034b1b220341ff007110d204200141f8016a202e420186224b420184224a2045420186202e423f88842245204a204510d304204b204a20012903f80120012903e80156200141f8016a41086a290300222e200141e8016a41086a290300224c56202e204c511b1b212e20030d000c020b0b42002145202c202d84420052ad212e0b0240024020264202882005423e8684222c2026852005420288222d20058584500d00202c202d84500d004100210302400340200141d8016a20262005200341046a41fe007110d204200341026a210320012903d801222c202685200141d8016a41086a290300222d20058584500d01202c202d844200520d000b0b200141c8016a20262005200341fe007110d20420012903c801200141c8016a41086a29030084212c4200212d024020030d00202c420052ad212c0c020b202c420052ad212c0340200141a8016a2026200541002003417e6a2207200720034b1b220341ff007110d204200141b8016a202c420186224b420184224a202d420186202c423f8884222d204a202d10d304204b204a20012903b80120012903a80156200141b8016a41086a290300222c200141a8016a41086a290300224c56202c204c511b1b212c20030d000c020b0b4200212d2026200584420052ad212c0b02400240024002400240202e20458450450d004100210c0c010b204920447c204820437c2226204854ad7c2148204720427c204620417c2205204654ad7c214602400240024020012d00d0070e03010200010b2005202656204620485620462048511b210c0c020b0340200141d8006a20262048202e204510d404202c2241202d2242844200510d04200141d8006a41086a290300212c2001290358212d200141c8006a200520462041204210d4044101210c202d2001290348224354202c200141c8006a41086a290300224a54202c204a5122031b0d0202402043202d54204a202c5420031b450d004100210c0c030b200141386a202d202c202e204510d304200141286a2043204a2041204210d304024020052001290328222c7d222d2046200141286a41086a2903007d2005202c54ad7d224a84500d002048200141386a41086a2903007d2143202620012903382205542103202620057d212c202e210520452146202d212e204a21452041212620422148202c20432003ad7d222d84500d030c010b0b4100210c0c010b03402045214a202e2141202c202d844200510d0220014188016a200520462041204a10d40420014198016a20262048202c202d10d4044101210c200129039801224220012903880122435420014198016a41086a290300222e20014188016a41086a290300224554202e20455122031b0d01024020432042542045202e5420031b450d004100210c0c020b200141f8006a2042202e202c202d10d304200141e8006a204320452041204a10d304024020052001290368222e7d22452046200141e8006a41086a2903007d2005202e54ad7d22428450450d004100210c0c020b2048200141f8006a41086a2903007d2143202620012903782205542103202620057d212e202c2105202d21462045212c2042212d20412126204a2148202e20432003ad7d2245844200520d000b0b200141980b6a200910a80320012802980b2122200128029c0b212420012802a00b2203450d022022200341057422156a2120202221030340200141f8086a41186a2216200341186a22072900002205370300200141f8086a41106a2217200341106a22042900002226370300200141f8086a41086a2218200341086a2206290000222c37030020012003290000222d3703f808200141d8076a41086a2208202c370300200141d8076a41106a220a2026370300200141d8076a41186a220b2005370300200141b8056a41186a22192007290000370300200141b8056a41106a221a2004290000370300201020062900003703002001202d3703d807200120032900003703b80520032900002105200241186a221b200729000037000020022005370000200241086a221c2006290000370000200241106a221d2004290000370000200120093602980b200141206a200141980b6a10a903410221070240200c20012d0020410171220445734101470d0020012d0021211f20014188066a41186a200b29030037030020014188066a41106a200a29030037030020014188066a41086a2008290300370300200120012903d80737038806200421070b200141e8056a41086a221220014188066a41086a220d290300370300200141e8056a41106a221320014188066a41106a220e290300370300200141e8056a41186a221420014188066a41186a220f29030037030020012001290388063703e8050240024020074102460d00200341206a21030c010b200341206a2103201541606a22150d010c040b0b0340200141f8046a41086a20122903002205370300200141f8046a41106a20132903002226370300200141f8046a41186a2014290300222c370300200120012903e805222d3703f804200141980b6a41186a202c370300200141980b6a41106a2026370300201120053703002001202d3703980b200142e4cab5fbb6ccdcb0e3003703d804200141d8046a200141980b6a201f411874411875410274419886c5006a3502004280af1a7e20007c10a60120032020460d0303402016200341186a220729000022053703002017200341106a220429000022263703002018200341086a2206290000222c37030020012003290000222d3703f80820192007290000370300201a2004290000370300201020062900003703002003290000212e2008202c370300200a2026370300200b20053703002001202e3703b8052001202d3703d807200120093602980b20062900002105200429000021262003290000212c201b2007290000370000201d2026370000201c20053700002002202c370000200141186a200141980b6a10a903410221070240200c20012d0018410171220445734101470d0020012d0019211f200f200b290300370300200e200a290300370300200d2008290300370300200120012903d80737038806200421070b2012200d2903003703002013200e2903003703002014200f29030037030020012001290388063703e805024020074102470d002020200341206a2203470d010c050b0b200341206a21030c000b0b41c4a7c1001058000b41c4a7c1001058000b02402024450d00202210290b200910ab0302400240200c0d00200141053a00a00b200141053a00980b200120093602a40b41b8d6c5004100200141980b6a10880120214200370300200142003703980541e286c500411320014198056a10042010202129030037030020012001290398053703b8052001200941016a3602980b200141b8056a4110200141980b6a410410032027103d0c010b200120093602a40b200141043a00a00b200141053a00980b41b8d6c5004100200141980b6a108801024020012903c8072205500d00200141d8076a200141b8066a41a00110ce041a20014188066a200520007c220510ac03200141980b6a200141d8076a41a00110ce041a200141f8086a201141880110ce041a02400240024002400240200128028c0622062001280290062203460d0020012802880621040c010b200341016a22072003490d1b20034101742204200720072004491b2206ad4290017e2226422088a70d1b2026a722074100480d1b0240024020030d002007102721040c010b20012802880620034190016c2007102821040b2004450d012001200636028c0620012004360288060b200420034190016c220c6a200141f8086a41880110ce044188016a20093602002001200341016a220736029006411710272203450d012003410f6a41002900ffd143370000200341086a41002900f8d143370000200341002900f0d14337000020034117412e10282203450d0220032005370017200141f8086a41186a22084200370300200141f8086a41106a220a4200370300200141f8086a41086a220b4200370300200142003703f8082003411f200141f8086a1000200141b8056a41186a2008290300370300200141b8056a41106a200a2903003703002010200b290300370300200120012903f8083703b8052001412036029c0b2001200141b8056a3602980b20014188066a200141980b6a10312003102902402007450d00200c4190016a2107200421030340024020032802004112460d002003103d0b20034190016a2103200741f07e6a22070d000b0b02402006450d00200410290b20214200370300200142003703980541e286c500411320014198056a10042010202129030037030020012001290398053703b8052001200941016a3602980b200141b8056a4110200141980b6a410410030c040b20074108102a000b41174101102a000b412e4101102a000b200141980b6a202741880110ce041a200141003b01d807200141106a200141980b6a200141d8076a10ad0220012001280210453a00a10b200141073a00a00b200141053a00980b200120093602a40b41b8d6c5004100200141980b6a10880120214200370300200142003703980541e286c500411320014198056a10042010202129030037030020012001290398053703b8052001200941016a3602980b200141b8056a4110200141980b6a410410030b201e2023470d000b2023211e0c130b200a4108102a000b41a8014108102a000b41084104102a000b41084104102a000b20074101102a000b20084101102a000b20034101102a000b20044101102a000b20064101102a000b41094101102a000b41014101102a000b418f89c3004133104e000b418f89c3004133104e000b418f89c3004133104e000b41eab3c30041c900104e000b41eab3c30041c900104e000b41084104102a000b41084104102a000b418f89c3004133104e000b0240201e2023460d00200141980b6a41106a2109200141980b6a41146a21040340200141b8056a41086a2203201e41086a2903003703002001201e2903003703b805201e41106a2802002102200141980b6a201e41146a41940110ce041a20024112460d01200141b8066a41086a22072003290300370300200120012903b8053703b806200141d8076a200141980b6a41940110ce041a200141980b6a41086a2007290300370300200120012903b8063703980b200120023602a80b2004200141d8076a41940110ce041a2009103d201e41a8016a221e2023470d000b0b02402029450d00202810290b02400240411710272202450d002002410f6a41002900ffd143370000200241086a41002900f8d143370000200241002900f0d143370000024020024117412e10282202450d0020022000370017200141f8086a41186a22034200370300200141f8086a41106a22074200370300200141f8086a41086a22094200370300200142003703f8082002411f200141f8086a1000200141b8056a41186a2003290300370300200141b8056a41106a2007290300370300200141b8056a41086a2009290300370300200120012903f8083703b805200141003602980b200141b8056a4120200141980b6a1005210702400240024020012802980b2203417f460d00200120033602dc07200120073602d807200141980b6a200141d8076a103b20012802980b22080d01418f89c3004133104e000b4100210a41082108410021030c010b200129029c0b210502402003450d00200710290b200141b8056a4120100c2005422088a721032005a7210a0b20021029200820034190016c22026a2109024020030d00200821020c030b200241f07e6a2107200141980b6a410472210620082102034020022802002103200141d8076a200241046a41840110ce041a0240024020034113460d00200141980b6a200141d8076a41840110ce041a024020034112470d0020070d02200921020c060b20024188016a2802002104200141b8066a200141980b6a41840110ce041a200120033602980b2006200141b8066a41840110ce041a200141003b01d807200141086a200141980b6a200141d8076a10ad0220012802082103200120043602a40b20012003453a00a10b200141073a00a00b200141053a00980b41b8d6c5004100200141980b6a10880120070d01200921020c050b20024190016a21020c040b20024190016a2102200741f07e6a21070c000b0b412e4101102a000b41174101102a000b024020022009460d00200141980b6a4104722107034020022802002103200141980b6a200241046a418c0110ce041a20034113460d01200141d8076a200141980b6a418c0110ce041a200120033602980b2007200141d8076a418c0110ce041a024020034112460d00200141980b6a103d0b20024190016a22022009470d000b0b0240200a450d00200810290b200010b401200141c00c6a24000f0b102b000b418f89c3004133104e000bf31605027f017e067f037e017f230041c0086b22042400200441c0056a200141a00210ce041a200441e0036a200441c0056a1086024101210502400240024002400240024002400240024002400240024002400240024020042802e0034101460d00200441e0036a41086a290300210620044190026a200441e0036a41106a41d00110ce041a20042006370338200441386a41086a20044190026a41d00110ce041a024020032802002201450d00200341086a28020021072003280204210841002109200441003602c00541ff88c3004110200441c0056a10052105024020042802c005220a417f460d002005450d00200441003602c005200441c0056a2005200a4104200a4104491b10ce041a200a41034d0d0520042802c0052109200510290b411410272205450d05200541106a4100280083ce45360000200541086a41002900fbcd45370000200541002900f3cd453700002005411441281028220a450d06200a2009360014200441e0036a41186a22054200370300200441e0036a41106a22094200370300200441e0036a41086a220b4200370300200442003703e003200a4118200441e0036a100020044190026a41186a200529030037030020044190026a41106a200929030037030020044190026a41086a200b290300370300200420042903e00337039002200441003602c805200442013703c005200420073602e003200441e0036a200441c0056a10300240024020042802c405220b20042802c80522096b2007490d0020042802c00521050c010b200920076a22052009490d09200b410174220c20052005200c491b220c4100480d0902400240200b0d00200c102721050c010b20042802c005200b200c102821050b2005450d082004200c3602c405200420053602c005200c210b0b200520096a2001200710ce041a20044190026a41202005200920076a10030240200b450d00200510290b200a1029410021052008450d00200110290b200441306a200441386a41d0006a10ac0220042d003421092004280230210a200441c0056a200441386a41d80110ce041a41002107024002400240024002400240024002400240024020042903e0054202510d00200441a0086a41186a200441c0056a41186a290300370300200441a0086a41106a200441c0056a41106a290300370300200441a0086a41086a200441c0056a41086a290300370300200420042903c0053703a00820044188066a290300210d20044180066a290300210e200441f8056a2903002106411310272207450d122007410f6a41002800d68d43360000200741086a41002900cf8d43370000200741002900c78d4337000020074113413310282207450d13200720042903a0083700132007412b6a200441b8086a290300370000200741236a200441b0086a2903003700002007411b6a200441a8086a290300370000200441206a200741331089022004290328210f2004280220210b20071029200f4200200b1b220f2006520d04411310272207450d142007410f6a41002800d68d43360000200741086a41002900cf8d43370000200741002900c78d4337000020074113413310282207450d15200720042903a0083700132007412b6a200441a0086a41186a290300370000200741236a200441a0086a41106a2903003700002007411b6a200441a0086a41086a290300370000200441e0036a41186a220b4200370300200441e0036a41106a22084200370300200441e0036a41086a220c4200370300200442003703e00320074133200441e0036a100020044190026a41186a200b29030037030020044190026a41106a200829030037030020044190026a41086a200c290300370300200420042903e003370390022004200642017c3703e00320044190026a4120200441e0036a4108100320071029200441186a41c1cdc500411710b501417f200428021c410020042802181b220720026a220b200b2007491b220b418080c002418080f001200941017122071b4b0d02200441e0036a41086a22094200370300200442003703e00341c1cdc5004117200441e0036a100420044190026a41086a22102009290300370300200420042903e003370390022004200b3602e00320044190026a4110200441e0036a41041003200441106a41a7cdc500411a10b501417f2004280214410020042802101b2208418094ebdc034180afd0e50220071b220b200a200b200a491b6a220c200c2008491b2208200b4b0d0220094200370300200442003703e00341a7cdc500411a200441e0036a100420102009290300370300200420042903e00337039002200420083602e00320044190026a4110200441e0036a41041003200441e0036a200e200d200441a0086a200a2007200210960120042d00e0034101460d012004418c046a280200210920044188046a280200210820044184046a280200210b200441fc036a280200210c200441f8036a2802002102024020044180046a2802002207450d002007410c6c210a2002210703400240200741046a280200450d00200728020010290b2007410c6a2107200a41746a220a0d000b0b0240200c450d00200210290b02402009450d002009410c6c210a200b210703400240200741046a280200450d00200728020010290b2007410c6a2107200a41746a220a0d000b0b02402008450d00200b10290b200441e0076a41086a200441a0086a41086a290300370300200441e0076a41106a200441a0086a41106a290300370300200441e0076a41186a200441a0086a41186a290300370300200420042903a0083703e007410121070b200441e0036a200441c0056a41d0006a41880110ce041a200441a0086a41186a2209200441e0076a41186a290300370300200441a0086a41106a220b200441e0076a41106a290300370300200441a0086a41086a2202200441e0076a41086a290300370300200420042903e0073703a0084102210a02402007450d0020044180086a41186a200929030037030020044180086a41106a200b29030037030020044180086a41086a2002290300370300200420042903a008370380084101210a0b2004419a026a20044180086a41086a290300370100200441a2026a20044180086a41106a290300370100200441aa026a20044180086a41186a2903003701002004200a3a009102200420042903800837019202200441003a009002200441086a200441e0036a20044190026a10ad02200428020c21092004200428020822074100473a00c105200441003a00c00541b8d6c5004100200441c0056a108801200441003602c00541ff88c3004110200441c0056a1005210b20042802c005220a417f470d074101210a0c080b20042d00e103210a20044190066a103d410321070240200a0e0706020606040500060b410021070c050b20044190066a103d0b410421070c030b20044190066a103d200f2006580d010b410121070c010b410221070b20002007360204200041013602002000410c6a4100360200200041086a41b8d6c50036020020054521000c030b200441003602c005200441c0056a200b200a4104200a4104491b10ce041a200a41034d0d0d20042802c005210a200b1029200a41016a210a0b2004200a3602c00541ff88c3004110200441c0056a410410030240024020070d004100210720004100360204200041086a20093602000c010b02402009411b470d000240200741dbeac200460d00200741dbeac200411b10d0040d010b20004104360204410121070c010b20002007360204200041086a2009360200410021070b200020073602002001450d0e20050d020c0e0b200041086a20042902e4033702002000420137020020032802002101410021000b20000d0c20010d0b0c0c0b200341046a280200450d0b200110290c0b0b418f89c3004133104e000b41144101102a000b41284101102a000b200c4101102a000b102b000b41134101102a000b41334101102a000b41134101102a000b41334101102a000b418f89c3004133104e000b200341046a280200450d00200110290b200441c0086a24000b950901087f230041106b2202240020024100360208200242013703002002410436020c2002410c6a20021030024002400240024002400240024002400240024020022802042203200228020822046b4104490d00200441046a2105200228020021030c010b200441046a22052004490d0820034101742206200520052006491b22064100480d080240024020030d002006102721030c010b200228020020032006102821030b2003450d0120022006360204200220033602000b20022005360208200320046a41eede91ab063600002002410e36020c2002410c6a200210300240024020022802042203200228020822066b410e490d002006410e6a2105200228020021040c010b2006410e6a22052006490d0820034101742204200520052004491b22074100480d080240024020030d002007102721040c010b200228020020032007102821040b2004450d022002200736020420022004360200200721030b20022005360208200420066a220641002900a8fb41370000200641066a41002900aefb413700000240200320056b41034b0d00200541046a22062005490d0820034101742207200620062007491b22064100480d080240024020030d002006102721040c010b200420032006102821040b2004450d0320022006360204200220043602000b2002200541046a360208200420056a410a360000024020022802042203200228020822056b41034b0d00200541046a22062005490d0820034101742207200620062007491b22064100480d080240024020030d002006102721040c010b200420032006102821040b2004450d0420022006360204200220043602000b2002200541046a360208200420056a41fb003600000240024020022802042205200228020822046b4104490d00200228020021050c010b200441046a22032004490d0820054101742206200320032006491b22034100480d080240024020050d002003102721050c010b200228020020052003102821050b2005450d0520022003360204200220053602000b2002200441046a360208200520046a41fd003600002002410836020c2002410c6a2002103041b8fbc10021072002280204210320022802082106034002400240200320066b4108490d00200641086a2104200228020021050c010b200641086a22042006490d0920034101742205200420042005491b22084100480d090240024020030d002008102721050c010b200228020020032008102821050b2005450d072002200836020420022005360200200821030b20022004360208200520066a2007290000370000200741086a28020021080240200320046b41034b0d00200441046a22062004490d0920034101742209200620062009491b22064100480d090240024020030d002006102721050c010b200520032006102821050b2005450d082002200636020420022005360200200621030b2002200441046a2206360208200520046a20083600002007410c6a22074198fcc100470d000b200241106a24002006ad4220862005ad840f0b20064101102a000b20074101102a000b20064101102a000b20064101102a000b20034101102a000b20084101102a000b20064101102a000b102b000bc91b05017f017e037f017e057f230041800a6b22022400024002402001450d00200220003602100c010b200241b8d6c5003602100b20022001360214200241e0076a200241106a108e02200241f0076a280200210120022903e007210320022802e807210420022802ec072105200241b0046a200241f4076a41e40010ce041a024002402004450d0020024180036a200241b0046a41e40010ce041a200241e0076a200241106a104820022802e00722000d0102402001450d00200141246c21002004210103400240024020012d0000220641034b0d0002400240024020060e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b2005450d00200410290b200241f4076a4101360200200242013702e407200241cc81c2003602e007200241023602b404200241c481c2003602b0042002200241b0046a3602f007200241e0076a41d481c2001057000b20022902e40721072002411c6a20024180036a41e40010ce041a20024190016a20013602002002418c016a20053602002002200436028801200220033703800120024194016a2002411c6a41e40010ce042101200241fc016a2007370200200220003602f80120024180016a10b902024002400240024002400240024002402002290380012203500d00200241e0076a2003427f7c108702200241e0076a2001412010d0040d004100210820022802f80121000240024020024180026a280200220141a0026c0d00410421094100210a0c010b2001410c6c220610272209450d042001210a0b02402001450d00200141a0026c2106200141057441606a2104200921010340200220003602b004200241e0076a200241b0046a10bf02200141086a200241e0076a41086a280200360200200120022903e0073702002001410c6a2101200041a0026a2100200641e07d6a22060d000b200441057641016a21080b41002106024002402008410c6c22010d004104210b4100210c0c010b2001410c6e220c41037422004100480d0220001027220b450d030b0240200920016a22052009460d0041002106200b210120092100034020002802002104200141046a200041086a28020036020020012004360200200141086a2101200641016a21062000410c6a22002005470d000b0b200241e0076a200b200610c0020240200c450d00200b10290b02402008450d002008410c6c21002009210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b0b0240200a450d00200910290b0240200241d4016a2201200241e0076a412010d004450d004198cec500410e1010200141201016200241e0076a412010160b02402001200241e0076a412010d0040d0020022802fc01210920022802f8012105200228028002210620024188026a20024180016a41f80010ce041a2005200641a0026c6a210020022903880221072005210102402006450d00200241b0046a41f0006a210420052101024002400340200241f8066a200141e80010ce041a200141e8006a290300210320024180036a200141f0006a41b00110ce041a20034203510d02200241b0046a200241f8066a41e80010ce041a2002200337039805200420024180036a41b00110ce041a2002200241b0046a3602d006200241e0076a200241d0066a10bf0220022802e8072106024020022802e407450d0020022802e00710290b200241e0076a200241b0046a41a00210ce041a200241003602e006200241d0066a200241e0076a2006200241e0066a10bc0220022802d0064101460d01024020022802d4062206450d00200620022802d80610100b200141a0026a22012000470d000b200021010c020b024020022802d4060e050a00000b090a0b4190fdc1001058000b200141a0026a21010b20012000460d05200241f8086a2106200241e0076a41f0006a2104034020024180036a200141e80010ce041a200141e8006a2903002103200241e0076a200141f0006a41b00110ce041a20034203510d06200241f8066a20024180036a41e80010ce041a200241b0046a200241e0076a41b00110ce041a200241e0076a200241f8066a41e80010ce041a200220033703c8082004200241b0046a41b00110ce041a2006103d200141a0026a22012000470d000c060b0b41b0fcc1001058000b4198fcc1001058000b102b000b20004104102a000b20064104102a000b02402009450d00200510290b200241086a41ff88c300411010c102200228020c210120022802082100200241e0076a41086a22064200370300200242003703e0074192cdc5004115200241e0076a1004200241b0046a41086a2006290300370300200220022903e0073703b00420022001410020001b3602e007200241b0046a4110200241e0076a41041003200710c202200241e0076a10c302200220024188026a41106a28020022093602f00620022802900221042002200241e0076a41106a28020022013602f406024020092001470d0002402009450d0020022802e807210541002106034002400240024002400240024002400240200420066a22012d00002208200520066a22002d0000470d000240024002400240024020080e050400010203040b024020042005460d00200141016a280000200041016a280000470d050b200141106a2802002208200041106a280200470d04200141086a280200220b200041086a280200220a460d09200b200a200810d0040d040c090b024020042005460d00200141016a280000200041016a280000470d040b200141106a2802002208200041106a280200470d03200141086a280200220b200041086a280200220a460d07200b200a200810d0040d030c070b024020042005460d00200141016a280000200041016a280000470d030b200141106a2802002208200041106a280200470d02200141086a280200220b200041086a280200220a460d05200b200a200810d0040d020c050b2001410c6a28020022082000410c6a280200470d01200141046a280200220b200041046a280200220a460d03200b200a200810d0040d010c030b20042005460d07200141016a200041016a412010d004450d010b41a481c00041141010200241b0046a2001104f20022802b004220820022802b8041016024020022802b404450d00200810290b200241b0046a2000104f20022802b004220820022802b8041016024020022802b404450d00200810290b20012d000020002d00002208470d05024020080e050005040302000b20042005460d060b200141016a200041016a412010d0040d040c050b2001410c6a28020022082000410c6a280200470d03200141046a2802002201200041046a2802002200460d0420012000200810d004450d040c030b024020042005460d00200141016a280000200041016a280000470d030b200141106a2802002208200041106a280200470d02200141086a2802002201200041086a2802002200460d0320012000200810d0040d020c030b024020042005460d00200141016a280000200041016a280000470d020b200141106a2802002208200041106a280200470d01200141086a2802002201200041086a2802002200460d0220012000200810d0040d010c020b024020042005460d00200141016a280000200041016a280000470d010b200141106a2802002208200041106a280200470d00200141086a2802002201200041086a2802002200460d0120012000200810d004450d010b41c0fdc1001058000b200641246a21062009417f6a22090d000b0b024020024188026a41346a2201200241e0076a41346a2200412010d004450d004198cec500410e10102001412010162000412010160b024020012000412010d004450d0041d8fdc1001058000b024020022802f0072200450d0020022802e8072101200041246c210003400240024020012d0000220641034b0d0002400240024020060e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b0240200241ec076a280200450d0020022802e80710290b02402002280298022200450d002002280290022101200041246c210003400240024020012d0000220641034b0d0002400240024020060e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b024020024194026a280200450d0020022802900210290b200241800a6a240042010f0b20024180036a41146a41033602002002418c036a411d360200200241f8066a41146a41033602002002200241f0066a3602e0062002200241f4066a3602d006200241b0046a41146a4100360200200242033702fc0620024190d1c5003602f8062002411d36028403200241b8d6c5003602c004200242013702b404200241a8fdc1003602b004200220024180036a360288072002200241b0046a360290032002200241d0066a360288032002200241e0066a36028003200241f8066a41b0fdc1001057000b41f8fcc1001058000b41e0fcc1001058000b41c8fcc1001058000bb51003067f027e067f230041206b2202240002400240024002400240024002400240024002400240024002400240024041a20210272203450d00200242a20237020420022003360200200341003b000020024102360208200228020021042002280204210502400240200128020022032903684202520d00024020054102470d0020044102410410282204450d0420024104360204200220043602000b200441023a00022002200228020841016a3602080c010b024020054102470d0020044102410410282204450d0420024104360204200220043602000b20044182013a00022002200228020841016a3602082003200210510240024020022802042206200228020822046b41c000490d00200441c0006a2101200228020021050c010b200441c0006a22012004490d1020064101742205200120012005491b22074100480d100240024020060d002007102721050c010b200228020020062007102821050b2005450d052002200736020420022005360200200721060b20022001360208200520046a22042003290024370000200441386a200341dc006a290000370000200441306a200341d4006a290000370000200441286a200341cc006a290000370000200441206a200341c4006a290000370000200441186a2003413c6a290000370000200441106a200341346a290000370000200441086a2003412c6a2900003700000240024020032903684201510d00024020062001470d00200141016a22042001490d1220014101742206200420042006491b22044100480d120240024020010d002004102721050c010b200520012004102821050b2005450d0820022004360204200220053602000b2002200141016a360208200520016a41003a00000c010b200341f8006a29030020032903702208420c882209420120094201561b8021090240200620016b41014b0d00200141026a22042001490d1120064101742207200420042007491b22044100480d110240024020060d002004102721050c010b200520062004102821050b2005450d0820022004360204200220053602000b2002200141026a360208200520016a2009a741047420087aa7417f6a22044101200441014b1b2204410f2004410f491b723b00000b20034180016a20021054200220034188016a360210200241106a200210590b20034198016a2002103220022802082103200241003602182002420137031020022003417e6a36021c2002411c6a200241106a10302002280208220441014d0d0620022802182105200228021021062002280214210a20024100360208200228020021030240024002402004417e6a2207450d004102210b2005450d0e200320062d00003a00004101210c2002200228020841016a36020820054101460d0e200620056a210d200320062d00013a00012002200228020841016a3602084102210b200641026a21014100210e2005417e6a2203450d0c2002280204220b20046b2003490d01200228020021040c020b0240024002402002280204220420054f0d0020044101742201200520052001491b22014100480d130240024020040d002001102721030c010b200320042001102821030b2003450d0c20022001360204200220033602002002280208210b0c010b4100210b2005450d010b2003200b6a220420062d00003a0000024020054101470d00200b41016a210b0c010b2005417f6a2101200641016a2103200441016a21040340200420032d00003a0000200441016a2104200341016a21032001417f6a22010d000b200b20056a210b0b2002200b3602084102210b0c0c0b200420036a220c2004490d0f200b4101742204200c200c2004491b220c4100480d0f02400240200b0d00200c102721040c010b2002280200200b200c102821040b2004450d092002200c360204200220043602000b200420056a200441026a200710cf041a024020052002280208220b460d002002280200200b6a2104200521030340024020034102470d002005210b0c0d0b200420012d00003a00002002200228020841016a360208200441016a2104200141016a2101200b2003417f6a2203470d000b200d20016b22030d004101210c2005210b0c0a0b20034100480d0e024020031027220c450d002005210b2003210e0c0a0b20034101102a000b41a2024101102a000b41044101102a000b41044101102a000b20074101102a000b20044101102a000b20044101102a000b419cb1c5001058000b20014101102a000b200c4101102a000b0240200d2001460d00200c20012d00003a00004101210f0240200141016a2203200d460d00200c41016a2104200520016b21010340200420032d00003a0000200441016a2104200d200341016a2203470d000b200620016a220f450d010b200c200f6a21050240024020022802042203200b20076a22046b200f490d00200228020021030c010b2004200f6a22012004490d0620034101742204200120012004491b22044100480d060240024020030d002004102721030c010b200228020020032004102821030b2003450d0520022004360204200220033602000b2003200f200b6a220d6a2003200b6a200710cf041a0240200d20022802082203460d00200228020020036a2104200f200b6a20036b2101200c2103034020052003460d01200420032d00003a00002002200228020841016a360208200341016a2103200441016a21042001417f6a22010d000b0b200d210b0b200e450d00200c10290b2007450d010b0240200b20022802082203460d002002280200220420036a2004200b6a200710cf041a0b2002200320076a3602080b0240200a450d00200610290b20002002290300370200200041086a200241086a280200360200200241206a24000f0b20044101102a000b102b000bd203010b7f230041206b22032400024002400240024020020d00410421040c010b2002410274220510272204450d010b0240200120024103746a22062001470d004101210741002108410021090c020b2002410374210a200141046a21052004210b0340200b2005280200360200200541086a2105200b41046a210b200a41786a220a0d000b200620016b41786a41037641016a210841012107410021094100210503402001280200210c02400240200920056b200141046a280200220b490d00200b20056a210a0c010b02402005200b6a220a2005490d002009410174220d200a200a200d491b220d4100480d000240024020090d00200d102721070c010b20072009200d102821070b02402007450d00200d21090c020b200d4101102a000b102b000b200720056a200c200b10ce041a200a2105200141086a22012006460d020c000b0b20054104102a000b200341186a22054200370300200341106a22014200370300200341086a220b42003703002003420037030020072004200820031021200041186a2005290300370000200041106a2001290300370000200041086a200b2903003700002000200329030037000002402009450d00200710290b02402002450d00200410290b200341206a24000b940101047f230041106b22032400410021042003410036020c200120022003410c6a10052105024002400240200328020c2206417f470d000c010b20034100360208200341086a20052006410420064104491b10ce041a200641034d0d01200328020821062005102920012002100c410121040b2000200436020020002006360204200341106a24000f0b418f89c3004133104e000bb15108067f027e027f017e077f027e027f037e230041a0046b2201240020014190036a41086a22024200370300200142003703900341e887c500411120014190036a1004200141b0036a41086a200229030037030020012001290390033703b003200141b0036a4110100c0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200042c0f000824200520d00200141b0036a109701411410272203450d09200341106a41002800bb8c40360000200341086a41002900b38c40370000200341002900ab8c4037000020034114413410282203450d08200320012903b0033700142003412c6a200141c8036a2204290300370000200341246a200141b0036a41106a22052903003700002003411c6a200141b0036a41086a220629030037000020014188016a2003413410840120014188016a41106a2903002107200129039001210820012802880121092003102920012007420020091b22073703a80120012008420020091b22083703a0012004200737030020052008370300200641013a00002001410a3a00b00341b8d6c5004100200141b0036a108801200141003a00b701200142003703c001200142003703b801200141b0026a41086a22034200370300200142003703b002418486c5004112200141b0026a100420014190036a41086a2003290300370300200120012903b00237039003200141003602b00320014190036a4110200141b0036a100521030240024020012802b0032209417f460d002003450d00200120093602cc01200120033602c801200141b0036a200141c8016a104520012802b003220a450d0920012902b403210b2009450d01200310290c010b4104210a4200210b0b4100210c0240200b422088a72209450d00200141b9036a210d200141f0026a210e200141b0026a41206a210f200141c8016a41086a2110200141e8036a2111410021124100210c41002103024003400240024002400240200c450d00200a20034102746a2104200a200320126a4102746a21050340200320094f0d02200141c8016a2004280200220610f20120012903c8014201520d04200141b0026a201041e00010ce041a20012903a001221320012903b002221454200141a0016a41086a2903002208200141b0026a41086a29030022075420082007511b450d03200141013a00b7010240201220036a220620094f0d0020052004280200360200200441046a2104200541046a2105200341016a22032009490d010c070b0b419481c000200620091037000b200a20034102746a21040340200320094f0d01200141c8016a2004280200220610f20120012903c8014201520d03200141b0026a201041e00010ce041a20012903a001221320012903b00222145a200141a0016a41086a2903002208200141b0026a41086a29030022075a20082007511b0d02200441046a2104200141013a00b701200341016a22032009490d000b4100210c0c050b41b880c000200320091037000b2001201320147d3703a0012001200820077d2013201454ad7d3703a801411210272204450d05200441106a41002f00c0a7413b0000200441086a41002900b8a741370000200441002900b0a74137000020044112412410282204450d0620042006360012200141b0036a41186a22054200370300200141b0036a41106a22154200370300200141b0036a41086a22164200370300200142003703b00320044116200141b0036a100020014190036a41186a200529030037030020014190036a41106a201529030037030020014190036a41086a2016290300370300200120012903b0033703900320014190036a4120100c20041029200f20012903c002200141b0026a41186a29030010ad01200141f8006a200e20142007108301200141b8016a41086a2204427f20042903002208200141f8006a41086a2903007c20012903b801221320012903787c22172013542204ad7c22132004201320085420132008511b22041b3703002001427f201720041b3703b80120112007370300200d200e290000370000200d41086a200e41086a290000370000200d41106a200e41106a290000370000200d41186a200e41186a290000370000200120143703e003200141023a00b8032001410a3a00b003200120063602dc0341b8d6c5004100200141b0036a1088010b2012417f6a2112200c41016a210c200341016a22032009490d000b0b200c450d00200320094f0d00200a20034102746a2204200c4102746b2004200920036b41027410cf041a0b200141b0026a41086a22034200370300200142003703b002418486c5004112200141b0026a100420014190036a41086a2003290300370300200120012903b00237039003200141003602b803200142013703b00320012009200c6b22033602c801200141c8016a200141b0036a10300240024020030d0020012802b803210920012802b403210620012802b00321040c010b2009410274200c4102746b211020012802b403210620012802b8032103200a210503402005280200210c02400240200620036b4104490d00200341046a210920012802b00321040c010b200341046a22092003490d1820064101742204200920092004491b22124100480d180240024020060d002012102721040c010b20012802b00320062012102821040b2004450d06200120123602b403200120043602b003201221060b200541046a2105200120093602b803200420036a200c360000200921032010417c6a22100d000b0b20014190036a411020042009100302402006450d00200410290b0240200ba7450d00200a10290b024020012d00b7010d0042002107200141e8006a20012903a0012208200141a0016a41086a2203290300221442c0843d420010d404200141d8006a20012903682213200141e8006a41086a290300220b42c0fb42427f10d304200141c8006a2013200b42a0c21e420010d304200320142014200141c8006a41086a29030020012903482213200820012903587c42018842ffffffff0f837c220b201354ad7c2213200b200856201320145620132014511b22091b22137d20082008200b20091b221454ad7d3703002001200820147d3703a001200141b0026a41086a22034200370300200142003703b00241b18ac0004116200141b0026a100420014190036a41086a2003290300370300200120012903b00237039003200141003602b00320014190036a4110200141b0036a100521030240024020012802b0032209417f470d0042002107420021080c010b024020030d00420021080c010b200142003703b803200142003703b003200141b0036a20032009411020094110491b10ce041a2009410f4d0d06200141b8036a290300210820012903b0032107200310290b200141b0026a41086a22034200370300200142003703b00241b18ac0004116200141b0026a100420014190036a41086a2003290300370300200120012903b00237039003200120073703b003200120083703b80320014190036a4110200141b0036a41101003200141b8016a41086a2203427f2003290300220b20082013200720147d200756200820137d2007201454ad7d221720085620172008511b22031b7c20012903b80122082007201420031b7c22172008542203ad7c220720032007200b542007200b511b22031b3703002001427f201720031b3703b801200141c8036a2013370300200141b0036a41106a2014370300200141b0036a41086a41033a00002001410a3a00b00341b8d6c5004100200141b0036a1088010b200141b0036a109701200141c8016a200141b0036a20012903b8012207200141b8016a41086a29030022084102109001024002400240024020012802c8010d00200141c8016a41106a290300211320012903d0012114200141306a41b18ac0004116108601200820137d2007201454ad7d201320087d2014200754ad7d20142007582013200858201320085122031b22091b2118200720147d201420077d20091b2119200141306a41106a2903004200200128023022091b210b2001290338420020091b21172014200756201320085620031b0d01200141b0026a41086a22034200370300200142003703b00241b18ac0004116200141b0026a100420014190036a41086a2003290300370300200120012903b002370390032001427f200b20187c201720197c22082017542203ad7c220720032007200b542007200b511b22031b3703b8022001427f200820031b3703b002200141b0026a21030c020b41f3c8c10041ca00101042002113200141b0026a41086a22034200370300200142003703b00241b18ac0004116200141b0026a100420014190036a41086a2003290300370300200120012903b00237039003200141003602c80120014190036a4110200141c8016a100521030240024020012802c8012209417f470d0042002113420021140c010b024020030d00420021140c010b200142003703d001200142003703c801200141c8016a20032009411020094110491b10ce041a2009410f4d0d09200141d0016a290300211420012903c8012113200310290b200141b0026a41086a22034200370300200142003703b00241b18ac0004116200141b0026a100420014190036a41086a2003290300370300200120012903b002370390032001427f201420087c201320077c22082013542203ad7c22072003200720145420072014511b22031b3703d0012001427f200820031b3703c80120014190036a4110200141c8016a411010030c020b200141b0026a41086a22034200370300200142003703b00241b18ac0004116200141b0026a100420014190036a41086a2003290300370300200120012903b0023703900320014200200b20187d2017201954ad7d2207201720197d22082017562007200b562007200b511b22031b3703b80220014200200820031b3703b002200141b0026a21030b20014190036a41102003411010030b20012903a0012107200141c8036a200141a0016a41086a290300370300200141c0036a2007370300200141b0036a41086a41043a00002001410a3a00b00341b8d6c5004100200141b0036a1088010b20024200370300200142003703900341c1c8c100411d20014190036a1004200141b0026a41086a200229030037030020012001290390033703b002200141003602b003200141b0026a4110200141b0036a1005210920012802b0032203417f460d0c2009450d0c200120093602c801200120033602cc01200142003703b003200141b0036a20092003410820034108491b220510ce041a2001200320056b22043602cc012001200920056a22053602c8010240200341074d0d0020012903b003210b200142003703b003200141b0036a20052004410820044108491b220310ce041a2001200420036b3602cc012001200520036a3602c801200441074d0d0020012903b0032117200141b0036a200141c8016a104120012802b0032203450d0020012902b4032108200141003a00b003200141b0036a20012802c801220620012802cc012204410047220510ce041a20042005490d062001200420056b22103602cc012001200620056a22053602c8012004450d0a20012d00b0034101470d0a42002107200142003703b003200141b0036a200520104108201041084922061b220410ce041a2001201020046b3602cc012001200520046a3602c80120060d0b20012903b0032119420121070c0c0b418f89c3004133104e000b41124101102a000b41244101102a000b20124101102a000b418f89c3004133104e000b418f89c3004133104e000b20052004103e000b418f89c3004133104e000b41344101102a000b41144101102a000b420021070b0b20091029200141ec016a2008370200200141e0016a2019370300200120033602e801200120073703d801200120173703d0012001200b3703c8010240200b2000520d002008422088a72106024020074200520d002006ad42287e2207422088a70d032007a72209417f4c0d030240024020090d00410821100c010b200910272210450d050b0240024020060d00410021040c010b200641286c210541002104201021090340200341086a2903002107200341106a2903002108200341186a290300211420032903002113200941206a200341206a290300370300200941186a2014370300200941106a2008370300200941086a200737030020092013370300200941286a2109200441016a2104200341286a2103200541586a22050d000b0b200141c8036a2004360200200141c4036a2006360200200141c0036a2010360200200120173703b803200142003703b003200141b0026a200141b0036a105d2001419b036a200141b8026a280200360000200120012903b00237009303200141bc026a20014197036a290000370000200141c6a4b9da043600b102200141023a00b00220012001290090033700b502200141b0026a1097032006450d01201010290c010b2006ad42287e2207422088a70d022007a72209417f4c0d020240024020090d00410821100c010b200910272210450d050b0240024020060d00410021040c010b200641286c210541002104201021090340200341086a2903002107200341106a2903002108200341186a290300211420032903002113200941206a200341206a290300370300200941186a2014370300200941106a2008370300200941086a200737030020092013370300200941286a2109200441016a2104200341286a2103200541586a22050d000b0b200141d0036a2004360200200141cc036a2006360200200141c8036a2010360200200141c0036a2017370300200120193703b803200142013703b003200141b0026a200141b0036a105d2001419b036a200141b8026a280200360000200120012903b00237009303200141bc026a20014197036a290000370000200141c6a4b9da043600b102200141023a00b00220012001290090033700b502200141b0026a1097032006450d00201010290b02402017200b7c2000520d0020014190036a41086a22034200370300200142003703900341c6c4c500411b20014190036a1004200141b0026a41086a2204200329030037030020012001290390033703b002200141103602b4032001200141b0026a3602b003200141e8016a2209200141b0036a102f200141b0036a41086a2009290000370300200141b0036a41106a200941086a280000360200200141003602b403200141093a00b00341b8d6c5004100200141b0036a10880120034200370300200142003703900341c1c8c100411d20014190036a10042004200329030037030020012001290390033703b002200141b0026a4110100c0c010b20012802ec01450d0020012802e80110290b20014190036a41086a22034200370300200142003703900341dec8c100411520014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141003602b003200141b0026a4110200141b0036a1005210320012802b0032209417f460d062003450d06200141003a00b003200141b0036a20032009410047220410ce041a20092004490d03024002402009450d0020012d00b003220541034b0d00200920046b2109200320046a21040240024020050e0403000301030b200142003703b003200141b0036a20042009410820094108491b220510ce041a200941074d0d0120012903b0032107200142003703b003200141b0036a200420056a200920056b2209410820094108491b10ce041a200941074b0d080c010b200142003703b003200141b0036a20042009410820094108491b220510ce041a200941074d0d0020012903b0032107200142003703b003200141b0036a200420056a200920056b2209410820094108491b10ce041a200941074b0d060b418f89c3004133104e000b200310290c060b1039000b20094108102a000b20094108102a000b20042009103e000b20012903b003210820031029024020072000520d00200142043703b003200120083703b803200141c8016a200141b0036a105d2001419b036a200141d0016a280200360000200120012903c80137009303200141d4016a20014197036a290000370000200141c6a4b9da043600c901200141023a00c80120012001290090033700cd01200141c8016a1097030b200820077c2000520d01200142003703b00320014190036a41086a22034200370300200142003703900341dec8c100411520014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141c8016a200141b0036a10e701200141b0026a411020012802c801220320012802d0011003024020012802cc01450d00200310290b200141023602b403200141093a00b00341b8d6c5004100200141b0036a1088010c010b20012903b003210820031029024020072000520d00200142033703b003200120083703b803200141c8016a200141b0036a105d2001419b036a200141d0016a280200360000200120012903c80137009303200141d4016a20014197036a290000370000200141c6a4b9da043600c901200141023a00c80120012001290090033700cd01200141c8016a1097030b200820077c2000520d00200142023703b00320014190036a41086a22034200370300200142003703900341dec8c100411520014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141c8016a200141b0036a10e701200141b0026a411020012802c801220320012802d0011003024020012802cc01450d00200310290b200141013602b403200141093a00b00341b8d6c5004100200141b0036a1088010b20014190036a41086a22034200370300200142003703900341a18ac000411020014190036a1004200141b0026a41086a2209200329030037030020012001290390033703b002200141206a200141b0026a109f03200129032821002001280220211020034200370300200142003703900341e1c4c500411520014190036a10042009200329030037030020012001290390033703b002200141003602b003200141b0026a4110200141b0036a100521030240024002400240024002400240024002400240024002400240024020012802b0032209417f460d002003450d00200141003a00b003200141b0036a20032009410047220410ce041a20092004490d022009450d0c20012d00b00321092003102920094102460d0020094101710d010b410810272209450d022009420037030020014190036a41086a22034200370300200142003703900341c78ac000411520014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141003602b803200142013703b003200141013602c801200141c8016a200141b0036a1030200929030021070240024020012802b403220520012802b80322046b4108490d0020012802b00321030c010b200441086a22032004490d0e20054101742206200320032006491b22064100480d0e0240024020050d002006102721030c010b20012802b00320052006102821030b2003450d04200120063602b403200120033602b003200621050b2001200441086a22063602b803200320046a2007370000200141b0026a411020032006100302402005450d00200310290b20091029410810272209450d042009420037030020014190036a41086a2203420037030020014200370390034188b7c000411620014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141003602b803200142013703b003200141013602c801200141c8016a200141b0036a1030200929030021070240024020012802b403220520012802b80322046b4108490d0020012802b00321030c010b200441086a22032004490d0e20054101742206200320032006491b22064100480d0e0240024020050d002006102721030c010b20012802b00320052006102821030b2003450d06200120063602b403200120033602b003200621050b2001200441086a22063602b803200320046a2007370000200141b0026a411020032006100302402005450d00200310290b2009102920014190036a41086a220342003703002001420037039003419eb7c000411020014190036a1004200141b0026a41086a2209200329030037030020012001290390033703b002200142003703b003200141b0026a4110200141b0036a41081003200141013a00b00320034200370300200142003703900341e1c4c500411520014190036a10042009200329030037030020012001290390033703b002200141b0026a4110200141b0036a410110030b20014190036a41086a22034200370300200142003703900341c78ac000411520014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141003602b003200141b0026a4110200141b0036a100521030240024020012802b0032209417f460d002003450d00200120093602cc01200120033602c801200141b0036a200141c8016a104020012802b0032202450d0720012902b403210b2009450d01200310290c010b410821024200210b0b20014190036a41086a2203420037030020014200370390034188b7c000411620014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141003602b003200141b0026a4110200141b0036a100521030240024020012802b0032209417f460d002003450d00200120093602cc01200120033602c801200141b0036a200141c8016a104020012802b0032206450d0820012902b403211402402009450d00200310290b2014422088a721030c010b4108210641002103420021140b200b422088a7210a024020100d00200a417f6a2209200a4b0d082009200a4f0d08200220094103746a2209450d08200929030021000b4100200a419c7f6a22092009200a41016a4b1b220e200a4b0d082002200e4103746a210c200e450d0b2003ad21082002211203402012290300210741002103024002400240024002402008a7221041014b0d0020100e020201020b20102109034020032009410176220420036a22052007200620054103746a290300541b2103200920046b220941014b0d000b0b20072006200341037422096a2903002213510d02200320072013566a21030c010b410021030b200120033602b00341d4b7c000412e200141b0036a4184b8c00010a201000b20082003ad580d0a200620096a2209200941086a2003417f7320106a41037410cf041a201442ffffffff0f832010417f6a2203ad422086842114201241086a2212200c460d0c2008427f7c21080c000b0b20042009103e000b41084108102a000b20064101102a000b41084108102a000b20064101102a000b418f89c3004133104e000b418f89c3004133104e000b41aeb7c0004126104e000b419cb1c5001058000b418080c0001058000b418f89c3004133104e000b200b42ffffffff0f8321080240200a200e6b2209450d000240200e450d002002200c200941037410cf041a2014422088a721030b2009ad42208620088421080b41002109024002400240200341014b0d00024020030e020002000b20144220882207a72103410021090c020b034020092003410176220420096a22052000200620054103746a290300541b2109200320046b220341014b0d000b0b02402000200620094103746a2903002207510d00200920002007566a21090b200920144220882207a722034d0d0041d0b1c5001058000b024002400240024002400240024002400240024020032014a7470d00200341016a22042003490d0a2007a722104101742205200420042005491b220441ffffffff01712004470d0a200441037422054100480d0a0240024020030d002005102721060c010b200620104103742005102821060b2006450d012004ad21140b200620094103746a220441086a2004200320096b41037410cf041a2004200037030002402008a72008422088220ba72203470d00200341016a22092003490d0a20034101742204200920092004491b220941ffffffff01712009470d0a200941037422044100480d0a0240024020030d002004102721020c010b200220034103742004102821020b2002450d022009ad21080b200220034103746a200037030002402007a7220d41016a220a200d4f0d004194b8c0001058000b200a4101762203200a4f0d02200620034103746a29030021130240200a4101710d002003417f6a2203200a4f0d04200620034103746a29030020137c42018821130b20014190036a41086a22034200370300200142003703900341c78ac000411520014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200141003602b803200142013703b0032001200b42017ca7220e3602c801200141c8016a200141b0036a103002400240200e0d0020012802b803211220012802b403211020012802b00321090c010b200e410374210c410020012802b80322036b210420012802b40321102002210503402005290300210702400240201020046a4108490d0020012802b00321090c010b200341086a22092003490d0c20104101742212200920092012491b22124100480d0c0240024020100d002012102721090c010b20012802b00320102012102821090b2009450d07200120123602b403200120093602b003201221100b200541086a21052001200341086a22123602b803200920036a2007370000200441786a210420122103200c41786a220c0d000b0b200141b0026a411020092012100302402010450d00200910290b02402008a7450d00200210290b20014190036a41086a2203420037030020014200370390034188b7c000411620014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200142013703b003200141003602b8032001200a3602c801200d41037441086a2112200141c8016a200141b0036a1030410020012802b80322036b210420012802b40321102006210503402005290300210702400240201020046a4108490d0020012802b00321090c010b200341086a22092003490d0b2010410174220c20092009200c491b220c4100480d0b0240024020100d00200c102721090c010b20012802b0032010200c102821090b2009450d072001200c3602b403200120093602b003200c21100b200541086a21052001200341086a220c3602b803200920036a2007370000200441786a2104200c2103201241786a22120d000b200141b0026a41102009200c100302402010450d00200910290b02402014a7450d00200610290b20014190036a41086a220342003703002001420037039003419eb7c000411020014190036a1004200141b0026a41086a200329030037030020012001290390033703b002200120133703b003200141b0026a4110200141b0036a410810030240200e41e500470d00200141106a41888dc300410d1094012013429a087c2001290318420020012802101b560d0020014190036a41086a2209420037030020014200370390034199a7c100411720014190036a1004200141b0026a41086a200929030037030020012001290390033703b002410810272209450d07200942e40037000020094108411010282209450d0820092013370008200141b0026a4110200941101003200910290b20034200370300200142003703900341cfa2c400411720014190036a1004200141b0036a41086a200329030037030020012001290390033703b0030240200141b0036a411041b8d6c50041004100100b417f470d00200141ceecc200410d109401200129030821072001280200210320014190036a41086a22094200370300200142003703900341cfa2c400411720014190036a1004200141b0036a41086a200929030037030020012001290390033703b00320012007420020031b3703c801200141b0036a4110200141c8016a410810030b20014190036a41086a22034200370300200142003703900341dbecc200411120014190036a1004200141b0036a41086a2209200329030037030020012001290390033703b003200141b0036a4110100c20034200370300200142003703900341fcc7c500411720014190036a10042009200329030037030020012001290390033703b003200141b0036a4110100c41bdcbc5004113108a02220341ff01714102460d082003410171450d08200141a0046a24000f0b20054108102a000b20044108102a000b41acb8c0002003200a1037000b41acb8c0002003200a1037000b20124101102a000b200c4101102a000b41084101102a000b41104101102a000b41d4e9c2001058000b102b000bd91a08017f017e047f027e047f017e037f017e23004190026b2201240042002102200141d0016a41086a22034200370300200142003703d0014192cdc5004115200141d0016a100420014190016a41086a2003290300370300200120012903d0013703900120014190016a4110100c200141286a41a7cdc500411a10b501200128022c21042001280228210520034200370300200142003703d00141d8cdc500411b200141d0016a1004200141f0016a41086a2003290300370300200120012903d0013703f001200141003602d001200141f0016a4110200141d0016a10052103024002400240024002400240024002400240024020012802d0012206417f460d002003450d00200142003703d001200141d0016a20032006410820064108491b10ce041a200641074d0d0120012903d0012102200310290b200141186a4180e59af7002004410020051b220320034180e59af7004922061b20034180e59af70020061b6b2206ad220742002007420010d304200742a8c30180210742ffffffffffffffffff00428080808080808080807f20061b2001290318220820012903202008423f87521b42808090bbbad6adf00d7f210802400240200341ffe49af7004b0d0042ffffffffffffffffff00428080808080808080807f2002200720087d22087d22074200531b20072002427f5522032008427f554720032007427f5547711b22024280ec94a37c20024280ec94a37c551b21020c010b42ffffffffffffffffff00428080808080808080807f2002200720087c22087c22074200531b20072002427f5522032008427f554620032007427f5547711b21020b200141d0016a41086a22034200370300200142003703d00141d8cdc500411b200141d0016a100420014190016a41086a22062003290300370300200120012903d00137039001410810272204450d012004200237000020014190016a41102004410810032004102920034200370300200142003703d00141a7cdc500411a200141d0016a100420062003290300370300200120012903d0013703900120014190016a4110100c20034200370300200142003703d00141c1cdc5004117200141d0016a100420062003290300370300200120012903d0013703900120014190016a4110100c20034200370300200142003703d00141888dc300410d200141d0016a100420062003290300370300200120012903d00137039001200141086a20014190016a109f03200129031021022001280208210920034200370300200142003703d00141d18fc3004111200141d0016a100420062003290300370300200120012903d00137039001200141003602f00120014190016a4110200141f0016a100521030240024020012802f0012206417f460d002003450d00200141f0016a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200141f0016a2003200410ce041a2006411f4d0d04200141d0016a41186a2206200141f0016a41186a2204290000370300200141d0016a41106a2205200141f0016a41106a220a290000370300200141d0016a41086a220b200141f0016a41086a220c290000370300200120012900f0013703d00120031029200141b0016a41186a22032006290300370300200141b0016a41106a22062005290300370300200141b0016a41086a2205200b290300370300200120012903d0013703b00120014190016a4110100c200420032903002207370300200a20062903002208370300200c2005290300220d370300200141306a41086a200d370300200141306a41106a2008370300200141306a41186a2007370300200120012903b00122073703f001200120073703300c010b200141f0016a41186a200141b0016a41186a290300370300200141f0016a41106a200141b0016a41106a290300370300200141f0016a41086a200141b0016a41086a290300370300200141306a41086a4200370300200141306a41106a4200370300200141306a41186a4200370300200120012903b0013703f001200142003703300b200141d0016a41086a22034200370300200142003703d00141aa8dc300410d200141d0016a1004200141f0016a41086a2003290300370300200120012903d0013703f001200141003602d001200141f0016a4110200141d0016a100521030240024020012802d0012206417f460d002003450d00200120063602b401200120033602b001200141d0016a200141b0016a104320012802d001220a450d0520012902d401210702402006450d00200310290b200141f0016a4110100c2007422088a721032007a7210b0c010b4104210a410021034100210b0b200141d0016a41086a22064200370300200142003703d00141958dc3004115200141d0016a100420014190016a41086a2006290300370300200120012903d00137039001200141003602d00120014190016a4110200141d0016a100521050240024020012802d0012206417f460d00200141f0016a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a200141f0016a2005200410ce041a2006411f4d0d06200141d0016a41186a2206200141f0016a41186a2204290000370300200141d0016a41106a220c200141f0016a41106a220e290000370300200141d0016a41086a220f200141f0016a41086a2210290000370300200120012900f0013703d00120051029200141b0016a41186a22052006290300370300200141b0016a41106a2206200c290300370300200141b0016a41086a220c200f290300370300200120012903d0013703b00120014190016a4110100c200420052903002207370300200e200629030022083703002010200c290300220d370300200141d0006a41086a200d370300200141d0006a41106a2008370300200141d0006a41186a2007370300200120012903b00122073703f001200120073703500c010b200141f0016a41086a200141b0016a41086a290300370300200141f0016a41106a200141b0016a41106a290300370300200141f0016a41186a200141b0016a41186a290300370300200141d0006a41086a4200370300200141d0006a41106a4200370300200141d0006a41186a4200370300200120012903b0013703f001200142003703500b02402002420020091b220242fb01540d00200242857e7c2207500d00411010272206450d06200641086a41002900bf8d43370000200641002900b78d4337000020064110412010282206450d0720062007370010200141b0016a41186a22044200370300200141b0016a41106a22054200370300200141b0016a41086a22094200370300200142003703b00120064118200141b0016a1000200141f0016a41186a2004290300370300200141f0016a41106a2005290300370300200141f0016a41086a2009290300370300200120012903b0013703f001200141f0016a4120100c200610290b200141b0016a41186a22064200370300200141b0016a41106a22044200370300200141b0016a41086a22054200370300200142003703b001200141b0016a101e200141f0006a41186a2006290300370300200141f0006a41106a2004290300370300200141f0006a41086a2005290300370300200120012903b001370370200141f0016a41186a2209200141306a41186a290300370300200141f0016a41106a220c200141306a41106a290300370300200141f0016a41086a220e200141306a41086a290300370300200120012903303703f001200642003703002004420037030020054200370300200142003703b0010240200141f0016a4120200141b0016a101f450d0020014190016a41086a2005290300220737030020014190016a41106a2004290300220837030020014190016a41186a2006290300220d370300200120012903b001221137039001200e2007370300200c20083703002009200d370300200120113703f00102402003200b470d00200341016a22062003490d0a20034101742204200620062004491b220bad42247e2207422088a70d0a2007a722064100480d0a0240024020030d0020061027210a0c010b200a200341246c20061028210a0b200a450d090b200a200341246c6a220641003a0000200620012903f001370001200641096a200141f8016a290300370000200641116a20014180026a290300370000200641196a20014188026a290300370000200620012f00d0013b0021200641236a200141d2016a2d00003a0000200341016a21030b2000200129033037001420002002370300200020012903703700342000412c6a200141306a41186a290300370000200041246a200141306a41106a2903003700002000411c6a200141306a41086a2903003700002000413c6a200141f0006a41086a290300370000200041c4006a200141f0006a41106a290300370000200041cc006a200141f0006a41186a290300370000200041106a20033602002000410c6a200b3602002000200a360208200041ec006a200141d0006a41186a290300370000200041e4006a200141d0006a41106a290300370000200041dc006a200141d0006a41086a2903003700002000200129035037005420014190026a24000f0b418f89c3004133104e000b41084101102a000b418f89c3004133104e000b418f89c3004133104e000b418f89c3004133104e000b41104101102a000b41204101102a000b20064104102a000b102b000bf90201027f23004180026b22022400024002402001450d00200220003602000c010b200241b8d6c5003602000b2002200136020420024180016a2002108e020240200228028801450d00200241086a20024180016a41f80010ce041a200241086a10b9020240200241186a2802002200450d0020022802102101200041246c210003400240024020012d0000220341034b0d0002400240024020030e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b0240200241146a280200450d00200228021010290b20024180026a240042010f0b2002411c6a41013602002002420137020c200241cc81c200360208200241023602fc01200241d082c2003602f8012002200241f8016a360218200241086a41d481c2001057000be40b01087f230041206b2202240020024100360218200242013703100240024002400240024002400240024002400240410410272203450d0020024284808080c00037021420022003360210200341edcad18b0636000002400240200228021420022802182203460d00200228021021040c010b200341016a22042003490d0a20034101742205200420042005491b22054100480d0a0240024020030d002005102721040c010b200228021020032005102821040b2004450d0220022005360214200220043602100b2002200341016a360218200420036a41073a00004112200241106a10c60241002103034020034184e7c1006a28020020034188e7c1006a280200200241106a10c702024002402003418ce7c1006a22052802004102470d0002400240200228021420022802182204460d00200228021021050c010b200441016a22052004490d0d20044101742206200520052006491b22064100480d0d0240024020040d002006102721050c010b200228021020042006102821050b2005450d0620022006360214200220053602100b2002200441016a360218200520046a41003a00000c010b02400240200228021420022802182204460d00200228021021060c010b200441016a22062004490d0c20044101742207200620062007491b22074100480d0c0240024020040d002007102721060c010b200228021020042007102821060b2006450d0620022007360214200220063602100b2002200441016a360218200620046a41013a00002005200241106a10c8020b02400240200341ace7c1006a22052802004102470d0002400240200228021420022802182204460d00200228021021050c010b200441016a22052004490d0d20044101742206200520052006491b22064100480d0d0240024020040d002006102721050c010b200228021020042006102821050b2005450d0820022006360214200220053602100b2002200441016a360218200520046a41003a00000c010b02400240200228021420022802182204460d00200228021021060c010b200441016a22062004490d0c20044101742207200620062007491b22074100480d0c0240024020040d002007102721060c010b200228021020042007102821060b2006450d0820022007360214200220063602100b2002200441016a360218200620046a41013a00002005200241106a10c9020b02400240200341bce7c1006a22052802004102470d0002400240200228021420022802182204460d00200228021021050c010b200441016a22052004490d0d20044101742206200520052006491b22064100480d0d0240024020040d002006102721050c010b200228021020042006102821050b2005450d0a20022006360214200220053602100b2002200441016a360218200520046a41003a00000c010b02400240200228021420022802182204460d00200228021021060c010b200441016a22062004490d0c20044101742207200620062007491b22074100480d0c0240024020040d002007102721060c010b200228021020042007102821060b2006450d0a20022007360214200220063602100b2002200441016a360218200620046a41013a00002005200241106a10ca020b200341cce7c1006a200241106a10cb02200341dc006a220341f80c470d000b20022802142107200228021021062002280218210320024100360218200242013703102002200336020c2002410c6a200241106a10300240024020022802142205200228021822046b2003490d00200228021021050c010b200420036a22082004490d0a20054101742209200820082009491b22084100480d0a0240024020050d002008102721050c010b200228021020052008102821050b2005450d0920022008360214200220053602100b200520046a2006200310ce041a200420036a210302402007450d00200610290b200241206a24002003ad4220862005ad840f0b41044101102a000b20054101102a000b20064101102a000b20074101102a000b20064101102a000b20074101102a000b20064101102a000b20074101102a000b20084101102a000b102b000b920701037f0240024002400240024002402000413f4b0d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0620024101742204200320032004491b22044100480d060240024020020d002004102721030c010b200128020020022004102821030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20004102743a00000f0b200041808001490d032000418080808004490d020c010b20044101102a000b0240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0520024101742204200320032004491b22044100480d050240024020020d002004102721030c010b200128020020022004102821030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a000002400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d0520034101742202200420042002491b22024100480d050240024020030d002002102721030c010b200128020020032002102821030b2003450d0220012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20003600000f0b20044101102a000b20024101102a000b024002400240200141046a2802002203200141086a28020022026b4104490d00200128020021030c010b200241046a22042002490d0320034101742202200420042002491b22024100480d030240024020030d002002102721030c010b200128020020032002102821030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20004102744102723600000f0b20024101102a000b024002400240200141046a2802002203200141086a28020022026b4102490d00200128020021030c010b200241026a22042002490d0220034101742202200420042002491b22024100480d020240024020030d002002102721030c010b200128020020032002102821030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241026a360200200320026a20004102744101723b00000f0b20024101102a000b102b000bc60801037f0240024002400240024002400240024002402001413f4b0d0002400240200241046a280200200241086a2802002203460d00200228020021040c010b200341016a22042003490d0920034101742205200420042005491b22054100480d090240024020030d002005102721040c010b200228020020032005102821040b2004450d0220022004360200200241046a2005360200200241086a28020021030b200241086a200341016a360200200420036a20014102743a00000c050b200141808001490d032001418080808004490d020c010b20054101102a000b0240024002400240200241046a280200200241086a2802002203460d00200228020021040c010b200341016a22042003490d0820034101742205200420042005491b22054100480d080240024020030d002005102721040c010b200228020020032005102821040b2004450d0120022004360200200241046a2005360200200241086a28020021030b200241086a2205200341016a360200200420036a41033a000002400240200241046a2802002204200528020022036b4104490d00200228020021040c010b200341046a22052003490d0820044101742203200520052003491b22034100480d080240024020040d002003102721040c010b200228020020042003102821040b2004450d0220022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a20013600000c040b20054101102a000b20034101102a000b024002400240200241046a2802002204200241086a28020022036b4104490d00200228020021040c010b200341046a22052003490d0620044101742203200520052003491b22034100480d060240024020040d002003102721040c010b200228020020042003102821040b2004450d0120022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a20014102744102723600000c020b20034101102a000b02400240200241046a2802002204200241086a28020022036b4102490d00200228020021040c010b200341026a22052003490d0420044101742203200520052003491b22034100480d040240024020040d002003102721040c010b200228020020042003102821040b2004450d0220022004360200200241046a2003360200200241086a28020021030b200241086a200341026a360200200420036a20014102744101723b00000b02400240200241046a2802002204200241086a28020022036b2001490d00200228020021040c010b200320016a22052003490d0320044101742203200520052003491b22034100480d030240024020040d002003102721040c010b200228020020042003102821040b2004450d0220022004360200200241046a2003360200200241086a28020021030b200241086a200320016a360200200420036a2000200110ce041a0f0b20034101102a000b20034101102a000b102b000b860201037f230041206b220224000240024020002802004101460d00200220002802041101002002280204200241086a280200200110c7022002410c6a200110b004200228020c450d01200241106a28020021030240200241186a2802002200450d00200041d8006c21044100210103400240200320016a220041346a280200450d002000413c6a280200450d00200041386a28020010290b0240200041c4006a280200450d00200041cc006a280200450d00200041c8006a28020010290b2004200141d8006a2201470d000b0b200241146a280200450d01200310290c010b200041086a2802002000410c6a280200200110c702200041106a200110b0040b200241206a24000bae0201047f230041106b220224000240024020002802004101460d00200241086a200028020411010020022802082103200228020c2200200110c6022000450d012000412c6c2104410021050340200320056a220041046a280200200041086a280200200110c7022000410c6a200110af04200041206a28020020032005412841242000411c6a2802004101461b6a6a280200200110ad0420042005412c6a2205470d000c020b0b200028020421032000410c6a2802002200200110c6022000450d002000412c6c2104410021050340200320056a220041046a280200200041086a280200200110c7022000410c6a200110af04200041206a28020020032005412841242000411c6a2802004101461b6a6a280200200110ad0420042005412c6a2205470d000b0b200241106a24000be60201047f230041106b220224000240024020002802004101460d00200241086a200028020411010020022802082103200228020c2200200110c6022000450d012000412c6c2104410021050340200320056a220041046a280200200041086a280200200110c702200041106a28020020032005411841142000410c6a2802004101461b6a6a280200200110ad04200041206a28020020032005412841242000411c6a2802004101461b6a6a280200200110ad0420042005412c6a2205470d000c020b0b200028020421032000410c6a2802002200200110c6022000450d002000412c6c2104410021050340200320056a220041046a280200200041086a280200200110c702200041106a28020020032005411841142000410c6a2802004101461b6a6a280200200110ad04200041206a28020020032005412841242000411c6a2802004101461b6a6a280200200110ad0420042005412c6a2205470d000b0b200241106a24000b880401057f230041206b220224000240024020002802004101460d00200241086a200028020411010020022802082103200228020c2200200110c6022000450d01200041386c2104410021050340200320056a220041046a280200200041086a280200200110c702200041106a280200200041146a280200200110c70202400240200041186a2802004101460d00200241106a2000411c6a280200200041206a28020028020c110000200228021022062002280218200110c7022002280214450d01200610290c010b2000411c6a280200200041246a280200200110c7020b2000412c6a2802002003200541344130200041286a2802004101461b6a6a280200200110ad042004200541386a2205470d000c020b0b200028020421032000410c6a2802002200200110c6022000450d00200041386c2104410021050340200320056a220041046a280200200041086a280200200110c702200041106a280200200041146a280200200110c70202400240200041186a2802004101460d00200241106a2000411c6a280200200041206a28020028020c110000200228021022062002280218200110c7022002280214450d01200610290c010b2000411c6a280200200041246a280200200110c7020b2000412c6a2802002003200541344130200041286a2802004101461b6a6a280200200110ad042004200541386a2205470d000b0b200241206a24000ba80301027f230041a0076b22022400024002402001450d00200220003602080c010b200241b8d6c5003602080b2002200136020c200241f0046a200241086a104902400240024020022903d8054203510d00200241106a200241f0046a41a00210ce041a200241b0026a200241106a41a00210ce041a2002200241b0026a3602f004200241d0046a200241f0046a10bf0220022802d8042101200241f0046a200241b0026a41a00210ce041a20024198076a20022802d804360200200220022903d00437039007200241e0046a200241f0046a200120024190076a10bc02410121000240024020022802e0044101460d004100210020022802e40441004721030c010b4280828898f01f20022802e404410374ad88a721030b410110272201450d01200120003a000020014101410210282201450d02200120033a0001200241a0076a24002001ad428080808020840f0b200241c4026a4101360200200242013702b402200241cc81c2003602b00220024102360214200241e882c2003602102002200241106a3602c002200241b0026a41d481c2001057000b41014101102a000b41024101102a000bee1003097f017e037f230041e0016b22022400200241206a41ff88c300411010c1022002280224210320022802202104200241a0016a41086a22054200370300200242003703a0014192cdc5004115200241a0016a1004200241286a41086a2005290300370300200220022903a0013703284100210620022003410020041b3602c00141042107200241286a4110200241c0016a41041003200241106a41888dc300410d1094012002290318420020022802101b10c202200241086a4192cdc500411510b5014104210841002109024002400240200228020c410020022802081b220a450d00200aad420c7e220b422088a70d01200ba722034100480d01200310272208450d02200821034100210c034002400240024002400240411410272204450d00200441106a4100280083ce45360000200441086a41002900fbcd45370000200441002900f3cd4537000020044114412810282205450d012005200c360014200241286a41186a22044200370300200241286a41106a220d4200370300200241286a41086a220942003703002002420037032820054118200241286a1000200241c0016a41186a2004290300370300200241c0016a41106a200d290300370300200241c0016a41086a2009290300370300200220022903283703c00120024100360228200241c0016a4120200241286a1005210d20022802282209417f460d03200d450d03200220093602b4012002200d3602b001200241286a200241b0016a104420022802282204450d02200229022c210b02402009450d00200d10290b200241c0016a4120100c0c040b41144101102a000b41284101102a000b418f89c3004133104e000b410021040b2005102920032004410120041b360200200341046a200ba7410020041b360200200341086a200b422088a7410020041b3602002003410c6a2103200a200c41016a220c470d000b200a21090b0240024002400240024002402009410c6c2203450d002003410c6e220641037422044100480d06200410272207450d010b410021050240200820036a220d2008460d00200721032008210403402004280200210c200341046a200441086a2802003602002003200c360200200341086a2103200541016a21052004410c6a2204200d470d000b0b200241c0016a2007200510c00202402006450d00200710290b02402009450d002009410c6c21042008210303400240200341046a280200450d00200328020010290b2003410c6a2103200441746a22040d000b0b0240200a450d00200810290b200241286a41186a200241c0016a41186a290300370300200241286a41106a200241c0016a41106a290300370300200241286a41086a200241c0016a41086a290300370300200220022903c001370328200241a0016a41086a22034200370300200242003703a00141958dc3004115200241a0016a1004200241b0016a41086a2003290300370300200220022903a0013703b001200241b0016a4110200241286a41201003200241286a10c302200241003602b801200242013703b001412010272203450d01200242a080808080043702b401200220033602b0012003200229023c370000200341086a200241c4006a290200370000200341106a200241cc006a290200370000200341186a200241d4006a290200370000200241286a200241b0016a10540240024020022802b401220520022802b801220c6b4120490d00200c41206a210320022802b00121040c010b200c41206a2203200c490d0620054101742204200320032004491b220d4100480d060240024020050d00200d102721040c010b20022802b0012005200d102821040b2004450d032002200d3602b401200220043602b001200d21050b200220033602b8012004200c6a220c200229025c370000200c41086a200241e4006a290200370000200c41106a200241ec006a290200370000200c41186a200241f4006a2902003700000240200520036b411f4b0d00200341206a220c2003490d062005410174220d200c200c200d491b220c4100480d060240024020050d00200c102721040c010b20042005200c102821040b2004450d042002200c3602b401200220043602b0010b200420036a220441086a20024184016a290200370000200441106a2002418c016a290200370000200441186a20024194016a2902003700002002200341206a3602b8012004200229027c3700002002280230210e2002200241286a41106a28020022063602c001200241c0016a200241b0016a10300240024020060d0020022802b801210420022802b00121050c010b200641246c210820022802b401210920022802b8012103200e210c0340200241c0016a200c104f20022802c001210a02400240200920036b20022802c801220d490d002003200d6a210420022802b00121050c010b2003200d6a22042003490d0820094101742205200420042005491b22074100480d080240024020090d002007102721050c010b20022802b00120092007102821050b2005450d07200220073602b401200220053602b001200721090b200220043602b801200520036a200a200d10ce041a024020022802c401450d00200a10290b200c41246a210c200421032008415c6a22080d000b2006450d00200641246c210c200e210303400240024020032d0000220d41034b0d00024002400240200d0e0404000102040b2003410c6a280200450d03200341086a28020010290c030b2003410c6a280200450d02200341086a28020010290c020b2003410c6a280200450d01200341086a28020010290c010b200341086a280200450d00200341046a28020010290b200341246a2103200c415c6a220c0d000b0b0240200241346a280200450d00200e10290b200241e0016a24002004ad4220862005ad840f0b20044104102a000b41204101102a000b200d4101102a000b200c4101102a000b20074101102a000b102b000b20034104102a000b900c03017f027e097f230041b0026b22022400024002402001450d00200220003602100c010b200241b8d6c5003602100b20022001360214200241286a200241106a10fb010240024020022802282201450d002002200229022c37021c20022001360218200241286a200241186a10cf02024020022802284101470d002002200229022c3703c80141beefc2004128200241c8016a4188eec20010a201000b200241286a41086a2903002103200241ceecc200410d109401200229030821042002280200210141a002102722050d0141a0024108102a000b2002413c6a41013602002002420137022c200241cc81c200360228200241023602cc012002418083c2003602c8012002200241c8016a360238200241286a41d481c2001057000b2005200241c8016a41e80010ce04220642023703682006410236029801200620022903a001370370200641f8006a200241a0016a41086a29030037030020064180016a200241b0016a29030037030020064188016a200241b8016a29030037030020064190016a200241c0016a29030037030020062003200442b9067c42b90620011b220420042003541b3703a001200641a8016a200241286a41f80010ce041a200241186a2101200228021c21070240024003402001280200220841086a210020082f0106220941037421014100210a0240024003402001450d0141c8e2c1002000410810d004220b450d02200141786a2101200a41016a210a200041086a2100200b417f4a0d000b200a417f6a21090b024020070d0041d0e2c1002101412821000c030b2007417f6a2107200820094102746a41e4016a21010c010b0b2008200a410c6c6a220141e0006a2802002100200141e8006a280200210120024200370328200241286a20002001410820014108491b10ce041a200141074b0d0141fec4c5002101412921000b2002200036022c2002200136022841f88cc000412b200241286a41e88cc00010a201000b20022903282103200241286a41086a220142003703002002420037032841c78ac0004115200241286a1004200241c8016a41086a2001290300370300200220022903283703c8014100210120024100360228200241c8016a4110200241286a1005210a02400240024002400240024020022802282200417f460d00200220003602a4012002200a3602a001200241286a200241a0016a10402002280228220b450d02200241306a2802002101200228022c21082000450d01200a10290c010b4108210b410021080b4100210002402001417f6a220a20014b0d00200a20014f0d00200b200a4103746a2201450d00200129030020035221000b02402008450d00200b10290b0240024020000d004101210c0c010b200641a00241c00410282205450d02200541a0026a200241c8016a41e80010ce041a2005420237038803200520033703c0032005410c3602b803200520022903a0013703900320054198036a200241a8016a290300370300200541a0036a200241b0016a290300370300200541a8036a200241b8016a290300370300200541b0036a200241c0016a290300370300200541c8036a200241286a41f80010ce041a4102210c0b2002280218200228021c200228022010fc01200241003602d001200242013703c8012002200c360228200c41a0026c210d200241286a200241c8016a103020022802cc01210820022802d00121014100210a034020022005200a6a3602a001200241286a200241a0016a10bf022002280228210702400240200820016b20022802302206490d00200120066a210020022802c801210b0c010b200120066a22002001490d052008410174220b20002000200b491b22094100480d050240024020080d0020091027210b0c010b20022802c801200820091028210b0b200b450d04200220093602cc012002200b3602c801200921080b200220003602d001200b20016a2007200610ce041a0240200228022c450d00200710290b20002101200d200a41a0026a220a470d000b200c41a0026c210a410021010340200520016a4198016a103d200a200141a0026a2201470d000b20051029200241b0026a24002000ad422086200bad840f0b418f89c3004133104e000b41c0044108102a000b20094101102a000b102b000bad0201077f230041106b2202240020012802042103024002400240024003402001280200220441086a210520042f01062206410374210141002107024003402001450d0141e4cac5002005410810d0042208450d03200141786a2101200741016a2107200541086a21052008417f4a0d000b2007417f6a21060b02402003450d002003417f6a2103200420064102746a41e4016a21010c010b0b200041eccac500360204200041086a41283602000c010b20042007410c6c6a220141e0006a2802002105200141e8006a280200210120024200370308200241086a20052001410820014108491b10ce041a200141074b0d0120004194cbc500360204200041086a41293602000b410121010c010b200041086a2002290308370300410021010b20002001360200200241106a24000bb91e08067f017e057f017e047f027e027f017e230041b0026b22022400024002402001450d00200220003602100c010b200241b8d6c5003602100b20022001360214200241c8006a200241106a108e020240024020022802502203450d00200241d8006a280200210420022802542105200241c8006a200241106a1048200228024822060d0102402004450d00200441246c21002003210103400240024020012d0000220741034b0d0002400240024020070e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b2005450d00200310290b200241dc006a41013602002002420137024c200241cc81c200360248200241023602d4012002419c83c2003602d0012002200241d0016a360258200241c8006a41d481c2001057000b200229024c2108200241c8006a200241106a10fb01024020022802482201450d002002200229024c37021c20022001360218200241013b01342002420037022c2002418883c000360228200241286a41086a21090240024002400240024002402008422088a7220a450d002006200a41a0026c6a210b200241d0016a410272210c2006210d0340200d41e8006a2903004202520d010240024002400240024002400240024002400240024002400240200d2802980122014102470d00200d2903a001210e200241186a2101200228021c210f024002400240024003402001280200221041086a210020102f010622114103742101410021070240024003402001450d0141f6c4c5002000410810d0042212450d02200141786a2101200741016a2107200041086a21002012417f4a0d000b2007417f6a21110b200f450d02200f417f6a210f201020114102746a41e4016a21010c010b0b20102007410c6c6a220141e0006a2802002100200141e8006a280200210120024200370348200241c8006a20002001410820014108491b10ce041a0240200141074b0d00201342808080807083422984210e41fec4c50021110c020b200e42f20c8020022903482213510d0341a08fc30021114131210f0c020b201342808080807083421c84210e41a7c5c50021110b200ea7210f0b024002400240024020022d0035450d00413121014195fac10021000c010b2002280228200228022c200228023010fc012002420037022c2002418883c000360228200242e2c289abb68edbb7f400370338200241d0016a410272410041da0010cd041a200241c8006a410041840110cd041a41e40110272212450d0520124100360200201241046a200241d0016a41dc0010ce041a201241e0006a200241c8006a41840110ce041a2002410036022c2002201236022820122f0106220d4103742110417f210041002101024002400340024020102001470d00200d21000c020b200241386a201220016a41086a410810d0042207450d02200141086a2101200041016a2100200741004e0d000b0b200242e2c289abb68edbb7f40037025c20022009360258200220003602542002201236024c200241003602482002200241286a360250200241003602d801200242013703d0012002200f360238200241386a200241d0016a103020022802d401220020022802d80122016b200f490d0220022802d00121000c030b412d210141c6fac10021000b2002200136024c2002200036024841f3fac1004122200241c8006a4198fbc10010a201000b2001200f6a22072001490d1220004101742212200720072012491b22074100480d120240024020000d002007102721000c010b20022802d00120002007102821000b2000450d04200220073602d401200220003602d0010b20022001200f6a3602d801200020016a2011200f10ce041a200241386a41086a20022802d801360200200220022903d001370338200241c8006a200241386a10fd0120024180023b0134200241d0016a41086a200241286a41086a290300370300200220022903283703d0010c100b200d2802980121010b20014102470d0b200d2903a0012114200241c8006a200241186a10cf020240024020022802484101470d002002350250210e200228024c2115410121160c010b2002290350210e200241ceecc200410d10940102402014200e423c7c560d00410021162014200229030842b9067c42b90620022802001b220e540d010c0d0b201742808080807083422584210e410121164199efc20021150b024020022d0035450d00413121014195fac10021000c050b02402016450d002002280228200228022c200228023010fc012002420037022c2002418883c000360228200242f4d2b59bc7ae98b8303703380c030b20022802282112200242f4d2b59bc7ae98b8303703382012418883c000460d02200228022c210f0c030b41e4014104102a000b20074101102a000b200c410041da0010cd041a200241c8006a410041840110cd041a41e40110272212450d034100210f20124100360200201241046a200241d0016a41dc0010ce041a201241e0006a200241c8006a41840110ce041a2002410036022c200220123602280b034020122f010622114103742110417f210041002101024002400340024020102001470d00201121000c020b200241386a201220016a41086a410810d0042207450d02200141086a2101200041016a21002007417f4a0d000b0b200f450d03200f417f6a210f201220004102746a41e4016a28020021120c010b0b412d210141c6fac10021000b2002200136024c2002200036024841f3fac1004122200241c8006a4198fbc10010a201000b200242f4d2b59bc7ae98b83037025c20022009360258200220003602542002201236024c200241003602482002200241286a360250200241003602d801200242013703d0014101102721010240024020160d002001450d03200141003a000020024281808080103702d401200220013602d00120014101410910282201450d042001200e3700012002428980808090013702d401200220013602d0010c010b2001450d04200141013a000020024281808080103702d401200220013602d0012002200ea72201360238200241386a200241d0016a10300240024020022802d401220720022802d80122006b2001490d0020022802d00121070c010b200020016a22122000490d0b20074101742210201220122010491b22124100480d0b0240024020070d002012102721070c010b20022802d00120072012102821070b2007450d06200220123602d401200220073602d0010b2002200020016a3602d801200720006a2015200110ce041a0b200241386a41086a200241d0016a41086a280200360200200220022903d001370338200241c8006a200241386a10fd01200220163a0035200241003a0034200e21172016450d05200241d0016a41086a200241286a41086a290300370300200220022903283703d0010c080b41e4014104102a000b41014101102a000b41094101102a000b41014101102a000b20124101102a000b200d41a0026a220d200b470d000b0b200241d0016a41086a2009290300370300200220022903283703d0010b2002280218200228021c200228022010fc0102402004450d00200441246c21002003210103400240024020012d0000220741034b0d0002400240024020070e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b02402005450d00200310290b2008a721070240200a450d00200a41a0026c210020064198016a210103402001103d200141a0026a2101200041e07d6a22000d000b0b02402007450d00200610290b2002410036025020024201370348410110272201450d03200242818080801037024c20022001360248200120022d00dc013a000020014101410210282201450d02200242828080802037024c20022001360248200120022d00dd013a000120022802d801210d20014102410610282212450d0120024286808080e00037024c200220123602482012200d36000220022802d00122072100024020022802d4012210450d002010210120072100034020002802e40121002001417f6a22010d000b0b0240024002400240200d0d004280808080e000210e0c010b41062110200241d0016a210b4106210f41002111034002400240201120002f01064f0d0020002011410c6c6a41e0006a2101200020114103746a41086a2107201141016a21110c010b02400240200028020022010d00201742808080807083200bad84211741002107410021010c010b2000330104422086200bad842117410121070b201721142017210e02402017422088a7220020012f0106490d000340200e221442ffffffff0f83210e200741016a210720012f01042200200128020022012f01064f0d000b0b20012000410c6c6a2111200120004103746a2116200041027420016a41e8016a28020021002014a7210b02402007417f6a2201450d00034020002802e40121002001417f6a22010d000b0b201141e0006a2101201641086a2107410021110b02402010200f6b41074b0d00200f41086a2216200f490d0520104101742204201620162004491b22164100480d050240024020100d002016102721120c010b201220102016102821120b2012450d032002201636024c200220123602480b2002200f41086a3602502012200f6a200729000037000020012802002116200220012802082201360228200241286a200241c8006a103002400240200228024c2210200228025022076b2001490d00200228024821120c010b200720016a22122007490d052010410174220f20122012200f491b220f4100480d050240024020100d00200f102721120c010b20022802482010200f102821120b2012450d042002200f36024c20022012360248200f21100b2002200720016a220f360250201220076a2016200110ce041a200d417f6a220d0d000b200fad422086210e20022802d401211020022802d00121070b2007201020022802d80110fc01200241b0026a2400200e2012ad840f0b20164101102a000b200f4101102a000b102b000b41064101102a000b41024101102a000b41014101102a000b200241dc006a41013602002002420137024c200241cc81c200360248200241023602d4012002419c83c2003602d0012002200241d0016a360258200241c8006a41d481c2001057000b7701027f230041206b22022400200241b8d6c500410010db0102404120102722030d0041204101102a000b20032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a290300370000200241206a24002003ad42808080808004840bcf4c040b7f027e127f067e230041c00a6b22022400024002402001450d00200220003602400c010b200241b8d6c5003602400b20022001360244200241e8066a200241c0006a104902400240024002400240024002400240024002400240024002400240024002400240024020022903d0074203510d00200241c8006a200241e8066a41a00210ce041a200241e8026a200241c8006a41a00210ce041a2002200241e8026a36028805200241e8066a20024188056a10bf0220022802f0062100024020022802ec06450d0020022802e80610290b200241e8066a200241e8026a41a00210ce041a20024188056a200241e8066a10860202402002280288054101470d00200228029005416b6a220141054b0d10200228028c05210002400240024020010e06001313131301000b4102210341f601210120004184efc200460d0120004184efc200411510d004450d010c120b410021010240200041a981c200470d00410021030c130b41002103200041a981c200411a10d0040d110b0c110b200241e8066a20024190056a41d80110ce041a200241386a200241b8076a220410ac020240024002402002290388074202520d0041c00110272201450d04200141013a00b801200142003703b00120014280808080c0003703a801200142043703a0012001427f3703980120014200370390012001420137038801200142003703800120014280808080c000370378200142043703702001427f37036820014200370360200142013703582001420037035020014280808080c000370348200142043703402001427f37033820014200370330200142013703282001420037032020014280808080c000370318200142043703102001427f37030820014200370300200141bc016a20024188056a41036a28000036000020012002280088053600b9012002200141c0016a36028c0a200220013602880a200241043602840a200220013602800a200241900a6a41206a22054200370300200241900a6a41186a22064280808080c000370300200241013a00b80a200242043703a00a2002427f3703980a200242003703900a200241c8096a41086a22072001290308370300200241c8096a41106a22082001290310370300200241c8096a41186a22032001290318370300200241c8096a41206a22092001290320370300200220012903003703c809200220012800293602f80920022001412c6a2800003600fb09200141306a210020012d0028220a4102460d1020024188096a41286a220b200241900a6a41286a220c29030037030020024188096a41206a200529030037030020024188096a41186a200629030037030020024188096a41106a200241900a6a41106a29030037030020024188096a41086a200241900a6a41086a290300370300200220022903900a3703880920024188056a41206a200929030037030020024188056a41186a200329030037030020024188056a41106a200829030037030020024188056a41086a2007290300370300200220022903c809370388052002200a3a00b005200241b1056a220a20022802f809360000200a41036a20022800fb09360000200241900a6a20024188096a20024188056a10d3022007200041086a2903003703002008200041106a2903003703002003200041186a2903003703002009200041206a290300370300200220002903003703c809200220012800593602f8092002200141dc006a2800003600fb09200141e0006a210020012d005822074102470d010c100b20022d003c21032002280238210841c00110272205450d0420022903a007210d411310272201450d052001410f6a41002800d68d43360000200141086a41002900cf8d43370000200141002900c78d4337000020014113413310282201450d06200120022903e8063700132001412b6a20024180076a290300370000200141236a200241f8066a2903003700002001411b6a200241e8066a41086a290300370000200241286a200141331089022002290330210e20022802282106200110290240024002400240200e420020061b220e200d560d00410c10272206450d0b412010272201450d0c200120022903e806370000200141186a200241e8066a41186a290300370000200141106a200241e8066a41106a290300370000200141086a200241e8066a41086a2903003700002001412041c00010282201450d0d2001200d37002041042107200641046a42c0808080800537020020062001360200410021010240200e200d5a0d00410c10272207450d0f412010272201450d10200120022903e806370000200141186a200241e8066a41186a290300370000200141106a200241e8066a41106a290300370000200141086a200241e8066a41086a2903003700002001412041c00010282201450d112001200d427f7c370020200742c0808080800537020420072001360200410121010b20022002280088053602800a20022002418b056a220b2800003600830a200220022802800a3602f809200220022800830a3600fb09200241206a41c1cdc500411710b501417f2002280224410020022802201b220920006a220a200a2009491b418080c002418080f001200341017122031b4b0d01200241186a41a7cdc500411a10b501417f200228021c410020022802181b220a418094ebdc034180afd0e50220031b2209200820092008491b6a220c200c200a491b20094b0d0120022002280088053602900a20022002418b056a2800003600930a200220022802900a3602c809200220022800930a3600cb0920024188056a20022903a807200241b0076a290300200241e8066a20082003200010960120022d0088054101460d02200541013a005820054281808080103703502005200636024c2005200136024820052001360244200520073602402005427f37033820052008ad220d370330200542013703282005420037032020054280808080c000370318200542043703102005427f37030820054200370300200520022802f809360059200541dc006a220f20022800fb09360000200541013a008801200542003703800120054280808080c000370378200542043703702005427f3703682005427f200d20031b370360200520022802c809360089012005418c016a20022800cb0936000020052002290390053703900120054198016a20024188056a41106a2200290300370300200541a0016a20024188056a41186a2206290300370300200541a8016a20024188056a41206a2207290300370300200541b0016a20024188056a41286a2208290300370300200541b8016a20024188056a41306a2903003703002002200541c0016a36028c0a200220053602880a200241043602840a200220053602800a200241900a6a41206a22034200370300200241900a6a41186a22094280808080c000370300200241013a00b80a200242043703a00a2002427f3703980a200242003703900a200241c8096a41086a220a2005290308370300200241c8096a41106a220b2005290310370300200241c8096a41186a220c2005290318370300200241c8096a41206a22102005290320370300200220052903003703c809200220052800293602f80920022005412c6a2800003600fb09200541306a210120052d002822114102460d1120024188096a41286a200241900a6a41286a29030037030020024188096a41206a200329030037030020024188096a41186a200929030037030020024188096a41106a200241900a6a41106a29030037030020024188096a41086a200241900a6a41086a290300370300200220022903900a37038809200720102903003703002006200c2903003703002000200b29030037030020024188056a41086a200a290300370300200220022903c80937038805200220113a00b005200241b1056a221120022802f809360000201141036a221220022800fb09360000200241900a6a20024188096a20024188056a10d302200a200141086a290300370300200b200141106a290300370300200c200141186a2903003703002010200141206a290300370300200220012903003703c809200220052800593602f8092002200f2800003600fb09200541e0006a210120052d0058220a4102470d050c110b20022002280088053602800a20022002418b056a2800003600830a20024181083b0188092005102941012101410421080c020b20022002280088053602900a2002200b2800003600930a20024181023b01880902402001450d002001410c6c21002007210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b200710290b0240200641046a280200450d00200628020010290b200610292005102941012108410121010c100b200220022d00890522083a008909200241013a00880902402001450d002001410c6c21002007210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b200710290b0240200641046a280200450d00200628020010290b2006102920051029410121010b0c0e0b200b200c29030037030020024188096a41206a220c200241900a6a41206a221029030037030020024188096a41186a2211200241900a6a41186a220f29030037030020024188096a41106a2212200241900a6a41106a221329030037030020024188096a41086a2214200241900a6a41086a2215290300370300200220022903900a3703880920024188056a41206a2216200241c8096a41206a220829030037030020024188056a41186a2217200241c8096a41186a220329030037030020024188056a41106a2218200241c8096a41106a220929030037030020024188056a41086a2219200241c8096a41086a220b290300370300200220022903c80937038805200220073a00b005200a20022802f809360000200a41036a220720022800fb09360000200241900a6a20024188096a20024188056a10d302200b200041086a2903003703002009200041106a2903003703002003200041186a2903003703002008200041206a290300370300200220002903003703c80920022001280089013602f80920022001418c016a2800003600fb0920014190016a210020012d008801221a4102460d0e20024188096a41286a221b200241900a6a41286a221c290300370300200c20102903003703002011200f2903003703002012201329030037030020142015290300370300200220022903900a370388092016200829030037030020172003290300370300201820092903003703002019200b290300370300200220022903c809370388052002201a3a00b005200a20022802f809360000200720022800fb09360000200241900a6a20024188096a20024188056a10d302200b200041086a2903003703002009200041106a2903003703002003200041186a2903003703002008200041206a290300370300200220002903003703c809200220012800b9013602f8092002200141bc016a2800003600fb09200141c0016a210020012d00b80122014102460d0e201b201c29030037030020024188096a41206a200241900a6a41206a29030037030020024188096a41186a200241900a6a41186a29030037030020024188096a41106a200241900a6a41106a29030037030020024188096a41086a200241900a6a41086a290300370300200220022903900a3703880920024188056a41206a200241c8096a41206a29030037030020024188056a41186a200241c8096a41186a29030037030020024188056a41106a200241c8096a41106a29030037030020024188056a41086a200241c8096a41086a290300370300200220022903c80937038805200220013a00b005200a20022802f809360000200a41036a20022800fb09360000200241900a6a20024188096a20024188056a10d3020c0e0b20024188096a41286a2213200241900a6a41286a221429030037030020024188096a41206a2215200241900a6a41206a221629030037030020024188096a41186a2217200241900a6a41186a221829030037030020024188096a41106a2219200241900a6a41106a221a29030037030020024188096a41086a221b200241900a6a41086a221c290300370300200220022903900a3703880920024188056a41206a221d200241c8096a41206a220b29030037030020024188056a41186a221e200241c8096a41186a220c29030037030020024188056a41106a221f200241c8096a41106a221029030037030020024188056a41086a2220200241c8096a41086a220f290300370300200220022903c809370388052002200a3a00b005201120022802f809360000201220022800fb09360000200241900a6a20024188096a20024188056a10d302200f200141086a2903003703002010200141106a290300370300200c200141186a290300370300200b200141206a290300370300200220012903003703c80920022005280089013602f80920022005418c016a2800003600fb0920054190016a210120052d008801220a4102460d0b2013201429030037030020152016290300370300201720182903003703002019201a290300370300201b201c290300370300200220022903900a37038809201d200b290300370300201e200c290300370300201f20102903003703002020200f290300370300200220022903c809370388052002200a3a00b005201120022802f809360000201141036a220a20022800fb09360000200241900a6a20024188096a20024188056a10d302200f200141086a2903003703002010200141106a290300370300200c200141186a290300370300200b200141206a290300370300200220012903003703c809200220052800b9013602f8092002200541bc016a2800003600fb09200541c0016a210120052d00b80122054102460d0b20024188096a41286a200241900a6a41286a29030037030020024188096a41206a200241900a6a41206a29030037030020024188096a41186a200241900a6a41186a29030037030020024188096a41106a200241900a6a41106a29030037030020024188096a41086a200241900a6a41086a290300370300200220022903900a3703880920024188056a41206a200241c8096a41206a29030037030020024188056a41186a200241c8096a41186a29030037030020024188056a41106a200241c8096a41106a29030037030020024188056a41086a200241c8096a41086a290300370300200220022903c80937038805200220053a00b005201120022802f809360000200a20022800fb09360000200241900a6a20024188096a20024188056a10d3020c0b0b200241fc026a4101360200200242013702ec02200241cc81c2003602e8022002410236024c200241b483c2003602482002200241c8006a3602f802200241e8026a41d481c2001057000b41c0014108102a000b41c0014108102a000b41134101102a000b41334101102a000b410c4104102a000b41204101102a000b41c0004101102a000b410c4104102a000b41204101102a000b41c0004101102a000b20024188056a41086a2205200241900a6a41086a2903003703002000200241900a6a41106a29030037030020062009290300370300200720032903003703002008200241900a6a41286a290300370300200220013602880a200220022903900a37038805200241800a6a103a20024188096a41086a200229038805222137030020024188096a41106a2005290300220e37030020024188096a41186a2000290300220d37030020024188096a41206a200629030037030020024188096a41286a200729030037030020024188096a41306a200829030037030041002101200241003a008809200da7210c20022d00890921080b200241b8096a2d0000210f200241b4096a2802002109200241b0096a2802002110200241ac096a280200210b200241a8096a280200210a200241a4096a2802002111024020010d00410121030c020b42bcf7ea858cf8afdfbd7f2008410473ad42078342038688a72101410021030c010b20024188056a41086a2201200241900a6a41086a29030037030020024188056a41106a2207200241900a6a41106a29030037030020024188056a41186a2208200629030037030020024188056a41206a2206200529030037030020024188056a41286a2205200241900a6a41286a290300370300200220003602880a200220022903900a37038805200241800a6a103a20024188096a41106a2001290300220d37030020024188096a41186a2201200729030037030020024188096a41206a2200200829030037030020024188096a41286a2208200629030037030020024188096a41306a220620052903003703002002200229038805220e37039009200241003a008809200241800a6a41086a200d3703002002200e3703800a20024188096a412c6a28020021072008280200210b200241ac096a280200210920002802002108200241a4096a280200210c2001280200210a024002400240024002400240024020022802b8074111470d002006290300210d20024188056a41086a22014200370300200242003703880541d2c5c500411020024188056a1004200241900a6a41086a200129030037030020022002290388053703900a2002410036028805200241900a6a411020024188056a10052101024002402002280288052200417f460d002001450d00200220003602cc09200220013602c80920024188056a200241c8096a10412002280288052210450d0320024190056a2802002111200228028c05210f2000450d01200110290c010b41082110410021114100210f0b200241e4076a21002010201141286c6a210320102101024003400240200320016b41f8004b0d00024020032001460d002010201141286c6a2103200241e4076a210503404101210620052001460d0420012000412010d004450d042003200141286a2201470d000b0b410021060c020b4101210620012000460d0120012000412010d004450d01200141286a22052000460d0120052000412010d004450d01200141d0006a22052000460d0120052000412010d004450d01200141f8006a22052000460d01200141a0016a210120052000412010d0040d000b0b0240200f450d00201010290b2006450d00200241106a4193c8c500411410b50120024188056a2002280214410020022802101b200010b201200228028805220520022802900541b8d6c50041004100100b21010240200228028c05450d00200510290b2001417f470d0020024190086a28020041c000470d00200228028808220141086a290000210e200141106a2900002121200141186a2900002122200141206a2900002123200141286a2900002124200141306a29000021252001290000212620024188056a41386a200141386a29000037030020024188056a41306a202537030020024188056a41286a202437030020024188056a41206a202337030020024188056a41186a202237030020024188056a41106a202137030020024188056a41086a200e3703002002202637038805200241003602980a200242013703900a20022903c007210e410810272201450d022001200e3700002002428880808080013702940a200220013602900a200241c8076a200241900a6a1061200241e0076a28020021100240024020022802940a220520022802980a22066b4104490d0020022802900a21010c010b200641046a22012006490d0b20054101742203200120012003491b22034100480d0b0240024020050d002003102721010c010b20022802900a20052003102821010b2001450d04200220033602940a200220013602900a200321050b2002200641046a22033602980a200120066a201036000002400240200520036b411f4d0d00200521100c010b200341206a22102003490d0b20054101742211201020102011491b22104100480d0b0240024020050d002010102721010c010b200120052010102821010b2001450d05200220103602940a200220013602900a0b200120036a22052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a29000037000002402001200641246a220520024188056a200010140d00200241086a4193c8c500411410b50120022802e007200228020c410020022802081b490d00410c102722000d06410c4104102a000b2010450d00200110290b02402008450d002008410c6c2100200a210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b0b0240200c450d00200a10290b02402007450d002007410c6c21002009210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b0b42002121427f210e4104210c0240200b450d00200910290b4100210a4101210f410121094101211041002111410021030c050b418f89c3004133104e000b41084101102a000b20034101102a000b20104101102a000b200020053602082000201036020420002001360200200220022802f8093602c009200220022800fb093600c309200241900a6a41206a428180808010370300200241900a6a41186a4100360200200241bc0a6a20022800c30936000041012103200241013a00b80a200220003602ac0a200242043703a00a2002427f3703980a200242003703900a200220022802c0093600b90a20024188056a41246a200736020020024188056a41206a200b36020020024188056a41186a200836020020024188056a41146a200c36020020024188056a41086a200241800a6a41086a2903003703002002200d3703b005200220093602a4052002200a36029805200220022903800a37038805200241c8096a200241900a6a20024188056a10d302200241c8096a41146a2802002111200241c8096a41186a280200210a200241c8096a41206a2802002110200241c8096a41246a280200210920022903c809212120022903d009210e20022802d809210c20022802e409210b20022d00f009210f0b410021010b2004103d0c010b4100210341810121010b200241003602f0064201210d200242013703e806024002400240024002400240024002400240024002400240200341024d0d004200210e0c010b024002400240024020030e03000102000b410110272200450d04200241013602ec06200220022802f006220541016a3602f006200220003602e806200020056a41003a00000240024020022802ec0620022802f0062200460d0020022802e80621050c010b200041016a22052000490d0f20004101742204200520052004491b22044100480d0f0240024020000d002004102721050c010b20022802e80620002004102821050b2005450d06200220043602ec06200220053602e80620022802f00621000b2002200041016a3602f006200520006a20013a00000c020b410110272201450d05200241013602ec06200220022802f006220041016a3602f006200220013602e806200120006a41013a00000240024020022802ec06220020022802f00622016b4108490d0020022802e80621000c010b200141086a22052001490d0e20004101742201200520052001491b22014100480d0e0240024020000d002001102721000c010b20022802e80620002001102821000b2000450d07200220013602ec06200220003602e80620022802f00621010b2002200141086a3602f006200020016a20213700002002200a3602e802200241e8026a200241e8066a10300240200a450d00200c200a410c6c6a2108200c21050340200528020021062002200541086a28020022013602e802200241e8026a200241e8066a10300240024020022802ec06220420022802f00622006b2001490d0020022802e80621040c010b200020016a22072000490d1020044101742200200720072000491b22004100480d100240024020040d002000102721040c010b20022802e80620042000102821040b2004450d0a200220003602ec06200220043602e80620022802f00621000b2002200020016a3602f006200420006a2006200110ce041a2005410c6a22052008470d000b0b200220093602e802200241e8026a200241e8066a103002402009450d00200b2009410c6c6a2108200b21050340200528020021062002200541086a28020022013602e802200241e8026a200241e8066a10300240024020022802ec06220420022802f00622006b2001490d0020022802e80621040c010b200020016a22072000490d1020044101742200200720072000491b22004100480d100240024020040d002000102721040c010b20022802e80620042000102821040b2004450d0b200220003602ec06200220043602e80620022802f00621000b2002200020016a3602f006200420006a2006200110ce041a2005410c6a22052008470d000b0b0240024020022802ec06220020022802f00622016b4108490d0020022802e80621000c010b200141086a22052001490d0e20004101742201200520052001491b22014100480d0e0240024020000d002001102721000c010b20022802e80620002001102821000b2000450d0a200220013602ec06200220003602e80620022802f00621010b2002200141086a3602f006200020016a200e3700000240024020022802ec0620022802f0062201460d0020022802e80621000c010b200141016a22002001490d0e20014101742205200020002005491b22054100480d0e0240024020010d002005102721000c010b20022802e80620012005102821000b2000450d0b200220053602ec06200220003602e80620022802f00621010b2002200141016a3602f006200020016a200f3a00000c010b410110272200450d0a200241013602ec06200220022802f006220541016a3602f006200220003602e806200020056a41023a00000240024020022802ec0620022802f0062200460d0020022802e80621050c010b200041016a22052000490d0d20004101742204200520052004491b22044100480d0d0240024020000d002004102721050c010b20022802e80620002004102821050b2005450d0c200220043602ec06200220053602e80620022802f00621000b2002200041016a3602f006200520006a20013a00000b20023502f006422086210e20023502e806210d0b024020034101470d000240200a450d00200a410c6c2100200c210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b0b02402011450d00200c10290b02402009450d002009410c6c2100200b210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b0b2010450d00200b10290b200241c00a6a2400200e200d840f0b41014101102a000b20044101102a000b41014101102a000b20014101102a000b20004101102a000b20004101102a000b20014101102a000b20054101102a000b41014101102a000b20044101102a000b102b000b980505017f027e077f017e017f230041106b220324002002290300210420012903002105200141106a21062002280210210702400240024002400240200141146a2802002208200141186a28020022096b200241186a280200220a490d00200628020021080c010b2009200a6a220b2009490d032008410174220c200b200b200c491b220bad420c7e220d422088a70d03200da7220c4100480d030240024020080d00200c102721080c010b20062802002008410c6c200c102821080b2008450d0120012008360210200141146a200b3602000b20082009410c6c6a2007200a410c6c10ce041a200141186a2009200a6a36020020024100360218200341086a200641086a280200360200200320062902003703002001411c6a2106200228021c210b02400240200141206a2802002208200141246a28020022096b200241246a280200220a490d00200628020021080c010b2009200a6a220c2009490d032008410174220e200c200c200e491b220cad420c7e220d422088a70d03200da7220e4100480d030240024020080d00200e102721080c010b20062802002008410c6c200e102821080b2008450d022001200836021c200141206a200c3602000b20082009410c6c6a200b200a410c6c10ce041a200141246a2009200a6a360200200241003602242000427f200520047c220420042005541b37030020002003290300370210200041186a200341086a2802003602002000200629020037021c200041246a200641086a280200360200200020022d0028410020012d00281b3a00282000200229030822052001290308220420042005561b3703080240200241146a280200450d00200710290b0240200241206a280200450d00200b10290b200341106a24000f0b200c4104102a000b200e4104102a000b102b000be41807017f027e027f017e017f017e0e7f23004180046b2202240020024200370368200241e8006a200041b8d6c50020011b2001410820014108491b10ce041a0240024002400240024002400240024002400240024002400240024002400240024002400240200141074d0d0020022903682103200241186a41d9b0c0004111109401200229032021042002280218210041002105200241003602684101210641014185b1c000411c200241e8006a101721012004420020001b2107024002400240024020022802682200417f470d0041012100410121060c010b2000ad2204422086200484210420014521002001450d00200241003a0068200241e8006a20012004422088a72206410047220510ce041a20062005490d042006450d0120022d0068210820024200370368200241e8006a200120056a200620056b2206410820064108491b10ce041a200641074d0d01200229036822092007542009200354200841ff01711b2106200121050b0240200720035a0d0020060d020b20002004a745720d14200510290c140b02402004a7450d00200110290b41b284c500412d10100c130b410110272201450d02200141003a000020014101410910282201450d032001200337000141014185b1c000411c4100200520001b22062004422088a7417f20061b200141091018210620011029024020002004a745720d00200510290b20060d12200241003602484201200241c8006a1019210020022802482201417f460d1220022000360288032002200136028c03200241003a0068200241e8006a20002001410047220610ce041a20012006490d042002200120066b36028c032002200020066a360288032001450d124100210a0240024020022d0068450d000c010b200241e8006a20024188036a10440240200228026822010d000c010b200229026c21042001210a0b20001029200a450d1241002106200241e8006a2004422088a72200412020004120491b22016a41004100412020016b2001411f4b1b10cd041a200241e8006a200a200110ce041a2004a7210b2000411f4d0d11200241306a200241f1006a290000370300200241386a200241f9006a2900003703002002413f6a20024180016a2900003700002002200229006937032820022d0068210c20024100360248200241c8006a101a210020022802482201417f460d1020022000360288032002200136028c03200241003a0068200241e8006a20002001410047220610ce041a20012006490d052002200120066b36028c032002200020066a3602880302400240024002402001450d0020022d0068220641014b0d004100210d024020060e020003000b200241e8006a20024188036a10442002280268220d450d00200229026c2109200241106a20024188036a102e2009a7210e02402002280210450d00024002402002280214220f41d502200f41d502491b22100d00410421110c010b2010410c6c220610272211450d0c0b0240200f450d004100211241002106410021080340200241e8006a20024188036a10440240200228026822130d0002402008450d002011210503400240200541046a280200450d00200528020010290b2005410c6a2105200641746a22060d000b0b2010450d03201110290c030b200841016a2105200229026c2104024020082010470d002012200520052012491b2210ad420c7e2207422088a70d152007a722144100480d150240024020080d002014102721110c010b201120062014102821110b2011450d0f0b201120066a22082013360200200841046a2004370200201241026a21122006410c6a210620052108200f2005470d000b0b20110d020b200e450d00200d10290b4100210d0c020b200fad4220862010ad8421042009422088a7210f0b2004422088a721142004a721150b02402001450d00200010290b200d450d10200241086a4193c8c500411410b501200241c8006a41086a200241286a41086a290300370300200241c8006a41106a200241286a41106a290300370300200241c8006a41176a200241286a41176a29000037000020022002290328370348200228020c2116200228020821172002420137036820024100360270410810272201450d0820024288808080800137026c20022001360268200120033700002002200f3602880320024188036a200241e8006a103002400240200228026c2200200228027022016b200f490d00200228026821000c010b2001200f6a22062001490d0e20004101742205200620062005491b22064100480d0e0240024020000d002006102721000c010b200228026820002006102821000b2000450d0a2002200636026c200220003602680b20022001200f6a360270200020016a200d200f10ce041a200220143602880320024188036a200241e8006a10300240024020140d00200228026c2105200228027021130c010b20112014410c6c6a2110201121000340200028020021122002200041086a28020022013602880320024188036a200241e8006a103002400240200228026c2205200228027022066b2001490d00200228026821080c010b200620016a22082006490d1020054101742213200820082013491b22134100480d100240024020050d002013102721080c010b200228026820052013102821080b2008450d0d2002201336026c20022008360268201321050b2002200620016a2213360270200820066a2012200110ce041a2000410c6a22002010470d000b0b02400240200520136b4104490d00200228026821010c010b201341046a22012013490d0e20054101742200200120012000491b22004100480d0e0240024020050d002000102721010c010b200228026820052000102821010b2001450d0c2002200036026c20022001360268200021050b2002201341046a2200360270200120136a2016410020171b220836000002400240200520006b411f4d0d00200521060c010b200041206a22062000490d0e20054101742212200620062012491b22064100480d0e0240024020050d002006102721010c010b200120052006102821010b2001450d0d2002200636026c200220013602680b200120006a2200200c3a000020002002290348370001200041096a200241d0006a290300370000200041116a200241d8006a290300370000200041186a200241df006a2900003700002002410036026842012001201341246a200241e8006a101b2100024002400240024020022802682205417f470d0020060d010c020b02402000450d0002402006450d00200110290b200241e8006a2002418e036a41e80010ce041a200241ac026a200c3a0000200241a8026a2008360200200241a4026a2014360200200241a0026a20153602002002419c026a201136020020024198026a200f36020020024194026a200e36020020024190026a200d36020020024188026a2003370300200241b5026a200241d0006a290300370000200241bd026a200241d8006a290300370000200241c4026a200241df006a2900003700002002411136028002200242023703d001200220022903483700ad02200241d8026a2005360200200241d4026a2005360200200241d0026a20003602002002200241e8006a3602fc0320024188036a200241fc036a10bf022002280288032200200228029003101c21010240200228028c03450d00200010290b2001450d0320024180026a103d410521060c150b2006450d010b200110290b0240200e450d00200d10290b02402014450d002014410c6c21002011210103400240200141046a280200450d00200128020010290b2001410c6a2101200041746a22000d000b0b410321062015450d12201110290c120b410110272201450d0e200141013a000020014101410910282201450d0f2001200337000141014185b1c000411c20014109101d2001102920024180026a103d200b450d12200a10290c120b200241fc006a41013602002002420137026c200241cc81c2003602682002410236028c03200241d083c20036028803200220024188036a360278200241e8006a41d481c2001057000b20052006103e000b41014101102a000b41094101102a000b20062001103e000b20062001103e000b20064104102a000b20144104102a000b41084101102a000b20064101102a000b20134101102a000b20004101102a000b20064101102a000b102b000b41014101102a000b41094101102a000b410421060b0240200b450d00200a10290b02400240024002400240024020060e06010203040500010b41d883c500412e10100c050b418684c500412c10100c040b41b284c500412d10100c030b41df84c500412a10100c020b418985c500411f10100c010b41a885c500412e10100b20024180046a240042010be60905027f027e027f017e067f230041d0006b22022400024002402001450d00200220003602080c010b200241b8d6c5003602080b2002200136020c200241206a200241086a1043024002400240024002400240024020022802202203450d002002200229022422043702142002200336021020024101360248200241d6a1c10036024c200241206a200241106a200241c8006a105f02400240200229032022054205510d00200241386a2802002101200241306a280200210620022802342107024020054200520d0020022903282108200621090c020b2005a7220041014b0d000240024020000e020001000b2007450d01200610290c010b200228023c450d00200110290b41002106410021090b200241003602282002420137032041011027210a0240024020090d00200a450d0320024281808080103702242002200a360220200a41003a000042808080801021050c010b200a450d0320024281808080103702242002200a360220200a41013a000020022001360248200241c8006a200241206a10300240024020010d002002280224210b200228022821000c010b2009200141286c6a210c2002280224210b2002280228210020092101034002400240200b20006b4120490d00200041206a210d2002280220210a0c010b200041206a220d2000490d0a200b410174220a200d200d200a491b220e4100480d0a02400240200b0d00200e1027210a0c010b2002280220200b200e1028210a0b200a450d072002200e3602242002200a360220200e210b0b200a20006a220041186a200141186a290000370000200041106a200141106a290000370000200041086a200141086a2900003700002002200d36022820002001290000370000200141206a290300210502400240200b200d6b4108490d00200d41086a21000c010b200d41086a2200200d490d0a200b410174220e20002000200e491b220e4100480d0a02400240200b0d00200e1027210a0c010b200a200b200e1028210a0b200a450d082002200e3602242002200a360220200e210b0b20022000360228200a200d6a2005370000200c200141286a2201470d000b0b02400240200b20006b4108490d002002280220210a0c010b200041086a22012000490d08200b410174220d20012001200d491b22014100480d0802400240200b0d0020011027210a0c010b2002280220200b20011028210a0b200a450d07200220013602242002200a3602200b2002200041086a2201360228200a20006a20083700002001ad42208621052009450d002007450d00200610290b2004a7210b02402004422088a72201450d00200141246c21002003210103400240024020012d0000220d41034b0d00024002400240200d0e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b0240200b450d00200310290b200241d0006a24002005200aad840f0b200241346a410136020020024201370224200241cc81c20036022020024102360214200241e883c2003602102002200241106a360230200241206a41d481c2001057000b41014101102a000b41014101102a000b200e4101102a000b200e4101102a000b20014101102a000b102b000ba90a03027f047e077f230041d0006b22022400024002402001450d00200220003602080c010b200241b8d6c5003602080b2002200136020c200241206a200241086a10430240024002400240024002400240024020022802202203450d002002200229022422043702142002200336021020024101360248200241d6a1c10036024c200241206a200241106a200241c8006a105f42002105024002400240200229032022064205520d0042002107410021080c010b200241386a2802002108200241306a2802002100200228023c210920022802342101024020064201520d002001ad42208621052000ad2107200241c0006a280200210020022903282106200821010c020b02402006a7220a41014b0d0002400240200a0e020001000b2001450d01200010290c010b2009450d00200810290b41002108420021070b410021010b200241003602282002420137032041011027210b0240024020010d00200b450d034101210c200241013602242002200b360220200b41003a00000c010b200b450d0320024281808080103702242002200b360220200b41013a0000200b410141091028220a450d042002428980808090013702242002200a360220200a200637000120022000360248200241c8006a200241206a10300240024020000d002002280224210b2002280228210c0c010b2001200041286c6a210d2002280224210b2002280228210c034002400240200b200c6b4120490d00200c41206a21002002280220210a0c010b200c41206a2200200c490d0b200b410174220a20002000200a491b220e4100480d0b02400240200b0d00200e1027210a0c010b2002280220200b200e1028210a0b200a450d082002200e3602242002200a360220200e210b0b200a200c6a220c41186a200141186a290000370000200c41106a200141106a290000370000200c41086a200141086a29000037000020022000360228200c2001290000370000200141206a29030021060240200b20006b41074b0d00200041086a220c2000490d0b200b410174220e200c200c200e491b220c4100480d0b02400240200b0d00200c1027210a0c010b200a200b200c1028210a0b200a450d092002200c3602242002200a360220200c210b0b2002200041086a220c360228200a20006a2006370000200d200141286a2201470d000b0b02400240200b200c6b4108490d002002280220210b0c010b200c41086a2201200c490d09200b4101742200200120012000491b22014100480d0902400240200b0d0020011027210b0c010b2002280220200b20011028210b0b200b450d08200220013602242002200b3602200b200b200c6a2005200784370000200c41086a210c2009450d00200810290b2004a7210e02402004422088a72201450d00200141246c21002003210103400240024020012d0000220a41034b0d00024002400240200a0e0404000102040b2001410c6a280200450d03200141086a28020010290c030b2001410c6a280200450d02200141086a28020010290c020b2001410c6a280200450d01200141086a28020010290c010b200141086a280200450d00200141046a28020010290b200141246a21012000415c6a22000d000b0b0240200e450d00200310290b200241d0006a2400200cad422086200bad840f0b200241346a410136020020024201370224200241cc81c200360220200241023602142002418884c2003602102002200241106a360230200241206a41d481c2001057000b41014101102a000b41014101102a000b41094101102a000b200e4101102a000b200c4101102a000b20014101102a000b102b000bb405020a7f017e230041306b2202240041082103200241186a41086a220442003703002002420037031841c6c4c500411b200241186a1004200241086a41086a2004290300370300200220022903183703084100210520024100360218200241086a4110200241186a100521060240024020022802182207417f460d002002200736022c20022006360228200241186a200241286a1041024020022802182203450d00200241206a2802002104200228021c21052007450d02200610290c020b418f89c3004133104e000b410021040b200241003602202002420137031820022004360208200241086a200241186a10300240024002400240024020040d0020022802202107200228021821080c010b2003200441286c6a2109200228021c210a2002280220210720032104034002400240200a20076b4120490d00200741206a2106200228021821080c010b200741206a22062007490d05200a4101742208200620062008491b220b4100480d0502400240200a0d00200b102721080c010b2002280218200a200b102821080b2008450d032002200b36021c20022008360218200b210a0b200820076a220741186a200441186a290000370000200741106a200441106a290000370000200741086a200441086a2900003700002002200636022020072004290000370000200441206a290300210c02400240200a20066b4108490d00200641086a21070c010b200641086a22072006490d05200a410174220b20072007200b491b220b4100480d0502400240200a0d00200b102721080c010b2008200a200b102821080b2008450d042002200b36021c20022008360218200b210a0b20022007360220200820066a200c3700002009200441286a2204470d000b0b02402005450d00200310290b200241306a24002007ad4220862008ad840f0b200b4101102a000b200b4101102a000b102b000b7101017f024002400240410810272202450d00200242f20c37000020024108411010282202450d01200242960237000820024110412010282202450d02200242e807370018200242e8073700102002ad42808080808004840f0b41084101102a000b41104101102a000b41204101102a000b870d05017f017e067f017e077f230041f0006b22022400200241106a41e2c5c50041131094012002290318210320022802102104200241d0006a41086a220542003703002002420037035041d2c5c5004110200241d0006a1004200241206a41086a2005290300370300200220022903503703204100210620024100360250200241206a4110200241d0006a100521050240024020022802502207417f460d002005450d002002200736023420022005360230200241d0006a200241306a1041024020022802502206450d00200241d8006a2802002108200228025421092007450d02200510290c020b418f89c3004133104e000b0b200241c3c5c500410f1094012002290308210a2002280200210b200241d0006a41086a22054200370300200242003703504185c6c500410f200241d0006a1004200241206a41086a20052903003703002002200229035037032020024100360250200241206a4110200241d0006a10052105024002400240024002400240024002400240024020022802502207417f460d002005450d00200241d0006a2007412020074120491b220c6a410041004120200c6b200c411f4b1b10cd041a200241d0006a2005200c10ce041a2007411f4d0d02200241306a41186a2207200241d0006a41186a220c290000370300200241306a41106a220d200241d0006a41106a220e290000370300200241306a41086a220f200241d0006a41086a22102900003703002002200229005037033020051029200c2007290300370300200e200d2903003703002010200f290300370300200220022903303703500c010b200241d8006a4200370300200241e0006a4200370300200241e8006a4200370300200242003703500b200241306a41186a200241d0006a41186a290300370300200241306a41106a200241d0006a41106a290300370300200241306a41086a200241d0006a41086a290300370300200220022903503703302002410036025820024201370350410810272205450d01200242888080808001370254200220053602502005200a4200200b1b37000020054108411010282205450d0220024290808080800237025420052003420020041b3700082002200536025002404110200228025822076b41074b0d00200741086a22042007490d084110410174220b20042004200b491b22044100480d080240024041100d002004102721050c010b200541102004102821050b2005450d0420022004360254200220053602500b2006410820061b21102002200741086a360258200520076a42eb0237000020022008410020061b2205360220200241206a200241d0006a1030200228025421082002280258210e02402005450d002010200541286c6a21114100200e6b210b410021050340200e20056a210c024002402008200b6a4120490d00200228025021040c010b200c41206a2207200c490d0a20084101742204200720072004491b22074100480d0a0240024020080d002007102721040c010b200228025020082007102821040b2004450d072002200736025420022004360250200721080b2004200e6a20056a220d41186a201020056a220741186a290000370000200d41106a200741106a290000370000200d41086a200741086a2900003700002002200c41206a220f360258200d2007290000370000200741206a290300210302402008200b6a41606a41074b0d00200f41086a220d200f490d0a2008410174220f200d200d200f491b220d4100480d0a0240024020080d00200d102721040c010b20042008200d102821040b2004450d082002200d36025420022004360250200d21080b2002200c41286a3602582004200e6a20056a41206a2003370000200b41586a210b200541286a21052011200741286a470d000b200e20056a210e0b024002402008200e6b4120490d00200228025021050c010b200e41206a2205200e490d0820084101742207200520052007491b22074100480d080240024020080d002007102721050c010b200228025020082007102821050b2005450d0720022007360254200220053602500b2005200e6a22072002290330370000200741186a200241306a41186a290300370000200741106a200241306a41106a290300370000200741086a200241306a41086a290300370000200e41206a210702402006450d002009450d00201010290b200241f0006a24002007ad4220862005ad840f0b418f89c3004133104e000b41084101102a000b41104101102a000b20044101102a000b20074101102a000b200d4101102a000b20074101102a000b102b000b800603097f037e027f230041306b22022400200241186a41086a220342003703002002420037031841d2c5c5004110200241186a1004200241086a41086a2003290300370300200220022903183703084100210420024100360218200241086a4110200241186a100521050240024002400240024020022802182206417f460d002002200636022c20022005360228200241186a200241286a104120022802182207450d01200241206a2802002103200228021c210802402006450d00200510290b410021040240200341286c22060d00410121094100210a0c030b200641286d220a41ffffff3f71200a470d04200a41057422064100480d042006102722090d0220064101102a000b410121094100210a0c020b418f89c3004133104e000b02402003450d00200341286c21054100210420092103200721060340200641086a290000210b200641106a290000210c2006290000210d200341186a200641186a290000370000200341106a200c370000200341086a200b3700002003200d370000200441016a2104200341206a2103200641286a2106200541586a22050d000b0b2008450d00200710290b200241003602202002420137031820022004360208200241086a200241186a103002400240024020040d0020022802202106200228021821080c010b2004410574210e4100200228022022066b210520022802182108200228021c21072009210303400240200720056a411f4b0d00200641206a22042006490d042007410174220f20042004200f491b22044100480d040240024020070d002004102721080c010b200820072004102821080b2008450d03200421070b200820066a22042003290000370000200441186a200341186a290000370000200441106a200341106a290000370000200441086a200341086a290000370000200541606a2105200641206a2106200341206a2103200e41606a220e0d000b2002200736021c20022006360220200220083602180b0240200a450d00200910290b200241306a24002006ad4220862008ad840f0b20044101102a000b102b000b860601087f230041106b2202240020024100360208200242013703002000280200210302400240024002400240410410272204450d0020024284808080c00037020420022004360200200420033600002000280204210320044104410810282204450d012002428880808080013702042004200336000420022004360200200028020821042002200041106a280200220336020c2002410c6a2002103002402003450d00200341057421052002280204210620022802082103034002400240200620036b4120490d00200341206a2107200228020021080c010b200341206a22072003490d0720064101742208200720072008491b22094100480d070240024020060d002009102721080c010b200228020020062009102821080b2008450d052002200936020420022008360200200921060b200820036a220341086a200441086a290000370000200341106a200441106a290000370000200341186a200441186a290000370000200220073602082003200429000037000020072103200441206a2104200541606a22050d000b0b2000280214210420022000411c6a280200220336020c2002410c6a200210300240024020030d002002280208210320022802042105200228020021080c010b200341057421094100200228020822036b210620022802042105034002400240200520066a4120490d00200228020021080c010b200341206a22072003490d0720054101742208200720072008491b22074100480d070240024020050d002007102721080c010b200228020020052007102821080b2008450d062002200736020420022008360200200721050b200820036a220741086a200441086a290000370000200741106a200441106a290000370000200741186a200441186a2900003700002002200341206a220336020820072004290000370000200641606a2106200441206a2104200941606a22090d000b0b2001280200200128020420082003100302402005450d00200810290b200241106a24000f0b41044101102a000b41084101102a000b20094101102a000b20074101102a000b102b000bb60201037f230041106b22022400200241003602082002420137030020002d000021034101102721040240024002400240024020034101460d002004450d02200441003a0000200242818080801037020420022004360200200041086a200210dd02200228020445210020022802082103200228020021040c010b2004450d02200441013a00002002428180808010370204200220043602004121210320044101412110282204450d0320042000290001370001200441096a200041096a290000370000200441116a200041116a290000370000200441196a200041196a290000370000200242a1808080900437020420022004360200410021000b20012802002001280204200420031003024020000d00200410290b200241106a24000f0b41014101102a000b41014101102a000b41214101102a000bfd0b02067f027e230041106b22022400200028022821032002200041306a280200220436020c2002410c6a2001103002400240024002400240024002400240024002400240200141046a2802002205200141086a28020022066b2004490d00200128020021050c010b200620046a22072006490d0920054101742206200720072006491b22064100480d090240024020050d002006102721050c010b200128020020052006102821050b2005450d0120012005360200200141046a2006360200200141086a28020021060b200141086a2207200620046a360200200520066a2003200410ce041a2000280234210502400240200141046a2802002206200728020022046b4104490d00200128020021060c010b200441046a22032004490d0920064101742204200320032004491b22044100480d090240024020060d002004102721060c010b200128020020062004102821060b2006450d0220012006360200200141046a2004360200200141086a28020021040b200141086a2203200441046a360200200620046a200536000002400240200141046a2802002206200328020022046b4120490d00200128020021060c010b200441206a22052004490d0920064101742204200520052004491b22044100480d090240024020060d002004102721060c010b200128020020062004102821060b2006450d0320012006360200200141046a2004360200200141086a28020021040b200141086a2205200441206a360200200620046a220441186a200041d0006a290000370000200441106a200041c8006a290000370000200441086a200041c0006a29000037000020042000290038370000200041086a29030021082000290300210902400240200141046a2802002206200528020022046b4110490d00200128020021060c010b200441106a22052004490d0920064101742204200520052004491b22044100480d090240024020060d002004102721060c010b200128020020062004102821060b2006450d0420012006360200200141046a2004360200200141086a28020021040b200141086a2205200441106a360200200620046a22042008370008200420093700002000290310210802400240200141046a2802002206200528020022046b4108490d00200128020021060c010b200441086a22052004490d0920064101742204200520052004491b22044100480d090240024020060d002004102721060c010b200128020020062004102821060b2006450d0520012006360200200141046a2004360200200141086a28020021040b200141086a2205200441086a360200200620046a20083700000240024020002903184201510d0002400240200141046a28020020052802002200460d00200128020021040c010b200041016a22042000490d0b20004101742206200420042006491b22064100480d0b0240024020000d002006102721040c010b200128020020002006102821040b2004450d0820012004360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200420006a41003a00000c010b02400240200141046a28020020052802002204460d00200128020021060c010b200441016a22062004490d0a20044101742205200620062005491b22054100480d0a0240024020040d002005102721060c010b200128020020042005102821060b2006450d0820012006360200200141046a2005360200200141086a28020021040b200141086a2205200441016a360200200620046a41013a00002000290320210802400240200141046a2802002204200528020022006b4108490d00200128020021040c010b200041086a22062000490d0a20044101742200200620062000491b22004100480d0a0240024020040d002000102721040c010b200128020020042000102821040b2004450d0920012004360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200420006a20083700000b200241106a24000f0b20064101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20064101102a000b20054101102a000b20004101102a000b102b000b130020004106360204200041a894c2003602000b3400200041e087c20036020420004100360200200041146a4107360200200041106a418cacc200360200200041086a42083702000b02000b3701017f02404110102722020d0041104101102a000b2002420037000820024201370000200042908080808002370204200020023602000b5d01027f230041106b22022400200241003602082002420137030002404101102722030d0041014101102a000b200341003a0000200041086a4101360200200241013602042002200336020020002002290300370200200241106a24000bc70101017f23004190016b22022400200241003a00782002428080848080023703682002420137035820024201370350200242af0137034820024287013703402002420137033820024201370330200242013703282002420137032020024201370318200242013703102002420137030820024280808080c00037036020024280808180800437037020024100360288012002420137038001200241086a20024180016a109302200041086a200228028801360200200020022903800137020020024190016a24000b130020004110360204200041c4b5c2003602000b3301017f02404108102722020d0041084101102a000b2000428880808080013702042000200236020020024280ade2043700000b3201017f02404104102722020d0041044101102a000b20004284808080c000370204200020023602002002418080013600000b3101017f02404104102722020d0041044101102a000b20004284808080c0003702042000200236020020024180083600000b3101017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242e8073700000b3c01017f02404110102722020d0041104101102a000b2002420037000820024280a094a58d1d370000200042908080808002370204200020023602000b3b01017f02404110102722020d0041104101102a000b2002420037000820024280c8afa025370000200042908080808002370204200020023602000b3801017f02404110102722020d0041104101102a000b200242003700082002429601370000200042908080808002370204200020023602000b3801017f02404110102722020d0041104101102a000b20024200370008200242e807370000200042908080808002370204200020023602000b3701017f02404110102722020d0041104101102a000b2002420037000820024204370000200042908080808002370204200020023602000b3001017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241083600000b3701017f02404110102722020d0041104101102a000b2002420037000820024210370000200042908080808002370204200020023602000b3001017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242023700000be80c03067f0b7e047f230041106b2202240020024100360208200241086a2001280200220320012802042204410420044104491b220510ce041a2001200420056b22063602042001200320056a220536020002400240200441034b0d00200041023a00700c010b2002280208210720024200370308200241086a20052006410820064108491b220410ce041a2001200620046b22033602042001200520046a22043602000240200641074b0d00200041023a00700c010b2002290308210820024200370308200241086a20042003410820034108491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341074b0d00200041023a00700c010b2002290308210920024200370308200241086a20042006410820064108491b220510ce041a2001200620056b22033602042001200420056a22043602000240200641074b0d00200041023a00700c010b2002290308210a20024200370308200241086a20042003410820034108491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341074b0d00200041023a00700c010b2002290308210b20024200370308200241086a20042006410820064108491b220510ce041a2001200620056b22033602042001200420056a22043602000240200641074b0d00200041023a00700c010b2002290308210c20024200370308200241086a20042003410820034108491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341074b0d00200041023a00700c010b2002290308210d20024200370308200241086a20042006410820064108491b220510ce041a2001200620056b22033602042001200420056a22043602000240200641074b0d00200041023a00700c010b2002290308210e20024200370308200241086a20042003410820034108491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341074b0d00200041023a00700c010b2002290308210f20024200370308200241086a20042006410820064108491b220510ce041a2001200620056b22033602042001200420056a22043602000240200641074b0d00200041023a00700c010b2002290308211020024200370308200241086a20042003410820034108491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341074b0d00200041023a00700c010b2002290308211120024200370308200241086a20042006410820064108491b220510ce041a2001200620056b22033602042001200420056a22043602000240200641074b0d00200041023a00700c010b2002290308211220024100360208200241086a20042003410420034104491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341034b0d00200041023a00700c010b2002280208211320024100360208200241086a20042006410420064104491b220510ce041a2001200620056b22033602042001200420056a22043602000240200641034b0d00200041023a00700c010b2002280208211420024100360208200241086a20042003410420034104491b220510ce041a2001200320056b22063602042001200420056a22043602000240200341034b0d00200041023a00700c010b2002280208211520024100360208200241086a20042006410420064104491b220510ce041a2001200620056b22033602042001200420056a22043602000240200641034b0d00200041023a00700c010b20022802082116200241003a0008200241086a20042003410047220510ce041a024020032005490d002001200320056b22063602042001200420056a2204360200024020030d00200041023a00700c020b20022d0008210320024100360208200241086a20042006410420064104491b220510ce041a2001200620056b3602042001200420056a3602000240200641034b0d00200041023a00700c020b20022802082101200020033a00702000200136026c2000201636026820002015360264200020143602602000201336025c200020073602582000201237035020002011370348200020103703402000200f3703382000200e3703302000200d3703282000200c3703202000200b3703182000200a370310200020093703082000200837030020002002280008360071200041f4006a200241086a41036a2800003600000c010b20052003103e000b200241106a24000b970402067f017e230041e0006b2202240002400240024002400240411a10272203450d00200341186a41002f00cfce423b0000200341106a41002900c7ce42370000200341086a41002900bfce42370000200341002900b7ce423700002003411a413a10282203450d012003200129000037001a200341326a200141186a2900003700002003412a6a200141106a290000370000200341226a200141086a290000370000200241c0006a41186a22014200370300200241c0006a41106a22044200370300200241c0006a41086a22054200370300200242003703402003413a200241c0006a1000200241186a41186a2001290300370300200241186a41106a2004290300370300200241186a41086a20052903003703002002200229034037031820024100360240200241186a4120200241c0006a1005210420022802402201417f460d032002200136023c20022004360238200241c0006a200241386a10f30220022802482205450d02200241086a2206200241c0006a41146a290200370300200241106a2207200241c0006a411c6a2802003602002002200229024c3703002002290340210802402001450d00200410290b20002005360208200020083702002000200229030037020c200041146a20062903003702002000411c6a20072802003602000c040b411a4101102a000b413a4101102a000b418f89c3004133104e000b200041003602080b20031029200241e0006a24000bc60202067f017e230041106b220224002002410036020020022001280200220320012802042204410420044104491b220510ce0421022001200420056b22063602042001200320056a220536020002400240200441034b0d00200041003602080c010b2002280200210720024100360200200220052006410420064104491b220310ce0421042001200620036b3602042001200520036a3602000240200641034b0d00200041003602080c010b2004280200210620042001102d0240200428020022050d00200041003602080c010b2004290204210820042001102d2008a721010240200428020022030d00200041003602082001450d01200510290c010b200041186a2004290204370200200041146a2003360200200041106a20084220883e02002000200136020c2000200536020820002006360204200020073602000b200241106a24000b130020004104360204200041d4cec2003602000b3400200041cad6c20036020420004100360200200041146a4105360200200041106a41e0d6c200360200200041086a42133702000b340020004194ddc20036020420004100360200200041146a4105360200200041106a41a8ddc200360200200041086a42133702000bf02105027f017e027f017e067f230041f0016b22012400024002400240024002400240024041880110272202450d000240024002400240024002400240024002400240024002400240024002400240024002400240200028020022002802000e12000102030405060708090a0b0c0d0e0f1011000b200141e8006a200041086a10960220024100360200200241106a200141e8006a41086a290300370300200220012903683703080c110b109702000b200041086a290300210320024102360200200220033703080c0f0b200141e8006a200041046a1038200241033602002002410c6a200141f0006a280200360200200220012903683702040c0e0b109802000b0240024002400240200041086a280200417f6a220441014b0d0020040e020102010b41e4bdc0001058000b41012104024002402000410c6a22052d00004101460d00200141026a200541036a2d00003a0000200141f0006a2000411c6a290200370300200141e8006a41106a200041246a29020037030020014180016a2000412c6a2d00003a0000200120052f00013b01002001200041146a290200370368200041106a2802002105410021040c010b200041106a28020021050b200141246a41026a200141026a2d00003a0000200141286a41086a200141e8006a41086a290300370300200141286a41106a200141e8006a41106a290300370300200141286a41186a200141e8006a41186a280200360200200120012f01003b012420012001290368370328200041386a29030021032000290330210641012107200141106a21000c010b41012104024002402000410c6a22052d00004101460d00200141ee016a200541036a2d00003a0000200141f0006a2000411c6a290200370300200141e8006a41106a200041246a29020037030020014180016a2000412c6a2d00003a0000200120052f00013b01ec012001200041146a290200370368200041106a2802002105410021040c010b200041106a28020021050b41022107200141246a41026a200141ec016a41026a2d00003a0000200141286a41086a200141e8006a41086a290300370300200141286a41106a200141e8006a41106a290300370300200141286a41186a200141e8006a41186a280200360200200120012f01ec013b012420012001290368370328200120002903303703102001200041386a290300370318200041c8006a290300210320002903402106200121000b2000200637030020002003370308200220043a000c20022007360208200220012f01243b000d2002410f6a200141266a2d00003a000020022005360210200220012903283702142002411c6a200141286a41086a290300370200200241246a200141386a2903003702002002412c6a200141c0006a280200360200200241386a200141106a41086a2903003703002002200129031037033020022001290300370340200241c8006a200141086a290300370300200241053602000c0c0b200141e8006a200041086a10990220024106360200200241386a200141e8006a41306a290300370300200241306a200141e8006a41286a290300370300200241286a200141e8006a41206a290300370300200241206a200141e8006a41186a290300370300200241186a200141e8006a41106a290300370300200241106a200141e8006a41086a290300370300200220012903683703080c0b0b200141e8006a41186a200041286a290000370300200141e8006a41106a200041206a290000370300200141f0006a200041186a290000370300200141e8006a41286a200041386a290000370300200141e8006a41306a200041c0006a290000370300200141e8006a41386a200041c8006a2900003703002001200041106a2900003703682001200041306a290000370388012000410c6a2802002204417f4c0d0c0240024020040d00410121000c010b20002802042105200410272200450d0e20002005200410ce041a0b200141286a41386a2205200141e8006a41386a290300370300200141286a41306a2207200141e8006a41306a290300370300200141286a41286a2208200141e8006a41286a290300370300200141286a41206a2209200141e8006a41206a290300370300200141286a41186a220a200141e8006a41186a290300370300200141286a41106a220b200141e8006a41106a290300370300200141286a41086a220c200141e8006a41086a290300370300200120012903683703282002200436020c200220043602082002200036020420022001290328370210200241186a200c290300370200200241206a200b290300370200200241286a200a290300370200200241306a2009290300370200200241386a2008290300370200200241c0006a2007290300370200200241c8006a2005290300370200200241073602000c0a0b200141e8006a200041086a109a0220024108360200200241386a200141e8006a41306a290300370300200241306a200141e8006a41286a290300370300200241286a200141e8006a41206a290300370300200241206a200141e8006a41186a290300370300200241186a200141e8006a41106a290300370300200241106a200141e8006a41086a290300370300200220012903683703080c090b02400240024002400240024020002d0004417f6a220441034b0d0020040e0401020304010b41c893c2001058000b200041106a280200220741ffffff3f712007470d0e20074105742204417f4c0d0e200041086a2802002109410121004101210802402004450d00200410272208450d110b024020070d0041002104410021070c040b20074105742105416020096b210a2008210020092104034020002004290000370000200041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a290000370000200041206a2100200441206a2104200541606a22050d000b41012100200920074105746a200a6a41057641016a21040c030b200041086a10f7022108410221000c020b200041086a28020021082000410c6a10f7022107410321000c010b2001412a6a200041046a220441036a2d00003a0000200141e8006a41086a2000411c6a290000370300200141e8006a41106a200041246a2d00003a0000200120042f00013b01282001200041146a29000037036820002d00254100472109200041286a2802002105200041106a28000021042000410c6a2800002107200041086a2800002108410421000b200220003a0004200220012f01283b0005200220043602102002200736020c200220083602082002200129036837021420022005360228200220093a002520024109360200200241076a2001412a6a2d00003a00002002411c6a200141f0006a290300370200200241246a200141f8006a2d00003a00000c080b02400240024002400240024020002d0004417f6a220441034b0d0020040e0401020304010b41c893c2001058000b200041106a280200220741ffffff3f712007470d0d20074105742204417f4c0d0d200041086a2802002109410121004101210802402004450d00200410272208450d110b024020070d0041002104410021070c040b20074105742105416020096b210a2008210020092104034020002004290000370000200041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a290000370000200041206a2100200441206a2104200541606a22050d000b41012100200920074105746a200a6a41057641016a21040c030b200041086a10f7022108410221000c020b200041086a28020021082000410c6a10f7022107410321000c010b2001412a6a200041046a220441036a2d00003a0000200141e8006a41086a2000411c6a290000370300200141e8006a41106a200041246a2d00003a0000200120042f00013b01282001200041146a29000037036820002d00254100472109200041286a2802002105200041106a28000021042000410c6a2800002107200041086a2800002108410421000b200220003a0004200220012f01283b0005200220043602102002200736020c200220083602082002200129036837021420022005360228200220093a00252002410a360200200241076a2001412a6a2d00003a00002002411c6a200141f0006a290300370200200241246a200141f8006a2d00003a00000c070b200141e8006a200041086a10c8012002410b360200200241c0006a200141e8006a41386a290300370300200241386a200141e8006a41306a290300370300200241306a200141e8006a41286a290300370300200241286a200141e8006a41206a290300370300200241206a200141e8006a41186a290300370300200241186a200141e8006a41106a290300370300200241106a200141e8006a41086a290300370300200220012903683703080c060b200041086a29030021032002410c360200200220033703080c050b2000410c6a2802002204417f4c0d060240024020040d00410121000c010b20002802042105200410272200450d0b20002005200410ce041a0b2002200436020c20022004360208200220003602042002410d3602000c040b024002400240024002400240200041086a280200417f6a220441024b0d0020040e03010203010b4190a9c1001058000b200041386a2903002103200041306a290300210641012104024002402000410c6a2d00004101460d00200141f0006a2000411c6a290200370300200141e8006a41106a200041246a29020037030020014180016a2000412c6a2d00003a00002001200041146a29020037036820002f000d2000410f6a2d0000411074722105200041106a2802002100410021040c010b200041106a28020021000b200141286a41186a200141e8006a41186a280200360200200141286a41106a200141e8006a41106a290300370300200141286a41086a200141e8006a41086a29030037030020012001290368370328410121070c030b2000410c6a28020022044108762105410221070c010b2000410c6a28020022044108762105410321070b0b200220063703302002200036021020022007360208200220012903283702142002410e360200200241386a200337030020022005410874200441ff01717236020c2002411c6a200141286a41086a290300370200200241246a200141386a2903003702002002412c6a200141c0006a2802003602000c030b200141e8006a200041086a109c02200241086a200141e8006a41800110ce041a2002410f3602000c020b02400240024002402000280204417f6a220441014b0d0020040e020102010b41f8e2c1001058000b41880110272204450d0a2004200041086a280200109502410121000c010b4101210402400240200041086a2d00004101460d00200141e8006a41086a200041186a290200370300200141e8006a41106a200041206a290200370300200141e8006a41186a200041286a2d00003a00002001200041106a29020037036820002f00092000410b6a2d00004110747221072000410c6a2802002105410021040c010b2000410c6a28020021050b200141286a41186a200141e8006a41186a280200360200200141286a41106a200141e8006a41106a290300370300200141286a41086a200141e8006a41086a2903003703002001200129036837032820042007410874722104410221000b2002200536020c20022004360208200220003602042002200129032837021020024110360200200241186a200141306a290300370200200241206a200141286a41106a290300370200200241286a200141286a41186a2802003602000c010b200141e8006a200041086a10b101200241086a200141e8006a41d80010ce041a200241113602000b200141f0016a240020020f0b4188014108102a000b1039000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b4188014108102a000bc50401047f230041f0006b22072400200741086a200242002003200410d304200741c0006a41e887c50041111094012007290348210320072802402108200741e0006a41086a220942003703002007420037036041e887c5004111200741e0006a1004200741d0006a41086a220a2009290300370300200720072903603703502007200120027d2003420020081b7c370360200741d0006a4110200741e0006a41081003200741306a20002007290308200741086a41086a290300108301200741306a41086a290300210120072903302102200741186a41b18ac0004116108601200520027d200220057d2002200558200120065820012006511b22001b2103200620017d2005200254ad7d200120067d2002200554ad7d20001b2106200741186a41106a2903004200200728021822081b21052007290320420020081b2102024002402000450d00200942003703002007420037036041b18ac0004116200741e0006a1004200a20092903003703002007200729036037035020074200200520067d2002200354ad7d2206200220037d2201200256200620055620062005511b22091b37036820074200200120091b370360200741e0006a21090c010b200942003703002007420037036041b18ac0004116200741e0006a1004200a2009290300370300200720072903603703502007427f200520067c200220037c22062002542209ad7c22022009200220055420022005511b22091b3703682007427f200620091b370360200741e0006a21090b200741d0006a4110200941101003200741f0006a24000bcd0101047f200020014105746a210320002104024003400240200320046b41e0004b0d00024020042003460d00200020014105746a210503404101210620022004460d0420042002412010d004450d042005200441206a2204470d000b0b41000f0b4101210620042002460d0120042002412010d004450d01200441206a22052002460d0120052002412010d004450d01200441c0006a22052002460d0120052002412010d004450d01200441e0006a22052002460d0120044180016a210420052002412010d0040d000b0b20060bbd0101047f230041a0026b2202240020024100360290012001412020024190016a100521030240024002402002280290012204417f470d00411221050c010b2002200436029c02200220033602980220024190016a20024198026a103c20022802900122054112460d012002410c6a20024190016a41047241840110ce041a02402004450d00200310290b20014120100c0b20002005360200200041046a2002410c6a41840110ce041a200241a0026a24000f0b418f89c3004133104e000b970402067f017e230041e0006b2202240002400240024002400240411a10272203450d00200341186a41002f009de7423b0000200341106a4100290095e742370000200341086a410029008de74237000020034100290085e7423700002003411a413a10282203450d012003200129000037001a200341326a200141186a2900003700002003412a6a200141106a290000370000200341226a200141086a290000370000200241c0006a41186a22014200370300200241c0006a41106a22044200370300200241c0006a41086a22054200370300200242003703402003413a200241c0006a1000200241186a41186a2001290300370300200241186a41106a2004290300370300200241186a41086a20052903003703002002200229034037031820024100360240200241186a4120200241c0006a1005210420022802402201417f460d032002200136023c20022004360238200241c0006a200241386a10f30220022802482205450d02200241086a2206200241c0006a41146a290200370300200241106a2207200241c0006a411c6a2802003602002002200229024c3703002002290340210802402001450d00200410290b20002005360208200020083702002000200229030037020c200041146a20062903003702002000411c6a20072802003602000c040b411a4101102a000b413a4101102a000b418f89c3004133104e000b200041003602080b20031029200241e0006a24000ba40b03087f017e017f23004180026b22022400200241e0016a41186a22034200370300200241e0016a41106a22044200370300200241e0016a41086a22054200370300200242003703e001200241e0016a2001280200220620012802042207412020074120491b220810ce041a2001200720086b22093602042001200620086a22083602000240024002400240024002402007411f4d0d00200241c0016a41186a2003290300370300200241c0016a41106a2004290300370300200241c0016a41086a2005290300370300200220022903e0013703c001200241003a00e001200241e0016a20082009410047220710ce041a20092007490d022001200920076b22063602042001200820076a22073602002009450d0020022d00e00122034106490d010b200041023a00210c040b200241186a200241c0016a41186a290300370300200241106a200241c0016a41106a290300370300200241086a200241c0016a41086a290300370300200220022903c001370300200241003a00e001200241e0016a20072006410047220810ce041a20062008490d012001200620086b22093602042001200720086a220736020002402006450d0020022d00e001220841014b0d00410021060240024020080e020100010b200241e0016a2009412020094120491b22086a41004100412020086b2008411f4b1b10cd041a200241e0016a2007200810ce041a2001200920086b22043602042001200720086a22073602002009411f4d0d01200241a0016a41086a200241e0016a41086a290000220a37030020024180016a41186a200241e0016a41186a29000037030020024180016a41106a200241e0016a41106a29000037030020024180016a41086a200a370300200220022900e001220a3703a0012002200a3703800141012106200421090b200241e0006a41186a20024180016a41186a290300370300200241e0006a41106a20024180016a41106a290300370300200241e0006a41086a20024180016a41086a2903003703002002200229038001370360200241003a00e001200241e0016a20072009410047220810ce041a20092008490d032001200920086b22043602042001200720086a22073602002009450d0020022d00e001220841014b0d00410021090240024020080e020100010b200241e0016a2004412020044120491b22086a41004100412020086b2008411f4b1b10cd041a200241e0016a2007200810ce041a2001200420086b3602042001200720086a3602002004411f4d0d01200241a0016a41086a200241e0016a41086a290000220a37030020024180016a41186a200241e0016a41186a29000037030020024180016a41106a200241e0016a41106a29000037030020024180016a41086a200a370300200220022900e001220a3703a0012002200a37038001410121090b200241206a41186a220120024180016a41186a290300370300200241206a41106a220720024180016a41106a290300370300200241206a41086a220820024180016a41086a290300370300200241c0006a41086a2204200241e0006a41086a290300370300200241c0006a41106a2205200241e0006a41106a290300370300200241c0006a41186a220b200241e0006a41186a290300370300200220022903800137032020022002290360370340200041186a200241186a290300370000200041106a200241106a290300370000200041086a200241086a29030037000020002002290300370000200020063a0021200020033a0020200041c2006a20093a0000200020022903403700222000412a6a2004290300370000200041326a20052903003700002000413a6a200b290300370000200041c3006a2002290320370000200041cb006a2008290300370000200041d3006a2007290300370000200041db006a20012903003700000c040b200041023a00210c030b20072009103e000b20082006103e000b20082009103e000b20024180026a24000b3400200041e6efc20036020420004100360200200041146a4102360200200041106a41f0efc200360200200041086a42073702000bd60401097f230041d0006b220224000240410f10272203450d00200341076a41002900f3ec42370000200341002900ecec4237000002402003410f411e10282204450d002004200036000f200241306a41186a22034200370300200241306a41106a22004200370300200241306a41086a220542003703002002420037033020044113200241306a1000200241086a41186a2003290300370300200241086a41106a2000290300370300200241086a41086a20052903003703002002200229033037030820024100360238200242013703302001280200210620022001280208220336022c2002412c6a200241306a10300240024020030d002002280238210520022802342107200228023021080c010b2003410574210920022802302108200228023421072002280238210020062103034002400240200720006b4120490d00200041206a21050c010b0240200041206a22052000490d002007410174220a20052005200a491b220a4100480d000240024020070d00200a102721080c010b20082007200a102821080b02402008450d00200a21070c020b200a4101102a000b102b000b200820006a22002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020052100200341206a2103200941606a22090d000b2002200736023420022005360238200220083602300b200241086a412020082005100302402007450d00200810290b200410290240200141046a280200450d00200610290b200241d0006a24000f0b411e4101102a000b410f4101102a000bd06704167f017e087f017e23004180036b2204240041002105200441003602f002200420023602ec02200420013602e8020240024002400240024002400240200241034b0d0041012106200441013a00d002200441ec016a4101360200200442013702dc0120044180c0c5003602d8012004411f3602b4022004200441b0026a3602e8012004200441d0026a3602b00220044180016a200441d8016a10e6032004280280012107200428028401210820042802880121094105210a4100210b0c010b200441043602f002024020012800004180c2cdeb06460d004101210a410121060c010b024002402002417c714104460d00200241074b0d0141082002107f000b41012106200441013a00d002200441ec016a4101360200200442013702dc0120044180c0c5003602d8012004411f3602b4022004200441b0026a3602e8012004200441d0026a3602b00220044180016a200441d8016a10e6032004280280012107200428028401210820042802880121094105210a410021054100210b0c010b200441083602f002410121060240200128000422074101460d004102210a0c010b200441d8016a200441e8026a10f20302400240024020042802d8014101470d00410421084100210c410021090c010b200441d8016a410572210d410421084128210a410021054100210c410021094100210b02400340200441d0026a41026a2201200d41026a2d00003a00002004200d2f00003b01d002200428028402210e200428028002210f20042802fc01211020042802f801211120042802f401211220042802f001211320042802ec01211420042802e801211520042802e401211620042802e0012117024020042d00dc012206417e6a41ff0171410a4b0d004100211802400240024002400240024002400240024002400240024020060e0f0b0b000102030405060708090a0b0b0b0b410121180c0a0b410221180c090b410321180c080b410421180c070b410521180c060b410621180c050b410721180c040b410821180c030b410921180c020b410a21180c010b410b21180b0240200b41ff0171221920184d0d004113210a0c030b4100211802400240024002400240024002400240024002400240024020060e0f0b0b000102030405060708090a0b0b0b0b410121180c0a0b410221180c090b410321180c080b410421180c070b410521180c060b410621180c050b410721180c040b410821180c030b410921180c020b410a21180c010b410b21180b024020192018470d004114210a0c030b4100210b0240024002400240024002400240024002400240024020060e0f0b0b000102030405060708090a0b0b0b0b4101210b0c0a0b4102210b0c090b4103210b0c080b4104210b0c070b4105210b0c060b4106210b0c050b4107210b0c040b4108210b0c030b4109210b0c020b410a210b0c010b410b210b0b20044180016a41026a221820012d00003a0000200420042f01d0023b01800102400240200c2009470d00200c41016a2201200c490d072005200120012005491b2209ad422c7e221a422088a70d07201aa722014100480d0702400240200c0d002001102721080c010b2008200a41586a2001102821080b2008450d010b2008200a6a220141586a20063a00002001200e3602002001417c6a200f360200200141786a2010360200200141746a2011360200200141706a20123602002001416c6a2013360200200141686a2014360200200141646a2015360200200141606a20163602002001415c6a2017360200200141596a220120042f0180013b0000200141026a20182d00003a0000200541026a2105200a412c6a210a200c41016a210c200441d8016a200441e8026a10f20320042802d8014101460d030c010b0b20014104102a000b024002402006410d4b0d00024002400240024002400240024002400240024002400240024020060e0e0001020304050607080e090a0b0c000b2016450d0d201710290c0d0b02402016450d00201710290b2013450d0c201410290c0c0b02402015450d00201541047421062017210103400240200141046a280200450d00200128020010290b200141106a2101200641706a22060d000b0b2016450d0b201710290c0b0b02402015450d00201541286c21062017210103400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200641586a22060d000b0b2016450d0a201710290c0a0b2016450d09201710290c090b2016450d08201710290c080b2016450d07201710290c070b02402015450d00201720154104746a210d201721050340024020052802082206450d0020052802002101200641047421060340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200641706a22060d000b0b200541106a21010240200541046a280200450d00200528020010290b200121052001200d470d000b0b2016450d06201710290c060b02402015450d00201541146c21062017210103400240200141046a280200450d00200128020010290b200141146a21012006416c6a22060d000b0b2016450d05201710290c050b02402015450d0020172015411c6c6a210d20172105034002402005410c6a2802002206450d0020052802042101200641047421060340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200641706a22060d000b0b0240200541086a280200450d00200528020410290b2005411c6a21010240200541146a280200450d00200528021010290b200121052001200d470d000b0b2016450d04201710290c040b02402015450d002017201541186c6a210d2017210503400240200541046a280200450d00200528020010290b0240200541146a2802002206450d00200528020c2101200641047421060340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200641706a22060d000b0b200541186a21010240200541106a280200450d00200528020c10290b200121052001200d470d000b0b2016450d03201710290c030b02402015450d0020172015411c6c6a210d20172105034002402005410c6a2802002206450d0020052802042101200641047421060340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200641706a22060d000b0b0240200541086a280200450d00200528020410290b2005411c6a21010240200541146a280200450d00200528021010290b200121052001200d470d000b0b2016450d02201710290c020b0240201741ff0171220141024b0d0002400240024020010e03000102000b2015450d04201610290c040b02402013450d002013410c6c2106201521010340024020012802002205450d00200141046a280200450d00200510290b2001410c6a2101200641746a22060d000b0b2014450d03201510290c030b02402013450d00201520134104746a21162015211703402017220d41106a21170240200d2802042201450d000240200d410c6a2802002206450d002006410c6c21060340024020012802002205450d00200141046a280200450d00200510290b2001410c6a2101200641746a22060d000b0b200d41086a280200450d00200d28020410290b20172016470d000b0b2014450d02201510290c020b2015450d01201610290c010b02402016450d00201710290b02402013450d002012450d00201310290b200f450d00201010290b0c010b024020042d00dc010d00200c412c6c210641002105410021010240034020062001460d01200820016a210a2001412c6a220b2101200a2d0000410b470d000b2008200b6a41606a28020021050b200c412c6c21064100210d410021010240034020062001460d01200820016a210a2001412c6a220b2101200a2d00004104470d000b200441f8006a2008200b6a41586a108003200428027c210d0b02402005200d470d004100210a4101210741e100210b41f3da012105410021060c030b0240200c450d00200c412c6c210a20082101034020011088032001412c6a2101200a41546a220a0d000b0b410121064119210a024020090d000c030b200810290c020b20042802dc01220a4110762105200a410876210b200441d8016a41106a280200210d200441e4016a2802002117200441d8016a41086a28020021070b0240200c450d00200c412c6c210620082101034020011088032001412c6a2101200641546a22060d000b0b4101210602402009450d00200810290b200d2109201721080b02402006450d00200821060c040b20042802f0022002470d022005411074200b41ff017141087472200a41ff017172211b2008200c412c6c6a210a20082101024002400340200a2001460d0120012d000021022001412c6a2206210120024102470d000b200441f0006a200641586a1080034104211c200428027021024100211002400240024002400240200428027422010d004100211d0c010b2001410474220a4100480d06200a1027221c450d012001211d0b02402001450d002001410474210641002110201c21010340200241086a280200220a417f4c0d032002410c6a2d0000210b2002280200210502400240200a0d004101210d0c010b200a1027220d450d050b200d2005200a10ce0421052001410d6a2002410d6a2d00003a00002001410c6a200b3a0000200141086a200a360200200141046a200a36020020012005360200200141106a2101201041016a2110200241106a2102200641706a22060d000b0b201c450d030c040b200a4104102a000b1039000b200a4101102a000b4100211d4104211c410021100b2008200c412c6c6a210a20082101024003404100210641b8d6c500210b0240200a2001470d00410021010c020b20012d000021022001412c6a2205210120024103470d000b200441e8006a200541586a1080034100210120042802682202450d00200428026c21012002210b0b0240024020010d0041012112410021134100210a4100210e410421154100210b4100211e41042114410421174100210241002105410021164100211f410121190c010b200141286c210d200b411c6a2101410421154100210641002113410121124100210a4100210e4100210b4100211e41042114410421174100210241002105410021164100211f41012119024002400240024002400340024002400240024002402001417c6a2d00000e0400010203000b2001280200210f0240024020052002460d00200521110c010b200241016a22112002490d0c20024101742218201120112018491b221841ffffffff03712018470d0c201841027422114100480d0c0240024020020d002011102721170c010b201720024102742011102821170b2017450d0620022111201821020b201720114102746a200f360200200541016a21050c030b200441d8016a41086a220f200141086a280200360200200420012902003703d8010240200a200e470d00200a41016a220e200a490d0b200a4101742211200e200e2011491b220ead420c7e221a422088a70d0b201aa722114100480d0b02400240200a0d002011102721150c010b2015200a410c6c2011102821150b2015450d060b2015200a410c6c6a221120042903d801370200201141086a200f280200360200200a41016a210a0c020b200441d8016a41086a220f200141086a280200360200200420012902003703d8010240200b201e470d00200b41016a2211200b490d0a200b4101742218201120112018491b221ead420c7e221a422088a70d0a201aa722114100480d0a02400240200b0d002011102721140c010b2014200b410c6c2011102821140b2014450d060b2014200b410c6c6a221120042903d801370200201141086a200f280200360200200b41016a210b0c010b2001417e6a220f2d000021112001417d6a22182d00002120024020062013470d00200641016a22132006490d0920064101742221201320132021491b221320136a22222013490d0920224100480d090240024020060d002022102721120c010b201220212022102821120b2012450d060b201220064101746a222220114101713a0001202220203a0000200f2d0000210f20182d000021110240201f2016470d00201641016a22182016490d0920164101742220201820182020491b221f201f6a2218201f490d0920184100480d090240024020160d002018102721190c010b201920202018102821190b2019450d070b200641016a2106201920164101746a2218200f4101713a0001201820113a0000201641016a21160b200141286a2101200d41586a220d450d060c000b0b20114104102a000b20114104102a000b20114104102a000b20224101102a000b20184101102a000b2008200c412c6c6a210f200821010240024002400240024002400240024002400240024002400240024003400240200f2001470d002002210d0c020b20012d0000210d2001412c6a22112101200d4104470d000b200441e0006a201141586a10800302402004280264220d0d002002210d0c010b20042802602101200d410274210f0340200128020021110240024020052002460d002002210d200521180c010b200241016a220d2002490d1020024101742218200d200d2018491b220d41ffffffff0371200d470d10200d41027422184100480d100240024020020d002018102721170c010b201720024102742018102821170b2017450d0320022118200d21020b200141046a2101201720184102746a2011360200200541016a2105200f417c6a220f0d000b0b2008200c412c6c6a210f20082101024002400340200f2001460d0120012d000021022001412c6a2211210120024105470d000b200441d8006a201141586a108003200428025c410c6c2218450d0020042802582101200a410174210f200a410c6c21020340200141086a2111024002400240200141046a2802004101470d002004201128020022203602c0022001280200222220204b0d010b20044100360280010c010b200441023602ec01200442023702dc01200441dc9cc5003602d801200441013602f402200441013602ec02200420223602d0022004200441e8026a3602e8012004200441d0026a3602f0022004200441c0026a3602e80220044180016a200441d8016a10e603200428028001450d0020044180016a21010c0e0b2001290200211a200441d8016a41086a222020112802003602002004201a3703d8010240200a200e470d00200a41016a220e200a490d11200f200e200e200f491b220ead420c7e221a422088a70d11201aa722114100480d1102400240200a0d002011102721150c010b201520022011102821150b2015450d030b2001410c6a2101201520026a221120042903d801370200201141086a2020280200360200200f41026a210f2002410c6a2102200a41016a210a201841746a22180d000b0b2008200c412c6c6a210f20082101024002400340200f2001460d0120012d000021022001412c6a2211210120024106470d000b200441d0006a201141586a10800320042802542202450d00200428025021012002410c6c2111200b410174210f200b410c6c21020340200441d8016a200110f503024020042802d801450d00200441d8016a21010c0f0b2001290200211a200441d8016a41086a2218200141086a2802003602002004201a3703d8010240200b201e470d00200b41016a221e200b490d12200f201e201e200f491b221ead420c7e221a422088a70d12201aa722204100480d1202400240200b0d002020102721140c010b201420022020102821140b2014450d030b2001410c6a2101201420026a222020042903d801370200202041086a2018280200360200200f41026a210f2002410c6a2102200b41016a210b201141746a22110d000b0b2008200c412c6c6a210f20082101024002400240024002400340200f2001460d0120012d000021022001412c6a2211210120024107470d000b200441c8006a201141586a108003200428024c2202450d002004280248220120024104746a212220064101742102200441d8016a41047221200340200441d8016a20012019201610f60302400240024020042d00d8014101460d00200420042d00d901220f3a00c0020240200f2001410c6a2d00002211470d0020044100360280010c030b200441023602ec01200442023702dc01200441f09dc5003602d801200441203602f402200441203602ec02200420113a00d0022004200441e8026a3602e8012004200441c0026a3602f0022004200441d0026a3602e80220044180016a200441d8016a10e6030c010b20044180016a41086a202041086a28020036020020042020290200370380010b0240200428028001450d0020044180016a21010c140b2001410c6a2d0000210f0b2001410d6a2d00002111024020062013470d00200641016a22132006490d162002201320132002491b221320136a22182013490d1620184100480d160240024020060d002018102721120c010b201220022018102821120b2012450d030b201220026a2218200f3a0000201841016a20114101713a0000200241026a2102200641016a2106200141106a22012022470d000b0b200441b8016a2005360200200441b4016a200d36020020044180016a412c6a2010360200200441a8016a201d360200200441a0016a20063602002004419c016a201336020020044194016a200a36020020044190016a200e360200200420173602b0012004201c3602a40120042012360298012004201536028c012004200b360288012004201e3602840120042014360280012008200c412c6c6a210a20082101024003400240200a2001470d004100210b0c020b20012d000021022001412c6a2206210120024104470d000b200441c0006a200641586a1080032004280244210b0b2004200b3602bc012008200c412c6c6a210a20082101024003400240200a2001470d00410021010c020b20012d000021022001412c6a220621012002410b470d000b200641606a28020021010b200420013602c001200b2001470d0d0240200b450d002008200c412c6c6a210a200821010340200a2001460d0520012d000021022001412c6a2206210120024104470d000b2008200c412c6c6a210b200821010340200b2001460d0420012d000021022001412c6a220a21012002410b470d000b200441386a200641586a108003200428023c2201450d002004280238220d20014102746a2115200a41606a2117200a41586a211620044191026a2111410021050340200420053602c4012017280200210120162802002102200442013702dc01200441f492c5003602d801200441013602d402200441013602ec012004200441d0026a3602e8012004200441c4016a3602d002200441e8026a200441d8016a10e60320042802e802210a20042902ec02211a200120054d0d110240201aa7450d00200a10290b2004200d28020022013602d002024002400240024020042802ac0120014b0d00200441013602ec01200442023702dc01200441e8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441d0026a3602c002200441e8026a200441d8016a10e60320042902ec02221a422088a7210120042802e802210a201aa721020c010b0240024002402002200541186c6a22022802142210450d0020042802a40120014104746a220a2d000d2113200a280200210e200228020c210120022802002114200a280208220f2106024020022802082212450d002012410374210b200f21022014210a034002402002200a2802006a220620024f0d00024041201027220a0d0041204101102a000b200a41186a41002900b8a345370000200a41106a41002900b0a345370000200a41086a41002900a8a345370000200a41002900a0a3453700000c040b200a41086a210a20062102200b41786a220b0d000b0b0240410810272202450d0020022013ad42ff0183422886370200200441d0026a41026a220a200441e8026a41026a2d00003a0000200420042f00e8023b01d002200420133a00900220044180800136028c022004428180808010370284022004200236028002200442808080808080103703f801200442013703f001200420063602ec01200420123602e801200420143602e4012004200f3602e0012004200e3602dc01200420044180016a3602d801201120042f01d0023b0000201141026a200a2d00003a0000201041047441706a41047641016a210641002102034020042002360298022004200136029c02200441b0026a200441d8016a200110f803024020042802b002450d00200441c0026a41086a200441b0026a41086a280200360200200420042903b0023703c002200441033602e402200442033702d402200441e88ac5003602d002200441213602fc02200441013602f402200441223602ec022004200441e8026a3602e0022004200441c0026a3602f802200420044198026a3602f00220042004419c026a3602e802200441a0026a200441d0026a10e603024020042802c402450d0020042802c00210290b20042802a002220a450d0020042902a402211a024020042802f401450d0020042802f00110290b201a42208821230240200428028402450d0020042802800210290b2023a72101201aa721020c070b200141106a21012006200241016a2202470d000b02402004280288020d00024020042802f401450d0020042802f00110290b200428028402450d0720042802800210290c070b41808bc5001058000b41084104102a000b41201027220a450d01200a41186a41002900de8a45370000200a41106a41002900d68a45370000200a41086a41002900ce8a45370000200a41002900c68a453700000b41202102412021010c010b41204101102a000b200a450d010b2004200a3602d00220042001ad4220862002ad843702d4022004200441d0026a3602c002200441023602ec01200442023702dc01200441fc92c5003602d801200441233602f402200441013602ec022004200441e8026a3602e8012004200441c0026a3602f0022004200441c4016a3602e802200441c8016a200441d8016a10e603024020042802d402450d0020042802d00210290b20042802c801220a450d0020042902cc01211a0c120b200541016a2105200d41046a220d2015470d000b0b2008200c412c6c6a210a2008210102400340200a2001460d0120012d000021022001412c6a2206210120024109470d000b2004200641586a28020022013602b002024020042802b80120014b0d00200441ec016a4101360200200442023702dc01200441d8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441b0026a3602c002200441e8026a200441d8016a10e6030c0d0b200420042802b00120014102746a28020022013602d002024020042802ac0120014b0d00200441ec016a4101360200200442023702dc01200441e8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441d0026a3602c002200441e8026a200441d8016a10e6030c0d0b024020042802a40120014104746a22013502084200520d00200131000d4220864280808080f000834280808080c000510d010b412d1027220a450d02200a41256a41002900b19345370000200a41206a41002900ac9345370000200a41186a41002900a49345370000200a41106a410029009c9345370000200a41086a41002900949345370000200a410029008c934537000042ad808080d005211a0c100b2008200c412c6c6a210a200821010340200a2001460d0b20012d000021022001412c6a2206210120024108470d000b200441306a200641586a2201108003200441d8016a200428023410fb03200441e8026a41086a200441e4016a290200370300200441e8026a41106a200441d8016a41146a280200360200200420042902dc013703e802200441286a2001108003200428022c2201450d0920042802282215200141146c6a210e034020152217450d0a410021022017280208220d210120172802002216210a0240200d4104490d004100210220162101200d210a0340200128000020024105777341b9f3ddf1796c2102200141046a2101200a417c6a220a41034b0d000b200d417c6a22012001417c71220a6b2101200a20166a41046a210a0b02400240200141014b0d00200a21060c010b200a41026a21062001417e6a21012002410577200a2f00007341b9f3ddf1796c21020b02402001450d00200241057720062d00007341b9f3ddf1796c21020b201741146a2115200241057741ff017341b9f3ddf1796c22024119762213410874201372220141107420017221054100210f20042802f002211220042802e802210b20042802ec0221062002210103400240200b200120067122016a2800002214200573220a417f73200a41fffdfb776a7141808182847871220a450d00024003400240200d2012200a6841037620016a2006714103746a221041046a280200470d00201620102802002210460d0220162010200d10d004450d020b200a417f6a200a71220a450d020c000b0b200441ec016a4101360200200442013702dc01200441bc93c5003602d801200441023602b4022004200d3602c402200420163602c0022004200441b0026a3602e8012004200441c0026a3602b002200441d0026a200441d8016a10e6030c0a0b200f41046a220f20016a2101201420144101747141808182847871450d000b024020042802f8020d00200441e8026a10fc0320042802e802210b20042802ec0221060b200620027121024104210103402002220a20016a2006712102200141046a2101200b200a6a280000418081828478712205450d000b0240200b200568410376200a6a20067122016a2c000022024100480d00200b200b280200418081828478716841037622016a2d000021020b200b20016a20133a00002001417c6a200671200b6a41046a20133a000020042802f00220014103746a200dad4220862016ad84370200200420042802f40241016a3602f402200420042802f80220024101716b3602f802024002400240024002400240201728020c0e0400030201000b2004201728021022013602a002024020042802b80120014b0d00200441ec016a4101360200200442023702dc01200441d8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441a0026a3602c002200441d0026a200441d8016a10e6030c0e0b200420042802b00120014102746a28020022013602b00220042802ac0120014b0d03200441013602ec01200442023702dc01200441e8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441b0026a3602c002200441d0026a200441d8016a10e6030c0d0b2004201728021022013602a002024020042802a00120014b0d00200441ec016a4101360200200442023702dc0120044188a1c5003602d801200441013602c4022004200441c0026a3602e8012004200441a0026a3602c002200441d0026a200441d8016a10e6030c0d0b20042802980120014101746a2d0001450d02200441ec016a4101360200200442023702dc01200441a8a1c5003602d801200441013602c4022004200441c0026a3602e8012004200441a0026a3602c002200441d0026a200441d8016a10e6030c0c0b2004201728021022013602b00220042802880120014b0d01200441013602ec01200442023702dc0120044188a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441b0026a3602c002200441d0026a200441d8016a10e60320042802d002220a0d0c0c010b2004201728021022013602b00220042802940120014d0d010b2015200e470d010c0b0b0b200441ec016a4101360200200442023702dc01200441b8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441b0026a3602c002200441d0026a200441d8016a10e6030c070b20184101102a000b412d4101102a000b41aa92c50041c800104e000b418c92c500411e104e000b20204104102a000b20114104102a000b20184104102a000b20042802d002210a0b20042902d402211a2006450d060240200641016a220141ffffffff01712001470d00200641086a417c712202200641056a490d00200220014103746a2002491a0b200b10290c060b20042802ec022201450d000240200141016a220241ffffffff01712002470d00200141086a417c71220a200141056a490d00200a20024103746a200a491a0b20042802e80210290b2008200c412c6c6a210a2008210102400340200a2001460d0120012d000021022001412c6a2206210120024103470d000b200441206a200641586a10800320042802242201450d0020042802202106200141286c210b41002101034002400240024002400240200620016a220241186a2d00000e0400030201000b20042002411c6a28020022023602d00220042802ac0120024b0d03200441ec016a4101360200200442023702dc01200441e8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441d0026a3602c002200441e8026a200441d8016a10e6030c060b2002411a6a2d0000450d022002410c6a2802002101200241146a2802002102200441d8016a41146a4101360200200420023602d402200420013602d002200441023602c402200442013702dc01200441c493c5003602d8012004200441d0026a3602c0022004200441c0026a3602e801200441e8026a200441d8016a10e6030c050b200441d8016a2002411c6a10f50320042802d801220a450d0120042902dc01211a0c080b200241206a2802004101470d002002411c6a280200210a2004200241246a28020022023602b002200a20024d0d00200441023602ec01200442023702dc01200441dc9cc5003602d801200441013602f402200441013602ec022004200a3602c0022004200441e8026a3602e8012004200441c0026a3602f0022004200441b0026a3602e802200441d0026a200441d8016a10e60320042802d002220a0d060b200b200141286a2201470d000b0b024002400240200428029401220141014b0d00200428028801220141014b0d012008200c412c6c6a210a2008210102400240024002400340200a2001460d0120012d000021022001412c6a220621012002410c470d000b200441186a200641586a10800320042802182201200428021c411c6c6a2106034020012006460d012004200128020022023602d002024020042802880120024b0d00200441013602ec01200442023702dc0120044188a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441d0026a3602c002200441e8026a200441d8016a10e60320042802e802220a450d0020042902ec02211a0c0d0b200441d8016a200141046a220120042802980120042802a00110f60320042d00d8014101460d02200141186a210120042d00d901450d000b41201027220a450d06200a41186a41002900f49345370000200a41106a41002900ec9345370000200a41086a41002900e49345370000200a41002900dc934537000042a08080808004211a0c0b0b2008200c412c6c6a210a2008210102400340200a2001460d0120012d000021022001412c6a220621012002410a470d000b200441106a200641586a10800320042802142201450d002004280210220b2001411c6c6a21050340200b450d012004200b28020022013602d00220042802940120014d0d03200441d8016a200b41046a20042802980120042802a00110f60320042d00d8014101460d0420042d00d9010d09200441086a200b10fd0302400240200428020c2201450d00200428020821022001410274210a20042802b801210603402004200228020022013602b0020240200620014b0d00200441ec016a4101360200200442023702dc01200441d8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441b0026a3602c002200441e8026a200441d8016a10e6030c0c0b200420042802b00120014102746a28020022013602d00220042802ac0120014d0d02200241046a2102200a417c6a220a0d000b0b200b411c6a220b2005460d020c010b0b200441013602ec01200442023702dc01200441e8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441d0026a3602c002200441e8026a200441d8016a10e6030c070b0240200428028401450d0020042802800110290b0240200428029001450d00200428028c0110290b0240200428029c01450d0020042802980110290b024020042802ac012202450d0020042802a40121012002410474210203400240200141046a280200450d00200128020010290b200141106a2101200241706a22020d000b0b024020042802a801450d0020042802a40110290b024020042802b401450d0020042802b00110290b201f450d0d201910290c0d0b200441e0016a290300211a20042802dc01210a0c090b200441ec016a4101360200200442023702dc01200441b8a0c5003602d801200441013602c4022004200441c0026a3602e8012004200441d0026a3602c002200441e8026a200441d8016a10e6030c040b200441e0016a290300211a20042802dc01210a0c070b200441ec016a4101360200200442013702dc01200441cc93c5003602d801200441013602d402200420013602c0022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10e6030c020b200441ec016a4101360200200442013702dc01200441d493c5003602d801200441013602d402200420013602c0022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10e6030c010b41204101102a000b20042802e802210a20042902ec02211a0c030b024041201027220a450d00200a41186a41002900f49345370000200a41106a41002900ec9345370000200a41086a41002900e49345370000200a41002900dc934537000042a08080808004211a0c030b41204101102a000b200441ec016a4102360200200441f4026a4101360200200442023702dc01200441fc91c5003602d801200441013602ec022004200441e8026a3602e8012004200441c0016a3602f0022004200441bc016a3602e802200441d0026a200441d8016a10e60320042802d002210a0b20042902d402211a0b0240200428028401450d0020042802800110290b0240200428029001450d00200428028c0110290b0240200428029c01450d0020042802980110290b024020042802ac012202450d0020042802a40121012002410474210203400240200141046a280200450d00200128020010290b200141106a2101200241706a22020d000b0b024020042802a801450d0020042802a40110290b024020042802b401450d0020042802b00110290b201f450d0120191029200a0d040c020b2001290204211a2001280200210a0240201f450d00201910290b0240201e450d00201410290b0240200e450d00201510290b02402013450d00201210290b02402010450d0020104104742102201c210103400240200141046a280200450d00200128020010290b200141106a2101200241706a22020d000b0b0240201d450d00201c10290b200d450d00201710290b200a0d020b2000201b36020420004100360200200041186a2003360200200041146a200c360200200041106a20093602002000410c6a2008360200200041086a20073602000c040b102b000b0240201aa7450d00200a10290b200041f48cc50036020420004101360200200041086a41133602000240200c450d00200c412c6c210220082101034020011088032001412c6a2101200241546a22020d000b0b2009450d02200810290c020b200441003a00d002200441ec016a4101360200200442013702dc0120044180c0c5003602d8012004411f3602b4022004200441b0026a3602e8012004200441d0026a3602b00220044180016a200441d8016a10e603200428028001210720042802840121060240200c450d00200c412c6c210220082101034020011088032001412c6a2101200241546a22020d000b0b4105210a2009450d00200810290b02402006450d00200a41ff01714105470d00200710290b200041de8cc50036020420004101360200200041086a41163602000b20044180036a24000b160020002001280208360204200020012802003602000bd41301177f23004190026b2202240002400240024002400240024020002802002203418883c000460d00200028020421040c010b41002104200241b8016a410041d80010cd041a2002411f6a220542003700002002420037011a41ec0010272203450d0120034100360200200320022902183702042003410b6a2005290000370000200341136a200241b7016a41d90010ce041a20004100360204200020033602000b200141ff01712106024003402003410c6a2107200341086a210820032f010621094100210502400240034020092005460d01200820056a210a200741086a2107200541016a210502404100417f4101200a2d0000220a20064b1b200a2006461b41016a0e03000301000b0b2005417f6a21090b2004450d022004417f6a2104200320094102746a41ec006a28020021030c010b0b200742013702000c030b2000200028020841016a360208024002400240024020032f01062205410b490d00200241276a41016a410041d80010cd041a200241003a001941ec0010272204450d03200441003602002004410036000f20044200370007200420022f01183b0005200441136a200241276a41d90010ce041a2003410e6a2d0000210b2003280248210c2003280244210d200441086a2003410f6a20032f010641796a220510ce042107200441146a200341cc006a200541037410ce042106200341063b0106200420053b010620094107490d0120072009417a6a220a6a2007200941796a22096a2207200541ffff037120096b10cf041a200720013a00002006200a4103746a200620094103746a2207200441066a22052f010020096b41037410cf041a2007410136020020052f010021070c020b200341086a2207200941016a22066a200720096a2207200520096b220a10cf041a200720013a0000200341146a220720064103746a200720094103746a2207200a41037410cf041a200741013602002003200541016a3b01060c050b200341086a2205200941016a22066a200520096a220a200341066a22052f0100220720096b220810cf041a200a20013a0000200341146a220a20064103746a200a20094103746a2209200841037410cf041a200941013602000b2005200741016a3b01002003280200220a450d02200341046a2105200241276a41016a210e200241a8016a210f200241a0016a211020024198016a211120024190016a211220024180016a41086a2113034020052f0100210602400240024002400240200a2f01062205410b490d00200e410041d80010cd041a200241003a0019200220022f01183b0108200241b7016a200241276a41d90010ce041a200f4200370300201042003703002011420037030020124200370300201342003703002002420037038001419c0110272207450d03200741003602002007410036000f20074200370007200720022f01083b0005200741136a200241b7016a41d90010ce041a20074194016a200f2903003702002007418c016a201029030037020020074184016a2011290300370200200741fc006a2012290300370200200741f4006a2013290300370200200720022903800137026c200a41c8006a2802002114200a41c4006a2802002115200a410e6a2d00002116200741086a200a410f6a200a2f0106220341796a220510ce042117200741146a200a41cc006a200541037410ce042118200741ec006a200a4188016a2003417a6a220841027410ce042101200a41063b0106200720053b010602402008450d00410021052001210303402003280200220920053b010420092007360200200341046a21032008200541016a2205470d000b0b20064107490d0120172006417a6a22036a2017200641796a22056a220920072f010620056b10cf041a2009200b3a0000201820034103746a201820054103746a220920072f010620056b41037410cf041a2009200d3602002009200c360204200720072f010641016a22093b01062006410274220b20016a416c6a200120034102746a2208200941ffff0371220620036b41027410cf041a2008200436020020062003490d022007200b6a41d4006a2103034020032802002209200541016a22053b010420092007360200200341046a210320052006490d000c030b0b200a41086a2207200641016a22036a200720066a2207200520066b220910cf041a2007200b3a0000200a41146a220720034103746a200720064103746a2207200941037410cf041a2007200d3602002007200c360204200a200541016a22053b01062006410274200a41ec006a22076a41086a200720034102746a2207200541ffff0371220920036b41027410cf041a20072004360200200620094f0d08200a2003417f6a22054102746a41f0006a2103034020032802002207200541016a22053b01042007200a360200200341046a210320052009490d000c090b0b200a41086a2203200641016a22056a200320066a2203200a2f0106220920066b220810cf041a2003200b3a0000200a41146a220320054103746a200320064103746a2203200841037410cf041a2003200d3602002003200c360204200a200941016a22033b010620064102742201200a41ec006a22096a41086a200920054102746a2208200341ffff0371220920056b41027410cf041a20082004360200200620094f0d00200a20016a41f0006a2105034020052802002203200641016a22063b01042003200a360200200541046a210520092006470d000b0b200a28020022030d01200721042014210c2015210d2016210b0c050b419c014104102a000b200a41046a21052003210a2016210b2015210d2014210c200721040c000b0b41ec004104102a000b41ec004104102a000b200241b7016a41016a410041d80010cd041a2002411f6a220542003700002002420037011a200220022902183703082002200529000037000f200241276a200241b7016a41d90010ce041a200241a8016a22034200370300200241a0016a2207420037030020024180016a41186a2209420037030020024190016a2206420037030020024180016a41086a220a42003703002002420037038001419c0110272205450d0120054100360200200520022903083702042005410b6a200229000f370000200541136a200241276a41d90010ce041a20054194016a20032903003702002005418c016a200729030037020020054184016a2009290300370200200541fc006a2006290300370200200541f4006a200a290300370200200520022903800137026c20052000280200220336026c200020053602002000200028020441016a360204200341003b010420032005360200200520052f010622034103746a220741186a200c360200200741146a200d360200200520036a41086a200b3a0000200541ec006a200341016a22034102746a2004360200200520033b0106200420033b0104200420053602000b20024190026a24000f0b419c014104102a000bd11e01387f23004190016b2202240020024184016a4200370200200241fc006a4280808080c000370200200241ec006a4200370200200241e4006a4280808080c000370200200241d0006a4200370300200241c0006a4200370300200241386a4280808080c000370300200241286a4200370300200241206a4280808080c000370300200241106a4200370300200242043702742002420437025c20024204370348200242043703302002420437031820024280808080c000370308200242043703002001410c6a280200210320024180016a210420012802082105024002400240200141106a28020022060d00410421014100210741002108410021094100210a4104210b4100210c4100210d4104210e4100210f41002110410421114100211241002113410421144100210641002115410421164100211741002118410421194100211a4100211b4104211c4100211d4100211e4104211f41002120410021210c010b410021224100211f41002123410021244100211c410021254100212641002127410021284100212941002107024003402001212a2007211520052006417f6a2206412c6c6a2201280024211720012800202119200128001821182001280014211420012800102116200128000c210c2001280008210b200128000421094101210741012112024002400240024002400240024020012d0000220a417e6a2208410d4d0d00410121130c010b4101211341012110410121114101210f4101210d4101210e20092101024002400240024002400240024002400240024020080e0e000102030405060f0708090e0e11000b02402029450d000240202b450d00202b41047421072029210103400240200141046a280200450d00200128020010290b200141106a2101200741706a22070d000b0b202c450d00202910290b4101211341002112200c212b200b212c200921290c090b02402028450d000240202d450d00202d41286c21072028210103400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200741586a22070d000b0b202e450d00202810290b4100211341012112200c212d200b212e200921280c080b0240202f450d002027450d00202710290b20152107202a210120092127200b212f200c21300c0c0b02402031450d002026450d00202610290b20152107202a210120092126200b2131200c21320c0b0b02402033450d002025450d00202510290b20152107202a210120092125200b2133200c21340c0a0b0240201c450d000240201a450d00201c201a4104746a210d201c21080340024020082802082207450d0020082802002101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b200841106a21010240200841046a280200450d00200828020010290b200121082001200d470d000b0b2035450d00201c10290b4100211041012112200c211a200b21352009211c410121130c050b02402024450d000240201e450d00201e41146c21072024210103400240200141046a280200450d00200128020010290b200141146a21012007416c6a22070d000b0b2036450d00202410290b4100211141012112200c211e200b21362009212441012113410121100c050b02402023450d000240201d450d002023201d411c6c6a210d20232108034002402008410c6a2802002207450d0020082802042101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b0240200841086a280200450d00200828020410290b2008411c6a21010240200841146a280200450d00200828021010290b200121082001200d470d000b0b2037450d00202310290b4100210f41012112200c211d200b2137200921234101211341012110410121110c050b0240201f450d000240201b450d00201f201b41186c6a210d201f210803400240200841046a280200450d00200828020010290b0240200841146a2802002207450d00200828020c2101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b200841186a21010240200841106a280200450d00200828020c10290b200121082001200d470d000b0b2020450d00201f10290b4100210d41012112200c211b200b21202009211f4101211341012110410121114101210f4101210e0c050b02402022450d0002402038450d0020222038411c6c6a210d20222108034002402008410c6a2802002207450d0020082802042101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b0240200841086a280200450d00200828020410290b2008411c6a21010240200841146a280200450d00200828021010290b200121082001200d470d000b0b2039450d00202210290b4100210e41012112200c2138200b2139200921224101211341012110410121114101210f4101210d0c040b410121100b410121110b4101210f0b4101210d4101210e0b02400240024002400240200a410d4b0d0020152107202a210102400240024002400240024002400240024002400240200a0e0e080900010202020304100506070a080b2012450d0e0240200c450d00200c41047421072009210103400240200141046a280200450d00200128020010290b200141106a2101200741706a22070d000b0b200b450d0e0c0d0b2013450d0d200c450d00200c41286c21072009210103400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200741586a22070d000b0b200b0d0b0c0c0b2010450d0b0240200c450d002009200c4104746a210a200921080340024020082802082207450d0020082802002101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b200841106a21010240200841046a280200450d00200828020010290b200121082001200a470d000b0b200b0d0a0c0b0b2011450d0a0240200c450d00200c41146c21072009210103400240200141046a280200450d00200128020010290b200141146a21012007416c6a22070d000b0b200b0d090c0a0b200f450d090240200c450d002009200c411c6c6a210a20092108034002402008410c6a2802002207450d0020082802042101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b0240200841086a280200450d00200828020410290b2008411c6a21010240200841146a280200450d00200828021010290b200121082001200a470d000b0b200b0d080c090b200d450d080240200c450d002009200c41186c6a210a2009210803400240200841046a280200450d00200828020010290b0240200841146a2802002207450d00200828020c2101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b200841186a21010240200841106a280200450d00200828020c10290b200121082001200a470d000b0b200b0d070c080b200e450d07200c450d002009200c411c6c6a210a20092108034002402008410c6a2802002207450d0020082802042101200741047421070340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200741706a22070d000b0b0240200841086a280200450d00200828020410290b2008411c6a21010240200841146a280200450d00200828021010290b200121082001200a470d000b0b200b0d050c060b0240200b450d00200910290b2014450d05201610290c050b0240200941ff0171220141024b0d0002400240024020010e03000102000b200c450d070c050b02402014450d002014410c6c2107200c21010340024020012802002208450d00200141046a280200450d00200810290b2001410c6a2101200741746a22070d000b0b2016450d060c030b02402014450d00200c20144104746a210b200c210a0340200a220941106a210a024020092802042201450d0002402009410c6a2802002207450d002007410c6c21070340024020012802002208450d00200141046a280200450d00200810290b2001410c6a2101200741746a22070d000b0b200941086a280200450d00200928020410290b200a200b470d000b0b20160d020c050b200c0d020c040b0240200b450d00200910290b02402014450d002018450d00201410290b2017450d03201910290c030b200c10290c020b200b10290c010b200910290b20152107202a21010b20060d000b410021062001212a200721150b201b4100201f1b210720204100201f1b2108201d410020231b21212037410020231b2120201e410020241b21092036410020241b210a201a4100201c1b211e20354100201c1b211d2034410020251b210c2033410020251b210d2032410020261b211b2031410020261b211a2030410020271b210f202f410020271b2110202d410020281b2118202e410020281b2117202b410020291b2112202c410020291b2113201f4104201f1b21012023410420231b211f2024410420241b210b201c4104201c1b211c2025410420251b210e2026410420261b21192027410420271b21112028410420281b21162029410420291b211420220d010b4104212241002139410021380b200410a4040240200228028401450d0020022802800110290b200241d8006a202a3602002002200636028801200220033602840120022005360280012002203836027c2002203936027820022022360274200220073602702002200836026c2002200136026820022021360264200220203602602002201f36025c20022015360254200220093602502002200a36024c2002200b3602482002201e3602442002201d3602402002201c36023c2002200c3602382002200d3602342002200e3602302002201b36022c2002201a360228200220193602242002200f3602202002201036021c2002201136021820022018360214200220173602102002201636020c20022012360208200220133602042002201436020020002002418c0110ce041a20024190016a24000bc30a01107f230041106b220224000240024002400240024020012802004101470d00200141106a2d000021032001410c6a2802002104200141086a280200210520012f0112210620012d0011210720012802042108200241086a200010800320022802082201200228020c22094104746a210a4100210b20094104490d01200341ff0171210c024002400340024020012d000c200c470d0020012802082004470d002001280200210d200421092008210e024003402009450d012009417f6a2109200e2d0000210f200d2d00002110200e41016a210e200d41016a210d2010200f460d000c020b0b20012d000d2209410446220f200741ff0171220d410446220e470d002009200d460d06200e0d06200f0d060b024002402001411c6a2d0000200c470d00200141186a2802002004470d002001280210210d200421092008210e024003402009450d012009417f6a2109200e2d0000210f200d2d00002110200e41016a210e200d41016a210d2010200f460d000c020b0b20012d001d2209410446220f200741ff0171220d410446220e470d002009200d460d01200e0d01200f0d010b02402001412c6a2d0000200c470d00200141286a2802002004470d002001280220210d200421092008210e024003402009450d012009417f6a2109200e2d0000210f200d2d00002110200e41016a210e200d41016a210d2010200f460d000c020b0b20012d002d2209410446220f200741ff0171220d410446220e470d002009200d460d03200e0d03200f0d030b02402001413c6a2d0000200c470d00200141386a2802002004470d002001280230210d200421092008210e024003402009450d012009417f6a2109200e2d0000210f200d2d00002110200e41016a210e200d41016a210d2010200f460d000c020b0b20012d003d2209410446220f200741ff0171220d410446220e470d002009200d460d04200e0d04200f0d040b200b41046a210b200a200141c0006a22016b41304d0d050c010b0b200b410172210b0c040b200b410272210b0c030b200b410372210b0c020b2001280204210b0c030b2001200a460d0102400240200741ff017122114104460d00200341ff0171210c0c010b200341ff0171210c0340024020012d000c200c470d0020012802082004470d002001280200210d200421092008210e024003402009450d012009417f6a2109200e2d0000210f200d2d00002110200e41016a210e200d41016a210d2010200f460d000c020b0b20012d000d4104460d030b200b41016a210b200141106a2201200a470d000c030b0b0340024020012d000c200c470d0020012802082004470d002001280200210e200421092008210d024003402009450d012009417f6a2109200d2d0000210f200e2d00002110200d41016a210d200e41016a210e2010200f460d000c020b0b20012d000d22092011470d0020094104470d020b200b41016a210b200141106a2201200a460d020c000b0b2005450d01200810290c010b02400240200041046a28020020002802082201460d00200028020021090c010b02400240200141016a22092001490d002001410174220d20092009200d491b220d41ffffffff0071200d470d00200d410474220e4100480d000240024020010d00200e102721090c010b20002802002001410474200e102821090b2009450d0120002009360200200041046a200d360200200028020821010c020b102b000b200e4104102a000b200920014104746a220120063b010e200120073a000d200120033a000c2001200436020820012005360204200120083602002000200028020841016a360208200220001080032002280204417f6a210b0b200241106a2400200b0bcc21032d7f017e017f230041306b2202240020012802042103200128020021044101210502400240024002400240024002400240024002400240024002400240024002400240200128020822060d004104210741002108410121090c010b412c10272207450d01200741023a0000200720022f002d3b00012007200636000c200720033600082007200436000420072002290208370210200741036a2002412d6a41026a2d00003a0000200741186a200241106a290200370200200741206a200241186a290200370200200741286a200241086a41186a28020036020041002109410121080b200141106a280200210a200128020c210b02400240200141146a280200220c0d002008210d0c010b2008410174220d200841016a220e200e200d491b220d412c6c210e0240024020080d00200e102721070c010b20072008412c6c200e102821070b2007450d0220072008412c6c6a220e41033a0000200e20022f002d3b0001200e200c36000c200e200a360008200e200b360004200e2002290208370210200e41036a2002412f6a2d00003a0000200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a280200360200200841016a2108410021050b2001411c6a280200210f200128021821104100211102400240200141206a28020022120d00410021130c010b0240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22142014200e491b220ead422c7ea722144100480d0e02400240200d0d002014102721070c010b2007200d412c6c2014102821070b2007450d04200e210d0b20072008412c6c6a220e41043a0000200e201236000c200e200f360008200e2010360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a28020036020041012113200841016a21080b200141286a28020021122001280224211502402001412c6a2802002214450d000240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22112011200e491b220ead422c7ea722114100480d0e02400240200d0d002011102721070c010b2007200d412c6c2011102821070b2007450d05200e210d0b20072008412c6c6a220e41053a0000200e201436000c200e2012360008200e2015360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a28020036020041012111200841016a21080b200141346a28020021142001280230211602400240200141386a28020022170d00410021180c010b0240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22192019200e491b220ead422c7ea722194100480d0e02400240200d0d002019102721070c010b2007200d412c6c2019102821070b2007450d06200e210d0b20072008412c6c6a220e41063a0000200e201736000c200e2014360008200e2016360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a28020036020041012118200841016a21080b200141c0006a280200211a200128023c211b4101211702400240200141c4006a280200221c0d004101211d0c010b0240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22192019200e491b220ead422c7ea722194100480d0e02400240200d0d002019102721070c010b2007200d412c6c2019102821070b2007450d07200e210d0b20072008412c6c6a220e41073a0000200e201c36000c200e201a360008200e201b360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a280200360200200841016a21084100211d0b200141cc006a280200211e2001280248211f0240200141d0006a2802002220450d000240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22172017200e491b220ead422c7ea722174100480d0e02400240200d0d002017102721070c010b2007200d412c6c2017102821070b2007450d08200e210d0b20072008412c6c6a220e41083a0000200e202036000c200e201e360008200e201f360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241086a41086a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a280200360200200841016a2108410021170b41012119024020012802544101470d00200141d8006a28020021210240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22222022200e491b220ead422c7ea722224100480d0e02400240200d0d002022102721070c010b2007200d412c6c2022102821070b2007450d09200e210d0b20072008412c6c6a220e41093a0000200e2021360204200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370208200e41106a200241106a290200370200200e41186a200241086a41106a290200370200200e41206a200241086a41186a290200370200200e41286a200241086a41206a280200360200200841016a21080b200141e0006a2802002123200128025c21220240200141e4006a2802002224450d000240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22192019200e491b220ead422c7ea722194100480d0e02400240200d0d002019102721070c010b2007200d412c6c2019102821070b2007450d0a200e210d0b20072008412c6c6a220e410a3a0000200e202436000c200e2023360008200e2022360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a280200360200200841016a2108410021190b200141ec006a2802002125200128026821264101212102400240200141f0006a28020022270d00410121280c010b0240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22292029200e491b220ead422c7ea722294100480d0e02400240200d0d002029102721070c010b2007200d412c6c2029102821070b2007450d0b200e210d0b20072008412c6c6a220e410b3a0000200e202736000c200e2025360008200e2026360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a280200360200200841016a2108410021280b200141f8006a280200212a200128027421290240200141fc006a280200222b450d000240200d2008470d0041000d0e41000d0e200d410174220e200d41016a22212021200e491b220ead422c7ea722214100480d0e02400240200d0d002021102721070c010b2007200d412c6c2021102821070b2007450d0c200e210d0b20072008412c6c6a220e410c3a0000200e202b36000c200e202a360008200e2029360004200e20022f002d3b0001200e41036a2002412f6a2d00003a0000200e2002290208370210200e41186a200241106a290200370200200e41206a200241186a290200370200200e41286a200241086a41186a280200360200200841016a2108410021210b20014184016a280200212c200128028001210e02400240200d20086b20014188016a280200412c6c222d412c6d2201490d00200820016a21010c010b200820016a22012008490d0d200d410174222e20012001202e491b222ead422c7e222f422088a70d0d202fa722304100480d0d02400240200d0d002030102721070c010b2007200d412c6c2030102821070b2007450d0c202e210d0b20072008412c6c6a200e202d10ce041a0240202c450d00200e10290b41c00510272208450d0d2000200736020820004280c2cdeb16370200200241086a410c6a4210370200200041106a20013602002000410c6a200d3602002002200836021020024280c2cdeb16370308200241106a10a404200810292021450d0e0240202b450d002029202b411c6c6a210d20292107034002402007410c6a2802002208450d0020072802042101200841047421080340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200841706a22080d000b0b0240200741086a280200450d00200728020410290b2007411c6a21010240200741146a280200450d00200728021010290b200121072001200d470d000b0b202a450d0e202910290c0e0b412c4104102a000b200e4104102a000b20144104102a000b20114104102a000b20194104102a000b20194104102a000b20174104102a000b20224104102a000b20194104102a000b20294104102a000b20214104102a000b20304104102a000b102b000b41c0054104102a000b02402028450d0002402027450d002026202741186c6a210d2026210703400240200741046a280200450d00200728020010290b0240200741146a2802002208450d00200728020c2101200841047421080340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200841706a22080d000b0b200741186a21010240200741106a280200450d00200728020c10290b200121072001200d470d000b0b2025450d00202610290b02402019450d0002402024450d0020222024411c6c6a210d20222107034002402007410c6a2802002208450d0020072802042101200841047421080340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200841706a22080d000b0b0240200741086a280200450d00200728020410290b2007411c6a21010240200741146a280200450d00200728021010290b200121072001200d470d000b0b2023450d00202210290b02402017450d0002402020450d00202041146c2108201f210103400240200141046a280200450d00200128020010290b200141146a21012008416c6a22080d000b0b201e450d00201f10290b0240201d450d000240201c450d00201b201c4104746a210d201b21070340024020072802082208450d0020072802002101200841047421080340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200841706a22080d000b0b200741106a21010240200741046a280200450d00200728020010290b200121072001200d470d000b0b201a450d00201b10290b02402014410047201841017371450d00201610290b02402012410047201141017371450d00201510290b0240200f410047201341017371450d00201010290b02402005450d000240200c450d00200c41286c2108200b210103400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200841586a22080d000b0b200a450d00200b10290b02402009450d0002402006450d00200641047421082004210103400240200141046a280200450d00200128020010290b200141106a2101200841706a22080d000b0b2003450d00200410290b200241306a24000b860501017f411021010240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200041ff01710eac010001020202020202020202020202020303030404050506060707080809090a0a0b0b0c0d0d0e0e0f0f1010111213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f2020212122222323242425252627272828292a2a2b2b2c2d2d2e2e2f2f303031313232333434353536363737383839393a3a3b3b3c3c3d3d3e3e3f3f40404141424243434444454546464747484a4a4a4a49494a4a4a4a4a4a4a4a4a4a4a4a4a4a4b4b4b4b000b41110f0b41120f0b410a0f0b41080f0b41080f0b41040f0b41040f0b41040f0b41040f0b41040f0b41040f0b41040f0b41050f0b41050f0b41050f0b41050f0b41050f0b41130f0b41140f0b41060f0b41070f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410b0f0b410c0f0b410c0f0b410c0f0b410c0f0b410c0f0b410c0f0b41000f0b41000f0b41010f0b41020f0b41030f0b41030f0b41000f0b41000f0b41000f0b41000f0b41000f0b41000f0b41010f0b41020f0b41030f0b41030f0b41000f0b41000f0b41000f0b41000f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410d0f0b410e0f0b410e0f0b410f21010b20010bfe0101057f02400240024002400240200041086a28020022032001490d002003200041046a280200460d01200341016a2104200028020021050c020b41d0b1c5001058000b200341016a22042003490d0220034101742205200420042005491b220641ffffffff00712006470d02200641047422074100480d020240024020030d002007102721050c010b200028020020034104742007102821050b2005450d0120002005360200200041046a20063602000b200520014104746a220541106a2005200320016b41047410cf041a200541086a200241086a29030037030020052002290300370300200041086a20043602000f0b20074108102a000b102b000b800502067f017e230041306b22022400200241106a200141246a290200370300200241086a2001411c6a29020037030020022001290214370300200241186a41106a200141106a280200360200200241186a41086a200141086a290200370300200220012902003703182000200241186a1083032103024002400240024002402000411c6a280200200041206a2802002204460d00200028021821050c010b200441016a22052004490d0320044101742206200520052006491b220641ffffffff03712006470d03200641027422074100480d030240024020040d002007102721050c010b200028021820044102742007102821050b2005450d01200020053602182000411c6a2006360200200028022021040b200520044102746a20033602002000200028022041016a360220200241186a41106a200241106a290300370300200241186a41086a200241086a2903003703002002200229030037031802400240200041ec006a280200200041f0006a2802002204460d00200028026821050c010b200441016a22052004490d0320044101742203200520052003491b2203ad42187e2208422088a70d032008a722064100480d030240024020040d002006102721050c010b2000280268200441186c2006102821050b2005450d0220002005360268200041ec006a2003360200200041f0006a28020021040b2005200441186c6a22042002290318370200200441106a200241186a41106a290300370200200441086a200241186a41086a290300370200200041f0006a22042004280200220441016a360200024020012d002c450d0020004101360254200041d8006a20043602000b200241306a24000f0b20074104102a000b20064104102a000b102b000bcf0d01067f0240024020002d00002201410d4b0d00024002400240024002400240024002400240024002400240024020010e0e0001020304050607080e090a0b0c000b200041086a280200450d0d200041046a28020010290f0b0240200041086a280200450d00200041046a28020010290b200041146a280200450d0c200041106a28020010290f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d00200128020010290b200141106a2101200241706a22020d000b0b200041086a280200450d0b200028020410290f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200241586a22020d000b0b200041086a280200450d0a200028020410290f0b200041086a280200450d09200041046a28020010290f0b200041086a280200450d08200041046a28020010290f0b200041086a280200450d07200041046a28020010290f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d00200328020010290b2001210320012004470d000b0b200041086a280200450d06200028020410290f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d00200128020010290b200141146a21012002416c6a22020d000b0b200041086a280200450d05200028020410290f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a2104034002402003410c6a2802002202450d0020032802042101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b0240200341086a280200450d00200328020410290b2003411c6a21010240200341146a280200450d00200328021010290b2001210320012004470d000b0b200041086a280200450d04200028020410290f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d00200328020010290b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d00200328020c10290b2001210320012004470d000b0b200041086a280200450d03200028020410290f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a2104034002402003410c6a2802002202450d0020032802042101200241047421020340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200241706a22020d000b0b0240200341086a280200450d00200328020410290b2003411c6a21010240200341146a280200450d00200328021010290b2001210320012004470d000b0b200041086a280200450d02200028020410290f0b0240200041046a2d0000220141024b0d0002400240024020010e03000102000b2000410c6a280200450d04200041086a28020010290f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c21020340024020012802002203450d00200141046a280200450d00200310290b2001410c6a2101200241746a22020d000b0b200041106a280200450d03200028020c10290f0b0240200041146a2802002201450d002000410c6a280200220520014104746a210603402005220441106a2105024020042802042201450d0002402004410c6a2802002202450d002002410c6c21020340024020012802002203450d00200141046a280200450d00200310290b2001410c6a2101200241746a22020d000b0b200441086a280200450d00200428020410290b20052006470d000b0b200041106a280200450d02200028020c10290c020b2000410c6a280200450d01200041086a28020010290f0b0240200041086a280200450d00200041046a28020010290b0240200041146a2802002201450d00200041186a280200450d00200110290b200041246a280200450d00200041206a28020010290f0b0b907f05087f017e1d7f037e187f23002203210420034180096b41607122032400024002400240024002400240024002400240024002400240024002400240411010272205450d00200541063a0000412010272206450d01200641063a00104100210720064100360204200620032f00f0053b00012006412d3a0000200641036a200341f2056a2d00003a0000024020052d00004109470d00200528020841ffffffff0371450d00200528020410290b20051029200141106a2802002208412c6c21092001280208210a02400340024020092007470d00411010272205450d0520054180023b010c200542828080802037020420052006360200200520032f01d0033b010e02402001410c6a2802002008470d00200841016a22072008490d0f20084101742209200720072009491b2207ad422c7e220b422088a70d0f200ba722094100480d0f0240024020080d0020091027210a0c010b200a2008412c6c20091028210a0b200a450d072001200a3602082001410c6a20073602000b2001200841016a220c360210200a2008412c6c6a220741073a0000200720032f00e0043b0001200742818080801037000820072005360004200720032902f005370210200741036a200341e2046a2d00003a0000200741186a200341f8056a290200370200200741206a20034180066a290200370200200741286a200341f0056a41186a2802003602004100210d0c020b200a20076a21052007412c6a220e210720052d00004107470d000b200320032f01d0033b01f005200a200e6a220541586a210a024002402005415c6a220c280200200541606a22092802002207460d00200a280200210e0c010b200741016a220e2007490d0d20074101742208200e200e2008491b220841ffffffff00712008470d0d2008410474220d4100480d0d0240024020070d00200d1027210e0c010b200541586a2802002007410474200d1028210e0b200e450d06200c2008360200200541586a200e360200200928020021070b200e20074104746a22074180023b010c200742828080802037020420072006360200200720032f01f0053b010e2009200928020041016a360200200341c0006a200a1080032003280244417f6a210d2001280210210c2001280208210a0b200c412c6c2107200a41586a210502400340410021062007450d01200741546a2107200541286a21092005412c6a220e210520092d00004103470d000b200e41086a2802002207450d00200741286c2105200e28020041186a2107410021060340200620072d0000456a2106200741286a2107200541586a22050d000b0b200c412c6c2107200a41586a210502400340410021092007450d01200741546a2107200541286a210e2005412c6a22082105200e2d00004103470d000b200841086a2802002207450d00200741286c2105200828020041186a2107410021090340200920072d0000456a2109200741286a2107200541586a22050d000b0b200c412c6c2107200a41606a210502400340024020070d00410021070c020b200741546a2107200541206a210e2005412c6a220a2105200e2d00004104470d000b200a28020021070b200720096a220f41ffffffff0371200f470d0c200f4102742207417f4c0d0c0240024020070d00410421100c010b2007107c2210450d060b024002400240024002400240200f450d002010200f4102746a211141002112201021130340024020122006490d0020012802102214412c6c220921072001280208221541586a220e2105024003404100210a2007450d01200741546a2107200541286a21082005412c6a220c210520082d00004103470d000b200c41086a2802002207450d00200741286c2105200c28020041186a21074100210a0340200a20072d0000456a210a200741286a2107200541586a22050d000b0b2012200a6b220a20124b0d0303402009450d05200941546a2109200e41286a2107200e412c6a2205210e20072d0000410b470d000b200541086a280200200a4d0d052005280200200a41186c6a2802082105200341f0056a200a200110960420032802f405210720032802f0054101460d072013200720056a3602000b201241016a2112201341046a22132011470d000b0b20012802102114200128020821150c0f0b412c10272207450d0a200741286a4100280092ac45360000200741206a410029008aac45370000200741186a4100290082ac45370000200741106a41002900faab45370000200741086a41002900f2ab45370000200741002900eaab4537000042ac808080c005210b0c020b412c10272207450d0a200741286a41002800beac45360000200741206a41002900b6ac45370000200741186a41002900aeac45370000200741106a41002900a6ac45370000200741086a410029009eac4537000020074100290096ac4537000042ac808080c005210b0c010b411e10272207450d0a200741166a41002900d8ac45370000200741106a41002900d2ac45370000200741086a41002900caac45370000200741002900c2ac45370000429e808080e003210b0b201010290c0a0b20032903f805210b2010102920070d09410021100c0a0b41104108102a000b41204108102a000b41104104102a000b20094104102a000b200d4104102a000b20074104102a000b412c4101102a000b412c4101102a000b411e4101102a000b410021100c030b02402014450d0020152014412c6c6a2116200341e0046a41146a2117200341e0076a2118200341f0056a41017221190340024020152d0000410b470d00201528020c2207450d002015280204220a200741186c6a211a03400240200a41146a220c2802002207450d00200a410c6a21124100210e0240024002400240024002400340200e20074f0d014101210702402012280200200e41047422136a22052d0000410b470d002003200541046a22053602c0022010450d04200f200528020022054d0d03201020054102746a2802002209450d00201920032f00e0043b0000201941026a200341e0046a41026a2d00003a0000200341123a00f0052003200d3602d407200341133a00d007200341d7003a00c007200320093602b4072003412d3a00b0072003200d3602a407200341123a00a00720032005360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200d3602b406200341123a00b0062003200d3602a406200341133a00a006200341d6003a00900620032009360284062003412d3a0080062003200d3602f405200c2802002211200e4d0d05200c200e360200200a28020c2107200320183602f804200320123602f0042003200720136a220841106a22063602e8042003200e41016a22143602e0042003201120146b221b3602e404200320072014410474221c6a221d3602ec042003200341f0056a3602f40420062107024020082d0000220941ac01460d004100210702400340200820076a21050240200941ff01714109470d00200541086a28020041ffffffff0371450d00200541046a28020010290b2007450d012003200541206a3602e804200741106a2107200541106a2d0000220941ac01470d000b200820076a41106a21070c010b200541106a21070b02402007201d460d00034020032007220541106a22073602e8040240024020052d000022094109460d00200941ac01470d010c030b200541086a28020041ffffffff0371450d00200541046a28020010290b20062007470d000b0b0240024002400240201b450d0002402014200a2802142207470d00200341f0056a2107201821080c030b2013200741047422076b2109200a28020c20076a2105200341f0056a21072018210603400240024020072006470d00410021070c010b2003200741106a3602f4040b200341d0036a2007109c0420032d00d00341ac01460d04200520032903d003370300200541086a200341d0036a41086a290300370300200a200a28021441016a3602142009450d02200541106a2105200941706a210920032802f804210620032802f40421070c000b0b20122017109d040c020b20032802f804210820032802f40421070b0240200820076b2205450d000240024020032802f004220641046a221d280200221320116b20054104762209490d00200628020021050c010b201120096a22052011490d1020134101742211200520052011491b221141ffffffff00712011470d102011410474221e4100480d100240024020130d00201e102721050c010b20062802002013410474201e102821050b2005450d0920062005360200201d20113602000b2005201420096a22134104746a2005201c6a201b41047410cf041a200320133602e004201320062802082205460d00200e20096a410474200541047422056b2109200628020020056a210503400240024020072008470d00410021070c010b2003200741106a3602f4040b200341d0036a2007109c0420032d00d00341ac01460d02200520032903d003370300200541086a200341d0036a41086a2903003703002006200628020841016a3602082009450d01200541106a2105200941706a210920032802f804210820032802f40421070c000b0b200341003602d803200342083703d003200341d0036a2017109d0420032802d003221b20032802d803220541047422086a210620032802d403211c201b210702402005450d000240024020032802f004221341046a221d280200220720032802e404221420032802e00422056a22116b20084104752209490d00201328020021070c010b201120096a221e2011490d1020074101742211201e201e2011491b221141ffffffff00712011470d102011410474221e4100480d100240024020070d00201e102721070c010b20132802002007410474201e102821070b2007450d0a20132007360200201d20113602000b2007200520096a220941047422116a200720054104746a201441047410cf041a200320093602e004201b2107200920132802082205460d002013280200220720116a211d200720054104746a2109201b21050340024020080d00200621070c020b200341d0036a41026a2207200541036a2d00003a0000200320052f00013b01d003024020052d0000221441ac01470d00200541106a21070c020b200541046a290200210b2005410c6a2802002111200920143a00002009410c6a2011360200200941046a200b37020020032f01d0032114200941036a20072d00003a0000200941016a20143b00002013201328020841016a360208200841706a2108200541106a22072105200941106a2209201d470d000b0b024020072006460d0003400240024020072d000022054109460d00200541ac01470d010c030b200741086a28020041ffffffff0371450d00200741046a28020010290b200741106a22072006470d000b0b201c450d00201b10290b024020032802e804220720032802ec042206460d00034020032007220541106a22073602e8040240024020052d000022094109460d00200941ac01470d010c030b200541086a28020041ffffffff0371450d00200541046a28020010290b20062007470d000b0b024020032802e4042207450d00024020032802e004220620032802f004220841086a22092802002205460d002008280200220820054104746a200820064104746a200741047410cf041a0b2009200720056a3602000b024020032d00f0054109470d0020032802f80541ffffffff0371450d0020032802f40510290b024020032d0080064109470d0020032802880641ffffffff0371450d0020032802840610290b024020032d0090064109470d0020032802980641ffffffff0371450d0020032802940610290b024020032d00a0064109470d0020032802a80641ffffffff0371450d0020032802a40610290b024020032d00b0064109470d0020032802b80641ffffffff0371450d0020032802b40610290b024020032d00c0064109470d0020032802c80641ffffffff0371450d0020032802c40610290b024020032d00d0064109470d0020032802d80641ffffffff0371450d0020032802d40610290b024020032d00e0064109470d0020032802e80641ffffffff0371450d0020032802e40610290b024020032d00f0064109470d0020032802f80641ffffffff0371450d0020032802f40610290b024020032d0080074109470d0020032802880741ffffffff0371450d0020032802840710290b024020032d0090074109470d0020032802980741ffffffff0371450d0020032802940710290b024020032d00a0074109470d0020032802a80741ffffffff0371450d0020032802a40710290b024020032d00b0074109470d0020032802b80741ffffffff0371450d0020032802b40710290b024020032d00c0074109470d0020032802c80741ffffffff0371450d0020032802c40710290b024020032d00d0074109470d0020032802d80741ffffffff0371450d0020032802d40710290b410f21070b2007200e6a220e200c2802002207490d000c070b0b41e0acc500200e20071037000b2003410136028406200342013702f405200341f0acc5003602f005200341243602d4032003200341d0036a360280062003200341c0026a3602d003200341e0046a200341f0056a10e60320032802e0042207450d0420032902e404210b0c0b0b419eabc50041cc00104e000b419cb1c5001058000b201e4108102a000b201e4108102a000b200a41186a220a201a470d000b0b2015412c6a22152016470d000b0b200341c8006a41106a200141106a280200221f360200200341c8006a41086a200141086a290200220b37030020032001290200370348201f412c6c2107200ba7222041586a210502400340024020070d00410021090c020b200741546a2107200541286a21092005412c6a220e210520092d00004108470d000b200341386a200e10800320032802382109200328023c21070b2007410020091b2106201f412c6c2107202041586a2105200941b8d6c50020091b210e02400340024020070d00410021090c020b200741546a2107200541286a21092005412c6a220a210520092d0000410a470d000b200341306a200a10800320032802302109200328023421070b2007410020091b2108201f412c6c2107202041586a2105200941b8d6c50020091b211e02400340024020070d00410021210c020b200741546a2107200541286a21092005412c6a220a210520092d00004109470d000b200a2802002105410121210b200342003702742003418883c000360270201e2008411c6c6a2122200e200641146c6a2106200341e0046a410272222341266a2124202341186a2125202341086a21264100211741002127410021284100210c4100211c4104211a410421110240024002400240410041ff01710e03000102000b410021070c020b410221070c010b410121070b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020070e03000104040b0240201741ff01710e03020300020b20284101470d05410021070c080b2021450d0e41022119410021214100211d200521070c1b0b0340024002400240024002402006200e22076b413c4b0d0020072006470d012007210e0c020b200728020c0d03200741146a210e200741106a28020021070c1e0b200741106a21090340200728020c450d02200941146a2109200741146a22072006470d000b2006210e0b20284101470d05410021070c0a0b200941046a210e200928020021070c1b0b200741206a280200450d19200741346a280200450d18200741d0006a210e200741c8006a280200450d170c000b0b03400240024002402006200e22076b413c4b0d004101211720072006470d012007210e0c1f0b200728020c0d01200741146a210e200741106a28020021070c170b200741106a210902400340200728020c450d01200941146a2109200741146a22072006470d000b2006210e0c1e0b200941046a210e200928020021070c160b200741206a280200450d14200741346a280200450d13200741d0006a210e200741c8006a280200450d120c000b0b0240024002400240201741ff01710e03010200010b20284101470d02410021070c090b0340024002400240024002402006200e22076b413c4b0d0020072006470d012007210e0c020b200728020c0d03200741146a210e200741106a28020021070c160b200741106a21090340200728020c450d02200941146a2109200741146a22072006470d000b2006210e0b20284101470d07410021070c080b200941046a210e200928020021070c130b200741206a280200450d11200741346a280200450d10200741d0006a210e200741c8006a280200450d0f0c000b0b03400240024002402006200e22076b413c4b0d0020072006460d10200741106a21090340200728020c450d02200941146a2109200741146a22072006470d000c110b0b200728020c0d01200741146a210e200741106a28020021070c0e0b200941046a210e200928020021070c0d0b200741206a280200450d0b200741346a280200450d0a200741d0006a210e200741c8006a280200450d090c000b0b410121070c060b410121070c040b410121070c020b410121070b0340024002400240024020070e020001010b20182027470d01410121070c030b201e2022460d0a200341206a201e10fd0320032802202218450d0a201e411c6a211e201820032802244102746a21270c010b2018450d092018280200210741012119410221172005211d201841046a2118410121280c160b410021070c000b0b0340024002400240024020070e020001010b20182027470d014101212820272118410121070c030b41022117201e2022460d17200341186a201e10fd03201e411c6a211e20032802182207450d182007200328021c4102746a2127200721180c010b201841046a2109024020180d004101212841022117200921180c180b201828020021074101212841022117410021192005211d200921180c150b410021070c000b0b0340024002400240024020070e020001010b20182027470d014101212820272118410121070c030b41022117201e2022460d16200341106a201e10fd03201e411c6a211e20032802102207450d17200720032802144102746a2127200721180c010b201841046a2109024020180d004101212841022117200921180c170b201828020021074101212841022117410021192005211d200921180c140b410021070c000b0b0340024002400240024020070e020001010b20182027470d01410121070c030b201e2022460d07200341286a201e10fd0320032802282218450d07201e411c6a211e2018200328022c4102746a21270c010b2018450d062018280200210741012119410221172005211d201841046a2118410121280c130b410021070c000b0b200741cc006a28020021070c020b2007413c6a210e200741386a28020021070c010b200741286a210e200741246a28020021070b410121192005211d410121170c0d0b200341e0006a41086a200341f0006a41086a28020036020020032003290370370360201f412c6c2107202041586a210502400340410021092007450d01200741546a2107200541286a210e2005412c6a220a2105200e2d00004103470d000b200a41086a2802002207450d00200741286c2105200a28020041186a2107410021090340200920072d0000456a2109200741286a2107200541586a22050d000b0b201f412c6c2107202041606a210502400340024020070d00410021070c020b200741546a2107200541206a210e2005412c6a220a2105200e2d00004104470d000b200a28020021070b200341f0056a41106a200341c8006a41106a280200360200200341f0056a41086a200341c8006a41086a290300370300200320032903483703f005200341b0016a200341f0056a1082030240200c450d002011200c4102746a2118200720096a211b200341e0076a2112200341e7046a211703402011220741046a21112007280200210a200341e0006a21072003280264210803402007280200220641086a210520062f0106220c4102742107417f210902400340024020070d00200c21090c020b2005280200210e2007417c6a2107200941016a2109200541046a210502404100417f4101200e200a4b1b200e200a461b41016a0e03020001020b0b200641346a20094105746a22132802182105201328021c21072003200d3602d407200341133a00d007200341d7003a00c007200320073602b4072003412d3a00b0072003200d3602a407200341123a00a00720032005360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200d3602b406200341123a00b0062003200d3602a406200341133a00a006200341d6003a00900620032007360284062003412d3a0080062003200d3602f405200341123a00f0052013280208220a41106a220e41ffffffff0071200e470d15200e4104742207417f4c0d15201341086a21190240024002400240024020070d004108210c0c010b20071027220c450d012019280200210a0b0240200a0d00410021050c030b4100210941002107034002402007200e470d00200e41016a2205200e490d19200e4101742206200520052006491b220541ffffffff00712005470d19200541047422064100480d1902400240200e0d0020061027210c0c010b200c200e41047420061028210c0b200c450d032005210e0b200c20096a2205410f3a0000200541046a2007360200200541016a20032f01d0033b0000200541036a200341d0036a41026a2d00003a0000200941106a2109200741016a22052107200a2005460d030c000b0b20074108102a000b20064108102a000b02400240024002400240024002400240200e20056b410f4f0d002005410f6a22072005490d1c200e4101742209200720072009491b220741ffffffff00712007470d1c200741047422094100480d1c02400240200e0d0020091027210c0c010b200c200e41047420091028210c0b200c450d012007210e0b200c20054104746a2107200341f0056a2109034020052108024002400240024020092d00002205414f6a41fb004f0d000c010b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e312c2c0001022c2c0304052c06072c2c08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292c0b20092d00012106410221050c2b0b20092d00012106410321050c2a0b20092d00012106410421050c290b200941046a280200210a410721050c270b200941046a280200210a410821050c260b2009280208221d41ffffffff0371201d470d44201d4102742205417f4c0d440240024020050d004104210a0c010b20051027220a450d2a0b0240201d450d0020092802042105201d4102742114200a2106034020062005280200360200200641046a2106200541046a21052014417c6a22140d000b0b200935020c422086201dad84210b410921050c250b200941046a280200210a410b21050c240b200941046a280200210a20092d00012106410c21050c240b200941046a280200210a410f21050c220b200941046a280200210a411021050c210b200941046a280200210a411121050c200b200941046a280200210a411221050c1f0b200941046a280200210a411321050c1e0b200941046a280200210a2009350208210b411421050c1d0b200941046a280200210a2009350208210b411521050c1c0b200941046a280200210a2009350208210b411621050c1b0b200941046a280200210a2009350208210b411721050c1a0b200941046a280200210a2009350208210b411821050c190b200941046a280200210a2009350208210b411921050c180b200941046a280200210a2009350208210b411a21050c170b200941046a280200210a2009350208210b411b21050c160b200941046a280200210a2009350208210b411c21050c150b200941046a280200210a2009350208210b411d21050c140b200941046a280200210a2009350208210b411e21050c130b200941046a280200210a2009350208210b411f21050c120b200941046a280200210a2009350208210b412021050c110b200941046a280200210a2009350208210b412121050c100b200941046a280200210a2009350208210b412221050c0f0b200941046a280200210a2009350208210b412321050c0e0b200941046a280200210a2009350208210b412421050c0d0b200941046a280200210a2009350208210b412521050c0c0b200941046a280200210a2009350208210b412621050c0b0b200941046a280200210a2009350208210b412721050c0a0b200941046a280200210a2009350208210b412821050c090b200941046a280200210a2009350208210b412921050c080b200941046a280200210a2009350208210b412a21050c070b20092d00012106412b21050c070b20092d00012106412c21050c060b200941046a280200210a412d21050c040b2009290308210b412e21050c020b200941046a280200210a412f21050c020b2009290308210b413021050b0b0b200720063a0001200720053a0000200741086a200b370300200741046a200a360200200841016a2105200741106a2107200941106a22092012470d000b02400240200e2005460d00200e21090c010b200e41016a2207200e490d1c200e4101742205200720072005491b220941ffffffff00712009470d1c200941047422074100480d1c02400240200e0d0020071027210c0c010b200c200e41047420071028210c0b200c450d03200e21050b200c20054104746a220741063a0000200720032900e004370001200741086a2017290000370000200341e0046a200341b0016a418c0110ce041a411010272205450d03200541063a0000200341d0036a200341e0046a418c0110ce041a20192802002207417f4c0d1c0240024020070d004101210a41014101200710ce041a2007ad210b410021070c010b2013280200210e20071027220a450d05200a200e200710ce04210e20071027220a450d06200a200e200710ce041a200e10292007ad210b0b200341e0046a200341d0036a418c0110ce041a201331000d2129200341d0036a200341e0046a418c0110ce041a200341e0046a200341d0036a418c0110ce041a200341c0026a200341e0046a418c0110ce041a41101027220e450d06200841026a2106202a428080808080804083222a200b842029422886844280808080800c84210b200e41063a0000200e1029200341d0036a200341c0026a418c0110ce041a200341e0046a200341d0036a418c0110ce041a024020052d00004109470d00200528020841ffffffff0371450d00200528020410290b20051029200341c0026a200341e0046a418c0110ce041a200341e0046a200341c0026a418c0110ce041a200341003602fc03200320063602f803200320093602f4032003200c3602f003200341003602ec03200342043702e4032003200b3702dc03200320073602d8032003200a3602d403200341013602d003200341e0046a200341d0036a108703200341b0016a200341e0046a418c0110ce041a201341013602102013201b360214024020032d00f0054109470d0020032802f80541ffffffff0371450d0020032802f40510290b024020032d0080064109470d0020032802880641ffffffff0371450d0020032802840610290b024020032d0090064109470d0020032802980641ffffffff0371450d0020032802940610290b024020032d00a0064109470d0020032802a80641ffffffff0371450d0020032802a40610290b024020032d00b0064109470d0020032802b80641ffffffff0371450d0020032802b40610290b024020032d00c0064109470d0020032802c80641ffffffff0371450d0020032802c40610290b024020032d00d0064109470d0020032802d80641ffffffff0371450d0020032802d40610290b024020032d00e0064109470d0020032802e80641ffffffff0371450d0020032802e40610290b024020032d00f0064109470d0020032802f80641ffffffff0371450d0020032802f40610290b024020032d0080074109470d0020032802880741ffffffff0371450d0020032802840710290b024020032d0090074109470d0020032802980741ffffffff0371450d0020032802940710290b024020032d00a0074109470d0020032802a80741ffffffff0371450d0020032802a40710290b024020032d00b0074109470d0020032802b80741ffffffff0371450d0020032802b40710290b024020032d00c0074109470d0020032802c80741ffffffff0371450d0020032802c40710290b024020032d00d0074109470d0020032802d80741ffffffff0371450d0020032802d40710290b202a4280808080808c0184212a201b41016a211b20112018470d090c0a0b20094108102a000b20054104102a000b20074108102a000b41104108102a000b20074101102a000b20074101102a000b41104108102a000b02402008450d002008417f6a2108200620094102746a4194036a21070c010b0b0b41b0b2c500418001104e000b0240201c450d00201a10290b200341f0056a200341b0016a418c0110ce041a200341e0046a200341f0056a1084030240200341e0046a41106a2802002207450d0020032802e80422192007412c6c6a211d0340024020192d000041786a220741024b0d0002400240024020070e03000102000b201928020c2207450d0220192802042209200741146c6a211203400240200928020c0d002009280210210c2003280264210d200341e0006a210703402007280200220841286a210e200841086a210520082f010622134102742107417f210a02400340024020070d002013210a0c020b200528020021062007417c6a2107200a41016a210a200e41206a210e200541046a210502404100417f41012006200c4b1b2006200c461b41016a0e03020001020b0b0240200e417c6a280200450d002009200e2802003602100c030b41b0b3c5004135104e000b200d450d01200d417f6a210d2008200a4102746a4194036a21070c000b0b200941146a22092012470d000c030b0b201928020421082003280264210c200341e0006a210703402007280200220641286a2109200641086a210520062f0106220d4102742107417f210e02400340024020070d00200d210e0c020b2005280200210a2007417c6a2107200e41016a210e200941206a2109200541046a210502404100417f4101200a20084b1b200a2008461b41016a0e03020001020b0b02402009417c6a280200450d00201920092802003602040c040b41b0b3c5004135104e000b200c450d02200c417f6a210c2006200e4102746a4194036a21070c000b0b201928020c2207450d00201928020422112007411c6c6a211b0340024020112802182207450d002011280210220d20074102746a21140340200d221241046a210d201228020021082003280264210c200341e0006a210703402007280200220641286a2109200641086a210520062f010622134102742107417f210e024002400340024020070d002013210e0c020b2005280200210a2007417c6a2107200e41016a210e200941206a2109200541046a210502404100417f4101200a20084b1b200a2008461b41016a0e03020001020b0b02402009417c6a280200450d00201220092802003602000c020b41b0b3c5004135104e000b200c450d00200c417f6a210c2006200e4102746a4194036a21070c010b0b200d2014470d000b0b2011411c6a2211201b470d000b0b2019412c6a2219201d470d000b0b200341ec046a290200210b20032802e004210720032902e404212a200328026020032802642003280268109f04200041106a200b370200200041086a202a37020020002007360204200041003602002010450d13200f450d1320101029200424000f0b200741cc006a28020021070c020b2007413c6a210e200741386a28020021070c010b200741286a210e200741246a28020021070b41002117410121192005211d0c080b200741cc006a28020021070c020b2007413c6a210e200741386a28020021070c010b200741286a210e200741246a28020021070b41012117410021192005211d0c040b200741cc006a28020021070c020b2007413c6a210e200741386a28020021070c010b200741286a210e200741246a28020021070b410021192005211d410021170b2003200736027c0240024002400240024002400240024002402010450d000240200f20074b0d002003410136028406200342023702f405200341a0b2c5003602f005200341013602d4032003200341d0036a360280062003200341fc006a3602d003200341e0046a200341f0056a10e60320032902e404220b422088a7210920032802e0042113200ba721160c090b201020074102746a2802002205450d0402400240201c200c470d00200c41016a2209200c490d0e200c410174220a20092009200a491b221c41ffffffff0371201c470d0e201c41027422094100480d0e02400240200c0d0020091027211a0c010b201a200c41027420091028211a0b201a450d01201a21110b2011200c4102746a2007360200200341f0056a200328027c2208200341c8006a109b0420032802f805211620032802f4052113024020032802f00522014101470d0020032802fc0521090c0a0b20132802082207417f4c0d0e20132d000c210a02400240024020070d00410121090c010b20132802002112200710272209450d0120092012200710ce041a0b2003200a3a008c0120032007360288012003200736028401200320093602800120132d000d21072003200536029c012003200328027c360298012003410036029001200320073a008d0102400240024020032802702207418883c000460d002003280274211b0c010b20244200370100202341206a420037010020254200370100202341106a42003701002026420037010020234200370100200341f0056a410041e00210cd041a41940310272207450d014100211b20074100360200200720032903e0043702042007410c6a200341e0046a41086a290300370200200741146a200341e0046a41106a2903003702002007411c6a200341e0046a41186a290300370200200741246a200341e0046a41206a2903003702002007412c6a200341e0046a41286a290300370200200741346a200341f0056a41e00210ce041a20034100360274200320073602700b200c41016a210c0340200741146a210920072f010622154102742114417f210a4100210502400340024020142005470d002015210a0c020b200720056a2112200541046a2105200a41016a210a200941206a210902404100417f4101201241086a280200221220084b1b20122008461b41016a0e03020001020b0b2009290200210b2009200329038001370200200941186a200329039801370200200941106a2207290200212a2007200329039001370200200941086a200329038801370200202a42ffffffff0f83420285500d08200b42808080807083500d08200ba710290c080b0240201b450d00201b417f6a211b2007200a4102746a4194036a28020021070c010b0b2003200328027841016a360278200329039801210b200329039001212a2003290388012129200329038001212b20072f01062209410b490d0420244200370100202341206a222c420037010020254200370100202341106a222d42003701002026420037010020234200370100200341f0056a410041e00210cd041a024041940310272205450d0020054100360200200520032903e0043702042005410c6a200341e0046a41086a222e290300370200200541146a200341e0046a41106a222f2903003702002005411c6a200341e0046a41186a2230290300370200200541246a200341e0046a41206a22312903003702002005412c6a200341e0046a41286a2232290300370200200541346a200341f0056a41e00210ce042112200341f0056a41086a221b200741fc016a290200370300200341f0056a41106a221520074184026a290200370300200341f0056a41186a22332007418c026a290200370300200320072902f4013703f00520072802202134200541086a200741246a20072f010641796a220941027410ce042114201220074194026a200941057410ce042112200741063b0106200520093b010620302033290300370300202f2015290300370300202e201b290300370300200320032903f0053703e00402400240200a4107490d002014200a417a6a22354102746a2014200a41796a220a4102746a2214200941ffff0371200a6b41027410cf041a20142008360200201220354105746a2012200a4105746a2209200541066a22122f0100200a6b41057410cf041a200941186a200b3702002009202a370210200920293702082009202b37020020122f010021140c010b200741086a2209200a41016a22354102746a2009200a4102746a2209200741066a22122f01002214200a6b223641027410cf041a20092008360200200741346a220920354105746a2009200a4105746a2209203641057410cf041a200941186a200b3702002009202a370210200920293702082009202b3702000b2012201441016a3b0100200341d0036a41186a22372030290300220b370300200341d0036a41106a2238202f290300222a370300200341d0036a41086a2239202e2903002229370300200341b0016a41186a223a200b370300200341b0016a41106a223b202a370300200341b0016a41086a223c2029370300200320032903e004220b3703d0032003200b3703b0010240200728020022120d00200521090c070b20072f010421352005213d0340200341c0026a41186a223e203a290300370300200341c0026a41106a223f203b290300370300200341c0026a41086a2240203c290300370300200320032903b0013703c002203541ffff037121080240024002400240024020122f01062207410b490d0020244200370100202c420037010020254200370100202d420037010020264200370100202342003701002039202e2903003703002038202f29030037030020372030290300370300200341d0036a41206a22072031290300370300200341d0036a41286a22052032290300370300200320032903e0043703d003200341f0056a410041900310cd041a41c40310272209450d0320094100360200200920032903d0033702042009410c6a2039290300370200200941146a20382903003702002009411c6a2037290300370200200941246a20072903003702002009412c6a2005290300370200200941346a200341f0056a41900310ce042105201241206a280200214120332012418c026a290200370300201520124184026a290200370300201b201241fc016a2902003703002003201241f4016a2902003703f005200941086a201241246a20122f0106220a41796a220741027410ce042142200520124194026a200741057410ce04214320094194036a201241b0036a200a417a6a221441027410ce042136201241063b0106200920073b010602402014450d00410021072036210503402005280200220a20073b0104200a2009360200200541046a21052014200741016a2207470d000b0b20302033290300220b370300202f2015290300222a370300202e201b2903002229370300200320032903f005222b3703e0042033200b3703002015202a370300201b20293703002003202b3703f005203541ffff037122054107490d0120422008417a6a220a41027422146a2042200841796a22074102746a220520092f010620076b41027410cf041a200520343602002043200a4105746a204320074105746a220520092f010620076b41057410cf041a200541186a203e290300370200200541106a203f290300370200200541086a2040290300370200200520032903c002370200200920092f010641016a22053b01062008410274223520366a416c6a203620146a2214200541ffff03712208200a6b41027410cf041a2014203d3602002008200a490d02200920356a41fc026a210503402005280200220a200741016a22073b0104200a2009360200200541046a210520072008490d000c030b0b201241086a2205200841016a2209410274220a6a2005200841027422146a2205200720086b221b41027410cf041a20052034360200201241346a220520094105746a200520084105746a2205201b41057410cf041a200541186a203e290300370200200541106a203f290300370200200541086a2040290300370200200520032903c0023702002012200741016a22073b0106201420124194036a22056a41086a2005200a6a2205200741ffff0371220a20096b41027410cf041a2005203d3602002008200a4f0d0c20122009417f6a22074102746a4198036a2105034020052802002209200741016a22073b010420092012360200200541046a21052007200a490d000c0d0b0b201241086a2207200841016a2214410274220a6a2007200841027422356a220720122f0106223620086b224241027410cf041a20072034360200201241346a220720144105746a200720084105746a2207204241057410cf041a200741186a203e290300370200200741106a203f290300370200200741086a2040290300370200200720032903c0023702002012203641016a22073b0106203520124194036a22366a41086a2036200a6a2236200741ffff0371220a20146b41027410cf041a2036203d3602002005200a4f0d00201220356a4198036a2107034020072802002205200841016a22083b010420052012360200200741046a2107200a2008470d000b0b203a2033290300370300203b2015290300370300203c201b290300370300200320032903f0053703b001201228020022070d01204121340c090b41c4034104102a000b20122f0104213520072112204121342009213d0c000b0b4194034104102a000b4194034104102a000b20074101102a000b20094104102a000b419eabc50041cc00104e000b200741086a2205200a41016a22124102746a2005200a4102746a22052009200a6b221441027410cf041a20052008360200200741346a220520124105746a2005200a4105746a2205201441057410cf041a200541186a200b3702002005202a370210200520293702082005202b3702002007200941016a3b01060c010b20244200370100202c420037010020254200370100202d420037010020264200370100202342003701002039202e2903003703002038202f29030037030020372030290300370300200341d0036a41206a22052031290300370300200341d0036a41286a220a2032290300370300200320032903e0043703d003200341f0056a410041900310cd041a41c40310272207450d0220074100360200200720032903d0033702042007410c6a2039290300370200200741146a20382903003702002007411c6a2037290300370200200741246a20052903003702002007412c6a200a290300370200200741346a200341f0056a41900310ce04210820072003280270220536029403200320073602702003200328027441016a36027420052007360200200541003b0104200820072f0106220a4105746a220520032903b001370200200541186a203a290300370200200541106a203b290300370200200541086a203c2903003702002007200a4102746a41086a203436020020074194036a200a41016a22054102746a2009360200200720053b0106200920053b0104200920073602000b2001450d002016450d00201310290b201d2105201941ff01710e03010205010b41c4034104102a000b410021070c040b410221070c030b200328027020032802742003280278109f040240201c450d00201a10290b0240201f450d00201f412c6c210520202107034020071088032007412c6a2107200541546a22050d000b0b0240200341d4006a280200450d00202010290b2000201336020420004101360200200041086a2009ad4220862016ad843702002010450d06200f450d0620101029200424000f0b2022211e0b410121070c000b0b102b000b1039000b2000200736020420004101360200200041086a200b37020002402010450d00200f450d00201010290b20012802082105024020012802102203450d002003412c6c210720052103034020031088032003412c6a2103200741546a22070d000b0b2001410c6a280200450d00200510290b200424000ba6810204117f017e037f017e230041e0006b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0f0100021211100f0e0d0c0b0a080706010b200141186a2802002104200141146a2802002105200141106a28020021062001410c6a2802002107200141086a2802002108200141046a28020021090240200241046a280200200241086a280200220a460d002002280200210b0c180b200a41016a220c200a490d14200a410174220d200c200c200d491b220c4100480d1402400240200a0d00200c1027210b0c010b2002280200200a200c1028210b0b200b450d042002200b360200200241046a200c360200200241086a280200210a0c170b2001410c6a280200210c200141086a2802002104200141046a280200210b20012d0001210502400240200241046a280200200241086a280200220a460d002002280200210d0c010b200a41016a220d200a490d14200a4101742206200d200d2006491b22064100480d1402400240200a0d0020061027210d0c010b2002280200200a20061028210d0b200d450d032002200d360200200241046a2006360200200241086a280200210a0b200241086a2206200a41016a360200200d200a6a20053a000002400240200241046a280200220d2006280200220a6b200c490d002002280200210d0c010b200a200c6a2205200a490d14200d410174220a20052005200a491b220a4100480d1402400240200d0d00200a1027210d0c010b2002280200200d200a1028210d0b200d450d022002200d360200200241046a200a360200200241086a280200210a0b200241086a200a200c6a360200200d200a6a200b200c10ce041a4100210c41012107024020040d004101210d0c220b200b10294101210d0c210b2001410c6a2802002106200141086a280200210e200141046a280200210f024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d14200a410174220d200c200c200d491b220d4100480d1402400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41013a0000200f20064104746a21104100210d4100210c41002105410121042006210a024003400240200c2005470d00200d200c41016a220b200b200d491b22054100480d1602400240200d0d002005102721040c010b2004200c2005102821040b2004450d020b2004200c6a200a41807f72200a41ff0071200a410776220b1b3a0000200d41026a210d200c41016a210c200b210a200b0d000b024020060d00200f21080c130b200f210a02400340200a41106a2108200a2d000d22114105460d14200a2d000c210d200a2802082109200a2802042112200a28020021130240024002400240024002402005200c470d00200c41016a220a200c490d1c200c410174220b200a200a200b491b22054100480d1c02400240200c0d002005102721040c010b2004200c2005102821040b2004450d010b2004200c6a200d3a0000200c41016a210a200c410174220c41046a2107200c41026a210d2009210c0340200721060240200a2005470d00200a41016a220b200a490d1d200d200b200b200d491b22054100480d1d02400240200a0d002005102721040c010b2004200a2005102821040b2004450d030b2004200a6a200c41807f72200c41ff0071200c410776220b1b3a0000200641026a2107200d41026a210d200a41016a210a200b210c200b0d000b0240024020090d00200a210c0c010b4100210d0340200a200d6a210c41fc00210b02400240024002402013200d6a2d00000e050200010305020b41fe00210b0c020b41fd00210b0c010b41ff00210b0b0240200c2005470d00200c41016a2205200c490d1e2006200520052006491b22054100480d1e02400240200c0d002005102721040c010b2004200c2005102821040b2004450d050b2004200a6a200d6a200b3a0000200641026a21062009200d41016a220d470d000b200a200d6a210c0b20120d030c040b20054101102a000b20054101102a000b20054101102a000b201310290b4100210a024020114104460d0002402005200c470d00200c41016a220a200c490d18200c410174220d200a200a200d491b22054100480d1802400240200c0d002005102721040c010b2004200c2005102821040b2004450d030b2004200c6a41013a0000200c41016a210c201141077141ff0073210a0b024002402005200c470d00200c41016a220d200c490d18200c410174220b200d200d200b491b22054100480d1802400240200c0d002005102721040c010b2004200c2005102821040b2004450d010b2004200c6a200a3a0000200c41016a210c2008210a20082010470d010c160b0b20054101102a000b20054101102a000b20054101102a000b200d4101102a000b200a4101102a000b20064101102a000b200c4101102a000b200141286a2802002104200141246a2802002111200141206a28020021092001411c6a2802002106200141186a2802002113200141146a28020021082001410c6a2902002114200141086a280200210d200141046a280200210b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d22200a4101742205200c200c2005491b22054100480d2202400240200a0d0020051027210c0c010b2002280200200a20051028210c0b200c450d012002200c360200200241046a2005360200200241086a280200210a0b200241086a200a41016a36020041002105200c200a6a41003a0000200341dc006a41003602002003420137025420032002360250200320143e02482003200d3602442003200b360240200341086a200341c0006a200341d0006a10ed03024020032d0008220a411a460d0020032f000920032d000b41107472210c200341086a41086a2903002114200328020c21044100210d0c1e0b2014422088a7210c0340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d23200a410174220b200d200d200b491b220b4100480d2302400240200a0d00200b1027210d0c010b2003280254200a200b1028210d0b200d450d032003200b3602582003200d3602540b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b4101211202402008450d00200320063602482003201336024420032008360240200341086a200341c0006a200341d0006a10ed03024020032d0008220a411a460d0020032f000920032d000b41107472210c200341106a2903002114200328020c21044100210d410121050c1f0b410021120b200920044104746a21062004210c0340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d23200a410174220b200d200d200b491b220b4100480d2302400240200a0d00200b1027210d0c010b2003280254200a200b1028210d0b200d450d042003200b3602582003200d3602540b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b024020040d002009210b0c1d0b200441047441706a21072009210d0340200d41106a210b200d410c6a2802002102200d41086a280200210a200d280204210c0240024002400240024002400240024002400240200d2802000e09000102030405060727000b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d2c200d4101742205200420042005491b22054100480d2c02400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d0e20032005360258200320043602540b2003200d41016a36025c2004200d6a41003a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d2d200d4101742205200420042005491b22054100480d2d02400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1020032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2d200c4101742204200d200d2004491b22044100480d2d02400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d11200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000c080b0b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d2b200d4101742205200420042005491b22054100480d2b02400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1020032005360258200320043602540b2003200d41016a36025c2004200d6a41013a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d2c200d4101742205200420042005491b22054100480d2c02400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1220032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2c200c4101742204200d200d2004491b22044100480d2c02400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d13200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000c070b0b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d2a200d4101742205200420042005491b22054100480d2a02400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1220032005360258200320043602540b2003200d41016a36025c2004200d6a41023a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d2b200d4101742205200420042005491b22054100480d2b02400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1420032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2b200c4101742204200d200d2004491b22044100480d2b02400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d15200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000c060b0b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d29200d4101742205200420042005491b22054100480d2902400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1420032005360258200320043602540b2003200d41016a36025c2004200d6a41033a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d2a200d4101742205200420042005491b22054100480d2a02400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1620032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2a200c4101742204200d200d2004491b22044100480d2a02400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d17200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000b200341086a2002200341d0006a10e10320032d0008220a411a460d0520032f000920032d000b41107472210c0c220b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d28200d4101742205200420042005491b22054100480d2802400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1620032005360258200320043602540b2003200d41016a36025c2004200d6a41043a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d29200d4101742205200420042005491b22054100480d2902400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1820032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d29200c4101742204200d200d2004491b22044100480d2902400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d19200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000b200341086a2002200341d0006a10e10320032d0008220a411a460d0420032f000920032d000b41107472210c0c210b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d27200d4101742205200420042005491b22054100480d2702400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1820032005360258200320043602540b2003200d41016a36025c2004200d6a41053a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d28200d4101742205200420042005491b22054100480d2802400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1a20032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d28200c4101742204200d200d2004491b22044100480d2802400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d1b200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000b200341086a2002200341d0006a10e10320032d0008220a411a460d0320032f000920032d000b41107472210c0c200b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d26200d4101742205200420042005491b22054100480d2602400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1a20032005360258200320043602540b2003200d41016a36025c2004200d6a41063a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d27200d4101742205200420042005491b22054100480d2702400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1c20032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d27200c4101742204200d200d2004491b22044100480d2702400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d1d200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000c020b0b024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d25200d4101742205200420042005491b22054100480d2502400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1c20032005360258200320043602540b2003200d41016a36025c2004200d6a41073a00000340024002402003280258200328025c220d460d00200328025421040c010b200d41016a2204200d490d26200d4101742205200420042005491b22054100480d2602400240200d0d002005102721040c010b2003280254200d2005102821040b2004450d1e20032005360258200320043602540b2003200d41016a36025c2004200d6a200c41807f72200c41ff0071200c410776220d1b3a0000200d210c200d0d000b0340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d26200c4101742204200d200d2004491b22044100480d2602400240200c0d0020041027210d0c010b2003280254200c20041028210d0b200d450d1f200320043602582003200d3602540b2003200c41016a36025c200d200c6a200a41807f72200a41ff0071200a410776220c1b3a0000200c210a200c0d000b0b2003411a3a00080b200741706a2107200b210d200b2006470d000b2006210b0c1c0b20054101102a000b200b4101102a000b200b4101102a000b20054101102a000b20054101102a000b20044101102a000b20054101102a000b20054101102a000b20044101102a000b20054101102a000b20054101102a000b20044101102a000b20054101102a000b20054101102a000b20044101102a000b20054101102a000b20054101102a000b20044101102a000b20054101102a000b20054101102a000b20044101102a000b20054101102a000b20054101102a000b20044101102a000b20054101102a000b20054101102a000b20044101102a000b20032903102114200328020c2104024003402007450d01200741706a2107200b280200210d200b41106a210b200d4108470d000b0b02402011450d00200910290b20124521054101210d0c010b024003402006200b460d01200b280200210a200b41106a210b200a4108470d000b0b02402011450d00200910290b20032802582109200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d08200a4101742206200d200d2006491b22064100480d0802400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d07200c410174220a200d200d200a491b220a4100480d0702400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402009450d00200210290b41002110410121072008450d032012450d032013450d03200810290c030b20064101102a000b200a4101102a000b02402003280258450d00200328025410290b02402008452005720d002013450d00200810290b0240200d201145720d00200910290b200a411a470d1141002110410121070b4101210c4101210d4101210b4101210841012109410121044101210541012113410121064101210241012111410121120c350b200141146a280200210f200141106a28020021112001410c6a2802002113200141086a2802002110200141056a2d0000210d200141046a2d00002109024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d0c200a410174220b200c200c200b491b220b4100480d0c02400240200a0d00200b1027210c0c010b2002280200200a200b1028210c0b200c450d012002200c360200200241046a200b360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41003a00000240410410272212450d00201241eec2b5ab06360000024020090e0400050403000b410121064100210a4100210c2011210d034002400240200a200c460d00200a21070c010b200a41016a220c200a490d0e200a410174220b200c200c200b491b22074100480d0e02400240200a0d002007102721060c010b2006200a2007102821060b02402006450d00200a210c2007210a0c010b20074101102a000b2006200c6a200d41807f72200d41ff0071200d410776220b1b3a0000200c41016a210c200b210d200b0d000b0240024002402007200c6b20114f0d00200c20116a220a200c490d0f2007410174220d200a200a200d491b220a4100480d0f0240024020070d00200a102721060c010b20062007200a102821060b2006450d01200a21070b2006200c6a2010201110ce041a200c20116a21084101210e20130d010c080b200a4101102a000b201010290c060b41044101102a000b200b4101102a000b410021154101210e20102106201321072011210841012116410121170c040b2003410036024820034201370340410121044100210d4100210a2010210c02400240024002400240024003400240200a200d470d00200d41016a220b200d490d10200d4101742205200b200b2005491b220b4100480d1002400240200d0d00200b102721040c010b2004200d200b102821040b2004450d022003200b36024420032004360240200b210d0b2003200a41016a22053602482004200a6a200c41807f72200c41ff0071200c410776220b1b3a00002005210a200b210c200b0d000b2013200f4104746a21060240200f0d002013210b0c040b2013210b2010450d03200641706a21162010210e4100210a2013210803402008210b02400340200b41046a28020022070d01200a41016a210a2006200b41106a220b470d000c070b0b200b41106a2108200a41016a2115200e417f6a210e200b41086a2902002114200b28020021172003280244210d2003280248210c02400240034002400240200c200d460d00200328024021040c010b200d41016a2204200d490d13200d4101742205200420042005491b22054100480d1302400240200d0d002005102721040c010b2003280240200d2005102821040b2004450d0220032005360244200320043602402005210d0b2003200c41016a22053602482004200c6a200a41807f72200a41ff0071200a41077622041b3a00002005210c2004210a20040d000b200320143703102003200736020c20032017360208200341d0006a200341086a200341c0006a10ea0320032d00502204411a460d010c040b20054101102a000b2016200b460d032015210a200e0d000c030b0b200b4101102a000b20032d0053210e20032f0051211720032802542105200329035821140240200641706a200b460d00200b41106a210b0340200b220a41106a210b0240200a2802042207450d00200a28020821080240200a410c6a280200220a450d00200a410c6c210c2007210a03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b2008450d00200710290b200b2006470d000b0b02402011450d00201310290b2004411a460d03200e411074210a02402003280244450d00200328024010290b2017200a72210a02400240200941024b0d000240024020090e03000109000b2013450d080c020b0240200f450d00200f410c6c210d2013210c03400240200c280200220b450d00200c41046a280200450d00200b10290b200c410c6a210c200d41746a220d0d000b0b02402011450d00201310290b2004411a470d074100210541012104410021080c0a0b2013450d060b201010290c050b200b41106a210b0b200b2006460d000340200b220a41106a210b0240200a2802042204450d00200a28020821050240200a410c6a280200220a450d00200a410c6c210c2004210a03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b2005450d00200410290b200b2006470d000b0b2011450d00201310290b2003280248210820032802442107200328024021064102210d410021164101210e41002117410021150c030b4100210e2003410036024820034201370340200341146a200f360200200341086a41086a20113602002003201336020c20032010360208200341d0006a200341086a200341c0006a10ea03024020032d00502204411a460d0020032d0053411074210a20032f0051210c200341d0006a41086a29030021142003280254210502402003280244450d00200328024010290b200c200a72210a0c010b2003280248210820032802442107200328024021064101211641002117410021154101210d0c020b200041086a2014370200200041046a20053602002000200a410874200472360200201210290c030b4100211741012116410121154100210d0b024002400240410110272204450d002004200d3a00004102210d4101210a410121052008210c03400240200a2005470d00200d200a41016a220b200b200d491b22054100480d092004200a200510282204450d030b2004200a6a200c41807f72200c41ff0071200c410776220b1b3a0000200d41026a210d200a41016a210a200b210c200b0d000b02402005200a6b20084f0d00200a20086a220c200a490d082005410174220d200c200c200d491b220c4100480d080240024020050d00200c102721040c010b20042005200c102821040b2004450d03200c21050b2004200a6a2006200810ce041a02402007450d00200610290b2008200a6a21080240200941024b0d00024002400240024020090e03000102000b2015201345720d07201010290c070b200e450d060240200f450d00200f410c6c210c2013210a03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b20110d010c060b2016450d050240200f450d002013200f4104746a21072013210603402006220b41106a21060240200b280204220a450d000240200b410c6a280200220c450d00200c410c6c210c03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b200b41086a280200450d00200b28020410290b20062007470d000b0b2011450d050b201310290c040b2017201345720d03201010290c030b41014101102a000b20054101102a000b200c4101102a000b2003411c6a2008360200200341186a20053602002003200436021420034284808080c00037020c20032012360208200341d0006a200341086a200210f103200320032900513703402003200341d0006a41086a29000037004720032d0050220a411a460d012000200a3a000020002003290340370001200041086a20032900473700000b410021094101210d4101210c4101210b410121044101210541012106410121074101210241012108410121130c1a0b41002112410121074101210c4101210d4101210b41012108410121094101210441012105410121134101210641012102410121110c330b2001410c6a2802002105200141086a2802002113200141046a28020021090240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d15200a410174220d200c200c200d491b220d4100480d1502400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a410b3a0000200341dc006a4100360200200342013702542003200236025020092005411c6c6a21074100210a4100210c2005210d034002400240200a200c460d002003280254210a0c010b200a41016a220b200a490d16200a4101742204200b200b2004491b220b4100480d1602400240200a0d00200b1027210a0c010b2003280254200a200b1028210a0b200a450d032003200b3602582003200a3602540b2003200c41016a36025c200a200c6a200d41807f72200d41ff0071200d410776220d1b3a00000240200d450d002003280258210a200328025c210c200d210d0c010b0b200921042005450d062009210a0340200a411c6a2104200a2802042202450d07200a41186a2802002105200a41146a2802002108200a41086a2902002114200a280200210c200a28021021060340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d17200a410174220b200d200d200b491b220b4100480d1702400240200a0d00200b1027210d0c010b2003280254200a200b1028210d0b200d450d052003200b3602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b2003201437024420032002360240200341086a200341c0006a200341d0006a10de03024020032d0008220d411a470d002005210c0340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d18200a410174220b200d200d200b491b220b4100480d1802400240200a0d00200b1027210d0c010b2003280254200a200b1028210d0b200d450d072003200b3602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b024002402003280258220c200328025c220a6b2005490d002003280254210c0c010b200a20056a220d200a490d0b200c410174220a200d200d200a491b220a4100480d0b02400240200c0d00200a1027210c0c010b2003280254200c200a1028210c0b200c450d072003200a3602582003200c360254200328025c210a0b2003200a20056a36025c200c200a6a2006200510ce041a02402008450d00200610290b2004210a20042007470d010c090b0b20032d000b211220032f0009211020032903102114200328020c21112008450d05200610290c050b200d4101102a000b200b4101102a000b200b4101102a000b200b4101102a000b200a4101102a000b024020042007460d0003402004280204220b450d01200441146a2802002105200441086a28020021062004280210210202402004410c6a280200220a450d00200a410474210c200b210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b02402006450d00200b10290b2004411c6a210402402005450d00200210290b20042007470d000b0b2012411074210a02402013450d00200910290b2010200a72210a02402003280258450d00200328025410290b2000200a3b00012000200d3a0000200041036a200a4110763a0000200041086a2014370000200041046a2011360000410021084101210d4101210c4101210b41012104410121054101210641012107410121020c190b20042007460d0003402004280204220d450d01200441146a280200210b200441086a28020021052004280210210602402004410c6a280200220a450d00200a410474210c200d210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b02402005450d00200d10290b2004411c6a21040240200b450d00200610290b20042007470d000b0b02402013450d00200910290b20032802582108200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d04200a4101742206200d200d2006491b22064100480d0402400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d03200c410174220a200d200d200a491b220a4100480d0302400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b41002111410121074101210c4101210d4101210b41012108410121094101210441012105410121134101210641012102410121120c340b20064101102a000b200a4101102a000b102b000b2001410c6a2802002105200141086a2802002117200141046a280200210e024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d0f200a410174220d200c200c200d491b220d4100480d0f02400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a410a3a00002003412c6a41003602002003420137022420032002360220200e200541186c6a210f4100210a4100210c2005210d0240034002400240200a200c460d002003280224210a0c010b200a41016a220b200a490d11200a4101742204200b200b2004491b220b4100480d1102400240200a0d00200b1027210a0c010b2003280224200a200b1028210a0b200a450d022003200b3602282003200a3602240b2003200c41016a36022c200a200c6a200d41807f72200d41ff0071200d410776220d1b3a00000240200d450d002003280228210a200328022c210c200d210d0c010b0b200e21092005450d03200341086a4101722102200341086a41026a2107200e210a02400340200a41186a2109200a2802002208450d05200a41146a2802002111200a41106a2802002112200a28020c2113200a29020421144100210c2003410036024c2003420137024420082014422088a7220d4103746a21062003200341206a3602402014a721104100210a024002400240024002400240034002400240200c200a460d002003280244210c0c010b200c41016a220a200c490d19200c410174220b200a200a200b491b220a4100480d1902400240200c0d00200a1027210c0c010b2003280244200c200a1028210c0b200c450d022003200a3602482003200c360244200328024c210a0b2003200a41016a36024c200c200a6a200d41807f72200d41ff0071200d410776220d1b3a00000240200d450d002003280248210c200328024c210a200d210d0c010b0b0240024020062008470d00200821040c010b2008210a0340200a41086a2104200a2902002214422088a7220a41ff01714104460d01200a41187441187521052014a7210c0340024002402003280248200328024c220a460d002003280244210d0c010b200a41016a220d200a490d1b200a410174220b200d200d200b491b220b4100480d1b02400240200a0d00200b1027210d0c010b2003280244200a200b1028210d0b200d450d052003200b3602482003200d360244200328024c210a0b2003200a41016a36024c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b024002402003280248200328024c220a460d002003280244210c0c010b200a41016a220c200a490d1a200a410174220d200c200c200d491b220d4100480d1a02400240200a0d00200d1027210c0c010b2003280244200a200d1028210c0b200c450d052003200d3602482003200c360244200328024c210a0b2003200a41016a36024c200c200a6a2005417f73220a413f7141c00072200a2005417f4a1b3a00002004210a20042006470d000b200621040b0240034020062004460d0120042d0004210a200441086a2104200a4104470d000b0b02402010450d00200810290b20132011410474220a6a210b024020110d002013210a0c050b201341186a210c200a41706a21042013210a0340200a2d0000210d2007200a41036a2d00003a00002003200a41016a2f00003b01080240200d41ac01470d00200a41106a210a0c060b200341306a41026a20072d000022053a0000200320032f010822063b0130200a41046a2902002114200a410c6a2802002108200220063b0000200241026a20053a00002003200d3a0008200320083602142003201437020c200341d0006a200341086a200341c0006a10e80320032d00502205411a46220d450d04200c41106a210c200441706a2104200a41106a220a200b470d000c060b0b200a4101102a000b200b4101102a000b200d4101102a000b20032d0053210820032f00512111200328025421062003290358211402402004450d00034002400240200c41786a220a2d000022044109460d00200441ac01470d010c030b200c28020041ffffffff0371450d00200a41046a28020010290b200c41106a210c200a41106a200b470d000b0b02402012450d00201310290b02402003280248450d00200328024410290b200d450d062009210a2009200f470d020c080b200a200b460d00034002400240200a2d0000220c4109460d00200c41ac01470d010c030b200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a220a200b470d000b0b02402012450d00201310290b20032802482111200328024421132003280240210d200328024c2208210c0240034002400240200d41086a2205280200200d410c6a2204280200220a460d00200d280204210b0c010b200a41016a220b200a490d14200a4101742206200b200b2006491b22064100480d1402400240200a0d0020061027210b0c010b200d280204200a20061028210b0b200b450d02200d200b360204200520063602002004280200210a0b2004200a41016a360200200b200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b024002402005280200220c2004280200220a6b2008490d00200d280204210c0c010b200a20086a220b200a490d13200c410174220a200b200b200a491b220a4100480d1302400240200c0d00200a1027210c0c010b200d280204200c200a1028210c0b200c450d03200d200c3602042005200a3602002004280200210a0b2004200a20086a360200200c200a6a2013200810ce041a02402011450d00201310290b2009210a2009200f470d010c070b0b20064101102a000b200a4101102a000b200b4101102a000b200d4101102a000b02402009200f460d0003402009280200220c450d01200941146a280200210a200941106a280200210b200928020c210d02402009280204450d00200c10290b0240200a450d00200a410474210c200d210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200941186a21090240200b450d00200d10290b2009200f470d000b0b2008411074210a02402017450d00200e10290b2011200a72210a02402003280228450d00200328022410290b2000200a3b0001200020053a0000200041036a200a4110763a0000200041086a2014370000200041046a2006360000410021024101210d4101210c4101210b410121044101210541012106410121070c160b2009200f460d0003402009280200220c450d01200941146a280200210a200941106a280200210b200928020c210d02402009280204450d00200c10290b0240200a450d00200a410474210c200d210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200941186a21090240200b450d00200d10290b2009200f470d000b0b02402017450d00200e10290b20032802282108200328022421022003280220220441086a210b200441046a2105200328022c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d0e200a4101742206200d200d2006491b22064100480d0e02400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d0d200c410174220a200d200d200a491b220a4100480d0d02400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b41002102410121074101210c4101210d4101210b4101210841012109410121044101210541012113410121060c220b20064101102a000b200a4101102a000b2001410c6a2802002105200141086a2802002113200141046a28020021090240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d12200a410174220d200c200c200d491b220d4100480d1202400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41093a0000200341dc006a4100360200200342013702542003200236025020092005411c6c6a21024100210a4100210c2005210d034002400240200a200c460d002003280254210a0c010b200a41016a220b200a490d13200a4101742204200b200b2004491b220b4100480d1302400240200a0d00200b1027210a0c010b2003280254200a200b1028210a0b200a450d032003200b3602582003200a3602540b2003200c41016a36025c200a200c6a200d41807f72200d41ff0071200d410776220d1b3a00000240200d450d002003280258210a200328025c210c200d210d0c010b0b200921062005450d062009210a0340200a411c6a2106200a2802042205450d07200a41186a2802002104200a41146a2802002108200a41086a2902002114200a2802102107200a280200210c0340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d14200a410174220b200d200d200b491b220b4100480d1402400240200a0d00200b1027210d0c010b2003280254200a200b1028210d0b200d450d052003200b3602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b2003201437024420032005360240200341086a200341c0006a200341d0006a10de03024020032d0008220d411a470d00200720044102746a21052004210c0340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d15200a410174220b200d200d200b491b220b4100480d1502400240200a0d00200b1027210d0c010b2003280254200a200b1028210d0b200d450d072003200b3602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02402004450d002007210403402004280200210c0340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d17200a410174220b200d200d200b491b220b4100480d1702400240200a0d00200b1027210d0c010b2003280254200a200b1028210d0b200d450d0a2003200b3602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b200441046a22042005470d000b0b02402008450d00200710290b2006210a20062002470d010c090b0b20032d000b211220032f0009211020032903102114200328020c21112008450d05200710290c050b200d4101102a000b200b4101102a000b200b4101102a000b200b4101102a000b200b4101102a000b024020062002460d0003402006280204220b450d01200641146a2802002104200641086a28020021052006280210210702402006410c6a280200220a450d00200a410474210c200b210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b02402005450d00200b10290b2006411c6a210602402004450d00200710290b20062002470d000b0b2012411074210a02402013450d00200910290b2010200a72210a02402003280258450d00200328025410290b2000200a3b00012000200d3a0000200041036a200a4110763a0000200041086a2014370000200041046a2011360000410021074101210d4101210c4101210b4101210441012105410121060c140b20062002460d0003402006280204220d450d01200641146a280200210b200641086a28020021042006280210210502402006410c6a280200220a450d00200a410474210c200d210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b02402004450d00200d10290b2006411c6a21060240200b450d00200510290b20062002470d000b0b02402013450d00200910290b20032802582108200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d0d200a4101742206200d200d2006491b22064100480d0d02400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d0c200c410174220a200d200d200a491b220a4100480d0c02400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b41002106410121074101210c4101210d4101210b41012108410121094101210441012105410121130c200b20064101102a000b200a4101102a000b200141046a280200210a0240024002400240024002400240200241046a280200200241086a280200220c460d002002280200210d0c010b200c41016a220d200c490d0e200c410174220b200d200d200b491b220b4100480d0e02400240200c0d00200b1027210d0c010b2002280200200c200b1028210d0b200d450d012002200d360200200241046a200b360200200241086a280200210c0b200241086a200c41016a360200200d200c6a41083a0000410121064100210b4100210c03400240200c200b470d00200b410174220d200b41016a22042004200d491b220d4100480d0f02400240200b0d00200d102721060c010b2006200b200d102821060b2006450d05200d210b0b2006200c6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41016a210c200d210a200d0d000b200c417f6a2109200241086a2105200241046a2107200c210d03400240024020072802002005280200220a460d00200228020021040c010b200a41016a2204200a490d0f200a4101742208200420042008491b22084100480d0f02400240200a0d002008102721040c010b2002280200200a2008102821040b2004450d0320022004360200200720083602002005280200210a0b2005200a41016a3602002004200a6a200d41807f72200d41ff0071200d410776220a1b3a0000200a210d200a0d000b02400240200241046a280200220d200241086a280200220a6b20094d0d002002280200210d0c010b200a200c6a2204200a490d0e200d410174220a20042004200a491b220a4100480d0e02400240200d0d00200a1027210d0c010b2002280200200d200a1028210d0b200d450d032002200d360200200241046a200a360200200241086a280200210a0b200241086a200a200c6a360200200d200a6a2006200c10ce041a41012107200b450d04200610290c040b200b4101102a000b20084101102a000b200a4101102a000b200d4101102a000b4101210c4101210d0c160b2001410c6a2802002109200141086a2802002113200141046a280200210802400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d0e200a410174220d200c200c200d491b220d4100480d0e02400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41073a0000200341dc006a410036020020034201370254200320023602502008200941146c6a2107410121044100210d4100210a2009210c03400240200a200d470d00200d41016a220b200d490d0f200d4101742205200b200b2005491b220b4100480d0f02400240200d0d00200b102721040c010b2004200d200b102821040b2004450d032003200b36025820032004360254200b210d0b2003200a41016a220536025c2004200a6a200c41807f72200c41ff0071200c410776220b1b3a00002005210a200b210c200b0d000b200821062009450d042008210a0340200a41146a2106200a28020c22054104460d05200a41106a280200210c200a29020021142003200a28020836024820032014370340200341086a200341c0006a200341d0006a10ed0320032d0008220a411a470d04024002402003280258220d200328025c220b460d00200328025421040c010b200b41016a220a200b490d0f200b410174220d200a200a200d491b220d4100480d0f02400240200b0d00200d102721040c010b2003280254200b200d102821040b2004450d042003200d360258200320043602540b2003200b41016a220a36025c2004200b6a20053a0000024003400240200a200d470d00200d41016a220b200d490d11200d4101742205200b200b2005491b220b4100480d1102400240200d0d00200b102721040c010b2004200d200b102821040b2004450d02200b210d0b2004200a6a200c41807f72200c41ff0071200c410776220b1b3a0000200a41016a210a200b210c200b0d000b2003200d3602582003200a36025c200320043602542006210a20062007470d010c070b0b200b4101102a000b200d4101102a000b200b4101102a000b200d4101102a000b20032d000b210c20032f0009210d20032903102114200328020c210b024020062007460d0003402006410c6a2802004104460d010240200641046a280200450d00200628020010290b200641146a22062007470d000b0b200c411074210c02402013450d00200810290b200d200c72210c02402003280258450d00200328025410290b2000200c3b00012000200a3a0000200041036a200c4110763a0000200041086a2014370000200041046a200b360000410021064101210d4101210c4101210b41012104410121050c110b20062007460d0003402006410c6a2802004104460d010240200641046a280200450d00200628020010290b200641146a22062007470d000b0b02402013450d00200810290b20032802582108200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d0b200a4101742206200d200d2006491b22064100480d0b02400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d0a200c410174220a200d200d200a491b220a4100480d0a02400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b41002113410121074101210c4101210d4101210b410121084101210941012104410121050c1d0b20064101102a000b200a4101102a000b2001410c6a2802002109200141086a2802002113200141046a2802002108024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d0e200a410174220d200c200c200d491b220d4100480d0e02400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41063a0000200341dc006a41003602002003420137025420032002360250200820094104746a21054100210a4100210c2009210d034002400240200a200c460d002003280254210a0c010b200a41016a220b200a490d0f200a4101742204200b200b2004491b220b4100480d0f02400240200a0d00200b1027210a0c010b2003280254200a200b1028210a0b200a450d032003200b3602582003200a3602540b2003200c41016a36025c200a200c6a200d41807f72200d41ff0071200d410776220d1b3a00000240200d450d002003280258210a200328025c210c200d210d0c010b0b2008210d2009450d054100210d0340200341086a41086a220a2008200d6a220c41086a2802003602002003200c2902003703080240200c410d6a2d000022044102470d00200c41106a210d0c070b200341306a41086a200a280200220a360200200320032903082214370330200c410c6a2d00002106200341206a41086a2207200a36020020032014370320024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0f200a4101742202200b200b2002491b22024100480d0f02400240200a0d0020021027210b0c010b2003280254200a20021028210b0b200b450d04200320023602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41fdf9ff77200641037441187141107376413f7141c000723a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0f200a4101742206200b200b2006491b22064100480d0f02400240200a0d0020061027210b0c010b2003280254200a20061028210b0b200b450d05200320063602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a20044100473a0000200341c0006a41086a200728020036020020032003290320370340200341086a200341c0006a200341d0006a10de0320032d0008220b411a470d05200d41106a210d200c41106a2005470d000c070b0b200d4101102a000b200b4101102a000b20024101102a000b20064101102a000b20032d000b210720032f00092102200328020c2111200329031021140240200941047441706a200d460d00200c41106a210d0340200d410d6a2d00004102460d01200d2802042106200d28020021040240200d280208220a450d00200a410474210c2004210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200d41106a210d02402006450d00200410290b200d2005470d000b0b2007411074210a02402013450d00200810290b2002200a72210a02402003280258450d00200328025410290b2000200a3b00012000200b3a0000200041036a200a4110763a0000200041086a2014370000200041046a2011360000410021054101210d4101210c4101210b410121040c0f0b200d2005460d000340200d410d6a2d00004102460d01200d2802042104200d280200210b0240200d280208220a450d00200a410474210c200b210a03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200d41106a210d02402004450d00200b10290b200d2005470d000b0b02402013450d00200810290b20032802582108200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d0a200a4101742206200d200d2006491b22064100480d0a02400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d09200c410174220a200d200d200a491b220a4100480d0902400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b41002105410121074101210c4101210d4101210b4101210841012109410121040c1b0b20064101102a000b200a4101102a000b2001410c6a2802002107200141086a2802002108200141046a280200210602400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d09200a410174220d200c200c200d491b220d4100480d0902400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41053a0000200341d0006a410c6a4100360200200342013702542003200236025020062007410c6c6a2102410121044100210d4100210a2007210c03400240200a200d470d00200d41016a220b200d490d0a200d4101742205200b200b2005491b220b4100480d0a02400240200d0d00200b102721040c010b2004200d200b102821040b2004450d032003200b36025820032004360254200b210d0b2003200a41016a220536025c2004200a6a200c41807f72200c41ff0071200c410776220b1b3a00002005210a200b210c200b0d000b2006210a2007450d022007410c6c210b4100210c034002402006200c6a220a41046a280200220d4102470d00200a410c6a210a0c040b200341086a200a280200200d200a41086a280200200341d0006a10eb03024020032d00082204411a460d0020032f000920032d000b41107472210520032903102114200328020c2107200a410c6a210d200b200c6b41746a210a02400340200a450d01200a41746a210a200d280204210c200d410c6a210d200c4102470d000b0b02402008450d00200610290b02402003280258450d00200328025410290b200020053b0001200020043a0000200041036a20054110763a0000200041086a2014370000200041046a2007360000410021044101210d4101210c4101210b0c100b200b200c410c6a220c470d000b2002210a0c020b200d4101102a000b200b4101102a000b200a410020076b410c6c6a210c024003402006200c460d01200c410c6a210c200a280204210d200a410c6a210a200d4102470d000b0b02402008450d00200610290b20032802582108200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d09200a4101742206200d200d2006491b22064100480d0902400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d08200c410174220a200d200d200a491b220a4100480d0802400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b41002104410121074101210c4101210d4101210b41012108410121090c190b20064101102a000b200a4101102a000b2001410c6a2802002109200141086a2802002113200141046a2802002106024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d09200a410174220d200c200c200d491b220d4100480d0902400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41043a0000200341d0006a410c6a4100360200200342013702542003200236025020062009410c6c6a2111410121044100210d4100210a2009210c03400240200a200d470d00200d41016a220b200d490d0a200d4101742205200b200b2005491b220b4100480d0a02400240200d0d00200b102721040c010b2004200d200b102821040b2004450d032003200b36025820032004360254200b210d0b2003200a41016a220536025c2004200a6a200c41807f72200c41ff0071200c410776220b1b3a00002005210a200b210c200b0d000b2006210a2009450d032009410c6c21084100210d034002402006200d6a220c41046a28020022044102470d00200c410c6a210a0c050b200c2802002105200c41086a2802002107024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d0a200a4101742202200b200b2002491b22024100480d0a02400240200a0d0020021027210b0c010b2003280254200a20021028210b0b200b450d04200320023602582003200b3602540b2003200a41016a36025c200b200a6a41f0003a0000200341086a200520042007200341d0006a10eb03024020032d0008220b411a460d0020032f000920032d000b41107472210420032903102114200328020c2105200c410c6a210c2008200d6b41746a210a02400340200a450d01200a41746a210a200c280204210d200c410c6a210c200d4102470d000b0b02402013450d00200610290b02402003280258450d00200328025410290b200020043b00012000200b3a0000200041036a20044110763a0000200041086a2014370000200041046a20053600004100210b4101210d4101210c0c0f0b2008200d410c6a220d470d000b2011210a0c030b200d4101102a000b200b4101102a000b20024101102a000b200a410020096b410c6c6a210c024003402006200c460d01200c410c6a210c200a280204210d200a410c6a210a200d4102470d000b0b02402013450d00200610290b20032802582108200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d08200a4101742206200d200d2006491b22064100480d0802400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d07200c410174220a200d200d200a491b220a4100480d0702400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b41002109410121074101210c4101210d4101210b410121080c170b20064101102a000b200a4101102a000b2001410c6a2802002106200141086a2802002109200141046a280200210802400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d0a200a410174220d200c200c200d491b220d4100480d0a02400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41033a0000200820064102746a21074100210d4100210a41002105410121042006210c03400240200a2005470d00200d200a41016a220b200b200d491b22054100480d0b02400240200d0d002005102721040c010b2004200a2005102821040b2004450d050b2004200a6a200c41807f72200c41ff0071200c410776220b1b3a0000200d41026a210d200a41016a210a200b210c200b0d000b02402006450d00200821060340200a410174210d2006280200210c03400240200a2005470d00200a41016a220b200a490d0d200d200b200b200d491b22054100480d0d02400240200a0d002005102721040c010b2004200a2005102821040b2004450d080b2004200a6a200c41807f72200c41ff0071200c410776220b1b3a0000200d41026a210d200a41016a210a200b210c200b0d000b200641046a22062007470d000b0b02402009450d00200810290b200241086a2106200241046a2107200a210d03400240024020072802002006280200220c460d002002280200210b0c010b200c41016a220b200c490d0b200c4101742208200b200b2008491b22084100480d0b02400240200c0d0020081027210b0c010b2002280200200c20081028210b0b200b450d032002200b360200200720083602002006280200210c0b2006200c41016a360200200b200c6a200d41807f72200d41ff0071200d410776220c1b3a0000200c210d200c0d000b02400240200241046a280200220d200241086a280200220c6b200a490d002002280200210d0c010b200c200a6a220b200c490d0a200d410174220c200b200b200c491b220c4100480d0a02400240200d0d00200c1027210d0c010b2002280200200d200c1028210d0b200d450d032002200d360200200241046a200c360200200241086a280200210c0b200241086a200c200a6a360200200d200c6a2004200a10ce041a41002108410121072005450d05200410290c050b200d4101102a000b20084101102a000b200c4101102a000b20054101102a000b20054101102a000b4101210c4101210d4101210b0c130b2001410c6a2802002106200141086a2802002111200141046a28020021130240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d11200a410174220d200c200c200d491b220d4100480d1102400240200a0d00200d1027210c0c010b2002280200200a200d1028210c0b200c450d012002200c360200200241046a200d360200200241086a280200210a0b200241086a200a41016a360200200c200a6a41023a0000200341dc006a410036020020034201370254200320023602502013200641286c6a21054100210a4100210c2006210d034002400240200a200c460d002003280254210a0c010b200a41016a220b200a490d12200a4101742204200b200b2004491b220b4100480d1202400240200a0d00200b1027210a0c010b2003280254200a200b1028210a0b200a450d032003200b3602582003200a3602540b2003200c41016a36025c200a200c6a200d41807f72200d41ff0071200d410776220d1b3a00000240200d450d002003280258210a200328025c210c200d210d0c010b0b2013210b2006450d0c2013210b0340200341086a41086a220d200b220a41086a2802003602002003200a290200370308200a41286a210b200a2d001822074104460d0d200a411b6a2d00002108200a41196a2f00002109200a41206a2900002114200a411c6a280000210c200a41146a2802002102200a41106a2802002104200a28020c2106200341206a41086a200d280200220a360200200320032903082218370320200341c0006a41086a200a36020020032018370340200341086a200341c0006a200341d0006a10ed03024020032d0008220a411a460d0020032f000920032d000b41107472210720032903102114200328020c21022004450d0d200610290c0d0b200320023602482003200436024420032006360240200341086a200341c0006a200341d0006a10ed03024020032d0008220a411a460d0020032f000920032d000b411074722107200328020c2102200329031021140c0d0b2014422088a7210a2014a7210d0240024002400240024020070e0400010203000b024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d16200a4101742204200d200d2004491b22044100480d1602400240200a0d0020041027210d0c010b2003280254200a20041028210d0b200d450d08200320043602582003200d3602540b2003200a41016a36025c200d200a6a41003a00000340024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d17200a4101742204200d200d2004491b22044100480d1702400240200a0d0020041027210d0c010b2003280254200a20041028210d0b200d450d0a200320043602582003200d3602540b2003200a41016a36025c200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000c040b0b024002402003280258200328025c2204460d00200328025421060c010b200441016a22062004490d1520044101742207200620062007491b22074100480d150240024020040d002007102721060c010b200328025420042007102821060b2006450d0920032007360258200320063602540b2003200441016a36025c200620046a41013a0000024002402003280258200328025c2204460d00200328025421060c010b200441016a22062004490d1520044101742207200620062007491b22074100480d150240024020040d002007102721060c010b200328025420042007102821060b2006450d0a20032007360258200320063602540b2003200441016a36025c200620046a41f0003a0000200341086a200c200d200a200341d0006a10eb0320032d0008220a411a460d0220032f000920032d000b4110747221070c0e0b024002402003280258200328025c2204460d00200328025421060c010b200441016a22062004490d1420044101742207200620062007491b22074100480d140240024020040d002007102721060c010b200328025420042007102821060b2006450d0a20032007360258200320063602540b2003200441016a36025c200620046a41023a0000200341086a200c200d200a200341d0006a10eb0320032d0008220a411a460d0120032f000920032d000b4110747221070c0d0b024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d13200a410174220d200c200c200d491b220d4100480d1302400240200a0d00200d1027210c0c010b2003280254200a200d1028210c0b200c450d0a2003200d3602582003200c3602540b2003200a41016a36025c200c200a6a41033a0000024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d13200a410174220d200c200c200d491b220d4100480d1302400240200a0d00200d1027210c0c010b2003280254200a200d1028210c0b200c450d0b2003200d3602582003200c3602540b2003200a41016a36025c200c200a6a2009200841107472220c417f73220a413f7141c00072200a200c411874411875417f4a1b3a0000024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d13200a4101742204200d200d2004491b22044100480d1302400240200a0d0020041027210d0c010b2003280254200a20041028210d0b200d450d0c200320043602582003200d3602540b2003200a41016a36025c200d200a6a200c4180fe03714100473a00000b200b2005470d000c0e0b0b200d4101102a000b200b4101102a000b20044101102a000b20044101102a000b20074101102a000b20074101102a000b20074101102a000b200d4101102a000b200d4101102a000b20044101102a000b20032903102114200328020c21020b0240200b2005460d000340200b41186a2d00004104460d01200b41106a280200210c200b410c6a280200210d0240200b41046a280200450d00200b28020010290b0240200c450d00200d10290b200b41286a220b2005470d000b0b02402011450d00201310290b02402003280258450d00200328025410290b200020073b00012000200a3a0000200041036a20074110763a0000200041086a2014370000200041046a20023600004100210c4101210d0c080b200b2005460d000340200b41186a2d00004104460d01200b41106a280200210a200b410c6a280200210c0240200b41046a280200450d00200b28020010290b0240200a450d00200c10290b200b41286a220b2005470d000b0b02402011450d00201310290b20032802582108200328025421022003280250220441086a210b200441046a2105200328025c2207210c024002400340024002402005280200200b280200220a460d002004280200210d0c010b200a41016a220d200a490d06200a4101742206200d200d2006491b22064100480d0602400240200a0d0020061027210d0c010b2004280200200a20061028210d0b200d450d022004200d36020020052006360200200b280200210a0b200b200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200441046a280200220c200441086a280200220a6b2007490d002004280200210c0c010b200a20076a220d200a490d05200c410174220a200d200d200a491b220a4100480d0502400240200c0d00200a1027210c0c010b2004280200200c200a1028210c0b200c450d022004200c360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200c200a6a2002200710ce041a02402008450d00200210290b4100210b410121074101210c4101210d0c130b20064101102a000b200a4101102a000b20082010460d0003402008410d6a2d00004105460d010240200841046a280200450d00200828020010290b200841106a22082010470d000b0b0240200e450d00200f10290b200241086a2106200241046a2107200c210d0240024003400240024020072802002006280200220a460d002002280200210b0c010b200a41016a220b200a490d04200a4101742208200b200b2008491b22084100480d0402400240200a0d0020081027210b0c010b2002280200200a20081028210b0b200b450d022002200b360200200720083602002006280200210a0b2006200a41016a360200200b200a6a200d41807f72200d41ff0071200d410776220a1b3a0000200a210d200a0d000b02400240200241046a280200220d200241086a280200220a6b200c490d002002280200210d0c010b200a200c6a220b200a490d03200d410174220a200b200b200a491b220a4100480d0302400240200d0d00200a1027210d0c010b2002280200200d200a1028210d0b200d450d022002200d360200200241046a200a360200200241086a280200210a0b200241086a200a200c6a360200200d200a6a2004200c10ce041a4100210d410121072005450d03200410290c030b20084101102a000b200a4101102a000b102b000b4101210c0c0c0b2000200c3b00012000200a3a0000200041036a200c4110763a0000200041086a2014370000200041046a2004360000410021134101210d4101210c4101210b410121044101210541012106410121074101210241012108410121090c090b4101210c200241086a200a41016a3602004100210d200b200a6a41003a00002003411c6a2004360200200341186a200536020020032006360214200320073602102003200836020c20032009360208200341d0006a200341086a200210f103200320032900513703402003200341d0006a41086a29000037004720032d0050220a411a460d092000200a3a000020002003290340370001200041086a20032900473700000b4101210b0b410121040b410121050b410121060b410121070b410121020b410121080b41012109410121130b20012d0000220a410e4b0d18200a0e0f0a0b0c0d0e0f1011121813141516170a0b4101210c410021074101210d0b4101210b0b410121080b410121090b410121040b410121050b410121130b410121060b410121020b41012111410121120c0f0b200141086a280200450d10200141046a28020010290c100b200d450d0f0240200141086a280200450d00200141046a28020010290b200141146a280200450d0f200141106a28020010290c0f0b02402001410c6a280200220c450d00200141046a280200210a200c410474210c03400240200a41046a280200450d00200a28020010290b200a41106a210a200c41706a220c0d000b0b200141086a280200450d0e200128020410290c0e0b200c450d0d02402001410c6a280200220c450d00200141046a280200210a200c41286c210c03400240200a41046a280200450d00200a28020010290b0240200a41106a280200450d00200a410c6a28020010290b200a41286a210a200c41586a220c0d000b0b200141086a280200450d0d200128020410290c0d0b200141086a280200450d0c200141046a28020010290c0c0b200b450d0b200141086a280200450d0b200141046a28020010290c0b0b2004450d0a200141086a280200450d0a200141046a28020010290c0a0b2005450d0902402001410c6a280200220a450d00200141046a280200220d200a4104746a210b03400240200d280208220c450d00200d280200210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200d41106a210a0240200d41046a280200450d00200d28020010290b200a210d200a200b470d000b0b200141086a280200450d09200128020410290c090b2006450d0802402001410c6a280200220c450d00200141046a280200210a200c41146c210c03400240200a41046a280200450d00200a28020010290b200a41146a210a200c416c6a220c0d000b0b200141086a280200450d08200128020410290c080b2007450d0702402001410c6a280200220a450d00200141046a280200220d200a411c6c6a210b03400240200d410c6a280200220c450d00200d280204210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b0240200d41086a280200450d00200d28020410290b200d411c6a210a0240200d41146a280200450d00200d28021010290b200a210d200a200b470d000b0b200141086a280200450d07200128020410290c070b2002450d0602402001410c6a280200220a450d00200141046a280200220d200a41186c6a210b03400240200d41046a280200450d00200d28020010290b0240200d41146a280200220c450d00200d28020c210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200d41186a210a0240200d41106a280200450d00200d28020c10290b200a210d200a200b470d000b0b200141086a280200450d06200128020410290c060b2008450d0502402001410c6a280200220a450d00200141046a280200220d200a411c6c6a210b03400240200d410c6a280200220c450d00200d280204210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b0240200d41086a280200450d00200d28020410290b200d411c6a210a0240200d41146a280200450d00200d28021010290b200a210d200a200b470d000b0b200141086a280200450d05200128020410290c050b2009450d040240200141046a2d0000220a41024b0d00024002400240200a0e03000102000b2001410c6a280200450d07200141086a28020010290c070b0240200141146a280200220c450d002001410c6a280200210a200c410c6c210c03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b200141106a280200450d06200128020c10290c060b0240200141146a280200220a450d002001410c6a2802002204200a4104746a210503402004220b41106a21040240200b280204220a450d000240200b410c6a280200220c450d00200c410c6c210c03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b200b41086a280200450d00200b28020410290b20042005470d000b0b200141106a280200450d05200128020c10290c050b2001410c6a280200450d04200141086a28020010290c040b2013450d030240200141086a280200450d00200141046a28020010290b0240200141146a280200220a450d00200141186a280200450d00200a10290b200141246a280200450d03200141206a28020010290c030b20011088030c020b410121100b2000411a3a0000024020012d0000220a410e4b0d0002400240024002400240024002400240024002400240024002400240200a0e0f0001020304050607080e090a0b0c0d000b200c450d0e200141086a280200450d0e200141046a28020010290c0e0b2007450d0d0240200141086a280200450d00200141046a28020010290b200141146a280200450d0d200141106a28020010290c0d0b200d450d0c02402001410c6a280200220c450d00200141046a280200210a200c410474210c03400240200a41046a280200450d00200a28020010290b200a41106a210a200c41706a220c0d000b0b200141086a280200450d0c200128020410290c0c0b200b450d0b02402001410c6a280200220c450d00200141046a280200210a200c41286c210c03400240200a41046a280200450d00200a28020010290b0240200a41106a280200450d00200a410c6a28020010290b200a41286a210a200c41586a220c0d000b0b200141086a280200450d0b200128020410290c0b0b2008450d0a200141086a280200450d0a200141046a28020010290c0a0b2009450d09200141086a280200450d09200141046a28020010290c090b2004450d08200141086a280200450d08200141046a28020010290c080b2005450d0702402001410c6a280200220a450d00200141046a280200220d200a4104746a210b03400240200d280208220c450d00200d280200210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200d41106a210a0240200d41046a280200450d00200d28020010290b200a210d200a200b470d000b0b200141086a280200450d07200128020410290c070b2013450d0602402001410c6a280200220c450d00200141046a280200210a200c41146c210c03400240200a41046a280200450d00200a28020010290b200a41146a210a200c416c6a220c0d000b0b200141086a280200450d06200128020410290c060b2006450d0502402001410c6a280200220a450d00200141046a280200220d200a411c6c6a210b03400240200d410c6a280200220c450d00200d280204210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b0240200d41086a280200450d00200d28020410290b200d411c6a210a0240200d41146a280200450d00200d28021010290b200a210d200a200b470d000b0b200141086a280200450d05200128020410290c050b2002450d0402402001410c6a280200220a450d00200141046a280200220d200a41186c6a210b03400240200d41046a280200450d00200d28020010290b0240200d41146a280200220c450d00200d28020c210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b200d41186a210a0240200d41106a280200450d00200d28020c10290b200a210d200a200b470d000b0b200141086a280200450d04200128020410290c040b2011450d0302402001410c6a280200220a450d00200141046a280200220d200a411c6c6a210b03400240200d410c6a280200220c450d00200d280204210a200c410474210c03400240200a2d00004109470d00200a41086a28020041ffffffff0371450d00200a41046a28020010290b200a41106a210a200c41706a220c0d000b0b0240200d41086a280200450d00200d28020410290b200d411c6a210a0240200d41146a280200450d00200d28021010290b200a210d200a200b470d000b0b200141086a280200450d03200128020410290c030b2012450d020240200141046a2d0000220a41024b0d00024002400240200a0e03000102000b2001410c6a280200450d05200141086a28020010290c050b0240200141146a280200220c450d002001410c6a280200210a200c410c6c210c03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b200141106a280200450d04200128020c10290c040b0240200141146a280200220a450d002001410c6a2802002204200a4104746a210503402004220b41106a21040240200b280204220a450d000240200b410c6a280200220c450d00200c410c6c210c03400240200a280200220d450d00200a41046a280200450d00200d10290b200a410c6a210a200c41746a220c0d000b0b200b41086a280200450d00200b28020410290b20042005470d000b0b200141106a280200450d03200128020c10290c030b2001410c6a280200450d02200141086a28020010290c020b2010450d010240200141086a280200450d00200141046a28020010290b0240200141146a280200220a450d00200141186a280200450d00200a10290b200141246a280200450d01200141206a28020010290c010b20011088030b200341e0006a24000b13002000410136020420004198f8c2003602000b3400200041f7fbc20036020420004100360200200041146a4102360200200041106a4180fcc200360200200041086a42093702000b2f01017f02404101102722020d0041014101102a000b200042818080801037020420002002360200200241003a00000b130020004101360204200041b4fec2003602000b3101017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242b9063700000b130020004101360204200041d881c3003602000b3400200041e182c30036020420004100360200200041146a4103360200200041106a41ec82c300360200200041086a420a3702000bb00a02067f017e230041106b220324002003200136020c2003410c6a200210300240024002400240024002400240024002402001450d00200141c8006c2104200241086a2101200241046a210503400240024020002d00004101460d0002400240200528020020012802002206460d00200228020021070c010b200641016a22072006490d0c20064101742208200720072008491b22084100480d0c0240024020060d002008102721070c010b200228020020062008102821070b2007450d052002200736020020052008360200200128020021060b2001200641016a360200200720066a41003a0000200041086a29030021090240024020052802002207200128020022066b4108490d00200228020021070c010b200641086a22082006490d0c20074101742206200820082006491b22064100480d0c0240024020070d002006102721070c010b200228020020072006102821070b2007450d062002200736020020052006360200200128020021060b2001200641086a360200200720066a20093700000c010b02400240200528020020012802002206460d00200228020021070c010b200641016a22072006490d0b20064101742208200720072008491b22084100480d0b0240024020060d002008102721070c010b200228020020062008102821070b2007450d062002200736020020052008360200200128020021060b2001200641016a360200200720066a41013a00000240024020052802002207200128020022066b4120490d00200228020021070c010b200641206a22082006490d0b20074101742206200820082006491b22064100480d0b0240024020070d002006102721070c010b200228020020072006102821070b2007450d072002200736020020052006360200200128020021060b2001200641206a360200200720066a220641186a200041196a290000370000200641106a200041116a290000370000200641086a200041096a2900003700002006200041016a2900003700000240200041216a2d00004101460d0002400240200528020020012802002206460d00200228020021070c010b200641016a22072006490d0c20064101742208200720072008491b22084100480d0c0240024020060d002008102721070c010b200228020020062008102821070b2007450d092002200736020020052008360200200128020021060b2001200641016a360200200720066a41003a00000c010b02400240200528020020012802002206460d00200228020021070c010b200641016a22072006490d0b20064101742208200720072008491b22084100480d0b0240024020060d002008102721070c010b200228020020062008102821070b2007450d092002200736020020052008360200200128020021060b2001200641016a360200200720066a41013a00000240024020052802002207200128020022066b4120490d00200228020021070c010b200641206a22082006490d0b20074101742206200820082006491b22064100480d0b0240024020070d002006102721070c010b200228020020072006102821070b2007450d0a2002200736020020052006360200200128020021060b2001200641206a360200200720066a220641186a200041226a220741186a290000370000200641106a200741106a290000370000200641086a200741086a290000370000200620072900003700000b200041c8006a2100200441b87f6a22040d000b0b200341106a24000f0b20084101102a000b20064101102a000b20084101102a000b20064101102a000b20084101102a000b20084101102a000b20064101102a000b102b000bf10703037f047e067f23002202210320024180026b416071220224002001411c6a22042902002105200420022903b801370200200141146a22042902002106200420022903b0013702002001410c6a22042902002107200420022903a801370200200241003a00a00120012902042108200120022903a00137020420022005370338200220063703302002200737032820022008370320200141246a2d00002109200241a0016a41176a22042005370000200241a0016a41106a220a2002290031370300200241a0016a41086a220b2002290029370300200220022900213703a00102402008a741ff01714101460d0020004100360220200324000f0b200241176a2004290000370000200241106a200a290300370300200241086a200b290300370300200220022903a001370300024002400240411210272204450d00200441106a41002f00f6a2443b0000200441086a41002900eea244370000200441002900e6a24437000020044112413210282204450d0120042002290300370012200420093a0031200441296a200241176a290000370000200441226a200241106a2903003700002004411a6a200241086a290300370000200241a0016a41186a220a4200370300200241a0016a41106a220b4200370300200241a0016a41086a220c4200370300200242003703a00120044132200241a0016a100020024180016a41186a200a29030037030020024180016a41106a200b29030037030020024180016a41086a200c290300370300200220022903a00137038001200241003602a00120024180016a4120200241a0016a1005210b20022802a001220a417f460d022002200a3602ec012002200b3602e801200241f0016a200241e8016a102d0240024020022802f001220c450d00200241f8016a280200210d20022802f401210e200241206a200241e8016a10940320022d00204102470d01200e450d00200c10290b418f89c3004133104e000b200241a0016a200241206a41017241c10010ce041a200241206a200241a0016a41c30010ce041a0240200a450d00200b10290b200241a0016a200241206a41c30010ce041a200241206a200241a0016a41c10010ce041a200141246a200241e0006a2d00003a00002001411c6a200241d8006a290000370000200141146a200241d0006a2900003700002001410c6a200241206a41286a2900003700002001200229004037000420002002290300370000200041086a200241086a290300370000200041106a200241106a290300370000200041176a200241176a290000370000200041286a200d3602002000200e3602242000200c360220200020093a001f20041029200324000f0b41124101102a000b41324101102a000b41b6b7c30041d700104e000be90703067f017e027f230041a0016b22022400200241003a00800120024180016a2001280200220320012802042204410047220510ce041a024002400240024020042005490d002001200420056b22063602042001200320056a22053602000240024002402004450d0020022d008001220441014b0d00410021030240024020040e020100010b20024180016a2006412020064120491b22046a41004100412020046b2004411f4b1b10cd041a20024180016a2005200410ce041a2001200620046b22073602042001200520046a22053602002006411f4d0d01200241c0006a41086a20024180016a41086a2900002208370300200241206a41186a20024180016a41186a290000370300200241206a41106a20024180016a41106a290000370300200241206a41086a2008370300200220022900800122083703402002200837032041012103200721060b200241186a200241206a41186a290300370300200241106a200241206a41106a290300370300200241086a200241206a41086a29030037030020022002290320370300200241003a00800120024180016a20052006410047220410ce041a20062004490d042001200620046b22073602042001200520046a22043602002006450d0520022d008001220541014b0d054100210620050e020201020b200041023a00000c050b20024180016a2007412020074120491b22056a41004100412020056b2005411f4b1b10cd041a20024180016a2004200510ce041a2001200720056b3602042001200420056a3602002007411f4d0d03200241c0006a41086a20024180016a41086a2900002208370300200241206a41186a20024180016a41186a290000370300200241206a41106a20024180016a41106a290000370300200241206a41086a20083703002002200229008001220837034020022008370320410121060b200241e0006a41186a2201200241206a41186a290300370300200241e0006a41106a2204200241206a41106a290300370300200241e0006a41086a2205200241206a41086a29030037030020024180016a41086a2207200241086a29030037030020024180016a41106a2209200241106a29030037030020024180016a41186a220a200241186a290300370300200220022903203703602002200229030037038001200020033a0000200041216a20063a00002000200229038001370001200041096a2007290300370000200041116a2009290300370000200041196a200a290300370000200041226a20022903603700002000412a6a2005290300370000200041326a20042903003700002000413a6a20012903003700000c030b20052004103e000b20042006103e000b200041023a00000b200241a0016a24000ba72207017f027e077f017e017f017e107f230041d0066b22032400200241d8006a2903002104200241d0006a290300210520022802002106200341c4006a200241046a41cc0010ce041a20034190016a200341c4006a41046a41c80010ce041a2001280200210720034190036a41186a2208200341c8016a29030037030020034190036a41106a2209200341c0016a29030037030020034190036a41086a220a200341b8016a290300370300200320032903b00137039003024002400240024041c80010272202450d002002420037030020022006360220200241186a4200370300200241106a4200370300200241086a42003703002002200341b0016a220b2902003702242002412c6a200b41086a290200370200200241346a200b41106a2902003702002002413c6a200b41186a290200370200200341286a41b18ac0004116108601200341186a2003290330200341286a41106a290300427f420010d404200341086a20052004200329031842002003280228220c1b220d4201200d420156200341186a41086a2903004200200c1b220d420052200d501b220c1b200d4200200c1b10d404200341e0026a41086a200a290300370300200341e0026a41106a2009290300370300200341e0026a41186a200829030037030020032003290390033703e0022003290308210d0240024002400240200741046a28020020072802082208460d00200728020021090c010b200841016a22092008490d012008410174220a20092009200a491b220aad42d0007e2204422088a70d012004a7220c4100480d010240024020080d00200c102721090c010b2007280200200841d0006c200c102821090b2009450d0220072009360200200741046a200a360200200728020821080b2009200841d0006c6a22084200370310200842003703082008200d37030020082002360220200820032903e00237022c200841186a4200370300200841246a428180808010370200200841346a200341e0026a41086a22022903003702002008413c6a200341e0026a41106a220a290300370200200841c4006a200341e0026a41186a22082903003702002007200728020841016a3602082001280208210c200341a0026a41186a200b41186a290000370300200341a0026a41106a200b41106a290000370300200341a0026a41086a200b41086a2900003703002003200b2900003703a002024002400240200c2802002201418883c000460d00200c28020421090c010b4100210920034190036a410041e00210cd041a20034188036a220b410036020020034180036a2207420037030020084200370300200a420037030020024200370300200342003703e00241940310272201450d01200141003b010620014100360200200141086a20034190036a41e00210ce041a20014190036a200b28020036020020014188036a200729030037020020014180036a200341f8026a290300370200200141f8026a200341f0026a290300370200200141f0026a200341e0026a41086a290300370200200120032903e0023702e802200c4100360204200c20013602000b02400340200141086a2108200141066a210e20012f0106220a41057421024100210b0240024003402002450d01200341a0026a2008412010d0042207450d02200241606a2102200b41016a210b200841206a21082007417f4a0d000b200b417f6a210a0b2009450d022009417f6a21092001200a4102746a4194036a28020021010c010b0b2001200b4102746a41e8026a20063602000c060b200341d8016a41186a200341a0026a41186a2202290300220d370300200341d8016a41106a200341a0026a41106a22082903002204370300200341d8016a41086a200341a0026a41086a220b2903002205370300200320032903a002220f3703d801200c200c28020841016a3602082002200d37030020082004370300200b20053703002003200f3703a0020240024002400240200e2f01002209410b490d0020034190036a410041e00210cd041a20034188036a2202410036020020034180036a22084200370300200341e0026a41186a4200370300200341e0026a41106a4200370300200341e0026a41086a4200370300200342003703e00241940310272210450d03201041003b010620104100360200201041086a20034190036a41e00210ce04210b20104190036a200228020036020020104188036a200829030037020020104180036a200341e0026a41186a290300370200201041f8026a200341e0026a41106a290300370200201041f0026a200341e0026a41086a290300370200201020032903e0023702e802200320012f00c8013b01dc022003200141ca016a2d00003a00de02200141cb016a2800002111200141cf016a2800002112200141d3016a2800002113200141d7016a28000021142003200141e0016a2900003700cd02200320012900db013703c8022001280280032115200b200141e8016a20012f010641796a220241057410ce04210b201041e8026a20014184036a200241027410ce042107200141063b0106201020023b0106200320032f01dc023b01c402200320032d00de023a00c602200320032903c8023703e002200320032900cd023700e502200a4107490d01201041066a210e200b200a417a6a22094105746a200b200a41796a22084105746a220b200241ffff037120086b41057410cf041a200b41186a200341a0026a41186a290300370000200b41106a200341a0026a41106a290300370000200b41086a200341a0026a41086a290300370000200b20032903a002370000200720094102746a210b200720084102746a21020c020b200141086a2207200a41016a220c4105746a2007200a4105746a22072009200a6b41057410cf041a200741186a2002290300370000200741106a2008290300370000200741086a200b290300370000200720032903a002370000200141e8026a2202200c4102746a2002200a4102746a220220012f0106200a6b41027410cf041a20022006360200200120012f010641016a3b01060c080b200141086a2202200a41016a22084105746a2002200a4105746a2202200e2f0100200a6b41057410cf041a200241186a200341a0026a41186a290300370000200241106a200341a0026a41106a290300370000200241086a200341a0026a41086a290300370000200220032903a002370000200141e8026a220b200a4102746a2102200b20084102746a210b200a21080b200b2002200e2f010020086b41027410cf041a20022006360200200e200e2f010041016a3b0100200341c0026a41026a221620032d00c60222023a00002003418c026a41026a221720023a0000200320032900e50237009502200320032903e00237039002200320032f01c40222023b01c00220032003290095023700fd0120032003290390023703f801200320023b018c0220012802002209450d0520012f0104210e20034190036a41027221180340201620172d00003a0000200320032f018c023b01c002200320032903f8013703a002200320032900fd013700a502200e41ffff037121010240024002400240024020092f01062202410b490d002018410041be0310cd041a41c40310272207450d0320074100360200200741046a20034190036a41c00310ce041a200320092f00c8013b01dc022003200941ca016a2d00003a00de022003200941db016a2900003703c8022003200941e0016a2900003700cd02200941cb016a2800002119200941cf016a280000211a200941d3016a280000211b200941d7016a280000211c20094180036a280200211d200741086a200941e8016a20092f0106220841796a220241057410ce04211e200741e8026a20094184036a200241027410ce04211f20074194036a200941b0036a2008417a6a220a41027410ce042106200941063b0106200720023b01060240200a450d00410021022006210803402008280200220b20023b0104200b2007360200200841046a2108200a200241016a2202470d000b0b200320032d00de0222023a00c602200320032f01dc0222083b01c402200320032903c8023703e002200320032900cd023700e50220034190026a41026a220a20023a0000200320083b019002200320032903e00237039003200320032900e50237009503200e41ffff037122084107490d01201e2001417a6a220b4105746a201e200141796a22024105746a220820072f010620026b41057410cf041a200841186a20032900a5023700002008201436000f2008201336000b2008201236000720082011360003200841026a20162d00003a0000200820032f01c0023b0000200820032903a002370013201f200b41027422086a201f20024102746a220e20072f0106221120026b41027410cf041a200e20153602002007201141016a220e3b01062001410274221120066a416c6a200620086a2208200e41ffff03712201200b6b41027410cf041a200820103602002001200b490d02200720116a41fc026a210803402008280200220b200241016a22023b0104200b2007360200200841046a210820022001490d000c030b0b200941086a2208200141016a220b4105746a200820014105746a2208200220016b41057410cf041a200841186a20032900a5023700002008201436000f2008201336000b2008201236000720082011360003200841026a200341c0026a41026a2d00003a0000200820032f01c0023b0000200820032903a002370013200941e8026a2202200b41027422086a2002200141027422076a220220092f0106220a20016b41027410cf041a200220153602002009200a41016a22023b0106200720094194036a22016a41086a200120086a2208200241ffff03712207200b6b41027410cf041a20082010360200200e41ffff037120074f0d0b2009200b417f6a22024102746a4198036a210803402008280200220b200241016a22023b0104200b2009360200200841046a210820022007490d000c0c0b0b200941086a2202200141016a220e4105746a200220014105746a220220092f010620016b41057410cf041a200241186a20032900a5023700002002201436000f2002201336000b2002201236000720022011360003200241026a20162d00003a0000200220032f01c0023b0000200220032903a002370013200941e8026a220b200e41027422066a200b200141027422026a220b20092f0106221120016b41027410cf041a200b20153602002009201141016a220b3b0106200220094194036a22116a41086a201120066a2206200b41ffff0371220b200e6b41027410cf041a200620103602002008200b4f0d00200920026a4198036a2102034020022802002208200141016a22013b010420082009360200200241046a2102200b2001470d000b0b2017200a2d00003a0000200320032f0190023b018c0220032003290390033703f80120032003290095033700fd01200928020022020d0120192111201c2114201b2113201a211220072110201d21150c080b41c4034104102a000b20092f0104210e20192111201c2114201b2113201a211220022109201d2115200721100c000b0b4194034104102a000b4194034104102a000b102b000b200c4108102a000b41c8004108102a000b20034190036a410272410041be0310cd041a41c40310272202450d0120024100360200200241046a20034190036a41c00310ce041a2002200c280200220836029403200c2002360200200c200c28020441016a360204200841003b010420082002360200200220022f0106220b4105746a220841086a20032f018c023b00002008410a6a2003418c026a41026a2d00003a0000200841176a2014360000200841136a20133600002008410f6a20123600002008410b6a20113600002008411b6a20032903f801370000200841206a20032900fd0137000020024194036a200b41016a22084102746a20103602002002200b4102746a41e8026a2015360200200220083b0106201020083b0104201020023602000b200020034190016a41c80010ce041a200341d0066a24000f0b41c4034104102a000bcc0b03087f017e037f230041306b22022400200241186a41086a220342003703002002420037031841cdf8c4004116200241186a1004200241086a41086a20032903003703002002200229031837030820024100360218200241086a4110200241186a100521030240024002400240024002400240024020022802182204417f460d002003450d002002200436022c20022003360228200241186a200241286a102d20022802182205450d02200241206a2802002106200228021c21072004450d01200310290c010b4101210541002106410021070b200520064105746a210820052103410021060240024003400240200820036b41e0004b0d0020032008460d03034020002003460d03200620032000412010d00422044100476a21062004450d032008200341206a2203470d000c040b0b20032000460d01200620032000412010d00422044100476a21062004450d01200341206a22042000460d01200620042000412010d00422044100476a21062004450d01200341c0006a22042000460d01200620042000412010d00422044100476a21062004450d01200341e0006a22042000460d01200620042000412010d00422044100476a210620034180016a210320040d000b0b200241186a41086a220342003703002002420037031841bec7c5004119200241186a1004200241086a41086a20032903003703002002200229031837030820024100360218200241086a4110200241186a1005210002400240024020022802182203417f460d002000450d00200220003602282002200336022c20024100360218200241186a20002003410420034104491b220410ce041a2002200320046b36022c2002200020046a3602280240200341034d0d0020022802182103200241186a200241286a1045200228021822090d020b418f89c3004133104e000b410421094100210041002108410021030c010b200229021c210a20001029200a422088a72100200aa721080b02400240200320016a220420034f0d002008210b200321040c010b02400240200020064d0d002008210b0c010b02400240200820006b200641016a2000200020064d1b220c20006b220d490d002008210b0c010b2000200d6a22032000490d092008410174220b20032003200b491b220b41ffffffff0371200b470d09200b41027422034100480d090240024020080d002003102721090c010b200920084102742003102821090b2009450d050b200920004102746a210302400240200d4102490d002000417f73200c6a2100034020034100360200200341046a21032000417f6a22000d000b200c417f6a21000c010b200d450d010b20034100360200200041016a21000b200020064d0d04200920064102746a2203200328020020016a3602000b200241186a41086a220342003703002002420037031841bec7c5004119200241186a1004200241086a41086a2003290300370300200220022903183703082002410036022020024201370318410410272203450d042003200436000020024284808080c00037021c2002200336021820022000360228200241286a200241186a10300240024020000d0020022802202101200228021c2108200228021821060c010b2000410274210d4100200228022022036b2100200228021c21082009210403402004280200210c02400240200820006a4104490d00200228021821060c010b200341046a22062003490d0920084101742201200620062001491b22014100480d090240024020080d002001102721060c010b200228021820082001102821060b2006450d082002200136021c20022006360218200121080b200441046a21042002200341046a2201360220200620036a200c3600002000417c6a210020012103200d417c6a220d0d000b0b200241086a411020062001100302402008450d00200610290b200b450d00200910290b02402007450d00200510290b200241306a24000f0b418f89c3004133104e000b20034104102a000b41e4f8c400200620001037000b41044101102a000b20014101102a000b102b000bde0605017f017e047f027e017f230041d0006b2201240042002102200141286a41086a220342003703002001420037032841aa8dc300410d200141286a1004200141186a41086a2003290300370300200120012903283703184100210320014100360228200141186a4110200141286a100521040240024002400240024020012802282205417f460d002001200536020c20012004360208200141286a200141086a104320012802282206450d02200129022c210202402005450d00200410290b2002422088a721032002a721050c010b41042106410021050b200141286a41206a200041206a280200360200200141286a41186a200041186a290200370300200141286a41106a200041106a290200370300200141286a41086a200041086a29020037030020012000290200370328024020032005470d00024020032002a7470d00200341016a22002003490d0420034101742205200020002005491bad220742247e2208422088a70d042008a722004100480d040240024020030d002000102721060c010b2006200341246c2000102821060b2006450d0320024280808080708320078421020b2002422088a721030b2006200341246c22096a22002001290328370200200041206a200141286a41206a280200360200200041186a200141286a41186a290300370200200041106a200141286a41106a290300370200200041086a200141286a41086a22002903003702002001200242ffffffff0f83200341016a2205ad4220868437020c20012006360208200042003703002001420037032841aa8dc300410d200141286a1004200141186a41086a2000290300370300200120012903283703182001411036022c2001200141186a360228200141086a200141286a105c2002a72104024020052003490d00200941246a21002006210303400240024020032d0000220541034b0d0002400240024020050e0404000102040b2003410c6a280200450d03200341086a28020010290c030b2003410c6a280200450d02200341086a28020010290c020b2003410c6a280200450d01200341086a28020010290c010b200341086a280200450d00200341046a28020010290b200341246a21032000415c6a22000d000b0b02402004450d00200610290b200141d0006a24000f0b418f89c3004133104e000b20004104102a000b102b000bd20601077f230041106b22022400024002400240024002400240024020002802704101460d0002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0720034101742205200420042005491b22054100480d070240024020030d002005102721040c010b200128020020032005102821040b2004450d0320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280274210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d0720044101742203200520052003491b22034100480d070240024020040d002003102721040c010b200128020020042003102821040b2004450d0420012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20063600000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0620034101742205200420042005491b22054100480d060240024020030d002005102721040c010b200128020020032005102821040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00000b20002001109d0220002802782103200220004180016a280200220036020c2002410c6a2001103002402000450d0020004105742106200141086a2105200141046a210703400240024020072802002204200528020022006b4120490d00200128020021040c010b200041206a22082000490d0720044101742200200820082000491b22004100480d070240024020040d002000102721040c010b200128020020042000102821040b2004450d062001200436020020072000360200200528020021000b2005200041206a360200200420006a220041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020002003290000370000200341206a2103200641606a22060d000b0b200241106a24000f0b20054101102a000b20034101102a000b20054101102a000b20004101102a000b102b000be70101017f024020002d0000417b6a220141064b0d00024002400240024020010e0700040401020403000b200041086a2d00004101470d03200041146a280200450d03200041106a28020010290c030b200041046a2d00004103470d0202402000410c6a280200450d00200041086a28020010290b200041186a280200450d02200041146a28020010290c020b200041046a2802000d012000410c6a280200450d01200041086a28020010290c010b200041086a2d00004105490d00200041306a280200450d002000412c6a28020010290b0240200041fc006a280200450d00200028027810290b0b130020004106360204200041f890c3003602000b34002000418d97c30036020420004100360200200041146a410f360200200041106a419497c300360200200041086a42063702000b950101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120102722060d0041204101102a000b20062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000b7401027f230041106b22022400200241003602082002420137030002404101102722030d0041014101102a000b200341003a00002002428180808010370204200220033602002002410036020c2002410c6a20021030200041086a200228020836020020002002290300370200200241106a24000b130020004100360204200041b8d6c5003602000b980104037f017e017f017e230041106b220224002002410036020c200141102002410c6a10052103024002400240200228020c2204417f470d00420021050c010b20024200370300200220032004410820044108491b10ce042106200441074d0d01200629030021072003102920014110100c420121050b2000200537030020002007370308200241106a24000f0b418f89c3004133104e000b0a0041c88ac3001058000b0a0041b88bc3001058000bf30c020b7f067e23004180016b22082400024002400240024002400240200728021c41016a220941004c0d002007411c6a210a2007200936021c200741246a280200210b200741206a220c210d024002400340200d280200220e41086a210f200e2f01062210410574210d41002111024002400340200d450d012004200f412010d0042212450d02200d41606a210d201141016a2111200f41206a210f2012417f4a0d000b2011417f6a21100b200b450d02200b417f6a210b200e20104102746a41880b6a210d0c010b0b200e201141e0006c6a220d41e8026a280200450d00200d41f8026a2903002113200d41f0026a29030021140c010b200841286a2007412c6a2802002004200741306a28020028021c110200200841306a2903002113200728021c2109200829032821140b20072009417f6a36021c200141186a29030021152007280250210d20012903102116024002400240024041004101410220142013842217501b20021b0e03010200010b200d41a8016a210d0c020b200d4188016a210d0c010b200d4198016a210d0b20162015844200510d01200841186a200d290300200d41086a2903002016201510d40420014200200129030822152008290318427f200841186a41086a290300501b7d22162016201556220d1b3703080240200d450d0041c6b5c300210d4122210f0c060b200a28020041016a220141004c0d022007200136021c2007280224210b024002400340200c280200220e41086a210f200e2f01062210410574210d41002111024002400340200d450d012003200f412010d0042212450d02200d41606a210d201141016a2111200f41206a210f2012417f4a0d000b2011417f6a21100b200b450d02200b417f6a210b200e20104102746a41880b6a210c0c010b0b200e201141e0006c6a220d41e8026a280200450d00200d41f8026a2903002115200d41f0026a29030021160c010b200841086a2007412c6a2802002003200741306a28020028021c110200200841106a2903002115200728021c2101200829030821160b200a2001417f6a3602000240201620057d2218201656201520067d2016200554ad7d221620155620162015511b4101470d0041e8b5c300210d411d210f0c060b024020174200520d002007280250220d290378200556200d4180016a290300221520065620152006511b450d004185b6c300210d411f210f0c060b2008200341022018201610910102402008280200220d450d002008280204210f0c060b0240201420057c2217201454220d201320067c200dad7c221520135420152013511b450d0041a4b6c300210d412d210f0c060b4100210d024020032004470d000c060b024020032004412010d0040d000c060b200a20032018201610f401200a20042017201510f401200841e0006a41086a200341086a290000370300200841e0006a41106a200341106a290000370300200841e0006a41186a200341186a290000370300200841c0006a41086a200441086a290000370300200841c0006a41106a200441106a290000370300200841c0006a41186a200441186a290000370300200820032900003703602008200429000037034002400240200741c0006a280200220f2007413c6a280200460d00200728023821110c010b200f41016a220d200f490d05200f4101742211200d200d2011491b220dad42e8007e2215422088a70d052015a722124100480d0502400240200f0d002012102721110c010b2007280238200f41e8006c2012102821110b2011450d04200720113602382007413c6a200d3602002007280240210f0b4100210d2011200f41e8006c6a220f41003a0000200f2008290360370001200f41096a200841e0006a41086a290300370000200f41116a200841e0006a41106a290300370000200f41196a200841e0006a41186a290300370000200f41216a2008290340370000200f41296a200841c0006a41086a290300370000200f41316a200841c0006a41106a290300370000200f41396a200841c0006a41186a290300370000200f41c4006a2008413c6a280000360000200f41c1006a2008280039360000200f41e0006a4100360200200f4201370358200f41d0006a2006370300200f41c8006a20053703002007200728024041016a3602400c050b41d8a8c1004118200841e0006a4180a9c10010a201000b41fcecc2001058000b41d8a8c1004118200841e0006a4180a9c10010a201000b20124108102a000b102b000b2000200f3602042000200d36020020084180016a24000bc50101057f230041306b220124002000410c6a28020021022000280204210302400240200041086a28020022040d00200321000c010b2004210520032100034020002802880b21002005417f6a22050d000b0340200320032f01064102746a41880b6a28020021032004417f6a22040d000b0b200141246a20032f0106360200200141206a41003602002001411c6a20033602002001200236022820014100360218200142003703102001200036020c20014100360208200141086a10d901200141306a24000b85e3010b047f017e037f017e097f017e037f097e027f0a7e2e7f230041c0176b2202240041d7c7c5004113108a02210302400240024002400240024002402001417f6a2204410670450d002003200341ff017141024771450d010b200241f80b6a41086a22034200370300200242003703f80b41abccc1004112200241f80b6a100420024198106a41086a2003290300370300200220022903f80b37039810200241003602b80d20024198106a4110200241b80d6a100521030240024002400240024020022802b80d2201417f460d002003450d00200220013602b40b200220033602b00b200241b80d6a200241b00b6a102d20022802b80d2205450d0220022902bc0d21062001450d01200310290c010b41012105420021060b410021070240024002402006422088a7220141057422030d0041082108410021090c010b20034105752209ad42d0007e220a422088a70d09200aa7220b4100480d09200b10272208450d010b2006a7210c0240200520036a2005460d002001410574210b20024198106a41206a2103410021072008210d200521010340200241b00b6a41086a220e200141086a290000370300200241b00b6a41106a220f200141106a290000370300200241b00b6a41186a2210200141186a290000370300200220012900003703b00b200241b80d6a200241b00b6a104d20024198106a41186a201029030037030020024198106a41106a200f29030037030020024198106a41086a200e290300370300200320022903b80d370300200341086a200241b80d6a41086a290300370300200341106a200241b80d6a41106a290300370300200341186a200241b80d6a41186a290300370300200341206a200241b80d6a41206a290300370300200341286a200241b80d6a41286a290300370300200220022903b00b37039810200741016a2107200d20024198106a41d00010ce0441d0006a210d200141206a2101200b41606a220b0d000b0b0240200c450d00200510290b200241f80b6a41086a22034200370300200242003703f80b41bec7c5004119200241f80b6a1004200241b80d6a41086a2003290300370300200220022903f80b3703b80d2002410036029810200241b80d6a411020024198106a100521030240024002402002280298102201417f460d002003450d00200220033602b00b200220013602b40b200241003602981020024198106a20032001410420014104491b220b10ce041a20022001200b6b3602b40b20022003200b6a3602b00b0240200141034d0d00200228029810210f20024198106a200241b00b6a104520022802981022110d020b418f89c3004133104e000b410421114100210e410021124100210f0c010b200229029c10210620031029200241b80d6a4110100c2006422088a7210e2006a721120b200241800a6a41ceecc200410d10940120022903880a210620022802800a2103200241f0096a41cfa2c400411710940120022903f809210a20022802f0092101200241f80b6a41086a220c4200370300200242003703f80b41cfa2c4004117200241f80b6a1004200241b80d6a41086a2213200c290300370300200220022903f80b3703b80d20022006420020031b220637039810200241b80d6a411020024198106a4108100302402006200a420020011b7d221450450d00410021150c040b200c4200370300200242003703f80b41cdf8c4004116200241f80b6a10042013200c290300370300200220022903f80b3703b80d2002410036029810200241b80d6a411020024198106a100521030240024002402002280298102201417f460d002003450d00200220013602b40b200220033602b00b20024198106a200241b00b6a102d2002280298102216450d02200241a0106a280200210d200228029c1021172001450d01200310290c010b410121164100210d410021170b200241d8096a41c8f9c4004111108601200241d8096a41106a290300211820022903e009211920022802d8092103200241c0096a41b18ac0004116108601200241b0096a20022903c809420020022802c00922011b221a200241c0096a41106a290300420020011b428094ebdc03420010d404200241a0096a20022903b0092206200241b0096a41086a290300220a4280ec94a37c427f10d30420024190096a2019420020031b2018420020031b200dad420010d304201442ffffffff0f8342ffffffff0f2014428080808010541b211b20022903a009201a7c211420024190096a41086a290300211c4100210b41d0dec1002101200229039009211d02400240034002404190e1c100200122036b41304b0d0020034190e1c100460d03200220032802002201360298102002418094ebdc0336029c1020024180096a2006200a20024198106a2001418094ebdc034b4102746a3502002218420010d3042002290380092219201820147e428094ebdc038042ffffffff0f837c2218201d5a20024180096a41086a2903002018201954ad7c2218201c5a2018201c511b0d03200241f0086a41086a21100c020b200220032802002201360298102002418094ebdc0336029c10200241e0086a2006200a20024198106a2001418094ebdc034b4102746a3502002218420010d30420022903e0082219201820147e428094ebdc038042ffffffff0f837c2218201d5a200241e0086a41086a2903002018201954ad7c2218201c5a2018201c511b0d02200220032802102201360298102002418094ebdc0336029c10200241d0086a2006200a20024198106a2001418094ebdc034b4102746a3502002218420010d304024020022903d0082219201820147e428094ebdc038042ffffffff0f837c2218201d5a200241d0086a41086a2903002018201954ad7c2218201c5a2018201c511b450d002003210b0c030b200220032802202201360298102002418094ebdc0336029c10200241c0086a2006200a20024198106a2001418094ebdc034b4102746a3502002218420010d304024020022903c0082219201820147e428094ebdc038042ffffffff0f837c2218201d5a200241c0086a41086a2903002018201954ad7c2218201c5a2018201c511b450d00200341106a210b0c030b200220032802302201360298102002418094ebdc0336029c10200241b0086a2006200a20024198106a2001418094ebdc034b4102746a3502002218420010d304200341c0006a2101200341306a210b20022903b0082219201820147e428094ebdc038042ffffffff0f837c2218201d54200241b0086a41086a2903002018201954ad7c2218201c542018201c511b0d000b200341206a210b0c010b03404180e1c1002003220b460d01200b41106a21032002200b41106a2802002201360298102002418094ebdc0336029c10200241f0086a2006200a20024198106a2001418094ebdc034b4102746a3502002218420010d30420022903f0082219201820147e428094ebdc038042ffffffff0f837c2218201d5a20102903002018201954ad7c2218201c5a2018201c511b450d000b0b4200211e20024190086a201d201c428094ebdc03420010d40420024180086a200229039008221920024190086a41086a290300221a4280ec94a37c427f10d304200b41d0dec100200b1b2203410c6a2d00002101200341046a280200210b200341086a28020021032002418094ebdc0336029c10200220033602981020024198106a2003418094ebdc034b4102746a35020021182002418094ebdc0336029c102002200b36029810200241f0076a2019201a20024198106a200b418094ebdc034b4102746a350200221f420010d304200241a0086a2006200a2018420010d304200241e0076a420020022903a008220a201820147e428094ebdc038042ffffffff0f837c220620022903f0072218201f200229038008201d7c7e428094ebdc038042ffffffff0f837c22147d22192019200656200241a0086a41086a2903002006200a54ad7c220a200241f0076a41086a2903002014201854ad7c22197d2006201454ad7d2218200a562018200a511b22031b427f200620147c22142014200654220b200a20197c200bad7c2206200a542006200a511b220b1b20011b4200201820031b427f2006200b1b20011b201b420010d304200241d0076a20022903e007200241e0076a41086a29030042e08f860f420010d4040240200d41057422030d00420021200c040b2011200e4102746a2121201620036a2122200241d0076a41086a290300212320022903d0072124200fad21252011210e4200211e420021202016210d024002400340200e2021460d0602400240200e2802002203450d00024002400240024002400240200f450d00200241c0076a202420232025420010d404200241b0076a20022903c0072206200241c0076a41086a290300220a2025420010d304200241a0076a2006200a200f20032003200f4b1bad2214420010d304202420022903b0077d20147e202580210620022903a0072114200241a0076a41086a290300211a411210272203450d01200341106a41002f0088a3443b0000200341086a4100290080a344370000200341002900f8a24437000020034112413210282203450d022003200d2900003700122003412a6a200d41186a290000370000200341226a200d41106a2900003700002003411a6a200d41086a290000370000200241c00a6a41186a22014200370300200241c00a6a41106a220b4200370300200241c00a6a41086a22104200370300200242003703c00a20034132200241c00a6a1000200241b80d6a41186a2001290300370300200241b80d6a41106a200b290300370300200241b80d6a41086a22052010290300370300200220022903c00a3703b80d2002410036029810200241b80d6a412020024198106a10052101200228029810220b417f460d042001450d042002200b36029c10200220013602981020024198076a20024198106a102e200228029807450d0320024180076a20024198106a1053200229038007a7450d0320024180076a41106a290300210a2002290388072119200b450d05200110290c050b41dcf9c4001058000b41124101102a000b41324101102a000b418f89c3004133104e000b420021194200210a0b2003102942002118200242003703c00d200242003703b80d024002402014200642ffffffff0f837c2206201920062019200654200a201a2006201454ad7c221454200a2014511b22031b22267d22272014200a201420031b22287d2006202654ad7d22298450450d00420021060c010b20024198106a200d104d20024198106a41086a29030022064200200229039810220a42015620064200522006501b22031b2106200a420120031b210a20022802b81021100240024020022802c01022030d00200241f8056a200a2006428094ebdc03420010d404200241f8056a41086a290300212a20022903f805212b0c010b2010200341306c6a210b200241f0066a200a2006428094ebdc03420010d404200241d0066a20272029428094ebdc03420010d404200241e0066a20272029428094ebdc03420010d504200241f0066a41086a290300222a420020022903f006222b420156202a420052202a501b22031b2118202b420120031b2119200241d0066a41086a290300211b20022903d006211f20022903e006212c201021030340200241c0066a200a200329030022142014200a56200341086a290300221420065620142006511b22011b2006201420011b2019201810d40420022903c006221a428080808010544100200241c0066a41086a290300501b450d04200241b0066a200a20062019201810d40420022903b0062214428080808010544100200241b0066a41086a290300501b450d0602402014a7450d0020024188066a201f201b201a42ffffffff0f83428094ebdc037e201442ffffffff0f838042ffffffff0f832214420010d30420024198066a200341106a200229038806221a2014202c7e428094ebdc038042ffffffff0f837c221420024188066a41086a2903002014201a54ad7c10d603200241b80d6a20022903980620022903a00620024198066a41106a29030010eb01200341306a2203200b460d020c010b0b41c489c3001058000b200241e8056a200a20022903a81022142014200a5620024198106a41186a290300221420065620142006511b22031b2006201420031b202b4201202b420156202a420052202a501b22031b2214202a420020031b221810d40420022903e8052219428080808010544100200241e8056a41086a290300501b450d02200241d8056a200a20062014201810d40420022903d8052206428080808010544100200241d8056a41086a290300501b450d042006a7450d05200241c8056a20272029428094ebdc03420010d404200241b8056a20022903c805220a200241c8056a41086a29030022144280ec94a37c427f10d304200241a8056a200a2014201942ffffffff0f83428094ebdc037e200642ffffffff0f838042ffffffff0f832206420010d30420022903a805220a2006202720022903b8057c7e428094ebdc038042ffffffff0f837c2218200a54ad2106200241a8056a41086a290300210a024020022802bc10450d00201010290b200a20067c21060b20024190056a200d201820267c220a200620287c200a201854ad7c10d603200241b80d6a20022903900520022903980520024190056a41106a29030010eb01427f202020052903007c201e20022903b80d7c220a201e542203ad7c22062003200620205420062020511b22031b2120427f200a20031b211e0b200e41046a210e200d41206a220d2022470d010c070b0b10a003000b10a103000b41c489c3001058000b418f89c3004133104e000b200b4108102a000b418f89c3004133104e000b02402012450d00201110290b200241b0106a202037030020024198106a41106a201e37030020024198106a41086a41003a0000200241033a00981041b8d6c500410020024198106a108801200241f8046a41b18ac0004116108601200241f8046a41106a2903002106200229038005210a20022802f8042103200241f80b6a41086a22014200370300200242003703f80b41b18ac0004116200241f80b6a1004200241b80d6a41086a2001290300370300200220022903f80b3703b80d2002427f2006420020031b220620207c200a420020031b220a201e7c2214200a542203ad7c220a2003200a200654200a2006511b22031b3703a0102002427f201420031b37039810200241b80d6a411020024198106a411010030240201e202084500d00201d201c84500d0042002106200241b00b6a41086a22034200370300200242003703b00b41b18ac0004116200241b00b6a1004200241b80d6a41086a2003290300370300200220022903b00b3703b80d2002410036029810200241b80d6a411020024198106a100521030240024002400240024002402002280298102201417f470d00420021064200210a0c010b024020030d004200210a0c010b200242003703a010200242003703981020024198106a20032001411020014110491b10ce041a2001410f4d0d01200241a0106a290300210a2002290398102106200310290b2006201d7d2214200656200a201c7d2006201d54ad7d2206200a562006200a511b0d04200241e8046a20142006201d201c10d404200241b8046a200241e8046a41086a29030022064200201e420010d304200241c8046a2020420020022903e804220a420010d304200241d8046a200a4200201e420010d304200642005220204200527120022903c0044200527220022903d00442005272200241d8046a41086a290300220620022903b80420022903c8047c7c2214200654720d0420022903d8042118200241b00b6a41086a22034200370300200242003703b00b41b18ac0004116200241b00b6a1004200241b80d6a41086a2003290300370300200220022903b00b3703b80d2002410036029810200241b80d6a411020024198106a100521032002280298102201417f460d022003450d02200242003703a010200242003703981020024198106a20032001411020014110491b10ce041a2001410f4d0d01200241a0106a290300210a2002290398102106200310290c030b418f89c3004133104e000b418f89c3004133104e000b420021064200210a0b200241b00b6a41086a22014200370300200242003703b00b41b18ac0004116200241b00b6a1004200241b80d6a41086a220b2001290300370300200220022903b00b3703b80d2002427f200a20147c200620187c221a2006542203ad7c221920032019200a542019200a511b22031b3703a0102002427f201a20031b37039810200241b80d6a411020024198106a4110100320024198106a109701200241a8046a20024198106a2006427f85201820031b2206200a427f85201420031b2214108301200241a8046a41086a290300211820022903a804210a20024190046a41b18ac00041161086012006200a7d200a20067d200a2006582018201458201820145122031b220d1b211b201420187d2006200a54ad7d201820147d200a200654ad7d200d1b211f20024190046a41106a2903004200200228029004220d1b21192002290398044200200d1b211a02400240200a200656201820145620031b0d00200b4200370300200242003703b80d41b18ac0004116200241b80d6a10042001200b290300370300200220022903b80d3703b00b200242002019201f7d201a201b54ad7d2206201a201b7d220a201a56200620195620062019511b22031b3703c00d20024200200a20031b3703b80d200241b80d6a21030c010b200241f80b6a41086a22034200370300200242003703f80b41b18ac0004116200241f80b6a100420012003290300370300200220022903f80b3703b00b2002427f2019201f7c201a201b7c220a201a542203ad7c22062003200620195420062019511b22031b3703c00d2002427f200a20031b3703b80d200241b80d6a21030b200241b00b6a41102003411010030b410121152017450d00201610290b20024188046a4189c7c500411210b5012002280288042103200228028c042101200c4200370300200242003703f80b4189c7c5004112200241f80b6a10042013200c290300370300200220022903f80b3703b80d2002200141016a410120031b221636029810200241b80d6a411020024198106a4104100320024180046a419bc7c500412310b501200c4200370300200242003703f80b419bc7c5004123200241f80b6a10042013200c290300370300200220022903f80b3703b80d2002200436029810200241b80d6a411020024198106a41041003024002400240024002400240024002400240024002400240024002400240201641a105490d00200241f80b6a41086a22034200370300200242003703f80b41eac7c5004112200241f80b6a1004200241b80d6a41086a2003290300370300200220022903f80b3703b80d2002410036029810200241b80d6a411020024198106a1005212d024002400240024002400240200228029810222e417f460d00202d450d002002202e36029c102002202d36029810200241f8036a20024198106a102e20022802f803450d1a024002400240024020022802fc0322224180042022418004491b220c0d00410421050c010b200c410374220310272205450d010b02402022450d00200228029810210e200228029c1021014100210f4100210d4100210b0340200241003602b00b200241b00b6a200e20014104200141044922211b221010ce041a2002200120106b220336029c102002200e20106a220e360298100240024020210d0020022802b00b2121200241003602b00b200241b00b6a200e2003410420034104491b221010ce041a2002200320106b220136029c102002200e20106a220e36029810200341034b0d010b200c450d1f200510290c1f0b200b41016a210320022802b00b21100240200b200c470d00200f20032003200f491b220c41ffffffff0171200c470d1e200c41037422134100480d1e02400240200b0d002013102721050c010b2005200d2013102821050b2005450d040b2005200d6a220b2021360200200b41046a2010360200200f41026a210f200d41086a210d2003210b20222003470d000b0b2005450d1c2022ad422086200cad842206422088a721032006a721170240202e450d00202d10290b20172003470d040c030b20034104102a000b20134104102a000b41042105410021170b2017220341016a22012003490d172003410174220b20012001200b491b221741ffffffff01712017470d17201741037422014100480d170240024020030d002001102721050c010b200520034103742001102821050b2005450d010b201641e07a6a2101200520034103746a220b2004360204200b20163602002005200341016a220f4103746a210d410021030240200f41044f0d002005210b0c020b2005210e02400340200e220b28020020014f0d040240200b41086a2802002001490d00200341016a21030c050b0240200b41106a2802002001490d00200341026a21030c050b200b41186a28020020014f0d01200341046a2103200d200b41206a220e6b41184b0d000b200b41206a210b0c020b200341036a21030c020b20014104102a000b200b200d460d000340200b28020020014f0d01200341016a2103200d200b41086a220b470d000b0b024002400240024002400240200f2003490d0041002101200f20036b2210450d0502402003450d002005200520034103746a201041037410cf041a0b2005280204210c200241f80b6a41086a22034200370300200242003703f80b419fcac5004113200241f80b6a1004200241b80d6a41086a2003290300370300200220022903f80b3703b80d20024198106a200241b80d6a411010bb0102402002280298104101470d00024020024198106a41086a2802002221200c2021200c491b220f200228029c1022014f0d002001210f0c050b02402001200f4f0d000340411a10272203450d04200341186a41002f00e8b3433b0000200341106a41002900e0b343370000200341086a41002900d8b343370000200341002900d0b3433700002003411a413410282203450d052003200136001a200241c00a6a41186a220b4200370300200241c00a6a41106a220d4200370300200241c00a6a41086a220e4200370300200242003703c00a2003411e200241c00a6a1000200241e00a6a41186a200b290300370300200241e00a6a41106a200d290300370300200241e00a6a41086a200e290300370300200220022903c00a3703e00a200241e00a6a4120100c20031029200141016a22032101200f2003470d000b0b2021200c4b0d040b200241f80b6a41086a22034200370300200242003703f80b419fcac5004113200241f80b6a1004200241b80d6a41086a2003290300370300200220022903f80b3703b80d200241b80d6a4110100c0c040b419cb1c5001058000b411a4101102a000b41344101102a000b200241f80b6a41086a22034200370300200242003703f80b419fcac5004113200241f80b6a1004200241b80d6a41086a2003290300370300200220022903f80b3703b80d410410272203450d032003200f36000020034104410810282203450d0420032021360004200241b80d6a4110200341081003200310290b201021010b200241f80b6a41086a22034200370300200242003703f80b41eac7c5004112200241f80b6a1004200241b80d6a41086a2003290300370300200220022903f80b3703b80d200241003602a0102002420137039810200220013602b00b200241b00b6a20024198106a10300240024020010d0020022802a0102103200228029c10210b20022802981021010c010b200520014103746a2113410020022802a010220f6b210d200228029c10210b410021030340200f20036a210e200520036a2210280200210c02400240200b200d6a4104490d0020022802981021010c010b200e41046a2201200e490d16200b4101742221200120012021491b22214100480d1602400240200b0d002021102721010c010b200228029810200b2021102821010b2001450d062002202136029c1020022001360298102021210b0b2002200e41046a22213602a0102001200f6a20036a200c360000201041046a280200210c0240200b200d6a417c6a41034b0d00202141046a22222021490d16200b4101742221202220222021491b22214100480d1602400240200b0d002021102721010c010b2001200b2021102821010b2001450d072002202136029c1020022001360298102021210b0b2002200e41086a3602a0102001200f6a20036a41046a200c360000200d41786a210d200341086a2103201041086a2013470d000b200f20036a21030b200241b80d6a41102001200310030240200b450d00200110290b2017450d00200510290b200241f0036a41bdc6c500411610b50120022802f403212f20022802f0032130200241e8036a41d3c6c500411d10b50120022802ec03213120022802e8032132200241c00a6a41186a22034200370300200241c00a6a41106a22014200370300200241c00a6a41086a220b4200370300200242003703c00a41b3a4c400411a200241c00a6a1000200241b80d6a41186a2003290300370300200241b80d6a41106a2001290300370300200241b80d6a41086a200b290300370300200220022903c00a3703b80d2002410036029810200241b80d6a412020024198106a1005210302400240200228029810220b417f470d00410021010c010b410021012003450d00200241c00a6a200b4120200b4120491b22016a41004100412020016b2001411f4b1b10cd041a200241c00a6a2003200110ce041a200b411f4d0d05200241e00a6a41186a2201200241c00a6a41186a290300370300200241e00a6a41106a220b200241c00a6a41106a290300370300200241e00a6a41086a220d200241c00a6a41086a290300370300200220022903c00a3703e00a2003102920024198106a41186a200129030037030020024198106a41106a200b29030037030020024198106a41086a200d290300370300200220022903e00a37039810410121010b412810272203450d05200320013a0004200341b8d6c5003602002003200229039810370005200320022f00b00b3b00252003410d6a20024198106a41086a290300370000200341156a20024198106a41106a2903003700002003411d6a20024198106a41186a290300370000200341276a200241b20b6a2d00003a0000200241c00a6a41186a22014200370300200241c00a6a41106a220b4200370300200241c00a6a41086a220d4200370300200242003703c00a41c6a3c400411a200241c00a6a1000200241b80d6a41186a2001290300370300200241b80d6a41106a200b290300370300200241b80d6a41086a200d290300370300200220022903c00a3703b80d4100210b2002410036029810200241b80d6a412020024198106a100521010240200228029810220d417f460d002001450d00200241c00a6a200d4120200d4120491b220b6a410041004120200b6b200b411f4b1b10cd041a200241c00a6a2001200b10ce041a200d411f4d0d07200241e00a6a41186a220b200241c00a6a41186a290300370300200241e00a6a41106a220d200241c00a6a41106a290300370300200241e00a6a41086a220e200241c00a6a41086a290300370300200220022903c00a3703e00a2001102920024198106a41186a200b29030037030020024198106a41106a200d29030037030020024198106a41086a200e290300370300200220022903e00a370398104101210b0b412810272233450d072033200b3a0004203341b8d6c5003602002033200229039810370005203320022f00b00b3b00252033410d6a20024198106a41086a2201290300370000203341156a20024198106a41106a220b2903003700002033411d6a20024198106a41186a220d290300370000203341276a200241b00b6a41026a2d00003a00002002420037028c0d2002418883c0003602880d200241003602a80d200242083703a00d200241b80c6a411c6a200241880d6a360200200241b80c6a41186a200241b00d6a360200200241003602c80c200241f4f9c4003602bc0c200220033602b80c2002200241a00d6a3602cc0c2002200241b00d6a3602c40c2002200241b00d6a3602c00c20024198106a200241b80c6a108b0202400240024020022d00d810220e4102470d00200241023a00f80d0c010b200241f80b6a41386a220f20024198106a41386a290300370300200241f80b6a41306a221020024198106a41306a290300370300200241f80b6a41286a220520024198106a41286a290300370300200241f80b6a41206a220c20024198106a41206a290300370300200241f80b6a41186a2221200d290300370300200241f80b6a41106a220d200b290300370300200241f80b6a41086a220b2001290300370300200241e00a6a41086a2201200241e1106a2222290000370300200241ef0a6a2213200241e8106a29000037000020022002290398103703f80b200220022900d9103703e00a200241d4106a200f290300370200200241cc106a2010290300370200200241c4106a2005290300370200200241bc106a200c29030037020020024198106a411c6a202129030037020020024198106a41146a200d290300370200200241a4106a200b290300370200200241013602c80c200220022903f80b37029c10200241b00b6a20024198106a41c40010ce041a200241003602981020024198106a410472200241b00b6a41c40010ce041a20024198106a41c8006a200e3a0000202220022903e00a370000200241e9106a2001290300370000200241f0106a2013290000370000200241b80d6a200241b80c6a41146a20024198106a10950320022d00f80d4102470d010b20031029410821344100213541082105410821174100210c0c0e0b20024198106a200310d70341c80010272234450d082034200241b80d6a41c80010ce041a200241d80c6a41186a200241b80c6a41186a290300370300200241d80c6a41106a200241b80c6a41106a290300370300200241d80c6a41086a200241b80c6a41086a290300370300200220022903b80c3703d80c20024198106a200241d80c6a108b02024020022d00d81022054102470d004101210c410121350c0c0b20024198106a41046a2103200241e1106a210d20024198106a410472212e200241ec0c6a2136200241d9106a210e20022802e80c21374102210f41c800210b410021014101213502400340200241f80b6a41386a221020024198106a41386a290300370300200241f80b6a41306a220c20024198106a41306a290300370300200241f80b6a41286a222120024198106a41286a290300370300200241f80b6a41206a222220024198106a41206a290300370300200241f80b6a41186a221320024198106a41186a290300370300200241f80b6a41106a220420024198106a41106a290300370300200241f80b6a41086a221620024198106a41086a290300370300200241e00a6a41086a2217200e41086a290000370300200241e00a6a410f6a222d200e410f6a29000037000020022002290398103703f80b2002200e2900003703e00a200341386a2010290300370200200341306a200c290300370200200341286a2021290300370200200341206a2022290300370200200341186a2013290300370200200341106a2004290300370200200341086a2016290300370200200320022903f80b3702002002203720016a221041016a3602e80c200241b00b6a20024198106a41c40010ce041a2002201036029810202e200241b00b6a41c40010ce041a200d20022903e00a370000200d41086a2017290300370000200d410f6a202d290000370000200220053a00e010200241b80d6a203620024198106a10950320022d00f80d4102460d0120024198106a200241b80d6a41c80010ce041a0240200141016a22102035470d00200241b00b6a20022802d80c20022802dc0c280210110000201041016a22052010490d15200f20052005200f491b2235ad42c8007e2206422088a70d152006a722054100480d15024002402001417f470d002005102721340c010b2034200b2005102821340b2034450d0c0b2034200b6a20024198106a41c80010ce041a200f41026a210f200b41c8006a210b20024198106a200241d80c6a108b022010210120022d00d81022054102460d0c0c000b0b200141016a210c203421050c0c0b41044101102a000b41084101102a000b20214101102a000b20214101102a000b418f89c3004133104e000b41284104102a000b418f89c3004133104e000b41284104102a000b41c8004108102a000b20054108102a000b201041016a210c0b20342105200241023a00f80d0b20022802d80c220120022802dc0c220328020011010002402003280204450d00200110290b200521170b200241b80d6a2033109303024002400240024020022802d80d222e450d00200241b00b6a41017221360240024002400240034020022802e00d211320022802dc0d2137200241d80c6a41186a2238200241b80d6a41186a290300370300200241d80c6a41106a2239200241b80d6a41106a290300370300200241d80c6a41086a223a200241b80d6a41086a290300370300200220022903b80d3703d80c200241b00b6a200241d80c6a108c02024002400240024020022d00b00b4101460d00200241003602b8100c010b200241f80b6a41186a203641186a290000370300200241f80b6a41106a203641106a290000370300200241f80b6a41086a203641086a290000370300200220362900003703f80b20024198106a200241f80b6a108d0220022802b81022030d010b420021194200211a0c010b20024198106a41086a290300211a200229039810211920022802bc10450d00200310290b2013ad42c8007e2206422088a70d062006a72203417f4c0d0602400240024020030d00410821160c010b200310272216450d010b02400240201341057422030d00410021220c010b202e20036a212d41002122202e210403402004220e41206a2104200241880d6a2103200228028c0d2110024003402003280200220f41086a2101200f2f0106222141057421034100210b0240024003402003450d01200e2001412010d004220d450d02200341606a2103200b41016a210b200141206a2101200d417f4a0d000b200b417f6a21210b2010450d022010417f6a2110200f20214102746a4194036a21030c010b0b200c200f200b4102746a41e8026a220328020022014d0d052005200141c8006c6a22012903102106200141186a290300210a200241d0036a41b18ac0004116108601200241c0036a20022903d803200241d0036a41106a290300427f420010d404200c200328020022014d0d06200241b0036a2019201a20022903c003420020022802d003220b1b221442012014420156200241c0036a41086a2903004200200b1b22144200522014501b220b1b20144200200b1b10d4042005200141c8006c6a220141186a427f200a200620022903b0037c2214200654220bad7c2218200b2018200a54201420065a1b220b1b3703002001427f2014200b1b370310200241e00a6a41186a2201200e41186a290000370300200241e00a6a41106a220b200e41106a290000370300200241e00a6a41086a220d200e41086a2900003703002002200e2900003703e00a2003280200210e024020132022470d00201341016a22032013490d122013410174220f20032003200f491b2203ad42c8007e2206422088a70d122006a7220f4100480d120240024020130d00200f102721160c010b2016201341c8006c200f102821160b2016450d08200321130b2016202241c8006c6a220342003703002003200e360220200341186a4200370300200341106a4200370300200341086a4200370300200320022903e00a3702242003412c6a200d290300370200200341346a200b2903003702002003413c6a2001290300370200202241016a21220b2004202d470d000b0b200241c00a6a41186a22032038290300370300200241c00a6a41106a22012039290300370300200241c00a6a41086a220b203a290300370300200220022903d80c3703c00a20024198036a41b18ac000411610860120024188036a20022903a00320024198036a41106a290300427f420010d404200241f8026a2019201a2002290388034200200228029803220d1b22064201200642015620024188036a41086a2903004200200d1b22064200522006501b220d1b20064200200d1b10d404200241b80c6a41086a220d200b290300370300200241b80c6a41106a220b2001290300370300200241b80c6a41186a22012003290300370300200220022903c00a3703b80c20022903f802210602402037450d00202e10290b2016450d0620024198106a41186a220e200129030037030020024198106a41106a220f200b29030037030020024198106a41086a220b200d290300370300200220022903b80c37039810024020022802a80d220120022802a40d470d00200241b80d6a203310d70320022802a40d220320022802a80d220d6b417f20022802b80d221041016a222120212010491b22104f0d00200d20106a2210200d490d0f2003410174220d20102010200d491b220dad42d0007e220a422088a70d0f200aa722104100480d0f0240024020030d002010102721030c010b20022802a00d200341d0006c2010102821030b2003450d062002200d3602a40d200220033602a00d0b20022802a00d200141d0006c6a22032016360220200320022903981037022c200341286a2022360200200341246a2013360200200342003703102003420037030820032006370300200341186a4200370300200341346a200b2903003702002003413c6a200f290300370200200341c4006a200e2903003702002002200141016a3602a80d200241b80d6a203310930320022802d80d222e0d010c060b0b20034108102a000b41e086c3002001200c1037000b41acf2c2002001200c1037000b200f4108102a000b20104108102a000b2033102902400240200c2031410420321b22034101200341014b1b4f0d0002402035450d00203410290b024020022802a80d2203450d00200341d0006c210120022802a00d41206a210303400240200341046a280200450d00200328020010290b200341d0006a2103200141b07f6a22010d000b0b024020022802a40d0d00410021130c020b20022802a00d1029410021130c010b200c202f410020301b2203200c2003491b223341ffffff3f712033470d0120334105742203417f4c0d01024002400240024020030d00410121130c010b200310272213450d010b2033ad422c7e2206422088a70d032006a72203417f4c0d0302400240024020030d00410421320c010b200310272232450d010b024020330d004100213a4100213b0c030b2005200c41c8006c22386a211620024198106a41186a212e20024198106a41106a213620024198106a41086a21374100212d2033213b03400240200c450d002038210303400240201741c0006a2d00000d00200241e8026a427f427f201741106a290300220642012006420156201741186a29030022064200522006501b22011b2006420020011b10d4042017200241e8026a41086a290300370308201720022903e8023703000b201741c8006a2117200341b87f6a22030d000b0b20022802a00d220d20022802a80d222141d0006c6a21040240024002400240024002402021450d00200d210e03400240200e2802282203450d00200341c8006c210b200e28022041206a21030340200c200328020022014d0d0402402005200141c8006c6a22012d00400d002001290310220a200141186a290300221484500d00200241d8026a200e29030022064200428080808010420010d304200241a8026a420042002006420010d304200241c8026a427f20022903d802200e41086a290300220642ffffffff0f8320065220022903b00242005272200241d8026a41086a2903002218200642208620022903a8027c7c220620185472220f1b427f2006200f1b200a201410d404200241b8026a200e41146a350200200e41186a290300220642208684200642208820022903c802200241c8026a41086a29030010d3042001427f2001290300220620022903b8027c220a200a200654220f200141086a22102903002206200241b8026a41086a2903007c200fad7c220a200654200a2006511b220f1b3703002010427f200a200f1b3703000b200341c8006a2103200b41b87f6a220b0d000b0b200e41d0006a220e2004470d000b0b202d41016a213a2005200c41c8006c6a210e203821012005210303402003210b02400240200e20036b41d8014d0d00200b41c0006a2d00000d01200b41c8006a21030c070b0340024020010d00202d213a0c0c0b200141b87f6a2101200b41c0006a210f200b41c8006a2203210b200f2d00000d000b200341b87f6a210b0c060b200b4188016a2d0000450d03200b41d0016a2d0000450d02200141e07d6a2101200b41a0026a2103200b4198026a2d00000d000b410321010c030b41acf2c2002001200c1037000b200b41d8016a2103410221010c010b200b4190016a2103410121010b200b200141c8006c6a210b0b02402003200e460d00200b41086a2903002106200b290300210a0340200341c8006a21010240200341c0006a2d00000d00200341086a2903002214200620032903002218200a54201420065420142006511b220e1b21062018200a200e1b210a2003200b200e1b210b0b2001210320162001470d000b0b200b41013a004002402021450d00200b417c6a2110200b41206a21210340200d41d0006a21220240200d2802282201450d00200d2802202103200141c8006c210103400240024020102003460d00200341246a2021412010d0040d010b200d41186a220e2903002106200b41086a220f290300210a2003200b2903002214200d29031022187d3703002003200a20067d2014201854ad7d370308200b2903002106200e200f290300370300200d20063703100b200341c8006a2103200141b87f6a22010d000b0b2022210d20222004470d000b0b202e200b41386a2900003703002036200b41306a2900003703002037200b41286a2900003703002002200b2900203703981002400240203b202d470d00202d4101742203203a203a2003491b223b41ffffff3f71203b470d0e203b41057422034100480d0e02400240202d0d002003102721130c010b2013202d4105742003102821130b2013450d010b2013202d4105746a2203200229039810370000200341186a202e290300370000200341106a2036290300370000200341086a203729030037000020052117203a212d203a20334f0d040c010b0b20034101102a000b20034104102a000b20034101102a000b0240024020022802a80d22030d00410021360c010b20022802a00d2222200341d0006c6a212e2013203a4105746a210e410021360340200220222f002c3b01b80d20022022412e6a2d00003a00ba0d20022022413f6a290000370398102002202241c4006a29000037009d10024020222802282203450d002022280220220f200341c8006c6a21042022413b6a2800002137202241376a2800002138202241336a28000021392022412f6a28000021312022412c6a21054100210c4108212141002110024002400340200f220d41246a2101200d41c8006a210f201321030240024003400240200e20036b41e0004b0d002003200e460d030340024020012003470d002003210b0c040b024020032001412010d0040d002003210b0c040b200e200341206a2203470d000c040b0b024020032001470d002003210b0c020b024020032001412010d0040d002003210b0c020b200341206a220b2001460d01200b2001412010d004450d01200341c0006a220b2001460d01200b2001412010d004450d01200341e0006a220b2001460d0120034180016a2103200b2001412010d0040d000b0b2005200b460d00200b2005412010d004450d000240024020222903102218200d290300220a85202241186a2903002214200d41086a2903002206858450450d0042002106428080808010210a0c010b20024198026a200a4200428080808010420010d30420024188026a42004200200a420010d3040240200642ffffffff0f832006522002290390024200527220024198026a41086a290300221920064220862002290388027c7c221a201954724101470d000240201842208820144220868422182014422088221484500d00200241e8016a200a20062018201410d404200241e8016a41086a290300210620022903e801210a0c020b41bcf2c2001058000b200241f8016a200229039802201a20184201201842015620144200522014501b22031b2014420020031b10d404200241f8016a41086a290300210620022903f801210a0b200d200a370310200d41186a20063703002002200d2f00243b01900b2002200d41266a2d00003a00920b2002200d41376a2900003703800b2002200d413c6a2900003700850b200d41336a2800002101200d412f6a280000210b200d412b6a2800002116200d41276a280000210d0240200c2010470d00200c41016a2203200c490d10200c4101742217200320032017491b2203ad42307e2214422088a70d102014a722174100480d1002400240200c0d002017102721210c010b2021200c41306c2017102821210b2021450d032003210c0b20022d00920b211720022f01900b212d2021201041306c6a2203200136000f2003200b36000b200320163600072003200d3600032003202d3b0100200341026a20173a00002003200a370320200341286a2006370300200320022903800b370013200341186a20022900850b370000201041016a21100b200f2004470d000b02402010450d0002400240201041306c22010d00420021064200210a0c010b202141206a2103420021064200210a0340200341086a290300200a7c2003290300220a20067c2206200a54ad7c210a200341306a2103200141506a22010d000b0b200241d8016a420042808080801020067d22142014428080808010564200200a200642808080801056ad7c7d22064200522006501b22031b22194200200620031b22062010ad221a420010d40420022903d801211402402019201a5441002006501b0d00200241d8016a41086a2903002118202141206a21032010210103402003427f2003290300220620147c220a200a200654220b200341086a220d290300220620187c200bad7c220a200654200a2006511b220b1b370300200d427f200a200b1b370300200341306a21032001417f6a22010d000b0b200241c8016a20142006201a200610d3040240201920022903c8017da7220d450d004100210303402021200320107041306c6a2201427f2001290320220642017c220a200a200654220b200141286a22012903002214200bad7c2218201454200a20065a1b220b1b3703202001427f2018200b1b370300200341016a2203200d490d000b0b200220022f01b80d3b01ac0b200220022d00ba0d3a00ae0b20022002290398103703980b2002200229009d1037009d0b024020332036470d00203341016a22032033490d0f20334101742201200320032001491b2203ad422c7e2206422088a70d0f2006a722014100480d0f0240024020330d002001102721320c010b20322033412c6c2001102821320b2032450d03200321330b20022d00ae0b210120022f01ac0b210b20322036412c6c6a2203203736000f2003203836000b20032039360007200320313600032003200b3b0100200341026a20013a0000200320022903980b370013200341186a200229009d0b370000200320103602282003200c36022420032021360220203641016a21360c030b200c450d02202110290c020b20174108102a000b20014104102a000b202241d0006a2222202e470d000b0b02402035450d00203410290b024020022802a80d2203450d00200341d0006c210120022802a00d41206a210303400240200341046a280200450d00200328020010290b200341d0006a2103200141b07f6a22010d000b0b20022802a40d450d0020022802a00d10290b20022802900d210f20022802880d21010240200228028c0d2203450d00034020012802940321012003417f6a22030d000b0b0240200f450d004100210b410021030340200f417f6a210f02400240200320012f01064f0d00200341016a21030c010b02400240200128020022030d00200bad21064100210d410021030c010b2001330104422086200bad8421064101210d0b200110292006a7210b024002402006422088a7220e20032f01064f0d00200321010c010b034002400240200328020022010d00200bad2106410021010c010b200d41016a210d2003330104422086200bad8421060b200310292006a7210b200121032006422088a7220e20012f01064f0d000b0b200e41027420016a4198036a28020021010240200d417f6a2203450d00034020012802940321012003417f6a22030d000b0b410021030b200f0d000b0b02402001418883c000460d0020012802002103200110292003450d0020032802002101200310292001450d00024020012802002203450d00034020011029200321012003280200220b2103200b0d000b0b200110290b024020130d00200241086a41c8f9c4004111108601410021130c030b2036412c6c2203412c6e213c41002117024002400240024020030d004108213d4100213c0c010b203c41ffffff1f71203c470d0a203c41067422014100480d0a20011027223d450d010b024002402032203220036a2237460d00200241b80d6a410172210e41002117203d210c203221050340200241c00a6a41186a2216200541186a290200370300200241c00a6a41106a222d200541106a290200370300200241c00a6a41086a222e200541086a290200370300200220052902003703c00a200241b80d6a2005108c02024002400240024020022d00b80d4101460d00200241003602b8100c010b200241b00b6a41186a200e41186a290000370300200241b00b6a41106a200e41106a290000370300200241b00b6a41086a200e41086a2900003703002002200e2900003703b00b20024198106a200241b00b6a108d0220022802b81022030d010b4200211a4200211b0c010b20024198106a41086a290300211b200229039810211a20022802bc10450d00200310290b2005280220210b4100210d024002402005280228222141306c220f0d0041082104410021210c010b202141ffffff1f712021470d0d202141067422034100480d0d200310272204450d030b2005412c6a21220240200b200b200f6a460d004100210d200421030340200b220141286a290300210a200141206a2903002106200241b80d6a2005108c02024002400240024020022d00b80d4101460d00200241003602b8100c010b200241b00b6a41186a200e41186a290000370300200241b00b6a41106a200e41106a290000370300200241b00b6a41086a200e41086a2900003703002002200e2900003703b00b20024198106a200241b00b6a108d0220022802b810220b0d010b42002118420021190c010b20024198106a41086a2903002119200229039810211820022802bc10450d00200b10290b200141306a210b200241b0016a41b18ac000411610860120024188016a20022903b801200241b0016a41106a290300427f420010d404200241e8006a20182019200229038801420020022802b00122101b22144201201442015620024188016a41086a290300420020101b22144200522014501b22101b2014420020101b10d40420024198016a41b18ac0004116108601200241f8006a20022903a00120024198016a41106a290300427f420010d404200241386a200a420020022903682214420010d304200241d8006a200642002014420010d304200241286a420042002006420010d304200241c8006a2002290378420020022802980122101b221442012014420156200241f8006a41086a290300420020101b22144200522014501b22101b2014420020101b427f200235025c200241d8006a41086a2903002218200229033820022903287c7c221442208684200229034020022903308442005220142018547222101b42ffffffff0f201442208820101b10d304200320063703002003200a370308200341286a200141186a290300370300200341206a200141106a290300370300200341186a200141086a290300370300200341106a2001290300370300200341386a200241c8006a41086a290300370300200341306a2002290348370300200341c0006a2103200d41016a210d200f41506a220f0d000b0b200c201a370300200c201b370308200c2004360230200c41386a200d360200200c41346a2021360200200c20022903c00a370310200c41186a202e290300370300200c41206a202d290300370300200c41286a2016290300370300201741016a2117200c41c0006a210c2022210520222037470d000b0b200242003702940a2002418883c0003602900a024002400240203a450d002013203a4105746a213120024198106a410272213e200241c00a6a41136a2134200241e00a6a41136a213f200241b80d6a4101722121201321050340200241b80d6a2005108c02024002400240024020022d00b80d4101460d00200241003602b8100c010b200241b00b6a41186a202141186a290000370300200241b00b6a41106a202141106a290000370300200241b00b6a41086a202141086a290000370300200220212900003703b00b20024198106a200241b00b6a108d0220022802b81022030d010b420021064200210a0c010b20024198106a41086a290300210a200229039810210620022802bc10450d00200310290b200241b00b6a41186a2222200541186a290000370300200241b00b6a41106a2204200541106a290000370300200241b00b6a41086a2216200541086a290000370300200220052900003703b00b0240024002400240024002400240024020022802900a220e418883c000460d0020022802940a210f0c010b200241b80d6a410041e00210cd041a20024198106a410041900410cd041a41f8061027220e450d014100210f200e41003b0106200e4100360200200e41086a200241b80d6a41e00210ce041a200e41e8026a20024198106a41900410ce041a200241003602940a2002200e3602900a0b200541206a210502400340200e41086a2101200e41066a210c200e2f0106221041057421034100210b024003402003450d01200241b00b6a2001412010d004220d450d03200341606a2103200b41016a210b200141206a2101200d417f4a0d000b200b417f6a21100b0240200f450d00200f417f6a210f200e20104102746a41f8066a280200210e0c010b0b200241b80c6a41186a22032022290300370300200241b80c6a41106a20042903002214370300200241b80c6a41086a20162903002218370300200220022903b00b22193703b80c200220022802980a41016a3602980a200241f80b6a41106a22302014370300200241f80b6a41086a22402018370300200241f80b6a41186a22412003290300370300200220193703f80b200c2f01002201410b490d04200241b80d6a410041e00210cd041a20024198106a410041900410cd041a41f80610272203450d02200341003b010620034100360200200341086a200241b80d6a41e00210ce04210b200341e8026a20024198106a41900410ce04210d200241e00a6a41086a2242200e41d0016a290000370300200241e00a6a41106a2243200e41d8016a290000370300200241e00a6a41186a2244200e41e0016a29000037030020024198106a41086a222d200e4190056a29030037030020024198106a41106a222e200e4198056a29030037030020024198106a41186a2237200e41a0056a29030037030020024198106a41206a2238200e41a8056a29030037030020024198106a41286a2239200e41b0056a2903003703002002200e2900c8013703e00a2002200e2903880537039810200b200e41e8016a200e2f010641796a220141057410ce04210b200d200e41b8056a200141306c10ce04210d200e41063b0106200320013b0106200220022f01e00a3b01ac0b200220022d00e20a3a00ae0b2002203f2900003703980b2002203f41056a224529000037009d0b20022800e30a214620022800e70a214720022800eb0a214820022800ef0a2149200241b80d6a41286a224a2039290300370300200241b80d6a41206a224b2038290300370300200241b80d6a41186a224c2037290300370300200241b80d6a41106a224d202e290300370300200241b80d6a41086a224e202d29030037030020022002290398103703b80d0240024020104107490d002010410574200b6a41c07e6a200b201041796a220f4105746a220b200141ffff0371200f6b41057410cf041a200b41186a2041290300370000200b41106a2030290300370000200b41086a2040290300370000200b20022903f80b370000201041306c200d6a220141e07d6a200141b07d6a2201200341066a220c2f0100200f6b41306c10cf041a200141186a200a370300200120063703102001200a37030820012006370300200141286a4100360200200142083703200c010b200e41086a20104105746a220141206a2001200c2f010020106b41057410cf041a200141186a2041290300370000200141106a2030290300370000200141086a2040290300370000200120022903f80b370000200e41e8026a201041306c6a220141306a2001200c2f010020106b41306c10cf041a200141186a200a370300200120063703102001200a37030820012006370300200141286a4100360200200142083703200b200c200c2f010041016a3b0100200241a00d6a41026a220120022d00ae0b3a00002016204e2903003703002004204d2903003703002022204c290300370300200241b00b6a41206a224f204b290300370300200241b00b6a41286a2250204a290300370300200220022f01ac0b3b01a00d200220022903980b3703c00a2002200229009d0b3700c50a200220022903b80d3703b00b200241d80c6a41286a22512050290300370300200241d80c6a41206a2252204f290300370300200241d80c6a41186a22532022290300370300200241d80c6a41106a22542004290300370300200241d80c6a41086a22552016290300370300200220022903b00b3703d80c200220022f01a00d3b01900b200220012d00003a00920b200220022903c00a3703800b200220022900c50a3700850b0240200e280200220f0d00200241900a6a21012003210b0c060b200e2f0104213541002156200321570340200241b00d6a41026a225820022d00920b3a0000200220022f01900b3b01b00d200220022903800b3703a00d200220022900850b3700a50d20502051290300370300204f2052290300370300202220532903003703002004205429030037030020162055290300370300200220022903d80c3703b00b203541ffff03712110024002400240200f2f01062203410b490d00203e410041a20710cd041a41a8071027220d450d07200d4100360200200d41046a20024198106a41a40710ce041a2044200f41e0016a2900003703002043200f41d8016a2900003703002042200f41d0016a2900003703002002200f2900c8013703e00a2039200f41b0056a2903003703002038200f41a8056a2903003703002037200f41a0056a290300370300202e200f4198056a290300370300202d200f4190056a2903003703002002200f2903880537039810200d41086a200f41e8016a200f2f0106220141796a220341057410ce042159200d41e8026a200f41b8056a200341306c10ce04215a200d41f8066a200f4194076a2001417a6a220c41027410ce04212f200f41063b0106200d20033b01060240200c450d0041002103202f210103402001280200220b20033b0104200b200d360200200141046a2101200c200341016a2203470d000b0b204a2039290300370300204b2038290300370300204c2037290300370300204d202e290300370300204e202d29030037030020022002290398103703b80d200220022f01e00a3b01ac0b200220022d00e20a3a00ae0b20022900e30a210620022900eb0a210a2002204529000037009d0b2002203f2900003703980b203420022903980b370000203441056a220c200229009d0b370000200220022d00ae0b3a00c20a200220022f01ac0b3b01c00a2002200a3700cb0a200220063700c30a2039204a2903003703002038204b2903003703002037204c290300370300202e204d290300370300202d204e290300370300200220022903b80d37039810203541ffff037122014107490d0120592010417a6a220b4105746a2059201041796a22034105746a2201200d2f010620036b41057410cf041a200141186a20022900a50d3700002001204936000f2001204836000b2001204736000720012046360003200141026a20582d00003a0000200120022f01b00d3b0000200120022903a00d370013201041306c205a6a220141e07d6a200141b07d6a2201200d2f0106223520036b41306c10cf041a200141286a2050290300370300200141206a204f290300370300200141186a2022290300370300200141106a2004290300370300200141086a2016290300370300200120022903b00b370300200d203541016a22013b010620104102742235202f6a416c6a202f200b4102746a2210200141ffff0371200b6b41027410cf041a20102057360200200b200d2f010622104b0d02200d20356a41e0066a210103402001280200220b200341016a22033b0104200b200d360200200141046a210120032010490d000c030b0b200f41086a2201201041016a220b4105746a200120104105746a2201200320106b220d41057410cf041a2001204936000f2001204836000b2001204736000720012046360003200141026a20582d00003a0000200120022f01b00d3b0000200120022903a00d370013200141186a20022900a50d370000200f201041306c6a22014198036a200141e8026a220c200d41306c10cf041a20014190036a205029030037030020014188036a204f29030037030020014180036a2022290300370300200141f8026a2004290300370300200141f0026a2016290300370300200c20022903b00b370300200f200341016a22033b01062010410274200f41f8066a22016a41086a2001200b4102746a2201200341ffff0371200b6b41027410cf041a2001205736020002402010200f2f010622034f0d002057200b3b01042057200f360200200b20034f0d002003417f6a210d200f200b417f6a22034102746a4180076a210103402001280200220b200341026a3b0104200b200f360200200141046a2101200d200341016a2203470d000b0b41001a200241900a6a1a200e1a0c090b200f41086a2203201041016a220b4105746a200320104105746a2203200f2f0106223520106b222f41057410cf041a2003204936000f2003204836000b2003204736000720032046360003200341026a20582d00003a0000200320022f01b00d3b0000200320022903a00d370013200341186a20022900a50d370000200f41e8026a201041306c6a220341306a2003202f41306c10cf041a200341286a2050290300370300200341206a204f290300370300200341186a2022290300370300200341106a2004290300370300200341086a2016290300370300200320022903b00b370300200f203541016a22033b01062010410274222f200f41f8066a22356a41086a2035200b4102746a2235200341ffff0371200b6b41027410cf041a203520573602002001200f2f0106220b4f0d00200f202f6a41fc066a2103034020032802002201201041016a22103b01042001200f360200200341046a2103200b2010470d000b0b205641016a21102002419c0d6a41026a220320022d00c20a3a00002040202d2903003703002030202e29030037030020412037290300370300200241f80b6a41206a22012038290300370300200241f80b6a41286a220b2039290300370300200220022f01c00a3b019c0d20022002290398103703f80b200220342900003703880d2002200c29000037008d0d20022800c30a214620022800c70a214720022800cb0a214820022800cf0a21492051200b29030037030020522001290300370300205320412903003703002054203029030037030020552040290300370300200220022903f80b3703d80c200220022f019c0d3b01900b200220032d00003a00920b200220022903880d3703800b2002200229008d0d3700850b0240200f28020022030d00200f1a200241900a6a22011a200d210b0c070b200f2f01042135200241900a6a1a200f1a2003210f200d2157201021560c000b0b200e200b41306c6a22034180036a200a370300200341f8026a2006370300200341f0026a200a370300200341e8026a200637030020034190036a410036020020034188036a220b28020021012003418c036a2802002103200b42083703002001450d052003450d05200110290c050b41f8064108102a000b41f8064108102a000b41a8074108102a000b200e20104105746a220341286a200341086a220b200120106b41057410cf041a200341206a2041290300370000200341186a2030290300370000200341106a2040290300370000200b20022903f80b370000200e201041306c6a22034198036a200341e8026a2201200e2f010620106b41306c10cf041a20034190036a410036020020034188036a420837030020034180036a200a370300200341f8026a2006370300200341f0026a200a37030020012006370300200e200e2f010641016a3b01060c010b203e410041a20710cd041a41a80710272203450d0320034100360200200341046a20024198106a41a40710ce041a20032001280200220d3602f806200120033602002001200128020441016a360204200d41003b0104200d2003360200200320032f0106220d4105746a220141086a20022f01900b3b00002001410a6a20022d00920b3a0000200141176a2049360000200141136a20483600002001410f6a20473600002001410b6a20463600002001411b6a20022903800b370000200141206a20022900850b3700002003200d41306c6a220141e8026a20022903d80c370300200141f0026a2055290300370300200141f8026a205429030037030020014180036a205329030037030020014188036a205229030037030020014190036a2051290300370300200341f8066a200d41016a22014102746a200b360200200320013b0106200b20013b0104200b2003360200200e1a0b20052031470d000b0b20174106742203450d04203d20036a212d203d211603402016450d05024020162802382203450d002016280230222220034106746a2104201641106a212103402022220c41106a210e200c41c0006a2122200241900a6a210320022802940a2110024003402003280200220f41086a2101200f2f0106220541057421034100210b0240024003402003450d01200e2001412010d004220d450d02200341606a2103200b41016a210b200141206a2101200d417f4a0d000b200b417f6a21050b2010450d022010417f6a2110200f20054102746a41f8066a21030c010b0b200f200b41306c6a220341e8026a2201427f20012903002206200c2903307c220a200a2006542201200341f0026a220b2903002206200c41386a220d2903007c2001ad7c220a200654200a2006511b22011b370300200b427f200a20011b37030020024198106a41086a220e202141086a2900003703002021290000210620024198106a41106a220f202141106a29000037030020024198106a41186a2210202141186a2900003703002002200637039810200d2903002106200c290330210a20034188036a210d0240024020034190036a220b28020022012003418c036a280200460d00200d28020021030c010b200141016a22032001490d1120014101742205200320032005491b2205ad42307e2214422088a70d112014a7220c4100480d110240024020010d00200c102721030c010b200d280200200141306c200c102821030b2003450d06200d2003360200200d41046a2005360200200b28020021010b2003200141306c6a220320063703082003200a3703002003200229039810370310200341186a200e290300370300200341206a200f290300370300200341286a2010290300370300200b200b28020041016a3602000b20222004470d000b0b201641c0006a2216202d470d000c050b0b41a8074108102a000b200c4108102a000b20034108102a000b20014108102a000b200241f80b6a41086a22034200370300200242003703f80b41cdf8c4004116200241f80b6a1004200241b80d6a41086a2003290300370300200220022903f80b3703b80d2002410036029810200241b80d6a411020024198106a10052103024002400240200228029810220b417f460d002003450d002002200b3602b40b200220033602b00b20024198106a200241b00b6a102d2002280298102237450d02200241a0106a2802002101200228029c102138200b450d01200310290c010b4100213841012137410021010b024002400240024002400240024020014105742204450d00203721030340410f10272201450d07200141076a4100290091a3443700002001410029008aa3443700002001410f412f10282201450d062001200329000037000f200141276a200341186a220f2900003700002001411f6a200341106a2210290000370000200141176a200341086a2205290000370000200241c00a6a41186a220b4200370300200241c00a6a41106a220d4200370300200241c00a6a41086a220e4200370300200242003703c00a2001412f200241c00a6a1000200241b80d6a41186a220c200b290300370300200241b80d6a41106a2221200d290300370300200241b80d6a41086a2222200e290300370300200220022903c00a3703b80d200241b80d6a4120100c20011029411210272201450d05200141106a41002f00c4a344222e3b0000200141086a41002900bca3442206370000200141002900b4a344220a37000020014112413210282201450d04200120032900003700122001412a6a200f290000370000200141226a20102900003700002001411a6a2005290000370000200b4200370300200d4200370300200e4200370300200242003703c00a20014132200241c00a6a1000200c200b2903003703002021200d2903003703002022200e290300370300200220022903c00a3703b80d200241206a200241b80d6a412010c102200228022421162002280220212d20011029024020164100202d1b22164102490d00411210272201450d04200141106a202e3b0000200141086a20063700002001200a37000020014112413210282201450d03200120032900003700122001412a6a200f290000370000200141226a20102900003700002001411a6a2005290000370000200b4200370300200d4200370300200e4200370300200242003703c00a20014132200241c00a6a1000200c200b2903003703002021200d2903003703002022200e290300370300200220022903c00a3703b80d20022016417f6a36029810200241b80d6a412020024198106a41041003200110290b200341206a2103200441606a22040d000b0b02402038450d00203710290b20022802900a210f024020022802940a2203450d00200321010340200f2802f806210f2001417f6a22010d000b03402003417f6a22030d000b0b024020022802980a22210d00427f2114427f21060c090b02400240200f2f0106450d00200f41e8026a210d200f41086a210e4101210c0c010b02400240200f28020022030d004100210b41002101410021030c010b200f2f0104210b410121010b0240200b20032f0106490d000340200141016a210120032f0104220b200328020022032f01064f0d000b0b2003200b41306c6a41e8026a210d2003200b4105746a41086a210e200b41027420036a41fc066a280200210f4100210c2001417f6a2203450d000340200f2802f806210f2003417f6a22030d000b0b20024198106a41106a212d427f2114427f21060340200d41086a2203290300210a200d2903002118200241b00b6a41186a2222200e41186a290000370300200241b00b6a41106a2204200e41106a290000370300200241b00b6a41086a2216200e41086a2900003703002002200e2900003703b00b200d280228220ead42307e2219422088a70d082019a72201417f4c0d08200d41186a29030021192003290300211a200d290310211b200d290300211f200d2802202103024002400240024002400240024020010d00410821100c010b200110272210450d010b02400240200e0d004100210b0c010b2003200e41306c6a210d4100210b201021010340200120032903003703002001200341086a290300370308200141106a200341106a290300370300200141186a200341186a290300370300200141206a200341206a290300370300200141286a200341286a290300370300200141306a2101200b41016a210b200341306a2203200d470d000b0b20024198106a41186a20193703002002201b3703a8102002201f370398102002200b3602c0102002200e3602bc10200220103602b8102002201a3703a010410f10272203450d01200341076a4100290091a3443700002003410029008aa3443700002003410f412f10282205450d02200520022903b00b37000f200541276a20222903003700002005411f6a2004290300370000200541176a2016290300370000200241c00a6a41186a22034200370300200241c00a6a41106a22014200370300200241c00a6a41086a220b4200370300200242003703c00a2005412f200241c00a6a1000200241b80d6a41186a2003290300370300200241b80d6a41106a2001290300370300200241b80d6a41086a200b290300370300200220022903c00a3703b80d200241003602800c200242013703f80b200220024198106a3602d80c200241d80c6a200241f80b6a10592002202d3602d80c200241d80c6a200241f80b6a105920022802b8102103200220022802c01022013602d80c200241d80c6a200241f80b6a103002402001450d00200141306c210d03400240024020022802fc0b220b20022802800c22016b4120490d0020022802f80b210b0c010b200141206a220e2001490d17200b4101742210200e200e2010491b220e4100480d1702400240200b0d00200e1027210b0c010b20022802f80b200b200e1028210b0b200b450d062002200e3602fc0b2002200b3602f80b0b200b20016a220b41086a200341186a290000370000200b41106a200341206a290000370000200b41186a200341286a2900003700002002200141206a3602800c200b200341106a290000370000200220033602d80c200241d80c6a200241f80b6a1059200341306a2103200d41506a220d0d000b0b20182014542103200a2006512101200a200654210b20022802fc0b210d200241b80d6a412020022802f80b220e20022802800c10030240200d450d00200e10290b2003200b20011b21032021417f6a212120051029024020022802bc10450d0020022802b81010290b200a200620031b21062018201420031b21142021450d0e0240200c200f2f01064f0d00200f200c41306c6a41e8026a210d200f200c4105746a41086a210e200c41016a210c0c060b02400240200f28020022030d004100210b41002101410021030c010b200f2f0104210b410121010b200b20032f0106490d040340200141016a210120032f0104220b200328020022032f01064f0d000c050b0b20014108102a000b410f4101102a000b412f4101102a000b200e4101102a000b2003200b41306c6a41e8026a210d2003200b4105746a41086a210e200b41027420036a41fc066a280200210f4100210c2001417f6a2203450d000340200f2802f806210f2003417f6a22030d000c010b0b0b41324101102a000b41124101102a000b41324101102a000b41124101102a000b412f4101102a000b410f4101102a000b418f89c3004133104e000b1039000b200241f80b6a41086a22034200370300200242003703f80b41c8f9c4004111200241f80b6a1004200241b80d6a41086a22012003290300370300200220022903f80b3703b80d200220063703a0102002201437039810200241b80d6a411020024198106a4110100320034200370300200242003703f80b41cdf8c4004116200241f80b6a100420012003290300370300200220022903f80b3703b80d200241003602a01020024201370398102002203a3602b00b200241b00b6a20024198106a103002400240203a0d0020022802a0102101200228029c10210e200228029810210f0c010b203a4105742110410020022802a01022016b210d200228029810210f200228029c10210e2013210303400240200e200d6a411f4b0d00200141206a220b2001490d08200e4101742205200b200b2005491b220b4100480d0802400240200e0d00200b1027210f0c010b200f200e200b1028210f0b200f450d07200b210e0b200f20016a220b2003290000370000200b41186a200341186a290000370000200b41106a200341106a290000370000200b41086a200341086a290000370000200d41606a210d200141206a2101200341206a2103201041606a22100d000b2002200e36029c10200220013602a0102002200f360298100b200241b80d6a4110200f200110030240200e450d00200f10290b20022802980a211020022802900a210b024020022802940a2203450d000340200b2802f806210b2003417f6a22030d000b0b02402010450d004100210d410021030340024002402003200b2f01064f0d00200b200341306c6a2201418c036a280200210f20014188036a2802002101200341016a21030c010b02400240200b28020022030d00200dad21064100210e410021030c010b200b330104422086200dad8421064101210e0b200b10292006a7210d024002402006422088a7220f20032f01064f0d00200321010c010b034002400240200328020022010d00200dad2106410021010c010b200e41016a210e2003330104422086200dad8421060b200310292006a7210d200121032006422088a7220f20012f01064f0d000b0b200f41027420016a41fc066a280200210b2001200f41306c6a2203418c036a280200210f20034188036a28020021010240200e417f6a2203450d000340200b2802f806210b2003417f6a22030d000b0b410021030b2001450d012010417f6a21100240200f450d00200110290b20100d000b0b0240200b418883c000460d00200b2802002103200b10292003450d0020032802002101200310292001450d00024020012802002203450d00034020011029200321012003280200220b2103200b0d000b0b200110290b02402017450d0020174106742101203d41306a210303400240200341046a280200450d00200328020010290b200341c0006a2103200141406a22010d000b0b203aad21060240203c450d00203d10290b20064220862106203bad210a02402036450d002036412c6c2101203241206a210303400240200341046a280200450d00200328020010290b2003412c6a2103200141546a22010d000b0b2006200a8421062033450d00203210290b02402012452015720d00201110290b20130d0102402007450d00200741d0006c2101200841c0006a210303400240200341046a280200450d00200328020010290b200341d0006a2103200141b07f6a22010d000b0b2009450d00200810290b200041003602000c010b200020063702042000201336020002402007450d00200741d0006c2101200841c0006a210303400240200341046a280200450d00200328020010290b200341d0006a2103200141b07f6a22010d000b0b2009450d00200810290b200241c0176a24000f0b200b4101102a000b102b000b418f89c3004133104e000b9f0501067f230041c0046b22012400200141b8036a41086a22024200370300200142003703b8034188d4c3004116200141b8036a100420014190016a41086a2002290300370300200120012903b80337039001200141003602b80320014190016a4110200141b8036a10052103024002400240024020012802b8032204417f470d00411221020c010b200120043602ac02200120033602a802200141b8036a200141a8026a103c20012802b8034112460d02200141b0026a200141b8036a41880110ce041a200141003a00a001200141a0016a20012802a802220520012802ac022202410047220610ce041a20022006490d012001200220066b3602ac022001200520066a3602a802024002402002450d0020012d00a00122054103490d010b200141b0026a103d0c030b20012802b0022102200141a0016a200141b0026a41047241840110ce041a20024112460d02200141b8036a200141a0016a41840110ce041a02402004450d00200310290b20014190016a4110100c0b2001410c6a200141b8036a41840110ce041a0240024020024112470d00419ed4c30021060c010b200141b0026a2001410c6a41840110ce041a200141013a00a001200141b8036a41086a22064200370300200142003703b80341f586c500411f200141b8036a100420014190016a41086a2006290300370300200120012903b8033703900120014190016a4110200141a0016a41011003200641023a0000200141053a00b8034100210641b8d6c5004100200141b8036a108801200120023602b803200141b8036a410472200141b0026a41840110ce041a200141a0016a20004280ce187c200141b8036a20054280af1a10b50320012802a0014101470d0020012802a40121060b200141c0046a240020060f0b20062002103e000b418f89c3004133104e000bb81304077f137e017f047e23004180036b22012400200141c0016a41086a22024200370300200142003703c00141b7d2c3004115200141c0016a1004200141d8026a41086a2002290300370300200120012903c0013703d802200141003602c001200141d8026a4110200141c0016a100521020240024002400240024002400240024002400240024020012802c0012203417f460d002002450d002001200336022c20012002360228200141c0016a200141286a103f20012802c0012204450d02200141c8016a280200210520012802c40121062003450d01200210290c010b4108210441002105410021060b0240200541b0016c22020d00200141003602302001200436022c200120043602282001200141f8026a3602340c080b200420026a2103200141c0016a20042802880110b603200441b0016a21020240024020012802d00122070d0042002108420021090c010b200141186a20012903c001200141c0016a41086a290300200141d8016a350200420010d304200141186a41086a29030021092001290318210820012802d401450d00200710290b200141013602302001200336022c200120023602282001200141f8026a3602342004450d072004ad422086210a024020022003460d00200541b0016c41d07e6a21034201210b0340200141c0016a20024188016a28020010b6030240024020012802d00122070d004200210c4200210d0c010b200141086a20012903c001200141c0016a41086a29030020013502d801420010d304200141086a41086a290300210d2001290308210c20012802d401450d00200710290b02402008200c562009200d562009200d511b0d002002ad422086200b84210a200c2108200d21090b200241b0016a2102200b42017c210b200341d07e6a22030d000b0b200a428080808010540d072005200aa722024d0d0120042005417f6a220741b0016c6a22034180016a290300210d20034188016a290300210920034190016a290300210b20034198016a290300210c200341e0006a2903002108200341e8006a290300210a200341f0006a290300210e200341f8006a290300210f200341c0006a2903002110200341c8006a2903002111200341d0006a2903002112200341d8006a2903002113200341206a2903002114200341286a2903002115200341306a2903002116200341386a290300211720032903002118200329030821192003290310211a2004200241b0016c6a220241186a221b290300211c200341a8016a290300211d200341a0016a290300211e201b200341186a2903003703002002290310211f2002201a3703102002290308211a200220193703082002290300211920022018370300200241386a2203290200211820032017370200200241306a2203290200211720032016370200200241286a2203290200211620032015370200200241206a2203290200211520032014370200200241d8006a2203290200211420032013370200200241d0006a2203290200211320032012370200200241c8006a2203290200211220032011370200200241c0006a2203290200211120032010370200200241f8006a220329020021102003200f370200200241f0006a2203290200210f2003200e370200200241e8006a2203290200210e2003200a370200200241e0006a2203290200210a2003200837020020024198016a200c37020020024190016a200b37020020024188016a2203280200211b2003200937020020024180016a220329020021092003200d370200200241a0016a201e370200200241a8016a201d370200200141286a41f8006a2010370300200141286a41f0006a200f370300200141286a41e8006a200e370300200141286a41e0006a200a370300200141286a41d8006a2014370300200141286a41d0006a2013370300200141286a41c8006a2012370300200141286a41c0006a2011370300200141286a41386a2018370300200141286a41306a2017370300200141286a41286a2016370300200141286a41206a2015370300200141286a41186a201c370300200141286a4180016a20093703002001201f3703382001201a37033020012019370328200120073602b801200120063602b401200120043602b001200141c0016a41086a22024200370300200142003703c00141b7d2c3004115200141c0016a1004200141d8026a41086a2002290300370300200120012903c0013703d802200141103602c4012001200141d8026a3602c001200141b0016a200141c0016a103302402007450d00200541b0016c41d07e6a21032004210203402002103d200241b0016a2102200341d07e6a22030d000b0b02402006450d00200410290b411310272202450d022002410f6a41002800ecd143360000200241086a41002900e5d143370000200241002900ddd14337000020024113412610282202450d032002201b360013200141c0016a41186a22034200370300200141c0016a41106a22074200370300200141c0016a41086a22044200370300200142003703c00120024117200141c0016a1000200141d8026a41186a2003290300370300200141d8026a41106a2007290300370300200141d8026a41086a2004290300370300200120012903c0013703d802200141003602c001200141d8026a4120200141c0016a1005210320012802c0012207417f460d052003450d05200120033602b001200120073602b401200142003703c801200142003703c001200141c0016a20032007411020074110491b220410ce041a2001200720046b3602b4012001200320046a3602b0012007410f4d0d04200141c8016a290300210920012903c001210d200141c0016a200141b0016a102d20012802c0012207450d0420012902c401210b20031029200141d8026a4120100c200b422088a72104200ba721050c060b418f89c3004133104e000b41ccd2c300200220051037000b41134101102a000b41264101102a000b418f89c3004133104e000b410021070b200210290240024020070d00200141286a103d0c010b024020044105742203450d002007210203402002200d200910ad01200241206a2102200341606a22030d000b0b200141e8016a2009370300200141e0016a200d370300200141d8016a2004360200200141d4016a2005360200200141d0016a2007360200200141cc016a201b360200200141c8016a41013a0000200141053a00c00141b8d6c5004100200141c0016a108801200141c0016a200141286a41880110ce041a200141d8026a20004280ce187c200141c0016a41004280af1a10b50320012802d8024101470d0020012802dc0221020c020b410021020c010b02402005450d00200541b0016c21032004210203402002103d200241b0016a2102200341d07e6a22030d000b0b41dcd2c30021022006450d00200410290b20014180036a240020020bda0604047f017e047f017e230041d0046b22022400024002400240411a10272203450d00200341186a41002f00dbd1433b0000200341106a41002900d3d143370000200341086a41002900cbd143370000200341002900c3d1433700002003411a413410282203450d012003200136001a200241c0026a41186a22014200370300200241c0026a41106a22044200370300200241c0026a41086a22054200370300200242003703c0022003411e200241c0026a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903c002370300200241003602c00220024120200241c0026a1005210102400240024020022802c0022204417f460d002001450d002002200136022020022004360224200242003703c002200241c0026a20012004410820044108491b220510ce041a2002200420056b3602242002200120056a3602200240200441074d0d0020022903c0022106200241c0026a200241206a103c20022802c0022105200241cc036a200241c0026a41047241840110ce041a20054112460d00200241bc016a200241cc036a41840110ce041a20022005360230200241306a410472200241bc016a41840110ce042107200241003a00c002200241c0026a2002280220220820022802242209410047220a10ce041a2009200a490d0620022009200a6b220436022420022008200a6a220a360220024002402009450d0020022d00c00222084103490d010b200241306a103d0c010b200242003703c002200241c0026a200a2004410820044108491b220910ce041a2002200420096b3602242002200a20096a360220200441074b0d02200241306a103d0b418f89c3004133104e000b200041123602080c010b20022903c002210b200241c0026a200741840110ce041a200220022800293602cc0320022002412c6a2800003600cf03200241306a200241c0026a41840110ce041a200220022800cf033600bf01200220022802cc033602bc012001102920002005360208200020063703002000410c6a200241306a41840110ce041a20004198016a20083a000020004190016a200b370200200020022802bc01360099012000419c016a20022800bf013600000b20031029200241d0046a24000f0b411a4101102a000b41344101102a000b200a2009103e000bfc0202047f017e230041d0006b22022400024002400240411310272203450d002003410f6a4100280096d243360000200341086a410029008fd24337000020034100290087d24337000020034113412610282203450d0120032001360013200241306a41186a22014200370300200241306a41106a22044200370300200241306a41086a220542003703002002420037033020034117200241306a1000200241086a41186a2001290300370300200241086a41106a2004290300370300200241086a41086a20052903003703002002200229033037030820024100360230200241086a4120200241306a100521040240024020022802302201417f460d002002200136022c20022004360228200241306a200241286a102d20022802302205450d042002290234210602402001450d00200410290b20002006370204200020053602000c010b20004100360208200042013702000b20031029200241d0006a24000f0b41134101102a000b41264101102a000b418f89c3004133104e000bc80301047f230041c0006b2202240002400240024002400240411010272203450d00200341086a41002900a6d1433700002003410029009ed1433700002001280200210420034110412010282203450d01200320043600102003412041c00010282203450d02200320012900043700142003412c6a2001411c6a290000370000200341246a200141146a2900003700002003411c6a2001410c6a290000370000200241206a41186a22014200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034134200241206a1000200241186a2001290300370300200241106a2004290300370300200241086a200529030037030020022002290320370300410021042002410036022020024120200241206a100521050240024020022802202201417f460d00200241003a0020200241206a20052001410047220410ce041a20012004490d052001450d0620022d0020220141ff0071220441064f0d0620051029200141077621010c010b410021010b20031029200020043a0001200020013a0000200241c0006a24000f0b41104101102a000b41204101102a000b41c0004101102a000b20042001103e000b418f89c3004133104e000b8f0e04017f047e117f087e230041a0036b22052400024002400240024002400240024020040d00420021064200210742002108420021090c010b20054180036a41186a220a420037030020054180036a41106a220b420037030020054180036a41086a220c42003703002005420037038003419ad2c300411d20054180036a1000200541c0026a41186a200a290300370300200541c0026a41106a200b290300370300200541c0026a41086a200c29030037030020052005290380033703c0024100210c200541003602d801200541c0026a4120200541d8016a1005210d024020052802d801220a417f460d0020054180036a200a4120200a4120491b220b6a410041004120200b6b200b411f4b1b10cd041a20054180036a200d200b10ce041a200a411f4d0d02200541d8016a41186a220a20054180036a41186a290300370300200541d8016a41106a220b20054180036a41106a290300370300200541d8016a41086a220c20054180036a41086a29030037030020052005290380033703d801200d102920054190016a41186a200a29030037030020054190016a41106a200b29030037030020054190016a41086a200c290300370300200520052903d801370390014101210c0b41281027220b450d02200b200c3a0004200b41b8d6c500360200200b200529039001370005200b20052f00d8013b0025200b410d6a20054190016a41086a290300370000200b41156a20054190016a41106a290300370000200b411d6a20054190016a41186a290300370000200b41276a200541da016a2d00003a000020054190016a200b10ad0342002108420021094200210642002107024020052d00d0014106460d002004417f6a210e200541d8016a41c0006a210f200541d8016a41206a2110200541d8016a41186a2111200341ff0171211242002106420021074200210842002109034020112007370300200520063703e801200520083703d801200520093703e001201020054190016a41c10010ce04210a02400240200f2002460d00200f2002412010d0040d010b200541e0026a41186a220c200a41186a2213290200370300200541e0026a41106a220d200a41106a2214290200370300200541e0026a41086a2215200a41086a22162902003703002005200a2902003703e002411010272204450d06200441086a41002900a6d1433700002004410029009ed14337000020044110412010282204450d07200420013600102004412041c00010282204450d08200420052903e0023700142004412c6a200c290300370000200441246a200d2903003700002004411c6a201529030037000020054180036a41186a2217420037030020054180036a41106a2218420037030020054180036a41086a2219420037030020054200370380032004413420054180036a1000200541c0026a41186a2017290300370300200541c0026a41106a2018290300370300200541c0026a41086a201929030037030020052005290380033703c002200541c0026a412041b8d6c50041004100100b211a20041029201a417f470d0020052d00b8022104200c2013290000370300200d2014290000370300201520162900003703002005200a2900003703e00202404100417f4101200420124b1b20042012461b41016a41014b0d00200321040b20054180016a200541e0026a10950120054180016a41086a290300211b200529038001211c02400240200441ff01710d002005201c201b420a420010d4042017200c2903003703002018200d29030037030020192015290300370300200520052903e00237038003200541106a200120054180036a4100200e10aa03200541106a41186a290300211d200541106a41086a290300211e2005290320211f2005290310212020052903002221211c200541086a2903002222211b0c010b200541c0006a201b42002004ad42ff01832221420010d304200541d0006a201c42002021420010d3042017200c2903003703002018200d29030037030020192015290300370300200520052903e00237038003200541e0006a200120054180036a2004200e10aa03200541306a42004200201c420010d304427f200541d0006a41086a2903002221200529034020052903307c7c221d2005290348200529033884420052201d2021547222041b2122427f200529035020041b2121200541e0006a41186a290300211d200541e0006a41086a290300211e2005290370211f200529036021200b201b20077c201c20067c2207201c54ad7c201d7c2007201f7c2206200754ad7c2107202220097c202120087c2209202154ad7c201e7c200920207c2208200954ad7c21090b20054190016a200b10ad0320052d00d0014106470d000b0b200b10290b2000200637031020002008370300200041186a200737030020002009370308200541a0036a24000f0b418f89c3004133104e000b41284104102a000b41104101102a000b41204101102a000b41c0004101102a000b8607010d7f230041e0006b220124000240024002400240024002400240411a10272202450d00200241186a41002f00dbd1433b0000200241106a41002900d3d143370000200241086a41002900cbd143370000200241002900c3d1433700002002411a413410282202450d012002200036001a200141c0006a41186a22034200370300200141c0006a41106a22044200370300200141c0006a41086a22054200370300200142003703402002411e200141c0006a1000200141206a41186a2003290300370300200141206a41106a2004290300370300200141206a41086a200529030037030020012001290340370320200141206a4120100c20021029411310272202450d022002410f6a4100280096d243360000200241086a410029008fd24337000020024100290087d24337000020024113412610282202450d0320022000360013200141c0006a41186a22044200370300200141c0006a41106a22054200370300200141c0006a41086a220342003703002001420037034020024117200141c0006a1000200141206a41186a22062004290300370300200141206a41106a22072005290300370300200141206a41086a200329030037030020012001290340370320200141206a4120100c20021029200141c0006a200010a8032001280244210820012802402109024020012802482202450d002002410574210a200921030340200141186a220b200341186a290000370300200141106a220c200341106a290000370300200141086a220d200341086a29000037030020012003290000370300411010272202450d06200241086a41002900a6d1433700002002410029009ed14337000020024110412010282202450d07200220003600102002412041c00010282202450d08200341206a2103200220012903003700142002412c6a200b290300370000200241246a200c2903003700002002411c6a200d2903003700002004420037030020054200370300200141c0006a41086a220b42003703002001420037034020024134200141c0006a10002006200429030037030020072005290300370300200141206a41086a200b29030037030020012001290340370320200141206a4120100c20021029200a41606a220a0d000b0b02402008450d00200910290b200141e0006a24000f0b411a4101102a000b41344101102a000b41134101102a000b41264101102a000b41104101102a000b41204101102a000b41c0004101102a000bfa0201057f230041d0006b22022400024002400240411710272203450d002003410f6a41002900ffd143370000200341086a41002900f8d143370000200341002900f0d14337000020034117412e10282203450d0120032001370017200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a22064200370300200242003703302003411f200241306a1000200241086a41186a2004290300370300200241086a41106a2005290300370300200241086a41086a20062903003703002002200229033037030820024100360230200241086a4120200241306a100521050240024020022802302204417f460d002002200436022c20022005360228200241306a200241286a103b20022802302206450d042002290234210102402004450d00200510290b20002001370204200020063602000c010b20004100360208200042083702000b20031029200241d0006a24000f0b41174101102a000b412e4101102a000b418f89c3004133104e000bec0903037f047e097f23002202210320024180036b416071220224002001411c6a220429020021052004200229039802370200200141146a2204290200210620042002290390023702002001410c6a220429020021072004200229038802370200200241003a00800220012902042108200120022903800237020420022005370378200220063703702002200737036820022008370360200141246a2d0000210920024180026a41176a2204200537000020024180026a41106a220a200229007137030020024180026a41086a220b2002290069370300200220022900613703800202402008a741ff01714101460d00200041063a0040200324000f0b200241186a41176a2004290000370000200241186a41106a200a290300370300200241186a41086a200b29030037030020022002290380023703180240024002400240411510272204450d002004410d6a41002900bbd143370000200441086a41002900b6d143370000200441002900aed14337000020044115413510282204450d0120042002290318370015200420093a00342004412c6a2002412f6a290000370000200441256a200241186a41106a2903003700002004411d6a200241186a41086a29030037000020024180026a41186a220a420037030020024180026a41106a220b420037030020024180026a41086a220c420037030020024200370380022004413520024180026a1000200241e0016a41186a200a290300370300200241e0016a41106a200b290300370300200241e0016a41086a200c29030037030020022002290380023703e0012002410036028002200241e0016a412020024180026a1005210d200228028002220e417f460d032002200e36023c2002200d36023820024180026a200241386a10fc0220022d00a1024102460d02200241b8016a41206a220a20024180026a41206a2d00003a0000200241b8016a41186a220b20024180026a41186a290300370300200241b8016a41106a220c20024180026a41106a290300370300200241b8016a41086a220f20024180026a41086a29030037030020022002290380023703b801200241e0006a200241a2026a41c10010ce041a0240200e450d00200d10290b200241386a41086a220e200f290300370300200241386a41106a220d200c290300370300200241386a41186a2210200b290300370300200241386a41206a2211200a2d00003a0000200220022903b80137033820024180026a200241e0006a41c10010ce041a200a20112d00003a0000200b2010290300370300200c200d290300370300200f200e290300370300200220022903383703b801200241e0006a20024180026a41c10010ce041a200141246a200241e0006a41c0006a2d00003a00002001411c6a200241e0006a41386a290000370000200141146a200241e0006a41306a2900003700002001410c6a200241e0006a41286a290000370000200120022900800137000420002002290318370000200041086a200241186a41086a290300370000200041106a200241186a41106a290300370000200041176a200241186a41176a290000370000200020093a001f200020022903b801370020200041286a200f290300370000200041306a200c290300370000200041386a200b290300370000200041c0006a200a2d00003a000020041029200324000f0b41154101102a000b41354101102a000b418f89c3004133104e000b41b6b7c30041d700104e000bd50703037f047e047f230022022103200241a0026b416071220224002001411c6a22042902002105200420022903b801370200200141146a22042902002106200420022903b0013702002001410c6a22042902002107200420022903a801370200200241003a00a00120012902042108200120022903a00137020420022005370338200220063703302002200737032820022008370320200141246a2d00002109200241a0016a41176a22042005370000200241a0016a41106a220a2002290031370300200241a0016a41086a220b2002290029370300200220022900213703a00102402008a741ff01714101460d0020004200370300200324000f0b200241176a2004290000370000200241106a200a290300370300200241086a200b290300370300200220022903a0013703000240024002400240411210272204450d00200441106a41002f0088a3443b0000200441086a4100290080a344370000200441002900f8a24437000020044112413210282204450d0120042002290300370012200420093a0031200441296a200241176a290000370000200441226a200241106a2903003700002004411a6a200241086a290300370000200241a0016a41186a220a4200370300200241a0016a41106a220b4200370300200241a0016a41086a220c4200370300200242003703a00120044132200241a0016a100020024180016a41186a200a29030037030020024180016a41106a200b29030037030020024180016a41086a200c290300370300200220022903a00137038001200241003602a00120024180016a4120200241a0016a1005210b20022802a001220a417f460d032002200a36029c022002200b36029802200241a0016a20024198026a10af0320022d00b8014102460d02200241a0016a41086a290300210520022903a001210820022802b001210c200241206a200241b9016a41c70010ce041a0240200a450d00200b10290b200241a0016a200241206a41c10010ce041a200241206a200241a0016a41c10010ce041a200141246a200241e0006a2d00003a00002001411c6a200241206a41386a290000370000200141146a200241206a41306a2900003700002001410c6a200241206a41286a2900003700002001200229004037000420002002290300370008200041106a200241086a290300370000200041186a200241106a2903003700002000411f6a200241176a290000370000200041306a2005370300200041286a2008370300200041386a200c360200200020093a00272000420137030020041029200324000f0b41124101102a000b41324101102a000b418f89c3004133104e000b41b6b7c30041d700104e000b860905027f027e057f017e027f23004190026b22022400200241206a2001102e0240024002402002280220450d0020022802242103200241086a200110532002290308a70d010b200041023a00180c010b200241186a290300210420022903102105200241003a00f001200241f0016a2001280200220620012802042207410047220810ce041a02400240024020072008490d002001200720086b22093602042001200620086a22083602002007450d0220022d00f001220741014b0d02410021060240024020070e020100010b200241f0016a2009412020094120491b22076a41004100412020076b2007411f4b1b10cd041a200241f0016a2008200710ce041a2001200920076b220a3602042001200820076a22083602002009411f4d0d03200241b0016a41086a200241f0016a41086a290000220b37030020024190016a41186a200241f0016a41186a29000037030020024190016a41106a200241f0016a41106a29000037030020024190016a41086a200b370300200220022900f001220b3703b0012002200b3703900141012106200a21090b200241f0006a41186a20024190016a41186a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41086a20024190016a41086a2903003703002002200229039001370370200241003a00f001200241f0016a20082009410047220710ce041a20092007490d012001200920076b220a3602042001200820076a22073602002009450d0220022d00f001220841014b0d02410021090240024020080e020100010b200241f0016a200a4120200a4120491b22086a41004100412020086b2008411f4b1b10cd041a200241f0016a2007200810ce041a2001200a20086b3602042001200720086a360200200a411f4d0d03200241b0016a41086a200241f0016a41086a290000220b37030020024190016a41186a200241f0016a41186a29000037030020024190016a41106a200241f0016a41106a29000037030020024190016a41086a200b370300200220022900f001220b3703b0012002200b37039001410121090b200241306a41186a220120024190016a41186a290300370300200241306a41106a220720024190016a41106a290300370300200241306a41086a220820024190016a41086a290300370300200241d0006a41086a220a200241f0006a41086a290300370300200241d0006a41106a220c200241f0006a41106a290300370300200241d0006a41186a220d200241f0006a41186a2903003703002002200229039001370330200220022903703703502000200437030820002005370300200020063a001820002003360210200041396a20093a000020002002290350370019200041216a200a290300370000200041296a200c290300370000200041316a200d2903003700002000413a6a2002290330370100200041c2006a2008290300370100200041ca006a2007290300370100200041d2006a2001290300370100200041de006a2002412e6a2f01003b0100200041da006a200228012a3601000c030b20082007103e000b20072009103e000b200041023a00180b20024190026a24000b3400200041ceb8c30036020420004100360200200041146a4107360200200041106a41d4b8c300360200200041086a42043702000b950101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002404120102722060d0041204101102a000b20062002290300370000200042a0808080800437020420002006360200200641186a2003290300370000200641106a2004290300370000200641086a2005290300370000200241206a24000b130020004102360204200041e4c5c3003602000b3101017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242f02e3700000b3101017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242eb023700000bef0803037f017e047f230041f0026b22052400200541c986c500411910b5010240024002402005280204410020052802001b2206417f6a220720064d0d00200541123602100c010b200541086a200710a70320052802104112460d00200541a8016a200541086a41a00110ce041a20052903a8012108200541a8016a41086a103d20082001580d00200041f7d2c30036020420004101360200200041086a41c7003602002002103d0c010b200541a8016a41086a22074200370300200542003703a80141c986c5004119200541a8016a1004200541086a41086a2007290300370300200520052903a8013703082005200641016a3602a801200541086a4110200541a8016a41041003200520013703a8012007200241880110ce042109200520033a00c002200520043703b802024002400240024002400240411a10272207450d00200741186a41002f00dbd1433b0000200741106a41002900d3d143370000200741086a41002900cbd143370000200741002900c3d1433700002007411a413410282202450d012002200636001a200541086a41186a22074200370300200541086a41106a220a4200370300200541086a41086a220b4200370300200542003703082002411e200541086a1000200541c8026a41186a2007290300370300200541c8026a41106a200a290300370300200541c8026a41086a200b290300370300200520052903083703c802200541003602102005420137030820052903a8012101410810272207450d022005410836020c20052005280210220a41086a360210200520073602082007200a6a20013700002009200541086a1032024020052d00c002220741024b0d00024002400240024020070e03000102000b4100210a0c020b4101210a0c010b4102210a0b2005200a3a00ef0202400240200528020c20052802102207460d002005280208210b0c010b200741016a220b2007490d072007410174220c200b200b200c491b220c4100480d070240024020070d00200c1027210b0c010b20052802082007200c1028210b0b200b450d052005200c36020c2005200b360208200528021021070b2005200741016a360210200b20076a200a3a00000b20052903b802210102400240200528020c220a200528021022076b4108490d002005280208210a0c010b200741086a220b2007490d06200a4101742207200b200b2007491b22074100480d0602400240200a0d0020071027210a0c010b2005280208200a20071028210a0b200a450d052005200736020c2005200a360208200528021021070b2005200741086a360210200a20076a2001370000200528020c2107200541c8026a41202005280208220a2005280210100302402007450d00200a10290b200210292009103d200541b4016a2006360200200541b1016a20033a0000200541a8016a41086a41033a0000200541053a00a80141b8d6c5004100200541a8016a10880120004100360200200020063602040c060b411a4101102a000b41344101102a000b41084101102a000b200c4101102a000b20074101102a000b102b000b200541f0026a24000bd10302047f037e230041d0006b2202240002400240411310272203450d002003410f6a41002800ecd143360000200341086a41002900e5d143370000200341002900ddd14337000020034113412610282203450d0120032001360013200241286a41186a22014200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820034117200241286a1000200241086a41186a2001290300370300200241086a41106a2004290300370300200241086a41086a20052903003703002002200229032837030820024100360228200241086a4120200241286a1005210102400240024020022802282204417f460d002001450d00200220013602482002200436024c2002420037033020024200370328200241286a20012004411020044110491b220510ce041a2002200420056b36024c2002200120056a36024802402004410f4d0d00200241306a290300210620022903282107200241286a200241c8006a102d200228022822040d020b418f89c3004133104e000b410021040c010b200229022c2108200110292000200637030820002007370300200020083702140b2000200436021020031029200241d0006a24000f0b41134101102a000b41264101102a000b130020004111360204200041bcd4c3003602000b3400200041f3f3c30036020420004100360200200041146a410f360200200041106a41fcf3c300360200200041086a42093702000ba00101037f230041a0016b220224002002411236020020024100360298012002420137039001200241003a009f010240410110272203450d002002200336029001200320022802980122046a20022d009f013a000020024101360294012002200441016a2203360298012000200229039001370200200041086a2003360200024020022802004112460d002002103d0b200241a0016a24000f0b41014101102a000bb70101057f230041206b22022400200241186a22034200370300200241106a22044200370300200241086a220542003703002002420037030002400240412010272206450d0020062002290300370000200641186a2003290300370000200641106a2004290300370000200641086a20052903003700002006412041c00010282206450d01200042c0808080900437020420002006360200200641003a0020200241206a24000f0b41204101102a000b41c0004101102a000b4901017f230041106b2202240020024100360208200242013703002002410036020c2002410c6a20021030200041086a200228020836020020002002290300370200200241106a24000b1300200041063602042000419490c4003602000b3201017f02404108102722020d0041084101102a000b2000428880808080013702042000200236020020024280af1a3700000b3201017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242c0d1023700000b3e01017f02404110102722020d0041104101102a000b20024200370008200242808084fea6dee111370000200042908080808002370204200020023602000b3201017f02404108102722020d0041084101102a000b2000428880808080013702042000200236020020024280ce183700000be51a03037f027e067f230041f0016b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e12000102030405060708090a0b0c0d0e0f1011000b200241e8006a200141086a10960220004100360200200041106a200241e8006a41086a290300370300200041086a20022903683703000c110b109702000b20004102360200200041086a200141086a2903003703000c0f0b200241e8006a200141046a1038200041033602002000410c6a200241f0006a280200360200200020022903683702040c0e0b109802000b0240024002400240200141086a280200417f6a220341014b0d0020030e020102010b41e4bdc0001058000b41012103024002402001410c6a22042d00004101460d00200241026a200441036a2d00003a0000200241f0006a2001411c6a290200370300200241e8006a41106a200141246a29020037030020024180016a2001412c6a2d00003a0000200220042f00013b01002002200141146a290200370368200141106a2802002104410021030c010b200141106a28020021040b200241246a41026a200241026a2d00003a0000200241286a41086a200241e8006a41086a290300370300200241286a41106a200241e8006a41106a290300370300200241286a41186a200241e8006a41186a280200360200200220022f01003b012420022002290368370328200141386a29030021052001290330210641012107200241106a21010c010b41012103024002402001410c6a22042d00004101460d00200241ee016a200441036a2d00003a0000200241f0006a2001411c6a290200370300200241e8006a41106a200141246a29020037030020024180016a2001412c6a2d00003a0000200220042f00013b01ec012002200141146a290200370368200141106a2802002104410021030c010b200141106a28020021040b41022107200241246a41026a200241ec016a41026a2d00003a0000200241286a41086a200241e8006a41086a290300370300200241286a41106a200241e8006a41106a290300370300200241286a41186a200241e8006a41186a280200360200200220022f01ec013b012420022002290368370328200220012903303703102002200141386a290300370318200141c8006a290300210520012903402106200221010b20012006370300200120053703082000410c6a20033a0000200041086a2007360200200020022f01243b000d2000410f6a200241266a2d00003a0000200041106a2004360200200041146a20022903283702002000411c6a200241286a41086a290300370200200041246a200241286a41106a2903003702002000412c6a200241c0006a280200360200200041386a200241106a41086a290300370300200041306a2002290310370300200041c0006a2002290300370300200041c8006a200241086a290300370300200041053602000c0c0b200241e8006a200141086a10990220004106360200200041386a200241e8006a41306a290300370300200041306a200241e8006a41286a290300370300200041286a200241e8006a41206a290300370300200041206a200241e8006a41186a290300370300200041186a200241e8006a41106a290300370300200041106a200241e8006a41086a290300370300200041086a20022903683703000c0b0b200241e8006a41186a200141286a290000370300200241e8006a41106a200141206a290000370300200241f0006a200141186a290000370300200241e8006a41286a200141386a290000370300200241e8006a41306a200141c0006a290000370300200241e8006a41386a200141c8006a2900003703002002200141106a2900003703682002200141306a290000370388012001410c6a2802002203417f4c0d0b0240024020030d00410121010c010b20012802042104200310272201450d0d20012004200310ce041a0b200241286a41386a2204200241e8006a41386a290300370300200241286a41306a2207200241e8006a41306a290300370300200241286a41286a2208200241e8006a41286a290300370300200241286a41206a2209200241e8006a41206a290300370300200241286a41186a220a200241e8006a41186a290300370300200241286a41106a220b200241e8006a41106a290300370300200241286a41086a220c200241e8006a41086a290300370300200220022903683703282000410c6a2003360200200041086a200336020020002001360204200041106a2002290328370200200041186a200c290300370200200041206a200b290300370200200041286a200a290300370200200041306a2009290300370200200041386a2008290300370200200041c0006a2007290300370200200041c8006a2004290300370200200041073602000c0a0b200241e8006a200141086a109a0220004108360200200041386a200241e8006a41306a290300370300200041306a200241e8006a41286a290300370300200041286a200241e8006a41206a290300370300200041206a200241e8006a41186a290300370300200041186a200241e8006a41106a290300370300200041106a200241e8006a41086a290300370300200041086a20022903683703000c090b200241e8006a200141046a109b0220004109360200200041246a20024188016a2903003702002000411c6a20024180016a290300370200200041146a200241f8006a2903003702002000410c6a200241f0006a290300370200200020022903683702040c080b200241e8006a200141046a109b022000410a360200200041246a20024188016a2903003702002000411c6a20024180016a290300370200200041146a200241f8006a2903003702002000410c6a200241f0006a290300370200200020022903683702040c070b200241e8006a200141086a10c8012000410b360200200041c0006a200241e8006a41386a290300370300200041386a200241e8006a41306a290300370300200041306a200241e8006a41286a290300370300200041286a200241e8006a41206a290300370300200041206a200241e8006a41186a290300370300200041186a200241e8006a41106a290300370300200041106a200241e8006a41086a290300370300200041086a20022903683703000c060b2000410c360200200041086a200141086a2903003703000c050b2001410c6a2802002203417f4c0d050240024020030d00410121010c010b20012802042104200310272201450d0820012004200310ce041a0b200020013602042000410d3602002000410c6a2003360200200041086a20033602000c040b024002400240024002400240200141086a280200417f6a220341024b0d0020030e03010203010b4190a9c1001058000b200141386a2903002105200141306a290300210641012103024002402001410c6a2d00004101460d00200241f0006a2001411c6a290200370300200241e8006a41106a200141246a29020037030020024180016a2001412c6a2d00003a00002002200141146a29020037036820012f000d2001410f6a2d0000411074722104200141106a2802002101410021030c010b200141106a28020021010b200241286a41186a200241e8006a41186a280200360200200241286a41106a200241e8006a41106a290300370300200241286a41086a200241e8006a41086a29030037030020022002290368370328410121070c030b2001410c6a28020022034108762104410221070c010b2001410c6a28020022034108762104410321070b0b2000410e360200200041386a2005370300200041306a2006370300200041106a2001360200200041086a2007360200200041146a20022903283702002000410c6a2004410874200341ff0171723602002000411c6a200241286a41086a290300370200200041246a200241286a41106a2903003702002000412c6a200241c0006a2802003602000c030b200241e8006a200141086a109c02200041086a200241e8006a41800110ce041a2000410f3602000c020b02400240024002402001280204417f6a220341014b0d0020030e020102010b41f8e2c1001058000b41880110272203450d072003200141086a280200109502410121010c010b4101210302400240200141086a2d00004101460d00200241e8006a41086a200141186a290200370300200241e8006a41106a200141206a290200370300200241e8006a41186a200141286a2d00003a00002002200141106a29020037036820012f00092001410b6a2d00004110747221072001410c6a2802002104410021030c010b2001410c6a28020021040b200241286a41186a200241e8006a41186a280200360200200241286a41106a200241e8006a41106a290300370300200241286a41086a200241e8006a41086a2903003703002002200229036837032820032007410874722103410221010b20002001360204200041103602002000410c6a2004360200200041086a2003360200200041106a2002290328370200200041186a200241286a41086a290300370200200041206a200241286a41106a290300370200200041286a200241286a41186a2802003602000c010b200241e8006a200141086a10b101200041086a200241e8006a41d80010ce041a200041113602000b200241f0016a24000f0b1039000b20034101102a000b20034101102a000b4188014108102a000bb20503047f027e057f230041d0006b220224000240411310272203450d002003410f6a41002800ecd143360000200341086a41002900e5d143370000200341002900ddd143370000024020034113412610282204450d0020042000360013200241286a41186a22034200370300200241286a41106a22004200370300200241286a41086a220542003703002002420037032820044117200241286a1000200241086a41186a2003290300370300200241086a41106a2000290300370300200241086a41086a2005290300370300200220022903283703082002410036023020024201370328200141086a2903002106200129030021070240411010272203450d00200320073700002003200637000820024290808080800237022c20022003360228200128021021082002200141186a280200220336024c200241cc006a200241286a10300240024020030d0020022802302105200228022c21092002280228210a0c010b2003410574210b2002280228210a200228022c21092002280230210020082103034002400240200920006b4120490d00200041206a21050c010b0240200041206a22052000490d002009410174220c20052005200c491b220c4100480d000240024020090d00200c1027210a0c010b200a2009200c1028210a0b0240200a450d00200c21090c020b200c4101102a000b102b000b200a20006a22002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a29000037000020052100200341206a2103200b41606a220b0d000b2002200936022c200220053602302002200a3602280b200241086a4120200a2005100302402009450d00200a10290b200410290240200141146a280200450d00200810290b200241d0006a24000f0b41104101102a000b41264101102a000b41134101102a000bbd0402087f047e230041e0006b22022400024002400240410f10272203450d00200341076a41002900909d44370000200341002900899d443700002003410f412f10282203450d012003200129000037000f200341276a200141186a2900003700002003411f6a200141106a290000370000200341176a200141086a290000370000200241206a41186a22014200370300200241206a41106a22044200370300200241206a41086a22054200370300200242003703202003412f200241206a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002002410036024020024120200241c0006a100521050240024020022802402201417f460d00200241206a2001412020014120491b22046a41004100412020046b2004411f4b1b10cd041a200241206a2005200410ce041a2001411f4d0d04200241c0006a41186a2201200241206a41186a2204290300370300200241c0006a41106a2206200241206a41106a2207290300370300200241c0006a41086a2208200241206a41086a2209290300370300200220022903203703402005102920042001290300220a37030020072006290300220b37030020092008290300220c37030020022002290340220d370320200041013a00002000200d370001200041096a200c370000200041116a200b370000200041196a200a3700000c010b200041003a00000b20031029200241e0006a24000f0b410f4101102a000b412f4101102a000b418f89c3004133104e000bba0f010f7f230041f0006b22042400024002400240024002400240024002400240024002400240411a10272205450d00200541186a41002f00dbd1433b0000200541106a41002900d3d143370000200541086a41002900cbd143370000200541002900c3d1433700002005411a413410282205450d012005200136001a200441c8006a41186a22064200370300200441c8006a41106a22074200370300200441c8006a41086a22084200370300200442003703482005411e200441c8006a1000200441286a41186a2006290300370300200441286a41106a2007290300370300200441286a41086a200829030037030020042004290348370328200441286a412041b8d6c50041004100100b21062005102902400240024002402006417f470d0041839ec40021070c010b200441086a41186a200041186a290000370300200441086a41106a200041106a290000370300200441086a41086a200041086a29000037030020042000290000370308411010272205450d05200541086a41002900a6d1433700002005410029009ed14337000020054110412010282205450d06200520013600102005412041c00010282205450d07200520042903083700142005412c6a200441086a41186a2209290300370000200541246a200441086a41106a220a2903003700002005411c6a200441086a41086a220b290300370000200441c8006a41186a22064200370300200441c8006a41106a22074200370300200441c8006a41086a220842003703002004420037034820054134200441c8006a1000200441286a41186a2006290300370300200441286a41106a2007290300370300200441286a41086a200829030037030020042004290348370328200441286a412041b8d6c50041004100100b210c200510290240200c417f470d00200441086a200110a8032006200041186a2900003703002007200041106a2900003703002008200041086a2900003703002004200029000037034802400240200428020c220d20042802102206460d00200641016a21052004280208210e0c010b200641016a22052006490d0420064101742207200520052007491b220d41ffffff3f71200d470d04200d41057422074100480d040240024020060d0020071027210e0c010b2004280208200641057420071028210e0b200e450d0a2004200d36020c2004200e3602080b200e20064105746a22062004290348370000200641186a200441c8006a41186a290300370000200641106a200441c8006a41106a290300370000200641086a200441c8006a41086a29030037000020042005360210411310272206450d0a2006410f6a4100280096d243360000200641086a410029008fd24337000020064100290087d2433700002006411341261028220f450d0b200f2001360013200441c8006a41186a22064200370300200441c8006a41106a22074200370300200441c8006a41086a2208420037030020044200370348200f4117200441c8006a1000200441286a41186a2006290300370300200441286a41106a2007290300370300200441286a41086a20082903003703002004200429034837032820044100360250200442013703482004200536026c200441ec006a200441c8006a10300240024020050d0020042802502106200428024c210c200428024821100c010b200541057421114100200428025022066b210820042802482110200428024c210c200e210503400240200c20086a411f4b0d00200641206a22072006490d06200c4101742212200720072012491b22074100480d0602400240200c0d002007102721100c010b2010200c2007102821100b2010450d052007210c0b201020066a22072005290000370000200741186a200541186a290000370000200741106a200541106a290000370000200741086a200541086a290000370000200841606a2108200641206a2106200541206a2105201141606a22110d000b2004200c36024c20042006360250200420103602480b200441286a41202010200610030240200c450d00201010290b200f1029200d450d00200e10290b2009200041186a290000370300200a200041106a290000370300200b200041086a29000037030020042000290000370308411010272205450d0b200541086a41002900a6d1433700002005410029009ed14337000020054110412010282205450d0c200520013600102005412041c00010282205450d0d200520042903083700142005412c6a200441086a41186a290300370000200541246a200441086a41106a2903003700002005411c6a200441086a41086a290300370000200441c8006a41186a22064200370300200441c8006a41106a22074200370300200441c8006a41086a220842003703002004420037034820054134200441c8006a1000200441286a41186a2006290300370300200441286a41106a2007290300370300200441286a41086a200829030037030020042004290348370328410110272206450d0e41002107200641807f410020021b2003723a0000200441286a412020064101100320061029200510290b200441f0006a240020070f0b20074101102a000b102b000b411a4101102a000b41344101102a000b41104101102a000b41204101102a000b41c0004101102a000b20074101102a000b41134101102a000b41264101102a000b41104101102a000b41204101102a000b41c0004101102a000b41014101102a000bec0302047f027e230041d0006b2202240002400240411310272203450d002003410f6a41002800bb9c44360000200341086a41002900b49c44370000200341002900ac9c4437000020034113413310282203450d01200320012900003700132003412b6a200141186a290000370000200341236a200141106a2900003700002003411b6a200141086a290000370000200241286a41186a22014200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820034133200241286a1000200241086a41186a2001290300370300200241086a41106a2004290300370300200241086a41086a20052903003703002002200229032837030820024100360228200241086a4120200241286a1005210102400240024020022802282204417f460d002001450d00200220013602482002200436024c20024200370328200241286a20012004410820044108491b220510ce041a2002200420056b36024c2002200120056a3602480240200441074d0d0020022903282106200241286a200241c8006a102d200228022822040d020b418f89c3004133104e000b410021040c010b200229022c2107200110292000200737020c200020063703000b2000200436020820031029200241d0006a24000f0b41134101102a000b41334101102a000bf40801037f200141046a2802002102200141086a280200210302400240024002400240024002400240024020002d00004101460d000240024020022003460d00200128020021020c010b200341016a22022003490d0920034101742204200220022004491b22044100480d090240024020030d002004102721020c010b200128020020032004102821020b2002450d0320012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a41003a00000c010b0240024020022003460d00200128020021020c010b200341016a22022003490d0820034101742204200220022004491b22044100480d080240024020030d002004102721020c010b200128020020032004102821020b2002450d0320012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41013a000002400240200141046a2802002202200428020022036b4120490d00200128020021020c010b200341206a22042003490d0820024101742203200420042003491b22034100480d080240024020020d002003102721020c010b200128020020022003102821020b2002450d0420012002360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200220036a220341186a200041196a290000370000200341106a200041116a290000370000200341086a200041096a290000370000200320002900013700000b200141046a2802002102200141086a2802002103024020002d00214101460d000240024020022003460d00200128020021000c010b200341016a22002003490d0820034101742202200020002002491b22024100480d080240024020030d002002102721000c010b200128020020032002102821000b2000450d0520012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b0240024020022003460d00200128020021020c010b200341016a22022003490d0720034101742204200220022004491b22044100480d070240024020030d002004102721020c010b200128020020032004102821020b2002450d0520012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41013a000002400240200141046a2802002202200428020022036b4120490d00200128020021020c010b200341206a22042003490d0720024101742203200420042003491b22034100480d070240024020020d002003102721020c010b200128020020022003102821020b2002450d0620012002360200200141046a2003360200200141086a28020021030b200141086a200341206a360200200220036a220141186a2000413a6a290000370000200141106a200041326a290000370000200141086a2000412a6a2900003700002001200041226a2900003700000f0b20044101102a000b20044101102a000b20034101102a000b20024101102a000b20044101102a000b20034101102a000b102b000bab0201027f230041106b2202240020024100360208200242013703000240412010272203450d002003200029002c370000200341086a200041346a290000370000200341106a2000413c6a290000370000200341186a200041c4006a290000370000200242a08080808004370204200220033602002002200036020c2002410c6a200210592002200041106a36020c2002410c6a20021059200028022021032002200041286a280200220036020c2002410c6a2002103002402000450d002003200041186c6a210003402002200336020c2002410c6a20021059200341106a200210302000200341186a2203470d000b0b2002280204210320012802002001280204200228020022002002280208100302402003450d00200010290b200241106a24000f0b41204101102a000bcd0801067f230041106b220224002002410036020820024201370300200041106a200210302002200036020c2002410c6a20021059200228020421032002280208210402400240024002400240024002400240024020002d00184101460d000240024020032004460d00200228020021050c010b200441016a22032004490d0920044101742205200320032005491b22034100480d090240024020040d002003102721050c010b200228020020042003102821050b2005450d0320022003360204200220053602000b2002200441016a2206360208200520046a41003a00000c010b0240024020032004460d00200228020021050c010b200441016a22032004490d0820044101742205200320032005491b22034100480d080240024020040d002003102721050c010b200228020020042003102821050b2005450d0320022003360204200220053602000b2002200441016a360208200520046a41013a00000240024020022802042203200228020822046b4120490d00200441206a21060c010b200441206a22062004490d0820034101742207200620062007491b22074100480d080240024020030d002007102721050c010b200520032007102821050b2005450d042002200736020420022005360200200721030b200520046a220441086a200041216a290000370000200441106a200041296a290000370000200441186a200041316a290000370000200220063602082004200041196a2900003700000b02400240200041396a2d00004101460d00024020032006470d00200341016a22002003490d0920034101742204200020002004491b22004100480d090240024020030d002000102721050c010b200520032000102821050b2005450d0620022000360204200220053602000b2002200641016a360208200520066a41003a00002002280208210420022802042105200228020021030c010b024020032006470d00200341016a22042003490d0820034101742207200420042007491b22044100480d080240024020030d002004102721050c010b200520032004102821050b2005450d0620022004360204200220053602000b2002200641016a360208200520066a41013a00000240024020022802042205200228020822046b4120490d00200228020021030c010b200441206a22032004490d0820054101742206200320032006491b22064100480d080240024020050d002006102721030c010b200228020020052006102821030b2003450d072002200636020420022003360200200621050b200320046a220641086a200041c2006a290000370000200641106a200041ca006a290000370000200641186a200041d2006a2900003700002002200441206a220436020820062000413a6a2900003700000b2001280200200128020420032004100302402005450d00200310290b200241106a24000f0b20034101102a000b20034101102a000b20074101102a000b20004101102a000b20044101102a000b20064101102a000b102b000b9316010c7f230041f0026b2201240002400240024002400240411210272202450d00200241106a41002f0088a3443b0000200241086a4100290080a344370000200241002900f8a24437000020024112413210282202450d01200220002900003700122002412a6a200041186a290000370000200241226a200041106a2900003700002002411a6a200041086a290000370000200141e8006a41186a22004200370300200141e8006a41106a22034200370300200141e8006a41086a220442003703002001420037036820024132200141e8006a1000200141c8016a41186a2000290300370300200141c8016a41106a2003290300370300200141c8016a41086a2004290300370300200120012903683703c8012001410036029002200141c8016a412020014190026a100521002001280290022205417f460d032000450d032001200536024c2001200036024820014190026a200141c8006a10af0320012d00a80222034102460d02200141e8006a41186a200141c1026a290000370300200141e8006a41106a200141b9026a290000370300200141e8006a41086a200141b1026a290000370300200141f0016a41086a200141d2026a290100370300200141f0016a41106a200141da026a290100370300200141f0016a41186a200141e2026a290100370300200120012900a9023703682001200141ca026a2901003703f001200141c9026a2d0000210402402005450d00200010290b200141c8016a4120100c0c040b41124101102a000b41324101102a000b418f89c3004133104e000b410221030b200141286a41186a2200200141e8006a41186a290300370300200141286a41106a2205200141e8006a41106a290300370300200141286a41086a2206200141e8006a41086a290300370300200141086a41086a2207200141f0016a41086a2208290300370300200141086a41106a2209200141f0016a41106a220a290300370300200141086a41186a220b200141f0016a41186a220c29030037030020012001290368370328200120012903f00137030820021029024020034102460d0020082006290300370300200a2005290300370300200c2000290300370300200141c8006a41086a2007290300370300200141c8006a41106a2009290300370300200141c8006a41186a200b290300370300200120012903283703f0012001200129030837034841002102024002400240024002400240024002400240200441ff01714101470d00411210272202450d01200241106a41002f0088a3443b0000200241086a4100290080a344370000200241002900f8a24437000020024112413210282202450d02200220012903483700122002412a6a200141e0006a290300370000200241226a200141c8006a41106a2903003700002002411a6a200141c8006a41086a2903003700000b0240024020034101470d00411210272200450d04200041106a41002f0088a3443b0000200041086a4100290080a344370000200041002900f8a24437000020004112413210282200450d05200020012903f0013700122000412a6a200141f0016a41186a290300370000200041226a200141f0016a41106a2903003700002000411a6a200141f0016a41086a290300370000200141e8006a41186a22054200370300200141e8006a41106a22064200370300200141e8006a41086a220742003703002001420037036820004132200141e8006a1000200141c8016a41186a2005290300370300200141c8016a41106a2006290300370300200141c8016a41086a2007290300370300200120012903683703c8012001410036029002200141c8016a412020014190026a100521062001280290022205417f470d0141e0a3c40041d300104e000b200141e8006a41186a22004200370300200141e8006a41106a22054200370300200141e8006a41086a220642003703002001420037036841b3a4c400411a200141e8006a1000200141c8016a41186a2000290300370300200141c8016a41106a2005290300370300200141c8016a41086a2006290300370300200120012903683703c8010240200441ff01714101460d00200141c8016a4120100c0c080b412010272200450d0520002001290348370000200041186a200141c8006a41186a290300370000200041106a200141c8006a41106a290300370000200041086a200141c8006a41086a290300370000200141c8016a4120200041201003200010290c070b200120053602ec01200120063602e80120014190026a200141e8016a10af0320012d00a80222074102460d05200141b0016a41106a220820014190026a41106a2209290300370300200141b0016a41086a220a20014190026a41086a220b29030037030020012001290390023703b001200141e8006a200141a9026a220c41c70010ce041a02402005450d00200610290b200b200a29030037030020092008290300370300200120012903b00137039002200120073a00a802200c200141e8006a41c70010ce041a200141c9026a20043a0000200141ca026a2001290348370100200141d2026a200141c8006a41086a290300370100200141da026a200141c8006a41106a290300370100200141e2026a200141c8006a41186a290300370100200141e8006a41186a22044200370300200141e8006a41106a22054200370300200141e8006a41086a220642003703002001420037036820004132200141e8006a1000200141c8016a41186a2004290300370300200141c8016a41106a2005290300370300200141c8016a41086a2006290300370300200120012903683703c8012001412036026c2001200141c8016a36026820014190026a200141e8006a10c80320001029410121040c070b41124101102a000b41324101102a000b41124101102a000b41324101102a000b41204101102a000b418f89c3004133104e000b41002100410021040b02400240024002400240024020020d00410021030c010b200141e8006a41186a22054200370300200141e8006a41106a22064200370300200141e8006a41086a220742003703002001420037036820024132200141e8006a1000200141c8016a41186a2005290300370300200141c8016a41106a2006290300370300200141c8016a41086a2007290300370300200120012903683703c8012001410036029002200141c8016a412020014190026a100521062001280290022205417f460d02200120053602ec01200120063602e80120014190026a200141e8016a10af0320012d00a8024102460d01200141b0016a41106a220720014190026a41106a2208290300370300200141b0016a41086a220920014190026a41086a220a29030037030020012001290390023703b001200141e8006a200141a9026a220b41c70010ce041a02402005450d00200610290b200a200929030037030020082007290300370300200120012903b00137039002200b200141e8006a41c70010ce0420012903f001370000200141b1026a200141f0016a41086a290300370000200141b9026a200141f0016a41106a290300370000200141c1026a200141f0016a41186a290300370000200120033a00a802200141e8006a41186a22034200370300200141e8006a41106a22054200370300200141e8006a41086a220642003703002001420037036820024132200141e8006a1000200141c8016a41186a2003290300370300200141c8016a41106a2005290300370300200141c8016a41086a2006290300370300200120012903683703c8012001412036026c2001200141c8016a36026820014190026a200141e8006a10c80320021029410121030b200420004572450d020c030b418f89c3004133104e000b41e0a3c40041d300104e000b200010290b2002452003720d00200210290b200141f0026a24000bf31b01107f230041d0026b220124000240024002400240411210272202450d00200241106a41002f00f6a2443b0000200241086a41002900eea244370000200241002900e6a24437000020024112413210282202450d01200220002900003700122002412a6a200041186a290000370000200241226a200041106a2900003700002002411a6a200041086a290000370000200141b0016a41186a22004200370300200141b0016a41106a22034200370300200141b0016a41086a22044200370300200142003703b00120024132200141b0016a1000200141f8016a41186a2000290300370300200141f8016a41106a2003290300370300200141f8016a41086a2004290300370300200120012903b0013703f80120014100360260200141f8016a4120200141e0006a1005210020012802602204417f460d022000450d02200120043602c402200120003602c002200141c0006a200141c0026a102d0240024020012802402205450d0020012802442106200141e0006a200141c0026a10940320012d006022074102470d012006450d00200510290b418f89c3004133104e000b200141b0016a41186a200141f9006a290000370300200141b0016a41106a200141f1006a290000370300200141b0016a41086a200141e9006a290000370300200141a0026a41086a2001418a016a290100370300200141a0026a41106a20014192016a290100370300200141a0026a41186a2001419a016a290100370300200120012900613703b001200120014182016a2901003703a00220014181016a2d0000210302402004450d00200010290b200141f8016a4120100c0c030b41124101102a000b41324101102a000b410221070b200141206a41186a2200200141b0016a41186a290300370300200141206a41106a2204200141b0016a41106a290300370300200141206a41086a2208200141b0016a41086a290300370300200141086a2209200141a0026a41086a220a290300370300200141106a220b200141a0026a41106a220c290300370300200141186a220d200141a0026a41186a220e290300370300200120012903b001370320200120012903a00237030020021029024002400240024020074102460d00200a2008290300370300200c2004290300370300200e2000290300370300200141c0006a41086a2009290300370300200141c0006a41106a200b290300370300200141c0006a41186a200d290300370300200120012903203703a002200120012903003703404100210c024002400240024002400240024002400240200341ff01714101470d00411210272202450d01200241106a41002f00f6a2443b0000200241086a41002900eea244370000200241002900e6a2443700002002411241321028220c450d02200c2001290340370012200c412a6a200141d8006a290300370000200c41226a200141c0006a41106a290300370000200c411a6a200141c0006a41086a2903003700000b0240024020074101470d00411210272202450d04200241106a41002f00f6a2443b0000200241086a41002900eea244370000200241002900e6a2443700002002411241321028220d450d05200d20012903a002370012200d412a6a200141a0026a41186a290300370000200d41226a200141a0026a41106a290300370000200d411a6a200141a0026a41086a290300370000200141b0016a41186a22024200370300200141b0016a41106a22004200370300200141b0016a41086a22044200370300200142003703b001200d4132200141b0016a1000200141f8016a41186a2002290300370300200141f8016a41106a2000290300370300200141f8016a41086a2004290300370300200120012903b0013703f80120014100360260200141f8016a4120200141e0006a1005210020012802602204417f460d072000450d072001200436029c022001200036029802200141c0026a20014198026a102d024020012802c002220e450d00200141c8026a280200210220012802c402210f200141b0016a20014198026a10940320012d00b00122084102470d02200f450d00200e10290b418f89c3004133104e000b200141b0016a41186a22024200370300200141b0016a41106a22004200370300200141b0016a41086a22044200370300200142003703b00141c6a3c400411a200141b0016a1000200141f8016a41186a2002290300370300200141f8016a41106a2000290300370300200141f8016a41086a2004290300370300200120012903b0013703f8010240200341ff01714101460d00200141f8016a4120100c0c080b412010272202450d0520022001290340370000200241186a200141c0006a41186a290300370000200241106a200141c0006a41106a290300370000200241086a200141c0006a41086a290300370000200141f8016a4120200241201003200210290c070b200141e0006a200141b0016a41017241c10010ce041a200141b0016a200141e0006a41c30010ce041a02402004450d00200010290b200120083a006c200120023602682001200f3602642001200e360260200141ed006a200141b0016a41c30010ce041a2001418d016a20033a00002001418e016a200129034037010020014196016a200141c0006a41086a2903003701002001419e016a200141c0006a41106a290300370100200141a6016a200141c0006a41186a290300370100200141b0016a41186a22004200370300200141b0016a41106a22034200370300200141b0016a41086a22044200370300200142003703b001200d4132200141b0016a1000200141f8016a41186a2000290300370300200141f8016a41106a2003290300370300200141f8016a41086a2004290300370300200120012903b0013703f801200141003602b801200142013703b001200120023602c002200141c0026a200141b0016a1030024002402002450d002002410574210a410020012802b80122006b210420012802b001210920012802b4012108200e210203400240200820046a411f4b0d00200041206a22032000490d0e2008410174220b20032003200b491b22034100480d0e0240024020080d002003102721090c010b200920082003102821090b2009450d03200321080b200920006a22032002290000370000200341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200441606a2104200041206a2100200241206a2102200a41606a220a0d000b200120083602b401200120003602b801200120093602b0010b200141ec006a200141b0016a10c60320012802b4012102200141f8016a412020012802b001220020012802b801100302402002450d00200010290b0240200f450d00200e10290b200d10294101210f0c080b20034101102a000b41124101102a000b41324101102a000b41124101102a000b41324101102a000b41204101102a000b41e0a3c40041d300104e000b4100210d4100210f0b02400240200c0d00410021020c010b200141b0016a41186a22024200370300200141b0016a41106a22004200370300200141b0016a41086a22034200370300200142003703b001200c4132200141b0016a1000200141f8016a41186a2002290300370300200141f8016a41106a2000290300370300200141f8016a41086a2003290300370300200120012903b0013703f80120014100360260200141f8016a4120200141e0006a1005210320012802602200417f460d042001200036029c022001200336029802200141c0026a20014198026a102d0240024020012802c002220e450d00200141c8026a280200210220012802c4022110200141b0016a20014198026a10940320012d00b0014102470d012010450d00200e10290b418f89c3004133104e000b200141e0006a200141b0016a41017241c10010ce041a200141b0016a200141e0006a41c30010ce041a02402000450d00200310290b20012002360268200120103602642001200e360260200141ed006a200141b0016a41c30010ce0420012903a002370000200141f5006a200141a0026a41086a290300370000200141fd006a200141a0026a41106a29030037000020014185016a200141a0026a41186a290300370000200120073a006c200141b0016a41186a22004200370300200141b0016a41106a22034200370300200141b0016a41086a22044200370300200142003703b001200c4132200141b0016a1000200141f8016a41186a2000290300370300200141f8016a41106a2003290300370300200141f8016a41086a2004290300370300200120012903b0013703f801200141003602b801200142013703b001200120023602c002200141c0026a200141b0016a103002402002450d002002410574210a410020012802b80122006b210420012802b001210920012802b4012108200e210203400240200820046a411f4b0d00200041206a22032000490d062008410174220b20032003200b491b22034100480d060240024020080d002003102721090c010b200920082003102821090b2009450d05200321080b200920006a22032002290000370000200341186a200241186a290000370000200341106a200241106a290000370000200341086a200241086a290000370000200441606a2104200041206a2100200241206a2102200a41606a220a0d000b200120083602b401200120003602b801200120093602b0010b200141ec006a200141b0016a10c60320012802b4012102200141f8016a412020012802b001220020012802b801100302402002450d00200010290b02402010450d00200e10290b200c1029410121020b0240200f200d45720d00200d10290b0240200c452002720d00200c10290b2006450d00200510290b200141d0026a24000f0b20034101102a000b102b000b41e0a3c40041d300104e000b13002000410d360204200041d0a4c4003602000b3400200041ced2c40036020420004100360200200041146a4115360200200041106a41d8d2c400360200200041086a42073702000b7501027f230041106b22022400200241003602082002420137030002404104102722030d0041044101102a000b2003410036000020024284808080c000370204200220033602002002410036020c2002410c6a20021030200041086a200228020836020020002002290300370200200241106a24000b3001017f02404108102722020d0041084101102a000b20004288808080800137020420002002360200200242003700000bdf0301077f230041c0006b22022400200241186a4200370300200241106a22034200370300200241086a4200370300200241286a22044100360200200242003703002002420837032020024100360238200242013703302002200236023c2002413c6a200241306a10592002200336023c2002413c6a200241306a10592002280220210320022004280200220436023c2002413c6a200241306a10300240024002402004450d00200441306c210503400240024020022802342206200228023822046b4120490d00200441206a2107200228023021060c010b200441206a22072004490d0420064101742208200720072008491b22084100480d040240024020060d002008102721060c010b200228023020062008102821060b2006450d0320022008360234200220063602300b200620046a220441086a200341186a290000370000200441106a200341206a290000370000200441186a200341286a290000370000200220073602382004200341106a2900003700002002200336023c2002413c6a200241306a1059200341306a2103200541506a22050d000b0b20002002290330370200200041086a200241306a41086a28020036020002402002280224450d00200228022010290b200241c0006a24000f0b20084101102a000b102b000b7001017f230041306b220224002002420037031020024200370308200241033602182002410036022820024201370320200241186a200241206a10302002200241086a36022c2002412c6a200241206a1059200041086a200228022836020020002002290320370200200241306a24000b3201017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241c0843d3600000b3001017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241043600000bdf0606077f047e037f037e017f017e230041a0016b2202240020024180016a41186a2203420037030020024180016a41106a2204420037030020024180016a41086a22054200370300200242003703800120024180016a2001280200220620012802042207412020074120491b220810ce041a2001200720086b3602042001200620086a360200024002402007411f4b0d00200041003602200c010b200241e0006a41186a2003290300370300200241e0006a41106a2004290300370300200241e0006a41086a20052903003703002002200229038001370360200241c8006a2001105302402002290348a70d00200041003602200c010b200241c8006a41106a29030021092002290350210a200241306a2001105302402002290330a70d00200041003602200c010b200241c0006a290300210b2002290338210c200241286a2001102e024002400240024002402002280228450d0002400240200228022c220d41aa01200d41aa01491b220e0d00410821040c010b200e41186c220710272204450d030b0240200d450d00200241106a41106a210f4100210341002106410021080340200241106a20011053024002402002290310a7450d00200f290300211020022903182111200241086a2001102e20022802080d010b200e450d03200410290c030b200841016a2107200228020c210502402008200e470d002003200720072003491b220ead42187e2212422088a70d072012a722134100480d070240024020080d002013102721040c010b200420062013102821040b2004450d060b200420066a2208201037030820082011370300200841106a2005360200200341026a2103200641186a210620072108200d2007470d000b0b20040d010b200041003602200c040b20024180016a41186a200241e0006a41186a290300221037030020024180016a41106a200241e0006a41106a290300221137030020024180016a41086a200241e0006a41086a290300221237030020022002290360221437038001200041186a200b3703002000200c370310200020093703082000200a3703002000200dad422086200ead84370224200020043602202000412c6a2014370200200041346a20123702002000413c6a2011370200200041c4006a20103702000c030b20074108102a000b20134108102a000b102b000b200241a0016a24000b130020004102360204200041b8f6c4003602000b3101017f02404104102722020d0041044101102a000b20004284808080c00037020420002002360200200241a0053600000bb90d021e7f037e230041f0026b22042400024002400240024002400240410d10272205450d00200541056a41002900aca344370000200541002900a7a3443700002005410d412d10282205450d012005200129000037000d200541256a200141186a2900003700002005411d6a200141106a290000370000200541156a200141086a290000370000200441a0026a41186a22064200370300200441a0026a41106a22074200370300200441a0026a41086a22084200370300200442003703a0022005412d200441a0026a1000200441e0016a41186a2006290300370300200441e0016a41106a2007290300370300200441e0016a41086a2008290300370300200420042903a0023703e001200441003602a002200441e0016a4120200441a0026a10052107024002400240024020042802a0022206417f460d00200441003a00a002200441a0026a20072006410047220810ce041a20062008490d062006450d0720042d00a002220641034f0d07200710292005102920060e03010302010b200510290b200441f8006a2001108c0220042d00784101470d06200441a0016a41186a20044191016a2205290000370300200441a0016a41106a20044189016a2206290000370300200441a0016a41086a20044181016a2207290000370300200420042900793703a001200441a0026a200441a0016a108d02200441c0016a41186a22082005290000370300200441c0016a41106a22092006290000370300200441c0016a41086a220a2007290000370300200420042900793703c00120042802c002220b450d06200441e0016a41186a220c2008290300370300200441e0016a41106a220d2009290300370300200441e0016a41086a220e200a290300370300200441e0016a41286a2205200441a0026a41086a2206290300370300200441e0016a41306a2207200441a0026a41106a2208290300370300200441e0016a41386a220f200441a0026a41186a2210290300370300200441086a41286a2211200441ec026a2212280200360200200441086a41206a2213200441e4026a2214290200370300200441086a41186a2215200441dc026a2216290200370300200441086a41106a2217200441d4026a2218290200370300200441086a41086a2219200441cc026a221a290200370300200420042903c0013703e001200420042903a00237038002200420042902c402370308200441386a41386a221b200f290300370300200441386a41306a221c2007290300370300200441386a41286a221d2005290300370300200441386a41206a221e200429038002370300200441386a41186a221f200c290300370300200441386a41106a2220200d290300370300200441386a41086a2221200e290300370300200420042903e001370338200f201b2903003703002007201c2903003703002005201d290300370300200441e0016a41206a221b201e290300370300200c201f290300370300200d2020290300370300200e2021290300370300200420042903383703e001200441f8006a41186a201f290300370300200441f8006a41106a2020290300370300200441f8006a41086a2021290300370300200420042903383703782010200f29030037030020082007290300370300200620052903003703002004200b3602c0022004201b2903003703a002200441c4026a22052004290308370200201a2019290300370200201820172903003702002016201529030037020020142013290300370200201220112802003602002010290300212220082008290300222320027c22243703002010202220037c2024202354ad7c37030020062903002122200420042903a002222320027c22243703a0022006202220037c2024202354ad7c370300200441c0016a200120022003109f0120043502c001210220092903002122200a2903002103200441f8006a200441a0026a10d80302402005280200450d0020042802c00210290b200242018521020c070b200441a0026a2001108c0220042d00a0024101470d05200441f8016a200441b9026a290000370300200441e0016a41106a200441b1026a290000370300200441e0016a41086a200441a9026a290000370300200420042900a1023703e001200441386a200441e0016a20022003109f0120043502384201852102200441386a41106a2903002122200441386a41086a29030021030c060b200441a0026a200120022003109f0120043502a0024201852102200441b0026a2903002122200441a8026a29030021030c050b410d4101102a000b412d4101102a000b20082006103e000b418f89c3004133104e000b420021020b2000200337030820002002370300200041106a2022370300200441f0026a24000b0900200042003702000bdb0201047f230041d0006b22022400200242f3e885db96cddbb320370308200241086a2001412c6a2001290300200141086a290300427f410e10a80102400240410e10272203450d00200341066a410029009fa34437000020034100290099a3443700002003410e412e10282203450d012003200029000037000e200341266a200041186a2900003700002003411e6a200041106a290000370000200341166a200041086a290000370000200241306a41186a22004200370300200241306a41106a22044200370300200241306a41086a22054200370300200242003703302003412e200241306a1000200241106a41186a2000290300370300200241106a41106a2004290300370300200241106a41086a200529030037030020022002290330370310200241203602342002200241106a3602302001200241306a10c70320031029200241d0006a24000f0b410e4101102a000b412e4101102a000b02000bd70302027f077e23004180016b22032400200341c0006a200110ae0302400240024020032903404201520d00200241016a2104200341c0006a41086a21020340200341086a41306a200241306a2903002205370300200341086a41286a200241286a2903002206370300200341086a41206a200241206a2903002207370300200341086a41186a200241186a2903002208370300200341086a41106a200241106a2903002209370300200341086a41086a200241086a290300220a37030020032002290300220b370308200341c0006a41306a2005370300200341c0006a41286a2006370300200341c0006a41206a2007370300200341c0006a41186a2008370300200341c0006a41106a20093703002002200a3703002003200b3703402004417f6a2204450d02200341c0006a200110ae0320032903404201510d000b0b200042003703000c010b2000200329034037030820004201370300200041386a200341c0006a41306a290300370300200041306a200341c0006a41286a290300370300200041286a200341c0006a41206a290300370300200041206a200341c0006a41186a290300370300200041186a200341c0006a41106a290300370300200041106a200341c8006a2903003703000b20034180016a24000beb050a067f017e017f017e017f017e017f017e017f017e230041206b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200020044105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c37000020052008370000024020032001490d00200321040c030b2006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200020034105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c370000200520083700002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200020044105746a22012900002108200020054105746a220041086a2205290000210a200041106a2204290000210c200041186a2203290000210e20012000290000370000200141186a220629000021102006200e370000200141106a2206290000210e2006200c370000200141086a2201290000210c2001200a370000200320103700002004200e3700002005200c370000200020083700000b200241206a24000f0b41c481c500200520011037000b41b481c500200420011037000be90609067f017e017f017e017f027e017f017e027f230041206b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d0220052006200020064105746a200020054105746a412010d0044100481b21060b200620014f0d03200420014f0d02200020044105746a2204200020064105746a2205412010d004417f4a0d03200541086a22072900002108200541106a2209290000210a200541186a220b290000210c2004290000210d20042005290000370000200441186a220e290000210f200e200c370000200441106a220e290000210c200e200a370000200441086a2204290000210a20042008370000200b200f3700002009200c3700002007200a3700002005200d370000200621040c000b0b41b883c500200620011037000b41c883c500200420011037000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241186a2209200041186a2204290000370300200241106a220b200041106a2205290000370300200241086a220e200041086a2203290000370300200020074105746a220641086a2900002108200641106a290000210a200641186a290000210c2000290000210d200020062900003700002004200c3700002005200a370000200320083700002002200d37030041002105024002400240034020062002290300370000200641186a2009290300370000200641106a200b290300370000200641086a200e2903003700002005410174220641017221040240200641026a220620074f0d00200420074f0d0220062004200020044105746a200020064105746a412010d0044100481b21040b200420074f0d03200520074f0d02200020054105746a2205200020044105746a2206412010d004417f4a0d032009200541186a2203290000370300200b200541106a2210290000370300200e200541086a2211290000370300200641086a2900002108200641106a290000210a200641186a290000210c2005290000210d200520062900003700002003200c3700002010200a370000201120083700002002200d370300200421050c000b0b41b883c500200420071037000b41c883c500200520071037000b200741014b0d000b0b200241206a24000f0b41c481c500200720011037000bdb08030a7f017e0a7f230041c0006b22022400200041a07f6a21032001417f6a2104200141324921054101210641002107024003400240024020062001490d00410021080c010b41012108200020064105746a2209200941606a412010d0044100480d0003404101210a20042006460d03200641016a2106200941206a220a2009412010d0042108200a21092008417f4a0d000b200620014921080b2006200146210a20050d0120062001460d0102400240024002402006417f6a220920014f0d002008450d0120002006410574220b6a220a290000210c200a200020094105746a22092900003700002009200c370000200a41086a220d290000210c200d200941086a220e290000370000200e200c370000200a41106a220f290000210c200f200941106a22102900003700002010200c370000200a41186a2211290000210c2011200941186a22122900003700002012200c37000020064102490d03200920002006417e6a22084105746a2213412010d004417f4a0d032009290000210c20092013290000370000200241206a41186a22142012290000370300200241206a41106a22152010290000370300200241206a41086a2216200e290000370300200e201341086a2900003700002010201341106a2900003700002012201341186a2900003700002002200c3703204100210e2008450d022003200b6a210903400240200241206a2009412010d0044100480d002008210e0c040b200941206a2009290000370000200941386a200941186a290000370000200941306a200941106a290000370000200941286a200941086a290000370000200941606a21092008417f6a22080d000c030b0b41b481c500200920011037000b41c481c500200620011037000b2000200e4105746a22092002290320370000200941186a2014290300370000200941106a2015290300370000200941086a20162903003700000b200741016a21070240200120066b22104102490d00200a41206a2209200a412010d004417f4a0d00200a290000210c200a2009290000370000200241206a41186a22122011290000370300200241206a41106a2213200f290000370300200241206a41086a220b200d290000370300200d200941086a290000370000200f200941106a2900003700002011200941186a2900003700002002200c3703204101210d024020104103490d00200a41c0006a200241206a412010d004417f4a0d00410321084102210e0340200a200e4105746a220941606a220d2009290000370000200d41186a200941186a290000370000200d41106a200941106a290000370000200d41086a200941086a290000370000024020082010490d00200e210d0c020b20084105742109200e210d2008210e200841016a2108200a20096a200241206a412010d0044100480d000b0b200a200d4105746a22092002290320370000200941186a2012290300370000200941106a2013290300370000200941086a200b2903003700000b20074105470d000b4100210a0b200241c0006a2400200a0bb204030e7f017e017f230041c0006b22032400200128020022042001280208220541047422066a210720012802042108200421010240024002402005450d00200341306a41017221094100210a200341306a41026a210b200341206a410172220c41076a210d0340200b2004200a6a220141036a2d00003a00002003200141016a2f00003b0130024020012d0000220e41ac01470d00200141106a21010c020b2003410c6a41026a200b2d0000220f3a0000200320032f013022103b010c200141046a29020021112001410c6a2802002112200920103b0000200941026a200f3a00002003200e3a00302003201236023c20032011370234200341206a200341306a200210df032003200c2900003703102003200d290000370017024020032d0020220e411a470d002006200a41106a220a470d010c030b0b2000200e3a000020002003290310370001200041086a20032900173700000240200541047441706a200a460d00200141186a2101034002400240200141786a220a2d0000220b4109460d00200b41ac01470d010c030b200128020041ffffffff0371450d00200a41046a28020010290b200141106a2101200a41106a2007470d000b0b2008450d02200410290c020b20012007460d0003400240024020012d0000220a4109460d00200a41ac01470d010c030b200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a22012007470d000b0b02402008450d00200410290b2000411a3a00000b200341c0006a24000bf6d60202097f017e230041106b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df50120044101742208200520052008491b22084100480df5010240024020040d002008102721050c010b200628020020042008102821050b2005450dad0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df50120044101742208200520052008491b22084100480df5010240024020040d002008102721050c010b200628020020042008102821050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df40120044101742208200520052008491b22084100480df4010240024020040d002008102721050c010b200628020020042008102821050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df40120044101742208200520052008491b22084100480df4010240024020040d002008102721050c010b200628020020042008102821050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df30120044101742208200520052008491b22084100480df3010240024020040d002008102721050c010b200628020020042008102821050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df30120044101742208200520052008491b22084100480df3010240024020040d002008102721050c010b200628020020042008102821050b2005450db00120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490df00120044101742207200620062007491b22074100480df0010240024020040d002007102721060c010b200928020020042007102821060b2006450db00120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df1012004410174220a20062006200a491b220a4100480df1010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490def0120044101742207200620062007491b22074100480def010240024020040d002007102721060c010b200928020020042007102821060b2006450db10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df0012004410174220a20062006200a491b220a4100480df0010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210a2001410c6a2802002104200141086a2802002109200141046a280200210b02400240200241086a2802002002410c6a2802002201460d00200a28020021050c010b200141016a22052001490dee0120014101742206200520052006491b22064100480dee010240024020010d002006102721050c010b200a28020020012006102821050b2005450db20120022005360204200241086a20063602002002410c6a28020021010b2002410c6a2206200141016a360200200520016a410e3a000020032009200b200b20094102746a200210e00320032d0000411a470d9303200241086a2107034002400240200728020020062802002201460d00200a28020021050c010b200141016a22052001490def0120014101742208200520052008491b22084100480def010240024020010d002008102721050c010b200a28020020012008102821050b2005450db4012002200536020420072008360200200628020021010b2006200141016a360200200520016a200441807f72200441ff0071200441077622011b3a00002001210420010d000b0240200941ffffffff0371450d00200b10290b2000411a3a00000c95030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490ded0120044101742206200520052006491b22064100480ded010240024020040d002006102721050c010b200228020420042006102821050b2005450db30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490dec0120044101742207200620062007491b22074100480dec010240024020040d002007102721060c010b200928020020042007102821060b2006450db30120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490ded012004410174220a20062006200a491b220a4100480ded010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490deb0120044101742207200620062007491b22074100480deb010240024020040d002007102721060c010b200928020020042007102821060b2006450db40120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490dec012004410174220a20062006200a491b220a4100480dec010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490deb0120044101742206200520052006491b22064100480deb010240024020040d002006102721050c010b200928020020042006102821050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dea0120044101742206200520052006491b22064100480dea010240024020040d002006102721050c010b200228020420042006102821050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490de90120044101742206200520052006491b22064100480de9010240024020040d002006102721050c010b200228020420042006102821050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de80120044101742207200620062007491b22074100480de8010240024020040d002007102721060c010b200928020020042007102821060b2006450db60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de9012004410174220a20062006200a491b220a4100480de9010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db801200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de70120044101742207200620062007491b22074100480de7010240024020040d002007102721060c010b200928020020042007102821060b2006450db70120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de8012004410174220a20062006200a491b220a4100480de8010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db901200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de60120044101742207200620062007491b22074100480de6010240024020040d002007102721060c010b200928020020042007102821060b2006450db80120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de7012004410174220a20062006200a491b220a4100480de7010240024020040d00200a102721060c010b20092802002004200a102821060b2006450dba01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de50120044101742207200620062007491b22074100480de5010240024020040d002007102721060c010b200928020020042007102821060b2006450db90120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de6012004410174220a20062006200a491b220a4100480de6010240024020040d00200a102721060c010b20092802002004200a102821060b2006450dbb01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de40120044101742207200620062007491b22074100480de4010240024020040d002007102721060c010b200928020020042007102821060b2006450dba0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de5012004410174220a20062006200a491b220a4100480de5010240024020040d00200a102721060c010b20092802002004200a102821060b2006450dbc01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de30120044101742208200720072008491b22084100480de3010240024020040d002008102721070c010b200a28020020042008102821070b2007450dbb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de4012004410174220b20072007200b491b220b4100480de4010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dbd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de40120044101742209200620062009491b22094100480de4010240024020040d002009102721060c010b200a28020020042009102821060b2006450dbe012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de20120044101742208200720072008491b22084100480de2010240024020040d002008102721070c010b200a28020020042008102821070b2007450dbd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de3012004410174220b20072007200b491b220b4100480de3010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dbf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de30120044101742209200620062009491b22094100480de3010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de10120044101742208200720072008491b22084100480de1010240024020040d002008102721070c010b200a28020020042008102821070b2007450dbf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de2012004410174220b20072007200b491b220b4100480de2010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de20120044101742209200620062009491b22094100480de2010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de00120044101742208200720072008491b22084100480de0010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de1012004410174220b20072007200b491b220b4100480de1010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de10120044101742209200620062009491b22094100480de1010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddf0120044101742208200720072008491b22084100480ddf010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de0012004410174220b20072007200b491b220b4100480de0010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de00120044101742209200620062009491b22094100480de0010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dde0120044101742208200720072008491b22084100480dde010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddf012004410174220b20072007200b491b220b4100480ddf010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddf0120044101742209200620062009491b22094100480ddf010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc8012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddd0120044101742208200720072008491b22084100480ddd010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc70120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dde012004410174220b20072007200b491b220b4100480dde010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dde0120044101742209200620062009491b22094100480dde010240024020040d002009102721060c010b200a28020020042009102821060b2006450dca012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddc0120044101742208200720072008491b22084100480ddc010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc90120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddd012004410174220b20072007200b491b220b4100480ddd010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dcb01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddd0120044101742209200620062009491b22094100480ddd010240024020040d002009102721060c010b200a28020020042009102821060b2006450dcc012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddb0120044101742208200720072008491b22084100480ddb010240024020040d002008102721070c010b200a28020020042008102821070b2007450dcb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddc012004410174220b20072007200b491b220b4100480ddc010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dcd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddc0120044101742209200620062009491b22094100480ddc010240024020040d002009102721060c010b200a28020020042009102821060b2006450dce012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dda0120044101742208200720072008491b22084100480dda010240024020040d002008102721070c010b200a28020020042008102821070b2007450dcd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddb012004410174220b20072007200b491b220b4100480ddb010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dcf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddb0120044101742209200620062009491b22094100480ddb010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd90120044101742208200720072008491b22084100480dd9010240024020040d002008102721070c010b200a28020020042008102821070b2007450dcf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dda012004410174220b20072007200b491b220b4100480dda010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dda0120044101742209200620062009491b22094100480dda010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd80120044101742208200720072008491b22084100480dd8010240024020040d002008102721070c010b200a28020020042008102821070b2007450dd10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd9012004410174220b20072007200b491b220b4100480dd9010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd90120044101742209200620062009491b22094100480dd9010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd70120044101742208200720072008491b22084100480dd7010240024020040d002008102721070c010b200a28020020042008102821070b2007450dd30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd8012004410174220b20072007200b491b220b4100480dd8010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd80120044101742209200620062009491b22094100480dd8010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd60120044101742208200720072008491b22084100480dd6010240024020040d002008102721070c010b200a28020020042008102821070b2007450dd50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da3022004410174220b20072007200b491b220b4100480da3020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da30220044101742209200620062009491b22094100480da3020240024020040d002009102721060c010b200a28020020042009102821060b2006450dd9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da10220044101742208200720072008491b22084100480da1020240024020040d002008102721070c010b200a28020020042008102821070b2007450dd80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da2022004410174220b20072007200b491b220b4100480da2020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dda01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da20220044101742209200620062009491b22094100480da2020240024020040d002009102721060c010b200a28020020042009102821060b2006450ddb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da00220044101742208200720072008491b22084100480da0020240024020040d002008102721070c010b200a28020020042008102821070b2007450dda0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da1022004410174220b20072007200b491b220b4100480da1020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450ddc01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da10220044101742209200620062009491b22094100480da1020240024020040d002009102721060c010b200a28020020042009102821060b2006450ddd012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9f0220044101742208200720072008491b22084100480d9f020240024020040d002008102721070c010b200a28020020042008102821070b2007450ddc0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da0022004410174220b20072007200b491b220b4100480da0020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dde01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da00220044101742209200620062009491b22094100480da0020240024020040d002009102721060c010b200a28020020042009102821060b2006450ddf012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9e0220044101742208200720072008491b22084100480d9e020240024020040d002008102721070c010b200a28020020042008102821070b2007450dde0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9f022004410174220b20072007200b491b220b4100480d9f020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9f0220044101742209200620062009491b22094100480d9f020240024020040d002009102721060c010b200a28020020042009102821060b2006450de1012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9d0220044101742208200720072008491b22084100480d9d020240024020040d002008102721070c010b200a28020020042008102821070b2007450de00120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9e022004410174220b20072007200b491b220b4100480d9e020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9e0220044101742209200620062009491b22094100480d9e020240024020040d002009102721060c010b200a28020020042009102821060b2006450de3012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9c0220044101742208200720072008491b22084100480d9c020240024020040d002008102721070c010b200a28020020042008102821070b2007450de20120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9d022004410174220b20072007200b491b220b4100480d9d020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9d0220044101742209200620062009491b22094100480d9d020240024020040d002009102721060c010b200a28020020042009102821060b2006450de5012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9b0220044101742208200720072008491b22084100480d9b020240024020040d002008102721070c010b200a28020020042008102821070b2007450de40120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9c022004410174220b20072007200b491b220b4100480d9c020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9c0220044101742209200520052009491b22094100480d9c020240024020040d002009102721050c010b200a28020020042009102821050b2005450de7012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a0220044101742208200720072008491b22084100480d9a020240024020040d002008102721070c010b200a28020020042008102821070b2007450de60120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b022004410174220b20072007200b491b220b4100480d9b020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b0220044101742209200620062009491b22094100480d9b020240024020040d002009102721060c010b200a28020020042009102821060b2006450de9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d990220044101742208200720072008491b22084100480d99020240024020040d002008102721070c010b200a28020020042008102821070b2007450de80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a022004410174220b20072007200b491b220b4100480d9a020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dea01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a0220044101742209200620062009491b22094100480d9a020240024020040d002009102721060c010b200a28020020042009102821060b2006450deb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d980220044101742208200520052008491b22084100480d98020240024020040d002008102721050c010b200628020020042008102821050b2005450dea0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d980220044101742208200520052008491b22084100480d98020240024020040d002008102721050c010b200628020020042008102821050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d970220044101742208200520052008491b22084100480d97020240024020040d002008102721050c010b200628020020042008102821050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d970220044101742208200520052008491b22084100480d97020240024020040d002008102721050c010b200628020020042008102821050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d960220044101742207200520052007491b22074100480d96020240024020040d002007102721050c010b200228020420042007102821050b2005450dec0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a000020032006200210e1032003210220032d0000411a470df0020c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d950220044101742206200520052006491b22064100480d95020240024020040d002006102721050c010b200228020420042006102821050b2005450dec0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c200210e2032003210220032d0000411a470def020c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d940220044101742208200520052008491b22084100480d94020240024020040d002008102721050c010b200628020020042008102821050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d940220054101742204200820082004491b22044100480d94020240024020050d002004102721050c010b200628020020052004102821050b2005450ded0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d930220044101742207200520052007491b22074100480d93020240024020040d002007102721050c010b200628020020042007102821050b2005450ded0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d930220054101742204200720072004491b22044100480d93020240024020050d002004102721050c010b200628020020052004102821050b2005450dee0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d920220044101742206200520052006491b22064100480d92020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d910220044101742206200520052006491b22064100480d91020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d900220044101742206200520052006491b22064100480d90020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f0220044101742206200520052006491b22064100480d8f020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e0220044101742206200520052006491b22064100480d8e020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d0220044101742206200520052006491b22064100480d8d020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c0220044101742206200520052006491b22064100480d8c020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b0220044101742206200520052006491b22064100480d8b020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a0220044101742206200520052006491b22064100480d8a020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d890220044101742206200520052006491b22064100480d89020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d880220044101742206200520052006491b22064100480d88020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d870220044101742206200520052006491b22064100480d87020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d860220044101742206200520052006491b22064100480d86020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d850220044101742206200520052006491b22064100480d85020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d840220044101742206200520052006491b22064100480d84020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d830220044101742206200520052006491b22064100480d83020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d820220044101742206200520052006491b22064100480d82020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d810220044101742206200520052006491b22064100480d81020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d800220044101742206200520052006491b22064100480d80020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff0120044101742206200520052006491b22064100480dff010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe0120044101742206200520052006491b22064100480dfe010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd0120044101742206200520052006491b22064100480dfd010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc0120044101742206200520052006491b22064100480dfc010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb0120044101742206200520052006491b22064100480dfb010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa0120044101742206200520052006491b22064100480dfa010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df90120044101742206200520052006491b22064100480df9010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df80120044101742206200520052006491b22064100480df8010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df50120044101742206200520052006491b22064100480df5010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df40120044101742206200520052006491b22064100480df4010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df30120044101742206200520052006491b22064100480df3010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df00120044101742206200520052006491b22064100480df0010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490def0120044101742206200520052006491b22064100480def010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dba0220044101742206200520052006491b22064100480dba020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db90220044101742206200520052006491b22064100480db9020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db80220044101742206200520052006491b22064100480db8020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db70220044101742206200520052006491b22064100480db7020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db60220044101742206200520052006491b22064100480db6020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db50220044101742206200520052006491b22064100480db5020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db40220044101742206200520052006491b22064100480db4020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db30220044101742206200520052006491b22064100480db3020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db20220044101742206200520052006491b22064100480db2020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db10220044101742206200520052006491b22064100480db1020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db00220044101742206200520052006491b22064100480db0020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daf0220044101742206200520052006491b22064100480daf020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae0220044101742206200520052006491b22064100480dae020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad0220044101742206200520052006491b22064100480dad020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac0220044101742206200520052006491b22064100480dac020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dab0220044101742206200520052006491b22064100480dab020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daa0220044101742206200520052006491b22064100480daa020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da90220044101742206200520052006491b22064100480da9020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da80220044101742206200520052006491b22064100480da8020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da70220044101742206200520052006491b22064100480da7020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da60220044101742206200520052006491b22064100480da6020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da50220044101742206200520052006491b22064100480da5020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da40220044101742206200520052006491b22064100480da4020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da30220044101742206200520052006491b22064100480da3020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da20220044101742206200520052006491b22064100480da2020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da10220044101742206200520052006491b22064100480da1020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da00220044101742206200520052006491b22064100480da0020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f0220044101742206200520052006491b22064100480d9f020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9e0220044101742206200520052006491b22064100480d9e020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9d0220044101742206200520052006491b22064100480d9d020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9c0220044101742206200520052006491b22064100480d9c020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9b0220044101742206200520052006491b22064100480d9b020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9a0220044101742206200520052006491b22064100480d9a020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d990220044101742206200520052006491b22064100480d99020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d980220044101742206200520052006491b22064100480d98020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d970220044101742206200520052006491b22064100480d97020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d960220044101742206200520052006491b22064100480d96020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d950220044101742206200520052006491b22064100480d95020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d940220044101742206200520052006491b22064100480d94020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d930220044101742206200520052006491b22064100480d93020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d920220044101742206200520052006491b22064100480d92020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d910220044101742206200520052006491b22064100480d91020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d900220044101742206200520052006491b22064100480d90020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f0220044101742206200520052006491b22064100480d8f020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e0220044101742206200520052006491b22064100480d8e020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d0220044101742206200520052006491b22064100480d8d020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c0220044101742206200520052006491b22064100480d8c020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b0220044101742206200520052006491b22064100480d8b020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a0220044101742206200520052006491b22064100480d8a020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d890220044101742206200520052006491b22064100480d89020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d880220044101742206200520052006491b22064100480d88020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d870220044101742206200520052006491b22064100480d87020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d860220044101742206200520052006491b22064100480d86020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d850220044101742206200520052006491b22064100480d85020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d840220044101742206200520052006491b22064100480d84020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d830220044101742206200520052006491b22064100480d83020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d820220044101742206200520052006491b22064100480d82020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d810220044101742206200520052006491b22064100480d81020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d800220044101742206200520052006491b22064100480d80020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff0120044101742206200520052006491b22064100480dff010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe0120044101742206200520052006491b22064100480dfe010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd0120044101742206200520052006491b22064100480dfd010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc0120044101742206200520052006491b22064100480dfc010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb0120044101742206200520052006491b22064100480dfb010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa0120044101742206200520052006491b22064100480dfa010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df90120044101742206200520052006491b22064100480df9010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df80120044101742206200520052006491b22064100480df8010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df50120044101742206200520052006491b22064100480df5010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df40120044101742206200520052006491b22064100480df4010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df30120044101742206200520052006491b22064100480df3010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df00120044101742206200520052006491b22064100480df0010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc0120044101742206200520052006491b22064100480dfc010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb0120044101742206200520052006491b22064100480dfb010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa0120044101742206200520052006491b22064100480dfa010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df90120044101742206200520052006491b22064100480df9010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df80120044101742206200520052006491b22064100480df8010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df50120044101742206200520052006491b22064100480df5010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df40120044101742206200520052006491b22064100480df4010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df30120044101742206200520052006491b22064100480df3010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411a3a000020012d00004109470df201200141086a28020041ffffffff0371450df201200141046a28020010290cf2010b20064101102a000b20064101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20064101102a000b20064101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20064101102a000b20084101102a000b20064101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20064101102a000b20064101102a000b20064101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b102b000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20074101102a000b20064101102a000b20084101102a000b20044101102a000b20074101102a000b20044101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b102b000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b102b000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b102b000b20002003290300370200200041086a200341086a290300370200200941ffffffff0371450d01200b10290c010b20002002290200370200200041086a200241086a29020037020020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200341106a24000bb60301057f2004410c6a2105200441086a2106024002400240034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d0420074101742209200820082009491b22094100480d040240024020070d002009102721080c010b200428020420072009102821080b2008450d022004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b024020022003460d002004410c6a2105200441086a2106034020022802002101034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d0620074101742209200820082009491b22094100480d060240024020070d002009102721080c010b200428020420072009102821080b2008450d052004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b200241046a22022003470d000b0b2000411a3a00000f0b20094101102a000b20094101102a000b102b000bc30301067f200141c000712103200141ff0071210402400240024002400240200141077522050d002003450d010b2002410c6a2106200241086a2107034002402005417f470d00200341ff01710d020b02400240200728020020062802002208460d00200228020421030c010b200841016a22032008490d0520084101742204200320032004491b22044100480d050240024020080d002004102721030c010b200228020420082004102821030b2003450d032002200336020420072004360200200628020021080b2006200841016a360200200320086a200141807f723a0000200541c000712103200541ff007121042005210120054107752208210520080d002008210520030d000b0b02400240200241086a2802002002410c6a2802002205460d00200228020421080c010b200541016a22082005490d0320054101742203200820082003491b22034100480d030240024020050d002003102721080c010b200228020420052003102821080b2008450d0220022008360204200241086a20033602002002410c6a28020021050b2002410c6a200541016a360200200820056a20043a00002000411a3a00000f0b20044101102a000b20034101102a000b102b000bc30301067f2001a7220341c000712104200341ff0071210502400240024002400240200142078722014200520d002004450d010b2002410c6a2106200241086a2107034002402001427f520d00200441ff01710d020b02400240200728020020062802002204460d00200228020421050c010b200441016a22052004490d0520044101742208200520052008491b22084100480d050240024020040d002008102721050c010b200228020420042008102821050b2005450d032002200536020420072008360200200628020021040b2006200441016a360200200520046a200341807f723a00002001a7220341c000712104200341ff00712105200142078722014200520d0020040d000b0b02400240200241086a2802002002410c6a2802002204460d00200228020421030c010b200441016a22032004490d0320044101742206200320032006491b22064100480d030240024020040d002006102721030c010b200228020420042006102821030b2003450d0220022003360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200320046a20053a00002000411a3a00000f0b20084101102a000b20064101102a000b102b000bcf03010a7f230041306b22022400200241216a220341076a210441002105410021064100210741002108410821090240024002400340200241186a200110e403024020022802184101470d002000200229021c370204200041013602002000410c6a200241186a410c6a29020037020002402007450d00200921070340024020072d00004109470d00200741086a28020041ffffffff0371450d00200741046a28020010290b200741106a2107200641706a22060d000b0b2008450d04200910290c040b200220032900003703082002200429000037000f20022d0020210a2002200229000f37001f200220022903083703180240024020072008470d00200741016a220b2007490d032005200b200b2005491b220841ffffffff00712008470d032008410474220b4100480d030240024020070d00200b102721090c010b20092006200b102821090b2009450d010b200920066a220b200a3a0000200b41016a2002290318370000200b41086a200229001f370000200541026a2105200641106a2106200741016a2107200a41ff01714106460d030c010b0b200b4108102a000b102b000b20002009360204200041003602002000410c6a2007360200200041086a20083602000b200241306a24000b99b601020a7f017e230041f0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d02200320054f0d0120052003107f000b200241013a0048200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a10e603200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c610b2001280200220620046a2d000021072001410c6a2208200536020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200741bf014b0d0020070ec001b702b702010203b70200000000000405060708090a00000000000000000b0c000000000d0e0f101100000012131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901b7020b2000410b3a000420004101360200200041056a20073a00000cb9020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da102200620056a2c00002101200820093602004100210a0240200141004e0d00411821090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410221070cbd020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a10e603200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbc020b4102210a410221070cb8020b4103210a410221070cb7020b4101210a0b410221070cb5020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da102200620056a2c00002101200820093602004100210a0240200141004e0d00411821090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410321070cbc020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a10e603200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbb020b4102210a410321070cb7020b4103210a410321070cb6020b4101210a0b410321070cb4020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da102200620056a2c00002101200820093602004100210a0240200141004e0d00411821090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410421070cbb020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a10e603200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cba020b4102210a410421070cb6020b4103210a410421070cb5020b4101210a0b410421070cb3020b410621070cb2020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb5020b410721070cb1020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb4020b410821070cb0020b200241d8006a200110e70341042109200228025822064101460da201200241e0006a280200210b200228025c210302400240200241e4006a28020022040d00410021074100210a0c010b0240024020044102742205410275220741ffffffff03712007470d0020054100480d002005102722090d0120054104102a000b102b000b200441027421042005417c6a210a410021050340200920056a200320056a2802003602002004200541046a2205470d000b200a41027641016a210a0b0240200b450d00200310290b20022d005c4105470dae022006450dae0220022802640da3010cae020b410a21070cae020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddb012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb1020b410b21070cad020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddb012003200541016a22044f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a2101200421052007418001710d000b20014120490d01410d210120074110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb0020b0240024020032004460d00200441016a22012004490dd901200320014f0d0120012003107f000b200241013a0048200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a10e603200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cb0020b200620046a2d0000210520082001360200024020050d00410c21074100210a0cad020b200041163a000420004101360200200041056a20053a00000caf020b410d21070cab020b410e21070caa020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460dda012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cad020b410f21070ca9020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460dda012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cac020b411021070ca8020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460dda012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cab020b411121070ca7020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460dda012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000caa020b411221070ca6020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460dda012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000ca9020b411321070ca5020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddb01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca8020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9c010b20032001460d9a012001417f460dd7012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9b010b200aad210c411421070ca4020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddc01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca7020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9d010b20032001460d9b012001417f460dd8012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9c010b200aad210c411521070ca3020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddd01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca6020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9e010b20032001460d9c012001417f460dd9012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9d010b200aad210c411621070ca2020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dde01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca5020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9f010b20032001460d9d012001417f460dda012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9e010b200aad210c411721070ca1020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddf01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca4020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca0010b20032001460d9e012001417f460ddb012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9f010b200aad210c411821070ca0020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de001200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca3020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca1010b20032001460d9f012001417f460ddc012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da0010b200aad210c411921070c9f020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de101200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca2020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca2010b20032001460da0012001417f460ddd012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da1010b200aad210c411a21070c9e020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de201200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca1020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca3010b20032001460da1012001417f460dde012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da2010b200aad210c411b21070c9d020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de301200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca0020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca4010b20032001460da2012001417f460ddf012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da3010b200aad210c411c21070c9c020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de401200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9f020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca5010b20032001460da3012001417f460de0012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da4010b200aad210c411d21070c9b020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de501200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9e020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca6010b20032001460da4012001417f460de1012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da5010b200aad210c411e21070c9a020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de601200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9d020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca7010b20032001460da5012001417f460de2012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da6010b200aad210c411f21070c99020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de701200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca8010b20032001460da6012001417f460de3012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b41202107024020054120490d00410d21012004410f4b0da7010b200aad210c0c98020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de801200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9b020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca9010b20032001460da7012001417f460de4012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da8010b200aad210c412121070c97020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de901200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9a020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caa010b20032001460da8012001417f460de5012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da9010b200aad210c412221070c96020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dea01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c99020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cab010b20032001460da9012001417f460de6012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daa010b200aad210c412321070c95020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450deb01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c98020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cac010b20032001460daa012001417f460de7012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dab010b200aad210c412421070c94020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dec01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c97020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cad010b20032001460dab012001417f460de8012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dac010b200aad210c412521070c93020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ded01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c96020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cae010b20032001460dac012001417f460de9012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dad010b200aad210c412621070c92020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dee01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c95020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caf010b20032001460dad012001417f460dea012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dae010b200aad210c412721070c91020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450def01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c94020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb0010b20032001460dae012001417f460deb012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daf010b200aad210c412821070c90020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df001200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c93020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb1010b20032001460daf012001417f460dec012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db0010b200aad210c412921070c8f020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df101200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c92020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb2010b20032001460db0012001417f460ded012003200141016a2207490d8d02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db1010b200aad210c412a21070c8e020b0240024020032005460d00200441026a21012005417f460dee01200320014f0d0120012003107f000b200241013a0048200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a10e603200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c91020b200620056a2d0000210920082001360200024020090d00412b21074100210a0c8e020b200041153a000420004101360200200041056a20093a00000c90020b0240024020032005460d00200441026a21012005417f460dee01200320014f0d0120012003107f000b200241013a0048200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a10e603200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c90020b200620056a2d0000210920082001360200024020090d00412c21074100210a0c8d020b200041153a000420004101360200200041056a20093a00000c8f020b41002101410021090240024002400340410d210a2001411f4b0d010240024020032005460d002005417f460df2012003200541016a22074f0d01200541016a2003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e6034105210a0c020b200620056a2c0000210420082007360200200441ff00712001411f71742009722109200141076a21012007210520044100480d000b200441c00071210502402001411f4b0d0020050d020b0240024020014120490d0020050d010b200441ff01714108490d0320014120490d032005450d010c030b20044180017241ff017141f7014b0d020b2000200a36020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c90020b2009417f2001411f71747221090b412d21070c8b020b4200210c4100210102400240024002400340410e21072001413f4b0d010240024020032005460d002005417f460df3012003200541016a22094f0d01200541016a2003107f000b200241013a0008200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241086a360238200241286a200241d8006a10e6032002290328210c20022802302101410521070c030b200620056a2d0000210420082009360200200441ff0071220aad2001413f71ad86200c84210c200141076a210120092105200441187441187522094100480d000b200941c00071210502402001413f4b0d0020050d030b02400240200141c000490d0020050d010b200141c000490d0420090d010c040b200a41ff00460d030b0b200020073a0004200020022f00183b000520004101360200200041106a2001360200200041086a200c370200200041076a2002411a6a2d00003a00000c8f020b200c427f2001413f71ad8684210c0b412e21070c8a020b02400240200320056b4104490d00200441056a21012005417b4b0dee01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e60320004281808080d000370300200041086a2002290228370200200041106a200241286a41086a2802003602000c8d020b200620056a280000210920082001360200412f21070c89020b02400240200320056b4108490d00200441096a2101200541774b0dee01200320014f0d0120012003107f000b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e6032002290328210c200041106a2002280230360200200041086a200c37020020004281808080d0003703000c8c020b200620056a290000210c20082001360200413021070c88020b413121070c87020b413221070c86020b413321070c85020b413421070c84020b413521070c83020b413621070c82020b413721070c81020b413821070c80020b413921070cff010b413a21070cfe010b413b21070cfd010b413c21070cfc010b413d21070cfb010b413e21070cfa010b413f21070cf9010b41c00021070cf8010b41c10021070cf7010b41c20021070cf6010b41c30021070cf5010b41c40021070cf4010b41c50021070cf3010b41c60021070cf2010b41c70021070cf1010b41c80021070cf0010b41c90021070cef010b41ca0021070cee010b41cb0021070ced010b41cc0021070cec010b41cd0021070ceb010b41ce0021070cea010b41cf0021070ce9010b41d00021070ce8010b41d10021070ce7010b41d20021070ce6010b41d30021070ce5010b41d40021070ce4010b41d50021070ce3010b41d60021070ce2010b41d70021070ce1010b41d80021070ce0010b41d90021070cdf010b41da0021070cde010b41db0021070cdd010b41dc0021070cdc010b41dd0021070cdb010b41de0021070cda010b41df0021070cd9010b41e00021070cd8010b41e10021070cd7010b41e20021070cd6010b41e30021070cd5010b41e40021070cd4010b41e50021070cd3010b41e60021070cd2010b41e70021070cd1010b41e80021070cd0010b41e90021070ccf010b41ea0021070cce010b41eb0021070ccd010b41ec0021070ccc010b41ed0021070ccb010b41ee0021070cca010b41ef0021070cc9010b41f00021070cc8010b41f10021070cc7010b41f20021070cc6010b41f30021070cc5010b41f40021070cc4010b41f50021070cc3010b41f60021070cc2010b41f70021070cc1010b41f80021070cc0010b41f90021070cbf010b41fa0021070cbe010b41fb0021070cbd010b41fc0021070cbc010b41fd0021070cbb010b41fe0021070cba010b41ff0021070cb9010b41800121070cb8010b41810121070cb7010b41820121070cb6010b41830121070cb5010b41840121070cb4010b41850121070cb3010b41860121070cb2010b41870121070cb1010b41880121070cb0010b41890121070caf010b418a0121070cae010b418b0121070cad010b418c0121070cac010b418d0121070cab010b418e0121070caa010b418f0121070ca9010b41900121070ca8010b41910121070ca7010b41920121070ca6010b41930121070ca5010b41940121070ca4010b41950121070ca3010b41960121070ca2010b41970121070ca1010b41980121070ca0010b41990121070c9f010b419a0121070c9e010b419b0121070c9d010b419c0121070c9c010b419d0121070c9b010b419e0121070c9a010b419f0121070c99010b41a00121070c98010b41a10121070c97010b41a20121070c96010b41a30121070c95010b41a40121070c94010b41a50121070c93010b41a60121070c92010b41a70121070c91010b41a80121070c90010b41a90121070c8f010b41aa0121070c8e010b41ab0121070c8d010b200041013602002000200241d8006a41047222012902003702042000410c6a200141086a2902003702000c8f010b200228026010290c8a010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8c010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8a010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c88010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c86010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c84010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c82010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c80010b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7e0b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7c0b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7a0b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c780b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c760b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c740b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c720b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c700b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6e0b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6c0b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6a0b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c680b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c660b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c640b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c620b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c600b417f2005103e000b417f2009103e000b417f2009103e000b417f2009103e000b417f200541016a103e000b417f200541016a103e000b417f200541016a103e000b417f200541016a103e000b417f2001103e000b417f200541016a103e000b417f200541016a103e000b417f200541016a103e000b417f200541016a103e000b417f200541016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f200141016a103e000b417f2001103e000b417f2001103e000b417f200541016a103e000b417f200541016a103e000b20052001103e000b20052001103e000b20092003107f000b20092003107f000b20092003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b200141016a2003107f000b0240024002400240024002402007200a470d002007210a0c010b2007200a490d010240200a0d004100210a024020070d00410421090c020b20091029410421090c010b20092007410274200a410274220510282209450d020b4100210541002107034002402005411f4d0d00410f21010c080b20012802082206200128020c2203460d06200341016a22042003490d0320062004490d04200128020020036a2d0000210320082004360200200341ff00712005411f71742007722107200541076a21052003418001710d000b024020054120490d00410d21012003410f4b0d070b2007ad422086200aad84210c410921070c040b41ac87c5001058000b20054104102a000b417f2004103e000b20042006107f000b20004100360200200041106a200c3703002000410c6a2009360200200041096a200a3a0000200041086a20073a00000c020b200241013a0018200241ec006a41013602002002420137025c20024180c0c5003602582002411f36023c2002200241386a3602682002200241186a360238200241286a200241d8006a10e603410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a280200360200200a41ffffffff0371450d00200910290b200241f0006a24000bd30101017f230041106b22022400024002400240024020002d00000e03010200010b2002200128021841dcbfc500410b2001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040c020b2002200128021841e7bfc500410c2001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040c010b2002200128021841f3bfc500410d2001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040b200241106a240020000b8a0301067f230041306b2202240020012802002103024002402001280204220441037422050d00410021060c010b200341046a2107410021060340200728020020066a2106200741086a2107200541786a22050d000b0b024002400240024002400240200141146a2802000d00200621070c010b02402004450d00024002402006410f4b0d002003280204450d010b200620066a220720064f0d020b4101210541002107200241086a21060c020b41f0d2c500410041001037000b2007417f4c0d01200241086a2106024020070d0041012105410021070c010b200710272205450d020b200241003602102002200736020c200220053602082002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a29020037030020022001290200370318200241146a4180d3c500200241186a1091040d0220002006290200370200200041086a200641086a280200360200200241306a24000f0b1039000b20074101102a000b4198d3c5004133200241186a41ccd3c50010a201000bf30603067f017e067f230041c0006b2202240041002103410021040240024002400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005107f000b200241013a000f2002413c6a41013602002002420137022c20024180c0c5003602282002411f3602142002200241106a36023820022002410f6a360210200241186a200241286a10e603410521030c020b200128020020066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b200241086a200241186a41086a280200220136020020022002290218220837030020002003360204200041086a2008370200200041106a2001360200200041013602000c050b410421090240024020040d004100210a0c010b4100210a4100210b0340200b220c41016a210b4100210341002105024002400240034002402003411f4d0d00410f21010c020b024002402001280208220d200128020c2206460d00200641016a22072006490d09200d20074f0d012007200d107f000b200241013a00002002413c6a41013602002002420137022c20024180c0c5003602282002411f3602142002200241106a36023820022002360210200241186a200241286a10e60320022802182103200228021c2106200228022021074100210e410521010c030b200128020020066a2d000021062001200736020c200641ff00712003411f71742005722105200341076a21032006418001710d000b20034120490d0220064110490d02410d21010b0b20004101360200200041106a20073602002000410c6a2006360200200041086a20033602002000200e410874200172360204200a450d07200910290c070b0240200a200c470d00200a4101742203200a41016a220620062003491b220341ffffffff03712003470d06200341027422064100480d0602400240200a0d002006102721090c010b2009200a4102742006102821090b2009450d052003210a0b2005410876210e2009200c4102746a2005360200200b2004470d000b0b20002009360204200041003602002000410c6a2004360200200041086a200a3602000c040b417f2007103e000b417f2007103e000b20064104102a000b102b000b200241c0006a24000bf6d60202097f017e230041106b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df50120044101742208200520052008491b22084100480df5010240024020040d002008102721050c010b200628020020042008102821050b2005450dad0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df50120044101742208200520052008491b22084100480df5010240024020040d002008102721050c010b200628020020042008102821050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df40120044101742208200520052008491b22084100480df4010240024020040d002008102721050c010b200628020020042008102821050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df40120044101742208200520052008491b22084100480df4010240024020040d002008102721050c010b200628020020042008102821050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df30120044101742208200520052008491b22084100480df3010240024020040d002008102721050c010b200628020020042008102821050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df30120044101742208200520052008491b22084100480df3010240024020040d002008102721050c010b200628020020042008102821050b2005450db00120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490df00120044101742207200620062007491b22074100480df0010240024020040d002007102721060c010b200928020020042007102821060b2006450db00120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df1012004410174220a20062006200a491b220a4100480df1010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490def0120044101742207200620062007491b22074100480def010240024020040d002007102721060c010b200928020020042007102821060b2006450db10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df0012004410174220a20062006200a491b220a4100480df0010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210a2001410c6a2802002104200141086a2802002109200141046a280200210b02400240200241086a2802002002410c6a2802002201460d00200a28020021050c010b200141016a22052001490dee0120014101742206200520052006491b22064100480dee010240024020010d002006102721050c010b200a28020020012006102821050b2005450db20120022005360204200241086a20063602002002410c6a28020021010b2002410c6a2206200141016a360200200520016a410e3a000020032009200b200b20094102746a200210e00320032d0000411a470d9303200241086a2107034002400240200728020020062802002201460d00200a28020021050c010b200141016a22052001490def0120014101742208200520052008491b22084100480def010240024020010d002008102721050c010b200a28020020012008102821050b2005450db4012002200536020420072008360200200628020021010b2006200141016a360200200520016a200441807f72200441ff0071200441077622011b3a00002001210420010d000b0240200941ffffffff0371450d00200b10290b2000411a3a00000c95030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490ded0120044101742206200520052006491b22064100480ded010240024020040d002006102721050c010b200228020420042006102821050b2005450db30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490dec0120044101742207200620062007491b22074100480dec010240024020040d002007102721060c010b200928020020042007102821060b2006450db30120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490ded012004410174220a20062006200a491b220a4100480ded010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490deb0120044101742207200620062007491b22074100480deb010240024020040d002007102721060c010b200928020020042007102821060b2006450db40120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490dec012004410174220a20062006200a491b220a4100480dec010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490deb0120044101742206200520052006491b22064100480deb010240024020040d002006102721050c010b200928020020042006102821050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dea0120044101742206200520052006491b22064100480dea010240024020040d002006102721050c010b200228020420042006102821050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490de90120044101742206200520052006491b22064100480de9010240024020040d002006102721050c010b200228020420042006102821050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de80120044101742207200620062007491b22074100480de8010240024020040d002007102721060c010b200928020020042007102821060b2006450db60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de9012004410174220a20062006200a491b220a4100480de9010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db801200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de70120044101742207200620062007491b22074100480de7010240024020040d002007102721060c010b200928020020042007102821060b2006450db70120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de8012004410174220a20062006200a491b220a4100480de8010240024020040d00200a102721060c010b20092802002004200a102821060b2006450db901200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de60120044101742207200620062007491b22074100480de6010240024020040d002007102721060c010b200928020020042007102821060b2006450db80120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de7012004410174220a20062006200a491b220a4100480de7010240024020040d00200a102721060c010b20092802002004200a102821060b2006450dba01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de50120044101742207200620062007491b22074100480de5010240024020040d002007102721060c010b200928020020042007102821060b2006450db90120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de6012004410174220a20062006200a491b220a4100480de6010240024020040d00200a102721060c010b20092802002004200a102821060b2006450dbb01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de40120044101742207200620062007491b22074100480de4010240024020040d002007102721060c010b200928020020042007102821060b2006450dba0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de5012004410174220a20062006200a491b220a4100480de5010240024020040d00200a102721060c010b20092802002004200a102821060b2006450dbc01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de30120044101742208200720072008491b22084100480de3010240024020040d002008102721070c010b200a28020020042008102821070b2007450dbb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de4012004410174220b20072007200b491b220b4100480de4010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dbd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de40120044101742209200620062009491b22094100480de4010240024020040d002009102721060c010b200a28020020042009102821060b2006450dbe012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de20120044101742208200720072008491b22084100480de2010240024020040d002008102721070c010b200a28020020042008102821070b2007450dbd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de3012004410174220b20072007200b491b220b4100480de3010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dbf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de30120044101742209200620062009491b22094100480de3010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de10120044101742208200720072008491b22084100480de1010240024020040d002008102721070c010b200a28020020042008102821070b2007450dbf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de2012004410174220b20072007200b491b220b4100480de2010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de20120044101742209200620062009491b22094100480de2010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de00120044101742208200720072008491b22084100480de0010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de1012004410174220b20072007200b491b220b4100480de1010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de10120044101742209200620062009491b22094100480de1010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddf0120044101742208200720072008491b22084100480ddf010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de0012004410174220b20072007200b491b220b4100480de0010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de00120044101742209200620062009491b22094100480de0010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dde0120044101742208200720072008491b22084100480dde010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddf012004410174220b20072007200b491b220b4100480ddf010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddf0120044101742209200620062009491b22094100480ddf010240024020040d002009102721060c010b200a28020020042009102821060b2006450dc8012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddd0120044101742208200720072008491b22084100480ddd010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc70120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dde012004410174220b20072007200b491b220b4100480dde010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dc901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dde0120044101742209200620062009491b22094100480dde010240024020040d002009102721060c010b200a28020020042009102821060b2006450dca012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddc0120044101742208200720072008491b22084100480ddc010240024020040d002008102721070c010b200a28020020042008102821070b2007450dc90120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddd012004410174220b20072007200b491b220b4100480ddd010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dcb01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddd0120044101742209200620062009491b22094100480ddd010240024020040d002009102721060c010b200a28020020042009102821060b2006450dcc012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddb0120044101742208200720072008491b22084100480ddb010240024020040d002008102721070c010b200a28020020042008102821070b2007450dcb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddc012004410174220b20072007200b491b220b4100480ddc010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dcd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddc0120044101742209200620062009491b22094100480ddc010240024020040d002009102721060c010b200a28020020042009102821060b2006450dce012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dda0120044101742208200720072008491b22084100480dda010240024020040d002008102721070c010b200a28020020042008102821070b2007450dcd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddb012004410174220b20072007200b491b220b4100480ddb010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dcf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddb0120044101742209200620062009491b22094100480ddb010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd90120044101742208200720072008491b22084100480dd9010240024020040d002008102721070c010b200a28020020042008102821070b2007450dcf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dda012004410174220b20072007200b491b220b4100480dda010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dda0120044101742209200620062009491b22094100480dda010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd80120044101742208200720072008491b22084100480dd8010240024020040d002008102721070c010b200a28020020042008102821070b2007450dd10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd9012004410174220b20072007200b491b220b4100480dd9010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd90120044101742209200620062009491b22094100480dd9010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd70120044101742208200720072008491b22084100480dd7010240024020040d002008102721070c010b200a28020020042008102821070b2007450dd30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd8012004410174220b20072007200b491b220b4100480dd8010240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd80120044101742209200620062009491b22094100480dd8010240024020040d002009102721060c010b200a28020020042009102821060b2006450dd6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd60120044101742208200720072008491b22084100480dd6010240024020040d002008102721070c010b200a28020020042008102821070b2007450dd50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da3022004410174220b20072007200b491b220b4100480da3020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dd801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da30220044101742209200620062009491b22094100480da3020240024020040d002009102721060c010b200a28020020042009102821060b2006450dd9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da10220044101742208200720072008491b22084100480da1020240024020040d002008102721070c010b200a28020020042008102821070b2007450dd80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da2022004410174220b20072007200b491b220b4100480da2020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dda01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da20220044101742209200620062009491b22094100480da2020240024020040d002009102721060c010b200a28020020042009102821060b2006450ddb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da00220044101742208200720072008491b22084100480da0020240024020040d002008102721070c010b200a28020020042008102821070b2007450dda0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da1022004410174220b20072007200b491b220b4100480da1020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450ddc01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da10220044101742209200620062009491b22094100480da1020240024020040d002009102721060c010b200a28020020042009102821060b2006450ddd012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9f0220044101742208200720072008491b22084100480d9f020240024020040d002008102721070c010b200a28020020042008102821070b2007450ddc0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da0022004410174220b20072007200b491b220b4100480da0020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dde01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da00220044101742209200620062009491b22094100480da0020240024020040d002009102721060c010b200a28020020042009102821060b2006450ddf012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9e0220044101742208200720072008491b22084100480d9e020240024020040d002008102721070c010b200a28020020042008102821070b2007450dde0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9f022004410174220b20072007200b491b220b4100480d9f020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9f0220044101742209200620062009491b22094100480d9f020240024020040d002009102721060c010b200a28020020042009102821060b2006450de1012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9d0220044101742208200720072008491b22084100480d9d020240024020040d002008102721070c010b200a28020020042008102821070b2007450de00120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9e022004410174220b20072007200b491b220b4100480d9e020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9e0220044101742209200620062009491b22094100480d9e020240024020040d002009102721060c010b200a28020020042009102821060b2006450de3012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9c0220044101742208200720072008491b22084100480d9c020240024020040d002008102721070c010b200a28020020042008102821070b2007450de20120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9d022004410174220b20072007200b491b220b4100480d9d020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9d0220044101742209200620062009491b22094100480d9d020240024020040d002009102721060c010b200a28020020042009102821060b2006450de5012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9b0220044101742208200720072008491b22084100480d9b020240024020040d002008102721070c010b200a28020020042008102821070b2007450de40120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9c022004410174220b20072007200b491b220b4100480d9c020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9c0220044101742209200520052009491b22094100480d9c020240024020040d002009102721050c010b200a28020020042009102821050b2005450de7012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a0220044101742208200720072008491b22084100480d9a020240024020040d002008102721070c010b200a28020020042008102821070b2007450de60120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b022004410174220b20072007200b491b220b4100480d9b020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450de801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b0220044101742209200620062009491b22094100480d9b020240024020040d002009102721060c010b200a28020020042009102821060b2006450de9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d990220044101742208200720072008491b22084100480d99020240024020040d002008102721070c010b200a28020020042008102821070b2007450de80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a022004410174220b20072007200b491b220b4100480d9a020240024020040d00200b102721070c010b200a2802002004200b102821070b2007450dea01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a0220044101742209200620062009491b22094100480d9a020240024020040d002009102721060c010b200a28020020042009102821060b2006450deb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d980220044101742208200520052008491b22084100480d98020240024020040d002008102721050c010b200628020020042008102821050b2005450dea0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d980220044101742208200520052008491b22084100480d98020240024020040d002008102721050c010b200628020020042008102821050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d970220044101742208200520052008491b22084100480d97020240024020040d002008102721050c010b200628020020042008102821050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d970220044101742208200520052008491b22084100480d97020240024020040d002008102721050c010b200628020020042008102821050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d960220044101742207200520052007491b22074100480d96020240024020040d002007102721050c010b200228020420042007102821050b2005450dec0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a000020032006200210e1032003210220032d0000411a470df0020c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d950220044101742206200520052006491b22064100480d95020240024020040d002006102721050c010b200228020420042006102821050b2005450dec0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c200210e2032003210220032d0000411a470def020c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d940220044101742208200520052008491b22084100480d94020240024020040d002008102721050c010b200628020020042008102821050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d940220054101742204200820082004491b22044100480d94020240024020050d002004102721050c010b200628020020052004102821050b2005450ded0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d930220044101742207200520052007491b22074100480d93020240024020040d002007102721050c010b200628020020042007102821050b2005450ded0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d930220054101742204200720072004491b22044100480d93020240024020050d002004102721050c010b200628020020052004102821050b2005450dee0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d920220044101742206200520052006491b22064100480d92020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d910220044101742206200520052006491b22064100480d91020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d900220044101742206200520052006491b22064100480d90020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f0220044101742206200520052006491b22064100480d8f020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e0220044101742206200520052006491b22064100480d8e020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d0220044101742206200520052006491b22064100480d8d020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c0220044101742206200520052006491b22064100480d8c020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b0220044101742206200520052006491b22064100480d8b020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a0220044101742206200520052006491b22064100480d8a020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d890220044101742206200520052006491b22064100480d89020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d880220044101742206200520052006491b22064100480d88020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d870220044101742206200520052006491b22064100480d87020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d860220044101742206200520052006491b22064100480d86020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d850220044101742206200520052006491b22064100480d85020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d840220044101742206200520052006491b22064100480d84020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d830220044101742206200520052006491b22064100480d83020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d820220044101742206200520052006491b22064100480d82020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d810220044101742206200520052006491b22064100480d81020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d800220044101742206200520052006491b22064100480d80020240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff0120044101742206200520052006491b22064100480dff010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe0120044101742206200520052006491b22064100480dfe010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd0120044101742206200520052006491b22064100480dfd010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc0120044101742206200520052006491b22064100480dfc010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb0120044101742206200520052006491b22064100480dfb010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa0120044101742206200520052006491b22064100480dfa010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df90120044101742206200520052006491b22064100480df9010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df80120044101742206200520052006491b22064100480df8010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df50120044101742206200520052006491b22064100480df5010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df40120044101742206200520052006491b22064100480df4010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df30120044101742206200520052006491b22064100480df3010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df00120044101742206200520052006491b22064100480df0010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490def0120044101742206200520052006491b22064100480def010240024020040d002006102721050c010b200228020420042006102821050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dba0220044101742206200520052006491b22064100480dba020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db90220044101742206200520052006491b22064100480db9020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db80220044101742206200520052006491b22064100480db8020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db70220044101742206200520052006491b22064100480db7020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db60220044101742206200520052006491b22064100480db6020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db50220044101742206200520052006491b22064100480db5020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db40220044101742206200520052006491b22064100480db4020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db30220044101742206200520052006491b22064100480db3020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db20220044101742206200520052006491b22064100480db2020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db10220044101742206200520052006491b22064100480db1020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db00220044101742206200520052006491b22064100480db0020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daf0220044101742206200520052006491b22064100480daf020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae0220044101742206200520052006491b22064100480dae020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad0220044101742206200520052006491b22064100480dad020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac0220044101742206200520052006491b22064100480dac020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dab0220044101742206200520052006491b22064100480dab020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daa0220044101742206200520052006491b22064100480daa020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da90220044101742206200520052006491b22064100480da9020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da80220044101742206200520052006491b22064100480da8020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da70220044101742206200520052006491b22064100480da7020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da60220044101742206200520052006491b22064100480da6020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da50220044101742206200520052006491b22064100480da5020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da40220044101742206200520052006491b22064100480da4020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da30220044101742206200520052006491b22064100480da3020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da20220044101742206200520052006491b22064100480da2020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da10220044101742206200520052006491b22064100480da1020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da00220044101742206200520052006491b22064100480da0020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f0220044101742206200520052006491b22064100480d9f020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9e0220044101742206200520052006491b22064100480d9e020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9d0220044101742206200520052006491b22064100480d9d020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9c0220044101742206200520052006491b22064100480d9c020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9b0220044101742206200520052006491b22064100480d9b020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9a0220044101742206200520052006491b22064100480d9a020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d990220044101742206200520052006491b22064100480d99020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d980220044101742206200520052006491b22064100480d98020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d970220044101742206200520052006491b22064100480d97020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d960220044101742206200520052006491b22064100480d96020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d950220044101742206200520052006491b22064100480d95020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d940220044101742206200520052006491b22064100480d94020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d930220044101742206200520052006491b22064100480d93020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d920220044101742206200520052006491b22064100480d92020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d910220044101742206200520052006491b22064100480d91020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d900220044101742206200520052006491b22064100480d90020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f0220044101742206200520052006491b22064100480d8f020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e0220044101742206200520052006491b22064100480d8e020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d0220044101742206200520052006491b22064100480d8d020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c0220044101742206200520052006491b22064100480d8c020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b0220044101742206200520052006491b22064100480d8b020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a0220044101742206200520052006491b22064100480d8a020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d890220044101742206200520052006491b22064100480d89020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d880220044101742206200520052006491b22064100480d88020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d870220044101742206200520052006491b22064100480d87020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d860220044101742206200520052006491b22064100480d86020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d850220044101742206200520052006491b22064100480d85020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d840220044101742206200520052006491b22064100480d84020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d830220044101742206200520052006491b22064100480d83020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d820220044101742206200520052006491b22064100480d82020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d810220044101742206200520052006491b22064100480d81020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d800220044101742206200520052006491b22064100480d80020240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff0120044101742206200520052006491b22064100480dff010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe0120044101742206200520052006491b22064100480dfe010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd0120044101742206200520052006491b22064100480dfd010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc0120044101742206200520052006491b22064100480dfc010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb0120044101742206200520052006491b22064100480dfb010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa0120044101742206200520052006491b22064100480dfa010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df90120044101742206200520052006491b22064100480df9010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df80120044101742206200520052006491b22064100480df8010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df50120044101742206200520052006491b22064100480df5010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df40120044101742206200520052006491b22064100480df4010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df30120044101742206200520052006491b22064100480df3010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df00120044101742206200520052006491b22064100480df0010240024020040d002006102721050c010b200228020420042006102821050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc0120044101742206200520052006491b22064100480dfc010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb0120044101742206200520052006491b22064100480dfb010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa0120044101742206200520052006491b22064100480dfa010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df90120044101742206200520052006491b22064100480df9010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df80120044101742206200520052006491b22064100480df8010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df70120044101742206200520052006491b22064100480df7010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df60120044101742206200520052006491b22064100480df6010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df50120044101742206200520052006491b22064100480df5010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df40120044101742206200520052006491b22064100480df4010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df30120044101742206200520052006491b22064100480df3010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df20120044101742206200520052006491b22064100480df2010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df10120044101742206200520052006491b22064100480df1010240024020040d002006102721050c010b200228020420042006102821050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411a3a000020012d00004109470df201200141086a28020041ffffffff0371450df201200141046a28020010290cf2010b20064101102a000b20064101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20064101102a000b20064101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20064101102a000b20084101102a000b20064101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20064101102a000b20064101102a000b20064101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20074101102a000b200a4101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b102b000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b200b4101102a000b20094101102a000b20084101102a000b20084101102a000b20084101102a000b20084101102a000b20074101102a000b20064101102a000b20084101102a000b20044101102a000b20074101102a000b20044101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b102b000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b102b000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b20064101102a000b102b000b20002003290300370200200041086a200341086a290300370200200941ffffffff0371450d01200b10290c010b20002002290200370200200041086a200241086a29020037020020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200341106a24000b8307010c7f200028021021030240024002400240200028020822044101460d0020030d012000280218200120022000411c6a28020028020c11050021030c030b2003450d010b0240024020020d00410021020c010b200120026a2105200041146a28020041016a21064100210720012103200121080340200341016a210902400240024020032c0000220a417f4a0d000240024020092005470d004100210b200521030c010b20032d0001413f71210b200341026a220921030b200a411f71210c0240200a41ff0171220a41df014b0d00200b200c41067472210a0c020b0240024020032005470d004100210d2005210e0c010b20032d0000413f71210d200341016a2209210e0b200d200b41067472210b0240200a41f0014f0d00200b200c410c7472210a0c020b02400240200e2005470d004100210a200921030c010b200e41016a2103200e2d0000413f71210a0b200b410674200c411274418080f0007172200a72220a418080c400470d020c040b200a41ff0171210a0b200921030b02402006417f6a2206450d00200720086b20036a21072003210820052003470d010c020b0b200a418080c400460d00024002402007450d0020072002460d0041002103200720024f0d01200120076a2c00004140480d010b200121030b2007200220031b21022003200120031b21010b20040d002000280218200120022000411c6a28020028020c1105000f0b4100210902402002450d002002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b0240200220096b200028020c2206490d002000280218200120022000411c6a28020028020c1105000f0b410021074100210902402002450d00410021092002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b200920026b20066a210a024002400240410020002d0030220320034103461b0e0402000100020b200a21074100210a0c010b200a4101762107200a41016a410176210a0b200741016a2103024003402003417f6a2203450d0120002802182000280204200028021c280210110400450d000b41010f0b2000280204210941012103200028021820012002200028021c28020c1105000d00200a41016a2103200028021c210a20002802182100034002402003417f6a22030d0041000f0b20002009200a280210110400450d000b41010f0b20030bfb07030e7f017e017f200241086a2103200241046a210420012802002205210602400240024002400240034002400240200428020020032802002207460d00200228020021080c010b200741016a22082007490d0220074101742209200820082009491b22094100480d020240024020070d002009102721080c010b200228020020072009102821080b2008450d032002200836020020042009360200200328020021070b2003200741016a360200200820076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b2001280204220a2001410c6a2802002206410c6c6a210b200141086a280200210c200a21072006450d03200a21072005450d03200b41746a210d200241086a210841002107200a210e02400340200e2103024003402003280200220f0d01200741016a2107200b2003410c6a2203470d000c080b0b2003410c6a210e200741016a21102005417f6a2105200341046a290200211102400240034002400240200241046a220428020020082802002206460d00200228020021090c010b200641016a22092006490d0620064101742201200920092001491b22014100480d060240024020060d002001102721090c010b200228020020062001102821090b2009450d022002200936020020042001360200200828020021060b2008200641016a360200200920066a200741807f72200741ff0071200741077622061b3a0000200621072006450d020c000b0b20014101102a000b2011422088a7221221060240034002400240200428020020082802002207460d00200228020021090c010b200741016a22092007490d0520074101742201200920092001491b22014100480d050240024020070d002001102721090c010b200228020020072001102821090b2009450d022002200936020020042001360200200828020021070b2008200741016a360200200920076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b0240024020042802002206200828020022076b2012490d00200228020021060c010b200720126a22092007490d0420064101742207200920092007491b22074100480d040240024020060d002007102721060c010b200228020020062007102821060b2006450d032002200636020020042007360200200828020021070b2008200720126a360200200620076a200f201210ce041a02402011a7450d00200f10290b200d2003460d052010210720050d010c050b0b20014101102a000b20074101102a000b102b000b20094101102a000b2003410c6a21070b2007200b460d000340024020072802002206450d00200741046a280200450d00200610290b2007410c6a2207200b470d000b0b0240200c450d00200a10290b2000411a3a00000bcb0401067f200441046a2105024002400240024002400240200441086a2802002004410c6a2802002206460d00200528020021070c010b200641016a22072006490d0420064101742208200720072008491b22084100480d040240024020060d002008102721070c010b200528020020062008102821070b2007450d0120042007360204200441086a20083602002004410c6a28020021060b2004410c6a2208200641016a360200200720066a20024101463a0000200441086a2109034002400240200928020020082802002206460d00200528020021070c010b200641016a22072006490d052006410174220a20072007200a491b220a4100480d050240024020060d00200a102721070c010b20052802002006200a102821070b2007450d03200420073602042009200a360200200828020021060b2008200641016a360200200720066a200141807f72200141ff0071200141077622061b3a00002006210120060d000b024020024101470d002004410c6a2107200441086a2108034002400240200828020020072802002206460d00200528020021010c010b200641016a22012006490d0620064101742209200120012009491b22094100480d060240024020060d002009102721010c010b200528020020062009102821010b2001450d052004200136020420082009360200200728020021060b2007200641016a360200200120066a200341807f72200341ff0071200341077622061b3a00002006210320060d000b0b2000411a3a00000f0b20084101102a000b200a4101102a000b20094101102a000b102b000bc30701097f230041d0006b2202240002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d0420032005490d072001280200220620046a2d000021072001200536020c0240200741014d0d00410c21040c020b4100210820070e020302030b200241013a001f200241cc006a41013602002002420137023c20024180c0c5003602382002411f3602342002200241306a36024820022002411f6a360230200241206a200241386a10e6032002411a6a200241286a28020036010020022002290320370112200220022901103703002002200241166a290100370106410521040b200020073a0005200020043a000420002002290300370106200041013602002000410c6a20022901063701000c060b410121080b410120036b2109200441026a2104410021074100210a02400240034002402007411f4d0d00410f21070c020b02400240200920046a4102460d002004450d06200320044f0d0120042003107f000b200241013a0000200241cc006a41013602002002420137023c20024180c0c5003602382002411f3602342002200241306a36024820022002360230200241106a200241386a10e603410521070c020b200620046a417f6a2d000021052001200436020c200541ff00712007411f7174200a72210a200441016a2104200741076a21072005418001710d000b20074120490d01410d210720054110490d010b2000200736020420004101360200200041086a2002290210370200200041106a200241106a41086a2802003602000c050b0240024020080d00410021040c010b2004417f6a2104410021074100210802400240034002402007411f4d0d00410f21040c020b0240024020032004460d002004417f460d082003200441016a22094f0d01200441016a2003107f000b200241013a0000200241cc006a41013602002002420137023c20024180c0c5003602382002411f3602342002200241306a36024820022002360230200241106a200241386a10e603410521040c020b200620046a2d000021052001200936020c200541ff00712007411f71742008722108200741076a2107200921042005418001710d000b20074120490d01410d210420054110490d010b2000200436020420004101360200200041086a2002290210370200200041106a200241106a41086a2802003602000c060b410121040b2000200a360204200041003602002000410c6a2008360200200041086a20043602000c040b417f2005103e000b417f2004103e000b417f200441016a103e000b20052003107f000b200241d0006a24000ba60301077f2002410c6a2103200141086a28020022042105024002400240034002400240200241086a220628020020032802002207460d00200228020421080c010b200741016a22082007490d0420074101742209200820082009491b22094100480d040240024020070d002009102721080c010b200228020420072009102821080b2008450d022002200836020420062009360200200328020021070b2003200741016a360200200820076a200541807f72200541ff0071200541077622071b3a00002007210520070d000b200128020421032001280200210802400240200241086a28020022052002410c6a28020022076b2004490d00200228020421050c010b200720046a22062007490d0320054101742207200620062007491b22074100480d030240024020050d002007102721050c010b200228020420052007102821050b2005450d0220022005360204200241086a20073602002002410c6a28020021070b2002410c6a200720046a360200200520076a2008200410ce041a02402003450d00200810290b2000411a3a00000f0b20094101102a000b20074101102a000b102b000b8b07010b7f230041d0086b22022400410021034100210402400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005107f000b200241013a0089082002411c6a41013602002002420137020c20024180c0c5003602082002411f36029c08200220024198086a360218200220024189086a36029808200241b8086a200241086a10e603410521030c020b2001280200220820066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b2000200336020420004101360200200041086a20022902b808370200200041106a200241b8086a41086a2802003602000c030b024020040d002000428080808010370200200041086a42003702000c030b200241086a410041800810cd041a410121094100210a410021064100210b03400240024002400240200520076b2004200b6b22034180082003418008491b2203490d00200720036a220c2007490d022005200c4f0d01200c2005107f000b200241013a00a708200241cc086a4101360200200242013702bc0820024180c0c5003602b8082002411f36029c08200220024198086a3602c8082002200241a7086a36029808200241a8086a200241b8086a10e60320024194086a200241b0086a280200360000200220022903a80837008c08200041053a000420002002290089083700052000410c6a20024190086a29000037000020004101360200200a450d06200910290c060b200241086a200820076a200310ce041a2001200c36020c0240200a20066b2003490d00200320066a210c0c020b0240200620036a220c2006490d00200a4101742207200c200c2007491b22074100480d0002400240200a0d002007102721090c010b2009200a2007102821090b02402009450d002007210a0c030b20074101102a000b102b000b2007200c103e000b200920066a200241086a200310ce041a20042003200b6a220b4d0d02200128020c21072001280208210520012802002108200c21060c000b0b417f2007103e000b200241086a2009200c10dc01024020022802084101470d000240200a450d00200910290b200041083a0004200041013602000c010b200020093602042000410c6a200c360200200041086a200a360200200041003602000b200241d0086a24000b1600200120002802002200280200200028020810e9030bef0201067f230041c0006b2202240041002103410021040240024003400240024002402003411f4b0d002001280204220520012802082206460d01200641016a22072006490d04200520074f0d0220072005107f000b200041013602002000410f3a00040c040b200241013a000f200241346a41013602002002420137022420024180c0c5003602202002411f36023c2002200241386a36023020022002410f6a360238200241106a200241206a10e6032002410b6a200241186a28020036000020022002290310370003200041053a0004200020022900003700052000410c6a200241076a290000370000200041013602000c030b200128020020066a2d0000210620012007360208200641ff00712003411f71742004722104200341076a21032006418001710d000b0240024020034120490d002006410f4b0d010b20004100360200200020043602040c020b200041013602002000410d3a00040c010b417f2007103e000b200241c0006a24000bdb06010a7f20012802042103200128020021044100210541012106410021072001280208220821090240024002400240024002400340024020072005470d002005410174220a200541016a220b200b200a491b220a4100480d070240024020050d00200a102721060c010b20062005200a102821060b2006450d02200a21050b200620076a200941807f72200941ff00712009410776220a1b3a0000200741016a2107200a2109200a0d000b200520076b20084f0d02200720086a22092007490d052005410174220a20092009200a491b220941004e0d010c050b200a4101102a000b0240024020050d002009102721060c010b200620052009102821060b2006450d01200921050b200620076a2004200810ce041a02402003450d00200410290b200128020c210c0240200520086b20076b200141146a2802002209490d00200820096a20076a21030c020b200820076a220a20096a2203200a490d022005410174220a20032003200a491b220a4100480d020240024020050d00200a102721060c010b20062005200a102821060b02402006450d00200a21050c020b200a4101102a000b20094101102a000b200620086a20076a200c200910ce041a200241086a210b200241046a210820032109024002400340024002402008280200200b2802002207460d002002280200210a0c010b200741016a220a2007490d0420074101742204200a200a2004491b22044100480d040240024020070d0020041027210a0c010b2002280200200720041028210a0b200a450d022002200a36020020082004360200200b28020021070b200b200741016a360200200a20076a200941807f72200941ff0071200941077622071b3a00002007210920070d000b02400240200241046a2802002209200241086a28020022076b2003490d00200228020021090c010b200720036a220a2007490d0320094101742207200a200a2007491b22074100480d030240024020090d002007102721090c010b200228020020092007102821090b2009450d0220022009360200200241046a2007360200200241086a28020021070b200241086a200720036a360200200920076a2006200310ce041a02402005450d00200610290b2000411a3a00000240200141106a280200450d00200c10290b0f0b20044101102a000b20074101102a000b102b000be5bc0106077f017e047f017e197f027e230041f080046b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280204220320012802082204460d00200441016a22052004490d02200320054f0d0120052003107f000b200241013a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022802d88004210420022802dc8004210120004101360200200041003a00042001450d1d200410290c1d0b200128020020046a2d00002104200120053602082004410b4b0d02024020040e0c00100f0e0d0c0b0a02060504000b200241c0006a200110f0034101210620022802442107024020022802404101470d0020074108762108200241d0006a2802002101200241c0006a41086a29030021090c1c0b4100210a200241c0006a41004180800110cd041a4100210b410021032007450d10410121064100210b410021054100210c034002400240024002402001280204220d200128020822036b2007200c6b220441808001200441808001491b2204490d00200320046a22082003490d02200d20084f0d012008200d107f000b200241013a00c88004200241ec80046a4101360200200242013702dc800420024180c0c5003602d880042002411f3602242002200241206a3602e880042002200241c880046a360220200241286a200241d880046a10e6032002290328210920022802302101410521070240200b450d00200610290b0c1f0b200241c0006a200128020020036a200410ce041a200120083602080240200b20056b2004490d00200420056a21030c020b200520046a22032005490d14200b4101742208200320032008491b22084100480d1402400240200b0d002008102721060c010b2006200b2008102821060b02402006450d002008210b0c020b20084101102a000b20032008103e000b200620056a200241c0006a200410ce041a2003210520072004200c6a220c4b0d000c110b0b417f2005103e000b200241c0006a200110f303024020022802404101470d00200041013602002000200241c0006a41047222012902003702042000410c6a200141086a2902003702000c1b0b200241d4006a2802002108200241d0006a2802002101200241cc006a2802002105200241c8006a280200210b2002280244210c410021044100210302400240034002402004411f4d0d00410f21010c0a0b20052001460d082001417f460d012005200141016a2206490d02200c20016a2d0000220a41ff00712004411f71742003722103200441076a210420062101200a418001710d000b20044120490d06410d2101200a410f4b0d080c060b417f200141016a103e000b200141016a2005107f000b200041123a000420004101360200200041056a20043a00000c190b200241c0006a200110f3030240024020022802404101470d00200228024422014108762106200241c0006a41086a2903002209422088210e200241d0006a280200210a0c010b200241386a200241d4006a280200360200200241306a200241cc006a29020037030020022002290244370328410021064100210141002105024002400240024002400240024002400240034002402001411f4d0d00410f21070c070b2002280230220a20022802342204460d08200441016a22032004490d02200a2003490d01200228022820046a2d0000210420022003360234200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d002004410f4d0d0041002106410d21070c060b02400240024020050d004100210d410421030c010b410421034100210d4100210703402007220f41016a2107410021014100210c02400240024002400240024003404100210602402001411f4d0d00410f21070c0f0b2002280230220b20022802342204460d01200441016a220a2004490d02200b200a490d04200228022820046a2d000021042002200a360234200441ff00712001411f7174200c72210c200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d21070c0e0b200241c0006a200241286a10e303024020022802404101470d002002280244220741087621062002280250210a200228024c210b200228024821080c0e0b200228024c21102002280248211120022802442112410021044100210b034002402004411f4d0d00410f21070c0e0b200228023022062002280234220a460d0c200a41016a2201200a490d0320062001490d0520022802282208200a6a2d0000210a20022001360234200a41ff00712004411f7174200b72210b200441076a2104200a418001710d000b20044120490d05200a410f4d0d05410d21070c0c0b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210b20022802e08004210a2009a72108410521070c0c0b417f200a103e000b417f2001103e000b200a200b107f000b20012006107f000b41002113200241c0006a41004180800410cd041a02400240200b0d0041012114410021150c010b41002113410121144100210a4100211603400240024002400240200620016b200b20166b220441808004200441808004491b2204490d00200120046a22152001490d02200620154f0d0120152006107f000b200241013a00c78004200241013602ec8004200242013702dc800420024180c0c5003602d880042002411f3602242002200241206a3602e880042002200241c780046a360220200241c880046a200241d880046a10e60320022802c88004210820022802cc8004210b20022802d08004210a410521072013450d0b201410290c0b0b200241c0006a200820016a200410ce041a2002201536023402402013200a6b2004490d002004200a6a21150c020b200a20046a2215200a490d1e20134101742201201520152001491b22014100480d1e0240024020130d002001102721140c010b201420132001102821140b02402014450d00200121130c020b20014101102a000b20012015103e000b2014200a6a200241c0006a200410ce041a200b200420166a22164d0d012002280234210120022802302106200228022821082015210a0c000b0b0240200d200f470d00200d4101742201200d41016a220420042001491b2201ad421c7e2209422088a70d1b2009a722044100480d1b02400240200d0d002004102721030c010b2003200d411c6c2004102821030b2003450d032001210d0b2003200f411c6c6a2201200c41087622043b000120012014360210200120123602042001200c3a0000200141036a20044110763a0000200141186a2015360200200141146a20133602002001410c6a2010360200200141086a201136020020072005470d000b0b200228023420022802384621010240200228022c450d00200228022810290b2001450d072005ad422086200dad842109410c21040c1c0b20044104102a000b2003200a107f000b417f2003103e000b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210b20022802e08004210a2009a72108410521070b02402010450d0020104104742104201221010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b410021062011450d00201210290b0240200f450d002003200f411c6c6a210c20032105034002402005410c6a2802002204450d0020052802042101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b0240200541086a280200450d00200528020410290b2005411c6a21010240200541146a280200450d00200528021010290b200121052001200c470d000b0b200d450d03200310290c030b4100210b410021080c020b20024103410220011b3a00c88004200241c0006a41146a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d88004210920022802e08004210a02402005450d0020032005411c6c6a210620032105034002402005410c6a2802002204450d0020052802042101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b0240200541086a280200450d00200528020410290b2005411c6a21010240200541146a280200450d00200528021010290b2001210520012006470d000b0b2009422088210e4105210141002106200d450d02200310290c020b200241013a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210b20022802e08004210a2009a7210841052107410021060b2006410874200741ff0171722101200bad220e4220862008ad842109200228022c450d00200228022810290b20004101360200200041106a200a360200200041086a200e422086200942ffffffff0f838437020020002006410874200141ff0171723602040c180b200241c0006a200110f3030240024020022802404101470d002002280244220b4108762101200241c0006a41086a2903002209422088210e200241d0006a28020021080c010b200241d4006a2802002114200241d0006a2802002101200241cc006a280200210a200241c8006a28020021132002280244210c410021044100210602400240024002400240024002400240024002400240024002400240034002402004411f4d0d00410f210b0c020b02400240200a2001460d002001417f460d06200a200141016a22054f0d01200141016a200a107f000b200241013a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d88004210920022802e0800421084105210b0c030b200c20016a2d0000220341ff00712004411f71742006722106200441076a2104200521012003418001710d000b20044120490d0220034110490d02410d210b0b0b2009422088a7210d2009a721160c0b0b024002400240024002400240024002400240024002400240024020060d0041002117410421030c010b200241c9006a211841042103410021174100211903402019221a41016a2119410021014100210b034002402001411f4d0d00410f210b0c170b200a2005460d142005417f460d0d200a200541016a2204490d06200c20056a2d0000220741ff00712001411f7174200b72210b200141076a2101200421052007418001710d000b024020014120490d002007410f4d0d00410d210b0c160b4100210f200241c0006a41004180800110cd041a02400240200b0d00410121102004210541002111410021070c010b41002111410121104100211541002112034002400240200a20046b200b20126b220141808001200141808001491b2201490d00200420016a22052004490d0f200a20054f0d012005200a107f000b200241013a00c78004200241013602ec8004200242013702dc800420024180c0c5003602d880042002411f3602242002200241206a3602e880042002200241c780046a360220200241c880046a200241d880046a10e60320022903c880042209422088a7210d20022802d0800421082009a721164105210b2011450d18201010290c180b200241c0006a200c20046a200110ce041a02400240201120156b2001490d00200120156a21070c010b201520016a22072015490d2820114101742204200720072004491b22044100480d280240024020110d002004102721100c010b201020112004102821100b2010450d0d200421110b201020156a200241c0006a200110ce041a2005210420072115200b200120126a22124b0d000b0b20024100360234200220103602282002200736023820022007ad4220862011ad8437022c4100210141002112034002402001411f4d0d00410f210b0c140b2007200f460d12200f417f460d0a2007200f41016a220b490d052010200f6a2d000021042002200b360234200441ff00712001411f71742012722112200141076a2101200b210f2004418001710d000b024020014120490d002004410f4d0d00410d210b0c130b4100211b0240024020120d004104211c410021110c010b410021114104211c4100211d0340201d221e41016a211d4100210141002115024002400240034002402001411f4d0d00410f211520162101200d211f0c020b024002402002280230220f20022802342204460d00200441016a220b2004490d10200f200b4f0d01200b200f107f000b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d880042209422088a7211f20022802e0800421082009a72101410521150c020b2002280228221020046a2d000021072002200b360234200741ff00712001411f71742015722115200141076a21012007418001710d000b20014120490d0120074110490d0120162101200d211f410d21150b200141087621204101210741002104200821214100210b20012116201f210d0c010b0240024002400240200f200b460d00200441026a2101200b417f460d0e200f20014f0d012001200f107f000b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022802d88004212220022802dc8004212320022802e080042124410521150c010b2010200b6a2c00002104200220013602340240200441004e0d00411821150c010b0240200441c000710d00410621150c010b200441807f72220141ff017141fb014b0d0141062115200121040b20224108762120410121074100210b2023211f20242121202221010c010b20154180807c71210b201541087621042001417f732101410021070b200b200441ff017141087472201541ff017172210b02402007450d002020410874200141ff01717221162011450d15201c10290c150b02402011201e470d0020114101742204201141016a220720072004491b220441ffffffff01712004470d28200441037422074100480d280240024020110d0020071027211c0c010b201c201141037420071028211c0b201c450d09200421110b201c201e4103746a220420013a00042004200b360200201d2012470d000b0b4101210b41082110410021014100210741002115034020012104200241c0006a200241286a10e403024020022802404101470d0020022802502121200228024c211f200228024821162002280244210b0c120b200241d880046a41026a2201201841026a2d00003a0000200220182f00003b01d88004200228024c211e2002280250211d200228025421250240024020022d0048220f4106470d00200b417f6a210b0c010b200f417e6a41034f0d00200b41016a2226200b4f21272026210b20270d004115211f419487c50021164104210b200f4109470d11201d41ffffffff03710d100c110b200241c0006a41026a222620012d00003a0000200220022f01d880043b0140024020072015470d00200741016a22012007490d27201b20012001201b491b221541ffffffff00712015470d27201541047422014100480d270240024020070d002001102721100c010b201020042001102821100b2010450d040b201020046a2201200f3a00002001410c6a2025360200200141086a201d360200200141046a201e360200200141016a20022f01403b0000200141036a20262d00003a0000201b41026a211b200441106a2101200741016a2107200b0d000b200228023420022802384621010240200228022c450d00200228022810290b2001450d1402402017201a470d0020174101742201201741016a220420042001491b2201ad42187e2209422088a70d262009a722044100480d260240024020170d002004102721030c010b2003201741186c2004102821030b2003450d04200121170b2003201a41186c6a2201201036020c20012012360208200120113602042001201c360200200141146a2007360200200141106a201536020020192006470d000b0b2005201446210102402013450d00200c10290b2001450d142006ad4220862017ad842109410b21040c270b20014108102a000b20044104102a000b200f41016a2007107f000b200541016a200a107f000b20074104102a000b417f2001103e000b417f200b103e000b417f200f41016a103e000b20044101102a000b20042005103e000b417f200541016a103e000b417f200141016a103e000b201e10290b0b02402007450d00201021010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b02402015450d00201010290b2011450d01201c10290c010b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d880042209422088a7211f20022802e0800421212009a721164105210b0b0240200228022c450d00200228022810290b201f210d202121080c020b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210d20022802e0800421082009a721164105210b0c010b20024103410220011b3a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022802d88004211620022802dc8004210d20022802e08004210802402007450d00200441106a21054100210103400240201020016a22042d00004109470d00200441086a28020041ffffffff0371450d00200441046a28020010290b2005200141106a2201470d000b0b02402015450d00201010290b4105210b2011450d00201c10290b0240201a450d002003201a41186c6a210a2003210503400240200541046a280200450d00200528020010290b0240200541146a2802002204450d00200528020c2101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b200541186a21010240200541106a280200450d00200528020c10290b200121052001200a470d000b0b2017450d01200310290c010b20024103410220011b3a0028200241c0006a41146a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d88004210920022802e08004210802402006450d002003200641186c6a210a2003210503400240200541046a280200450d00200528020010290b0240200541146a2802002204450d00200528020c2101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b200541186a21010240200541106a280200450d00200528020c10290b200121052001200a470d000b0b2009422088210e4105210b410021012017450d01200310290c010b200b4108762101200dad220e4220862016ad8421092013450d00200c10290b20004101360200200041106a2008360200200041086a200e422086200942ffffffff0f838437020020002001410874200b41ff0171723602040c170b200241c0006a200110f3030240024020022802404101470d00200228024422014108762106200241c0006a41086a2903002209422088210e200241d0006a280200210a0c010b200241e880046a200241d4006a280200360200200241e080046a200241cc006a290200370300200220022902443703d880044100210641002101410021050240024002400240024002400240024002400240034002402001411f4d0d00410f210b0c080b20022802e08004220a20022802e480042204460d09200441016a22032004490d01200a2003490d0420022802d8800420046a2d00002104200220033602e48004200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d002004410f4d0d0041002106410d210b0c070b0240024020050d004100210d410421030c010b410421034100210d4100210803402008221641016a2108410021014100210c0240024002400240024003404100210602402001411f4d0d00410f210b0c030b20022802e08004220b20022802e480042204460d01200441016a220a2004490d09200b200a490d0c20022802d8800420046a2d000021042002200a3602e48004200441ff00712001411f7174200c72210c200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d210b0c020b200241c0006a200241d880046a10e303024020022802404101470d002002280244220b41087621062002280250210a200228024c2108200228024821070c020b200228024c21132002280248210f20022802442115200241c0006a200241d880046a10e703024020022802404101470d002002280244210b2002280250210a200228024c21082002280248210702402013450d0020134104742104201521010340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b200b4108762106200f450d02201510290c020b200228024821142002280244210702400240200228024c22010d00410021064104210b4100210a0c010b2001410274220a410275220641ffffffff03712006470d1e200a4100480d1e200a1027220b450d0d200a417c6a2110200b210120072104034020012004280200360200200141046a2101200441046a2104200a417c6a220a0d000b201041027641016a210a0b02402014450d00200710290b200d2016470d04200d4101742201200d41016a220420042001491b2201ad421c7e2209422088a70d1d2009a722044100480d1d200d0d022004102721030c030b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088a721082002280230210a2009a721074105210b0b02402016450d0020032016411c6c6a210c20032105034002402005410c6a2802002204450d0020052802042101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b0240200541086a280200450d00200528020410290b2005411c6a21010240200541146a280200450d00200528021010290b200121052001200c470d000b0b200d450d0e200310290c0e0b2003200d411c6c2004102821030b2003450d052001210d0b20032016411c6c6a2201200c41087622043b00012001200b360210200120153602042001200c3a0000200141036a20044110763a0000200141186a200a360200200141146a20063602002001410c6a2013360200200141086a200f36020020082005470d000b0b20022802e4800420022802e88004462101024020022802dc8004450d0020022802d8800410290b2001450d072005ad422086200dad842109410a21040c1a0b417f2003103e000b417f200a103e000b20044104102a000b2003200a107f000b200a200b107f000b200a4104102a000b41002108410021070c020b20024103410220011b3a00c88004200241c0006a41146a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e603200229032821092002280230210a02402005450d0020032005411c6c6a210620032105034002402005410c6a2802002204450d0020052802042101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b0240200541086a280200450d00200528020410290b2005411c6a21010240200541146a280200450d00200528021010290b2001210520012006470d000b0b2009422088210e4105210141002106200d450d02200310290c020b200241013a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088a721082002280230210a2009a721074105210b410021060b2006410874200b41ff01717221012008ad220e4220862007ad84210920022802dc8004450d0020022802d8800410290b20004101360200200041106a200a360200200041086a200e422086200942ffffffff0f838437020020002006410874200141ff0171723602040c160b200820064621010240200b450d00200c10290b02402001450d00410921040c0f0b20024103410220011b3a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e603200241e380046a200241306a280200360000200220022903283700db8004200041053a0004200020022900d880043700052000410c6a200241df80046a290000370000200041013602000c150b200241013a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e603410521010b2000200136020420004101360200200041086a20022902d88004370200200041106a200241d880046a41086a280200360200200b450d13200c10290c130b200241c0006a200110f3030240024020022802404101470d00200228024422044108762101200241c0006a41086a2903002209422088210e200241d0006a28020021060c010b200241e880046a200241d4006a280200360200200241e080046a200241cc006a290200370300200220022902443703d880044100210c4100210141002105024002400240024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f2104410021050c130b20022802e08004220a20022802e480042204460d11200441016a22032004490d01200a2003490d0820022802d8800420046a2d00002104200220033602e48004200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d2104410021050c120b0240024020050d0041002116410421030c010b410421034100210a41002116410021130340200241c0006a200241d880046a10ee03024020022802404101470d002002200229024c22093703c8800420022802482105200228024421042009a7210c0c110b200228024821152002280244210f0240024020022802e08004220420022802e480042206460d00200641016a22012006490d05200420014f0d0120012004107f000b200241013a00c78004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c780046a360220200241286a200241c0006a10e6030c0e0b200228024c211420022802d88004220c20066a2d0000210d200220013602e480040240200d41034d0d00410a21010c100b02400240024002400240200d0e0400010203000b4100210d4100210b4100210603400240200b411f4d0d00410f21010c150b20042001460d132001417f460d092004200141016a2207490d0f200c20016a2d00002108200220073602e48004200841ff0071200b411f71742006722106200b41076a210b200721012008418001710d000b4100210d200b4120490d032008410f4d0d03410d21010c130b4100210b410021060340200b411f4b0d100240024020042001460d002001417f460d0b2004200141016a22074f0d01200141016a2004107f000b200241013a00c78004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c780046a360220200241286a200241c0006a10e6030c120b200c20016a2d00002108200220073602e48004200841ff0071200b411f71742006722106200b41076a210b200721012008418001710d000b4101210d200b4120490d022008410f4d0d020c0e0b4100210b410021060340200b411f4b0d0f0240024020042001460d002001417f460d0b2004200141016a22074f0d01200141016a2004107f000b200241013a00c78004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c780046a360220200241286a200241c0006a10e6030c110b200c20016a2d00002108200220073602e48004200841ff0071200b411f71742006722106200b41076a210b200721012008418001710d000b4102210d200b4120490d012008410f4b0d0d0c010b4100210b410021060340200b411f4b0d0e0240024020042001460d002001417f460d0b2004200141016a22074f0d01200141016a2004107f000b200241013a00c78004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c780046a360220200241286a200241c0006a10e6030c100b200c20016a2d00002108200220073602e48004200841ff0071200b411f71742006722106200b41076a210b200721012008418001710d000b4103210d200b4120490d002008410f4b0d0c0b200220063602d080042002200d3602cc800420022902cc80042109024020162013470d0020164101742201201641016a220420042001491b2201ad42147e220e422088a70d1d200ea722044100480d1d0240024020160d002004102721030c010b2003201641146c2004102821030b2003450d09200121160b2003201341146c6a2201200937020c20012014360208200120153602042001200f360200200a41146a210a201341016a2201211320012005470d000b0b20022802e4800420022802e88004462101024020022802dc8004450d0020022802d8800410290b2001450d0f2005ad4220862016ad842109410821040c1e0b417f2003103e000b417f2001103e000b417f200141016a103e000b417f200141016a103e000b417f200141016a103e000b417f200141016a103e000b20044104102a000b2003200a107f000b200141016a2004107f000b410d21014100210d0c030b410f21014100210d0c020b20022802282105200229022c2109410521014100210d0c010b200241013a00c78004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c780046a360220200241286a200241c0006a10e60320022802282105200229022c2109410521010b200d4108742001722104200220093703c880042009a7210c2015450d00200f10290b20022802cc8004210602402013450d002003210103400240200141046a280200450d00200128020010290b200141146a2101200a416c6a220a0d000b0b2016450d02200310290c020b20024103410220011b3a00c88004200241c0006a41146a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e603200229032821092002280230210602402005450d00200541146c21042003210103400240200141046a280200450d00200128020010290b200141146a21012004416c6a22040d000b0b2009422088210e41052104410021012016450d02200310290c020b200241013a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088a7210c200228023021062009a72105410521040b20044108762101200cad220e4220862005ad84210920022802dc8004450d0020022802d8800410290b20004101360200200041106a2006360200200041086a200e422086200942ffffffff0f838437020020002001410874200441ff0171723602040c120b200241c0006a200110f3030240024020022802404101470d00200228024422054108762101200241c0006a41086a2903002209422088210e200241d0006a280200210a0c010b200241386a200241d4006a280200360200200241306a200241cc006a290200370300200220022902443703284100210b410021014100210602400240024002400240024002400240034002402001411f4d0d00410f21054100210c0c090b2002280230220a20022802342204460d07200441016a22052004490d01200a2005490d052002280228220c20046a2d0000210420022005360234200441ff00712001411f71742006722106200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d21054100210c0c080b024020060d00410421034100210d0c060b2006417f6a21144100211641002107410021084100210d4104210f410421030340024002400240024002400240024002400240200a2005460d00200541016a22042005490d0b200a20044f0d012004200a107f000b200241013a00c78004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c780046a360220200241c880046a200241c0006a10e60320022802c88004210c20022802cc8004210b20022802d08004210a410521130c010b200c20056a2c000021012002200436023402400240200141004e0d00411821130c010b41062113200141c00071450d00200141807f72220141ff017141fb014b0d020b0b200241e880046a200a360200200241e480046a200b360200200241e080046a200c360200200220013a00dd8004200220133a00dc80040c010b024002400240200a2004460d00200541026a21052004417f460d0b200a20054f0d012005200a107f000b200241013a00c78004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c780046a360220200241c880046a200241c0006a10e60320022802c88004210c20022802cc8004210b20022802d08004210a410521010c010b200c20046a2d00002104200220053602340240200441014b0d004100210a20040e020403040b410c21010b200241e880046a200a360200200241e480046a200b360200200241e080046a200c360200200220043a00dd8004200220013a00dc80040b200241013a00d8800420022802dc800421050c020b418002210a0b200241c0006a200241286a10e303200228024c210b2002280248210c2002280244210520022802404101470d01200241d0006a280200210a0b02402008450d00200320076a21060340024020032802082204450d0020032802002101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b200341106a21010240200341046a280200450d00200328020010290b2001210320062001470d000b0b200d450d09200f10290c090b200841016a211302402008200d470d002016201320132016491b220d41ffffffff0071200d470d11200d41047422044100480d110240024020080d0020041027210f0c010b200f200720041028210f0b200f450d05200f21030b200320076a220420053602002004410c6a20154180807c712001417f7341ff017172200a722215360200200441086a200b360200200441046a200c36020020142008460d06201641026a2116200741106a2107200228023421052002280230210a2002280228210c201321080c000b0b417f2005103e000b417f2004103e000b417f2005103e000b20044104102a000b2005200a107f000b200228023420022802384621010240200228022c450d00200228022810290b02402001450d002006ad422086200dad842109410721040c0e0b20024103410220011b3a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d88004210920022802e08004210a02402006450d00200320064104746a2106200321050340024020052802082204450d0020052802002101200441047421040340024020012d00004109470d00200141086a28020041ffffffff0371450d00200141046a28020010290b200141106a2101200441706a22040d000b0b200541106a21010240200541046a280200450d00200528020010290b2001210520012006470d000b0b2009422088210e4105210541002101200d450d02200310290c020b200241013a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210b20022802e08004210a2009a7210c410521050b20054108762101200bad220e422086200cad842109200228022c450d00200228022810290b20004101360200200041106a200a360200200041086a200e422086200942ffffffff0f838437020020002001410874200541ff0171723602040c110b200241c0006a200110f3030240024020022802404101470d00200228024422044108762105200241c0006a41086a2903002209422088210e200241d0006a28020021010c010b200241e880046a200241d4006a280200360200200241e080046a200241cc006a290200220937030020022002290244220e3703d88004200ea7210c2009a721034100210420022802e4800421014100210502400240024002400240024002400240024003402004411f4b0d0120032001460d032001417f460d042003200141016a220a490d06200c20016a2d0000220641ff00712004411f71742005722105200441076a2104200a21012006418001710d000b2002200a3602e4800420044120490d012006410f4d0d0141002104410d210c0c060b200220013602e4800441002104410f210c0c050b0240024020050d00410421034100210d0c010b4100210741002106410021014100210d410421030340200241c0006a200241d880046a10ec0320022f004520022d0047411074722104200228024c210b2002280248210820022d0044210c024020022802404101470d00200241d0006a2802002101200d450d08200310290c080b200141016a210a02402001200d470d002007200a200a2007491b220dad420c7e2209422088a70d102009a722164100480d100240024020010d002016102721030c010b200320062016102821030b2003450d050b200320066a2201200c3a0000200141036a20044110763a0000200141016a20043b0000200141086a200b360200200141046a2008360200200741026a21072006410c6a2106200a21012005200a470d000b0b20022802e4800420022802e88004462101024020022802dc8004450d0020022802d8800410290b2001450d062005ad422086200dad842109410621040c110b200220033602e48004200241013a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088a7210b200228023021012009a721084105210c410021040c040b417f200141016a103e000b20164104102a000b200141016a2003107f000b4100210b410021080b200441ffffff07712205410874200c41ff0171722104200bad220e4220862008ad84210920022802dc8004450d0120022802d8800410290c010b20024103410220011b3a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088210e200228023021014105210441002105200d450d00200310290b20004101360200200041106a2001360200200041086a200e422086200942ffffffff0f838437020020002005410874200441ff0171723602040c100b200241c0006a200110f3030240024020022802404101470d00200228024422044108762105200241c0006a41086a2903002209422088210e200241d0006a28020021010c010b200241e880046a200241d4006a280200360200200241e080046a200241cc006a290200220937030020022002290244220e3703d88004200ea7210c2009a721054100210420022802e480042101410021060240024002400240024002400240024002400240024003402004411f4b0d0120052001460d032001417f460d042005200141016a220a490d07200c20016a2d0000220341ff00712004411f71742006722106200441076a2104200a21012003418001710d000b2002200a3602e4800420044120490d012003410f4d0d0141002104410d210a0c080b200220013602e4800441002104410f210a0c070b024020060d004100210b410421030c060b2006417f6a2116410421034108210d4100210841002107034002400240024002402005200a460d00200a41016a2201200a490d07200520014f0d0120012005107f000b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e6032002280228210b200228022c210c200228023021014105210a0c010b200c200a6a2c00002104200220013602e480040240200441004e0d004118210a0c010b4107210a0240200441c000710d000c010b200441807f7222044170470d00200241c0006a200241d880046a10ec0320022f004520022d004741107472210420022d0044210a20022802404101470d0120044180feff0771410876210520022802502101200228024c210c2002280248210b0b2005410874200441ff01717221042008450d09200310290c090b200228024c21052002280248210c0240024020072008460d002008210b0c010b20084101742201200841016a220b200b2001491b220bad420c7e2209422088a70d102009a722014100480d100240024020080d002001102721030c010b20032008410c6c2001102821030b2003450d050b2003200d6a22012005360200200141796a220520043b00002001417c6a200c360200200141786a200a3a0000200541026a20044110763a000020162007460d06200741016a2107200d410c6a210d20022802e48004210a20022802e08004210520022802d88004210c200b21080c000b0b200220053602e48004200241013a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088a7210c200228023021012009a7210b4105210a410021040c060b417f200141016a103e000b417f2001103e000b20014104102a000b200141016a2005107f000b20022802e4800420022802e88004462101024020022802dc8004450d0020022802d8800410290b2001450d022006ad422086200bad842109410521040c0c0b4100210c4100210b0b200441ffffff07712205410874200a41ff0171722104200cad220e422086200bad84210920022802dc8004450d0120022802d8800410290c010b20024103410220011b3a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088210e200228023021014105210441002105200b450d00200310290b20004101360200200041106a2001360200200041086a200e422086200942ffffffff0f838437020020002005410874200441ff0171723602040c0f0b200241c0006a200110f3030240024020022802404101470d00200228024422044108762105200241c0006a41086a2903002209422088210e200241d0006a28020021010c010b200241d4006a280200210d200241d0006a2802002101200241cc006a2802002105200241c8006a28020021072002280244210c4100210b41002104410021060240024002400240024002400240034002402004411f4d0d00410f2104410021050c030b20052001460d012001417f460d032005200141016a220a490d06200c20016a2d0000220341ff00712004411f71742006722106200441076a2104200a21012003418001710d000b024020044120490d002003410f4d0d00410d2104410021050c020b410421030240024020060d00410021130c010b410021164100211303402016221541016a2116200a2101410021044100210b024002400240034002402004411f4d0d00410f21040c020b0240024020052001460d002001417f460d0b2005200141016a220a4f0d01200141016a2005107f000b200241013a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022802d88004210520022802dc8004210b20022802e080042101410521040c030b200c20016a2d0000220841ff00712004411f7174200b72210b200441076a2104200a21012008418001710d000b20044120490d0220084110490d02410d21040b0b2013450d04200310290c040b024020132015470d0020154101742201201620162001491b221341ffffffff03712013470d0e201341027422014100480d0e0240024020150d002001102721030c010b200320154102742001102821030b2003450d070b200320154102746a200b36020020162006470d000b0b200a200d46210102402007450d00200c10290b2001450d062006ad4220862013ad842109410421040c0f0b200241013a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210b20022802e0800421012009a72105410521040b200bad220e4220862005ad842109410021052007450d05200c10290c050b417f200141016a103e000b417f200141016a103e000b20014104102a000b200141016a2005107f000b20024103410220011b3a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d880042209422088210e20022802e08004210141052104410021052013450d00200310290b20004101360200200041106a2001360200200041086a200e422086200942ffffffff0f838437020020002005410874200441ff0171723602040c0e0b200241c0006a200110f3030240024020022802404101470d00200228024422044108762101200241c0006a41086a2903002209422088210e200241d0006a28020021060c010b200241e880046a200241d4006a280200360200200241e080046a200241cc006a290200370300200220022902443703d880044100210c41002101410021050240024002400240024002400240024002400240034002402001411f4d0d00410f2104410021050c0b0b20022802e08004220a20022802e480042204460d09200441016a22032004490d02200a2003490d0120022802d8800420046a2d00002104200220033602e48004200441ff00712001411f71742005722105200141076a21012004418001710d000b024020014120490d002004410f4d0d00410d2104410021050c0a0b02400240024020050d0041002116410421030c010b410421034100210a41002116410021130340200241c0006a200241d880046a10ee03200228024c210c2002280248210f20022802442110024020022802404101470d0020022802502106200f2105201021040c0a0b200241c0006a200241d880046a10ee03200228024c21112002280248211420022802442112024020022802404101470d0020022802502106201421052011210c201221040c090b024002400240024002400240024002400240024002400240024002400240024020022802e08004220620022802e48004220b460d00200b41016a2201200b490d02200620014f0d0120012006107f000b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022802282105200229022c210e4105210741002115410021060c160b20022802d88004220d200b6a2d00002104200220013602e48004410021150240200441034d0d0041092107410021060c160b024002400240024020040e0400010203000b410021154100210441002107034002402004411f4d0d00410f21070c180b0240024020062001460d002001417f460d072006200141016a22084f0d01200141016a2006107f000b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022802282105200229022c210e41052107410021150c190b200d20016a2d0000210b200220083602e48004200b41ff00712004411f71742007722107200441076a210420082101200b418001710d000b4100211520044120490d0f200b410f4d0d0f410d21070c160b0240024020062001460d00200b41026a21042001417f460d0620062004490d07200d20016a2c00002101200220043602e4800402402001417f4a0d00411821050c0e0b200141c000710d010c0c0b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e6032002290328210920022802302104410521050c0c0b200141807f7222014170470d0a200241c0006a200241d880046a10ec032002290348210920022802442107024020022802404101470d00200228025021040c0d0b410121150c0f0b200241c0006a200241d880046a10ec032002290348210920022802442107024020022802404101460d00410221150c0f0b200220022802503602482007418080807871211520074180807c712106200741087621040c0c0b0240024020062001460d00200b41026a21082001417f460d0620062008490d08200d20016a2c00002104200220083602e480040240200441004e0d0041182107410021060c180b200441c000710d010c090b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60341052107200229022c210e20022802282105410021060c160b200441807f72220441ff017141fc01490d070240024020062008460d00200b41036a21012008417f460d07200620014f0d0120012006107f000b200241013a00c88004200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022802282105200229022c210e41052107410021060c160b200d20086a2d0000210b200220013602e48004410021060240200b41014d0d00410c210741002115200b21040c160b2004417f732104410321150240200b0e020e000e0b410121060c0d0b417f2001103e000b417f200141016a103e000b417f2004103e000b20042006107f000b417f2008103e000b417f2001103e000b20082006107f000b41062107410021060c0d0b410721050b200141ff017141087420057221070b200220043602482007418080807871211520074180807c712106200741087621040b200220093703402002290244210e2009a721050c090b0b024020162013470d0020164101742201201641016a220b200b2001491b2201ad42287e220e422088a70d11200ea7220b4100480d110240024020160d00200b102721030c010b2003201641286c200b102821030b2003450d03200121160b2003201341286c6a2201201236020c2001200c3602082001200f36020420012010360200200141206a20093702002001411c6a20073602002001411a6a20063a0000200141196a20043a0000200141186a20153a0000200141146a2011360200200141106a2014360200200a41286a210a201341016a2201211320012005470d000b0b20022802e4800420022802e88004462101024020022802dc8004450d0020022802d8800410290b2001450d082005ad4220862016ad842109410321040c120b200b4104102a000b2003200a107f000b417f2003103e000b0b41002106410021040b200741ff0171200441ff0171410874722006418080fc0771722015722104200e422088a72106200ea7210c2014450d00201210290b200f450d00201010290b02402013450d002003210103400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200a41586a220a0d000b0b2016450d02200310290c020b20024103410220011b3a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e603200229032821092002280230210602402005450d00200541286c21042003210103400240200141046a280200450d00200128020010290b0240200141106a280200450d002001410c6a28020010290b200141286a2101200441586a22040d000b0b2009422088210e41052104410021012016450d02200310290c020b200241013a00c88004200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241c880046a360220200241286a200241c0006a10e60320022903282209422088a7210c200228023021062009a72105410521040b20044108762101200cad220e4220862005ad84210920022802dc8004450d0020022802d8800410290b20004101360200200041106a2006360200200041086a200e422086200942ffffffff0f838437020020002001410874200441ff0171723602040c0d0b200241c0006a200110f3030240024020022802404101470d00200228024422014108762105200241c0006a41086a2903002209422088210e200241d0006a28020021040c010b200241d4006a2802002113200241d0006a2802002101200241cc006a2802002105200241c8006a28020021072002280244210c41002108410021044100210a024002400240024002400240024002400240034002402004411f4d0d00410f21014100210a0c0a0b20052001460d082001417f460d022005200141016a2206490d01200c20016a2d0000220341ff00712004411f7174200a72210a200441076a2104200621012003418001710d000b024020044120490d002003410f4d0d00410d21014100210a0c090b024002400240200a0d0041002112410421030c010b410120056b210d4100210b4104210341002112410021110340024002400240024002400240024002400240024020052006460d00200641016a22012006490d0120052001490d050240200c20066a2d0000221641e000460d004117210f0c130b201141016a211a200641026a2101410021164100210441002108034002402004411f4d0d00410f210f0c0a0b200d20016a4102460d082001450d0320052001490d07200c20016a417f6a2d0000220641ff00712004411f71742008722108200141016a2101200441076a21042006418001710d000b024020044120490d002006410f4d0d00410d210f0c090b2001417f6a210441002115410121100240024020080d00410021170c010b4100211441002106410021170340024002400240024020052004460d00200120066a2216450d09200520164f0d0120162005107f000b200241013a0028200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022802d88004210a20022802dc8004210820022802e0800421014105210f0c010b02400240200c20046a2c0000221641004e0d004118210f0c010b4106210f201641c00071450d00201641807f72221641ff017141fb014b0d020b0b2017450d0b201010290c0b0b200641016a210f024020062017470d002014200f200f2014491b22174100480d1b0240024020060d002017102721100c010b201020062017102821100b20100d0020174101102a000b200441016a2104201020066a2016417f733a0000201441026a2114200f21062008200f470d000b0b2010411076411074221f201041087641ff0171410874221872201041ff017122107221144100210103404100211602402015411f4d0d00410f210f0c130b0240024020052004460d002004417f460d072005200441016a22064f0d01200441016a2005107f000b200241013a0028200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022802d88004210a20022802dc8004210820022d00e08004210120022d00e18004210520022f01e2800421044105210f0c130b200c20046a2d0000220f41ff00712015411f71742001722101201541076a211520062104200f418001710d000b20154120490d09200f410f4d0d09410d210f0c110b200241013a0028200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022802d88004210a20022802dc8004210820022d00e08004210120022d00e18004210520022f01e2800421044105210f0c110b417f2001103e000b417f2001103e000b417f2016103e000b417f200441016a103e000b20012005107f000b20012005107f000b200241013a0028200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210820022802e0800421012009a7210a4105210f0b20014110762104200141087621050c090b0240200141014d0d004104210f41ba8cc500210a412421080c070b02400240024020010e020001000b410421040c010b20052006460d06024002400240200641016a22012006490d0020052001490d010240200c20066a2c0000221641004e0d004118210f0c0c0b4106210f201641c00071450d02201641807f72221641ff017141fb014d0d022016417f732104200121060c030b417f200641016a103e000b200641016a2005107f000b0c080b024020122011470d0020124101742201201241016a221620162001491b220141ffffffff00712001470d0f200141047422164100480d0f0240024020120d002016102721030c010b200320124104742016102821030b2003450d03200121120b200320114104746a220120194180807c71200441ff01714108747241e00072221936020c200120083602082001201736020420012018201072201f72360200200b41106a210b201a2111201a200a470d000b0b2006201346210102402007450d00200c10290b2001450d07200aad4220862012ad842109410221040c100b20164104102a000b200141016a2005107f000b417f200141016a103e000b200241013a0028200241013602542002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022802d88004210a20022802dc8004210820022d00e08004210120022d00e18004210520022f01e2800421044105210f0b0b2017450d00201410290b200541ff0171410874200141ff017172210520044110742104201641ff0171410874210602402011450d002003210103400240200141046a280200450d00200128020010290b200141106a2101200b41706a220b0d000b0b200520047221042006200f7221012012450d02200310290c020b20024103410220011b3a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d88004210920022802e0800421040240200a450d00200a41047421052003210103400240200141046a280200450d00200128020010290b200141106a2101200541706a22050d000b0b2009422088210e41052101410021052012450d02200310290c020b200241013a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210820022802e0800421042009a7210a410521010b200141087621052008ad220e422086200aad8421092007450d00200c10290b20004101360200200041106a2004360200200041086a200e422086200942ffffffff0f838437020020002005410874200141ff0171723602040c0c0b410021014100210402400340410021080240200a4105470d00410f21070c0b0b2003200a460d032003200a4d0d012006200a6a2d0000220541ff00712001411f71742004722104200141076a2101200a41016a220c210a2005418001710d000b024020014120490d002005410f4d0d00410d21070c0a0b024020040d0041002105410121134100210a4100210d0c050b200241c0006a410041800810cd041a410121134100210d4100210541002107034002400240024002402003200c6b200420076b22014180082001418008491b2201490d00200c20016a2216200c490d02200320164f0d0120162003107f000b200241013a00c88004200241ec80046a4101360200200242013702dc800420024180c0c5003602d880042002411f3602242002200241206a3602e880042002200241c880046a360220200241286a200241d880046a10e60320022903282209422088a7210a200228023021012009a72104410521070240200d0d002004210d0c0f0b201310292004210d0c0e0b200241c0006a2006200c6a200110ce041a0240200d20056b2001490d00200120056a210a0c020b200520016a220a2005490d04200d410174220c200a200a200c491b220c4100480d0402400240200d0d00200c102721130c010b2013200d200c102821130b02402013450d00200c210d0c020b200c4101102a000b200c2016103e000b201320056a200241c0006a200110ce041a2016210c200a21052004200120076a22074d0d040c000b0b200a41016a2003107f000b102b000b200241013a0028200241d4006a41013602002002420137024420024180c0c5003602402002411f3602242002200241206a3602502002200241286a360220200241d880046a200241c0006a10e60320022903d880042209422088a7210a20022802e0800421012009a7210d410521070c070b200241c0006a2013200a10dc01024020022802404101470d00410821070240200d0d000c080b201310290c070b201341087621052016210c0b2003200c490d012003200c6b2204417f4c0d020240024020040d00410121010c010b200410272201450d0420012006200c6a200410ce041a0b200aad4220862109200dad210e2004ad222842208621290240200b450d00200610290b2009200e8421092029202884210e2005410874201341ff0171722103410121040b200020043a000420004100360200200041056a20022f001d3b0000200041186a200e370200200041146a20013602002000410c6a2009370200200041086a2003360200200041206a200229020c370200200041076a2002411f6a2d00003a0000200041286a2002410c6a41086a2902003702000c060b200c2003103e000b1039000b20044101102a000b4100210a4100210d0b200aad422086200dad842109200b450d00200610290b20004101360200200041106a2001360200200041086a200937020020002008410874200741ff0171723602040b200241f080046a24000bf404010b7f230041c080016b220224002002200110f003410121030240024020022802004101470d0020002002290204370204200041013602002000410c6a2002410c6a2902003702000c010b20022802042104200241004180800110cd042105410021064100210702400240024002402004450d00410021084100210641012103410021090340024002402001280204220a200128020822076b200420096b220b41808001200b41808001491b220b490d002007200b6a220c2007490d04200a200c4f0d01200c200a107f000b200541013a008f8001200541b480016a4101360200200542013702a4800120054180c0c5003602a080012005411f3602bc80012005200541b880016a3602b0800120052005418f80016a3602b880012005419080016a200541a080016a10e6032005418b80016a2005419880016a2802003600002005200529039080013700838001200041053a00042000200529008080013700052000410c6a2005418780016a290000370000200041013602002006450d06200310290c060b2005200128020020076a200b10ce04210a2001200c36020802400240200620086b200b490d00200b20086a21070c010b2008200b6a22072008490d052006410174220c20072007200c491b220c4100480d050240024020060d00200c102721030c010b20032006200c102821030b2003450d04200c21060b200320086a200a200b10ce041a200721082004200b20096a22094b0d000b0b2000200336020420004100360200200041146a2007360200200041106a41003602002000410c6a2007360200200041086a20063602000c030b2007200c103e000b200c4101102a000b102b000b200241c080016a24000b0e0020003502004101200110aa010bf60201037f230041c0006b22022400200141086a2802002103200128020421042002200128020022013602100240024002402001418080044b0d0002402004450d0020022003360214200120034b0d022003418080044d0d002002413c6a41013602002002420237022c200241ec9cc5003602282002410136021c200241c89cc5003602182002200241186a3602382002200241286a10e6030c030b200241003602000c020b2002413c6a41013602002002420237022c200241cc9cc5003602282002410136021c200241c89cc5003602182002200241186a3602382002200241286a10e6030c010b200241246a41013602002002413c6a41023602002002420237022c200241dc9cc5003602282002410136021c2002200241186a3602382002200241106a3602202002200241146a3602182002200241286a10e6030b024002402002280200450d0020002002290300370200200041086a200241086a2802003602000c010b200041003602000b200241c0006a24000bf90501037f230041f0006b2204240002400240024002400240024020012802084102460d00412e10272201450d01200041013a0000200141266a41002900e09e45370000200141206a41002900da9e45370000200141186a41002900d29e45370000200141106a41002900ca9e45370000200141086a41002900c29e45370000200141002900ba9e45370000200041086a42ae808080e005370200200041046a20013602000c050b02400240024002400240200128020022052d0000416e6a2201411e4b0d004100210620010e1f03000000000000000000000000000000000000000000000000000008040102030b412010272201450d05200041013a0000200141186a41002900809f45370000200141106a41002900f89e45370000200141086a41002900f09e45370000200141002900e89e45370000200041086a42a08080808004370200200041046a20013602000c080b410221060c060b410321060c050b20042005280204220136020c0240024020012003490d0041889fc5002105200441e8006a2103200441d0006a2101200441c0006a21020c010b200220014101746a22012d0001450d0441989fc5002105200441386a2103200441206a2101200441106a21020b20034101360204200141146a410136020020012003360210200142023702042001200536020020032004410c6a3602002002200110e603200041013a00002000410c6a200241086a280200360200200041046a20022902003702000c050b410121060c030b412e4101102a000b41204101102a000b20012d000021060b0240200541106a2d00004106470d00200041003a0000200020063a00010c010b0240412910272201450d00200041013a0000200141286a41002d00d09f453a0000200141206a41002900c89f45370000200141186a41002900c09f45370000200141106a41002900b89f45370000200141086a41002900b09f45370000200141002900a89f45370000200041086a42a98080809005370200200041046a20013602000c010b41294101102a000b200441f0006a24000b8f0201017f230041106b220224000240024002400240024020002d00000e0401020300010b2002200128021841d0bfc50041032001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040c030b2002200128021841d3bfc50041032001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040c020b2002200128021841d6bfc50041032001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040c010b2002200128021841d9bfc50041032001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040b200241106a240020000bf7c30103077f027e027f230041f0006b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000eac0100df010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01000b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810272200450dab012003421837025c20032000360258200341d8006a4100411810fe0320032003280260220041186a3602602000200328025822016a411841f6a1c500411810ff032003200329025c37025c20032001360258418697c500413b200341d8006a41c497c50010a201000b02400240200128022820044103746a22052802002206200141206a28020022024b0d002006200220062002491b21040c010b024002402001411c6a280200220420026b200620026b2207490d0020012802182108200221040c010b200220076a22082002490dde0120044101742209200820082009491b22094100480dde010240024020040d002009102721080c010b200128021820042009102821080b2008450dad01200120083602182001411c6a2009360200200141206a28020021040b200820046a21090240024020074102490d002009410420062002417f736a220210cd041a2008200220046a22046a21090c010b2007450d010b200941043a0000200441016a21040b200141206a2004360200200541013a00060cde010b0240200141306a2802002204200141346a22062802004f0d002002310001210a200141206a350200210b024020042001412c6a280200470d00200441016a22022004490ddd0120044101742206200220022006491b220241ffffffff01712002470ddd01200241037422064100480ddd010240024020040d002006102721040c010b200128022820044103742006102821040b2004450dad01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200a422886200b84370200200141306a2201200128020041016a3602000cde010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450ddd012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450ddd012000200329023c370204200020013602000cde010b0240200141306a2802002204200141346a22062802004f0d002002310001210a200141206a350200210b024020042001412c6a280200470d00200441016a22022004490ddc0120044101742206200220022006491b220241ffffffff01712002470ddc01200241037422064100480ddc010240024020040d002006102721040c010b200128022820044103742006102821040b2004450dad01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200a422886200b8442808080803084370200200141306a2201200128020041016a3602000cdd010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450ddc012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450ddc012000200329023c370204200020013602000cdd010b2002310001210a200341d8006a200141186a200141286a22044100108004024020032d00584101470d002000200329025c370200200041086a200341e4006a2802003602000cdd010b0240200141306a2802002202200141346a22062802004f0d00200141206a350200210b024020022001412c6a280200470d00200241016a22062002490ddb0120024101742205200620062005491b220641ffffffff01712006470ddb01200641037422054100480ddb010240024020020d002005102721020c010b200428020020024103742005102821020b2002450dad01200120023602282001412c6a2006360200200141306a28020021020b200128022820024103746a200a422886200b8442808080801084370200200141306a2201200128020041016a3602000cdc010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450ddb012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450ddb012000200329023c370204200020013602000cdc010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810272200450dac012003421837025c20032000360258200341d8006a4100411810fe0320032003280260220041186a3602602000200328025822016a411841f6a1c500411810ff032003200329025c37025c2003200136025841d497c5004134200341d8006a41c497c50010a201000b02400240200141286a220228020020044103746a22042d00044101470d002004310005210a200341d8006a200141186a20021081042003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cdd010b411a10272201450dad01200141186a41002f00a098453b0000200141106a41002900989845370000200141086a410029009098453700002001410029008898453700002000429a808080a003370204200020013602000cdc010b0240200141306a2802002204200141346a22062802004f0d00200141206a350200210b024020042001412c6a280200470d00200441016a22062004490dda0120044101742205200620062005491b220641ffffffff01712006470dda01200641037422054100480dda010240024020040d002005102721020c010b200228020020044103742005102821020b2002450daf01200120023602282001412c6a2006360200200141306a28020021040b200128022820044103746a200a422886200b8442808080802084370200200141306a2201200128020041016a3602000cdb010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450dda012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dda012000200329023c370204200020013602000cdb010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810272200450dae012003421837025c20032000360258200341d8006a4100411810fe0320032003280260220041186a3602602000200328025822016a411841f6a1c500411810ff032003200329025c37025c2003200136025841d497c5004134200341d8006a41c497c50010a201000b200141286a220528020020044103746a22042d00052106024020042d00044101470d00200641ff01714104470daf010b0240024020024101460d00200341d8006a200141186a220220051081042003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cdc010b20012d003822024104460dd901200341d8006a200141186a2206200520021080040240024020032d00584101460d000240200141206a2802002204200141246a22082802004f0d00024020042001411c6a280200470d00200441016a22082004490ddc0120044101742207200820082007491b22084100480ddc010240024020040d002008102721040c010b200628020020042008102821040b2004450db401200120043602182001411c6a2008360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cdc010b200341ec006a220241013602002003420137025c200341f0a2c500360258200341013602042003200836020020032003360268200341106a200341d8006a10e60320032802102204450ddb012003200329021437021420032004360210200241013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382202450ddb01200329023c210a0c010b200328025c2202450dda01200341e0006a290300210a0b2000200a370204200020023602000cdb010b200641ff01714104460dd9010240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490dd90120044101742208200520052008491b22054100480dd9010240024020040d002005102721020c010b200228020020042005102821020b2002450db201200120023602182001411c6a2005360200200141206a28020021040b200128021820046a20063a0000200141206a2201200128020041016a3602000cda010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200536020020032003360268200341106a200341d8006a10e60320032802102202450dd9012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dd9012000200329023c370204200020013602000cda010b2003200241046a280200220236024802400240200141306a280200220420024d0d0020042002417f736a22022004490d0141d2a2c500411d104e000b200341ec006a220241023602002003411c6a41013602002003420237025c20034190a2c50036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a10e603200328023821042003200329023c37021420032004360210200241013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e6032003280214450dd101200328021010290cd1010b200141286a220428020020024103746a22022d00044103460dd10120022d0005220241ff01714104460dd101200341d8006a200141186a220620042002108004024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490dd90120044101742208200520052008491b22054100480dd9010240024020040d002005102721040c010b200628020020042005102821040b2004450db301200120043602182001411c6a2005360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cd3010b200341ec006a220241013602002003420137025c200341f0a2c500360258200341013602042003200536020020032003360268200341106a200341d8006a10e60320032802102204450dd2012003200329021437021420032004360210200241013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e6032003280214450dd101200328021010290cd1010b200328025c2202450dd101200341e0006a290300210a0cd2010b200241046a2802002102200341d8006a200141186a2205200141286a220641001080040240024020032d00584101470d00200341e0006a290300210a200328025c22010d010cd9010b200141306a28020021042003200236024802400240200420024d0d0020042002417f736a22022004490d0141d2a2c500411d104e000b200341ec006a220141023602002003411c6a41013602002003420237025c20034190a2c50036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a10e603200328023821022003200329023c37021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b200329023c210a200328023822010d010cd9010b200628020020024103746a22022d00044103460dd80120022d0005220241ff01714104460dd801200341d8006a200520062002108004024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490dd90120044101742208200620062008491b22064100480dd9010240024020040d002006102721040c010b200528020020042006102821040b2004450db401200120043602182001411c6a2006360200200141206a28020021040b200128021820046a20023a0000200141206a2201200128020041016a3602000cda010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450dd9012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dd901200329023c210a0c010b200328025c2201450dd801200341e0006a290300210a0b2000200a370204200020013602000cd8010b200241086a2802002105200241046a280200210420032002410c6a280200220636024802400240200141306a280200220220064d0d0020022006417f736a22062002490d0141d2a2c500411d104e000b200341ec006a22044102360200200341106a410c6a41013602002003420237025c20034190a2c50036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a10e603200328023821022003200329023c37021420032002360210200441013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b2003200329023c370204200320032802383602000ccd010b410421090240200141286a220c280200220820064103746a22062d00044103460d0020062d000521090b200320093a00302005450dc801200941ff0171220d4104460dc701200541027421050340200320042802002206360248200220064d0dca0120022006417f736a220620024f0dce01200820064103746a22062d00044103460dcb0120062d000522074104460dcb01200d2007470dcb01200441046a21042005417c6a22050d000cc9010b0b20012d003822024104460dc501200341d8006a200141186a2206200141286a20021080040240024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490dd70120044101742208200520052008491b22054100480dd7010240024020040d002005102721040c010b200628020020042005102821040b2004450db301200120043602182001411c6a2005360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cc8010b200341ec006a220241013602002003420137025c200341f0a2c500360258200341013602042003200536020020032003360268200341106a200341d8006a10e60320032802102204450dc7012003200329021437021420032004360210200241013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382202450dc701200329023c210a0c010b200328025c2202450dc601200341e0006a290300210a0b2000200a370204200020023602000cd6010b200128020021042003200241046a2802002202360254024002400240200441386a28020020024b0d00200341ec006a41013602002003420237025c200341d8a0c500360258200341013602342003200341306a3602682003200341d4006a360230200341386a200341d8006a10e603200341186a200329023c370300200341013602102003200328023822043602140c010b2003200428023020024102746a2802002202360200024002402004412c6a28020020024b0d0041012106200341ec006a41013602002003420237025c200341e8a0c5003602582003410136024c2003200341c8006a36026820032003360248200341386a200341d8006a10e603200341186a200329023c220a370300200a422088a7210820032802382104200aa721020c010b2003411c6a200428022420024104746a22042d000d22083a0000200341186a2004280208220236020020042802002104410021060b20032006360210200320043602142006450d010b200341186a21010cc3010b02402002450d002004417f6a2104200141286a2106200141186a21050340200341d8006a20052006200420026a2d0000108004024020032d00584101470d00200341e0006a2101200328025c21040cc5010b2002417f6a22020d000b0b200841ff01714104460dd4010240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490dd40120024101742206200420042006491b22044100480dd4010240024020020d002004102721020c010b200128021820022004102821020b2002450db101200120023602182001411c6a2004360200200141206a28020021020b200128021820026a20083a0000200141206a2201200128020041016a3602000cd5010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200436020020032003360268200341106a200341d8006a10e60320032802102202450dd4012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382204450dd401200329023c210a0cc3010b200241046a28020021052001280200210220034100360238024002400240200241146a2802000d00200341d8006a41146a41013602002003420237025c200341b8a0c50036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10e6030c010b200341d8006a200141186a2204200141286a22064100108004024020032d00584101470d00200341e0006a290300210a0cc2010b20012802002208412c6a280200210220032005360238200220054b0d01200341ec006a41013602002003420237025c200341e8a0c50036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10e6030b2003290214210a200328021022010dc1010cd4010b200828022420054104746a22052d000d2108024020052802082202450d002005280200417f6a21050340200341d8006a20042006200520026a2d0000108004024020032d00584101470d00200341e0006a290300210a0cc2010b2002417f6a22020d000b0b200841ff01714104460dd3010240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490dd30120024101742205200620062005491b22064100480dd3010240024020020d002006102721020c010b200428020020022006102821020b2002450db101200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20083a0000200141206a2201200128020041016a3602000cd4010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450dd3012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dd301200329023c210a0cc0010b200341d8006a200141186a200141286a410410800420032d00584101470dd201200328025c2201450dd2012000200341e0006a290300370204200020013602000cd3010b200341d8006a200141186a2204200141286a22064100108004200341d8006a21020240024020032d00584101460d00200341d8006a200420064104108004200341d8006a210220032d00584101460d00200341d8006a2004200620032d00592205108004200341d8006a210220032d00584101460d000240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490dd30120024101742208200620062008491b22064100480dd3010240024020020d002006102721020c010b200428020020022006102821020b2002450db201200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20053a0000200141206a2201200128020041016a3602000cd4010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450dd3012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dd301200329023c210a0c010b200241046a2802002201450dd201200241086a290200210a0b2000200a370204200020013602000cd2010b200341d8006a200141046a200241046a2802001082040240024020032d00584101460d000240200141206a2802002202200141246a22042802004f0d0020032d00592104024020022001411c6a280200470d00200241016a22062002490dd20120024101742205200620062005491b22064100480dd2010240024020020d002006102721020c010b200128021820022006102821020b2002450db201200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cd3010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200436020020032003360268200341106a200341d8006a10e60320032802102202450dd2012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dd201200329023c210a0c010b200328025c2201450dd101200341e0006a290300210a0b2000200a370204200020013602000cd1010b2003200241046a2802002202360200200341d8006a200141046a2002108204024020032d00584101470d002003200328025c22013602382003200341e0006a290300220a37023c0cbb010b200320032d005922023a0030200341d8006a200141186a200141286a4104108004024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380cba010b200320032d005922013a004820014104460dcf01200241ff01712001460dcf01200341106a41146a41253602002003411c6a4120360200200341d8006a41146a41033602002003420337025c200341c498c500360258200341013602142003200341106a3602682003200341c8006a3602202003200341306a36021820032003360210200341386a200341d8006a10e6030cb9010b200341d8006a200141046a200241046a2802001082040240024020032d00584101460d00200341d8006a200141186a2206200141286a20032d00592204108004024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dd10120024101742208200520052008491b22054100480dd1010240024020020d002005102721020c010b200628020020022005102821020b2002450db201200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cd2010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200536020020032003360268200341106a200341d8006a10e60320032802102202450dd1012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dd101200329023c210a0c020b200328025c2201450dd001200341e0006a290300210a0c010b200328025c2201450dcf01200341e0006a290300210a0b2000200a370204200020013602000ccf010b200128020021042003200241046a280200220236023802400240200441206a28020020024d0d000240200141206a2802002206200141246a22052802004f0d00200428021820024101746a2d00002102024020062001411c6a280200470d00200641016a22042006490dcf0120064101742205200420042005491b22044100480dcf010240024020060d002004102721060c010b200128021820062004102821060b2006450db101200120063602182001411c6a2004360200200141206a28020021060b200128021820066a20023a0000200141206a2201200128020041016a3602000cd0010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200536020020032003360268200341106a200341d8006a10e60320032802102202450dcf012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450dcf01200329023c210a0c010b200341ec006a41013602002003420237025c20034188a1c5003602582003410136024c2003200341c8006a3602682003200341386a360248200341106a200341d8006a10e60320032802102201450dce012003290214210a0b2000200a370204200020013602000cce010b2003200241046a28020022023602282001280200210420032002360254024002400240200441206a28020020024b0d00200341ec006a41013602002003420237025c20034188a1c5003602582003410136024c2003200341c8006a3602682003200341d4006a360248200341106a200341d8006a10e6030c010b200428021820024101746a22022d00010d01200341ec006a41013602002003420237025c20034198a1c50036025820034101360204200320033602682003200341d4006a360200200341106a200341d8006a10e6030b2003280210210120032003290214220a37023c200320013602380cb6010b200320022d000022023a002f200341d8006a200141186a200141286a4104108004024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380cb5010b200320032d005922013a00002001200241ff0171460dcc0120014104460dcc01200341106a41146a41253602002003411c6a4125360200200341d8006a41146a41033602002003420337025c200341dc98c500360258200341013602142003200341106a3602682003200336022020032003412f6a3602182003200341286a360210200341386a200341d8006a10e6030cb4010b200341d8006a2001200241046a280200410441001084042003280258450dcb0120002003290358370200200041086a200341d8006a41086a2802003602000ccc010b200341d8006a2001200241046a280200410841011084042003280258450dca0120002003290358370200200041086a200341d8006a41086a2802003602000ccb010b200341d8006a2001200241046a280200410441021084042003280258450dc90120002003290358370200200041086a200341d8006a41086a2802003602000cca010b200341d8006a2001200241046a280200410841031084042003280258450dc80120002003290358370200200041086a200341d8006a41086a2802003602000cc9010b200341d8006a2001200241046a280200410141001084042003280258450dc70120002003290358370200200041086a200341d8006a41086a2802003602000cc8010b200341d8006a2001200241046a280200410141001084042003280258450dc60120002003290358370200200041086a200341d8006a41086a2802003602000cc7010b200341d8006a2001200241046a280200410241001084042003280258450dc50120002003290358370200200041086a200341d8006a41086a2802003602000cc6010b200341d8006a2001200241046a280200410241001084042003280258450dc40120002003290358370200200041086a200341d8006a41086a2802003602000cc5010b200341d8006a2001200241046a280200410141011084042003280258450dc30120002003290358370200200041086a200341d8006a41086a2802003602000cc4010b200341d8006a2001200241046a280200410141011084042003280258450dc20120002003290358370200200041086a200341d8006a41086a2802003602000cc3010b200341d8006a2001200241046a280200410241011084042003280258450dc10120002003290358370200200041086a200341d8006a41086a2802003602000cc2010b200341d8006a2001200241046a280200410241011084042003280258450dc00120002003290358370200200041086a200341d8006a41086a2802003602000cc1010b200341d8006a2001200241046a280200410441011084042003280258450dbf0120002003290358370200200041086a200341d8006a41086a2802003602000cc0010b200341d8006a2001200241046a280200410441011084042003280258450dbe0120002003290358370200200041086a200341d8006a41086a2802003602000cbf010b200341d8006a2001200241046a280200410441001085042003280258450dbd0120002003290358370200200041086a200341d8006a41086a2802003602000cbe010b200341d8006a2001200241046a280200410841011085042003280258450dbc0120002003290358370200200041086a200341d8006a41086a2802003602000cbd010b200341d8006a2001200241046a280200410441021085042003280258450dbb0120002003290358370200200041086a200341d8006a41086a2802003602000cbc010b200341d8006a2001200241046a280200410841031085042003280258450dba0120002003290358370200200041086a200341d8006a41086a2802003602000cbb010b200341d8006a2001200241046a280200410141001085042003280258450db90120002003290358370200200041086a200341d8006a41086a2802003602000cba010b200341d8006a2001200241046a280200410241001085042003280258450db80120002003290358370200200041086a200341d8006a41086a2802003602000cb9010b200341d8006a2001200241046a280200410141011085042003280258450db70120002003290358370200200041086a200341d8006a41086a2802003602000cb8010b200341d8006a2001200241046a280200410241011085042003280258450db60120002003290358370200200041086a200341d8006a41086a2802003602000cb7010b200341d8006a2001200241046a280200410441011085042003280258450db50120002003290358370200200041086a200341d8006a41086a2802003602000cb6010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034188a0c50036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10e60320032802102202450d002003290214210a0c010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db50120024101742206200420042006491b22044100480db5010240024020020d002004102721020c010b200128021820022004102821020b2002450d9801200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb6010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200436020020032003360268200341106a200341d8006a10e60320032802102202450db5012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382202450db501200329023c210a0b2000200a370204200020023602000cb5010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034188a0c50036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10e60320032802102202450d002003290214210a0c010b200341d8006a200141186a2204200141286a4100108004024020032d00584101460d000240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490db50120024101742205200620062005491b22064100480db5010240024020020d002006102721020c010b200428020020022006102821020b2002450d9901200120023602182001411c6a2006360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb6010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102202450db5012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382202450db501200329023c210a0c010b200328025c2202450db401200341e0006a290300210a0b2000200a370204200020023602000cb4010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db20120024101742206200420042006491b22044100480db2010240024020020d002004102721020c010b200128021820022004102821020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb3010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200436020020032003360268200341106a200341d8006a10e60320032802102202450db2012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450db2012000200329023c370204200020013602000cb3010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db10120024101742206200420042006491b22044100480db1010240024020020d002004102721020c010b200128021820022004102821020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000cb2010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200436020020032003360268200341106a200341d8006a10e60320032802102202450db1012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450db1012000200329023c370204200020013602000cb2010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db00120024101742206200420042006491b22044100480db0010240024020020d002004102721020c010b200128021820022004102821020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000cb1010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200436020020032003360268200341106a200341d8006a10e60320032802102202450db0012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450db0012000200329023c370204200020013602000cb1010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490daf0120024101742206200420042006491b22044100480daf010240024020020d002004102721020c010b200128021820022004102821020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000cb0010b200341ec006a220141013602002003420137025c200341f0a2c500360258200341013602042003200436020020032003360268200341106a200341d8006a10e60320032802102202450daf012003200329021437021420032002360210200141013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382201450daf012000200329023c370204200020013602000cb0010b200341d8006a200141001086042003280258450dae0120002003290358370200200041086a200341d8006a41086a2802003602000caf010b200341d8006a200141001087042003280258450dad0120002003290358370200200041086a200341d8006a41086a2802003602000cae010b200341d8006a200141001087042003280258450dac0120002003290358370200200041086a200341d8006a41086a2802003602000cad010b200341d8006a200141001087042003280258450dab0120002003290358370200200041086a200341d8006a41086a2802003602000cac010b200341d8006a200141001087042003280258450daa0120002003290358370200200041086a200341d8006a41086a2802003602000cab010b200341d8006a200141001087042003280258450da90120002003290358370200200041086a200341d8006a41086a2802003602000caa010b200341d8006a200141001087042003280258450da80120002003290358370200200041086a200341d8006a41086a2802003602000ca9010b200341d8006a200141001087042003280258450da70120002003290358370200200041086a200341d8006a41086a2802003602000ca8010b200341d8006a200141001087042003280258450da60120002003290358370200200041086a200341d8006a41086a2802003602000ca7010b200341d8006a200141001087042003280258450da50120002003290358370200200041086a200341d8006a41086a2802003602000ca6010b200341d8006a200141001087042003280258450da40120002003290358370200200041086a200341d8006a41086a2802003602000ca5010b200341d8006a200141011086042003280258450da30120002003290358370200200041086a200341d8006a41086a2802003602000ca4010b200341d8006a200141011087042003280258450da20120002003290358370200200041086a200341d8006a41086a2802003602000ca3010b200341d8006a200141011087042003280258450da10120002003290358370200200041086a200341d8006a41086a2802003602000ca2010b200341d8006a200141011087042003280258450da00120002003290358370200200041086a200341d8006a41086a2802003602000ca1010b200341d8006a200141011087042003280258450d9f0120002003290358370200200041086a200341d8006a41086a2802003602000ca0010b200341d8006a200141011087042003280258450d9e0120002003290358370200200041086a200341d8006a41086a2802003602000c9f010b200341d8006a200141011087042003280258450d9d0120002003290358370200200041086a200341d8006a41086a2802003602000c9e010b200341d8006a200141011087042003280258450d9c0120002003290358370200200041086a200341d8006a41086a2802003602000c9d010b200341d8006a200141011087042003280258450d9b0120002003290358370200200041086a200341d8006a41086a2802003602000c9c010b200341d8006a200141011087042003280258450d9a0120002003290358370200200041086a200341d8006a41086a2802003602000c9b010b200341d8006a200141011087042003280258450d990120002003290358370200200041086a200341d8006a41086a2802003602000c9a010b200341d8006a200141021087042003280258450d980120002003290358370200200041086a200341d8006a41086a2802003602000c99010b200341d8006a200141021087042003280258450d970120002003290358370200200041086a200341d8006a41086a2802003602000c98010b200341d8006a200141021087042003280258450d960120002003290358370200200041086a200341d8006a41086a2802003602000c97010b200341d8006a200141021087042003280258450d950120002003290358370200200041086a200341d8006a41086a2802003602000c96010b200341d8006a200141021087042003280258450d940120002003290358370200200041086a200341d8006a41086a2802003602000c95010b200341d8006a200141021087042003280258450d930120002003290358370200200041086a200341d8006a41086a2802003602000c94010b200341d8006a200141031087042003280258450d920120002003290358370200200041086a200341d8006a41086a2802003602000c93010b200341d8006a200141031087042003280258450d910120002003290358370200200041086a200341d8006a41086a2802003602000c92010b200341d8006a200141031087042003280258450d900120002003290358370200200041086a200341d8006a41086a2802003602000c91010b200341d8006a200141031087042003280258450d8f0120002003290358370200200041086a200341d8006a41086a2802003602000c90010b200341d8006a200141031087042003280258450d8e0120002003290358370200200041086a200341d8006a41086a2802003602000c8f010b200341d8006a200141031087042003280258450d8d0120002003290358370200200041086a200341d8006a41086a2802003602000c8e010b200341d8006a200141001088042003280258450d8c0120002003290358370200200041086a200341d8006a41086a2802003602000c8d010b200341d8006a200141001088042003280258450d8b0120002003290358370200200041086a200341d8006a41086a2802003602000c8c010b200341d8006a200141001088042003280258450d8a0120002003290358370200200041086a200341d8006a41086a2802003602000c8b010b200341d8006a200141001089042003280258450d890120002003290358370200200041086a200341d8006a41086a2802003602000c8a010b200341d8006a200141001089042003280258450d880120002003290358370200200041086a200341d8006a41086a2802003602000c89010b200341d8006a200141001089042003280258450d870120002003290358370200200041086a200341d8006a41086a2802003602000c88010b200341d8006a200141001089042003280258450d860120002003290358370200200041086a200341d8006a41086a2802003602000c87010b200341d8006a200141001089042003280258450d850120002003290358370200200041086a200341d8006a41086a2802003602000c86010b200341d8006a200141001089042003280258450d840120002003290358370200200041086a200341d8006a41086a2802003602000c85010b200341d8006a200141001089042003280258450d830120002003290358370200200041086a200341d8006a41086a2802003602000c84010b200341d8006a200141001089042003280258450d820120002003290358370200200041086a200341d8006a41086a2802003602000c83010b200341d8006a200141001089042003280258450d810120002003290358370200200041086a200341d8006a41086a2802003602000c82010b200341d8006a200141001089042003280258450d800120002003290358370200200041086a200341d8006a41086a2802003602000c81010b200341d8006a200141001089042003280258450d7f20002003290358370200200041086a200341d8006a41086a2802003602000c80010b200341d8006a200141001089042003280258450d7e20002003290358370200200041086a200341d8006a41086a2802003602000c7f0b200341d8006a200141001089042003280258450d7d20002003290358370200200041086a200341d8006a41086a2802003602000c7e0b200341d8006a200141001089042003280258450d7c20002003290358370200200041086a200341d8006a41086a2802003602000c7d0b200341d8006a200141001089042003280258450d7b20002003290358370200200041086a200341d8006a41086a2802003602000c7c0b200341d8006a200141011088042003280258450d7a20002003290358370200200041086a200341d8006a41086a2802003602000c7b0b200341d8006a200141011088042003280258450d7920002003290358370200200041086a200341d8006a41086a2802003602000c7a0b200341d8006a200141011088042003280258450d7820002003290358370200200041086a200341d8006a41086a2802003602000c790b200341d8006a200141011089042003280258450d7720002003290358370200200041086a200341d8006a41086a2802003602000c780b200341d8006a200141011089042003280258450d7620002003290358370200200041086a200341d8006a41086a2802003602000c770b200341d8006a200141011089042003280258450d7520002003290358370200200041086a200341d8006a41086a2802003602000c760b200341d8006a200141011089042003280258450d7420002003290358370200200041086a200341d8006a41086a2802003602000c750b200341d8006a200141011089042003280258450d7320002003290358370200200041086a200341d8006a41086a2802003602000c740b200341d8006a200141011089042003280258450d7220002003290358370200200041086a200341d8006a41086a2802003602000c730b200341d8006a200141011089042003280258450d7120002003290358370200200041086a200341d8006a41086a2802003602000c720b200341d8006a200141011089042003280258450d7020002003290358370200200041086a200341d8006a41086a2802003602000c710b200341d8006a200141011089042003280258450d6f20002003290358370200200041086a200341d8006a41086a2802003602000c700b200341d8006a200141011089042003280258450d6e20002003290358370200200041086a200341d8006a41086a2802003602000c6f0b200341d8006a200141011089042003280258450d6d20002003290358370200200041086a200341d8006a41086a2802003602000c6e0b200341d8006a200141011089042003280258450d6c20002003290358370200200041086a200341d8006a41086a2802003602000c6d0b200341d8006a200141011089042003280258450d6b20002003290358370200200041086a200341d8006a41086a2802003602000c6c0b200341d8006a200141011089042003280258450d6a20002003290358370200200041086a200341d8006a41086a2802003602000c6b0b200341d8006a200141011089042003280258450d6920002003290358370200200041086a200341d8006a41086a2802003602000c6a0b200341d8006a200141021088042003280258450d6820002003290358370200200041086a200341d8006a41086a2802003602000c690b200341d8006a200141021088042003280258450d6720002003290358370200200041086a200341d8006a41086a2802003602000c680b200341d8006a200141021088042003280258450d6620002003290358370200200041086a200341d8006a41086a2802003602000c670b200341d8006a200141021088042003280258450d6520002003290358370200200041086a200341d8006a41086a2802003602000c660b200341d8006a200141021088042003280258450d6420002003290358370200200041086a200341d8006a41086a2802003602000c650b200341d8006a200141021088042003280258450d6320002003290358370200200041086a200341d8006a41086a2802003602000c640b200341d8006a200141021088042003280258450d6220002003290358370200200041086a200341d8006a41086a2802003602000c630b200341d8006a200141021089042003280258450d6120002003290358370200200041086a200341d8006a41086a2802003602000c620b200341d8006a200141021089042003280258450d6020002003290358370200200041086a200341d8006a41086a2802003602000c610b200341d8006a200141021089042003280258450d5f20002003290358370200200041086a200341d8006a41086a2802003602000c600b200341d8006a200141021089042003280258450d5e20002003290358370200200041086a200341d8006a41086a2802003602000c5f0b200341d8006a200141021089042003280258450d5d20002003290358370200200041086a200341d8006a41086a2802003602000c5e0b200341d8006a200141021089042003280258450d5c20002003290358370200200041086a200341d8006a41086a2802003602000c5d0b200341d8006a200141021089042003280258450d5b20002003290358370200200041086a200341d8006a41086a2802003602000c5c0b200341d8006a200141031088042003280258450d5a20002003290358370200200041086a200341d8006a41086a2802003602000c5b0b200341d8006a200141031088042003280258450d5920002003290358370200200041086a200341d8006a41086a2802003602000c5a0b200341d8006a200141031088042003280258450d5820002003290358370200200041086a200341d8006a41086a2802003602000c590b200341d8006a200141031088042003280258450d5720002003290358370200200041086a200341d8006a41086a2802003602000c580b200341d8006a200141031088042003280258450d5620002003290358370200200041086a200341d8006a41086a2802003602000c570b200341d8006a200141031088042003280258450d5520002003290358370200200041086a200341d8006a41086a2802003602000c560b200341d8006a200141031088042003280258450d5420002003290358370200200041086a200341d8006a41086a2802003602000c550b200341d8006a200141031089042003280258450d5320002003290358370200200041086a200341d8006a41086a2802003602000c540b200341d8006a200141031089042003280258450d5220002003290358370200200041086a200341d8006a41086a2802003602000c530b200341d8006a200141031089042003280258450d5120002003290358370200200041086a200341d8006a41086a2802003602000c520b200341d8006a200141031089042003280258450d5020002003290358370200200041086a200341d8006a41086a2802003602000c510b200341d8006a200141031089042003280258450d4f20002003290358370200200041086a200341d8006a41086a2802003602000c500b200341d8006a200141031089042003280258450d4e20002003290358370200200041086a200341d8006a41086a2802003602000c4f0b200341d8006a200141031089042003280258450d4d20002003290358370200200041086a200341d8006a41086a2802003602000c4e0b200341d8006a200141014100108a042003280258450d4c20002003290358370200200041086a200341d8006a41086a2802003602000c4d0b200341d8006a200141024100108a042003280258450d4b20002003290358370200200041086a200341d8006a41086a2802003602000c4c0b200341d8006a200141024100108a042003280258450d4a20002003290358370200200041086a200341d8006a41086a2802003602000c4b0b200341d8006a200141034100108a042003280258450d4920002003290358370200200041086a200341d8006a41086a2802003602000c4a0b200341d8006a200141034100108a042003280258450d4820002003290358370200200041086a200341d8006a41086a2802003602000c490b200341d8006a200141004101108a042003280258450d4720002003290358370200200041086a200341d8006a41086a2802003602000c480b200341d8006a200141004101108a042003280258450d4620002003290358370200200041086a200341d8006a41086a2802003602000c470b200341d8006a200141024101108a042003280258450d4520002003290358370200200041086a200341d8006a41086a2802003602000c460b200341d8006a200141024101108a042003280258450d4420002003290358370200200041086a200341d8006a41086a2802003602000c450b200341d8006a200141034101108a042003280258450d4320002003290358370200200041086a200341d8006a41086a2802003602000c440b200341d8006a200141034101108a042003280258450d4220002003290358370200200041086a200341d8006a41086a2802003602000c430b200341d8006a200141004102108a042003280258450d4120002003290358370200200041086a200341d8006a41086a2802003602000c420b200341d8006a200141004102108a042003280258450d4020002003290358370200200041086a200341d8006a41086a2802003602000c410b200341d8006a200141014102108a042003280258450d3f20002003290358370200200041086a200341d8006a41086a2802003602000c400b200341d8006a200141014102108a042003280258450d3e20002003290358370200200041086a200341d8006a41086a2802003602000c3f0b200341d8006a200141034102108a042003280258450d3d20002003290358370200200041086a200341d8006a41086a2802003602000c3e0b200341d8006a200141004103108a042003280258450d3c20002003290358370200200041086a200341d8006a41086a2802003602000c3d0b200341d8006a200141004103108a042003280258450d3b20002003290358370200200041086a200341d8006a41086a2802003602000c3c0b200341d8006a200141014103108a042003280258450d3a20002003290358370200200041086a200341d8006a41086a2802003602000c3b0b200341d8006a200141014103108a042003280258450d3920002003290358370200200041086a200341d8006a41086a2802003602000c3a0b200341d8006a200141024103108a042003280258450d3820002003290358370200200041086a200341d8006a41086a2802003602000c390b200341d8006a200141024100108a042003280258450d3720002003290358370200200041086a200341d8006a41086a2802003602000c380b200341d8006a200141034101108a042003280258450d3620002003290358370200200041086a200341d8006a41086a2802003602000c370b200341d8006a200141004102108a042003280258450d3520002003290358370200200041086a200341d8006a41086a2802003602000c360b200341d8006a200141014103108a0420032802580d1b0c340b41184101102a000b20094101102a000b20064104102a000b20064104102a000b20054104102a000b41184101102a000b411a4101102a000b20054104102a000b41184101102a000b200341ec006a41013602002003420237025c200341a498c5003602582003412636023c2003200441056a3602382003200341386a360268200341106a200341d8006a10e603200041086a200341106a41086a280200360200200020032903103702000c2b0b20084101102a000b20054101102a000b20054101102a000b20064101102a000b20054101102a000b20044101102a000b20064101102a000b20064101102a000b20064101102a000b20054101102a000b20044101102a000b20044101102a000b20064101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20002003290358370200200041086a200341d8006a41086a2802003602000c190b200329023c210a200328023821010b2001450d162000200a370204200020013602000c170b200329023c210a200328023821010b2001450d142000200a370204200020013602000c150b200328025c2201450d130b2000200a370204200020013602000c130b2004450d112001290200210a0b2000200a370204200020043602000c110b0240024002400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810272200450d012003421837025c20032000360258200341d8006a4100411810fe0320032003280260220041186a3602602000200328025822016a411841f6a1c500411810ff032003200329025c37025c20032001360258418697c500413b200341d8006a41c497c50010a201000b02400240200128022820044103746a22052802002206200141206a28020022024b0d002006200220062002491b21040c010b024002402001411c6a280200220420026b200620026b2207490d0020012802182108200221040c010b200220076a22082002490d1120044101742209200820082009491b22094100480d110240024020040d002009102721080c010b200128021820042009102821080b2008450d03200120083602182001411c6a2009360200200141206a28020021040b200820046a21090240024020074102490d002009410420062002417f736a220210cd041a2008200220046a22046a21090c010b2007450d010b200941043a0000200441016a21040b200141206a2004360200200541013a00060c110b41184101102a000b20094101102a000b200541027421050340200320042802002206360248200220064d0d0220022006417f736a220620024f0d060240200820064103746a22062d00044103460d0020062d00054104470d040b200441046a21042005417c6a22050d000b410421090b200341d8006a200141186a2202200c410010800420032d00584101470d02200341086a200341e4006a2802003602002003200329025c3703000c030b200341ec006a220441023602002003411c6a41013602002003420237025c20034190a2c50036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a10e603200328023821022003200329023c37021420032002360210200441013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b2003200329023c370204200320032802383602000c020b2003411c6a4126360200200341ec006a41023602002003420237025c200341b498c5003602582003200641056a360218200341263602142003200341106a3602682003200341306a3602102003200341d8006a10e6030c010b0240200941ff01714104460d00200341d8006a2002200c200910800402400240024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490d0e20044101742205200620062005491b22064100480d0e0240024020040d002006102721020c010b200228020020042006102821020b2002450d04200120023602182001411c6a2006360200200141206a28020021040b200128021820046a20093a0000200141206a2202200228020041016a3602000c040b200341ec006a220241013602002003420137025c200341f0a2c500360258200341013602042003200636020020032003360268200341106a200341d8006a10e60320032802102204450d032003200329021437021420032004360210200241013602002003420137025c200341b89cc50036025820034121360204200320033602682003200341106a360200200341386a200341d8006a10e60302402003280214450d00200328021010290b20032802382202450d03200329023c210a0c010b200328025c2202450d02200341e0006a290300210a0b2003200a370204200320023602000c020b20064101102a000b200341003602000b024020032802002202450d0020002003290204370204200020023602000c0b0b0240024002400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810272200450d012003421837025c20032000360258200341d8006a4100411810fe0320032003280260220041186a3602602000200328025822016a411841f6a1c500411810ff032003200329025c37025c20032001360258418697c500413b200341d8006a41c497c50010a201000b02400240200128022820044103746a22052802002206200141206a28020022024b0d002006200220062002491b21040c010b024002402001411c6a280200220420026b200620026b2207490d0020012802182108200221040c010b200220076a22082002490d0b20044101742209200820082009491b22094100480d0b0240024020040d002009102721080c010b200128021820042009102821080b2008450d03200120083602182001411c6a2009360200200141206a28020021040b200820046a21090240024020074102490d002009410420062002417f736a220210cd041a2008200220046a22046a21090c010b2007450d010b200941043a0000200441016a21040b200141206a2004360200200541013a00060c0b0b41184101102a000b20094101102a000b41d2a2c500411d104e000b20032802382202450d00200329023c210a0c010b0240200141306a2802002202417f6a220420024f0d00200420024d0d020b411810272200450d022003421837025c20032000360258200341d8006a4100411810fe0320032003280260220041186a3602602000200328025822016a411841f6a1c500411810ff032003200329025c37025c20032001360258418697c500413b200341d8006a41c497c50010a201000b2000200a370204200020023602000c060b02400240200128022820044103746a22052802002206200141206a28020022024b0d002006200220062002491b21040c010b024002402001411c6a280200220420026b200620026b2207490d0020012802182108200221040c010b200220076a22082002490d0420044101742209200820082009491b22094100480d040240024020040d002009102721080c010b200128021820042009102821080b2008450d03200120083602182001411c6a2009360200200141206a28020021040b200820046a21090240024020074102490d002009410420062002417f736a220210cd041a2008200220046a22046a21090c010b2007450d010b200941043a0000200441016a21040b200141206a2004360200200541013a00060c040b41184101102a000b20094101102a000b102b000b200341d8006a200141186a20051081042003280258450d0020002003290358370200200041086a200341d8006a41086a2802003602000c010b200041003602000b200341f0006a24000b6501017f230041206b2202240020024127360204200220003602002001411c6a2802002100200128021821012002411c6a41013602002002420137020c2002419c81c6003602082002200236021820012000200241086a1091042101200241206a240020010b0c00200028020020011093040bcd0201067f02400240024002402001450d0020014108490d010240200141ffffffff01712001470d00200141037441076e21010c030b41f495c5001058000b200041106a4200370200200041086a4280808080c000370200200041046a418c96c5003602000c020b200141016a21010b02400240417f2001417f6a6776220141016a220241ffffffff01712002470d00200141086a417c712203200141056a2204490d00200320024103746a22052003490d002005417d4f0d00200510272206450d012001200241037641076c20014108491b2107200641ff01200410cd04220520036a21030240200241034b0d00200520026a418001410320016b10cd041a0b200041146a2007360200200041106a41003602002000410c6a2003360200200041086a2001360200200041046a20053602000c020b41f495c5001058000b20054104102a000b200041003a00000b970d02117f017e230041206b220124000240024002400240200028020c220241016a22032002490d00200041046a28020022022104024020024108490d00200241016a41037641076c21040b024020032004410176490d00200141086a200310fb0320012d00084101460d042001411c6a2802002105200141146a2802002106200141106a2802002107200128020c210820002802002209280200417f7341808182847871210a200041046a28020020096a41016a210b2000280208210c200028020c210d03400240024002400240200a0d00200941046a210203402002200b4f0d02200c41206a210c20022802002103200241046a220421022003418081828478712203418081828478460d000b200341808182847873210a2004417c6a21090b200c200a684138716a220e280200210f410021030240200e28020422104104490d0041002103200f2102201021040340200228000020034105777341b9f3ddf1796c2103200241046a21022004417c6a220441034b0d000b2010417c6a22022002417c7122026b21102002200f6a41046a210f0b201041014b0d01200f21020c020b2000200d36020c2000200636020820002005200d6b3602102000280200210420002008360200200041046a22032802002102200320073602002002450d070240200241016a220341ffffffff01712003470d00200241086a417c712208200241056a490d00200820034103746a2008491a0b200410290c070b200f41026a21022010417e6a21102003410577200f2f00007341b9f3ddf1796c21030b02402010450d00200341057720022d00007341b9f3ddf1796c21030b200a417f6a210f41002102200341057741ff017341b9f3ddf1796c221121030340200241046a2202200320077122046a2103200820046a280000418081828478712210450d000b0240200820106841037620046a20077122026a2c00004100480d002008280200418081828478716841037621020b200f200a71210a200820026a201141197622033a00002002417c6a20077120086a41046a20033a0000200620024103746a200e2902003702000c000b0b200241016a21044100210341002102024003400240024020034101710d00200220044f0d0320022103200241016a21020c010b200241036a220320024922080d0220032004492207450d022004200241046a20081b200420071b21020b200028020020036a220320032802002203410776417f73418182840871200341fffefdfb07726a360200410121030c000b0b20002802002102200041046a220428020041016a220341044f0d01200241046a2002200310cf041a2004280200220220002802006a41016a418001410320026b10cd041a0c020b41f495c5001058000b200220036a20022800003600000b417f210202400240200041046a2211280200220341016a220f2003490d00200041086a21064100210b0340200b220c41016a210b0240200c20002802006a2d0000418001470d00024003402006280200200c4103746a220e2802002107410021030240200e28020422084104490d004100210320072102200821040340200228000020034105777341b9f3ddf1796c2103200241046a21022004417c6a220441034b0d000b2008417c6a22022002417c7122026b2108200220076a41046a21070b02400240200841014b0d00200721020c010b200741026a21022008417e6a2108200341057720072f00007341b9f3ddf1796c21030b02402008450d00200341057720022d00007341b9f3ddf1796c21030b201128020021082000280200210741002102200341057741ff017341b9f3ddf1796c220a21030340200241046a2202200320087122046a2103200720046a280000418081828478712210450d000b0240200720106841037620046a20087122026a2c00004100480d002007280200418081828478716841037621020b2002200a20087122036b200c20036b732008714104490d01200720026a22032d000021042003200a41197622103a00002002417c6a20087120076a41046a20103a00000240200441ff01460d00200628020020024103746a220229020021122002200e290200370200200e20123702000c010b0b20002802002203200c6a41ff013a000020032011280200200c417c6a716a41046a41ff013a0000200628020020024103746a200e2902003702000c010b2007200c6a200a41197622023a00002008200c417c6a7120076a41046a20023a00000b200b200f470d000b200041046a28020022024108490d010b200241016a41037641076c21020b20002002200028020c6b3602100b200141206a24000b19002000200141186a280200360204200020012802103602000b810101017f024002400240200041046a280200220320016b20024f0d00200120026a22022001490d0220034101742201200220022001491b22014100480d020240024020030d002001102721020c010b200028020020032001102821020b2002450d0120002002360200200041046a20013602000b0f0b20014101102a000b102b000bea0101017f230041e0006b22042400200420013602082004200336020c024020012003470d0020002002200110ce041a200441e0006a24000f0b200441286a41146a4103360200200441346a411d360200200441106a41146a41033602002004200441086a36024020042004410c6a360244200441c8006a41146a41003602002004420337021420044190d1c5003602102004411d36022c200441b8d6c5003602582004420137024c200441e4d1c5003602482004200441286a3602202004200441c8006a3602382004200441c4006a3602302004200441c0006a360228200441106a41a0d2c5001057000bbc0601037f230041d0006b22042400200420033a000f0240024002400240024020022802082205417f6a220620054f0d00200620054d0d010b411810272202450d012004421837023420042002360230200441306a4100411810fe0320042004280238220241186a3602382002200428023022056a411841f6a1c500411810ff03200420042902343702342004200536023041d497c5004134200441306a41c497c50010a201000b200141086a2802002105200228020020064103746a2206280200210202400240024020062d0006450d0020052002460d010b024002400240200520024d0d00200141086a2005417f6a2202360200200128020020026a2d00002205417c6a220241014b0d02024020020e020400040b4118102722020d0141184101102a000b412b10272202450d05200041013a0000200241276a41002800f29b45360000200241206a41002900eb9b45370000200241186a41002900e39b45370000200241106a41002900db9b45370000200241086a41002900d39b45370000200241002900cb9b45370000200041086a42ab808080b005370200200041046a20023602000c060b200241106a4100290086a245370000200241086a41002900fea145370000200241002900f6a14537000020044298808080800337022420042002360220200441c4006a410136020020044201370234200441b89cc5003602302004412136024c2004200441c8006a3602402004200441206a360248200441106a200441306a10e60302402004280224450d00200428022010290b200041013a0000200041046a20042903103702002000410c6a200441106a41086a2802003602000c050b0240200341ff017122024104460d0020052002470d020b200041003a0000200020053a00010c040b20004180083b01000c030b200420053a0048200441c4006a4102360200200441206a410c6a412536020020044202370234200441f89bc500360230200441253602242004200441206a3602402004200441c8006a36022820042004410f6a360220200441106a200441306a10e6032000410c6a200441186a280200360200200041046a2004290310370200200041013a00000c020b41184101102a000b412b4101102a000b200441d0006a24000bc00502047f017e230041d0006b22032400024002400240024002400240200241086a2802002204417f6a220520044f0d00200520044d0d010b411810272202450d01200241106a4100290086a245370000200241086a41002900fea145370000200241002900f6a14537000020034298808080800337022420032002360220200341cc006a41013602002003420137023c200341b89cc500360238200341213602142003200341106a3602482003200341206a3602102000200341386a10e6032003280224450d04200328022010290c040b0240024002402002280200220620054103746a2d000522054104460d00200341386a200120022005108004024020032d00384101470d002000200329023c370200200041086a200341c4006a2802003602000c070b200241086a2802002204450d01200228020021060b200241086a2004417f6a2202360200200620024103746a290200220742808080808080c0ff0083428080808080808001520d010b411810272202450d02200241106a4100290086a245370000200241086a41002900fea145370000200241002900f6a14537000020034298808080800337022420032002360220200341cc006a41013602002003420137023c200341b89cc500360238200341213602142003200341106a3602482003200341206a3602102000200341386a10e6032003280224450d04200328022010290c040b200141086a28020021022003200737030820022007a7470d02200041003602000c030b41184101102a000b41184101102a000b200341cc006a41023602002003412c6a41013602002003420237023c200341989bc50036023820034101360224200320023602342003200341206a3602482003200341086a3602282003200341346a360220200341106a200341386a10e603200041086a200341106a41086a280200360200200020032903103702000b200341d0006a24000bad0301057f230041c0006b2203240020032002360200024002402001280204220420024b0d002001280208417c6a21052001410c6a280200410374210102400340024020010d00200320043602042003412c6a4102360200200341306a410c6a41013602002003420337021c200341c0a3c500360218200341013602342003200341306a3602282003200341046a36023820032003360230200341086a200341186a10e6032000410c6a200341106a280200360200200041046a2003290308370200200041013a00000c040b02402004200541046a2802006a220620044f0d00412010272204450d02200041013a0000200441186a41002900b8a345370000200441106a41002900b0a345370000200441086a41002900a8a345370000200441002900a0a345370000200041086a42a08080808004370200200041046a20043602000c040b200141786a2101200541086a2105200420024b21072006210420070d0020062104200620024d0d000b20052d00002104200041003a0000200020043a00010c020b41204101102a000b200041003a00002000200128020020026a2d00003a00010b200341c0006a24000bbe0201037f230041106b220224000240024020002d00004104470d002002200128021841f499c50041032001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040c010b2002200128021841f799c50041082001411c6a28020028020c1105003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41809ac500108c04210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841b682c60041012004411c6a28020028020c1105000d010b2001280200220028021841b782c60041012000411c6a28020028020c11050021000b200120003a00080b200241106a2400200041ff01714100470b820601037f230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200541386a200141186a2203200141286a410010800420052d00384101470d012000200529023c370200200041086a200541c4006a2802003602000c020b200541cc006a41023602002005411c6a41013602002005420337023c200541f498c500360238200541013602142005200541106a36024820052005410c6a3602182005200541086a360210200541206a200541386a10e603200041086a200541206a41086a280200360200200020052903203702000c010b2001280200210220054100360220024020022802080d00200541cc006a41013602002005420237023c20054188a0c500360238200541013602342005200541306a3602482005200541206a360230200541106a200541386a10e60320052802102202450d0020002005290214370204200020023602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d0320024101742207200620062007491b22064100480d030240024020020d002006102721020c010b200328020020022006102821020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2202200228020041016a3602000c030b200541cc006a220241013602002005420137023c200541f0a2c50036023820054101360234200520063602302005200541306a360248200541106a200541386a10e60320052802102201450d022005200529021437021420052001360210200241013602002005420137023c200541b89cc500360238200541213602342005200541306a3602482005200541106a360230200541206a200541386a10e60302402005280214450d00200528021010290b20052802202202450d0220002005290224370204200020023602000c030b20064101102a000b102b000b200041003602000b200541d0006a24000bb00301017f230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200128020021022005410036023420022802080d01200541cc006a41013602002005420237023c20054188a0c500360238200541013602142005200541106a3602482005200541346a360210200541206a200541386a10e60320052802202202450d0120002005290224370204200020023602000c020b200541cc006a41023602002005412c6a41013602002005420337023c200541f498c500360238200541013602242005200541206a36024820052005410c6a3602282005200541086a360220200541106a200541386a10e603200041086a200541106a41086a280200360200200020052903103702000c010b200541386a200141186a2202200141286a22032004108004024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200541386a200220034100108004024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200041003602000b200541d0006a24000be70301047f230041c0006b22032400200341286a200141186a2204200141286a20021080040240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d0320024101742206200520052006491b22054100480d030240024020020d002005102721020c010b200428020020022005102821020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341f0a2c50036022820034101360214200320053602102003200341106a360238200341186a200341286a10e60320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341b89cc500360228200341213602142003200341106a3602382003200341186a3602102003200341286a10e6030240200328021c450d00200328021810290b20032802002201450d0220002003290204370204200020013602000c030b20054101102a000b102b000b200041003602000b200341c0006a24000ba00401047f230041c0006b22032400200341286a200141186a2204200141286a220520021080040240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a200420052002108004024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d0320024101742206200520052006491b22054100480d030240024020020d002005102721020c010b200428020020022005102821020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341f0a2c50036022820034101360214200320053602102003200341106a360238200341186a200341286a10e60320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341b89cc500360228200341213602142003200341106a3602382003200341186a3602102003200341286a10e6030240200328021c450d00200328021810290b20032802002201450d0220002003290204370204200020013602000c030b20054101102a000b102b000b200041003602000b200341c0006a24000be70301057f230041c0006b22032400200341286a200141186a2204200141286a20021080040240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d0320054101742207200620062007491b22064100480d030240024020050d002006102721050c010b200428020020052006102821050b2005450d02200120053602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341f0a2c50036022820034101360214200320063602102003200341106a360238200341186a200341286a10e60320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341b89cc500360228200341213602142003200341106a3602382003200341186a3602102003200341286a10e6030240200328021c450d00200328021810290b20032802002201450d0220002003290204370204200020013602000c030b20064101102a000b102b000b200041003602000b200341c0006a24000ba00401057f230041c0006b22032400200341286a200141186a2204200141286a220520021080040240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a200420052002108004024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d0320054101742207200620062007491b22064100480d030240024020050d002006102721040c010b200428020020052006102821040b2004450d02200120043602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c200341f0a2c50036022820034101360214200320063602102003200341106a360238200341186a200341286a10e60320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341b89cc500360228200341213602142003200341106a3602382003200341186a3602102003200341286a10e6030240200328021c450d00200328021810290b20032802002201450d0220002003290204370204200020013602000c030b20064101102a000b102b000b200041003602000b200341c0006a24000be70301047f230041c0006b22042400200441286a200141186a2205200141286a20021080040240024020042d00284101470d002000200429022c370200200041086a200441346a2802003602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d0320024101742207200620062007491b22064100480d030240024020020d002006102721020c010b200528020020022006102821020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20033a0000200141206a2201200128020041016a3602000c030b2004413c6a220141013602002004420137022c200441f0a2c50036022820044101360214200420063602102004200441106a360238200441186a200441286a10e60320042802182202450d022004200429021c37021c20042002360218200141013602002004420137022c200441b89cc500360228200441213602142004200441106a3602382004200441186a3602102004200441286a10e6030240200428021c450d00200428021810290b20042802002201450d0220002004290204370204200020013602000c030b20064101102a000b102b000b200041003602000b200441c0006a24000bc10201037f230041206b220224000240024020002d00004104470d002002200128021841b2bfc50041082001411c6a28020028020c11050022003a001820022001360210200241003a0019200241003602140c010b2002200128021841babfc50041052001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41c0bfc500108c04210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841b682c60041012004411c6a28020028020c1105000d010b2001280200220028021841b782c60041012000411c6a28020028020c11050021000b200120003a00080b200241206a2400200041ff01714100470bf30202047f057e230041d0006b2203240041012104024020002d00080d00200028020421050240200028020022062d00004104710d0041012104200628021841f481c60041b382c60020051b4102410120051b2006411c6a28020028020c1105000d0120012000280200200228020c11040021040c010b024020050d0041012104200628021841b482c60041022006411c6a28020028020c1105000d01200028020021060b41012104200341013a00172003200341176a3602102006290208210720062902102108200341346a41fc81c60036020020032006290218370308200629022021092006290228210a200320062d00303a00482006290200210b2003200a3703402003200937033820032008370328200320073703202003200b3703182003200341086a3602302001200341186a200228020c1104000d002003280230419482c6004102200328023428020c11050021040b200020043a00082000200028020441016a360204200341d0006a240020000b17000240200041046a280200450d00200028020010290b0b0c002000280200200110f7030b160020002802002200280200200028020820011082010b110020012000280200200028020810e9030bbd0801087f230041c0006b22032400200341246a2001360200200341346a200241146a2802002204360200200341033a00382003412c6a2002280210220520044103746a36020020034280808080800437030820032000360220410021062003410036021820034100360210200320053602302003200536022802400240024002400240200228020822070d0020022802002108200228020422092004200420094b1b220a450d0141012104200020082802002008280204200128020c1105000d04200841086a210241012106034002402005280200200341086a200541046a280200110400450d00410121040c060b2006200a4f0d02200241046a210020022802002101200541086a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110500450d000c050b0b20022802002108200228020422092002410c6a2802002205200520094b1b220a450d0041012104200020082802002008280204200128020c1105000d03200741106a2105200841086a21024101210603402003200541786a28020036020c2003200541106a2d00003a003820032005417c6a28020036020841002101410021040240024002400240200541086a2802000e0400010203000b2005410c6a2802002100410121040c020b02402005410c6a2802002207200328023422044f0d0041002104200328023020074103746a22072802044128470d0220072802002802002100410121040c020b41f8dbc500200720041037000b4100210420032802282207200328022c460d002003200741086a3602284100210420072802044128470d0020072802002802002100410121040b2003200036021420032004360210024002400240024002400240024020052802000e0404010006040b20032802282200200328022c470d010c050b200541046a2802002200200328023422044f0d01200328023020004103746a22002802044128470d04200028020028020021040c030b2003200041086a36022820002802044128470d03200028020028020021040c020b41f8dbc500200020041037000b200541046a28020021040b410121010b2003200436021c2003200136021802400240200541706a2802004101460d0020032802282204200328022c460d042003200441086a3602280c010b200541746a2802002204200328023422004f0d04200328023020044103746a21040b02402004280200200341086a200441046a280200110400450d00410121040c050b2006200a4f0d01200241046a210020022802002101200541246a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110500450d000c040b0b0240200920064d0d00410121042003280220200820064103746a22052802002005280204200328022428020c1105000d030b410021040c020b41c8dac5001058000b4188dcc500200420001037000b200341c0006a240020040bfc0101027f230041106b220224002002200128021841bb82c60041052001411c6a28020028020c1105003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a4190a3c500108c041a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d0041012101200028021841b682c60041012000411c6a28020028020c1105000d010b2002280200220128021841b782c60041012001411c6a28020028020c11050021010b200220013a00080b200241106a2400200141ff01714100470ba46601037f230041206b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000eac010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab0100010b200220012802184183b4c50041112001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000cab010b200220012802184194b4c500410b2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000caa010b20022001280218419fb4c50041032001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000ca9010b2002200128021841a2b4c50041052001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41a8b4c500108c0421000ca8010b2002200128021841b8b4c50041042001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41a8b4c500108c0421000ca7010b2002200128021841bcb4c50041022001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41a8b4c500108c0421000ca6010b2002200128021841beb4c50041042001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000ca5010b2002200128021841c2b4c50041032001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000ca4010b2002200128021841c5b4c50041022001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000ca3010b2002200128021841d8b4c50041042001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000ca2010b2002200128021841dcb4c50041072001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41e4b4c500108c04210120022000410c6a36020c20012002410c6a41c8b4c500108c0421000ca1010b2002200128021841f4b4c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000ca0010b2002200128021841fab4c50041042001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000c9f010b2002200128021841feb4c500410c2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041016a36020c20012002410c6a418cb5c500108c0421000c9e010b20022001280218419cb5c50041042001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c9d010b2002200128021841a0b5c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c9c010b2002200128021841a6b5c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000c9b010b2002200128021841aeb5c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000c9a010b2002200128021841b6b5c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000c99010b2002200128021841beb5c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000c98010b2002200128021841c7b5c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000c97010b2002200128021841d0b5c50041072001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c96010b2002200128021841d7b5c50041072001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c95010b2002200128021841deb5c50041072001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c94010b2002200128021841e5b5c50041072001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c93010b2002200128021841ecb5c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c92010b2002200128021841f5b5c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c91010b2002200128021841feb5c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c90010b200220012802184188b6c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c8f010b200220012802184192b6c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c8e010b20022001280218419bb6c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c8d010b2002200128021841a4b6c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c8c010b2002200128021841aeb6c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c8b010b2002200128021841b8b6c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c8a010b2002200128021841c2b6c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c89010b2002200128021841ccb6c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c88010b2002200128021841d4b6c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c87010b2002200128021841dcb6c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c86010b2002200128021841e4b6c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c85010b2002200128021841ecb6c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c84010b2002200128021841f5b6c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c83010b2002200128021841ffb6c50041092001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c82010b200220012802184188b7c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c81010b200220012802184192b7c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421012002200041086a36020c20012002410c6a41c8b4c500108c0421000c80010b20022001280218419cb7c500410d2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a418cb5c500108c0421000c7f0b2002200128021841a9b7c500410a2001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a418cb5c500108c0421000c7e0b2002200128021841b3b7c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41bcb7c500108c0421000c7d0b2002200128021841ccb7c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41d4b7c500108c0421000c7c0b2002200128021841e4b7c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41c8b4c500108c0421000c7b0b2002200128021841ecb7c50041082001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41f4b7c500108c0421000c7a0b200220012802184184b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c790b20022001280218418ab8c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c780b20022001280218418fb8c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c770b200220012802184194b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c760b20022001280218419ab8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c750b2002200128021841a0b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c740b2002200128021841a6b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c730b2002200128021841acb8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c720b2002200128021841b2b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c710b2002200128021841b8b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c700b2002200128021841beb8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c6f0b2002200128021841c4b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c6e0b2002200128021841cab8c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c6d0b2002200128021841cfb8c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c6c0b2002200128021841d4b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c6b0b2002200128021841dab8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c6a0b2002200128021841e0b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c690b2002200128021841e6b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c680b2002200128021841ecb8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c670b2002200128021841f2b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c660b2002200128021841f8b8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c650b2002200128021841feb8c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c640b200220012802184184b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c630b200220012802184189b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c620b20022001280218418eb9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c610b200220012802184193b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c600b200220012802184198b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c5f0b20022001280218419db9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c5e0b2002200128021841a2b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c5d0b2002200128021841a7b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c5c0b2002200128021841acb9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c5b0b2002200128021841b1b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c5a0b2002200128021841b6b9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c590b2002200128021841bbb9c50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c580b2002200128021841c0b9c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c570b2002200128021841c6b9c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c560b2002200128021841ccb9c50041092001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c550b2002200128021841d5b9c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c540b2002200128021841dbb9c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c530b2002200128021841e1b9c50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c520b2002200128021841e7b9c50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c510b2002200128021841eeb9c50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c500b2002200128021841f5b9c50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c4f0b2002200128021841fcb9c50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c4e0b200220012802184183bac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c4d0b200220012802184189bac50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c4c0b20022001280218418ebac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c4b0b200220012802184194bac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c4a0b20022001280218419abac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c490b2002200128021841a1bac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c480b2002200128021841a8bac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c470b2002200128021841afbac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c460b2002200128021841b6bac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c450b2002200128021841bcbac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c440b2002200128021841c2bac50041092001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c430b2002200128021841cbbac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c420b2002200128021841d1bac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c410b2002200128021841d7bac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c400b2002200128021841ddbac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c3f0b2002200128021841e4bac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c3e0b2002200128021841ebbac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c3d0b2002200128021841f2bac50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c3c0b2002200128021841f9bac50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c3b0b2002200128021841ffbac50041052001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c3a0b200220012802184184bbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c390b20022001280218418abbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c380b200220012802184190bbc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c370b200220012802184197bbc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c360b20022001280218419ebbc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c350b2002200128021841a5bbc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c340b2002200128021841acbbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c330b2002200128021841b2bbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c320b2002200128021841b8bbc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c310b2002200128021841bfbbc50041082001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c300b2002200128021841c7bbc50041082001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c2f0b2002200128021841cfbbc500410a2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c2e0b2002200128021841d9bbc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c2d0b2002200128021841e0bbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c2c0b2002200128021841e6bbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c2b0b2002200128021841ecbbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c2a0b2002200128021841f2bbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c290b2002200128021841f8bbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c280b2002200128021841febbc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c270b200220012802184184bcc500410b2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c260b20022001280218418fbcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c250b200220012802184195bcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c240b20022001280218419bbcc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c230b2002200128021841a2bcc50041082001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c220b2002200128021841aabcc50041082001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c210b2002200128021841b2bcc500410a2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c200b2002200128021841bcbcc50041072001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c1f0b2002200128021841c3bcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c1e0b2002200128021841c9bcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c1d0b2002200128021841cfbcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c1c0b2002200128021841d5bcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c1b0b2002200128021841dbbcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c1a0b2002200128021841e1bcc50041062001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c190b2002200128021841e7bcc500410b2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c180b2002200128021841f2bcc500410a2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c170b2002200128021841fcbcc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c160b200220012802184188bdc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c150b200220012802184194bdc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c140b2002200128021841a0bdc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c130b2002200128021841acbdc500410d2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c120b2002200128021841b9bdc500410d2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c110b2002200128021841c6bdc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c100b2002200128021841d2bdc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c0f0b2002200128021841debdc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c0e0b2002200128021841eabdc500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c0d0b2002200128021841f6bdc500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c0c0b200220012802184184bec500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c0b0b200220012802184192bec500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c0a0b2002200128021841a0bec500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c090b2002200128021841aebec500410c2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c080b2002200128021841babec500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c070b2002200128021841c8bec500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c060b2002200128021841d6bec500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c050b2002200128021841e4bec500410e2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c040b2002200128021841f2bec500410d2001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c030b2002200128021841ffbec50041112001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c020b200220012802184190bfc50041112001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000c010b2002200128021841a1bfc50041112001411c6a28020028020c1105003a001820022001360210200241003a001920024100360214200241106a21000b20002d00082101024020002802042203450d00200141ff0171210441012101024020040d00024020034101470d0020002d0009450d00200028020022042d00004104710d0041012101200428021841b682c60041012004411c6a28020028020c1105000d010b2000280200220128021841b782c60041012001411c6a28020028020c11050021010b200020013a00080b200241206a2400200141ff01714100470bd00201027f230041106b220224002000280200280200210020012802184196a4c50041052001411c6a28020028020c1105002103200241003a0005200220033a00042002200136020020022000410c6a36020c2002419ba4c500410e2002410c6a41aca4c50010950421012002200036020c200141bca4c50041092002410c6a41c8a4c50010950421012002200041046a36020c200141d8a4c500410c2002410c6a41c8a4c50010950421012002200041086a36020c200141e4a4c500410c2002410c6a41c8a4c5001095041a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341b082c6004102200111050021000c010b200341b282c6004101200111050021000b200220003a00040b200241106a2400200041ff01714100470bdd0302047f057e230041d0006b2205240041012106024020002d00040d0020002d000521070240200028020022082d00004104710d0041012106200828021841f481c60041f181c600200741ff017122071b4102410320071b2008411c6a28020028020c1105000d014101210620002802002208280218200120022008411c6a28020028020c1105000d01410121062000280200220828021841c481c60041022008411c6a28020028020c1105000d0120032000280200200428020c11040021060c010b0240200741ff01710d0041012106200828021841f681c60041032008411c6a28020028020c1105000d01200028020021080b41012106200541013a00172005200541176a360210200829020821092008290210210a200541346a41fc81c600360200200520082902183703082008290220210b2008290228210c200520082d00303a00482008290200210d2005200c3703402005200b3703382005200a370328200520093703202005200d3703182005200541086a360230200541086a2001200210c5040d00200541086a41c481c600410210c5040d002003200541186a200428020c1104000d002005280230419482c6004102200528023428020c11050021060b200041013a0005200020063a0004200541d0006a240020000b865f010b7f23004190016b220324002003200136021c2002280208220441586a2105200241106a2802002206412c6c2101024002400240024002400240024002400240024002400240024002400240024002400240024003402001450d01200141546a2101200541286a21072005412c6a2208210520072d00004104470d000b2006412c6c2101200441586a210503402001450d02200141546a2101200541286a21072005412c6a2209210520072d0000410b470d000b2006412c6c2101200441586a210503402001450d03200141546a2101200541286a21072005412c6a2204210520072d00004102470d000b024041002802c082464105490d002003410136023c20032003411c6a36023841002802c48246210120034188016a41980136020020034180016a42ec80808010370300200341f8006a4125360200200341f0006a4101360200200341e0006a4201370300200341d8006a410a360200200341aba8c50036027c20034186a8c500360274200341ec006a200341386a360200200341a4a5c50036025c200341fca7c5003602542003410536025041c882c60041b8d6c500200141024622011b200341d0006a41b4cac50041cccac50020011b2802101100000b200341106a20081080032003280214200328021c22014d0d03200328021020014102746a2201450d03200341086a20041080030240200328020c200128020022014d0d00200328020820014104746a22010d050b412510272201450d092001411d6a41002900c9a545370000200141186a41002900c4a545370000200141106a41002900bca545370000200141086a41002900b4a545370000200141002900aca545370000200041086a42a5808080d00437020020002001360204200041013602000c120b411310272201450d042001410f6a41002800ffa445360000200141086a41002900f8a445370000200141002900f0a445370000200041086a4293808080b00237020020002001360204200041013602000c110b410f10272201450d04200141076a410029008aa54537000020014100290083a545370000200041086a428f808080f00137020020002001360204200041013602000c100b410f10272201450d04200141076a4100290099a54537000020014100290092a545370000200041086a428f808080f00137020020002001360204200041013602000c0f0b412510272201450d042001411d6a41002900c9a545370000200141186a41002900c4a545370000200141106a41002900bca545370000200141086a41002900b4a545370000200141002900aca545370000200041086a42a5808080d00437020020002001360204200041013602000c0e0b0240200941086a280200200328021c22054b0d00412710272201450d062001411f6a41002900f0a545370000200141186a41002900e9a545370000200141106a41002900e1a545370000200141086a41002900d9a545370000200141002900d1a545370000200041086a42a7808080f00437020020002001360204200041013602000c0e0b20092802002109200341206a41086a420037030020034280808080c00037032020012d000d2107410021012003410036024020032007410447220a36023c2003200a360238200341003a0044024041002802c0824641044b0d00200341d0006a41086a200341386a41086a29030037030020032003290338370350200341d0006a21070c070b2003412936024c2003200341386a36024841002802c48246210120034188016a41cb0036020020034180016a42ec80808010370300200341f8006a4125360200200341f0006a4101360200200341e0006a4201370300200341d0006a41086a2207410a360200200341aba8c50036027c20034186a8c500360274200341ec006a200341c8006a360200200341f8a5c50036025c200341fca7c5003602542003410536025041c882c60041b8d6c500200141024622011b200341d0006a41b4cac50041cccac50020011b280210110000200328022c2108200328022821012007200341386a41086a29030037030020032003290338370350200341d0006a210720082001460d0620032802242101200341d0006a21070c070b41134101102a000b410f4101102a000b410f4101102a000b41254101102a000b41254101102a000b41274101102a000b200141016a22082001490d0520014101742206200820082006491b220841ffffffff00712008470d05200841047422064100480d050240024020010d002006102721010c010b200328022420014104742006102821010b2001450d012003200836022820032001360224200328022c21080b200120084104746a22012007290200370200200141086a200741086a2902003702002003200328022c41016a36022c410021072009200541186c6a2201280214450d022009200541186c6a410c6a2109200141146a2108200341d0006a410472210b410021074100210103400240200328022020074d0d00200341d0006a200341206a4100109804024020032802504101470d00200041013602002000200b2902003702042000410c6a200b41086a2802003602000c060b2007200328022020032802542d000c1b21070b02400240024002400240024002402001200828020022054f0d002003200928020020014104746a2205360234024041002802c082464105490d002003412236023c2003200341346a36023841002802c482462105200341c90136028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c50036027420034101360270200342013703602003419c81c60036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328023421050b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020052d000022060eac0102220000002201030405060708090a0b0c0d0e0f1010101010101010101010101010111111111111111111121314141414151616161616161616161615161616161616161616161616161616161616161616161717171818181818181818181818181818181717171818181818181818181818181818181717171717171718181818181818171717171717171818181818181819191919191919191919191919191919191919191919191919020b20052d00012105200320032802203602402003200541044722053602382003200641034720057136023c200341003a0044024041002802c082464105490d002003412936024c2003200341386a36024841002802c482462105200341cb0036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341f8a5c50036025c2003410a360258200341fca7c500360254200341053602502003200341c8006a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b2802101100000b200341d0006a41086a200341386a41086a2903003703002003200329033837035002400240200328022c22052003280228460d00200328022421060c010b200541016a22062005490d282005410174220c20062006200c491b220c41ffffffff0071200c470d28200c410474220d4100480d280240024020050d00200d102721060c010b20032802242005410474200d102821060b2006450d1d2003200c36022820032006360224200328022c21050b200620054104746a22052003290350370200200541086a200341d0006a41086a2903003702002003200328022c41016a36022c0c210b41002105024041002802c082464105490d000240200328022c2206417f6a220c20064b0d002003280224200c4104746a4100200c2006491b21050b2003412a36024c200320053602382003200341386a36024841002802c482462105200341d30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c500360274200341013602702003420137036020034180a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341c8006a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b2802101100000b0240200328022c2205450d0020032005417f6a220536022c200328022420054104746a22052d000c4102470d1a0b411710272201450d1c2001410f6a4100290097a645370000200141086a4100290090a64537000020014100290088a645370000200041086a4297808080f00237020020002001360204200041013602000c250b024041002802c082464105490d0041002802c482462105200341c10036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410036027020034201370360200341a0a6c50036025c2003410a360258200341fca7c50036025420034105360250200341b8d6c50036026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b2802101100000b0240200328022c2205417f6a220620054f0d00200620054d0d180b411710272201450d1e2001410f6a4100290097a645370000200141086a4100290090a64537000020014100290088a645370000200041086a4297808080f00237020020002001360204200041013602000c240b200341d0006a200341206a200541046a280200109804024020032802504101470d00200041013602002000200b2902003702042000410c6a200b41086a2802003602000c240b200341d0006a200341206a2003280254280204109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b024041002802c082464105490d0041002802c482462105200341c10036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410036027020034201370360200341a0a6c50036025c2003410a360258200341fca7c50036025420034105360250200341b8d6c50036026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b2802101100000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102722010d0141174101102a000b200328022420064104746a41013a000c0c1f0b2001410f6a4100290097a645370000200141086a4100290090a64537000020014100290088a645370000200041086a4297808080f00237020020002001360204200041013602000c230b200341d0006a200341206a200541046a280200109804024020032802504101470d00200041013602002000200b2902003702042000410c6a200b41086a2802003602000c230b200341d0006a200341206a20032802542802042205109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c230b200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c230b20032005360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c1e0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c220b200341d0006a200341206a2005410c6a280200109804024020032802504101470d00200041013602002000200b2902003702042000410c6a200b41086a2802003602000c220b2003280254280204210c200541086a2802004102742106200541046a280200210502400340024020060d00200341d0006a200341206a200c109a042003280250450d0220002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b200341d0006a200341206a2005280200109804024020032802504101470d00200041013602002000200b2902003702042000410c6a200b41086a2802003602000c240b2006417c6a2106200541046a21052003280254280204200c460d000b412710272201450d1a2001411f6a41002900dda645370000200141186a41002900d6a645370000200141106a41002900cea645370000200141086a41002900c6a645370000200141002900bea645370000200041086a42a7808080f00437020020002001360204200041013602000c220b024041002802c082464105490d0041002802c482462105200341c10036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410036027020034201370360200341a0a6c50036025c2003410a360258200341fca7c50036025420034105360250200341b8d6c50036026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b2802101100000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102722010d0141174101102a000b200328022420064104746a41013a000c0c1d0b2001410f6a4100290097a645370000200141086a4100290090a64537000020014100290088a645370000200041086a4297808080f00237020020002001360204200041013602000c210b200341d0006a200341206a200a109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c210b024041002802c082464105490d0041002802c482462105200341c10036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410036027020034201370360200341a0a6c50036025c2003410a360258200341fca7c50036025420034105360250200341b8d6c50036026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b2802101100000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102722010d0141174101102a000b200328022420064104746a41013a000c0c1c0b2001410f6a4100290097a645370000200141086a4100290090a64537000020014100290088a645370000200041086a4297808080f00237020020002001360204200041013602000c200b200341d0006a200541046a2802002002109b04024020032802504101470d00200041013602002000200b2902003702042000410c6a200b41086a2802003602000c200b200341d0006a200341206a20032802542205280208109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c200b200320052d000d4104472205360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c1b0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c1f0b20032004108003024002402003280204200541046a28020022054d0d002003280200220620054104746a220c0d010b410e10272201450d18200141066a41002900eba645370000200141002900e5a645370000200041086a428e808080e00137020020002001360204200041013602000c1f0b200341d0006a200341206a200620054104746a280208109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1f0b2003200c2d000d4104472205360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c1a0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c1e0b200341d0006a200341206a4101109a042003280250450d1820002003290350370204200041013602002000410c6a200341d8006a2802003602000c1d0b200341d0006a200341206a4102109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1d0b41012105200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1d0b20034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c180b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c1c0b4101210520034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c170b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c1b0b200341d0006a200341206a4101109a042003280250450d1520002003290350370204200041013602002000410c6a200341d8006a2802003602000c1a0b41012105200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1a0b20034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c150b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c190b4101210520034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c140b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c180b200341d0006a200341206a4101109a042003280250450d1220002003290350370204200041013602002000410c6a200341d8006a2802003602000c170b41012105200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c170b20034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c120b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c160b200341d0006a200341206a4102109a042003280250450d1020002003290350370204200041013602002000410c6a200341d8006a2802003602000c150b4101210520034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c100b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c140b41012105200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c140b20034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c0f0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c130b4101210520034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c0e0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c120b41012105200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c120b20034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c0d0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c110b200341d0006a200341206a4102109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c110b4101210520034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c0c0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c100b41012105200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c100b20034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c0b0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c0f0b200341d0006a200341206a4102109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c0f0b4101210520034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c0a0b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c0e0b41012105200341d0006a200341206a4101109a0402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c0e0b20034101360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328024821050b024002402003280220220620056a220520064f0d00410e102722010d01410e4101102a000b200320053602200c090b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c0d0b200328022420064104746a41013a000c0c070b20052802002106200320052802082205360238024041002802c082464105490d002003410136024c2003200341386a36024841002802c482462105200341db0036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341f4a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341c8006a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b280210110000200328023821050b2003200536022020032006360248024041002802c082464105490d002003410136023c2003200341c8006a36023841002802c482462105200341e30036028801200342ec8080801037038001200341aba8c50036027c2003412536027820034186a8c5003602742003410136027020034201370360200341a8a6c50036025c2003410a360258200341fca7c500360254200341053602502003200341386a36026c41c882c60041b8d6c500200541024622051b200341d0006a41b4cac50041cccac50020051b28021011000020032802202105200328024821060b0240200520066a220620054f0d00410e102722010d0a410e4101102a000b200320063602200c060b41fca6c500200120051037000b200d4104102a000b41174101102a000b41274101102a000b410e4101102a000b41174101102a000b200141016a22012008280200490d000c030b0b20064104102a000b200141066a41002900b6a645370000200141002900b0a645370000200041086a428e808080e00137020020002001360204200041013602000c010b20004100360200200020073602042003280228450d02200328022410290c020b2003280228450d01200328022410290c010b102b000b20034190016a24000bc60201027f230041106b2202240020012802184196a4c50041052001411c6a28020028020c1105002103200241003a0005200220033a00042002200136020020022000410c6a36020c2002419ba4c500410e2002410c6a41aca4c50010950421012002200036020c200141bca4c50041092002410c6a41c8a4c50010950421012002200041046a36020c200141d8a4c500410c2002410c6a41c8a4c50010950421012002200041086a36020c200141e4a4c500410c2002410c6a41c8a4c5001095041a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341b082c6004102200111050021000c010b200341b282c6004101200111050021000b200220003a00040b200241106a2400200041ff01714100470b9b0201027f024002400240024002402001410c6a2802002203417f6a220420034d0d00411610272201450d01200020013602042001410e6a4100290089aa45370000200141086a4100290083aa45370000200141002900fba945370000200041086a4296808080e0023702000c040b0240200420026b220220044d0d00411b10272201450d0220002001360204200141176a41002800a8aa45360000200141106a41002900a1aa45370000200141086a4100290099aa4537000020014100290091aa45370000200041086a429b808080b0033702000c040b200320024d0d022000200128020420024104746a360204200041003602000f0b41164101102a000b411b4101102a000b41acaac500200220031037000b200041013602000bbb0201037f230041106b220224000240024020002802000d00200220012802184186b2c50041042001411c6a28020028020c11050022003a000820022001360200200241003a0009200241003602040c010b20022001280218418ab2c50041042001411c6a28020028020c1105003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a4190b2c500108c04210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841b682c60041012004411c6a28020028020c1105000d010b2001280200220028021841b782c60041012000411c6a28020028020c11050021000b200120003a00080b200241106a2400200041ff01714100470bc50401027f230041d0006b2203240020032002360204024041002802c082464105490d002003410136020c2003200341046a36020841002802c482462102200341c8006a41ef00360200200341c0006a42ec80808010370300200341386a4125360200200341306a4101360200200341206a4201370300200341186a410a360200200341aba8c50036023c20034186a8c5003602342003412c6a200341086a360200200341a4a9c50036021c200341fca7c5003602142003410536021041c882c60041b8d6c500200241024622021b200341106a41b4cac50041cccac50020021b280210110000200328020421020b0240024002402002450d00200341106a2001410010980420032802104101470d012000200341106a4104722202290200370200200041086a200241086a2802003602000c020b200041003602000c010b02400240024002402001280200220220032802142204280208460d00200220032802046b220420024d0d02410f102722020d01410f4101102a000b024020042d000c0d00412510272202450d03200042a5808080d004370204200020023602002002411d6a41002900c9a945370000200241186a41002900c4a945370000200241106a41002900bca945370000200241086a41002900b4a945370000200241002900aca9453700000c040b200041003602000c030b2000428f808080f00137020420002002360200200241076a41002900d8a945370000200241002900d1a9453700000c020b20004100360200200120043602000c010b41254101102a000b200341d0006a24000bd809010b7f230041e0006b22032400200320013602202002280208220441586a2105200241106a2802002206412c6c210202400340024020020d00410021070c020b200241546a2102200541286a21072005412c6a2208210520072d00004102470d000b200341186a200810800320032802182107200328021c21020b2002410020071b21092006412c6c2102200441586a2105200741b8d6c50020071b210a02400340024020020d004100210b0c020b200241546a2102200541286a21072005412c6a2208210520072d00004104470d000b200341106a20081080032003280210210b2003280214210c0b2006412c6c2102200441586a2105200b41b8d6c500200b1b210d0240024002400240024002400240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d012006412c6c2102200441586a210502400240024003402002450d01200241546a2102200541286a21072005412c6a2208210520072d00004103470d000b200341086a200810800320032802082207200328020c41286c6a2108024003400240024002402008200722026b41f8004b0d0020022008460d0f2002411c6a2105034020022d0018450d02200541286a2105200241286a22022008470d000c100b0b20022d00180d012002411c6a2105200241286a21070c060b2005410c6a21070c050b200241c0006a2d0000450d01200241e8006a2d0000450d03200241a0016a210720024190016a2d00000d000b20024194016a21050c030b200241c4006a2105200241d0006a21070c020b4185aec50041c200104e000b200241ec006a2105200241f8006a21070b2001450d0203402001417f6a21010240024003400240024002402008200722026b41f8004b0d0020022008460d0e2002411c6a2105034020022d0018450d02200541286a2105200241286a22022008460d0f0c000b0b20022d00180d01200241286a210720010d052002411c6a21050c080b2005410c6a21072001450d070c040b200241c0006a2d0000450d02200241e8006a2d0000450d01200241a0016a210720024190016a2d00000d000b20010d0220024194016a21050c050b200241f8006a210720010d01200241ec006a21050c040b200241d0006a210720010d000b200241c4006a21050c020b410021050b200c4100200b1b200120056b22024d0d01200d20024102746a2205450d010b200320052802002202360224200920024d0d01200a20024104746a2202450d0120002002360204410021020c030b200341cc006a41013602002003420237023c200341a4afc5003602382003410136022c2003200341286a3602482003200341206a360228200341d0006a200341386a10e603200341d0006a21020c010b200341cc006a4102360200200341dc006a41013602002003420337023c200341b4afc500360238200341013602542003200341d0006a3602482003200341206a3602582003200341246a360250200341286a200341386a10e603200341286a21020b20022802002105200041086a200229020437020020002005360204410121020b20002002360200200341e0006a24000f0b41c7aec50041dd00104e000bc60902057f017e024020010d00200041ac013a00000f0b02400240024002400240024020012d00002202414f6a41fb004f0d000c010b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e312c2c0001022c2c0304052c06072c2c08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292c0b20012d00012103410221020c2b0b20012d00012103410321020c2a0b20012d00012103410421020c290b200141046a2802002104410721020c270b200141046a2802002104410821020c260b2001280208220541ffffffff03712005470d2720054102742202417f4c0d270240024020020d00410421040c010b200210272204450d290b02402005450d00200128020421022005410274210620042103034020032002280200360200200341046a2103200241046a21022006417c6a22060d000b0b200135020c4220862005ad842107410921020c250b200141046a2802002104410b21020c240b200141046a280200210420012d00012103410c21020c240b200141046a2802002104410f21020c220b200141046a2802002104411021020c210b200141046a2802002104411121020c200b200141046a2802002104411221020c1f0b200141046a2802002104411321020c1e0b200141046a280200210420013502082107411421020c1d0b200141046a280200210420013502082107411521020c1c0b200141046a280200210420013502082107411621020c1b0b200141046a280200210420013502082107411721020c1a0b200141046a280200210420013502082107411821020c190b200141046a280200210420013502082107411921020c180b200141046a280200210420013502082107411a21020c170b200141046a280200210420013502082107411b21020c160b200141046a280200210420013502082107411c21020c150b200141046a280200210420013502082107411d21020c140b200141046a280200210420013502082107411e21020c130b200141046a280200210420013502082107411f21020c120b200141046a280200210420013502082107412021020c110b200141046a280200210420013502082107412121020c100b200141046a280200210420013502082107412221020c0f0b200141046a280200210420013502082107412321020c0e0b200141046a280200210420013502082107412421020c0d0b200141046a280200210420013502082107412521020c0c0b200141046a280200210420013502082107412621020c0b0b200141046a280200210420013502082107412721020c0a0b200141046a280200210420013502082107412821020c090b200141046a280200210420013502082107412921020c080b200141046a280200210420013502082107412a21020c070b20012d00012103412b21020c070b20012d00012103412c21020c060b200141046a2802002104412d21020c040b20012903082107412e21020c020b200141046a2802002104412f21020c020b20012903082107413021020b0b0b200020033a0001200020023a0000200041086a2007370300200041046a20043602000f0b1039000b20024104102a000b8d0301067f230041106b220224000240024002400240200041046a2802002203200041086a28020022046b20012802042205200128020022066b4104762207490d00200028020021030c010b200420076a22062004490d0220034101742205200620062005491b220641ffffffff00712006470d02200641047422054100480d020240024020030d002005102721030c010b200028020020034104742005102821030b2003450d0120002003360200200041046a2006360200200041086a280200210420012802042105200128020021060b0240024020062005470d00410021060c010b2001200641106a3602000b20022006109c04024020022d000041ac01460d00200320044104746a2106034020062002290300370300200641086a200241086a29030037030002400240200128020022052001280204470d00410021050c010b2001200541106a3602000b200441016a2104200641106a210620022005109c0420022d000041ac01470d000b0b200041086a2004360200200241106a24000f0b20054108102a000b102b000b110020002802003502004101200110aa010bea0302057f017e02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d00200020014105746a220441c4006a2802002105200441386a2802002106200441346a2802002107200141016a21010c010b02400240200028020022010d002003ad210841002104410021010c010b20003301044220862003ad842108410121040b200010292008a72103024002402008422088a7220620012f01064f0d00200121050c010b034002400240200128020022050d002003ad2108410021050c010b200441016a210420013301044220862003ad8421080b200110292008a72103200521012008422088a7220620052f01064f0d000b0b200641027420056a4198036a2802002100200520064105746a220141c4006a2802002105200141386a2802002106200141346a280200210702402004417f6a2201450d00034020002802940321002001417f6a22010d000b0b410021010b20054102460d012002417f6a210202402006450d00200710290b20020d000b0b02402000418883c000460d0020002802002101200010292001450d0020012802002105200110292005450d00024020052802002201450d000340200510292001210520012802002200210120000d000b0b200510290b0b2300200141fd80c60041f880c60020002802002d000022001b4104410520001b10e9030b02000bc60201037f230041206b2202240002400240200028020022002d00004104470d002002200128021841b2bfc50041082001411c6a28020028020c11050022003a001820022001360210200241003a0019200241003602140c010b2002200128021841babfc50041052001411c6a28020028020c1105003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41c0bfc500108c04210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841b682c60041012004411c6a28020028020c1105000d010b2001280200220028021841b782c60041012000411c6a28020028020c11050021000b200120003a00080b200241206a2400200041ff01714100470b890501047f230041d0006b220224002000280200220041046a28020021032000280200210041012104200128021841ba82c60041012001411c6a28020028020c110500210502402003450d0020022000360204024020050d00024020012d0000410471450d0041012104200128021841b882c6004101200128021c28020c1105000d012001280200210541012104200241013a001720022005360218200241fc81c60036023420022001290218370308200220012d00303a00482002200128020436021c200220012902283703402002200129022037033820022001290210370328200220012902083703202002200241176a3602102002200241086a360230200241046a200241186a1080010d012002280230419482c6004102200228023428020c11050021040c010b200241046a200110800121040b024020034101470d00200421050c010b200041046a21002003410274417c6a210320042105034020022000360204200541ff0171210441012105024020040d00024020012802002204410471450d00200241013a001720022004360218200241fc81c60036023420022001290218370308200220012d00303a00482002200128020436021c200220012902283703402002200129022037033820022001290210370328200220012902083703202002200241176a3602102002200241086a360230200241046a200241186a1080010d012002280230419482c6004102200228023428020c11050021050c010b200128021841f481c6004102200128021c28020c1105000d00200241046a200110800121050b200041046a21002003417c6a22030d000b0b41012100024020050d00200128021841b982c6004101200128021c28020c11050021000b200241d0006a240020000b8c0e01087f024020002802082201450d00200028020022022001412c6c6a2103034020022204412c6a21020240024020042d00002200410d4b0d00024002400240024002400240024002400240024002400240024020000e0e0001020304050607080e090a0b0c000b200441086a280200450d0d200441046a28020010290c0d0b0240200441086a280200450d00200441046a28020010290b200441146a280200450d0c200441106a28020010290c0c0b02402004410c6a2802002201450d00200441046a28020021002001410474210103400240200041046a280200450d00200028020010290b200041106a2100200141706a22010d000b0b200441086a280200450d0b200428020410290c0b0b02402004410c6a2802002201450d00200441046a2802002100200141286c210103400240200041046a280200450d00200028020010290b0240200041106a280200450d002000410c6a28020010290b200041286a2100200141586a22010d000b0b200441086a280200450d0a200428020410290c0a0b200441086a280200450d09200441046a28020010290c090b200441086a280200450d08200441046a28020010290c080b200441086a280200450d07200441046a28020010290c070b02402004410c6a2802002200450d00200441046a280200220520004104746a21060340024020052802082201450d0020052802002100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010290b200041106a2100200141706a22010d000b0b200541106a21000240200541046a280200450d00200528020010290b2000210520002006470d000b0b200441086a280200450d06200428020410290c060b02402004410c6a2802002201450d00200441046a2802002100200141146c210103400240200041046a280200450d00200028020010290b200041146a21002001416c6a22010d000b0b200441086a280200450d05200428020410290c050b02402004410c6a2802002200450d00200441046a28020022052000411c6c6a2106034002402005410c6a2802002201450d0020052802042100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010290b200041106a2100200141706a22010d000b0b0240200541086a280200450d00200528020410290b2005411c6a21000240200541146a280200450d00200528021010290b2000210520002006470d000b0b200441086a280200450d04200428020410290c040b02402004410c6a2802002200450d00200441046a2802002205200041186c6a210603400240200541046a280200450d00200528020010290b0240200541146a2802002201450d00200528020c2100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010290b200041106a2100200141706a22010d000b0b200541186a21000240200541106a280200450d00200528020c10290b2000210520002006470d000b0b200441086a280200450d03200428020410290c030b02402004410c6a2802002200450d00200441046a28020022052000411c6c6a2106034002402005410c6a2802002201450d0020052802042100200141047421010340024020002d00004109470d00200041086a28020041ffffffff0371450d00200041046a28020010290b200041106a2100200141706a22010d000b0b0240200541086a280200450d00200528020410290b2005411c6a21000240200541146a280200450d00200528021010290b2000210520002006470d000b0b200441086a280200450d02200428020410290c020b0240200441046a2d0000220041024b0d0002400240024020000e03000102000b2004410c6a280200450d04200441086a28020010290c040b0240200441146a2802002201450d002004410c6a28020021002001410c6c21010340024020002802002205450d00200041046a280200450d00200510290b2000410c6a2100200141746a22010d000b0b200441106a280200450d03200428020c10290c030b0240200441146a2802002200450d002004410c6a280200220720004104746a210803402007220641106a2107024020062802042200450d0002402006410c6a2802002201450d002001410c6c21010340024020002802002205450d00200041046a280200450d00200510290b2000410c6a2100200141746a22010d000b0b200641086a280200450d00200628020410290b20072008470d000b0b200441106a280200450d02200428020c10290c020b2004410c6a280200450d01200441086a28020010290c010b0240200441086a280200450d00200441046a28020010290b0240200441146a2802002200450d00200441186a280200450d00200010290b200441246a280200450d00200441206a28020010290b20022003470d000b0b0bc30201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff01834101200110aa0121000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000b20024180016a240020000f0b2004418001103e000b2004418001103e000bd00203027f017e017f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210020034120710d012000ac22042004423f8722047c2004852000417f73411f76200110aa0121000c020b20002802002103410021000340200220006a41ff006a2003410f712205413072200541d7006a2005410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000c010b410021030340200220036a41ff006a2000410f712205413072200541376a2005410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141e8d9c5004102200220036a4180016a410020036b10ab0121000b20024180016a240020000f0b2003418001103e000b2000418001103e000bd00202027f027e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d0120042004423f8722057c2005852004427f55200110aa0121000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d022001410141e8d9c5004102200220006a4180016a410020006b10ab0121000b20024180016a240020000f0b2003418001103e000b2003418001103e000b040041000b02000b02000b2700200028020c200041106a2802001010200041146a3502001022200041186a350200102200000b08002000200110100bcd0701037f024002400240024002400240024002402001413f4b0d0002400240200241046a280200200241086a2802002203460d00200228020021040c010b200341016a22042003490d0820034101742205200420042005491b22054100480d080240024020030d002005102721040c010b200228020020032005102821040b2004450d0220022004360200200241046a2005360200200241086a28020021030b200241086a200341016a360200200420036a20014102743a00000c050b200141808001490d032001418080808004490d020c010b20054101102a000b0240024002400240200241046a280200200241086a2802002203460d00200228020021040c010b200341016a22042003490d0720034101742205200420042005491b22054100480d070240024020030d002005102721040c010b200228020020032005102821040b2004450d0120022004360200200241046a2005360200200241086a28020021030b200241086a2205200341016a360200200420036a41033a000002400240200241046a2802002204200528020022036b4104490d00200228020021040c010b200341046a22052003490d0720044101742203200520052003491b22034100480d070240024020040d002003102721040c010b200228020020042003102821040b2004450d0220022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a20013600000c040b20054101102a000b20034101102a000b024002400240200241046a2802002204200241086a28020022036b4104490d00200228020021040c010b200341046a22052003490d0520044101742203200520052003491b22034100480d050240024020040d002003102721040c010b200228020020042003102821040b2004450d0120022004360200200241046a2003360200200241086a28020021030b200241086a200341046a360200200420036a20014102744102723600000c020b20034101102a000b02400240200241046a2802002204200241086a28020022036b4102490d00200228020021040c010b200341026a22052003490d0320044101742203200520052003491b22034100480d030240024020040d002003102721040c010b200228020020042003102821040b2004450d0220022004360200200241046a2003360200200241086a28020021030b200241086a200341026a360200200420036a20014102744101723b00000b024020014103742201450d00200020016a210103402000280200200041046a280200200210c702200041086a22002001470d000b0b0f0b20034101102a000b102b000b841001047f024002400240024002400240024002400240024002400240024020002d0000220241024b0d0002400240024020020e03000102000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0f20024101742204200320032004491b22044100480d0f0240024020020d002004102721030c010b200128020020022004102821030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41003a0000200041086a2802002000410c6a280200200110c7020f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0e20024101742204200320032004491b22044100480d0e0240024020020d002004102721030c010b200128020020022004102821030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a000020002d0001210502400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d0e20024101742204200320032004491b22044100480d0e0240024020020d002004102721030c010b200128020020022004102821030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20053a0000200041086a2802002000410c6a280200200110c702200041146a280200200041186a280200200110c70202400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d0e20024101742204200320032004491b22044100480d0e0240024020020d002004102721030c010b200128020020022004102821030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20002d00023a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0d20024101742204200320032004491b22044100480d0d0240024020020d002004102721030c010b200128020020022004102821030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a000020002d0001210502400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d0d20024101742204200320032004491b22044100480d0d0240024020020d002004102721030c010b200128020020022004102821030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20053a0000200041086a2802002000410c6a280200200110c702200041146a280200200041186a280200200110c702200041206a280200200041246a280200200110c70220002d0002220041044b0d000240024002400240024020000e050001020304000b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d1120004101742203200220022003491b22034100480d110240024020000d002003102721020c010b200128020020002003102821020b2002450d0c20012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41003a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d1020004101742203200220022003491b22034100480d100240024020000d002003102721020c010b200128020020002003102821020b2002450d0c20012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41013a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d0f20004101742203200220022003491b22034100480d0f0240024020000d002003102721020c010b200128020020002003102821020b2002450d0c20012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41023a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d0e20004101742203200220022003491b22034100480d0e0240024020000d002003102721020c010b200128020020002003102821020b2002450d0c20012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41033a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d0d20004101742203200220022003491b22034100480d0d0240024020000d002003102721020c010b200128020020002003102821020b2002450d0c20012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41043a00000b0f0b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20044101102a000b20034101102a000b20034101102a000b20034101102a000b20034101102a000b20034101102a000b102b000bd50101027f200028020421020240024020002802004101460d00200041086a2802002200200110c6022000450d01200041186c2103200241146a21000340200041706a280200200041746a280200200110c7022000417c6a2802002000280200200110c702200041186a2100200341686a22030d000c020b0b2000410c6a2802002200200110c6022000450d00200041186c2103200241146a21000340200041706a280200200041746a280200200110c7022000417c6a2802002000280200200110c702200041186a2100200341686a22030d000b0b0bc806010a7f230041106b22022400200028020421030240024002400240024020002802004101460d00200041086a2802002200200110c6022000450d01200041d8006c2104410021050340200320056a220041046a280200200041086a280200200110c702200041d4006a2d0000210602400240200141046a2207280200200141086a22082802002209460d002001280200210a0c010b200941016a220a2009490d062009410174220b200a200a200b491b220b4100480d060240024020090d00200b1027210a0c010b20012802002009200b1028210a0b200a450d042001200a3602002007200b360200200828020021090b2008200941016a360200200a20096a20063a00002000410c6a200110ae0402400240200041346a2802004101460d002002200041386a2802002000413c6a28020028020c110000200228020022092002280208200110c7022002280204450d01200910290c010b200041386a280200200041c0006a280200200110c7020b200041c8006a2802002003200541d00041cc00200041c4006a2802004101461b6a6a280200200110ad042004200541d8006a2205470d000c020b0b2000410c6a2802002200200110c6022000450d00200041d8006c2104410021050340200320056a220041046a280200200041086a280200200110c702200041d4006a2d0000210602400240200141046a2207280200200141086a22082802002209460d002001280200210a0c010b200941016a220a2009490d052009410174220b200a200a200b491b220b4100480d050240024020090d00200b1027210a0c010b20012802002009200b1028210a0b200a450d042001200a3602002007200b360200200828020021090b2008200941016a360200200a20096a20063a00002000410c6a200110ae0402400240200041346a2802004101460d002002200041386a2802002000413c6a28020028020c110000200228020022092002280208200110c7022002280204450d01200910290c010b200041386a280200200041c0006a280200200110c7020b200041c8006a2802002003200541d00041cc00200041c4006a2802004101461b6a6a280200200110ad042004200541d8006a2205470d000b0b200241106a24000f0b200b4101102a000b200b4101102a000b102b000b0600200010230b0600200010240b2801017f0240200210232203450d002003200020022001200120024b1b10ce041a200010240b20030b1c01017f0240200010232201450d0020014100200010cd041a0b20010bb10101037f0240024002400240200028020022002802042203200028020822046b2002490d00200028020021030c010b200420026a22052004490d0220034101742204200520052004491b22044100480d020240024020030d002004102721030c010b200028020020032004102821030b2003450d012000200436020420002003360200200028020821040b2000200420026a360208200320046a2001200210ce041a41000f0b20044101102a000b102b000ba70401047f230041106b220224002000280200210002400240024002400240024002402001418001490d002002410036020c2001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c040b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c030b0240200028020822032000280204470d00200341016a22042003490d0620034101742205200420042005491b22044100480d060240024020030d002004102721030c010b200028020020032004102821030b2003450d022000200436020420002003360200200028020821030b200028020020036a20013a00002000200028020841016a3602080c030b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b20044101102a000b0240024020002802042204200028020822036b2001490d00200028020021040c010b200320016a22052003490d0320044101742203200520052003491b22034100480d030240024020040d002003102721040c010b200028020020042003102821040b2004450d022000200336020420002004360200200028020821030b2000200320016a360208200420036a2002410c6a200110ce041a0b200241106a240041000f0b20034101102a000b102b000b6401017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a4180d3c500200241086a1091042101200241206a240020010b0c0042ebbe8cdadd9294ae070b5401017f024002402001418080c400460d0041012104200028021820012000411c6a2802002802101104000d010b024020020d0041000f0b2000280218200220032000411c6a28020028020c11050021040b20040bcd0801067f230041f0006b220424002004200336020c20042002360208410121052001210602402001418102490d00410020016b2107418002210803400240200820014f0d00200020086a2c000041bf7f4c0d0041002105200821060c020b2008417f6a21064100210520084101460d01200720086a21092006210820094101470d000b0b200420063602142004200036021020044100410520051b36021c200441b8d6c50041ead9c50020051b3602180240024002400240200220014b22080d00200320014b0d00200220034b0d01024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b200420023602202002450d0220022001460d02200141016a210903400240200220014f0d00200020026a2c000041404e0d040b2002417f6a210820024101460d0420092002462106200821022006450d000c040b0b20042002200320081b360228200441306a41146a4103360200200441c8006a41146a4102360200200441d4006a410236020020044203370234200441f0d9c5003602302004410136024c2004200441c8006a3602402004200441186a3602582004200441106a3602502004200441286a360248200441306a4188dac5001057000b200441e4006a4102360200200441c8006a41146a4102360200200441d4006a4101360200200441306a41146a41043602002004420437023420044198dac5003602302004410136024c2004200441c8006a3602402004200441186a3602602004200441106a36025820042004410c6a3602502004200441086a360248200441306a41b8dac5001057000b200221080b024020082001460d00410121060240024002400240200020086a22092c00002202417f4a0d0041002105200020016a220621010240200941016a2006460d00200941026a210120092d0001413f7121050b2002411f712109200241ff017141df014b0d01200520094106747221010c020b2004200241ff0171360224200441286a21020c020b4100210020062107024020012006460d00200141016a210720012d0000413f7121000b200020054106747221010240200241ff017141f0014f0d0020012009410c747221010c010b41002102024020072006460d0020072d0000413f7121020b20014106742009411274418080f00071722002722201418080c400460d020b2004200136022441012106200441286a21022001418001490d00410221062001418010490d0041034104200141808004491b21060b200420083602282004200620086a36022c200441306a41146a4105360200200441ec006a4102360200200441e4006a4102360200200441c8006a41146a412b360200200441d4006a412c36020020044205370234200441e0dac500360230200420023602582004410136024c2004200441c8006a3602402004200441186a3602682004200441106a3602602004200441246a3602502004200441206a360248200441306a4188dbc5001057000b41c8dac5001058000b7f01037f230041206b2202240002402000280200200110be040d002001411c6a2802002103200128021821042002411c6a4100360200200241b8d6c5003602182002420137020c200241f0dbc50036020820042003200241086a1091040d002000280204200110be042101200241206a240020010f0b200241206a240041010bf00a03037f017e047f410121020240200128021841272001411c6a2802002802101104000d004102210302400240024002402000280200220241776a2200411e4d0d00200241dc00470d010c020b41f400210402400240024020000e1f05010303000303030303030303030303030303030303030303040303030304050b41f20021040c010b41ee0021040b0c020b02400240200210bd04450d00200241017267410276410773ad4280808080d0008421050c010b024002400240200241808004490d000240024002402002418080084f0d0020024180fe0371410876210641e1edc500210041002107200241ff017121040340200041026a2108200720002d000122036a2109024020002d000022002006460d00200020064b0d062009210720082100200841a7eec500470d010c060b20092007490d02200941a6014b0d03200741a7eec5006a2100024003402003450d012003417f6a210320002d00002107200041016a210020072004470d000c080b0b2009210720082100200841a7eec500470d000c050b0b200241ef83384b0d04200241e28b746a41e28d2c490d042002419fa8746a419f18490d04200241dee2746a410e490d04200241feffff0071419ef00a460d04200241a9b2756a4129490d04200241cb91756a410a4d0d0441012103200221040c070b20072009103e000b200941a601107f000b20024180fe0371410876210641b0e8c500210041002107200241ff01712104024002400340200041026a2108200720002d000122036a2109024020002d000022002006460d00200020064b0d03200921072008210020084182e9c500470d010c030b024020092007490d00200941a5024b0d0220074182e9c5006a2100024003402003450d012003417f6a210320002d00002107200041016a210020072004470d000c070b0b200921072008210020084182e9c500470d010c030b0b20072009103e000b200941a502107f000b200241ffff0371210741a7ebc50021034101210402400340200341016a21090240024020032d0000220041187441187522084100480d00200921030c010b200941e1edc500460d02200841ff007141087420032d0001722100200341026a21030b0240200720006b22074100480d0020044101732104200341e1edc500470d010b0b4101210320044101710d040c020b41c8dac5001058000b200241ffff0371210741cdefc50021034101210402400340200341016a21090240024020032d0000220041187441187522084100480d00200921030c010b200941e5f2c500460d02200841ff007141087420032d0001722100200341026a21030b0240200720006b22074100480d0020044101732104200341e5f2c500470d010b0b4101210320044101710d030c010b41c8dac5001058000b200241017267410276410773ad4280808080d0008421050b41032103200221040c010b200221040b03402003210741dc0021004101210241012103024002400240024020070e0401020300010b024002400240024002402005422088a741ff01710e06050403020100050b200542ffffffff8f60834280808080c000842105410321030c060b200542ffffffff8f608342808080803084210541f5002100410321030c050b200542ffffffff8f608342808080802084210541fb002100410321030c040b20042005a72207410274411c7176410f712203413072200341d7006a2003410a491b210002402007450d002005427f7c42ffffffff0f83200542808080807083842105410321030c040b200542ffffffff8f6083428080808010842105410321030c030b200542ffffffff8f6083210541fd002100410321030c020b20012802184127200128021c2802101104000f0b41002103200421000b20012802182000200128021c280210110400450d000b0b20020b950201017f024002402000418010490d00024002400240024002400240200041808004490d002000410c7641706a2201418002490d014188f3c50020014180021037000b200041067641606a220141df074b0d01200141d0dec5006a2d0000220141c9004b0d02200141037441e0f3c5006a21010c060b200141b0e6c5006a2d00004106742000410676413f7172220141ff034b0d02200141b0f8c5006a2d0000220141394b0d03200141037441b0fcc5006a21010c050b41e8f2c500200141e0071037000b41f8f2c500200141ca001037000b4198f3c50020014180041037000b41a8f3c5002001413a1037000b200041037641f8ffffff017141b8dcc5006a21010b200129030042012000413f71ad86834200520ba40201037f23004180016b2202240002400240024002400240200128020022034110710d0020034120710d012000ad4101200110aa0121000c020b410021030340200220036a41ff006a2000410f712204413072200441d7006a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141e8d9c5004102200220036a4180016a410020036b10ab0121000c010b410021030340200220036a41ff006a2000410f712204413072200441376a2004410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d022001410141e8d9c5004102200220036a4180016a410020036b10ab0121000b20024180016a240020000f0b2000418001103e000b2000418001103e000b0e0020003502004101200110aa010b1c002001280218418181c600410b2001411c6a28020028020c1105000b1c002001280218418c81c600410e2001411c6a28020028020c1105000b140020002802002001200028020428020c1104000bc30501077f410021040240024020024103712205450d00410420056b2205450d00200220032005200520034b1b22046a210641002105200141ff017121072004210820022109024003400240200620096b41034b0d0041002107200141ff0171210603402008450d04200920076a210a2008417f6a2108200741016a2107200a2d0000220a2006470d000b2005200a200141ff01714641016a4101716a20076a417f6a21050c020b200520092d0000220a2007476a2105200a2007460d012005200941016a2d0000220a2007476a2105200a2007460d012005200941026a2d0000220a2007476a2105200a2007460d012005200941036a2d0000220a2007476a21052008417c6a2108200941046a2109200a2007470d000b0b410121090c010b200141ff017121070240024020034108490d002004200341786a220a4b0d00200741818284086c210502400340200220046a220941046a2802002005732208417f73200841fffdfb776a7120092802002005732209417f73200941fffdfb776a7172418081828478710d01200441086a2204200a4d0d000b0b200420034b0d010b200220046a2109200220036a2102200320046b2108410021050240024003400240200220096b41034b0d0041002107200141ff0171210203402008450d04200920076a210a2008417f6a2108200741016a2107200a2d0000220a2002470d000b200a200141ff01714641016a41017120056a20076a417f6a21050c020b200520092d0000220a2007476a2105200a2007460d012005200941016a2d0000220a2007476a2105200a2007460d012005200941026a2d0000220a2007476a2105200a2007460d012005200941036a2d0000220a2007476a21052008417c6a2108200941046a2109200a2007470d000b0b41012109200520046a21050c020b41002109200520076a20046a21050c010b20042003103e000b20002005360204200020093602000b2701017f2000280200220128020020012802042000280204280200200028020828020010ba04000ba60401077f230041306b220324000240024020020d00410021040c010b200341286a210502400240024002400340024020002802082d0000450d00200028020041ed81c6004104200028020428020c1105000d050b2003410a3602282003428a808080103703202003200236021c200341003602182003200236021420032001360210200341086a410a2001200210c304024002400240024020032802084101470d00200328020c210403402003200420032802186a41016a2204360218024002402004200328022422064f0d00200328021421070c010b200328021422072004490d00200641054f0d072003280210200420066b22086a22092005460d0420092005200610d004450d040b200328021c22092004490d0220072009490d0220032006200341106a6a41176a2d0000200328021020046a200920046b10c3042003280204210420032802004101460d000b0b2003200328021c3602180b200028020841003a0000200221040c010b200028020841013a0000200841016a21040b2000280204210920002802002106024020044520022004467222070d00200220044d0d03200120046a2c000041bf7f4c0d030b200620012004200928020c1105000d04024020070d00200220044d0d04200120046a2c000041bf7f4c0d040b200120046a2101200220046b22020d000b410021040c040b20064104107f000b200120024100200410ba04000b200120022004200210ba04000b410121040b200341306a240020040b02000bfa0101017f230041106b220224002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a200110c5042101200241106a240020010b6101017f230041206b2202240020022000360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a419882c600200241086a1091042101200241206a240020010b0e0020002802002001200210c5040b810201017f230041106b22022400200028020021002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a200110c5042101200241106a240020010b6401017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a419882c600200241086a1091042101200241206a240020010b1c00200128021841bb82c60041052001411c6a28020028020c1105000b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f0240024020012000490d002002450d01200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000c020b0b2002450d002001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000b0b20000b4a01037f4100210302402002450d000240034020002d0000220420012d00002205470d01200141016a2101200041016a21002002417f6a2202450d020c000b0b200420056b21030b20030b5701017e02400240200341c000710d002003450d012001410020036b413f71ad8820022003413f71ad220486842102200120048621010c010b20012003413f71ad862102420021010b20002001370300200020023703080b5701017e02400240200341c000710d002003450d0120012003413f71ad2204882002410020036b413f71ad86842101200220048821020c010b20022003413f71ad882101420021020b20002001370300200020023703080b7501027e200020034220882205200142208822067e200320027e7c200420017e7c200342ffffffff0f832203200142ffffffff0f8322017e2204422088200320067e7c22034220887c200342ffffffff0f83200520017e7c22034220887c37030820002003422086200442ffffffff0f83843703000b3e01017f230041106b2205240020052001200220032004410010d604200529030021012000200541086a29030037030820002001370300200541106a24000b4c01017f230041206b22052400200542003703182005420037031020052001200220032004200541106a10d604200529031021012000200529031837030820002001370300200541206a24000be20502037f067e230041306b2206240002400240024002400240024002400240024002402002500d002003500d012004500d02200479a7200279a76b2207413f4b0d0341ff0020076b2108200741016a21070c080b02402004500d0020050d040c060b024002402005450d0020034200510d0620054200370308200520012003823703000c010b20034200510d050b200120038021010c060b2004500d030240024002402001500d0020047b4201510d01200479a7200279a76b2207413e4b0d0241ff0020076b2108200741016a21070c090b02402005450d0020054200370300200520022004823703080b200220048021010c070b02402005450d002005200137030020052004427f7c2002833703080b200220047a423f838821010c060b2005450d040c020b024020037b4201510d0041bf7f200379a7200279a76b22076b2108200741c1006a21070c060b02402005450d002005420037030820052003427f7c2001833703000b20034201510d06200641206a2001200220037aa710d204200641286a2903002102200629032021010c060b2005450d020b2005200137030020052002370308420021010c020b00000b420021010b420021020c010b200620012002200841ff007110d104200641106a20012002200741ff007110d204200641086a2903002102200641106a41086a2903002109200629030021012006290310210a0240024020070d004200210b4200210c0c010b4200210c4200210d03402009420186200a423f8884220b200b427f8520047c200a4201862002423f8884220a427f85220b20037c200b54ad7c423f87220b2004837d200a200b200383220e54ad7d2109200a200e7d210a420020024201862001423f8884842102200d2001420186842101200b420183220b210d2007417f6a22070d000b0b02402005450d002005200a370300200520093703080b200c20024201862001423f8884842102200b20014201868421010b2000200137030020002002370308200641306a24000b0bdb82060200418080c0000bc08206180010001d0000008858110013000000db03000009000000617373657274696f6e206661696c65643a20696e646578203c206c656e0000005000100043000000fb0a00003000000000000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962616c6c6f632f7665632e7273005000100043000000070b00002c0000004469676573744974656d206e6f7420657175616c3501100036000000326811005b000000fc0100000500000000000000000000000000000000000000f80010003d000000326811005b0000000302000005000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656450726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b20716564003501100036000000326811005b000000c801000005000000000000000000000000000000326811005b000000cf0100000500000076616c69646174696f6e206572726f72c80110007c00000044021000490000007a00000006000000657865632e7072656661625f6d6f64756c652e696e697469616c2063616e27742062652067726561746572207468616e20657865632e7072656661625f6d6f64756c652e6d6178696d756d3b0a09090909090974687573204d656d6f72793a3a6e6577206d757374206e6f74206661696c3b0a0909090909097165642f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f7761736d2f6d6f642e727300000000000000140310000a000000000000000010110002000000000000000000000020031000010000000000000000000000280310000d0000000000000034e81000010000000000000000000000380310000100000000000000000000003c8310000800000000000000400310000400000000000000000000006003100001000000000000004e65774163636f756e740000ab0310001b0000005265617065644163636f756e740000009403100017000000611011000900000061101100090000006a101100070000006a10110007000000680310002c000000205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c75652c2066656573292e20416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e76657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c75656163636f756e74206c6971756964697479207265737472696374696f6e732070726576656e74207769746864726177616c62656e6566696369617279206163636f756e74206d757374207072652d6578697374746f6f2066657720667265652066756e647320696e206163636f756e747061796d656e7420776f756c64206b696c6c206163636f756e74000000000000a40410001100000000000000b8041000020000000000000000000000c80410000100000000000000486561727462656174526563656976656400000060e810000b000000160510000b000000d0041000460000002041206e6577206865617274626561742077617320726563656976656420617420746869732060426c6f636b4e756d626572602066726f6d2060417574686f72697479496460417574686f72697479496454696d657374616d702055706461746542616c616e63657320546f74616c49737375616e636554696d657374616d7020526563656e7448696e74737405100031000000a50510004b0000007e0000000400000046696e616c2068696e74206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b2f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f66696e616c6974792d747261636b65722f7372632f6c69622e72730806100023000000a50510004b0000007f0000000400000046696e616c697a6564206865696768742061626f766520626c6f636b206e756d62657242616c616e636573204672656542616c616e636542616c616e63657320526573657276656442616c616e636542616c616e636573204c6f636b730000002d00000008000000040000002e0000004765747320616e64206465636f6465732066696e616c206e756d62657220696e686572656e74206461746142616c616e6365732056657374696e6700000000000c07100008000000000000001407100002000000000000000000000044071000170000000000000000000000fc0710000b0000000000000008081000030000000000000000000000500810000d000000000000007472616e7366657200000000b58f10000400000000000000b01d11002300000000000000ee25110005000000000000004d0a1000130000006c0a100036000000386b110000000000a20a100042000000e40a1000480000002c0b100045000000710b10002d000000386b1100000000009e0b100046000000386b1100000000007e1b11000b000000e40b10004c000000300c100033000000630c10005a000000386b110000000000bd0c100013000000386b110000000000d00c100054000000240d10004b0000006f0d100035000000a40d100037000000db0d100056000000386b1100000000001f1c11000c0000007365745f62616c616e63650000000000db2a10000300000000000000b01d11002300000000000000450a100008000000000000004d0a10001300000000000000600a10000c000000000000004d0a100013000000b808100025000000386b110000000000dd0810004800000025091000420000006709100046000000ad0910003a000000386b110000000000e70910002d000000386b1100000000007e1b11000b000000891b110020000000140a1000310000001f1c11000c00000020536574207468652062616c616e636573206f66206120676976656e206163636f756e742e20546869732077696c6c20616c74657220604672656542616c616e63656020616e642060526573657276656442616c616e63656020696e2073746f726167652e2069742077696c6c20616c736f2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d202860546f74616c49737375616e636560292e20496620746865206e65772066726565206f722072657365727665642062616c616e63652069732062656c6f7720746865206578697374656e7469616c206465706f7369742c2069742077696c6c20726573657420746865206163636f756e74206e6f6e636520286073797374656d3a3a4163636f756e744e6f6e636560292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c2069732060726f6f74602e202d20436f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e64207772697465732e6e65775f66726565436f6d706163743c543a3a42616c616e63653e6e65775f7265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572206163636f756e742e20607472616e73666572602077696c6c207365742074686520604672656542616c616e636560206f66207468652073656e64657220616e642072656365697665722e2049742077696c6c2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d2062792074686520605472616e73666572466565602e204966207468652073656e6465722773206163636f756e742069732062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c74206f6620746865207472616e736665722c20746865206163636f756e742077696c6c206265207265617065642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605369676e65646020627920746865207472616e736163746f722e202d20446570656e64656e74206f6e20617267756d656e747320627574206e6f7420637269746963616c2c20676976656e2070726f70657220696d706c656d656e746174696f6e7320666f72202020696e70757420636f6e6669672074797065732e205365652072656c617465642066756e6374696f6e732062656c6f772e202d20497420636f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e642077726974657320696e7465726e616c6c7920616e64206e6f20636f6d706c657820636f6d7075746174696f6e2e2052656c617465642066756e6374696f6e733a2020202d2060656e737572655f63616e5f77697468647261776020697320616c776179732063616c6c656420696e7465726e616c6c792062757420686173206120626f756e64656420636f6d706c65786974792e2020202d205472616e7366657272696e672062616c616e63657320746f206163636f756e7473207468617420646964206e6f74206578697374206265666f72652077696c6c20636175736520202020202060543a3a4f6e4e65774163636f756e743a3a6f6e5f6e65775f6163636f756e746020746f2062652063616c6c65642e2020202d2052656d6f76696e6720656e6f7567682066756e64732066726f6d20616e206163636f756e742077696c6c2074726967676572202020202060543a3a4475737452656d6f76616c3a3a6f6e5f756e62616c616e6365646020616e642060543a3a4f6e4672656542616c616e63655a65726f3a3a6f6e5f667265655f62616c616e63655f7a65726f602e00000000000000ec0f10000d0000000000000000000000f90f10000a0000000000000000000000000000000000000000000000000000000000000040811100bc101000000000000000000004101000010000000000000001000000000000000c101000070000000101000000000000423111000c00000000000000131010002b0000000000000000000000000000000000000040811100001b100000000000000000004010100001000000000000000000000000000000481010000b0000000101000000000000423111000c00000000000000f90f10000a0000000000000000000000000000000000000040811100bc1010000000000000000000541010000b000000000000000100000000000000ac1010000f0000000101000000000000423111000c00000000000000f90f10000a0000000000000000000000000000000000000040811100bc1010000000000000000000cc1010000b00000000000000010000000000000024111000050000000101000000000000423111000c00000000000000291110002c000000000000000000000000000000000000004081110058111000000000000000000068111000010000000000000001000000546f74616c49737375616e6365543a3a42616c616e636500991610002600000056657374696e6756657374696e675363686564756c653c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e000063161000360000004672656542616c616e636500e913100027000000386b1100000000001014100050000000601410005d000000bd14100055000000121510004f0000006115100051000000b215100015000000386b110000000000c7151000570000001e16100045000000526573657276656442616c616e6365002f0000000000000001000000300000009e1110005d000000fb11100027000000386b110000000000221210005b0000007d12100049000000386b110000000000c61210005d000000231310002d000000386b1100000000005013100053000000a3131000460000004c6f636b735665633c42616c616e63654c6f636b3c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e3e0000002f000000000000000100000031000000701110002e00000020416e79206c6971756964697479206c6f636b73206f6e20736f6d65206163636f756e742062616c616e6365732e2054686520616d6f756e74206f66207468652062616c616e6365206f66206120676976656e206163636f756e7420746861742069732065787465726e616c6c792072657365727665643b20746869732063616e207374696c6c2067657420736c61736865642c20627574206765747320736c6173686564206c617374206f6620616c6c2e20546869732062616c616e63652069732061202772657365727665272062616c616e63652074686174206f746865722073756273797374656d732075736520696e206f7264657220746f2073657420617369646520746f6b656e73207468617420617265207374696c6c20276f776e65642720627920746865206163636f756e7420686f6c6465722c20627574207768696368206172652073757370656e6461626c652e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e2074686973202772657365727665206163636f756e74272069732064656c657465643a207370656369666963616c6c792c2060526573657276656442616c616e6365602e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c6574656420696620604672656542616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e2920546865202766726565272062616c616e6365206f66206120676976656e206163636f756e742e205468697320697320746865206f6e6c792062616c616e63652074686174206d61747465727320696e207465726d73206f66206d6f7374206f7065726174696f6e73206f6e20746f6b656e732e20497420616c6f6e65206973207573656420746f2064657465726d696e65207468652062616c616e6365207768656e20696e2074686520636f6e747261637420657865637574696f6e20656e7669726f6e6d656e742e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e20746865202763757272656e74206163636f756e74272069732064656c657465643a207370656369666963616c6c7920604672656542616c616e6365602e20467572746865722c2074686520604f6e4672656542616c616e63655a65726f602063616c6c6261636b20697320696e766f6b65642c20676976696e672061206368616e636520746f2065787465726e616c206d6f64756c657320746f20636c65616e2075702064617461206173736f6369617465642077697468207468652064656c65746564206163636f756e742e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c657465642069662060526573657276656442616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e20496e666f726d6174696f6e20726567617264696e67207468652076657374696e67206f66206120676976656e206163636f756e742e2054686520746f74616c20756e6974732069737375656420696e207468652073797374656d2e0000000000d81710001200000000000000f90f10000a0000000000000040811100ec1710000000000000000000fc171000010000000000000000000000949f10000b00000000000000f90f10000a0000000000000040811100041810000000000000000000a09f1000010000000000000000000000a89f10000b00000000000000f90f10000a0000000000000040811100041810000000000000000000b49f1000010000000000000000000000bc9f10001200000000000000f90f10000a0000000000000040811100041810000000000000000000d09f1000010000000000000000000000d89f10001200000000000000f90f10000a0000000000000040811100141810000000000000000000fc9f100001000000000000004578697374656e7469616c4465706f73697400002f00000000000000010000003200000024181000350000002f0000000000000001000000330000002f00000000000000010000003400000020546865206d696e696d756d20616d6f756e7420726571756972656420746f206b65657020616e206163636f756e74206f70656e2e496d4f6e6c696e6520476f737369704174496d4f6e6c696e652052656365697665644865617274626561747373726d6c2f696d2d6f6e6c696e652d776f726b65722d737461747573576974686472617720686173206265656e20636865636b65642061626f76653b0a090909647565735f6c696d69746564203c2072656e745f627564676574203c2062616c616e6365202d2073756273697374656e6365203c2062616c616e6365202d206578697374656e7469616c5f6465706f7369743b0a09090971656400000000004c191000090000000000000058191000020000000000000000000000386b11000000000000000000686561727462656174000000000000004c1910000900000000000000881910002900000000000000b11910000a00000000000000d5ca1000070000004865617274626561743c543a3a426c6f636b4e756d6265722c20543a3a417574686f7269747949643e5f7369676e61747572650000000000c41a10000800000000000000000000001bf610000e0000000000000000000000000000000000000000000000000000000000000040811100cc1a10000000000000000000386b110000000000000000000100000000000000dc1a10000f0000000000000000000000eb1a1000150000000000000000000000000000000000000000000000000000000000000040811100001b10000000000000000000386b110000000000000000000000000000000000101b1000120000000201010000000000eb1a10001500000000000000221b10000e00000000000000d5ca1000070000000000000040811100301b10000000000000000000386b1100000000000000000001000000476f7373697041742f0000000000000001000000350000004c6173744e6577457261537461727473657373696f6e3a3a53657373696f6e496e6465782f000000000000000100000036000000526563656976656448656172746265617473543a3a417574686f7269747949642f00000000000000010000003100000000000000a83b11000e00000000000000eb1a1000150000000000000040811100781b10000000000000000000c83b110001000000000000002f00000000000000010000003700000054696d657374616d70204f72646572656448696e747354696d657374616d70204d656469616e616c77617973206174206c65617374206f6e6520726563656e742073616d706c653b20716564726563656e7420616e64206f72646572656420636f6e7461696e207468652073616d65206974656d733b20716564000038000000040000000400000039000000881c100043000000a50510004b000000b700000004000000401c100048000000820a00000a000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e72737072756e696e672064696374617465642062792077696e646f775f73697a6520776869636820697320616c776179732073617475726174656420617420313b207165646e6f7420656e6f75676820667265652066756e6473000000000c1d10000a00000000000000181d1000010000000000000000000000301d1000020000000000000066696e616c5f68696e74000000000000c5351000040000000000000073f3100017000000401d10003d0000007d1d10001b0000002048696e7420746861742074686520617574686f72206f66207468697320626c6f636b207468696e6b732074686520626573742066696e616c697a656420626c6f636b2069732074686520676976656e206e756d6265722e00000000081e10000a000000000000001bf610000e0000000000000040811100141e10000000000000000000241e10000100000000000000000000002c1e10000d000000000000001bf610000e00000000000000408111003c1e100000000000000000004c1e1000010000000000000057696e646f7753697a6500002f00000000000000010000003a0000009b1e1000460000005265706f72744c6174656e63790000002f00000000000000010000003b000000541e100047000000205468652064656c617920616674657220776869636820706f696e74207468696e6773206265636f6d6520737573706963696f75732e2044656661756c7420697320313030302e20546865206e756d626572206f6620726563656e742073616d706c657320746f206b6565702066726f6d207468697320636861696e2e2044656661756c74206973203130312e0000000a68110028000000fc1e1000430000008c010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f62616c616e6365732f7372632f6c69622e727300fc1e1000430000008c01000001000000676f74206f766572666c6f7720616674657220616464696e6720612066656520746f2076616c756500000000282010000b0000000000000018e81000020000000000000000000000342010000100000000000000000000003c201000100000000000000034e810000100000000000000000000004c201000010000000000000000000000542010000c00000000000000a483100001000000000000000000000060201000010000000000000000000000682010000e0000000000000078201000020000000000000000000000882010000100000000000000566f746572526561706564002621100015000000426164526561706572536c6173686564172110000f00000054616c6c7953746172746564e22010003500000054616c6c7946696e616c697a6564000090e810000e00000090e810000e000000902010005200000020412074616c6c792028666f7220617070726f76616c20766f746573206f662073656174287329292068617320656e646564202877697468206f6e65206f72206d6f7265206e6577206d656d62657273292e20412074616c6c792028666f7220617070726f76616c20766f746573206f662073656174287329292068617320737461727465642e20736c6173686564207265617065722072656170656420766f7465722c20726561706572436f756e63696c205265676973746572496e666f4f66436f756e63696c204d656d62657273436f756e63696c204e65787446696e616c697a657022100048000000820a00000a000000436f756e63696c205465726d4475726174696f6e436f756e63696c2050726573656e746174696f6e4475726174696f6e436f756e63696c204c6561646572626f617264007022100048000000880a00000e000000436f756e63696c2043616e64696461746573436f756e63696c20566f746572496e666f4f6647757275206d656469746174696f6e66696e616c697a652063616e206f6e6c792062652063616c6c656420616674657220612074616c6c7920697320737461727465642e436f756e63696c20417070726f76616c734f66436f756e63696c20566f7465727300000000000000000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000702410000d0000000000000080241000030000000000000000000000c8241000180000000000000000000000882510001300000000000000802410000300000000000000000000009c251000060000000000000000000000cc2510001300000000000000e0251000040000000000000000000000402610000c0000000000000000000000a02610000d00000000000000b0261000010000000000000000000000c82610000a000000000000000000000018271000100000000000000028271000010000000000000000000000402710000d0000000000000000000000a82710000e00000000000000b827100003000000000000000000000000281000080000000000000000000000402810001100000000000000542810000100000000000000000000006c281000030000000000000000000000842810000d0000000000000094281000010000000000000000000000ac281000040000000000000000000000cc2810001900000000000000e828100001000000000000000000000000291000020000000000000000000000102910001100000000000000e82810000100000000000000000000002429100002000000000000007365745f617070726f76616c7300000000000000b73510000500000000000000bc3510000900000000000000b0a910000500000000000000a02c10001200000000000000c53510000400000000000000c93510000800000085311000580000003931100010000000386b110000000000dd311000300000000d3210004a000000386b11000000000057321000350000008c32100051000000dd3210002c00000009331000530000005c33100062000000be331000600000001e3410001d0000003b341000570000009234100035000000386b110000000000c73410006b000000323510001d000000386b1100000000007e1b11000b0000002e271100080000004f3510002700000076351000410000001f1c11000c00000070726f78795f7365745f617070726f76616c7300d4301000650000003931100010000000386b1100000000007e1b11000b000000493110003c0000001f1c11000c000000726561705f696e6163746976655f766f7465720000000000ab3010000e000000000000004e1c11000c00000000000000db2a10000300000000000000b01d11002300000000000000b930100009000000000000004e1c11000c00000000000000c23010001200000000000000a02c1000120000004a2f100058000000a22f10005c000000fe2f100028000000386b1100000000002630100045000000386b1100000000006b30100040000000386b1100000000007e1b11000b0000002e27110008000000232f1000270000001f1c11000c000000726574726163745f766f74657200000000000000b0a9100005000000000000004e1c11000c000000472e10004b000000386b110000000000922e100042000000386b110000000000d42e10004f000000386b1100000000007e1b11000b0000002e27110008000000232f1000270000001f1c11000c0000007375626d69745f63616e64696461637900000000432e100004000000000000004e1c11000c000000b22c10001e000000386b110000000000d02c100044000000386b110000000000142d1000480000005c2d100051000000ad2d10004c000000f92d10001e000000386b1100000000007e1b11000b000000172e1000180000002f2e1000140000001f1c11000c00000070726573656e745f77696e6e6572000000000000922c10000900000000000000b01d110023000000000000009b2c10000500000000000000f32511001500000000000000b0a910000500000000000000a02c1000120000009e2b100059000000f72b1000680000005f2c10001e000000386b1100000000007e1b11000b0000007d2c1000150000000e7c1000110000001f1c11000c0000007365745f646573697265645f736561747300000000000000f629100005000000000000004e1c11000c000000de2a100059000000372b100052000000892b10001500000072656d6f76655f6d656d62657200000000000000db2a10000300000000000000b01d110023000000fb29100048000000386b110000000000432a1000480000008b2a1000500000007365745f70726573656e746174696f6e5f6475726174696f6e00000000000000f6291000050000000000000073f3100017000000a02910005600000088291000180000007365745f7465726d5f6475726174696f6e0000003429100054000000882910001800000020536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e74206120766f7465206265696e672070726573656e74656420666f722c2077696c6c20696e766f6b65206066696e616c697a655f766f7465602e20536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e746c79206120766f7465206265696e672070726573656e74656420666f722c2077696c6c636f756e742052656d6f7665206120706172746963756c6172206d656d6265722066726f6d20746865207365742e20546869732069732065666665637469766520696d6d6564696174656c792e204e6f74653a20412074616c6c792073686f756c642068617070656e20696e7374616e746c7920286966206e6f7420616c726561647920696e20612070726573656e746174696f6e20706572696f642920746f2066696c6c2074686520736561742069662072656d6f76616c206d65616e732074686174207468652064657369726564206d656d6265727320617265206e6f74206d65742e77686f20536574207468652064657369726564206d656d62657220636f756e743b206966206c6f776572207468616e207468652063757272656e7420636f756e742c207468656e2073656174732077696c6c206e6f7420626520757020656c656374696f6e207768656e2074686579206578706972652e204966206d6f72652c207468656e2061206e657720766f74652077696c6c2062652073746172746564206966206f6e65206973206e6f7420616c726561647920696e2070726f67726573732e20436c61696d207468617420607369676e656460206973206f6e65206f662074686520746f702053656c663a3a63617272795f636f756e742829202b2063757272656e745f766f746528292e312063616e646964617465732e204f6e6c7920776f726b73206966207468652060626c6f636b5f6e756d626572203e3d2063757272656e745f766f746528292e306020616e6420603c2063757272656e745f766f746528292e30202b2070726573656e746174696f6e5f6475726174696f6e28296020607369676e6564602073686f756c642068617665206174206c65617374202d204f28766f746572732920636f6d707574652e63616e646964617465746f74616c436f6d706163743c566f7465496e6465783e205375626d6974206f6e6573656c6620666f722063616e6469646163792e204163636f756e74206d757374206861766520656e6f756768207472616e736665727261626c652066756e647320696e20697420746f207061792074686520626f6e642e204e4f54453a20696620606f726967696e602068617320616c72656164792061737369676e656420617070726f76616c7320766961205b607365745f617070726f76616c73605d2c2069742077696c6c204e4f54206861766520616e7920757361626c652066756e647320746f20706173732063616e64696461637920626f6e6420616e64206d75737420666972737420726574726163742e204e6f746520746861742073657474696e6720617070726f76616c732077696c6c206c6f636b2074686520656e746972652062616c616e6365206f662074686520766f74657220756e74696c2072657472616374696f6e206f72206265696e67207265706f727465642e202d20496e646570656e64656e74206f6620696e7075742e202d205468726565204442206368616e6765732e736c6f742052656d6f7665206120766f7465722e20416c6c20766f746573206172652063616e63656c6c656420616e642074686520766f746572206465706f7369742069732072657475726e65642e2054686520696e646578206d7573742062652070726f7669646564206173206578706c61696e656420696e205b60766f7465725f6174605d2066756e6374696f6e2e20416c736f2072656d6f76657320746865206c6f636b206f6e207468652062616c616e6365206f662074686520766f7465722e20536565205b60646f5f7365745f617070726f76616c732829605d2e202d2054776f20666577657220444220656e74726965732c206f6e65204442206368616e67652e2052656d6f7665206120766f7465722e20466f72206974206e6f7420746f206265206120626f6e642d636f6e73756d696e67206e6f2d6f702c20616c6c20617070726f7665642063616e64696461746520696e6469636573206d757374206e6f772062652065697468657220756e72656769737465726564206f72207265676973746572656420746f20612063616e646964617465207468617420726567697374657265642074686520736c6f742061667465722074686520766f7465722067617665207468656972206c61737420617070726f76616c207365742e20426f746820696e6469636573206d7573742062652070726f7669646564206173206578706c61696e656420696e205b60766f7465725f6174605d2066756e6374696f6e2e204d61792062652063616c6c656420627920616e796f6e652e2052657475726e732074686520766f746572206465706f73697420746f20607369676e6564602e7265706f727465725f696e64657877686f5f696e646578617373756d65645f766f74655f696e646578205365742063616e64696461746520617070726f76616c732066726f6d20612070726f78792e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f74732061726520726567697374657265642e202d2053616d6520617320607365745f617070726f76616c73602077697468206f6e65206164646974696f6e616c2073746f7261676520726561642e205365742063616e64696461746520617070726f76616c732e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f7473204c6f636b732074686520746f74616c2062616c616e6365206f662063616c6c657220696e646566696e6974656c792e204f6e6c79205b60726574726163745f766f746572605d206f72205b60726561705f696e6163746976655f766f746572605d2063616e20756e6c6f636b207468652062616c616e63652e206068696e746020617267756d656e7420697320696e74657270726574656420646966666572656e746c79206261736564206f6e3a202d20696620606f726967696e602069732073657474696e6720617070726f76616c7320666f72207468652066697273742074696d653a2054686520696e6465782077696c6c20626520636865636b656420666f72206265696e6720612076616c6964205f686f6c655f20696e2074686520766f746572206c6973742e2020202d206966207468652068696e7420697320636f72726563746c7920706f696e74696e6720746f206120686f6c652c206e6f206665652069732064656475637465642066726f6d20606f726967696e602e2020202d204f74686572776973652c207468652063616c6c2077696c6c2073756363656564206275742074686520696e6465782069732069676e6f72656420616e642073696d706c792061207075736820746f20746865206c617374206368756e6b2020207769746820667265652073706163652068617070656e732e20496620746865206e65772070757368206361757365732061206e6577206368756e6b20746f20626520637265617465642c20612066656520696e646963617465642062792020205b60566f74696e67466565605d2069732064656475637465642e202d20696620606f726967696e6020697320616c7265616479206120766f7465723a2074686520696e646578205f5f6d7573745f5f2062652076616c696420616e6420706f696e7420746f2074686520636f727265637420706f736974696f6e206f662074686520606f726967696e6020696e207468652063757272656e7420766f74657273206c6973742e204e6f7465207468617420616e7920747261696c696e67206066616c73656020766f74657320696e2060766f746573602069732069676e6f7265643b20496e20617070726f76616c20766f74696e672c206e6f7420766f74696e6720666f7220612063616e64696461746520616e6420766f74696e672066616c73652c2061726520657175616c2e202d2054776f20657874726120444220656e74726965732c206f6e65204442206368616e67652e202d20417267756d656e742060766f74657360206973206c696d6974656420696e206c656e67746820746f206e756d626572206f662063616e646964617465732e766f7465735665633c626f6f6c3e68696e74536574496e64657800000000000000543b10001400000000000000000000001bf610000e00000000000000000000000000000000000000000000000000000000000000408111007c3b10000000000000000000683b100001000000000000000100000000000000703b10000c00000000000000000000001bf610000e00000000000000000000000000000000000000000000000000000000000000408111007c3b100000000000000000008c3b100001000000000000000100000000000000943b10000c0000000000000000000000061111000300000000000000000000000000000000000000000000000000000000000000408111001c4710000000000000000000a03b100001000000000000000100000000000000a0ad1000070000000000000000000000a83b10002300000000000000000000000000000000000000000000000000000000000000408111002c3d10000000000000000000cc3b100004000000000000000100000000000000ec3b1000090000000000000000000000f53b10000900000000000000000000000000000000000000000000000000000000000000408111001c4710000000000000000000003c100001000000000000000100000000000000083c10000b0000000101000000000000133c100018000000000000002b3c10001100000000000000000000000000000000000000408111002c3d100000000000000000003c3c100005000000000000000100000000000000643c10000e0000000101000000000000423111000c00000000000000723c1000100000000000000000000000000000000000000040811100f43d10000000000000000000843c100002000000000000000000000000000000943c10000b0000000101000000000000423111000c000000000000009f3c1000170000000000000000000000000000000000000040811100b83c10000000000000000000c83c100001000000000000000000000000000000d03c1000060000000101000000000000c93510000800000000000000d63c10001900000000000000000000000000000000000000408111002c3d10000000000000000000f03c100001000000000000000100000000000000f83c10000c0000000000000000000000c93510000800000000000000000000000000000000000000000000000000000000000000408111001c4710000000000000000000043d1000010000000000000001000000000000000c3d10000a0000000000000000000000c93510000800000000000000000000000000000000000000000000000000000000000000408111001c4710000000000000000000183d100001000000000000000100000000000000203d10000a0000000000000000000000b11a11001100000000000000000000000000000000000000000000000000000000000000408111002c3d100000000000000000003c3d100001000000000000000100000000000000443d10000e0000000000000000000000061111000300000000000000000000000000000000000000000000000000000000000000408111001c4710000000000000000000543d1000010000000000000001000000000000005c3d10000c0000000000000000000000683d1000280000000000000000000000000000000000000000000000000000000000000040811100903d10000000000000000000a03d100001000000000000000000000000000000a83d10000b0000000000000000000000b33d1000210000000000000000000000000000000000000000000000000000000000000040811100d43d10000000000000000000e43d10000200000000000000000000000000000010011100050000000101000000000000423111000c00000000000000423111000c0000000000000000000000000000000000000040811100f43d100000000000000000002801110002000000000000000000000050726573656e746174696f6e4475726174696f6e534310004f0000005465726d4475726174696f6e2f0000000000000001000000350000002d43100026000000446573697265645365617473f34210003a0000005665633c28543a3a4163636f756e7449642c20543a3a426c6f636b4e756d626572293e00cb4110005e000000294210005c0000008542100054000000d94210001a000000566f7465436f756e74566f7465496e64657800008441100047000000417070726f76616c734f6628543a3a4163636f756e7449642c20536574496e646578295665633c417070726f76616c466c61673e6f40100068000000386b110000000000d740100059000000386b11000000000030411000540000005265676973746572496e666f4f6628566f7465496e6465782c20753332290000fa3f10005f0000005940100016000000566f746572496e666f4f66566f746572496e666f3c42616c616e63654f663c543e3e00002f000000000000000100000036000000d93f100021000000566f746572735665633c4f7074696f6e3c543a3a4163636f756e7449643e3e00963f1000430000004e657874566f746572536574573f10003f000000566f746572436f756e7400003d3f10001a00000043616e6469646174657300002f000000000000000100000031000000213f10001c00000043616e646964617465436f756e740000fd3e1000240000004e65787446696e616c697a6528543a3a426c6f636b4e756d6265722c207533322c205665633c543a3a4163636f756e7449643e292f00000000000000010000003c000000b53e1000480000004c6561646572626f6172645665633c2842616c616e63654f663c543e2c20543a3a4163636f756e744964293e2f00000000000000010000003c000000043e1000670000006b3e10004a0000002f0000000000000001000000360000002047657420746865206c6561646572626f61726420696620776527726520696e207468652070726573656e746174696f6e2070686173652e2054686520666972737420656c656d656e742069732074686520776569676874206f66206561636820656e7472793b204974206d617920626520746865206469726563742073756d6d656420617070726f76616c207374616b65732c206f7220612077656967687465642076657273696f6e206f662069742e20546865206163636f756e747320686f6c64696e672074686520736561747320746861742077696c6c206265636f6d652066726565206f6e20746865206e6578742074616c6c792e2043757272656e74206e756d626572206f66206163746976652063616e64696461746573205468652070726573656e742063616e646964617465206c6973742e2043757272656e74206e756d626572206f6620566f746572732e20746865206e65787420667265652073657420746f2073746f7265206120766f74657220696e2e20546869732077696c6c206b6565702067726f77696e672e205468652070726573656e7420766f746572206c69737420286368756e6b656420616e6420636170706564206174205b60564f5445525f5345545f53495a45605d292e20426173696320696e666f726d6174696f6e2061626f7574206120766f7465722e2054686520766f746520696e64657820616e64206c69737420736c6f742074686174207468652063616e646964617465206077686f60207761732072656769737465726564206f7220604e6f6e6560206966207468657920617265206e6f742063757272656e746c7920726567697374657265642e2041206c697374206f6620766f74657320666f72206561636820766f7465722e2054686520766f746573206172652073746f726564206173206e756d657269632076616c75657320616e642070617273656420696e2061206269742d77697365206d616e6e65722e20496e206f7264657220746f2067657420612068756d616e2d7265616461626c6520726570726573656e746174696f6e2028605665633c626f6f6c3e60292c20757365205b60616c6c5f617070726f76616c735f6f66605d2e20467572746865726d6f72652c206561636820766563746f72206f66207363616c617273206973206368756e6b656420776974682074686520636170206f662060415050524f56414c5f5345545f53495a45602e2054686520746f74616c206e756d626572206f6620766f746520726f756e6473207468617420686176652068617070656e6564206f722061726520696e2070726f67726573732e205468652063757272656e74206d656d626572736869702e205768656e2074686572652773206120766f746520676f696e67206f6e2c20746869732073686f756c64207374696c6c206265207573656420666f7220657865637574697665206d6174746572732e2054686520626c6f636b206e756d62657220287365636f6e6420656c656d656e7420696e20746865207475706c65292069732074686520626c6f636b207468617420746865697220706f736974696f6e2069732061637469766520756e74696c202863616c63756c61746564206279207468652073756d206f662074686520626c6f636b206e756d626572207768656e20746865206d656d6265722077617320656c656374656420616e64207468656972207465726d206475726174696f6e292e204e756d626572206f66206163636f756e747320746861742073686f756c6420636f6e737469747574652074686520636f6c6c6563746976652e20486f77206c6f6e67206561636820706f736974696f6e2069732061637469766520666f722e20486f77206c6f6e6720746f2067697665206561636820746f702063616e64696461746520746f2070726573656e74207468656d73656c7665732061667465722074686520766f746520656e64732e000000000000d44510000d000000000000001d3311000c0000000000000040811100e44510000000000000000000f4451000020000000000000000000000044610000a000000000000001d3311000c0000000000000040811100104610000000000000000000204610000100000000000000000000002846100009000000000000001d3311000c0000000000000040811100344610000000000000000000444610000200000000000000000000005446100014000000000000001d3311000c000000000000004081110068461000000000000000000078461000020000000000000000000000884610000a0000000000000006111100030000000000000040811100944610000000000000000000a4461000020000000000000000000000b44610001300000000000000f53b1000090000000000000040811100c84610000000000000000000d8461000030000000000000000000000b00911000c000000000000001bf610000e0000000000000040811100f0461000000000000000000000471000020000000000000000000000104710000a00000000000000061111000300000000000000408111001c47100000000000000000002c471000050000000000000000000000544710000e0000000000000006111100030000000000000040811100644710000000000000000000744710000100000000000000000000007c471000110000000000000006111100030000000000000040811100904710000000000000000000a0471000010000000000000043616e646964616379426f6e640000002f00000000000000010000003d000000b04b10004e000000fe4b100014000000566f74696e67426f6e6400002f0000000000000001000000320000006e4b100042000000566f74696e674665650000002f00000000000000010000003e000000074b10004a000000514b10001d00000050726573656e74536c617368506572566f7465722f000000000000000100000033000000a34a100045000000e84a10001f0000004361727279436f756e7400002f000000000000000100000037000000354a1000470000007c4a100027000000496e6163746976654772616365506572696f64002f00000000000000010000003f000000984910004c000000e44910004b0000002f4a1000060000002f00000000000000010000004000000046491000490000008f491000090000004465636179526174696f00002f000000000000000100000041000000f34710004d00000040481000410000008148100047000000c84810004a0000001249100034000000564f5445525f5345545f53495a4500002f000000000000000100000042000000cf47100024000000415050524f56414c5f5345545f53495a450000002f000000000000000100000043000000a84710002700000020546865206368756e6b2073697a65206f662074686520617070726f76616c20766563746f722e20546865206368756e6b2073697a65206f662074686520766f74657220766563746f722e20446563617920666163746f72206f6620776569676874207768656e206265696e6720616363756d756c617465642e2049742073686f756c64207479706963616c6c792062652073657420746f205f5f6174206c656173745f5f20606d656d626572736869705f73697a65202d316020746f206b6565702074686520636f6c6c656374697665207365637572652e205768656e2073657420746f20604e602c20697420696e64696361746573206028312f4e295e7460206f66207374616b656420697320646563617965642061742077656967687420696e6372656d656e742073746570206074602e20302077696c6c20726573756c7420696e206e6f20776569676874206265696e6720616464656420617420616c6c20286e6f726d616c20617070726f76616c20766f74696e67292e204120726561736f6e61626c652064656661756c742076616c75652069732032342e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e204120726561736f6e61626c652064656661756c742076616c756520697320313030302e20486f77206d616e7920766f746520696e6469636573206e65656420746f20676f20627920616674657220612074617267657420766f7465722773206c61737420766f7465206265666f726520746865792063616e2062652072656170656420696620746865697220617070726f76616c7320617265206d6f6f742e204120726561736f6e61626c652064656661756c742076616c756520697320312e20486f77206d616e792072756e6e6572732d75702073686f756c64206861766520746865697220617070726f76616c73207065727369737420756e74696c20746865206e65787420766f74652e204120726561736f6e61626c652064656661756c742076616c756520697320322e205468652070756e6973686d656e742c2070657220766f7465722c20696620796f752070726f7669646520616e20696e76616c69642070726573656e746174696f6e2e204120726561736f6e61626c652064656661756c742076616c756520697320312e2054686520616d6f756e74206f662066656520706169642075706f6e206561636820766f7465207375626d697373696f6e2c20756e6c6573732069662074686579207375626d69742061205f686f6c655f20696e64657820616e64207265706c6163652069742e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f2062652061626c6520746f207375626d697420766f7465732e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f207375626d6974206f6e6527732063616e6469646163792e204120726561736f6e61626c652064656661756c742076616c756520697320392e00000a681100280000002c4c1000440000000b010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f656c656374696f6e732f7372632f6c69622e72732c4c1000440000000b01000001000000436f756e63696c2050726f787963616e6e6f74207265617020647572696e672070726573656e746174696f6e20706572696f647265706f72746572206d757374206265206120766f746572696e76616c6964207265706f7274657220696e646578766f746520696e646578206e6f742063757272656e7463616e6e6f74207265617020647572696e6720677261636520706572696f6474617267657420666f7220696e616374697669747920636c65616e7570206d75737420626520616374697665626164207265706f7274657220696e6465786261642074617267657420696e646578696e76616c69642074617267657420696e64657872657472616374696f6e20696e646578206d69736d6174636872657472616374696f6e20696e64657820696e76616c696463616e6e6f742072657472616374207768656e2070726573656e74696e6763616e6e6f742072657472616374206e6f6e2d766f7465726475706c69636174652063616e646964617465207375626d697373696f6e696e76616c69642063616e64696461746520736c6f7463616e64696461746520686173206e6f7420656e6f7567682066756e647363616e6e6f742070726573656e74206f757473696465206f662070726573656e746174696f6e20706572696f64696e646578206e6f742063757272656e747374616b65206465706f736974656420746f2070726573656e742077696e6e657220616e6420626520616464656420746f206c6561646572626f6172642073686f756c64206265206e6f6e2d7a65726f6c6561646572626f617264206d757374206578697374207768696c652070726573656e742070686173652061637469766570726573656e746572206d75737420686176652073756666696369656e7420736c61736861626c652066756e647370726573656e7465642063616e646964617465206d7573742062652063757272656e7463616e646964617465206e6f7420776f72746879206f66206c6561646572626f61726463616e646964617465206d757374206e6f7420666f726d2061206475706c696361746564206d656d62657220696620656c65637465646475706c69636174652070726573656e746174696f6e696e636f727265637420746f74616c6e6f20617070726f76616c206368616e67657320647572696e672070726573656e746174696f6e20706572696f64696e636f727265637420766f746520696e646578616d6f756e74206f662063616e6469646174657320746f207265636569766520617070726f76616c20766f7465732073686f756c64206265206e6f6e2d7a65726f616d6f756e74206f662063616e64696461746520766f7465732063616e6e6f742065786365656420616d6f756e74206f662063616e64696461746573696e76616c696420766f74657220696e64657877726f6e6720766f74657220696e6465786e657720766f746572206d75737420686176652073756666696369656e742066756e647320746f207061792074686520626f6e6446524e4b00000000000070e710000800000000000000b8511000010000000000000000000000c0511000010000000000000000000000c85110000800000000000000b40f1100010000000000000000000000d0511000010000000000000000000000d85110000700000000000000e0511000030000000000000000000000f8511000010000000000000000000000005210000500000000000000b40f110001000000000000000000000008521000010000000000000000000000105210000800000000000000b40f1100010000000000000000000000185210000100000000000000348910000d000000e95210000e0000005370656e64696e67af5210003a0000004177617264656400348910000d0000006a1011000700000061101100090000008f521000200000004275726e740000006c52100023000000526f6c6c6f766572205210004c000000205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e416c69766520636f6e7472616374206f7220746f6d6273746f6e6520616c726561647920657869737473647572696e6720657865637574696f6e0000000a681100280000004c5310004d0000005e000000080000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f7761736d2f72756e74696d652e72734772616e64706146696e616c697479205374616c6c656454726561737572792050726f706f73616c730000e0531000190000000054100048000000bb0100002d00000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f6f70732f61726974682e7273616c726561647920626f72726f776564616c7265616479206d757461626c7920626f72726f7765642f0000000000000001000000440000002f0000000000000001000000450000000a68110028000000a85410004300000084000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f74726561737572792f7372632f6c69622e7273000455100033000000375510004b000000b200000005000000636f6e74726163742073756273797374656d20726573756c74696e6720696e20706f73697469766520696d62616c616e6365212f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f6163636f756e745f64622e7273707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a09090909090960656d7074795f6f75747075745f627566602069732074616b656e206f6e6c7920686572653b0a09090909606578745f72657475726e602074726170733b0a090909096052756e74696d65602063616e206f6e6c792062652075736564206f6e6c7920666f72206f6e6520657865637574696f6e3b0a090909097165640000000000205810001200000000000000345810000100000000000000000000004c58100001000000000000007265706f72745f6d69736265686176696f720000000000006d5810000700000000000000d5ca1000070000005458100019000000205265706f727420736f6d65206d69736265686176696f722e5f7265706f72744772616e64706146696e616c6974790000000000d0de10000b00000000000000000000003c5a1000230000000000000000000000000000000000000000000000000000000000000040811100d06010000000000000000000605a100001000000000000000100000000000000685a10000500000000000000000000006d5a10001b0000000000000000000000000000000000000000000000000000000000000040811100885a10000000000000000000985a100001000000000000000100000000000000a05a10000d0000000000000000000000ad5a1000230000000000000000000000000000000000000000000000000000000000000040811100145b10000000000000000000d05a100001000000000000000000000000000000d85a10000a00000000000000000000001bf610000e0000000000000000000000000000000000000000000000000000000000000040811100145b10000000000000000000e45a100001000000000000000000000000000000ec5a1000070000000000000000000000f35a1000200000000000000000000000000000000000000000000000000000000000000040811100145b10000000000000000000245b10000100000000000000000000005665633c28417574686f7269747949642c20417574686f72697479576569676874293e00d45b10001b000000537461746553746f72656453746174653c543a3a426c6f636b4e756d6265723e2f000000000000000100000046000000b05b10002400000050656e64696e674368616e676553746f72656450656e64696e674368616e67653c543a3a426c6f636b4e756d6265723e7f5b1000310000004e657874466f726365640000505b10002f0000005374616c6c656428543a3a426c6f636b4e756d6265722c20543a3a426c6f636b4e756d62657229002f0000000000000001000000360000002c5b10002400000020607472756560206966207765206172652063757272656e746c79207374616c6c65642e206e65787420626c6f636b206e756d6265722077686572652077652063616e20666f7263652061206368616e67652e2050656e64696e67206368616e67653a20287369676e616c65642061742c207363686564756c6564206368616e6765292e205374617465206f66207468652063757272656e7420617574686f72697479207365742e205468652063757272656e7420617574686f72697479207365742e0000000000745c10000d00000000000000845c1000020000000000000000000000b45c1000090000000000000000000000fc5c10000f000000000000000c5d1000010000000000000000000000245d10000700000000000000000000005c5d100010000000000000000c5d10000100000000000000000000006c5d1000080000000000000070726f706f73655f7370656e6400000000000000ee2511000500000000000000f325110015000000000000004a5f10000b00000000000000b01d110023000000785e10004b000000c35e10004d000000105f100015000000386b1100000000007e1b11000b0000002e27110008000000f57b100019000000255f1000250000001f1c11000c00000072656a6563745f70726f706f73616c00000000006d5e10000b00000000000000b5a91000160000002e5e10003f000000386b1100000000007e1b11000b0000002e27110008000000f57b100019000000e6f21000100000001f1c11000c000000617070726f76655f70726f706f73616cac5d100057000000035e10002b000000386b1100000000007e1b11000b0000002e27110008000000f57b1000190000000e7c1000110000001f1c11000c00000020417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e2052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e70726f706f73616c5f69642050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e202d204f6e65204442206368616e67652c206f6e6520657874726120444220656e7472792e62656e65666963696172790000000000000088ad10000d0000000000000000000000348910000d0000000000000000000000000000000000000000000000000000000000000040811100606010000000000000000000706010000100000000000000010000000000000018ad1000090000000101000000000000348910000d00000000000000786010002400000000000000000000000000000000000000408111009c6010000000000000000000ac60100001000000000000000000000000000000b4601000090000000000000000000000bd601000120000000000000000000000000000000000000000000000000000000000000040811100d06010000000000000000000e06010000100000000000000010000002f000000000000000100000041000000456110002900000050726f706f73616c3c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e2f000000000000000100000036000000266110001f000000417070726f76616c735665633c50726f706f73616c496e6465783e002f000000000000000100000031000000e86010003e0000002050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e000000000000506210000c000000000000005c621000070000000000000040811100646210000000000000000000746210000200000000000000000000008462100013000000000000001d3311000c0000000000000040811100986210000000000000000000a8621000010000000000000000000000b06210000b000000000000001bf610000e0000000000000040811100bc6210000000000000000000cc621000010000000000000000000000d462100004000000000000005c621000070000000000000040811100d86210000000000000000000e8621000010000000000000050726f706f73616c426f6e645065726d696c6c002f000000000000000100000047000000a863100055000000fd6310004400000050726f706f73616c426f6e644d696e696d756d002f00000000000000010000003200000056631000520000005370656e64506572696f64002f00000000000000010000004800000034631000220000004275726e2f000000000000000100000049000000f0621000440000002050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e204672616374696f6e206f6620612070726f706f73616c27732076616c756520746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c616365207468652070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f6573206e6f742e4772616e64706146696e616c6974792050656e64696e674368616e67654772616e64706146696e616c697479205374617465496e636f6e73697374656e74207374617465202d20636f756c646e277420736574746c6520696d62616c616e636520666f722066756e6473207370656e74206279207472656173757279000000a854100043000000840000000100000050726f706f73657227732062616c616e636520746f6f206c6f774e6f2070726f706f73616c206174207468617420696e646578002d00000008000000040000004a0000004b00000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004772616e64706146696e616c697479204e657874466f726365643a73657373696f6e3a6b65797353657373696f6e2056616c696461746f727353657373696f6e204e6578744b65797373657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a0909097165640000000a681100280000002c601100500000003701000009000000000000000467100008000000000000000c6710000200000000000000000000003c6710000a000000000000007365745f6b657973000000008aca100004000000000000009568100007000000000000009c6810000500000000000000d5ca1000070000008c67100039000000c5671000480000000d68100031000000386b1100000000003e68100035000000386b1100000000007e1b11000b000000736810002200000094f21000160000001f1c11000c0000002053657473207468652073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c657220746f20606b6579602e20416c6c6f777320616e206163636f756e7420746f20736574206974732073657373696f6e206b6579207072696f7220746f206265636f6d696e6720612076616c696461746f722e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e20546865206469737061746368206f726967696e206f6620746869732066756e6374696f6e206d757374206265207369676e65642e202d204f286c6f67206e2920696e206e756d626572206f66206163636f756e74732e543a3a4b65797370726f6f6600000000000000c03111000a00000000000000000000000c6b1000130000000000000000000000000000000000000000000000000000000000000040811100ac6b10000000000000000000206b100001000000000000000100000000000000286b10000c0000000000000000000000136511000c0000000000000000000000000000000000000000000000000000000000000040811100346b10000000000000000000446b1000010000000000000001000000000000004c6b1000070000000000000000000000d33311000400000000000000000000000000000000000000000000000000000000000000408111006c6b10000000000000000000546b1000010000000000000001000000000000005c6b10000d0000000000000000000000d33311000400000000000000000000000000000000000000000000000000000000000000408111006c6b100000000000000000007c6b100001000000000000000100000000000000846b10000a00000000000000000000008e6b10001e0000000000000000000000000000000000000000000000000000000000000040811100ac6b10000000000000000000bc6b100002000000000000000100000000000000cc6b1000080000000204010000000000d5ca10000700000000000000d46b10000e0000000000000095681000070000000000000040811100206c10000000000000000000e46b100004000000000000000000000000000000046c1000080000000204010000000000d5ca100007000000000000000c6c10001400000000000000d46b10000e0000000000000040811100206c10000000000000000000306c10000400000000000000000000005665633c543a3a56616c696461746f7249643e00566e10001f00000043757272656e74496e6465782f000000000000000100000041000000386e10001e0000004368616e676564000a6e10002e0000005175657565644368616e6765640000002f000000000000000100000036000000f56d1000150000005175657565644b6579735665633c28543a3a56616c696461746f7249642c20543a3a4b657973293e2f0000000000000001000000310000006e6d10004f000000bd6d1000380000004e6578744b657973543a3a56616c696461746f7249640000476d100027000000386b110000000000996c100056000000ef6c1000580000004b65794f776e6572284b65795479706549642c205665633c75383e292f000000000000000100000036000000506c100049000000386b110000000000996c100056000000ef6c10005800000020546865206f776e6572206f662061206b65792e20546865207365636f6e64206b65792069732074686520604b657954797065496460202b2074686520656e636f646564206b65792e20546865206669727374206b657920697320616c77617973206044454455505f4b45595f5052454649586020746f206861766520616c6c20746865206461746120696e207468652073616d65206272616e6368206f662074686520747269652e20486176696e6720616c6c206461746120696e207468652073616d65206272616e63682073686f756c642070726576656e7420736c6f77696e6720646f776e206f7468657220717565726965732e20546865206e6578742073657373696f6e206b65797320666f7220612076616c696461746f722e2054686520717565756564206b65797320666f7220746865206e6578742073657373696f6e2e205768656e20746865206e6578742073657373696f6e20626567696e732c207468657365206b6579732077696c6c206265207573656420746f2064657465726d696e65207468652076616c696461746f7227732073657373696f6e206b6579732e20517565756564206b657973206368616e6765642e205472756520696620616e797468696e6720686173206368616e67656420696e20746869732073657373696f6e2e2043757272656e7420696e646578206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e00000000000000b06e10001000000000000000c06e1000050000000000000040811100c86e10000000000000000000d86e1000020000000000000044454455505f4b45595f505245464958265b75385d0000002f00000000000000010000004d000000e86e100059000000416f10000d0000002055736564206173206669727374206b657920666f7220604e6578744b6579736020616e6420604b65794f776e65726020746f2070757420616c6c20746865206461746120696e746f207468652073616d65206272616e6368206f662074686520747269652e00000000000080d1f00840787d01000000000065cd1d23b4cc3a113b5c2301000000d31b421e4fdcba34836c472001000000c75bbd1e52a1fd2e01b4511d010000005feb3f1f1d03952998c57b1a01000000bdb6ca1fa50181245d60c61701000000abd95e20029dc11fec4f3215010000006fadfd2034d5561b086ec01201000000efdba82133aa4017c3a4711001000000eb7a6222fd1b7f132df1460e01000000c1332d23942a1210ad66410c01000000777f0c2408d6f90c5e33620a01000000a3040525591e360ab7a5aa080100000085311d268803c70760341c070100000097465e279f85ac054289b805010000007346d628a4a4e603ce9181040100000019e89b2abe607502ad987903010000009db7d72c54ba5801bb71a30201000000eb88dd2ff4b29000c5cf0202010000000b8c8d349e412700f8d7a5010100000053657373696f6e205175657565644b657973636f6465206973206e6f7420666f756e647072697374696e6520636f6465206973206e6f7420666f756e647468657265206973206e6f7420656e6f7567682067617320666f722073746f72696e672074686520636f646553657373696f6e204b65794f776e65726e6f206173736f6369617465642076616c696461746f7220494420666f72206163636f756e742e72656769737465726564206475706c6963617465206b657966696e616c6e756d46696e616c697a6564206e756d62657220696e686572656e742064617461206e6f7420666f756e640a68110028000000907110003f0000006a000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f7375646f2f7372632f6c69622e7273000a00000014000000f071100048000000820a00000a00000000000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e72737375646f000000009472100005000000000000009c721000010000000000000000000000a4721000010000000000000000000000ac7210000a0000000000000034e81000010000000000000000000000b872100001000000000000005375646964000000d333110004000000fc721000180000004b65794368616e6765640000c07210003c00000020546865207375646f6572206a757374207377697463686564206964656e746974793b20746865206f6c64206b657920697320737570706c6965642e2041207375646f206a75737420746f6f6b20706c6163652e907110003f0000006a000000010000005375646f204b65796f6e6c79207468652063757272656e74207375646f206b65792063616e206368616e676520746865207375646f206b65796f6e6c79207468652063757272656e74207375646f206b65792063616e207375646f00000000008dcb100006000000000000004e000000000000000000000000000000000000000000000000000000000000004f00000000000000000000000000000050000000000000000000000000000000510000000000000000000000000000004edc100004000000000000005200000000000000000000000000000000000000000000000000000000000000510000000000000000000000020000000000000000000000000000000000000053000000000000000000000000000000f7bd10000900000000000000540000000000000000000000000000000000000000000000000000000000000055000000000000000000000002000000000000000000000000000000000000005600000000000000000000000000000061c110000a000000000000005700000000000000000000000000000000000000000000000000000000000000580000000000000000000000020000000000000000000000000000000000000051000000000000000000000000000000e6b7100007000000000000005900000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000005a00000000000000000000000000000051000000000000000000000000000000f879100008000000000000005b000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000005d0000000000000000000000000000005e0000000000000000000000000000004e29110007000000000000005f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000006100000000000000000000000000000062000000000000000000000000000000007a100007000000000000006300000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000006500000000000000000000000000000066000000000000000000000000000000f3f910000900000000000000670000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000690000000000000000000000000000006a000000000000000000000000000000077a100007000000000000006b000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000006d000000000000000000000000000000510000000000000000000000000000000e7a100012000000000000006e000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000006d00000000000000000000000000000051000000000000000000000000000000207a100009000000000000006f00000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000007100000000000000000000000000000072000000000000000000000000000000297a10000f000000020000000000000000000000000000000000000000000000000000000000000000000000730000000000000000000000020000000000000000000000000000000000000074000000000000000000000000000000387a1000070000000000000075000000000000000000000000000000000000000000000000000000000000007600000000000000000000000000000077000000000000000000000000000000510000000000000000000000000000003f7a100008000000000000007800000000000000000000000000000000000000000000000000000000000000790000000000000000000000000000007a0000000000000000000000000000007b000000000000000000000000000000477a100009000000000000007c000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000007e0000000000000000000000000000007f000000000000000000000000000000507a100004000000000000008000000000000000000000000000000000000000000000000000000000000000810000000000000000000000000000008200000000000000000000000000000051000000000000000000000000000000547a100008000000000000008300000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000008500000000000000000000000000000086000000000000000000000042616c616e63657353657373696f6e436f756e63696c546563686e6963616c436f6d6d6974746565456c656374696f6e7346696e616c697479547261636b65724772616e6470615472656173757279436f6e7472616374735375646f496d4f6e6c696e65000000003872100004000000000000007cef1000010000000000000000000000b47a1000090000000000000000000000fc7a10000700000000000000047b10000100000000000000000000001c7b100009000000000000001f7c10004e000000386b110000000000c17b100034000000386b1100000000007e1b11000b0000002e27110008000000f57b1000190000006d7c1000100000001f1c11000c0000007365745f6b657900000000004b1c11000300000000000000b01d110023000000647b10005d000000386b110000000000c17b100034000000386b1100000000007e1b11000b0000002e27110008000000f57b1000190000000e7c1000110000001f1c11000c0000002041757468656e74696361746573207468652063757272656e74207375646f206b657920616e6420736574732074686520676976656e204163636f756e7449642028606e6577602920617320746865206e6577207375646f206b65792e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2e202d204c696d697465642073746f726167652072656164732e202d204f6e65204442206368616e67652e2041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c20776974682060526f6f7460206f726967696e2e202d204e6f204442207772697465732e00000000000000d87c1000030000000000000000000000423111000c0000000000000000000000000000000000000000000000000000000000000040811100dc7c10000000000000000000ec7c10000100000000000000010000004b6579002f000000000000000100000087000000f47c1000210000002054686520604163636f756e74496460206f6620746865207375646f206b65792e4e6f206f74686572206572726f72732061726520616363657074656420616674657220616e2068617264206572726f7221496e686572656e7420776974682073616d65206964656e74696669657220616c726561647920657869737473215468657265206973206f6e6c79206f6e6520666174616c206572726f723b207165640000002d00000008000000040000002e0000007375627374726174652d6e6f64650000df6acb689907609b0200000037e397fc7c91f5e40100000040fe3ad401f8959a03000000d2bc9897eed08f1501000000f78b278be53f454c01000000ed99c5acb25eedf502000000cbca25e39f1423870100000022f09549cb59f9ff010000008d8010001c000000187f100044000000bf000000030000006980100024000000187f100044000000c8000000030000003180100038000000187f100044000000060100002a0000000980100028000000187f1000440000000701000032000000e17f100028000000187f100044000000090100002c000000b57f10002c000000187f100044000000080100004c000000837f100032000000187f10004400000031010000030000005c7f100027000000187f1000440000003901000004000000f07e100028000000187f1000440000003f0100000300000053746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e2f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f6578656375746976652f7372632f6c69622e7273446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e4e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e416c6c2065787472696e736963732073686f756c6420686176652074686520636f7272656374206e6f6e636545787472696e736963732073686f756c64206e6f742065786365656420626c6f636b206c696d6974416c6c2065787472696e736963732073686f756c642062652070726f7065726c79207369676e6564416c6c2065787472696e736963732073686f756c6420686176652073656e6465722061626c6520746f2070617920746865697220666565735472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e506172656e7420686173682073686f756c642062652076616c69642e626164207369676e617475726520696e2065787472696e73696300418110000d000000268110001b000000e480100042000000bf010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6e6f64652f72756e74696d652f7372632f6c69622e727342616420696e70757420646174612070726f766964656420746f20657865637574655f626c6f636b00005881100010000000696e697469616c697a655f626c6f636b708110000f0000006170706c795f65787472696e736963008881100013000000696e686572656e745f65787472696e7369637300a48110000f000000636865636b5f696e686572656e747300bc8110001400000076616c69646174655f7472616e73616374696f6ed88110000f0000006f6666636861696e5f776f726b657200f0811000160000006772616e6470615f70656e64696e675f6368616e6765000010821000150000006772616e6470615f666f726365645f6368616e6765496e76616c6964206f726967696e00000000003c8310000800000000000000448310000300000000000000000000005c831000010000000000000000000000648310000c0000000000000018e8100002000000000000000000000070831000010000000000000000000000788310000a00000000000000848310000100000000000000000000008c831000010000000000000000000000948310000f00000000000000a4831000010000000000000000000000ac831000010000000000000000000000b48310000a00000000000000c0831000020000000000000000000000d0831000020000000000000000000000e08310000800000000000000e8831000020000000000000000000000f883100001000000000000005472616e73666572611011000900000061101100090000006a101100070000002385100055000000496e7374616e746961746564ec84100037000000436f646553746f72656400005ce8100004000000be8410002e0000005363686564756c65557064617465640006111100030000008e841000300000004469737061746368656400006110110009000000d333110004000000238410004e000000718410001d000000436f6e74726163746110110009000000d5ca100007000000008410002300000020416e206576656e742066726f6d20636f6e7472616374206f66206163636f756e742e20412063616c6c2077617320646973706174636865642066726f6d2074686520676976656e206163636f756e742e2054686520626f6f6c207369676e616c73207768657468657220697420776173207375636365737366756c20657865637574696f6e206f72206e6f742e20547269676765726564207768656e207468652063757272656e74207363686564756c6520697320757064617465642e20436f646520776974682074686520737065636966696564206861736820686173206265656e2073746f7265642e20436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d6020746f2060746f60207769746820676976656e206076616c7565602061732070617274206f662061206063616c6c60206f722060637265617465602e64656661756c743a0000000070e71000080000000000000088861000040000000000000000000000a8861000020000000000000000000000b88610000500000000000000c0861000050000000000000000000000e8861000020000000000000000000000f886100008000000000000008483100001000000000000000000000000871000010000000000000000000000088710000b000000000000008483100001000000000000000000000014871000010000000000000000000000f2e7100008000000000000001c8710000200000000000000000000002c871000010000000000000000000000348710000e000000000000001c8710000200000000000000000000004487100001000000000000006110110009000000348910000d0000005ce8100004000000c68810000b000000d1881000530000002489100010000000566f74656400000061101100090000005ce8100004000000d333110004000000c68810000b000000c68810000b0000003e881000420000008088100046000000417070726f7665640d88100031000000446973617070726f76656400d8871000350000005ce8100004000000d33311000400000097871000410000004d656d626572457865637574656400004c8710004b00000020412073696e676c65206d656d6265722064696420736f6d6520616374696f6e3b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e20726573706563746976656c7920617320604d656d626572436f756e7460292e4d656d626572436f756e742041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20604d656d626572436f756e7460292e50726f706f73616c496e646578436f6e7472616374205072697374696e65436f6465496e7374616e636531436f6c6c656374697665204d656d62657273496e7374616e636532436f6c6c656374697665204d656d62657273436f6e747261637420436f646553746f72616765436f6e747261637420436f6e7472616374496e666f4f66436f6e74726163742047617350726963650a68110028000000e0891000450000007d000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6c6c6563746976652f7372632f6c69622e727300000000000000308b10000f00000000000000408b1000010000000000000000000000588b1000030000000000000000000000708b10000800000000000000788b1000020000000000000000000000a88b1000020000000000000000000000b94711000400000000000000b88b1000040000000000000000000000188c1000070000000000000000000000508c10000600000000000000588c1000040000000000000000000000b88c10000a0000000000000000000000088d10000f00000000000000188d1000020000000000000000000000488d1000050000000000000000000000708d10000a000000000000007c8d1000040000000000000000000000dc8d100006000000000000007570646174655f7363686564756c650000000000fb951000080000000000000003961000080000008b9510002d000000386b110000000000b8951000430000007075745f636f6465000000004d9310000900000000000000569310000c00000000000000879510000400000000000000d5ca100007000000fb94100057000000529510003500000000000000b58f10000400000000000000b01d11002300000000000000ee2511000500000000000000f325110015000000000000004d9310000900000000000000569310000c00000000000000629310000400000000000000d5ca1000070000006693100042000000386b110000000000a89310004a000000f29310002c0000001e941000460000006494100052000000b694100045000000637265617465000000000000449310000900000000000000f325110015000000000000004d9310000900000000000000569310000c00000000000000b98f10000900000000000000c28f10000b00000000000000629310000400000000000000d5ca1000070000002d9110006a000000386b1100000000009791100021000000386b110000000000b8911000500000000892100041000000499210005b000000a492100057000000fb9210002a000000259310001f000000636c61696d5f7375726368617267650000000000b58f10000400000000000000423111000c000000000000000f9110000a000000000000001991100014000000f58f10005c0000005190100045000000386b110000000000969010004e000000e49010002b000000726573746f72655f746f000000000000b58f10000400000000000000423111000c00000000000000b98f10000900000000000000c28f10000b00000000000000cd8f10000e000000000000001d3311000c00000000000000db8f10000500000000000000e08f1000150000000c8e100040000000386b1100000000004c8e10006f000000bb8e10004e000000098f1000640000006d8f10004800000020416c6c6f7773206120636f6e747261637420746f20726573746f7265206120746f6d6273746f6e6520627920676976696e67206974732073746f726167652e2054686520636f6e747261637420746861742077616e747320746f20726573746f72652028692e652e206f726967696e206f66207468652063616c6c2c206f7220606d73672e73656e6465726020696e20536f6c6964697479207465726d73292077696c6c20636f6d70757465206120746f6d6273746f6e652077697468206974732073746f7261676520616e642074686520676976656e20636f64655f686173682e2049662074686520636f6d707574656420746f6d6273746f6e65206d61746368207468652064657374696e6174696f6e206f6e652c207468652064657374696e6174696f6e20636f6e747261637420697320726573746f7265642077697468207468652072656e745f616c6c6f77616e636560207370656369666965642c207768696c6520746865206f726967696e2073656e647320616c6c206974732066756e647320746f207468652064657374696e6174696f6e20616e642069732072656d6f7665642e64657374636f64655f68617368436f6465486173683c543e72656e745f616c6c6f77616e636564656c74615665633c657865633a3a53746f726167654b65793e20416c6c6f777320626c6f636b2070726f64756365727320746f20636c61696d206120736d616c6c2072657761726420666f72206576696374696e67206120636f6e74726163742e204966206120626c6f636b2070726f6475636572206661696c7320746f20646f20736f2c206120726567756c61722075736572732077696c6c20626520616c6c6f77656420746f20636c61696d20746865207265776172642e20496620636f6e7472616374206973206e6f742065766963746564206173206120726573756c74206f6620746869732063616c6c2c206e6f20616374696f6e73206172652074616b656e20616e64207468652073656e646572206973206e6f7420656c696769626c6520666f7220746865207265776172642e6175785f73656e6465724f7074696f6e3c543a3a4163636f756e7449643e20437265617465732061206e657720636f6e74726163742066726f6d207468652060636f646568617368602067656e65726174656420627920607075745f636f6465602c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e204372656174696f6e20697320657865637574656420617320666f6c6c6f77733a202d205468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d2054686520736d6172742d636f6e7472616374206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20546865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792d63726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e792063616c6c2072656365697665642062792074686973206163636f756e742e202d2054686520636f6e747261637420697320696e697469616c697a65642e656e646f776d656e746761735f6c696d6974436f6d706163743c4761733e64617461204d616b657320612063616c6c20746f20616e206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e202a20496620746865206163636f756e74206973206120736d6172742d636f6e7472616374206163636f756e742c20746865206173736f63696174656420636f64652077696c6c20626520657865637574656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e202a20496620746865206163636f756e74206973206120726567756c6172206163636f756e742c20616e792076616c75652077696c6c206265207472616e736665727265642e202a204966206e6f206163636f756e742065786973747320616e64207468652063616c6c2076616c7565206973206e6f74206c657373207468616e20606578697374656e7469616c5f6465706f736974602c206120726567756c6172206163636f756e742077696c6c206265206372656174656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e2053746f7265732074686520676976656e2062696e617279205761736d20636f646520696e746f2074686520636861696e27732073746f7261676520616e642072657475726e73206974732060636f646568617368602e20596f752063616e20696e7374616e746961746520636f6e747261637473206f6e6c7920776974682073746f72656420636f64652e636f6465205570646174657320746865207363686564756c6520666f72206d65746572696e6720636f6e7472616374732e20546865207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652073746f726564207363686564756c652e7363686564756c655363686564756c650000000000749810000800000000000000000000007c9810000300000000000000000000000000000000000000000000000000000000000000408111000099100000000000000000008098100001000000000000000100000000000000889810000f000000000000000000000003961000080000000000000000000000000000000000000000000000000000000000000040811100989810000000000000000000a898100001000000000000000100000000000000b09810000c0000000101000000000000c28f10000b00000000000000d5ca100007000000000000000000000000000000000000004081110060b010000000000000000000bc98100001000000000000000000000000000000c49810000b0000000101000000000000c28f10000b00000000000000cf98100016000000000000000000000000000000000000004081110060b010000000000000000000e898100001000000000000000000000000000000f09810000e000000000000000000000020cb10000300000000000000000000000000000000000000000000000000000000000000408111000099100000000000000000001099100001000000000000000100000000000000189910000e0000000101000000000000423111000c00000000000000269910000f00000000000000000000000000000000000000408111003899100000000000000000004899100001000000000000000000000000000000509910000800000000000000000000001d3311000c0000000000000000000000000000000000000000000000000000000000000040811100589910000000000000000000689910000100000000000000010000004761735370656e7447617300a49a10002000000043757272656e745363686564756c65002f0000000000000001000000880000007f9a1000250000005072697374696e65436f6465269a100059000000436f646553746f726167657761736d3a3a5072656661625761736d4d6f64756c65000000cd991000590000004163636f756e74436f756e74657200002f000000000000000100000035000000b899100015000000436f6e7472616374496e666f4f66436f6e7472616374496e666f3c543e0000002f00000000000000010000003c0000008e9910002a00000047617350726963652f000000000000000100000089000000709910001e00000020546865207072696365206f66206f6e6520756e6974206f66206761732e2054686520636f6465206173736f6369617465642077697468206120676976656e206163636f756e742e20546865207375627472696520636f756e7465722e2041206d617070696e67206265747765656e20616e206f726967696e616c20636f6465206861736820616e6420696e737472756d656e746564207761736d20636f64652c20726561647920666f7220657865637574696f6e2e2041206d617070696e672066726f6d20616e206f726967696e616c20636f6465206861736820746f20746865206f726967696e616c20636f64652c20756e746f756368656420627920696e737472756d656e746174696f6e2e2043757272656e7420636f7374207363686564756c6520666f7220636f6e7472616374732e20476173207370656e7420736f2066617220696e207468697320626c6f636b2e00000000449e100013000000000000001bf610000e0000000000000040811100589e10000000000000000000689e1000040000000000000000000000889e100010000000000000001d3311000c0000000000000040811100989e10000000000000000000a89e1000010000000000000000000000b09e1000110000000000000006111100030000000000000040811100c49e10000000000000000000d49e1000020000000000000000000000e49e10000b000000000000001d3311000c0000000000000040811100f09e10000000000000000000009f1000010000000000000000000000089f100011000000000000001d3311000c00000000000000408111001c9f100000000000000000002c9f1000070000000000000000000000649f10000f000000000000001d3311000c0000000000000040811100749f10000000000000000000849f1000020000000000000000000000949f10000b000000000000001d3311000c000000000000004081110010a010000000000000000000a09f1000010000000000000000000000a89f10000b000000000000001d3311000c000000000000004081110010a010000000000000000000b49f1000010000000000000000000000bc9f100012000000000000001d3311000c000000000000004081110010a010000000000000000000d09f1000010000000000000000000000d89f100012000000000000001d3311000c0000000000000040811100ec9f10000000000000000000fc9f100001000000000000000000000004a010000b000000000000001d3311000c000000000000004081110010a01000000000000000000020a0100002000000000000000000000030a010000b000000000000007c9810000300000000000000408111005ca0100000000000000000003ca010000200000000000000000000004ca010000d000000000000007c9810000300000000000000408111005ca0100000000000000000006ca010000200000000000000000000007ca0100008000000000000000611110003000000000000004081110084a01000000000000000000094a01000020000000000000000000000a4a010000c0000000000000006111100030000000000000040811100b0a010000000000000000000c0a01000010000000000000000000000c8a010000d000000000000007c981000030000000000000040811100d8a010000000000000000000e8a0100002000000000000005369676e6564436c61696d48616e6469636170002f00000000000000010000008a00000085a6100038000000386b110000000000bda610004300000000a710001a000000546f6d6273746f6e654465706f7369742f00000000000000010000008b00000050a610003500000053746f7261676553697a654f66667365740000002f000000000000000100000043000000d7a510004b00000022a610002e00000052656e7442797465466565002f00000000000000010000008c0000008aa510004d00000052656e744465706f7369744f66667365740000002f00000000000000010000008d00000012a410004100000053a4100016000000386b11000000000069a410005a000000c3a410005600000019a51000530000006ca510001e000000537572636861726765526577617264002f00000000000000010000008e000000bfa3100039000000f8a310001a0000005472616e73666572466565009aa31000250000004372656174696f6e4665650073a31000270000005472616e73616374696f6e4261736546656500003ca31000370000005472616e73616374696f6e4279746546656500002f000000000000000100000034000000f9a2100043000000436f6e7472616374466565002f000000000000000100000033000000a7a210004b000000f2a210000700000043616c6c426173654665650052a210004700000099a210000e000000437265617465426173654665650000002f00000000000000010000003b00000001a21000490000004aa21000080000004d617844657074682f00000000000000010000008f000000aca1100047000000f3a110000e0000004d617856616c756553697a652f0000000000000001000000900000005ea110004e000000426c6f636b4761734c696d69740000002f000000000000000100000091000000f8a010004900000041a110001d00000020546865206d6178696d756d20616d6f756e74206f6620676173207468617420636f756c6420626520657870656e6465642070657220626c6f636b2e204120726561736f6e61626c652064656661756c742076616c75652069732031305f3030305f3030302e20546865206d6178696d756d2073697a65206f6620612073746f726167652076616c756520696e2062797465732e204120726561736f6e61626c652064656661756c74206973203136204b69422e20546865206d6178696d756d206e657374696e67206c6576656c206f6620612063616c6c2f63726561746520737461636b2e204120726561736f6e61626c652064656661756c742076616c7565206973203130302e20546865206261736520666565206368617267656420666f72206372656174696e67206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203137352e20546865206261736520666565206368617267656420666f722063616c6c696e6720696e746f206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203133352e205468652066656520726571756972656420746f20637265617465206120636f6e747261637420696e7374616e63652e204120726561736f6e61626c652064656661756c742076616c75652069732032312e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b2074686520626173652e205468652066656520726571756972656420746f2063726561746520616e206163636f756e742e205468652066656520726571756972656420746f206d616b652061207472616e736665722e205265776172642074686174206973207265636569766564206279207468652070617274792077686f736520746f75636820686173206c656420746f2072656d6f76616c206f66206120636f6e74726163742e2054686520616d6f756e74206f662066756e6473206120636f6e74726163742073686f756c64206465706f73697420696e206f7264657220746f206f66667365742074686520636f7374206f66206f6e6520627974652e204c6574277320737570706f736520746865206465706f73697420697320312c303030204255202862616c616e636520756e697473292f6279746520616e64207468652072656e7420697320312042552f627974652f6461792c207468656e206120636f6e7472616374207769746820312c3030302c3030302042552074686174207573657320312c303030206279746573206f662073746f7261676520776f756c6420706179206e6f2072656e742e20427574206966207468652062616c616e6365207265647563656420746f203530302c30303020425520616e64207468652073746f7261676520737461796564207468652073616d6520617420312c3030302c207468656e20697420776f756c6420706179203530302042552f6461792e205072696365206f6620612062797465206f662073746f7261676520706572206f6e6520626c6f636b20696e74657276616c2e2053686f756c642062652067726561746572207468616e20302e2053697a65206f66206120636f6e7472616374206174207468652074696d65206f66206372656174696f6e2e205468697320697320612073696d706c652077617920746f20656e73757265207468617420656d70747920636f6e747261637473206576656e7475616c6c7920676574732064656c657465642e20546865206d696e696d756d20616d6f756e7420726571756972656420746f2067656e6572617465206120746f6d6273746f6e652e204e756d626572206f6620626c6f636b2064656c617920616e2065787472696e73696320636c61696d20737572636861726765206861732e205768656e20636c61696d207375726368617267652069732063616c6c656420627920616e2065787472696e736963207468652072656e7420697320636865636b656420666f722063757272656e745f626c6f636b202d2064656c6179496e7374616e636531436f6c6c6563746976652050726f706f73616c73496e7374616e636531436f6c6c65637469766520566f74696e670000000000000004a810000b0000000000000010a8100001000000000000000000000028a8100004000000000000000000000048a81000070000000000000050a8100001000000000000000000000068a8100003000000000000000000000028ed1000070000000000000080a81000020000000000000000000000b0a81000040000000000000000000000e0ed10000400000000000000d0a8100003000000000000000000000018a9100004000000000000007365745f6d656d6265727300000000003fab10000b00000000000000b11a110011000000beaa10005400000012ab100017000000386b11000000000029ab100016000000657865637574650000000000f4f61000080000000000000038aa10001e00000056aa10003d000000386b11000000000093aa10002b000000000000005ff81000090000000000000024aa10001400000000000000f4f61000080000000000000038aa10001e0000007e1b11000b000000d2a9100024000000f6a910002e0000001f1c11000c00000000000000f4f61000080000000000000005f410000700000000000000b0a910000500000000000000b5a910001600000000000000cba910000700000000000000d3331100040000007e1b11000b00000038a91000230000005ba91000550000001f1c11000c000000202d20426f756e6465642073746f72616765207265616420616e64207772697465732e202d2057696c6c20626520736c696768746c792068656176696572206966207468652070726f706f73616c20697320617070726f766564202f20646973617070726f7665642061667465722074686520766f74652e696e646578436f6d706163743c50726f706f73616c496e6465783e617070726f7665202d20426f756e6465642073746f7261676520726561647320616e64207772697465732e202d20417267756d656e7420607468726573686f6c6460206861732062656172696e67206f6e207765696768742e436f6d706163743c4d656d626572436f756e743e426f783c3c542061732054726169743c493e3e3a3a50726f706f73616c3e20446973706174636820612070726f706f73616c2066726f6d2061206d656d626572207573696e672074686520604d656d62657260206f726967696e2e204f726967696e206d7573742062652061206d656d626572206f662074686520636f6c6c6563746976652e205365742074686520636f6c6c6563746976652773206d656d62657273686970206d616e75616c6c7920746f20606e65775f6d656d62657273602e204265206e69636520746f2074686520636861696e20616e642070726f76696465206974207072652d736f727465642e20526571756972657320726f6f74206f726967696e2e6e65775f6d656d62657273496e7374616e636531436f6c6c6563746976650000000000000018ad100009000000000000000000000021ad10000c000000000000000000000000000000000000000000000000000000000000004081110080b01000000000000000000030ad10000100000000000000010000000000000038ad10000a000000010100000000000005f41000070000000000000042ad100019000000000000000000000000000000000000004081110060b0100000000000000000005cad10000100000000000000000000000000000064ad100006000000010100000000000005f4100007000000000000006aad100013000000000000000000000000000000000000004081110060b01000000000000000000080ad10000100000000000000000000000000000088ad10000d00000000000000000000000611110003000000000000000000000000000000000000000000000000000000000000004081110070b01000000000000000000098ad100001000000000000000100000000000000a0ad1000070000000000000000000000b11a110011000000000000000000000000000000000000000000000000000000000000004081110080b010000000000000000000a8ad100001000000000000000100000050726f706f73616c735665633c543a3a486173683e00000070ae10002400000050726f706f73616c4f663c542061732054726169743c493e3e3a3a50726f706f73616c003dae100033000000566f74696e67566f7465733c543a3a4163636f756e7449643e00000010ae10002d00000050726f706f73616c436f756e74000000fead1000120000004d656d6265727300b0ad10004e000000205468652063757272656e74206d656d62657273206f662074686520636f6c6c6563746976652e20546869732069732073746f72656420736f7274656420286a7573742062792076616c7565292e2050726f706f73616c7320736f206661722e20566f746573206f6e206120676976656e2070726f706f73616c2c206966206974206973206f6e676f696e672e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e2054686520686173686573206f6620746865206163746976652070726f706f73616c732e496e7374616e636532436f6c6c656374697665000000000018ad100009000000000000000000000021ad10000c000000000000000000000000000000000000000000000000000000000000004081110080b01000000000000000000030ad10000100000000000000010000000000000038ad10000a000000010100000000000005f41000070000000000000042ad100019000000000000000000000000000000000000004081110060b0100000000000000000005cad10000100000000000000000000000000000064ad100006000000010100000000000005f4100007000000000000006aad100013000000000000000000000000000000000000004081110060b01000000000000000000080ad10000100000000000000000000000000000088ad10000d00000000000000000000000611110003000000000000000000000000000000000000000000000000000000000000004081110070b01000000000000000000098ad100001000000000000000100000000000000a0ad1000070000000000000000000000b11a110011000000000000000000000000000000000000000000000000000000000000004081110080b010000000000000000000a8ad10000100000000000000010000002f0000000000000001000000360000002f0000000000000001000000410000002f0000000000000001000000310000000a68110028000000a8b0100044000000b7010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f6c69622e7273a8b0100044000000b7010000010000006e6577207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e2063757272656e74496e76616c69642073757263686172676520636c61696d3a206f726967696e206d757374206265207369676e6564206f7220696e686572656e7420616e6420617578696c696172792073656e646572206f6e6c792070726f7669646564206f6e20696e686572656e7443616e6e6f7420726573746f72652066726f6d20696e6578697374696e67206f7220746f6d6273746f6e6520636f6e74726163744f726967696e20547269654964207772697474656e20696e207468652063757272656e7420626c6f636b546f6d6273746f6e657320646f6e2774206d6174636843616e6e6f7420726573746f726520746f20696e6578697374696e67206f7220616c69766520636f6e7472616374e0891000450000007d0000000100000070726f706f736572206e6f742061206d656d6265726475706c69636174652070726f706f73616c73206e6f7420616c6c6f776564496e7374616e636531436f6c6c6563746976652050726f706f73616c4f66496e7374616e636531436f6c6c6563746976652050726f706f73616c436f756e7470726f706f73616c206d757374206578697374766f746572206e6f742061206d656d6265726d69736d61746368656420696e6465786475706c696361746520766f74652069676e6f726564000020b3100048000000880a00000e000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e7273496e7374616e636532436f6c6c6563746976652050726f706f73616c73496e7374616e636532436f6c6c65637469766520566f74696e67496e7374616e636532436f6c6c6563746976652050726f706f73616c4f66496e7374616e636532436f6c6c6563746976652050726f706f73616c436f756e740000000000000cb410000f000000000000001cb410000200000000000000000000002cb4100004000000000000004e65774163636f756e74496e646578006110110009000000c7b410000c0000004cb4100022000000386b1100000000006eb4100041000000afb41000180000002041206e6577206163636f756e7420696e646578207761732061737369676e65642e2054686973206576656e74206973206e6f7420747269676765726564207768656e20616e206578697374696e6720696e64657820697320726561737369676e656420746f20616e6f7468657220604163636f756e744964602e4163636f756e74496e64657800ecb410002b00000017b5100044000000ff0000000400000054696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b2f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f74696d657374616d702f7372632f6c69622e7273626c6f636b2073697a65206c696d697420697320726561636865646f766572666c6f77206d756c7469706c79696e6720676173206c696d6974206279207072696365000000b8b510003000000017b5100044000000f30000000400000054696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b00b610004e00000017b5100044000000f40000000400000054696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c4d696e696d756d506572696f643e206265747765656e2073657175656e7469616c20626c6f636b7354696d657374616d70204e6f77417574686f727368697020417574686f72496e646963657320456e756d53657400a0b6100019000000c0b6100048000000bb0100002d000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f6f70732f61726974682e72732d00000008000000040000002e0000000a6811002800000030b71000420000004a000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f696e64696365732f7372632f6c69622e7273000030b71000420000004a00000001000000696e76616c6964206163636f756e7420696e64657854696d657374616d7020746f6f2066617220696e2066757475726520746f206163636570744765747320616e64206465636f6465732074696d657374616d7020696e686572656e742064617461496e646963657300000000000000a0b810000b0000000000000000000000abb810000f0000000000000000000000000000000000000000000000000000000000000040811100bcb810000000000000000000ccb8100001000000000000000100000000000000d4b81000070000000101000000000000abb810000f00000000000000b11a1100110000000000000000000000000000000000000040811100dcb810000000000000000000ecb810000100000000000000010000004e657874456e756d536574543a3a4163636f756e74496e64657800002f0000000000000001000000410000000ab910001f000000456e756d536574002f000000000000000100000031000000f4b81000160000002054686520656e756d65726174696f6e20736574732e20546865206e657874206672656520656e756d65726174696f6e207365742e000000b0b9100048000000880a00000e000000a0b610001900000060b9100047000000e20000000a0000000000000000000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f7374616b696e672f7372632f70687261676d656e2e72730000000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e7273496e6469636573204e657874456e756d536574417574686f727368697020556e636c65736d656d6f727976616c69646174696f6e3a20696d706f727420656e74727920706f696e747320746f2061206e6f6e2d6578697374656e74207479706543616e6e6f7420696d706f727420676c6f62616c736d6f64756c6520696d706f7274732061206e6f6e2d6578697374656e742066756e6374696f6e6d6f64756c6520696d706f72747320606578745f7072696e746c6e60206275742064656275672066656174757265732064697361626c656443616e6e6f7420696d706f7274207461626c65736d6f64756c652068617320696d706f7274732066726f6d2061206e6f6e2d27656e7627206e616d6573706163654d656d6f727920696d706f7274206d757374206861766520746865206669656c64206e616d6520276d656d6f7279274d756c7469706c65206d656d6f727920696d706f72747320646566696e65644d6178696d756d206e756d626572206f662070616765732073686f756c6420626520616c77617973206465636c617265642e52657175657374656420696e697469616c206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520726571756573746564206d6178696d756d4d6178696d756d206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520636f6e66696775726564206d6178696d756d2e00000000000044bc1000030000000000000048bc100001000000000000000000000060bc100009000000000000007365740000000000e2bd10000300000000000000e5bd100012000000a8bc100016000000386b110000000000bebc10005600000014bd100036000000386b1100000000004abd1000510000009bbd100011000000386b110000000000acbd10003600000020536574207468652063757272656e742074696d652e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e742073706563696669656420627920604d696e696d756d506572696f64602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652060496e686572656e74602e6e6f77436f6d706163743c543a3a4d6f6d656e743e54696d657374616d7000000000b0be100003000000000000000000000095e31000090000000000000000000000000000000000000000000000000000000000000040811100b4be10000000000000000000c4be100001000000000000000100000000000000ccbe1000090000000000000000000000d3331100040000000000000000000000000000000000000000000000000000000000000040811100f8c210000000000000000000d8be10000100000000000000010000004e6f77002f0000000000000001000000350000000dbf100024000000446964557064617465000000e0be10002d00000020446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e000000000000006cbf10000d0000000000000095e310000900000000000000408111007cbf100000000000000000008cbf100004000000000000004d696e696d756d506572696f640000002f000000000000000100000092000000acbf10005a00000006c010005a00000060c0100059000000b9c010001c00000020546865206d696e696d756d20706572696f64206265747765656e20626c6f636b732e204265776172652074686174207468697320697320646966666572656e7420746f20746865202a65787065637465642a20706572696f6420746861742074686520626c6f636b2070726f64756374696f6e206170706172617475732070726f76696465732e20596f75722063686f73656e20636f6e73656e7375732073797374656d2077696c6c2067656e6572616c6c7920776f726b2077697468207468697320746f2064657465726d696e6520612073656e7369626c6520626c6f636b2074696d652e20652e672e20466f7220417572612c2069742077696c6c20626520646f75626c65207468697320706572696f64206f6e2064656661756c742073657474696e67732e0000000000000004c110000a0000000000000010c1100001000000000000000000000028c1100001000000000000007365745f756e636c657300000000000049c110000a0000000000000053c110000e00000030c11000190000002050726f76696465206120736574206f6620756e636c65732e6e65775f756e636c65735665633c543a3a4865616465723e417574686f7273686970000000000074c210000600000000000000000000007ac210003a0000000000000000000000000000000000000000000000000000000000000040811100b4c210000000000000000000c4c2100001000000000000000100000000000000ccc21000060000000000000000000000423111000c0000000000000000000000000000000000000000000000000000000000000040811100d4c210000000000000000000e4c2100001000000000000000000000000000000ecc210000c0000000000000000000000d3331100040000000000000000000000000000000000000000000000000000000000000040811100f8c21000000000000000000008c31000010000000000000001000000556e636c65735665633c556e636c65456e7472794974656d3c543a3a426c6f636b4e756d6265722c20543a3a486173682c20543a3a4163636f756e7449643e3e2f00000000000000010000003100000058c3100007000000417574686f7200002f0000000000000001000000360000003fc3100019000000446964536574556e636c65732f00000000000000010000003600000010c310002f000000205768657468657220756e636c6573207765726520616c72656164792073657420696e207468697320626c6f636b2e20417574686f72206f662063757272656e7420626c6f636b2e20556e636c657300b0b9100048000000820a00000a000000556e636c657320616c72656164792073657420696e20626c6f636b2e756e636c652069732067656e65736973756e636c657320746f6f206869676820696e20636861696e756e636c6520706172656e74206e6f7420696e20636861696e756e636c65206e6f7420726563656e7420656e6f75676820746f20626520696e636c75646564756e636c6520616c726561647920696e636c75646564626164206f726967696e3a20657870656374656420746f206265206e6f206f726967696e626164206f726967696e3a20657870656374656420746f206265206120726f6f74206f726967696e626164206f726967696e3a20657870656374656420746f2062652061207369676e6564206f726967696e3a65787472696e7369635f696e64657873746f72616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c696420747970650000e0c410001900000000c5100048000000420100000e00000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f6c69622e727360c510000e0000006ec5100048000000400100004a0000006578706c696369742070616e69632f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f6c69622e7273000060c510000e0000006ec5100048000000410100004a000000e8c51000340000001cc6100045000000ac0000000300000074686520766563746f7220697320616c7761797320636c65617265643b2069742773207772697474656e206f6e6c79206f6e63652f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f657865632e72730000002f000000000000000100000093000000940000009500000096000000970000009800000053797374656d204e756d62657253797374656d2045787472696e73696373526f6f7453797374656d2044696765737453797374656d20426c6f636b4861736853797374656d204163636f756e744e6f6e636500000a68110028000000f4c610003f0000009d000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f626162652f7372632f6c69622e7273000a681100280000004cc7100041000000dd000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f73797374656d2f7372632f6c69622e7273000000f4c610003f0000009d0000000100000074696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c53797374656d20506172656e744861736853797374656d2052616e646f6d4d6174657269616c0030c8100048000000880a00000e00000053797374656d204576656e747353797374656d204576656e74546f706963730000000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e72730000000080c910000a00000000000000386b11000000000000000000000000008cc9100001000000000000000000000094c9100006000000000000009cc91000010000000000000000000000b4c91000010000000000000000000000bcc910000e00000000000000ccc91000010000000000000000000000e4c91000010000000000000000000000ecc910000800000000000000f4c910000100000000000000000000000cca100001000000000000000000000014ca10000b0000000000000020ca100001000000000000000000000038ca100001000000000000000000000040ca10000c000000000000004cca100001000000000000000000000064ca1000010000000000000066696c6c5f626c6f636b000045cb10004800000072656d61726b0000000000003ecb10000700000000000000d5ca10000700000023cb10001b0000007365745f686561705f70616765730000000000001bcb1000050000000000000020cb100003000000dcca10003f0000007365745f636f6465000000004b1c11000300000000000000d5ca100007000000c3ca1000120000007365745f73746f726167650000000000b1ca10000500000000000000b6ca10000d00000096ca10001b0000006b696c6c5f73746f72616765000000008aca100004000000000000008eca1000080000006cca10001e000000204b696c6c20736f6d65206974656d732066726f6d2073746f726167652e6b6579735665633c4b65793e2053657420736f6d65206974656d73206f662073746f726167652e6974656d735665633c4b657956616c75653e2053657420746865206e657720636f64652e5665633c75383e2053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e7061676573753634204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b20412062696720646973706174636820746861742077696c6c20646973616c6c6f7720616e79206f74686572207472616e73616374696f6e20746f20626520696e636c756465642e53797374656d0000000000bcd010000c0000000101000000000000423111000c00000000000000c8d0100008000000000000000000000000000000000000004081110048df10000000000000000000d0d0100001000000000000000100000000000000d8d010000e00000000000000000000000611110003000000000000000000000000000000000000000000000000000000000000004081110024d110000000000000000000e8d0100001000000000000000000000000000000f0d0100013000000000000000000000003d1100006000000000000000000000000000000000000000000000000000000000000004081110024d1100000000000000000000cd110000100000000000000000000000000000014d110001000000000000000000000000611110003000000000000000000000000000000000000000000000000000000000000004081110024d11000000000000000000034d11000010000000000000000000000000000003cd1100014000000000000000000000050d1100010000000000000000000000000000000000000000000000000000000000000004081110048df1000000000000000000060d110000200000000000000010000000000000070d110000900000001010000000000001bf610000e0000000000000005f4100007000000000000000000000000000000000000004081110020d2100000000000000000007cd110000100000000000000010000000000000084d110000d0000000101000000000000061111000300000000000000d5ca100007000000000000000000000000000000000000004081110094d110000000000000000000a4d1100001000000000000000100000000000000acd110000e0000000000000000000000bad11000120000000000000000000000000000000000000000000000000000000000000040811100ccd110000000000000000000dcd1100002000000000000000100000000000000ecd110000600000000000000000000001bf610000e000000000000000000000000000000000000000000000000000000000000004081110048df10000000000000000000f4d1100001000000000000000100000000000000fcd110000a000000000000000000000005f4100007000000000000000000000000000000000000000000000000000000000000004081110020d21000000000000000000008d210000100000000000000010000000000000010d210000e000000000000000000000005f4100007000000000000000000000000000000000000000000000000000000000000004081110020d21000000000000000000030d210000100000000000000010000000000000038d210000600000000000000000000003ed210000b00000000000000000000000000000000000000000000000000000000000000408111004cd2100000000000000000005cd210000100000000000000010000000000000064d210000600000000000000000000006ad2100023000000000000000000000000000000000000000000000000000000000000004081110090d210000000000000000000a0d2100001000000000000000100000000000000a8d210000a0000000000000000000000b2d210000a0000000000000000000000000000000000000000000000000000000000000040811100bcd210000000000000000000ccd2100001000000000000000100000000000000d4d210000b0000000201010000000000dfd21000020000000000000005f410000700000000000000e1d21000210000000000000040811100fcde1000000000000000000004d310000d00000000000000010000004163636f756e744e6f6e6365543a3a496e646578b1d910001f00000045787472696e736963436f756e74000083d910002e000000416c6c45787472696e736963735765696768745765696768740000003ed9100045000000416c6c45787472696e736963734c656e2f000000000000000100000036000000eed81000500000004e6578745765696768744d756c7469706c6965725765696768744d756c7469706c6965727ad8100059000000d3d810001b000000426c6f636b4861736800000054d810002600000045787472696e736963446174610000002f00000000000000010000003100000005d810004f00000052616e646f6d4d6174657269616c2869382c205665633c543a3a486173683e292f00000000000000010000009900000048d7100069000000b1d71000540000004e756d626572000006d7100042000000506172656e74486173680000ead610001c00000045787472696e73696373526f6f7400002f00000000000000010000009a000000a5d61000450000004469676573744469676573744f663c543e0000002f00000000000000010000003100000069d610003c0000004576656e74735665633c4576656e745265636f72643c543a3a4576656e742c20543a3a486173683e3e0000002f00000000000000010000003100000041d61000280000004576656e74436f756e744576656e74496e6465782f00000000000000010000004100000013d610002e0000004576656e74546f7069637328295665633c28543a3a426c6f636b4e756d6265722c204576656e74496e646578293e00006cd3100049000000b5d3100025000000386b110000000000dad310004b00000025d410002a000000386b1100000000004fd4100054000000a3d4100051000000f4d4100039000000386b1100000000002dd510005300000080d5100053000000d3d5100040000000204d617070696e67206265747765656e206120746f7069632028726570726573656e74656420627920543a3a486173682920616e64206120766563746f72206f6620696e6465786573206f66206576656e747320696e2074686520603c4576656e74733c543e3e60206c6973742e20546865206669727374206b657920736572766573206e6f20707572706f73652e2054686973206669656c64206973206465636c6172656420617320646f75626c655f6d6170206a75737420666f7220636f6e76656e69656e6365206f66207573696e67206072656d6f76655f707265666978602e20416c6c20746f70696320766563746f727320686176652064657465726d696e69737469632073746f72616765206c6f636174696f6e7320646570656e64696e67206f6e2074686520746f7069632e205468697320616c6c6f7773206c696768742d636c69656e747320746f206c6576657261676520746865206368616e67657320747269652073746f7261676520747261636b696e67206d656368616e69736d20616e6420696e2063617365206f66206368616e67657320666574636820746865206c697374206f66206576656e7473206f6620696e7465726573742e205468652076616c756520686173207468652074797065206028543a3a426c6f636b4e756d6265722c204576656e74496e646578296020626563617573652069662077652075736564206f6e6c79206a7573742074686520604576656e74496e64657860207468656e20696e20636173652069662074686520746f70696320686173207468652073616d6520636f6e74656e7473206f6e20746865206e65787420626c6f636b206e6f206e6f74696669636174696f6e2077696c6c20626520747269676765726564207468757320746865206576656e74206d69676874206265206c6f73742e20546865206e756d626572206f66206576656e747320696e2074686520604576656e74733c543e60206c6973742e204576656e7473206465706f736974656420666f72207468652063757272656e7420626c6f636b2e20446967657374206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2045787472696e7369637320726f6f74206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2048617368206f66207468652070726576696f757320626c6f636b2e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e20536572696573206f6620626c6f636b20686561646572732066726f6d20746865206c61737420383120626c6f636b73207468617420616374732061732072616e646f6d2073656564206d6174657269616c2e205468697320697320617272616e67656420617320612072696e6720627566666572207769746820746865206069386020707265666978206265696e672074686520696e64657820696e746f20746865206056656360206f6620746865206f6c6465737420686173682e2045787472696e73696373206461746120666f72207468652063757272656e7420626c6f636b20286d61707320616e2065787472696e736963277320696e64657820746f206974732064617461292e204d6170206f6620626c6f636b206e756d6265727320746f20626c6f636b206861736865732e20546865206e65787420776569676874206d756c7469706c6965722e20546869732073686f756c6420626520757064617465642061742074686520656e64206f66206561636820626c6f636b206261736564206f6e207468652073617475726174696f6e206c6576656c2028776569676874292e20546f74616c206c656e6774682028696e2062797465732920666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2077656967687420666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2065787472696e7369637320636f756e7420666f72207468652063757272656e7420626c6f636b2e2045787472696e73696373206e6f6e636520666f72206163636f756e74732e53657373696f6e20486973746f726963616c53657373696f6e7365706f636820696e64696365732077696c6c206e6576657220726561636820325e3634206265666f726520746865206465617468206f662074686520756e6976657273653b20716564000000000000000000000000000000000000000000000000000000000000000072656163686564206d6178696d756d2064657074682c2063616e6e6f7420637265617465009b00000018000000040000009c0000009d0000009e0000009f000000a0000000a10000006e6f7420656e6f7567682067617320746f20706179206261736520696e7374616e7469617465206665656e6f7420656e6f7567682067617320746f20706179207472616e736665722066656562616c616e636520746f6f206c6f7720746f2073656e642076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e7464657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c756572656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c20666565636f6e747261637420686173206265656e206576696374656470726576696f75732f6e657874206f6e6c7920636f6e7461696e206578697374696e6720656e74697265733b20776520656e756d6572617465207573696e67206e6578743b20656e747279206578697374733b207165640000004cc7100041000000dd000000010000003a6865617070616765733a636f64657472616e73616374696f6e20626972746820626c6f636b20616e6369656e7442616265000000000000bcde10000a000000000000000000000020cb100003000000000000000000000000000000000000000000000000000000000000004081110048df10000000000000000000c8de100001000000000000000100000000000000d0de10000b0000000000000000000000dbde10001e0000000000000000000000000000000000000000000000000000000000000040811100fcde100000000000000000000cdf10000100000000000000010000000000000014df10000e000000000000000000000020cb100003000000000000000000000000000000000000000000000000000000000000004081110048df1000000000000000000024df1000030000000000000001000000000000003cdf10000b000000000000000000000020cb100003000000000000000000000000000000000000000000000000000000000000004081110048df1000000000000000000058df10000100000000000000010000000000000060df10000a00000000000000000000006adf1000080000000000000000000000000000000000000000000000000000000000000040811100f0df1000000000000000000074df10000a000000000000000100000000000000c4df10000e00000000000000000000006adf1000080000000000000000000000000000000000000000000000000000000000000040811100f0df10000000000000000000d4df100001000000000000000100000000000000dcdf10001100000000000000000000006adf1000080000000000000000000000000000000000000000000000000000000000000040811100f0df1000000000000000000000e0100001000000000000000100000045706f6368496e6465780000cde2100015000000417574686f7269746965735665633c28417574686f7269747949642c2042616265576569676874293e0000002f000000000000000100000031000000b2e210001b00000045706f63685374617274536c6f74000019e210004000000059e210003e00000097e210001b00000043757272656e74536c6f74002f00000000000000010000003500000004e210001500000052616e646f6d6e6573735b75383b2033325d00003ee010002e000000386b1100000000006ce010000b000000386b11000000000077e0100041000000b8e010003e000000f6e01000450000003be110004500000080e1100041000000c1e11000430000004e65787452616e646f6d6e657373000027e0100017000000556e646572436f6e737472756374696f6e0000002f0000000000000001000000a200000008e010001f0000002052616e646f6d6e65737320756e64657220636f6e737472756374696f6e2e204e6578742065706f63682072616e646f6d6e6573732e205468652065706f63682072616e646f6d6e65737320666f7220746865202a63757272656e742a2065706f63682e20232053656375726974792054686973204d555354204e4f54206265207573656420666f722067616d626c696e672c2061732069742063616e20626520696e666c75656e6365642062792061206d616c6963696f75732076616c696461746f7220696e207468652073686f7274207465726d2e204974204d4159206265207573656420696e206d616e792063727970746f677261706869632070726f746f636f6c732c20686f77657665722c20736f206c6f6e67206173206f6e652072656d656d626572732074686174207468697320286c696b652065766572797468696e6720656c7365206f6e2d636861696e29206974206973207075626c69632e20466f72206578616d706c652c2069742063616e20626520757365642077686572652061206e756d626572206973206e656564656420746861742063616e6e6f742068617665206265656e2063686f73656e20627920616e206164766572736172792c20666f7220707572706f7365732073756368206173207075626c69632d636f696e207a65726f2d6b6e6f776c656467652070726f6f66732e2043757272656e7420736c6f74206e756d6265722e20536c6f74206174207768696368207468652063757272656e742065706f636820737461727465642e20497420697320706f737369626c652074686174206e6f20626c6f636b2077617320617574686f7265642061742074686520676976656e20736c6f7420616e64207468652065706f6368206368616e676520776173207369676e616c6c6564206c61746572207468616e20746869732e2043757272656e742065706f636820617574686f7269746965732e2043757272656e742065706f636820696e6465782e00000000000054e310000d0000000000000020cb100003000000000000004081110064e31000000000000000000074e3100002000000000000000000000084e31000110000000000000095e31000090000000000000040811100a0e310000000000000000000b0e31000050000000000000045706f63684475726174696f6e0000002f0000000000000001000000a300000008e51000430000004be510003f0000004578706563746564426c6f636b54696d65543a3a4d6f6d656e7400002f0000000000000001000000a4000000d8e310004100000019e41000440000005de41000410000009ee4100042000000e0e410002800000020546865206578706563746564206176657261676520626c6f636b2074696d6520617420776869636820424142452073686f756c64206265206372656174696e6720626c6f636b732e2053696e636520424142452069732070726f626162696c6973746963206974206973206e6f74207472697669616c20746f20666967757265206f7574207768617420746865206578706563746564206176657261676520626c6f636b2074696d652073686f756c64206265206261736564206f6e2074686520736c6f74206475726174696f6e20616e642074686520736563757269747920706172616d657465722060636020287768657265206031202d20636020726570726573656e7473207468652070726f626162696c697479206f66206120736c6f74206265696e6720656d707479292e20546865206e756d626572206f66202a2a736c6f74732a2a207468617420616e2065706f63682074616b65732e20576520636f75706c652073657373696f6e7320746f2065706f6368732c20692e652e2077652073746172742061206e65772073657373696f6e206f6e636520746865206e65772065706f636820626567696e732e00000000000070e71000080000000000000078e71000020000000000000000000000386b110000000000000000000000000088e71000060000000000000090e71000030000000000000000000000386b1100000000000000000000000000a8e710000e00000000000000386b1100000000000000000000000000386b1100000000000000000000000000b6e710000700000000000000c0e71000020000000000000000000000386b1100000000000000000000000000d0e710000600000000000000d8e71000010000000000000000000000386b1100000000000000000000000000e0e710000900000000000000d8e71000010000000000000000000000386b1100000000000000000000000000e9e710000900000000000000d8e71000010000000000000000000000386b1100000000000000000000000000f2e710000800000000000000fce71000020000000000000000000000386b11000000000000000000000000000ce81000090000000000000018e81000020000000000000000000000386b110000000000000000000000000028e810000b0000000000000034e81000010000000000000000000000386b11000000000000000000000000003ce81000060000000000000044e81000030000000000000000000000386b1100000000000000000050726f706f73656487e81000090000006a101100070000005461626c6564000087e81000090000006a1011000700000090e810000e00000045787465726e616c5461626c6564537461727465640000006be810000f0000007ae810000d00000050617373656400006be810000f0000004e6f7450617373656443616e63656c6c6564457865637574656400006be810000f000000d33311000400000044656c65676174656400000061101100090000006110110009000000556e64656c6567617465640061101100090000005665746f6564000061101100090000005ce810000400000060e810000b00000048617368426c6f636b4e756d6265725265666572656e64756d496e646578566f74655468726573686f6c6450726f70496e6465785665633c4163636f756e7449643e44656d6f637261637920566f74654f6644656d6f63726163792044656c65676174696f6e7344656d6f6372616379205265666572656e64756d496e666f4f6644656d6f6372616379204465706f7369744f6644656d6f6372616379204469737061746368517565756544656d6f637261637920566f74657273466f7268656164206f662044656d6f63726163792044656c65676174696f6e7344656d6f6372616379205075626c696350726f7073c0e9100048000000880a00000e0000004e6f207075626c69632070726f706f73616c732077616974696e6743616e6e6f7420696e6a6563742061207265666572656e64756d207468617420656e6473206561726c696572207468616e2070726563656564696e67207265666572656e64756d00002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e727344656d6f6372616379204e65787445787465726e616c4e6f2065787465726e616c2070726f706f73616c2077616974696e6700000000000028ed1000070000000000000030ed100002000000000000000000000060ed100006000000000000000000000090ed1000060000000000000098ed1000010000000000000000000000b0ed1000060000000000000000000000e0ed10000400000000000000e4ed100002000000000000000000000014ee10000700000000000000000000004cee10000a00000000000000e4ed100002000000000000000000000058ee100007000000000000000000000090ee10001100000000000000a4ee100004000000000000000000000004ef100006000000000000000000000034ef1000100000000000000044ef10000100000000000000000000005cef10000200000000000000000000006cef100010000000000000007cef100001000000000000000000000094ef1000020000000000000000000000a4ef100019000000000000007cef1000010000000000000000000000c0ef1000020000000000000000000000d0ef10000d00000000000000e0ef100003000000000000000000000028f0100008000000000000000000000068f010000d0000000000000078f0100001000000000000000000000090f0100001000000000000000000000098f010001100000000000000acf01000010000000000000000000000c4f01000010000000000000000000000ccf010000d00000000000000dcf0100003000000000000000000000024f110000100000000000000000000002cf11000090000000000000038f1100001000000000000000000000050f1100005000000000000000000000078f110000c00000000000000386b110000000000000000000000000084f11000050000000000000000000000acf110000c0000000000000038f11000010000000000000000000000b8f11000050000000000000000000000e0f110000800000000000000e8f1100002000000000000000000000018f2100005000000000000000000000040f210000a00000000000000386b11000000000000000000000000004cf21000050000000000000070726f706f73650000000000f4f610000800000000000000fcf610001000000000000000ee2511000500000000000000f32511001500000099f9100028000000386b1100000000007e1b11000b0000002e27110008000000d3f91000200000001f1c11000c0000007365636f6e64000000000000f4f610000800000000000000c1f910001200000099f9100028000000386b1100000000007e1b11000b0000002e27110008000000d4251100100000001f1c11000c000000766f746500000000c0f31000090000000000000093f310001800000000000000e0ed1000040000000000000095f910000400000019f910004d00000066f910002f000000386b1100000000007e1b11000b0000002e27110008000000faf810001f0000001f1c11000c00000070726f78795f766f7465000068f8100054000000bcf810003e000000386b1100000000007e1b11000b0000002e27110008000000faf810001f0000001f1c11000c000000656d657267656e63795f70726f706f736500000000000000f4f610000800000000000000fcf6100010000000000000005ff8100009000000000000007ae810000d000000000000000ef610000d000000000000001bf610000e0000000000000029f6100005000000000000001bf610000e00000060f7100022000000386b11000000000082f7100058000000daf7100046000000386b11000000000020f810003f000000656d657267656e63795f63616e63656c00000000c0f3100009000000000000006be810000f0000000cf7100054000000e8f610000c00000065787465726e616c5f70726f706f736500000000f4f610000800000000000000fcf61000100000009cf610004c000000e8f610000c00000065787465726e616c5f70726f706f73655f6d616a6f726974790000002ef610005600000084f610001800000065787465726e616c5f7075736800000000000000f8f310000d0000000000000005f4100007000000000000000ef610000d000000000000001bf610000e0000000000000029f6100005000000000000001bf610000e0000000cf410005400000060f4100059000000b9f410003b000000386b110000000000f4f410003e00000032f510004b0000007df5100055000000d2f510003c0000007665746f5f65787465726e616c00000000000000f8f310000d0000000000000005f4100007000000c9f310002f00000063616e63656c5f7265666572656e64756d00000000000000c0f31000090000000000000093f3100018000000abf310001500000063616e63656c5f717565756564000000000000006ff31000040000000000000073f3100017000000000000008af3100005000000000000004e1c11000c000000000000008ff31000040000000000000093f310001800000047f31000280000007365745f70726f78790000000000000042f310000500000000000000423111000c0000001cf3100026000000386b1100000000007e1b11000b00000094f21000160000001f1c11000c00000072657369676e5f70726f7879f6f2100026000000386b1100000000007e1b11000b000000e6f21000100000001f1c11000c00000072656d6f76655f70726f7879c0f2100026000000386b1100000000007e1b11000b000000e6f21000100000001f1c11000c00000064656c656761746500000000aaf210000200000000000000423111000c00000000000000acf210000a00000000000000b6f210000a00000085f210000f000000386b1100000000007e1b11000b00000094f21000160000001f1c11000c000000756e64656c6567617465000074f2100011000000386b1100000000007e1b11000b0000002e271100080000001f1c11000c00000020556e64656c656761746520766f74652e2044656c656761746520766f74652e202d204f6e6520657874726120444220656e7472792e746f636f6e76696374696f6e436f6e76696374696f6e20436c656172207468652070726f78792e2043616c6c6564206279207468652073746173682e202d204f6e6520444220636c6561722e20436c656172207468652070726f78792e2043616c6c6564206279207468652070726f78792e205370656369667920612070726f78792e2043616c6c6564206279207468652073746173682e70726f78792043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e7768656e436f6d706163743c543a3a426c6f636b4e756d6265723e776869636877686174436f6d706163743c5265666572656e64756d496e6465783e2052656d6f76652061207265666572656e64756d2e7265665f696e646578205665746f20616e6420626c61636b6c697374207468652065787465726e616c2070726f706f73616c20686173682e70726f706f73616c5f68617368543a3a48617368205363686564756c65207468652063757272656e746c792065787465726e616c6c792d70726f706f736564206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c656420696d6d6564696174656c792e204966207468657265206973206e6f2065787465726e616c6c792d70726f706f736564207265666572656e64756d2063757272656e746c792c206f72206966207468657265206973206f6e6520627574206974206973206e6f742061206d616a6f726974792d63617272696573207265666572656e64756d207468656e206974206661696c732e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652063757272656e742065787465726e616c2070726f706f73616c2e202d2060766f74696e675f706572696f64603a2054686520706572696f64207468617420697320616c6c6f77656420666f7220766f74696e67206f6e20746869732070726f706f73616c2e202d206064656c6179603a20546865206e756d626572206f6620626c6f636b20616674657220766f74696e672068617320656e64656420696e20617070726f76616c20616e6420746869732073686f756c64206265202020656e61637465642e20496e6372656173656420746f2060456d657267656e6379566f74696e67506572696f646020696620746f6f206c6f772e766f74696e675f706572696f64543a3a426c6f636b4e756d62657264656c6179205363686564756c652061206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e205363686564756c652061207265666572656e64756d20746f206265207461626c6564206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e70726f706f73616c426f783c543a3a50726f706f73616c3e205363686564756c6520616e20656d657267656e63792063616e63656c6c6174696f6e206f662061207265666572656e64756d2e2043616e6e6f742068617070656e20747769636520746f207468652073616d65205363686564756c6520616e20656d657267656e6379207265666572656e64756d2e20546869732077696c6c206372656174652061206e6577207265666572656e64756d20666f7220746865206070726f706f73616c602c20617070726f766564206173206c6f6e6720617320636f756e74656420766f7465732065786365656420607468726573686f6c646020616e642c20696620617070726f7665642c20656e61637465642061667465722074686520676976656e206064656c6179602e204974206d61792062652063616c6c65642066726f6d206569746865722074686520526f6f74206f722074686520456d657267656e6379206f726967696e2e7468726573686f6c6420566f746520696e2061207265666572656e64756d206f6e20626568616c66206f6620612073746173682e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b20206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d204f6e65204442206368616e67652c206f6e6520444220656e7472792e20566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e566f74652050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e436f6d706163743c50726f70496e6465783e202d2054776f204442206368616e6765732c206f6e6520444220656e7472792e44656d6f63726163790000000024ff10000f000000000000000000000087e81000090000000000000000000000000000000000000000000000000000000000000040811100e4ff1000000000000000000034ff1000010000000000000001000000000000003cff10000b000000000000000000000047ff10002b0000000000000000000000000000000000000000000000000000000000000040811100a0001100000000000000000074ff1000010000000000000001000000000000007cff100009000000010100000000000087e81000090000000000000085ff1000210000000000000000000000000000000000000040811100a8ff10000000000000000000b8ff100001000000000000000000000000000000c0ff10000f00000000000000000000006be810000f0000000000000000000000000000000000000000000000000000000000000040811100e4ff10000000000000000000d0ff100001000000000000000100000000000000d8ff10000900000000000000000000006be810000f0000000000000000000000000000000000000000000000000000000000000040811100e4ff10000000000000000000f4ff100001000000000000000100000000000000fcff10001000000001010000000000006be810000f000000000000000c0011002d00000000000000000000000000000000000000408111001801110000000000000000003c00110001000000000000000000000000000000440011000d00000001010000000000001bf610000e00000000000000510011002b00000000000000000000000000000000000000408111007c00110000000000000000008c00110001000000000000000100000000000000940011000900000001010000000000006be810000f00000000000000b11a1100110000000000000000000000000000000000000040811100a00011000000000000000000b000110001000000000000000100000000000000b8001100060000000101000000000000be0011001f0000000000000095f91000040000000000000000000000000000000000000040811100e00011000000000000000000f00011000400000000000000010000000000000010011100050000000101000000000000423111000c00000000000000423111000c00000000000000000000000000000000000000408111001801110000000000000000002801110002000000000000000000000000000000380111000b0000000101010000000000423111000c00000000000000430111001a0000000000000000000000000000000000000040811100600111000000000000000000700111000100000000000000010000000000000078011100150000000000000000000000d33311000400000000000000000000000000000000000000000000000000000000000000408111005402110000000000000000009001110002000000000000000100000000000000a00111000c0000000000000000000000ac0111001c0000000000000000000000000000000000000000000000000000000000000040811100c80111000000000000000000d801110004000000000000000000000000000000f801110009000000010100000000000005f410000700000000000000010211002300000000000000000000000000000000000000408111002402110000000000000000003402110002000000000000000000000000000000440211000d000000010100000000000005f410000700000000000000d3331100040000000000000000000000000000000000000040811100540211000000000000000000640211000100000000000000010000005075626c696350726f70436f756e7400d40711003d0000005075626c696350726f70735665633c2850726f70496e6465782c20543a3a50726f706f73616c2c20543a3a4163636f756e744964293e0000b4071100200000004465706f7369744f662842616c616e63654f663c543e2c205665633c543a3a4163636f756e7449643e2900002f00000000000000010000003c00000093071100210000005265666572656e64756d436f756e7400470711004c0000004e65787454616c6c790000002f00000000000000010000004100000015071100320000005265666572656e64756d496e666f4f66285265666572656e64756d496e666f3c543a3a426c6f636b4e756d6265722c20543a3a50726f706f73616c3e29000000e80611002d000000446973706174636851756575655665633c4f7074696f6e3c28543a3a50726f706f73616c2c205265666572656e64756d496e646578293e3e2f000000000000000100000031000000b806110030000000566f74657273466f720000002f0000000000000001000000310000008f06110029000000566f74654f66285265666572656e64756d496e6465782c20543a3a4163636f756e744964290000002f0000000000000001000000360000005005110058000000a805110053000000fb05110057000000520611003d00000050726f78790000002f000000000000000100000036000000e20411004c0000002e0511002200000044656c65676174696f6e7328543a3a4163636f756e7449642c20436f6e76696374696f6e290000002f0000000000000001000000a500000092041100500000004c6173745461626c656457617345787465726e616c0000003204110056000000880411000a0000004e65787445787465726e616c28543a3a50726f706f73616c2c20566f74655468726573686f6c64292f0000000000000001000000a600000044031100560000009a03110055000000ef03110029000000180411001a000000426c61636b6c69737428543a3a426c6f636b4e756d6265722c205665633c543a3a4163636f756e7449643e292f00000000000000010000003c000000b6021100540000000a0311003a00000043616e63656c6c6174696f6e730000002f0000000000000001000000360000006c0211004a000000205265636f7264206f6620616c6c2070726f706f73616c7320746861742068617665206265656e207375626a65637420746f20656d657267656e63792063616e63656c6c6174696f6e2e2041207265636f7264206f662077686f207665746f656420776861742e204d6170732070726f706f73616c206861736820746f206120706f737369626c65206578697374656e7420626c6f636b206e756d6265722028756e74696c207768656e206974206d6179206e6f742062652072657375626d69747465642920616e642077686f207665746f65642069742e20546865207265666572656e64756d20746f206265207461626c6564207768656e6576657220697420776f756c642062652076616c696420746f207461626c6520616e2065787465726e616c2070726f706f73616c2e20546869732068617070656e73207768656e2061207265666572656e64756d206e6565647320746f206265207461626c656420616e64206f6e65206f662074776f20636f6e646974696f6e7320617265206d65743a202d20604c6173745461626c656457617345787465726e616c60206973206066616c7365603b206f72202d20605075626c696350726f70736020697320656d7074792e205472756520696620746865206c617374207265666572656e64756d207461626c656420776173207375626d69747465642065787465726e616c6c792e2046616c7365206966206974207761732061207075626c69632070726f706f73616c2e2047657420746865206163636f756e742028616e64206c6f636b20706572696f64732920746f20776869636820616e6f74686572206163636f756e742069732064656c65676174696e6720766f74652e2057686f2069732061626c6520746f20766f746520666f722077686f6d2e2056616c7565206973207468652066756e642d686f6c64696e67206163636f756e742c206b65792069732074686520766f74652d7472616e73616374696f6e2d73656e64696e67206163636f756e742e204765742074686520766f746520696e206120676976656e207265666572656e64756d206f66206120706172746963756c617220766f7465722e2054686520726573756c74206973206d65616e696e6766756c206f6e6c792069662060766f746572735f666f726020696e636c756465732074686520766f746572207768656e2063616c6c6564207769746820746865207265666572656e64756d2028796f75276c6c20676574207468652064656661756c742060566f7465602076616c7565206f7468657277697365292e20496620796f7520646f6e27742077616e7420746f20636865636b2060766f746572735f666f72602c207468656e20796f752063616e20616c736f20636865636b20666f722073696d706c65206578697374656e636520776974682060566f74654f663a3a657869737473602066697273742e204765742074686520766f7465727320666f72207468652063757272656e742070726f706f73616c2e205175657565206f66207375636365737366756c207265666572656e646120746f20626520646973706174636865642e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206e657874207265666572656e64756d20696e64657820746861742073686f756c642062652074616c6c6965642e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e6461207374617274656420736f206661722e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e00000000000000640911000f000000000000001bf610000e00000000000000408111003c0a11000000000000000000740911000500000000000000000000009c0911000c000000000000001bf610000e0000000000000040811100bc0911000000000000000000a8091100010000000000000000000000b00911000c000000000000001bf610000e0000000000000040811100bc0911000000000000000000cc091100010000000000000000000000d40911000e000000000000001d3311000c0000000000000040811100e40911000000000000000000f4091100010000000000000000000000fc09110015000000000000001bf610000e0000000000000040811100140a11000000000000000000240a11000100000000000000000000002c0a11000d000000000000001bf610000e00000000000000408111003c0a110000000000000000004c0a11000100000000000000456e6163746d656e74506572696f64009b0b11005c000000386b110000000000f70b11004c000000430c11005a0000009d0c1100270000004c61756e6368506572696f64620b110039000000566f74696e67506572696f642f0000000000000001000000a7000000340b11002e0000004d696e696d756d4465706f73697400002f0000000000000001000000a8000000e70a11004d000000456d657267656e6379566f74696e67506572696f640000002f0000000000000001000000a9000000ac0a11003b000000436f6f6c6f6666506572696f640000002f0000000000000001000000aa000000540a11005800000020506572696f6420696e20626c6f636b7320776865726520616e2065787465726e616c2070726f706f73616c206d6179206e6f742062652072652d7375626d6974746564206166746572206265696e67207665746f65642e204d696e696d756d20766f74696e6720706572696f6420616c6c6f77656420666f7220616e20656d657267656e6379207265666572656e64756d2e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e20546865206d696e696d756d20706572696f64206f66206c6f636b696e6720616e642074686520706572696f64206265747765656e20612070726f706f73616c206265696e6720617070726f76656420616e6420656e61637465642e2049742073686f756c642067656e6572616c6c792062652061206c6974746c65206d6f7265207468616e2074686520756e7374616b6520706572696f6420746f20656e73757265207468617420766f74696e67207374616b657273206861766520616e206f70706f7274756e69747920746f2072656d6f7665207468656d73656c7665732066726f6d207468652073797374656d20696e207468652063617365207768657265207468657920617265206f6e20746865206c6f73696e672073696465206f66206120766f74652e0a68110028000000dc0c1100440000004b010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f64656d6f63726163792f7372632f6c69622e7273dc0c1100440000004b0100000100000076616c756520746f6f206c6f7770726f706f73657227732062616c616e636520746f6f206c6f7763616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7365636f6e64657227732062616c616e636520746f6f206c6f776e6f7420612070726f787944656d6f63726163792043616e63656c6c6174696f6e7370726f706f73616c207374696c6c20626c61636b6c697374656470726f706f73616c20616c7265616479206d616465696e76616c696420686173686e6578742065787465726e616c2070726f706f73616c206e6f742073696d706c65206d616a6f726974796e6f2070726f706f73616c206d61646544656d6f637261637920426c61636b6c6973746e6f2065787465726e616c2070726f706f73616c756e6b6e6f776e2070726f706f73616c6964656e74697479206d6179206e6f74207665746f20612070726f706f73616c20747769636544656d6f63726163792050726f7879616c726561647920612070726f787977726f6e672070726f78796e6f742064656c656761746564756e6b6e6f776e20696e64657863616e6e6f742063616e63656c207468652073616d652070726f706f73616c20747769636570726f706f73616c206e6f7420666f756e64766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e00000000000000ac0f11000600000000000000b40f1100010000000000000000000000bc0f1100010000000000000000000000c40f11000e00000000000000d40f1100020000000000000000000000e40f1100020000000000000000000000f40f11000c000000000000000010110002000000000000000000000010101100010000000000000052657761726400006a1011000700000009111100380000004f66666c696e655761726e696e670000611011000900000006111100030000007110110052000000c3101100430000004f66666c696e65536c61736861101100090000006a101100070000001810110049000000204f6e652076616c696461746f722028616e6420697473206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e4163636f756e74496442616c616e6365204f6e652076616c696461746f722028616e6420697473206e6f6d696e61746f72732920686173206265656e20676976656e20616e206f66666c696e652d7761726e696e6720286974206973207374696c6c2077697468696e20697473206772616365292e205468652061636372756564206e756d626572206f6620736c6173686573206973207265636f726465642c20746f6f2e75333220416c6c2076616c696461746f72732068617665206265656e2072657761726465642062792074686520676976656e2062616c616e63652e5374616b696e6720426f6e6465645374616b696e672043757272656e7445726153746172745374616b696e67204e6f6d696e61746f72735374616b696e672056616c696461746f72735374616b696e67205374616b6572735374616b696e67204c65646765725374616b696e672050617965655374616b696e6720536c617368436f756e7468656164206f66205374616b696e67204e6f6d696e61746f72734c696e6b616765206973207570646174656420696e206361736520656e7472792069732072656d6f7665643b20697420616c7761797320706f696e747320746f206578697374696e67206b6579733b2071656468656164206f66205374616b696e672056616c696461746f7273000000000000008c141100040000000000000090141100030000000000000000000000d81411000f0000000000000000000000501511000a000000000000005c151100010000000000000000000000741511000e0000000000000000000000e41511000600000000000000ec15110001000000000000000000000004161100170000000000000000000000bc1611001100000000000000386b1100000000000000000000000000d016110010000000000000000000000050171100080000000000000058171100010000000000000000000000701711000b0000000000000000000000c81711000800000000000000d0171100010000000000000000000000e81711000b0000000000000000000000401811000500000000000000386b1100000000000000000000000000481811000b0000000000000000000000a01811000900000000000000ac181100010000000000000000000000c41811000b00000000000000000000001c1911000e000000000000002c191100010000000000000000000000441911000b00000000000000000000009c1911001300000000000000b0191100010000000000000000000000c8191100010000000000000000000000d01911000d00000000000000386b1100000000000000000000000000e0191100080000000000000000000000201a11001700000000000000b0191100010000000000000000000000381a1100010000000000000000000000401a11001100000000000000541a11000100000000000000000000006c1a11000100000000000000626f6e6400000000a61d11000a00000000000000b01d11002300000000000000ee2511000500000000000000f32511001500000000000000281e110005000000000000002d1e11001100000044271100590000009d27110021000000386b110000000000be27110054000000386b1100000000001228110049000000386b1100000000007e1b11000b0000005b281100350000002e27110008000000902811001a000000386b110000000000aa2811005b00000005291100490000001f1c11000c000000626f6e645f6578747261000000000000362711000e00000000000000f3251100150000000826110059000000612611000d000000386b1100000000006e26110054000000c2261100590000001b27110013000000386b110000000000bf1c110055000000386b1100000000007e1b11000b000000141d11003a0000002e27110008000000d4251100100000001f1c11000c000000756e626f6e64000000000000ee2511000500000000000000f325110015000000ff211100550000005422110040000000942211004d000000386b110000000000e1221100520000003323110030000000386b110000000000632311004f000000b22311004f000000012411003f000000386b110000000000d31d110055000000386b1100000000004024110026000000386b1100000000007e1b11000b00000066241100500000004e1d110026000000b6241100590000000f2511005c0000006b25110069000000d425110010000000e42511000a00000077697468647261775f756e626f6e646564000000f81f11004b000000386b110000000000432011004d0000009020110013000000386b110000000000d31d110055000000386b110000000000a32011001b000000386b1100000000007e1b11000b000000be201100550000001321110051000000642111003d000000a12111005e000000741d1100320000001f1c11000c00000076616c696461746500000000d71f11000500000000000000dc1f11001c0000009d1f11003a000000386b110000000000881c110037000000386b110000000000d31d110055000000386b1100000000007e1b11000b000000141d11003a0000004e1d110026000000741d1100320000001f1c11000c0000006e6f6d696e617465000000006e1f11000700000000000000751f110028000000851e110044000000386b110000000000881c110037000000386b110000000000d31d110055000000386b1100000000007e1b11000b000000c91e110049000000121f110026000000381f1100360000001f1c11000c0000006368696c6c0000003e1e110032000000386b110000000000881c110037000000386b110000000000d31d110055000000386b1100000000007e1b11000b000000141d11003a000000701e110015000000741d1100320000001f1c11000c0000007365745f706179656500000000000000281e110005000000000000002d1e1100110000005a1c11002e000000386b110000000000881c110037000000386b110000000000d31d110055000000386b1100000000007e1b11000b000000141d11003a0000004e1d110026000000741d1100320000001f1c11000c0000007365745f636f6e74726f6c6c6572000000000000a61d11000a00000000000000b01d1100230000005a1c11002e000000386b110000000000881c110037000000386b110000000000bf1c110055000000386b1100000000007e1b11000b000000141d11003a0000004e1d110026000000741d1100320000001f1c11000c0000007365745f76616c696461746f725f636f756e7400000000004b1c110003000000000000004e1c11000c0000002b1c110020000000666f7263655f6e65775f657261000000e61a11004f000000351b110049000000386b1100000000007e1b11000b000000891b110020000000a91b110045000000ee1b1100310000001f1c11000c0000007365745f6f66666c696e655f736c6173685f677261636500c21a1100240000007365745f696e76756c6e657261626c657300000000000000a71a11000a00000000000000b11a110011000000741a11003300000020536574207468652076616c696461746f72732077686f2063616e6e6f7420626520736c61736865642028696620616e79292e76616c696461746f72735665633c543a3a4163636f756e7449643e2053657420746865206f66666c696e6520736c61736820677261636520706572696f642e20466f72636520746865726520746f2062652061206e6577206572612e205468697320616c736f20666f726365732061206e65772073657373696f6e20696d6d6564696174656c792061667465722e20606170706c795f72657761726473602073686f756c64206265207472756520666f722076616c696461746f727320746f20676574207468652073657373696f6e207265776172642e2023203c7765696768743e202d20496e646570656e64656e74206f662074686520617267756d656e74732e202d205472696767657273207468652050687261676d656e20656c656374696f6e2e20457870656e7369766520627574206e6f7420757365722d636f6e74726f6c6c65642e202d20446570656e6473206f6e2073746174653a20604f287c65646765737c202a207c76616c696461746f72737c29602e2023203c2f7765696768743e2054686520696465616c206e756d626572206f662076616c696461746f72732e6e6577436f6d706163743c7533323e202852652d2973657420746865207061796d656e742074617267657420666f72206120636f6e74726f6c6c65722e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f206279207468652073746173682c206e6f742074686520636f6e74726f6c6c65722e202d20496e646570656e64656e74206f662074686520617267756d656e74732e20496e7369676e69666963616e7420636f6d706c65786974792e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732e202d2057726974657320617265206c696d6974656420746f2074686520606f726967696e60206163636f756e74206b65792e636f6e74726f6c6c65723c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f7572636520546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2062792074686520636f6e74726f6c6c65722c206e6f74207468652073746173682e706179656552657761726444657374696e6174696f6e204465636c617265206e6f2064657369726520746f206569746865722076616c6964617465206f72206e6f6d696e6174652e202d20436f6e7461696e73206f6e6520726561642e204465636c617265207468652064657369726520746f206e6f6d696e6174652060746172676574736020666f7220746865206f726967696e20636f6e74726f6c6c65722e202d20546865207472616e73616374696f6e277320636f6d706c65786974792069732070726f706f7274696f6e616c20746f207468652073697a65206f66206074617267657473602c2077686963682069732063617070656420617420604d41585f4e4f4d494e4154494f4e53602e202d20426f74682074686520726561647320616e642077726974657320666f6c6c6f7720612073696d696c6172207061747465726e2e746172676574735665633c3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f757263653e204465636c617265207468652064657369726520746f2076616c696461746520666f7220746865206f726967696e20636f6e74726f6c6c65722e707265667356616c696461746f7250726566733c42616c616e63654f663c543e3e2052656d6f766520616e7920756e6c6f636b6564206368756e6b732066726f6d207468652060756e6c6f636b696e67602071756575652066726f6d206f7572206d616e6167656d656e742e205468697320657373656e7469616c6c7920667265657320757020746861742062616c616e636520746f206265207573656420627920746865207374617368206163636f756e7420746f20646f2077686174657665722069742077616e74732e2053656520616c736f205b6043616c6c3a3a756e626f6e64605d2e202d20436f756c6420626520646570656e64656e74206f6e2074686520606f726967696e6020617267756d656e7420616e6420686f77206d7563682060756e6c6f636b696e6760206368756e6b732065786973742e2020497420696d706c6965732060636f6e736f6c69646174655f756e6c6f636b656460207768696368206c6f6f7073206f76657220604c65646765722e756e6c6f636b696e67602c2077686963682069732020696e6469726563746c7920757365722d636f6e74726f6c6c65642e20536565205b60756e626f6e64605d20666f72206d6f72652064657461696c2e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732c20796574207468652073697a65206f6620776869636820636f756c64206265206c61726765206261736564206f6e20606c6564676572602e205363686564756c65206120706f7274696f6e206f662074686520737461736820746f20626520756e6c6f636b656420726561647920666f72207472616e73666572206f75742061667465722074686520626f6e6420706572696f6420656e64732e2049662074686973206c656176657320616e20616d6f756e74206163746976656c7920626f6e646564206c657373207468616e20543a3a43757272656e63793a3a6578697374656e7469616c5f6465706f73697428292c207468656e20697420697320696e6372656173656420746f207468652066756c6c20616d6f756e742e204f6e63652074686520756e6c6f636b20706572696f6420697320646f6e652c20796f752063616e2063616c6c206077697468647261775f756e626f6e6465646020746f2061637475616c6c79206d6f7665207468652066756e6473206f7574206f66206d616e6167656d656e7420726561647920666f72207472616e736665722e204e6f206d6f7265207468616e2061206c696d69746564206e756d626572206f6620756e6c6f636b696e67206368756e6b73202873656520604d41585f554e4c4f434b494e475f4348554e4b5360292063616e20636f2d657869737473206174207468652073616d652074696d652e20496e207468617420636173652c205b6043616c6c3a3a77697468647261775f756e626f6e646564605d206e65656420746f2062652063616c6c656420666972737420746f2072656d6f766520736f6d65206f6620746865206368756e6b732028696620706f737369626c65292e2053656520616c736f205b6043616c6c3a3a77697468647261775f756e626f6e646564605d2e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204c696d697465642062757420706f74656e7469616c6c79206578706c6f697461626c6520636f6d706c65786974792e202d20456163682063616c6c20287265717569726573207468652072656d61696e646572206f662074686520626f6e6465642062616c616e636520746f2062652061626f766520606d696e696d756d5f62616c616e6365602920202077696c6c2063617573652061206e657720656e74727920746f20626520696e73657274656420696e746f206120766563746f722028604c65646765722e756e6c6f636b696e676029206b65707420696e2073746f726167652e202020546865206f6e6c792077617920746f20636c65616e207468652061666f72656d656e74696f6e65642073746f72616765206974656d20697320616c736f20757365722d636f6e74726f6c6c656420766961206077697468647261775f756e626f6e646564602e202d204f6e6520444220656e7472792e203c2f7765696768743e76616c7565436f6d706163743c42616c616e63654f663c543e3e2041646420736f6d6520657874726120616d6f756e742074686174206861766520617070656172656420696e207468652073746173682060667265655f62616c616e63656020696e746f207468652062616c616e636520757020666f72207374616b696e672e20557365207468697320696620746865726520617265206164646974696f6e616c2066756e647320696e20796f7572207374617368206163636f756e74207468617420796f75207769736820746f20626f6e642e20556e6c696b65205b60626f6e64605d206f72205b60756e626f6e64605d20746869732066756e6374696f6e20646f6573206e6f7420696d706f736520616e79206c696d69746174696f6e206f6e2074686520616d6f756e7420746861742063616e2062652061646465642e202d204f2831292e6d61785f6164646974696f6e616c2054616b6520746865206f726967696e206163636f756e74206173206120737461736820616e64206c6f636b207570206076616c756560206f66206974732062616c616e63652e2060636f6e74726f6c6c6572602077696c6c20626520746865206163636f756e74207468617420636f6e74726f6c732069742e206076616c756560206d757374206265206d6f7265207468616e2074686520606578697374656e7469616c5f6465706f7369746020646566696e656420696e207468652042616c616e636573206d6f64756c652e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20627920746865207374617368206163636f756e742e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204d6f64657261746520636f6d706c65786974792e202d20546872656520657874726120444220656e74726965732e204e4f54453a2054776f206f66207468652073746f726167652077726974657320286053656c663a3a626f6e646564602c206053656c663a3a7061796565602920617265205f6e657665725f20636c65616e656420756e6c6573732074686520606f726967696e602066616c6c732062656c6f77205f6578697374656e7469616c206465706f7369745f20616e6420676574732072656d6f76656420617320647573742e5374616b696e6700000000000000903011000e000000000000000000000006111100030000000000000000000000000000000000000000000000000000000000000040811100603311000000000000000000a030110001000000000000000100000000000000a830110015000000000000000000000006111100030000000000000000000000000000000000000000000000000000000000000040811100c03011000000000000000000d030110001000000000000000100000000000000f40f11000c0000000000000000000000d8301100070000000000000000000000000000000000000000000000000000000000000040811100e03011000000000000000000f030110001000000000000000100000000000000f8301100110000000000000000000000061111000300000000000000000000000000000000000000000000000000000000000000408111006033110000000000000000000c31110001000000000000000100000000000000143111000d0000000000000000000000b11a110011000000000000000000000000000000000000000000000000000000000000004081110018341100000000000000000024311100030000000000000001000000000000003c311100060000000101000000000000423111000c00000000000000423111000c0000000000000000000000000000000000000040811100883111000000000000000000503111000100000000000000000000000000000058311100060000000101000000000000423111000c000000000000005e3111002900000000000000000000000000000000000000408111008831110000000000000000009831110001000000000000000000000000000000a0311100050000000101000000000000423111000c000000000000002d1e1100110000000000000000000000000000000000000040811100a83111000000000000000000b831110001000000000000000100000000000000c03111000a0000000101010000000000423111000c00000000000000dc1f11001c0000000000000000000000000000000000000040811100cc3111000000000000000000dc31110001000000000000000100000000000000e43111000a0000000101010000000000423111000c00000000000000b11a1100110000000000000000000000000000000000000040811100183411000000000000000000f031110001000000000000000100000000000000f8311100070000000101000000000000423111000c00000000000000ff3111002400000000000000000000000000000000000000408111002432110000000000000000003432110004000000000000000100000000000000543211000e0000000000000000000000b11a110011000000000000000000000000000000000000000000000000000000000000004081110018341100000000000000000064321100010000000000000001000000000000006c3211000a0000000000000000000000763211000800000000000000000000000000000000000000000000000000000000000000408111006033110000000000000000008032110001000000000000000100000000000000883211000f0000000000000000000000973211000b0000000000000000000000000000000000000000000000000000000000000040811100a43211000000000000000000b432110001000000000000000100000000000000bc3211001b0000000000000000000000136511000c0000000000000000000000000000000000000000000000000000000000000040811100603311000000000000000000d832110001000000000000000100000000000000e0321100110000000000000000000000f13211000a0000000000000000000000000000000000000000000000000000000000000040811100fc32110000000000000000000c33110001000000000000000100000000000000143311000900000000000000000000001d3311000c00000000000000000000000000000000000000000000000000000000000000408111002c33110000000000000000003c33110003000000000000000100000000000000543311000a0000000101000000000000423111000c00000000000000061111000300000000000000000000000000000000000000408111006033110000000000000000007033110002000000000000000100000000000000803311000f00000000000000000000008f331100280000000000000000000000000000000000000000000000000000000000000040811100183411000000000000000000b833110002000000000000000100000000000000c83311000b0000000000000000000000d3331100040000000000000000000000000000000000000000000000000000000000000040811100d83311000000000000000000e833110001000000000000000100000000000000f03311000a0000000000000000000000fa3311001d00000000000000000000000000000000000000000000000000000000000000408111001834110000000000000000002834110001000000000000000100000056616c696461746f72436f756e7400000e3b11002a0000004d696e696d756d56616c696461746f72436f756e740000002f0000000000000001000000ab000000be3a11005000000050657262696c6c002f0000000000000001000000ac0000006a3a1100540000004f66666c696e65536c61736847726163650000001c3a11004e000000496e76756c6e657261626c657300000048391100560000009e39110053000000f13911002b000000426f6e646564543a3a4163636f756e744964000008391100400000004c65646765725374616b696e674c65646765723c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e002f000000000000000100000036000000b73811005100000050617965650000002f0000000000000001000000360000007e3811003900000056616c696461746f727300002f0000000000000001000000ad0000002d381100510000004e6f6d696e61746f72730000d4371100590000005374616b6572734578706f737572653c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e002f0000000000000001000000ae00000017371100530000006a37110046000000386b110000000000b03711002400000043757272656e74456c65637465640000d83611003f00000043757272656e74457261457261496e6465780000c13611001700000043757272656e7445726153746172744d6f6d656e744f663c543e00002f000000000000000100000035000000a33611001e00000043757272656e74457261537461727453657373696f6e496e646578006f3611003400000043757272656e744572615265776172647345726152657761726473002f0000000000000001000000af0000002c36110043000000536c6f745374616b6542616c616e63654f663c543e0000002f000000000000000100000030000000b03511004c000000386b110000000000fc35110030000000536c617368436f756e7400002f0000000000000001000000410000003c35110057000000933511001d000000526563656e746c794f66666c696e655665633c28543a3a4163636f756e7449642c20543a3a426c6f636b4e756d6265722c20753332293e00c0341100550000001535110027000000466f7263654e6577457261626f6f6c002f0000000000000001000000360000007934110047000000426f6e646564457261735665633c28457261496e6465782c2053657373696f6e496e646578293e002f00000000000000010000003100000030341100490000002041206d617070696e672066726f6d207374696c6c2d626f6e646564206572617320746f207468652066697273742073657373696f6e20696e646578206f662074686174206572612e205472756520696620746865206e6578742073657373696f6e206368616e67652077696c6c2062652061206e657720657261207265676172646c657373206f6620696e6465782e204d6f737420726563656e742060524543454e545f4f46464c494e455f434f554e546020696e7374616e6365732e202857686f206974207761732c207768656e20697420776173207265706f727465642c20686f77206d616e7920696e7374616e63657320746865792077657265206f66666c696e6520666f72292e20546865206e756d626572206f662074696d6573206120676976656e2076616c696461746f7220686173206265656e207265706f72746564206f66666c696e652e205468697320676574732064656372656d656e746564206279206f6e652065616368206572612074686174207061737365732e2054686520616d6f756e74206f662062616c616e6365206163746976656c79206174207374616b6520666f7220656163682076616c696461746f7220736c6f742c2063757272656e746c792e2054686973206973207573656420746f20646572697665207265776172647320616e642070756e6973686d656e74732e205265776172647320666f72207468652063757272656e74206572612e205573696e6720696e6469636573206f662063757272656e7420656c6563746564207365742e205468652073657373696f6e20696e646578206174207768696368207468652063757272656e742065726120737461727465642e20546865207374617274206f66207468652063757272656e74206572612e205468652063757272656e742065726120696e6465782e205468652063757272656e746c7920656c65637465642076616c696461746f7220736574206b65796564206279207374617368206163636f756e742049442e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e74207468617420697320696e20616374696f6e207269676874206e6f772e20596f752063616e27742069746572617465207468726f7567682076616c696461746f727320686572652c2062757420796f752063616e2066696e64207468656d20696e207468652053657373696f6e206d6f64756c652e2054686973206973206b6579656420627920746865207374617368206163636f756e742e20546865206d61702066726f6d206e6f6d696e61746f72207374617368206b657920746f2074686520736574206f66207374617368206b657973206f6620616c6c2076616c696461746f727320746f206e6f6d696e6174652e20546865206d61702066726f6d202877616e6e616265292076616c696461746f72207374617368206b657920746f2074686520707265666572656e636573206f6620746861742076616c696461746f722e2057686572652074686520726577617264207061796d656e742073686f756c64206265206d6164652e204b657965642062792073746173682e204d61702066726f6d20616c6c2028756e6c6f636b6564292022636f6e74726f6c6c657222206163636f756e747320746f2074686520696e666f20726567617264696e6720746865207374616b696e672e204d61702066726f6d20616c6c206c6f636b65642022737461736822206163636f756e747320746f2074686520636f6e74726f6c6c6572206163636f756e742e20416e792076616c696461746f72732074686174206d6179206e6576657220626520736c6173686564206f7220666f726369626c79206b69636b65642e20497427732061205665632073696e63652074686579277265206561737920746f20696e697469616c697a6520616e642074686520706572666f726d616e636520686974206973206d696e696d616c2028776520657870656374206e6f206d6f7265207468616e20666f757220696e76756c6e657261626c65732920616e64207265737472696374656420746f20746573746e6574732e204e756d626572206f6620696e7374616e636573206f66206f66666c696e65207265706f727473206265666f726520736c617368696e6720626567696e7320666f722076616c696461746f72732e20536c6173682c207065722076616c696461746f7220746861742069732074616b656e20666f72207468652066697273742074696d6520746865792061726520666f756e6420746f206265206f66666c696e652e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e00000000a83b11000e00000000000000136511000c0000000000000040811100b83b11000000000000000000c83b1100010000000000000000000000d03b11000f0000000000000076321100080000000000000040811100e03b11000000000000000000f03b1100010000000000000053657373696f6e7350657245726100002f000000000000000100000037000000313c11001c000000426f6e64696e674475726174696f6e002f0000000000000001000000b0000000f83b110039000000204e756d626572206f6620657261732074686174207374616b65642066756e6473206d7573742072656d61696e20626f6e64656420666f722e204e756d626572206f662073657373696f6e7320706572206572612e5374616b696e672043757272656e74456c656374656400803c110048000000880a00000e0000000000000000000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e72735374616b696e6720536c6f745374616b65000000003e110019000000203e110048000000bb0100002d000000b10000002800000004000000b2000000b30000000000000000000000b40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f6f70732f61726974682e72730a68110028000000803e1100420000009f020000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f7374616b696e672f7372632f6c69622e727300009040110023000000664011002a000000803e1100420000009f02000001000000636f6e74726f6c6c657220616c72656164792070616972656463616e206e6f7420626f6e6420776974682076616c7565206c657373207468616e206d696e696d756d2062616c616e6365737461736820616c726561647920626f6e6465646e6f74206120636f6e74726f6c6c65726e6f74206120737461736863616e206e6f74207363686564756c65206d6f726520756e6c6f636b206368756e6b73756e7374616b65207468726573686f6c6420746f6f206c617267650a09090909090909096865616420697320736574207768656e20666972737420656c656d656e7420697320696e73657274656420616e6420756e736574207768656e206c61737420656c656d656e742069732072656d6f7665643b0a09090909090909096966206865616420697320536f6d65207468656e20697420706f696e747320746f206578697374696e67206b65793b207165640a09090909090909746172676574732063616e6e6f7420626520656d7074795374616b696e6720496e76756c6e657261626c6573696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64653a205f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e007041110048000000ab010000230000007041110048000000ac01000023000000494111001c000000646c110018000000df0300000d0000000041110049000000870200001d000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f736f72742e7273617373657274696f6e206661696c65643a206d6964203c3d206c656e00000000000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e727300411100490000009d0000003a0000000041110049000000a4000000300000004f6666636861696e206572726f723a207375626d697474696e67207472616e73616374696f6e206661696c6564214f6666636861696e206572726f723a206465636f64696e6720417574686f726974794964206661696c6564214f6666636861696e206572726f723a206465636f64696e6720576f726b6572537461747573206661696c6564214f6666636861696e206572726f723a2065787472696e736963206372656174696f6e206661696c6564214f6666636861696e206572726f723a207369676e696e67206661696c6564214f6666636861696e206572726f723a206665746368696e67206e6574776f726b207374617465206661696c656421496d4f6e6c696e65204c6173744e6577457261537461727454726561737572792050726f706f73616c436f756e74547265617375727920417070726f76616c73000000000000010000000200000004000000080000001000000044656d6f6372616379205075626c696350726f70436f756e7444656d6f6372616379205265666572656e64756d436f756e7444656d6f6372616379204e65787454616c6c7944656d6f6372616379204c6173745461626c656457617345787465726e616c746f6f206d616e7920696e737472756374696f6e73000000c44311002400000059691100170000004102000009000000547269656420746f20736872696e6b20746f2061206c6172676572206361706163697479436f6e7472616374204761735370656e74436f6e74726163742043757272656e745363686564756c65436f6e7472616374204163636f756e74436f756e7465726578745f7365745f73746f726167656578745f6765745f73746f726167656578745f63616c6c6578745f6372656174656578745f72657475726e6578745f63616c6c65726578745f616464726573736578745f6761735f70726963656578745f6761735f6c6566746578745f62616c616e63656578745f76616c75655f7472616e736665727265646578745f72616e646f6d6578745f6e6f776578745f64697370617463685f63616c6c6578745f736372617463685f73697a656578745f736372617463685f636f70796578745f6465706f7369745f6576656e746578745f7365745f72656e745f616c6c6f77616e63656578745f72656e745f616c6c6f77616e63656578745f7072696e746c6e6578745f626c6f636b5f6e756d6265724e6f6e2d656d7074792066756e6374696f6e20626f64792065787065637465640000264611000f000000354611000200000037461100030000009845110030000000c84511005e0000007d00000005000000617373657274696f6e206661696c65643a20636f6e746578742e6672616d655f737461636b2e69735f656d70747928292f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e312e302f7372632f66756e632e7273417420696e737472756374696f6e202840293a2052657475726e207479706573206c656e6774682073686f756c642062652030206f72203143616e2774206465636f6465207761736d20636f64654d6f64756c65206973206e6f742076616c69646d6f64756c65206465636c6172657320696e7465726e616c206d656d6f72796d756c7469706c65207461626c6573206465636c617265647461626c652065786365656473206d6178696d756d2073697a6520616c6c6f776564757365206f6620666c6f6174696e6720706f696e74207479706520696e2066756e6374696f6e20747970657320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e206c6f63616c7320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e20676c6f62616c7320697320666f7262696464656e67617320696e737472756d656e746174696f6e206661696c6564737461636b2068656967687420696e737472756d656e746174696f6e206661696c656463616c6c6465706c6f796465706c6f792066756e6374696f6e2069736e2774206578706f72746564756e6b6e6f776e206578706f72743a20657870656374696e67206f6e6c79206465706c6f7920616e642063616c6c2066756e6374696f6e7366756e6374696f6e206861732061206e6f6e2d6578697374656e7420747970656578706f72742072656665727320746f206e6f6e2d6578697374656e742066756e6374696f6e657870656374656420612066756e6374696f6e656e74727920706f696e7420706f696e747320746f20616e20696d706f727465642066756e6374696f6e656e74727920706f696e74206861732077726f6e67207369676e617475726563616c6c2066756e6374696f6e2069736e2774206578706f727465646572726f722073657269616c697a696e6720696e737472756d656e746564206d6f64756c65b44a11001e000000d24a11001f00000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2071656466756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2066756e6374696f6e5f73656374696f6e5f6c656e203d3d20636f64655f73656374696f6e5f6c656e3b2071656400009a4a11001a000000754a11000a0000007f4a11001b00000073746172742066756e6374696f6e20657870656374656420746f20686176652074797065205b5d202d3e205b5d000000644a110011000000444a110020000000244a110020000000fc491100280000007365676d656e74206f66667365742073686f756c642072657475726e20493332746f6f206d616e79206d656d6f727920726567696f6e7320696e20696e6465782073706163653a20746f6f206d616e79207461626c657320696e20696e6465782073706163653a20747279696e6720746f20696d706f7274206d757461626c6520676c6f62616c206475706c6963617465206578706f72742046756e6374696f6e20232072656164696e672f76616c69646174696f6e206572726f723a204d697373696e6720626f647920666f722066756e6374696f6e206c656e677468206f662066756e6374696f6e2073656374696f6e206973202c207768696c65206c656e206f6620636f64652073656374696f6e20697320000000104b11001c0000002c4b11005a0000004d00000028000000ffffffff48617368207461626c65206361706163697479206f766572666c6f772f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f6861736862726f776e2d302e312e382f7372632f7261772f6d6f642e72736d616b655f746f705f6672616d655f706f6c796d6f72706869632069732063616c6c6564207769746820656d707479206672616d6520737461636b000000b50000000c00000004000000b6000000746869732066756e6374696f6e2063616e27742062652063616c6c6564207769746820656d707479206672616d6520737461636b4d6973706c6163656420656c736520696e737472756374696f6e00004c4d110047000000934d110005000000104d110037000000474d110005000000dd4c110017000000d44c110009000000264f110014000000bc4c110018000000d44c110009000000264f1100140000008c4c11001d000000a94c1100130000003781110001000000546f6f206c61726765206d656d6f727920616c69676e6d656e7420325e20286578706563746564206174206d6f737420547279696e6720746f2075706461746520676c6f62616c20206f66207479706520547279696e6720746f20757064617465206c6f63616c20416e79537065636966696300380000000400000004000000b70000004c6162656c7320696e2062725f7461626c6520706f696e747320746f20626c6f636b206f6620646966666572656e742074797065733a2020616e6420496620626c6f636b20776974686f757420656c736520726571756972656420746f2068617665204e6f526573756c7420626c6f636b20747970652e2042757420697420686173202074797065a84d110018000000c04d11000b000000556e657870656374656420737461636b20686569676874202c20657870656374656420547279696e6720746f2061636365737320706172656e74206672616d6520737461636b2076616c7565732e0000084e1100170000001f4e11001600000045787065637465642076616c7565206f66207479706520206f6e20746f70206f6620737461636b2e20476f7420000000404e110007000000537461636b3a200000000100ca4e110024000000a04e110006000000a64e11000e000000b44e1100160000007c4e110024000000a04e1100060000006d6178696d756d206d656d6f72792073697a65206d757374206265206174206d6f7374202070616765736d6178696d756d206c696d697420206973206c657373207468616e206d696e696d756d20696e697469616c206d656d6f72792073697a65206d757374206265206174206d6f7374200000004f110026000000264f110014000000547279696e6720746f20696e697469616c697a65207661726961626c65206f6620747970652020776974682076616c7565206f66207479706520496e69742065787072657373696f6e2073686f756c6420616c776179732062652077697468206c656e67746820324e6f6e20636f6e7374616e74206f70636f646520696e20696e69742065787072d14f110007000000e34f110022000000d14f110007000000d84f11000b00000045787072657373696f6e20646f65736e277420656e647320776974682060656e6460206f70636f6465476c6f62616c20206973206d757461626c6520646f65736e277420657869737473206f72206e6f742079657420646566696e65640000001850110010000000285011000f0000004d656d6f727920617420696e6465782020646f65736e27742065786973747300485011000f000000285011000f0000005461626c6520617420696e6465782000f957110012000000285011000f000000785011000e000000285011000f0000005479706520617420696e646578200000e650110010000000285011000f000000b850110010000000d85011000e000000b850110010000000c850110010000000457870656374656420676c6f62616c2020746f20626520696d6d757461626c6520746f206265206d757461626c65476c6f62616c20617420696e646578206e6f6e2d656d70747920737461636b206578706563746564000020511100200000004051110012000000747279696e6720746f206765742076616c756520617420706f736974696f6e20206f6e20737461636b206f662073697a6520636865636b656420636f75706c65206f66206c696e65732061626f7665007851110015000000657863656564656420737461636b206c696d697420000000380000000400000004000000b80000004c6f63616c732072616e6765206e6f7420696e2033322d6269742072616e6765d851110022000000fa511100150000000f52110007000000547279696e6720746f20616363657373206c6f63616c207769746820696e64657820207768656e20746865726520617265206f6e6c7920206c6f63616c734672616d6569735f706f6c796d6f7270686963000000380000000400000004000000b9000000656e645f61726974790000003800000004000000040000001d0000006272616e63685f617269747973746172745f6865696768744e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e000000945511000a00000046756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e46756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e64885511000c000000f05411000b000000737461636b206d757374206265206e6f6e2d656d70747900e55411000b0000009e54110006000000737461636b206f766572666c6f774172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e64009754110007000000905311006c000000c800000011000000000000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e362e322f7372632f737461636b5f6865696768742f6d61785f6865696768742e72736d61785f686569676874707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768742f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e362e322f7372632f737461636b5f6865696768742f6d61785f6865696768742e72737472756e633a20707573683a20e054110005000000747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f77706f703a20756e726561636861626c65706f705f6672616d653a20636f6e74726f6c20737461636b20697320656d707479636f6e74726f6c20737461636b206f75742d6f662d626f756e64734055110048000000820a00000a000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f736c6963652f6d6f642e7273707573685f6672616d653a2066756e635f6964783a2066756e635f737461636b5f636f7374732069736e27742079657420636f6d70757465643b0a0909090944696420796f752063616c6c2060636f6d707574655f737461636b5f636f737473603f546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e6473a0561100650000002301000017000000785611002500000043616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a200000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e362e322f7372632f737461636b5f6865696768742f6d6f642e727366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b2071656466756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a09090909716564f9571100120000000b5811000f000000cc5711000a000000d657110014000000ea5711000f0000005369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e656446756e6374696f6e20617420696e64657820206973206e6f7420646566696e6564656e76676173305811005800000088000000160000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e362e322f7372632f6761732e72737372632f6c6962616c6c6f632f7665632e727300b45811001c0000008858110013000000c604000009000000617373657274696f6e206661696c65643a20656e64203c3d206c656ee85811001e0000008858110013000000b303000009000000617373657274696f6e206661696c65643a20696e646578203c3d206c656e4e6f6e65536f6d650000380000000400000004000000ba000000e559110012000000f75911000c0000006066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a090909097165644174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b66756e6374696f6e207769746820696478202069736e277420666f756e644636345265696e74657270726574493634556e726561636861626c654e6f70426c6f636b00380000000400000004000000bb0000004c6f6f704966456c7365456e644272003800000004000000040000001d0000004272496642725461626c6500380000000400000004000000bc00000052657475726e43616c6c43616c6c496e6469726563740000380000000400000004000000bd00000044726f7053656c6563744765744c6f63616c5365744c6f63616c5465654c6f63616c476574476c6f62616c536574476c6f62616c4933324c6f61644936344c6f61644633324c6f61644636344c6f61644933324c6f616438534933324c6f616438554933324c6f61643136534933324c6f61643136554936344c6f616438534936344c6f616438554936344c6f61643136534936344c6f61643136554936344c6f61643332534936344c6f616433325549333253746f726549363453746f726546333253746f726546363453746f726549333253746f72653849333253746f7265313649363453746f72653849363453746f7265313649363453746f7265333243757272656e744d656d6f727947726f774d656d6f7279493332436f6e737400380000000400000004000000be000000493634436f6e7374380000000400000004000000bf000000463332436f6e7374463634436f6e73743800000004000000040000000400000049333245717a49333245714933324e654933324c74534933324c74554933324774534933324774554933324c65534933324c655549333247655349333247655549363445717a49363445714936344e654936344c74534936344c74554936344774534936344774554936344c65534936344c655549363447655349363447655546333245714633324e654633324c7446333247744633324c65463332476546363445714636344e654636344c7446363447744636344c654636344765493332436c7a49333243747a493332506f70636e744933324164644933325375624933324d756c493332446976534933324469765549333252656d5349333252656d55493332416e644933324f72493332586f7249333253686c4933325368725349333253687255493332526f746c493332526f7472493634436c7a49363443747a493634506f70636e744936344164644936345375624936344d756c493634446976534936344469765549363452656d5349363452656d55493634416e644936344f72493634586f7249363453686c4936345368725349363453687255493634526f746c493634526f74724633324162734633324e65674633324365696c463332466c6f6f724633325472756e634633324e656172657374463332537172744633324164644633325375624633324d756c4633324469764633324d696e4633324d6178463332436f70797369676e4636344162734636344e65674636344365696c463634466c6f6f724636345472756e634636344e656172657374463634537172744636344164644636345375624636344d756c4636344469764636344d696e4636344d6178463634436f70797369676e493332577261704936344933325472756e63534633324933325472756e63554633324933325472756e63534636344933325472756e6355463634493634457874656e6453493332493634457874656e64554933324936345472756e63534633324936345472756e63554633324936345472756e63534636344936345472756e6355463634463332436f6e7665727453493332463332436f6e7665727455493332463332436f6e7665727453493634463332436f6e766572745549363446333244656d6f7465463634463634436f6e7665727453493332463634436f6e7665727455493332463634436f6e7665727453493634463634436f6e766572745549363446363450726f6d6f74654633324933325265696e746572707265744633324936345265696e746572707265744636344633325265696e746572707265744933324e6f526573756c7456616c756500380000000400000004000000b7000000463634493332493634463332496e76616c696444617461547261696c696e6744617461556e6578706563746564456f66086011000b000000492f4f204572726f723a20000a681100280000002c6011005000000087000000090000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d73616e64626f782f7372632f2e2e2f776974686f75745f7374642e72730a681100280000002c601100500000009000000009000000436f756e63696c20446573697265645365617473436f756e63696c20566f7465436f756e74436f756e63696c204e657874566f746572536574436f756e63696c20566f746572436f756e74436f756e63696c2043616e646964617465436f756e74000000000000007c6111000e000000000000008c611100010000000000000000000000946111000100000000000000000000009c6111000600000000000000386b1100000000000000000000000000a4611100010000000000000000000000ac6111000700000000000000386b1100000000000000000000000000b461110001000000000000004e6577417574686f72697469657300002f621100170000000b621100240000005061757365640000e461110027000000526573756d656400bc611100280000002043757272656e7420617574686f726974792073657420686173206265656e20726573756d65642e2043757272656e7420617574686f726974792073657420686173206265656e207061757365642e204e657720617574686f726974792073657420686173206265656e206170706c6965642e5665633c28417574686f7269747949642c20753634293e4772616e64706146696e616c69747920417574686f72697469657354696d657374616d7020496e697469616c697a656462616265736c6f74436f756c64206e6f74206465636f64652072657175657374656420696e686572656e742074797065214241424520696e686572656e742064617461206e6f7420666f756e64426162652045706f6368496e6465784261626520417574686f726974696573426162652045706f63685374617274536c6f74426162652043757272656e74536c6f74426162652052616e646f6d6e65737342616265204e65787452616e646f6d6e6573734261626520556e646572436f6e737472756374696f6e5374616b696e672056616c696461746f72436f756e745374616b696e67204d696e696d756d56616c696461746f72436f756e745374616b696e67204f66666c696e65536c61736847726163655374616b696e672043757272656e744572615374616b696e672043757272656e74457261537461727453657373696f6e496e6465785374616b696e672043757272656e74457261526577617264735374616b696e6720466f7263654e65774572615374616b696e6720426f6e64656445726173417574686f727368697020446964536574556e636c657353657373696f6e2043757272656e74496e64657853657373696f6e204368616e67656453657373696f6e205175657565644368616e6765640000000000786411000a00000000000000846411000100000000000000000000008c64110002000000000000004e657753657373696f6e0000136511000c0000009c64110055000000f164110022000000204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e53657373696f6e496e64657853657373696f6e2053746f72656452616e676500002f0000000000000001000000c0000000c1000000c20000002f0000000000000001000000c0000000c1000000c200000074696d737461703054696d657374616d7020696e686572656e742064617461206973206e6f742070726f76696465642e496e76616c69642074696d657374616d7020696e686572656e74206461746120656e636f64696e672e54696d657374616d702044696455706461746500000000286611001000000000000000386b110000000000000000000000000038661100010000000000000000000000406611000f00000000000000386b110000000000000000000000000050661100010000000000000045787472696e736963537563636573736d6611002500000045787472696e7369634661696c656400586611001500000020416e2065787472696e736963206661696c65642e20416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e53797374656d2045787472696e736963436f756e7453797374656d20416c6c45787472696e7369637357656967687453797374656d20416c6c45787472696e736963734c656e53797374656d204e6578745765696768744d756c7469706c69657253797374656d2045787472696e7369634461746153797374656d204576656e74436f756e7448617368206e6f7420657175616c0000406711001900000060671100500000005800000022000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f67656e657269632f6572612e72736578745f6368696c645f73746f726167655f726f6f74206e657665722072657475726e73207533323a3a6d61785f76616c75653b2071656452756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e67696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64652f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d636f6465632d342e312e332f7372632f636f6465632e7273000000a86811002d000000d56811000c000000e168110003000000617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a20ec6811003400000064657374696e6174696f6e20616e6420736f7572636520736c69636573206861766520646966666572656e74206c656e67746873646c110018000000470800000900000048691100110000005969110017000000ed020000050000006361706163697479206f766572666c6f777372632f6c6962616c6c6f632f7261775f7665632e7273e0691100460000006301000013000000380000000400000004000000c3000000c4000000c50000006120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f72002f0000000000000001000000c6000000000000002f72757374632f633739386466666163396463386338323337346462343866356234373436393063633665393638362f7372632f6c6962636f72652f666d742f6d6f642e7273010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020202020202020202020202020202020202020202020202020202020203030303030303030303030303030303040404040400000000000000000000000000486b110020000000686b1100120000002f0000000000000001000000c7000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e64657820697320303030313032303330343035303630373038303931303131313231333134313531363137313831393230323132323233323432353236323732383239333033313332333333343335333633373338333934303431343234333434343534363437343834393530353135323533353435353536353735383539363036313632363336343635363636373638363937303731373237333734373537363737373837393830383138323833383438353836383738383839393039313932393339343935393639373938393900007c6c110006000000826c110022000000646c110018000000040a0000050000007372632f6c6962636f72652f736c6963652f6d6f642e7273696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e67746820c46c110016000000da6c11000d000000646c1100180000000a0a000005000000736c69636520696e64657820737461727473206174202062757420656e6473206174206030785b2e2e2e5d00ae6d11000b0000006280110016000000e76c110001000000986d110016000000e307000009000000408011000e0000004e801100040000005280110010000000e76c110001000000986d110016000000e707000005000000008011002b0000002b801100150000007a01000015000000ae6d11000b000000b96d110026000000df6d110008000000e76d110006000000e76c110001000000986d110016000000f4070000050000007372632f6c6962636f72652f7374722f6d6f642e72736279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f662060000000366e110002000000206e1100160000005404000011000000206e110016000000480400002800000000000000000000007372632f6c6962636f72652f666d742f6d6f642e72732e2e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000f8030000000000000000000000000000000000000000000000000000000000000000feffffffffbfb6000000000000000000ff070000000000f8ffff0000010000000000000000000000c09f9f3d0000000002000000ffffff0700000000000000000000c0ff01000000000000f80f20e07911004a000000307c110000020000307e11003a00000000010203040506070809080a0b0c0d0e0f10111213140215161718191a1b1c1d1e1f2002020202020202020202210202020202020202020202020202222324252602270228020202292a2b022c2d2e2f300202310202023202020202020202023302023402020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023502360237020202020202020238023902020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023a3b3c020202023d02023e3f4041424344454602020247020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202024802020202020202020202024902020202023b020001020202020302020202040205060202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020207020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200010305050606030706080809110a1c0b190c140d120e0d0f0410031212130916011705180219031a071c021d011f1620032b042c022d0b2e01300331023201a702a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f0040d1145496465808184b2bcbebfd5d7f0f183858ba4a6bebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f747596972f5f262e2fa7afb7bfc7cfd7df9a409798308f1fc0c1ceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab351e1580e003190801042f043404070301070607110a500f1207550802041c0a090308030703020303030c0405030b06010e15053a0311070605100757070207150d500443032d03010411060f0c3a041d255f206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a061f414c042d0374083c030f033c0738082b0582ff1118082f112d032010210f808c048297190b158894052f053b07020e180980b030740c80d61a0c0580ff0580b605240c9bc60ad23010848d033709815c1480b80880c73035040a06380846080c06740b1e035a0459098083181c0a16094808808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0006010103010402080809020a050b02100111041205131114021502170219041c051d0824016a036b02bc02d102d40cd509d602d702da01e005e102e802ee20f004f906fa020c273b3e4e4f8f9e9e9f060709363d3e56f3d0d104141836375657bd35cecfe01287898e9e040d0e11122931343a4546494a4e4f64655a5cb6b71b1ca8a9d8d909379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a22253e3fc5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d00c72a3a4cbcc6e6f5e227b0503042d036504012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a81261f808128082a808617094e041e0f430e19070a0647092709750b3f412a063b050a0651060105100305808b602048080a80a65e22450b0a060d1339070a362c041080c03c64530c0180a0451b4808531d398107460a1d03474937030e080a0639070a81361980c7320d839b66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b654b0439071140041c97f80882f3a50d811f3103110408818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b80d52d031a040281703a0501850080d7294c040a04028311444c3d80c23c06010455051b3402810e2c04640c560a0d035d033d391d0d2c040907020e06809a83d60a0d030b05740c59070c140c0438080a0628081e527703310380a60c14040305030d06856a000000c0791100200000002700000019000000c0791100200000002800000020000000c0791100200000002a00000019000000c0791100200000002b00000018000000c0791100200000002c0000002000000000000000000000007372632f6c6962636f72652f756e69636f64652f626f6f6c5f747269652e72730000c0fbef3e00000000000e0000000000000000000000000000f8fffbffffff0700000000000014fe21fe000c00000002000000000000501e2080000c00004006000000000000108639020000002300be2100000c0000fc02000000000000d01e20c0000c0000000400000000000040012080000000000011000000000000c0c13d60000c0000000200000000000090443060000c00000003000000000000581e2080000c00000000845c8000000000000000000000f207807f000000000000000000000000f21f003f000000000000000000030000a002000000000000fe7fdfe0fffeffffff1f40000000000000000000000000e0fd66000000c301001e006420002000000000000000e00000000000001c0000001c0000000c0000000c00000000000000b03f40fe0f200000000000380000000000006000000000020000000000008701040e00008009000000000000407fe51ff89f000000000000ff7f0f0000000000f0170400000000f80f00030000003c3b00000000000040a303000000000000f0cf000000f7fffd211003fffffffffffffffb00100000000000000000ffffffff01000000000000800300000000000000008000000000ffffffff0000000000fc00000000000600000000000000000080f73f000000c0000000000000000000000300440800006000000030000000ffff038000000000c03f000080ff030000000000070000000000c833000000002000000000000000007e660008100000000000100000000000009dc1020000000030400000000000202100000000004000000000ffff0000ffff00000000000000000001000000020003000000000000000000000000000000000000000000000000000004000005000000000000000006000000000000000007000008090a000b0c0d0e0f000010111200001314151600001718191a1b001c0000001d0000000000001e1f202100000000002200230024252600000000270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002829000000000000000000000000000000002a2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000002d2e00002f0000000000000000000000000000000000000000000000000000000000003031320000000000000000000000000000000000000000003300000029000000000000340000000000000000000000000000000000000000000000350036000000000000000000000000000000000000000000000000000037380000383838390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000001000000000000000000c0076ef0000000000087000000006000000000000000f0000000c0ff01000000000002000000000000ff7f0000000000008003000000000078060700000080ef1f000000000000000800030000000000c07f001e000000000000000000000080d34000000080f8070000030000000000005801008000c01f1f0000000000000000ff5c00004000000000000000000000f9a50d000000000000000000000000803cb00100003000000000000000000000f8a70100000000000000000000000028bf00000000e0bc0f0000000000000080ff060000f00c01000000fe0700000000f87980007e0e0000000000fc7f03000000000000000000007fbf0000fcfffffc6d000000000000007eb4bf000000000000000000a3000000000000000000000018000000000000001f000000000000007f0000800000000000000080070000000000000000600000000000000000a0c307f8e70f0000003c00001c00000000000000ffffffffffff7ff8ffffffffff1f2000100000f8feff00007ffffff9db0700000000000000f0000000007f0000000000f00700000000000000000000ffffffffffffffffffffffffffffffffffff000063616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c75657372632f6c6962636f72652f6f7074696f6e2e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f66206066616c736574727565426f72726f774572726f72426f72726f774d75744572726f720000386b1100000000002b801100150000008e04000005000000386b110000000000c4801100020000003a200000d8801100150000003c040000050000007372632f6c6962636f72652f726573756c742e727320202020207b202c20207b0a000000c80000000c00000004000000c9000000ca000000cb0000002c0a0000380000000400000004000000cc000000cd000000ce000000207d7d28280a2c290a5d5b4572726f720041c082c6000b08000000000000000000d79003046e616d6501ce9003d704000e6578745f626c616b65325f323536011f6578745f6765745f616c6c6f63617465645f6368696c645f73746f7261676502176578745f636c6561725f6368696c645f73746f72616765030f6578745f7365745f73746f72616765040c6578745f74776f785f31323805196578745f6765745f616c6c6f63617465645f73746f7261676506166578745f73616e64626f785f6d656d6f72795f6e6577071b6578745f73616e64626f785f6d656d6f72795f74656172646f776e08176578745f73616e64626f785f696e7374616e746961746509126578745f73616e64626f785f696e766f6b650a1d6578745f73616e64626f785f696e7374616e63655f74656172646f776e0b146578745f6765745f73746f726167655f696e746f0c116578745f636c6561725f73746f726167650d166578745f6b696c6c5f6368696c645f73746f726167650e106578745f636c6561725f7072656669780f166578745f6368696c645f73746f726167655f726f6f74100e6578745f7072696e745f7574663811156578745f7365745f6368696c645f73746f7261676512166578745f73616e64626f785f6d656d6f72795f67657413166578745f73616e64626f785f6d656d6f72795f73657414126578745f737232353531395f76657269667915126578745f656432353531395f766572696679160d6578745f7072696e745f68657817156578745f6c6f63616c5f73746f726167655f67657418216578745f6c6f63616c5f73746f726167655f636f6d706172655f616e645f736574190a6578745f7075626b65791a116578745f6e6574776f726b5f73746174651b086578745f7369676e1c166578745f7375626d69745f7472616e73616374696f6e1d156578745f6c6f63616c5f73746f726167655f7365741e106578745f73746f726167655f726f6f741f186578745f73746f726167655f6368616e6765735f726f6f74200b6578745f74776f785f363421236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74220d6578745f7072696e745f6e756d230a6578745f6d616c6c6f6324086578745f6672656525693c636f72653a3a697465723a3a61646170746572733a3a46696c7465724d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a686135376361333065383863303365303426693c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c616c6c6f633a3a7665633a3a496e746f497465723c543e3e3e3a3a737065635f657874656e643a3a6833373139666330653134623738636436270c5f5f727573745f616c6c6f63280e5f5f727573745f7265616c6c6f63290e5f5f727573745f6465616c6c6f632a08727573745f6f6f6d2b34616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68336430333339633338393539363364642c693c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c616c6c6f633a3a7665633a3a496e746f497465723c543e3e3e3a3a737065635f657874656e643a3a68666465363930626535643534353335662d4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68313930363035356636656634383237362e5d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68323435356333626435643931376463372f3d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a683830383935343231326364636362353530633c7061726974795f636f6465633a3a636f6465633a3a436f6d706163745265663c7533323e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6861653539633130346438353133613637313d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6861326361663333656666326237333732327c6e6f64655f72756e74696d653a3a5f494d504c5f454e434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a656e636f64655f746f3a3a6835633263313064386662343437643537333d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6861376564663762316162326163643437343d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6866613865343765633933663536666432353d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6866616630326139373163346561326261362d616c6c6f633a3a7665633a3a5665633c543e3a3a72657461696e3a3a68313264383737303031386466653032333736636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a683863356337376530636566356239316638443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68343262303431353366346265353836383948616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303161313636363462353235323061643a4b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68663764316263323333653933356434373b4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68326461353465626366663537666563623c796e6f64655f72756e74696d653a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a6465636f64653a3a68393636393230613235616638643962363d30636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68343861333664316238316265333563653e36636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a68356364313639613635616238353965393f4e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6833363566626164393361653031316662404e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837316361626362323361376461623764414e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837366163313032323131663866333733424e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837366432313166353166623965376535434e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6838356533343365643362656139623361444f3c616c6c6f633a3a7665633a3a5665633c75383e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6839653666323565383838303562306638454e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6838653162663830323038623436323862464e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6861656661353936643166623837656439474e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6862616338653862656565356632616538484e3c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68663366396461396132336437353666354999013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68383635343265656636313566636131354a513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68356130336335333262653737623464394b513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68383163363735636233376362643435384c513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68636637353230666433393733623732394d3373726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7374616b6572733a3a68613032373064313462303632633031664e2e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a68643935376630653162613762346162644f6c3c73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c486173683e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a683530626630633838373135643038613150723c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683432346533633966643965353666383051753c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6836303438386636313863323464616261525d3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7536343e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830363032666566393830393762343861535e3c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c753132383e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683366333530343539333033356663666354633c7061726974795f636f6465633a3a636f6465633a3a436f6d706163745265663c7536343e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683038643361663639353837313639653555443c636f72653a3a666d743a3a417267756d656e747320617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a686566323037386633376634356236613156303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838306262653634343531326431353032572d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a68626563663738613764313663316663655829636f72653a3a70616e69636b696e673a3a70616e69633a3a683861643532323536383465376335666159643c7061726974795f636f6465633a3a636f6465633a3a436f6d706163745265663c753132383e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68646262326435373236386334653436375a303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68306663393031333831336461313064325b3d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68383831313733353133393938363536355c3d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a68663565393639663138373231616135665d367061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a68633433653166343632633166303232365e4473726d6c5f737570706f72743a3a7472616974733a3a5369676e6564496d62616c616e63653c422c503e3a3a6d657267653a3a68393961636662653066623534346133385f4e73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573743c486173683e3a3a636f6e766572745f66697273743a3a6864663130346139623139623564343238607a3c636f72653a3a697465723a3a61646170746572733a3a46696c7465724d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a7b7b636c6f737572657d7d3a3a686464386166653364373833613466363561bc017375627374726174655f7072696d6974697665733a3a6f6666636861696e3a3a5f494d504c5f454e434f44455f464f525f4f70617175654e6574776f726b53746174653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a6f6666636861696e3a3a4f70617175654e6574776f726b53746174653e3a3a656e636f64655f746f3a3a683864653337646339656532636163646662593c73726d6c5f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732073726d6c5f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a683765333337393936323566663435303863663c73726d6c5f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732073726d6c5f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a7b7b636c6f737572657d7d3a3a6864363435393936323564393661643362647d3c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6761733a3a68613365643138333131633165303431656589013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f73746f726167653a3a68643532333765626565386262646162346689013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f73746f726167653a3a68373830316462666232383639633365396782013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c3a3a68613836663537336437383362323836346884013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6372656174653a3a68326132393766353731373666386361326984013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72657475726e3a3a68356466383631343361653432386562366a84013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c65723a3a68386132303764613038646361303032386b85013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f616464726573733a3a68393631313338353961323437343534396c87013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f70726963653a3a68663338646437666630316265323433666d86013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f6c6566743a3a68653238626430613136333234663737636e85013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f62616c616e63653a3a68633235333030353435363561303231616f8f013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f76616c75655f7472616e736665727265643a3a68373239396531613762306235393139397084013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72616e646f6d3a3a68386230343966393830626561396630347181013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6e6f773a3a6863356634376663366532666365326363728b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f64697370617463685f63616c6c3a3a6839366164373461323632303534303837738a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f73697a653a3a6864363536323266343863303236666239748a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f636f70793a3a6866623732393936366436646236353066758b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6465706f7369745f6576656e743a3a68633864333539353230333061333532307690013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f72656e745f616c6c6f77616e63653a3a6865346536313364303366316231626364778c013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72656e745f616c6c6f77616e63653a3a68353239636230386335303534313937367885013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7072696e746c6e3a3a6836623535393535386661346339653736798a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f626c6f636b5f6e756d6265723a3a68316365326162663363373165346338657a3273725f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a68356134386464313632363132383634357b4573726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a746f5f657865637574696f6e5f726573756c743a3a68366565343861623838353831666630307c135f5f727573745f616c6c6f635f7a65726f65647da7017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f4445434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a6465636f64653a3a68343530373665613734316439633232317e643c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a68303930356635623465623032383638317f34636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68666661376637663531656636613535368001303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68303333356131383037343065326233648101303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68613432353462303530376636356239388201313c73747220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834336239616334336136363337613934830189013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f6372656174696e673a3a686433613133633364616236393537616384013573726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a6765743a3a686261616264646563653365626462363885018d013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6d616b655f667265655f62616c616e63655f62653a3a683563616137313734316335333937353386013573726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a6765743a3a683464373234623632323533336661633887017f3c73726d6c5f696e64696365733a3a4d6f64756c653c543e2061732073726d6c5f73797374656d3a3a4f6e4e65774163636f756e743c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6e65775f6163636f756e743a3a686465373063346364396166633432623988014073726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6576656e745f696e64657865643a3a686433643562663333343338323266626289013f73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f667265655f62616c616e63653a3a68373837306238356533356562373234328a013873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a68653364393136363537613365336232368b013673726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6b696c6c5f73746173683a3a68363338323138363461313337653137398c01453c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a6765743a3a68393061613361653732633833656639338d01d5013c73726d6c5f73657373696f6e3a3a4e6578744b6579733c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a67656e657261746f723a3a53746f72616765446f75626c654d61703c616c6c6f633a3a7665633a3a5665633c75383e2c3c542061732073726d6c5f73657373696f6e3a3a54726169743e3a3a56616c696461746f7249642c3c542061732073726d6c5f73657373696f6e3a3a54726169743e3a3a4b6579733e3e3a3a6b65795f666f723a3a68316239363465623039623463346132308e013773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68633766633938653035376633333530628f01cf013c73726d6c5f73657373696f6e3a3a4b65794f776e65723c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a67656e657261746f723a3a53746f72616765446f75626c654d61703c616c6c6f633a3a7665633a3a5665633c75383e2c287533322c20616c6c6f633a3a7665633a3a5665633c75383e292c3c542061732073726d6c5f73657373696f6e3a3a54726169743e3a3a56616c696461746f7249643e3e3a3a6b65795f666f723a3a6832353734656439663437656665366662900181013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a77697468647261773a3a683765636562373662383465393430366691018c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a656e737572655f63616e5f77697468647261773a3a683935333330336237353137646136643992013e73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a76657374696e675f62616c616e63653a3a683038396261373831343933393664343293013473726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6c6f636b733a3a683864613465376434306434633132323094013573726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a6765743a3a6862343536656135666434613534336564950186013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a746f74616c5f62616c616e63653a3a68376534653632323434633361613564659601653c73726d6c5f62616c616e6365733a3a54616b65466565733c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a683137353630656536396263363164333797014b73725f7072696d6974697665733a3a7472616974733a3a4163636f756e744964436f6e76657273696f6e3a3a696e746f5f6163636f756e743a3a686437643561323437653936343338323398013573726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a617574686f723a3a683339353630386434306535366633363899013d73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a68386630396366306366633562363166329a013f73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a68366338316362376438353434333664639b016f3c73726d6c5f62616c616e6365733a3a5f5f476574427974655374727563744672656542616c616e63653c542c493e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68363634653735366135323539653534659c014373726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f72657365727665645f62616c616e63653a3a68373633383762663065306136613933399d014873726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68363163646335643166613233316130619e01593c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f72616765446f75626c654d61703c4b312c4b322c563e3e3a3a72656d6f76655f7072656669783a3a68666332656331616339616533373238659f018e013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f696e746f5f6578697374696e673a3a6836343734656565626631616462323833a0014273726d6c5f636f6e7472616374733a3a72656e743a3a7472795f65766963745f6f725f616e645f7061795f72656e743a3a6838393064333938626561646466353532a101483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a696e736572743a3a6864373666326632313961373465366630a2012e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6837613261353064316536613633333539a3013c73726d6c5f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6835326137393065313637653833353630a4013e73726d6c5f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6837653761323665343030333039643361a5014773726d6c5f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863393961633631393662646166633363a6018c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a657874656e645f6c6f636b3a3a6836663666396631663235363035646265a701483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a696e736572743a3a6839643635656336376635656131633538a80189013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f6c6f636b3a3a6831376262623835373466386234353634a90149636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a6863623838333863316264623130623561aa012f636f72653a3a666d743a3a6e756d3a3a696d703a3a666d745f7536343a3a6839663433396331306235306661323566ab0135636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a6838303465663539383063333530396330ac018a013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a726573657276653a3a6832666663656134306236326365313862ad018c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a756e726573657276653a3a6835303762386634643561356339336231ae014373726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6835353135623762323533613661313033af014e73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863353237363563363832333466303030b0019c013c73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a57696e646f7753697a6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865326138353762393238303937326531b101493c73726d6c5f696d5f6f6e6c696e653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6830643964303130633531373464376137b201c6013c73726d6c5f696d5f6f6e6c696e653a3a5265636569766564486561727462656174733c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a67656e657261746f723a3a53746f72616765446f75626c654d61703c7533322c3c542061732073726d6c5f696d5f6f6e6c696e653a3a54726169743e3a3a417574686f7269747949642c616c6c6f633a3a7665633a3a5665633c75383e3e3e3a3a6b65795f666f723a3a6839666162343066636163363438666538b3013d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6835636338646430373363316466383730b4018c013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4f6e496e697469616c697a653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6862353162313535666137343830656531b5013573726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a6765743a3a6835636365313535316465373165343638b6014073726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a63616e6469646174655f7265675f696e666f3a3a6832373433366465363333363863636664b7013873726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a616c6c5f766f746572733a3a6865376465623636613036333563346364b8013a73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a617070726f76616c735f6f663a3a6862356366623966646431326362343134b901ab023c73726d6c5f656c656374696f6e733a3a566f746572496e666f4f663c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c73726d6c5f656c656374696f6e733a3a566f746572496e666f3c3c3c542061732073726d6c5f656c656374696f6e733a3a54726169743e3a3a43757272656e63792061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a42616c616e63653e3e3e3a3a6765743a3a6831326661383262363539366434343230ba018e013c73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572733a3a6863656133623466363866353031346137bb013773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6837366535353966323933386565373462bc01bc013c73726d6c5f656c656374696f6e733a3a566f746572733c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c7533322c616c6c6f633a3a7665633a3a5665633c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3e3e3a3a6765743a3a6831656136663334656630636666373762bd013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6832386162326161326664313362653432be013e73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838396534323930613036383532316361bf01713c73726d6c5f656c656374696f6e733a3a5f5f4765744279746553747275637443616e646964617465436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834353035376464383562306231303133c0014773726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6836393765613834396437376665333936c10199013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a564f5445525f5345545f53495a4544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839666233326632353861666432393464c20197013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e67506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864323236346132656331623566666433c3019e013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a496e6163746976654772616365506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834343861363466376433346165346563c40195013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4361727279436f756e7444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833323038376632623932366330353438c50194013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e6746656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862666235346331666336643035383166c60195013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e67426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835396333333633306664303535383639c70198013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616e646964616379426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835306436353364353736306636663333c801493c73726d6c5f656c656374696f6e733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6862313838373164656434333234353339c9015d3c73726d6c5f656c656374696f6e733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6865623237373936363537376332616332ca01323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6831666533363132333331313638633334cb013e73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a646f5f7365745f617070726f76616c733a3a6831623765636666336534616135336566cc013473726d6c5f696e64696365733a3a4d6f64756c653c543e3a3a656e756d5f7365743a3a6866613936323364346331613731636561cd013a73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a72656d6f76655f766f7465723a3a6839646330343430376563653138376565ce01483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a696e736572743a3a6834346562313437633932326265303632cf01793c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6832663762353865313534386536353861d001793c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6866343935363530383330653161313765d1017b3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6866643430616431306566633961633266d2017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6863303037346238366565616666666133d30180013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6864393037393837623738363764356263d401743c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6865636138346635343737616165636630d501723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832666162346632393762633738393362d601613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833343835613264643835383431636332d701723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6839656363306337636437383038323737d801483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a696e736572743a3a6837363131623933613539323766346231d901613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6863646339396163383037623662316336da014d73726d6c5f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a696e7374616e74696174653a3a6832386263643136653763303735623063db013173726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a72616e646f6d3a3a6835626633356265346662393261616566dc0127636f72653a3a7374723a3a66726f6d5f757466383a3a6830386430613533636364333636383366dd017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6835303462306465336135333763313630de014b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6838346466386135383335633337333363df0148616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6830613564653661326333656633346165e0012d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6865616138303137356633383063613361e1014673726d6c5f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a63616c6c3a3a6861303336313832306535346562393361e2017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6832656534383537613666386661386334e3017f3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6865616365323935303530343734363264e40181013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6839626533333032656563316461643338e50184013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6837666339623464643564653636666165e601783c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6838356631373164656563363033336438e701367061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6865366538646366383963393164383733e8013a73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6835313661376532386333333139343162e9013c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6835396665663231653832316339333063ea01663c73726d6c5f6772616e6470613a3a5f5f4765744279746553747275637453746174653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837636539336431333136393762366139eb014173726d6c5f737570706f72743a3a7472616974733a3a496d62616c616e63653a3a6d617962655f73756273756d653a3a6861393365353238393933316362383966ec013b73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6864316463633936373665393831316535ed013d73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6862653963626362376434633964363963ee014673726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6835333132373733363164353661346664ef018e013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4275726e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836306564613365323036363061346138f00195013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5370656e64506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863623665323938376635303361653937f10196013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a50726f706f73616c426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834633263343366353835343865633133f2013673726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a70726f706f73616c733a3a6837353937346665653933353466353965f3013773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6837626461616565326462313031336137f4014f73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e3a3a7365745f62616c616e63653a3a6833383666633233353830333065353239f5015c3c73726d6c5f74726561737572793a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6835303363326164363635633065383333f6013b73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a7363686564756c655f6368616e67653a3a6832633035326438376533663134326634f70130636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6834353035636165666339373038373732f801633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6830353463613161343333316134343562f901683c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a73697a655f68696e743a3a6835346530646462616330383561633239fa013e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6831623935356631303935383134306330fb01693c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6862303434633932643539306564396465fc01613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6839623462643566353137353466323766fd014b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6838633162393638623437653339643037fe01aa017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f454e434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a656e636f64655f746f3a3a6838663038613532313138663338346335ff013a73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683834376431616439393133353538633780023c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a683434313938383563633762383063623781024573726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6831653962326534666561326361353039820299013c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a44454455505f4b45595f50524546495844656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a686639643163336137393264633134353083028c013c73726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a54776f783634436f6e6361742061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654861736865723e3a3a686173683a3a683164626261313264323064653436316184023973726d6c5f636f6e7472616374733a3a7761736d3a3a636f64655f63616368653a3a6c6f61643a3a683264643638373532626636626134376585024273726d6c5f636f6e7472616374733a3a7761736d3a3a707265706172653a3a707265706172655f636f6e74726163743a3a68306335343562343937666534366438628602a5013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e2061732073725f7072696d6974697665733a3a7472616974733a3a436865636b61626c653c4c6f6f6b75703e3e3a3a636865636b3a3a68666538656361633632383338353936328702b3013c73726d6c5f73797374656d3a3a426c6f636b486173683c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265722c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a486173683e3e3a3a6765743a3a68343431663362346533343335343861358802cf017375627374726174655f636f6e73656e7375735f626162655f7072696d6974697665733a3a6469676573743a3a5f494d504c5f4445434f44455f464f525f526177426162655072654469676573743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f636f6e73656e7375735f626162655f7072696d6974697665733a3a6469676573743a3a526177426162655072654469676573743e3a3a6465636f64653a3a683037313535396534633038343031363689023573726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a6765743a3a68393666656334636533303439306538668a023673726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a74616b653a3a68366231633530646430346231333463628b02673c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a68323233383038663965353761356432338c023273726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a626f6e6465643a3a68386434613934326262666536326333618d02c9023c73726d6c5f7374616b696e673a3a4c65646765723c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c73726d6c5f7374616b696e673a3a5374616b696e674c65646765723c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c3c542061732073726d6c5f7374616b696e673a3a54726169743e3a3a43757272656e63792061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a42616c616e63653e3e3e3a3a6765743a3a68373038356335343662636132396435658e026f3c73725f7072696d6974697665733a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c486173683e206173207061726974795f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68393162623365343663353534323132398f02800173726d6c5f64656d6f63726163793a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f64656d6f63726163793a3a43616c6c3c543e3e3a3a6465636f64653a3a68653736633238363934363832396632309002840173726d6c5f636f6c6c6563746976653a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a6465636f64653a3a68653231663834313361313066313634669102800173726d6c5f636f6e7472616374733a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6e7472616374733a3a43616c6c3c543e3e3a3a6465636f64653a3a68366163336136623765636339306135359202870173726d6c5f636f6c6c6563746976653a3a5f494d504c5f454e434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a656e636f64655f746f3a3a68323335653561653030363565396561349302880173726d6c5f636f6e7472616374733a3a5f494d504c5f454e434f44455f464f525f5363686564756c653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6e7472616374733a3a5363686564756c653e3a3a656e636f64655f746f3a3a686562633839646631373665653164653894022b616c6c6f633a3a736c6963653a3a6d657267655f736f72743a3a68313463626638636433356132306266319502443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68363865366439316135393139346230319602463c73726d6c5f73797374656d3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68386266663463613331373663343263639702443c73726d6c5f626162653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68663664393738646663633837376133659802473c73726d6c5f696e64696365733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68313663623861346338646234313334349902473c73726d6c5f7374616b696e673a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68373666633963373334666261336461359a02493c73726d6c5f64656d6f63726163793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68303431353366306437383936366461329b024c3c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68326666376631336164376163353738649c02493c73726d6c5f636f6e7472616374733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a68333135656332616632303137313131659d027e6e6f64655f72756e74696d653a3a5f494d504c5f454e434f44455f464f525f4576656e743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a656e636f64655f746f3a3a68643763656231616366303439653433329e029c0173726d6c5f636f6c6c6563746976653a3a5f494d504c5f454e434f44455f464f525f5261774576656e743a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6c6c6563746976653a3a5261774576656e743c486173682c4163636f756e7449642c493e3e3a3a656e636f64655f746f3a3a68386634353235316432393239363762389f023e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7375646f3a3a6830386133316462373566343330376236a002406e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73797374656d3a3a6864613235613331643933323561306635a102416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f696e64696365733a3a6830646162326362666463313439353061a202426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f62616c616e6365733a3a6838323134323562646137346134663963a302416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7374616b696e673a3a6839613264663133306238666132323335a402416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73657373696f6e3a3a6831656130653737366464353437353263a502436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f64656d6f63726163793a3a6864303336633430386134353234373864a6024e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f6c6c6563746976655f496e7374616e6365313a3a6832396437623861636430646431663531a702436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f656c656374696f6e733a3a6864316262316639616565353031323836a802416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6772616e6470613a3a6839363135363934636266656563346462a902426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f74726561737572793a3a6866326661643637386264666634373730aa02436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f6e7472616374733a3a6865636666393337666661353935366132ab02436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f696d5f6f6e6c696e653a3a6865396637336636353965323164343131ac02653c6e6f64655f72756e74696d653a3a43616c6c2061732073725f7072696d6974697665733a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a6865366434613766316565633561663865ad02583c6e6f64655f72756e74696d653a3a43616c6c2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6862353331636238353865323938363930ae02583c73726d6c5f626162653a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6863353536316237633731306632633539af025e3c73726d6c5f617574686f72736869703a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6832646632666438336632656164396338b0025b3c73726d6c5f696e64696365733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6862376666346265626463386465616132b1025b3c73726d6c5f7374616b696e673a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6832303035636562333032366431636664b2025d3c73726d6c5f64656d6f63726163793a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6838656636323030356664393836613861b302603c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6863366537316138333437616237393437b402603c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6863623464333939326163376432636533b5025d3c73726d6c5f636f6e7472616374733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6835356337656461323135336366373732b6023973726d6c5f7375646f3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6865366235396363376330656539613636b7023773726d6c5f7375646f3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6833366437346636343139653935303735b802613c73726d6c5f7375646f3a3a5f5f476574427974655374727563744b65793c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830653237323634646338323863393962b9027173726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a696e697469616c697a655f626c6f636b3a3a6830343433383838616235343662356438ba023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6832613339366565346635393436316338bb0286013c28412c20422c20432c20442c20452c20462c20472c20482c20492c204a2c204b2c204c2c204d2c204e2c204f2c20502c2051292061732073725f7072696d6974697665733a3a7472616974733a3a4f6e496e697469616c697a653c4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6862643866356436373132643933333864bc027973726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a6170706c795f65787472696e7369635f776974685f6c656e3a3a6837666661346335666566636666356439bd020c436f72655f76657273696f6ebe0212436f72655f657865637574655f626c6f636bbf024173725f7072696d6974697665733a3a67656e657269633a3a656e636f64655f776974685f7665635f7072656669783a3a6861343833323533633862386230396162c0026c3c73725f7072696d6974697665733a3a7472616974733a3a426c616b6554776f3235362061732073725f7072696d6974697665733a3a7472616974733a3a486173683e3a3a656e756d6572617465645f747269655f726f6f743a3a6835613864386165636232643332343062c1023873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6862306162646235623134643465353630c20282013c28412c20422c20432c20442c20452c20462c20472c20482c20492c204a2c204b2c204c2c204d2c204e2c204f2c20502c2051292061732073725f7072696d6974697665733a3a7472616974733a3a4f6e46696e616c697a653c4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a6834613038313634316331363332643861c3023373726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a66696e616c697a653a3a6863353864366166643031653665613764c40215436f72655f696e697469616c697a655f626c6f636bc502114d657461646174615f6d65746164617461c602603c7061726974795f636f6465633a3a636f6465633a3a436f6d706163743c7533323e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6862313136333934333262366238323036c702433c5b75385d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6865326333656130663331616664363434c802623c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6865383930373662353839373366393932c902623c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6831326337313436376537633230336666ca02623c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6866356463356164333636313531353030cb02623c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6835623233303931303264376564333539cc021c426c6f636b4275696c6465725f6170706c795f65787472696e736963cd021b426c6f636b4275696c6465725f66696e616c697a655f626c6f636bce0220426c6f636b4275696c6465725f696e686572656e745f65787472696e73696373cf023873726d6c5f74696d657374616d703a3a657874726163745f696e686572656e745f646174613a3a6861663838366238613533323434616164d0021c426c6f636b4275696c6465725f636865636b5f696e686572656e7473d10218426c6f636b4275696c6465725f72616e646f6d5f73656564d2022b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6ed3025673725f7072696d6974697665733a3a7472616e73616374696f6e5f76616c69646974793a3a56616c69645472616e73616374696f6e3a3a636f6d62696e655f776974683a3a6831333237373835313963356563373134d402214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b6572d502214772616e6470614170695f6772616e6470615f70656e64696e675f6368616e6765d602204772616e6470614170695f6772616e6470615f666f726365645f6368616e6765d7021e4772616e6470614170695f6772616e6470615f617574686f726974696573d80214426162654170695f737461727475705f64617461d9020d426162654170695f65706f6368da0218436f6e73656e7375734170695f617574686f726974696573db023d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830626630326362356431343231643563dc023d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6833326332313137616131313964646462dd02be0173726d6c5f636f6e7472616374733a3a5f494d504c5f454e434f44455f464f525f526177416c697665436f6e7472616374496e666f3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6e7472616374733a3a526177416c697665436f6e7472616374496e666f3c436f6465486173682c42616c616e63652c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6830333031396235396230633565303563de023c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6835653738313263326535383766336138df023e73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6832653332306130366534306263373333e00230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6830303138366630366366636233393965e1026b3c73726d6c5f636f6e7472616374733a3a5f5f4765744279746553747275637447617350726963653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831323937653934626234623331393138e202713c73726d6c5f636f6e7472616374733a3a5f5f47657442797465537472756374436f6e7472616374496e666f4f663c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831356663633937373139383066663961e302723c73726d6c5f636f6e7472616374733a3a5f5f4765744279746553747275637443757272656e745363686564756c653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830373336343365316532386638386636e4024773726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6830303134653761653838393666656431e50298013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426c6f636b4761734c696d697444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836323933353364633134333962386431e60297013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d617856616c756553697a6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831363531353935303832653862363433e70293013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178446570746844656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833633730323537643734663966303434e80296013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616c6c4261736546656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837643534633062333230353030386132e90296013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a436f6e747261637446656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831383738366232346535343339303562ea029d013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5472616e73616374696f6e4279746546656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864323130333138383966623833626166eb029a013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53757263686172676552657761726444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839643636363739303462633066303161ec029c013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744465706f7369744f666673657444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837303438303530373033373134653739ed0296013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744279746546656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839653032303039643933303461333136ee029c013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53746f7261676553697a654f666673657444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836653631633863663736303163666534ef029b013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a546f6d6273746f6e654465706f73697444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839376335613137306432663734346430f0029e013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5369676e6564436c61696d48616e646963617044656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833326135613063303533336232346537f102850173726d6c5f636f6e7472616374733a3a5f494d504c5f4445434f44455f464f525f5363686564756c653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6e7472616374733a3a5363686564756c653e3a3a6465636f64653a3a6831383266623166313336663762316166f202cc013c73726d6c5f636f6c6c6563746976653a3a566f74696e673c542c493e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a486173682c73726d6c5f636f6c6c6563746976653a3a566f7465733c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3e3a3a6765743a3a6837643339613135396634613638326239f3028c0173726d6c5f636f6c6c6563746976653a3a5f494d504c5f4445434f44455f464f525f566f7465733a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6c6c6563746976653a3a566f7465733c4163636f756e7449643e3e3a3a6465636f64653a3a6832643432393434303730333636636233f4023f73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6835323366313938366530646630643836f5024173726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6832653365636438323863383739393535f6024173726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6837336431363862656265313532663737f702463c616c6c6f633a3a626f7865643a3a426f783c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6830643762653937613330343763653735f8023973726d6c5f636f6e7472616374733a3a6761733a3a726566756e645f756e757365645f6761733a3a6838313866393632316339316230343537f90234636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f6e7461696e733a3a6831303365623135656535646564646531fa023873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6830383262663632343263306632623461fb02cc013c73726d6c5f636f6c6c6563746976653a3a566f74696e673c542c493e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a486173682c73726d6c5f636f6c6c6563746976653a3a566f7465733c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3e3a3a6765743a3a6861656437373063336565313436653663fc026f7061726974795f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f7220284a2c204b293e3a3a6465636f64653a3a6861643334666633636666366665316235fd023c73726d6c5f696e64696365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6862336662666537393032306265393735fe02483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a696e736572743a3a6834386165363866363430643637633930ff024573726d6c5f636f6e7472616374733a3a7761736d3a3a707265706172653a3a436f6e74726163744d6f64756c653a3a6e65773a3a68373437356366353665323338356534318003467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a6833326461336131663335633534626538810348616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a683637346166653166306130323465343082033c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a68336630636663326637346565656337618303537061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a7265736f6c76655f747970655f7265663a3a68383163333338666361303832363762378403a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a686664643761346163616662643161303785033a707761736d5f7574696c733a3a72756c65733a3a496e737472756374696f6e547970653a3a6f703a3a686633303131633431356339376365353886032d616c6c6f633a3a7665633a3a5665633c543e3a3a696e736572743a3a68363636643938316464366132376430638703507061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a707573685f66756e6374696f6e3a3a6862613763333530303062636130303664880330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a683932363665303964363138393234383089033c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a68333739383539653330333963393636388a036b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a68623164636337303363343663623964638b033c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68623635383930326631373535393638638c033e73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68663835666539373737653832616264358d03703c73726d6c5f617574686f72736869703a3a5f5f47657442797465537472756374446964536574556e636c65733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68343130303364663439323339376665318e034773726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68333034663035323735396230316264348f0398013c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a686239363539613438323161636661376490033d73726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683130663030303861393865653633333791033f73726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68663765613765666566616631393237359203423c5b545d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68663965633961656539353233393630339303f0013c73726d6c5f7374616b696e673a3a5f5f6c696e6b65645f6d61705f64657461696c735f666f725f6e6f6d696e61746f72735f646f5f6e6f745f7573653a3a456e756d657261746f723c532c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c28616c6c6f633a3a7665633a3a5665633c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e2c2054293e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a68663836376561643438393337303834339403b20173726d6c5f7374616b696e673a3a5f494d504c5f4445434f44455f464f525f5f5f4c696e6b616765466f724e6f6d696e61746f7273446f4e6f745573653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f7374616b696e673a3a5f5f4c696e6b616765466f724e6f6d696e61746f7273446f4e6f745573653c4b65793e3e3a3a6465636f64653a3a686566626161663766313061613930656195036a636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653c413e20666f7220266d757420463e3a3a63616c6c5f6f6e63653a3a683136363036366137303432666462353096034a73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6164645f7265776172645f706f696e74735f746f5f76616c696461746f723a3a683735656331323130653264613130363497033673726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6c6f673a3a686133343062373339343239343636396698038d0173726d6c5f73797374656d3a3a5f494d504c5f454e434f44455f464f525f4576656e745265636f72643a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f73797374656d3a3a4576656e745265636f72643c452c543e3e3a3a656e636f64655f746f3a3a6831383165303465376138323761633563990330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68396130643239356566333862333764399a033973726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68626338333337653864313264346236349b033b73726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68386563303065326165306565653331659c03693c73726d6c5f73797374656d3a3a5f5f47657442797465537472756374426c6f636b486173683c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68356632616561336465623162303632369d036e3c73726d6c5f73797374656d3a3a5f5f4765744279746553747275637452616e646f6d4d6174657269616c3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68613438386465323261623362626564359e034473726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a68303539396532356662316566326537339f033873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6837356266613036323466393030326231a0035373725f7072696d6974697665733a3a50657262696c6c3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a7b7b636c6f737572657d7d3a3a6837346130386235616561303662323764a1035373725f7072696d6974697665733a3a50657262696c6c3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a7b7b636c6f737572657d7d3a3a6865383661363338393838616435346161a2033173726d6c5f636f6e7472616374733a3a657865633a3a7472616e736665723a3a6862663830353466313834383466353839a30330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6861666139633866303530303439646130a40386013c73726d6c5f7374616b696e673a3a4d6f64756c653c543e2061732073726d6c5f73657373696f6e3a3a4f6e53657373696f6e456e64696e673c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f73657373696f6e5f656e64696e673a3a6832613234666264303663303234333532a5033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f65787465726e616c3a3a6833356531373132666666373466393063a6033b73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f7075626c69633a3a6863383234336161666464663737653334a7033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a7265666572656e64756d5f696e666f3a3a6838313864663962306133383239316334a803a9013c73726d6c5f64656d6f63726163793a3a566f74657273466f723c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c7533322c616c6c6f633a3a7665633a3a5665633c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3e3a3a6765743a3a6834613163653538373963373732656365a9033573726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f74655f6f663a3a6861366663323631343066353861643433aa033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a64656c6567617465645f766f7465733a3a6866636666623734373361373837333534ab033e73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a636c6561725f7265666572656e64756d3a3a6836633962383630386238383461313433ac03ef013c73726d6c5f64656d6f63726163793a3a446973706174636851756575653c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265722c616c6c6f633a3a7665633a3a5665633c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c283c542061732073726d6c5f64656d6f63726163793a3a54726169743e3a3a50726f706f73616c2c20753332293e3e3e3e3a3a6765743a3a6839623362646538623237313239353830ad0380023c73726d6c5f64656d6f63726163793a3a5f5f6c696e6b65645f6d61705f64657461696c735f666f725f64656c65676174696f6e735f646f5f6e6f745f7573653a3a456e756d657261746f723c532c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c28283c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c2073726d6c5f64656d6f63726163793a3a436f6e76696374696f6e292c2054293e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6830376136373464663562323934383331ae03d0023c73726d6c5f7374616b696e673a3a5f5f6c696e6b65645f6d61705f64657461696c735f666f725f76616c696461746f72735f646f5f6e6f745f7573653a3a456e756d657261746f723c532c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c2873726d6c5f7374616b696e673a3a56616c696461746f7250726566733c3c3c542061732073726d6c5f7374616b696e673a3a54726169743e3a3a43757272656e63792061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a42616c616e63653e2c2054293e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6833316131666565343761333837613666af036f7061726974795f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f7220284a2c204b293e3a3a6465636f64653a3a6865656561636265623434343731336162b0033973726d6c5f626162653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6831613733373937373165363531313763b103683c73726d6c5f626162653a3a5f5f4765744279746553747275637452616e646f6d6e6573733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830313132633334653937373838386530b2034273726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864653837393762623036323933663036b30397013c73726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4578706563746564426c6f636b54696d6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837636434663762376361666466653533b40393013c73726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a45706f63684475726174696f6e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861633339313932336630646561303562b5033f73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a696e6a6563745f7265666572656e64756d3a3a6864336565376466366531343632366162b6033873726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6465706f7369745f6f663a3a6837626664333464323134343062343535b7033c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6839623865373439303362613166616237b8033e73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6866646263633263346636383265306163b9036f3c73726d6c5f64656d6f63726163793a3a5f5f476574427974655374727563744e65787445787465726e616c3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836376437386435646631303632323731ba036e3c73726d6c5f64656d6f63726163793a3a5f5f4765744279746553747275637444656c65676174696f6e733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834323930336365663137353532346361bb03703c73726d6c5f64656d6f63726163793a3a5f5f47657442797465537472756374446973706174636851756575653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835646562366164353830366265346539bc034773726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6865333836303831323234393138383538bd0398013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a436f6f6c6f6666506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830623839323664386236623263313030be03a0013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456d657267656e6379566f74696e67506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864643936336531386630643539383861bf0399013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d4465706f73697444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839633266363034646662653561616232c00397013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4c61756e6368506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837393135616137323139326261653861c103443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836386536643931613539313934623031c203483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a696e736572743a3a6835323464656336313866386533363731c303b5013c73726d6c5f64656d6f63726163793a3a50726f78793c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6765743a3a6831633631616464346133306331626537c4033573726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a646f5f766f74653a3a6862373137353137303439343332326261c503ef013c73726d6c5f64656d6f63726163793a3a426c61636b6c6973743c543e2061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a67656e657261746f723a3a53746f726167654d61703c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a486173682c283c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265722c20616c6c6f633a3a7665633a3a5665633c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e293e3e3a3a6765743a3a6865393534653832303430646532383064c603b50173726d6c5f7374616b696e673a3a5f494d504c5f454e434f44455f464f525f5f5f4c696e6b616765466f724e6f6d696e61746f7273446f4e6f745573653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f7374616b696e673a3a5f5f4c696e6b616765466f724e6f6d696e61746f7273446f4e6f745573653c4b65793e3e3a3a656e636f64655f746f3a3a6833393463653862336266643631386531c7033d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6832623333333738623965336532616637c8033d7061726974795f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6836386433646164383736643865623336c903483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a72656d6f76653a3a6862633938373830303863333662653266ca03483c552061732073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e3e3a3a72656d6f76653a3a6837623837323939626164376666626165cb033a73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6831303835663934326165613066666435cc033c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6831653964613665663737636163653537cd03723c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637443757272656e74457261526577617264733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864616431343838363463326230643566ce03703c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637443757272656e7445726153746172743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832353861326566303936323932613339cf03683c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563745374616b6572733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833393533663133633365306439616438d0036b3c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637456616c696461746f72733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834303432353238653931353637613536d1036d3c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563744f66666c696e65536c6173683c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835376230323932323131336530373366d203763c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563744d696e696d756d56616c696461746f72436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832393237623461376534303233303233d3039e0173726d6c5f7374616b696e673a3a5f494d504c5f4445434f44455f464f525f5374616b696e674c65646765723a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f7374616b696e673a3a5374616b696e674c65646765723c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6837393139373261393137633237353836d4034573726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6831326164313066663466363966303438d50398013c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426f6e64696e674475726174696f6e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836366661303833353962306264623630d6033773726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d616b655f7061796f75743a3a6836633933613435616433323637343635d70344636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a73697a655f68696e743a3a6832663966333337663331346430346261d8033973726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7570646174655f6c65646765723a3a6835323066333937386264646232376661d90330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6832383162643565356463633363633865da033e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6862653062383765616639383834363763db0334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6836316630353339376265346165306436dc032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6865656163363335353030636638613332dd033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6861386333323331343935333633336265de03683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6832326536303831316239376361613731df036b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6833313464396364336663323362303032e0037d3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973745772697465723c492c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6838343235363463313864343366306565e1036f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6834653832343164633166393264306465e2036f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743634206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6831366430333464363864636137656264e3036c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6830336336396535656266353063313036e4036f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6862626263366232363139386264373031e503443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839313834613132386161616566393339e60325616c6c6f633a3a666d743a3a666f726d61743a3a6830316632616438366163393537313166e703793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6863326538613330646462656461613462e8036b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6832306434326237363961666331303963e9032c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a6861366438393436643533653864653566ea03713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6830313964323733313537306237653565eb03783c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6866313935616364666237303034356435ec037c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6862376632633030343763366262323131ed0382017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a73657269616c697a653a3a6863303933363734393566363861636234ee0386017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a6836326535643235666332313139663161ef03323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6835353664376238663535366263363963f003743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6839666632356462616530336539636139f103713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6866386261353830386362663033336237f2036f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6831383061393939346363313364656166f303457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a6833343661393063316433323836303565f4034e636f72653a3a666d743a3a6e756d3a3a696d703a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a6838636363623736663163326366313235f503397761736d695f76616c69646174696f6e3a3a76616c69646174655f6d656d6f72795f747970653a3a6834616434666439623033616666656132f603347761736d695f76616c69646174696f6e3a3a657870725f636f6e73745f747970653a3a6833376565666538356536656134653533f703553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837663965313062313761383235343565f8034a7761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a737465703a3a6834383364653935633161363461363563f903473c7761736d695f76616c69646174696f6e3a3a4572726f7220617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6832643737393163616533616639343330fa03303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839343166666162333261613238643834fb03416861736862726f776e3a3a7261773a3a5261775461626c653c543e3a3a7472795f776974685f63617061636974793a3a6839316131643832316165666561623462fc033e6861736862726f776e3a3a7261773a3a5261775461626c653c543e3a3a726573657276655f7265686173683a3a6866376632653563623862643162646665fd03457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6866646634393463363530663965333032fe0337616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a6836636266366564636435643764353661ff033b636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f70795f66726f6d5f736c6963653a3a68656134643838343239623565386631648004347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f76616c75653a3a68333962623464666565633865336163668104347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f6c6162656c3a3a68306265623663623063666264383362368204407761736d695f76616c69646174696f6e3a3a7574696c3a3a4c6f63616c733a3a747970655f6f665f6c6f63616c3a3a68303962316539316364663361323835638304543c7761736d695f76616c69646174696f6e3a3a66756e633a3a537461636b56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68353262373862613035393164313065378404537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6c6f61643a3a68643631653439363063383835366639338504547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f73746f72653a3a68366264383738653965643435643134308604557761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f746573746f703a3a68656263623265346236356235623331398704547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f72656c6f703a3a68313065643039346235616632313966358804537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f756e6f703a3a68633437663530396438376362323431338904547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f62696e6f703a3a68623338343266346139323966303364388a04547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6376746f703a3a68613836306461386336626537623066638b04553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a426c6f636b5479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68626334663039353163653636626333668c0439636f72653a3a666d743a3a6275696c646572733a3a44656275675475706c653a3a6669656c643a3a68386332653034306164313637313634348d0430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68383833663961613434376433663434308e04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68306562333530386131623964616565388f04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68656636633035343338663334333237369004453c616c6c6f633a3a737472696e673a3a537472696e6720617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6830656338366664346535303535646566910423636f72653a3a666d743a3a77726974653a3a683263633535663738336132376161303292044c3c7761736d695f76616c69646174696f6e3a3a737461636b3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68376434363565363939343931383362339304553c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68343430663131396233306364383366329404303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683438373734633565333934323833323495043a636f72653a3a666d743a3a6275696c646572733a3a44656275675374727563743a3a6669656c643a3a6866326565303137626435353664666261960441707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a686535663861303461646332383866313297045a3c707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a4672616d6520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835626662636630363963393830393335980446707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a68646534363765613166633434376439399904453c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68623165623465333239306362663264349a044b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a68393230303336623534326131353238309b043f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a68336130383337643331383738633936629c0433636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26543e3a3a636c6f6e65643a3a68373433326438386565653331353766649d04533c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a737065635f657874656e643a3a68643630376234663532626135343434669e04323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68643466343861626239346363326466629f04613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6831326332376662386135316161323330a004303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830376435323632303134396236393730a10430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6830383334383934613965313131343030a204303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838393930636134353936346432353538a304303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6864303639363464626265306635333034a404463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833363230363132373936373366363831a504303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837666638363233383562363432343436a604303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838306664323863366234313432386138a704303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862333333346337346662323765343063a804383c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a6862356632376432643432633533313963a904343c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a6864333732633038613461626365636263aa04363c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a666c7573683a3a6835653133333330613631633430366531ab0411727573745f626567696e5f756e77696e64ac044e73725f696f3a3a696d703a3a6578743a3a65787465726e5f66756e6374696f6e735f686f73745f696d706c3a3a6578745f7072696e745f757466383a3a6863343839343937333162663664613538ad04423c5b545d206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6864646337663435393064333731386164ae04960173726d6c5f6d657461646174613a3a5f494d504c5f454e434f44455f464f525f53746f72616765456e747279547970653a3a3c696d706c207061726974795f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f6d657461646174613a3a53746f72616765456e747279547970653e3a3a656e636f64655f746f3a3a6861633536353632656363626263383462af04623c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6834626364303631653731303631316333b004623c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6833646134366334313938313066326233b1040a5f5f72675f616c6c6f63b2040c5f5f72675f6465616c6c6f63b3040c5f5f72675f7265616c6c6f63b404115f5f72675f616c6c6f635f7a65726f6564b5043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6839386630383364646366336530643539b6043b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6861623731346430333235303038653933b7043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a6838356462616235393333346166386562b804313c5420617320636f72653a3a616e793a3a416e793e3a3a747970655f69643a3a6838373362326233636138386434383161b90443636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a77726974655f7072656669783a3a6866353332373965323066353236636366ba042e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a6865653139323635326330646133653662bb044a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831353934666636313964313766353962bc04323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837663466306566323134623135303866bd043d636f72653a3a756e69636f64653a3a626f6f6c5f747269653a3a426f6f6c547269653a3a6c6f6f6b75703a3a6833333765663538373237613238613566be044e636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a68636238383338633162646231306235612e32343337bf0434636f72653a3a666d743a3a417267756d656e7456313a3a73686f775f7573697a653a3a6834343432343361643936333761656136c004453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839663861393035663061343166626565c104483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833623163616232626333636335643662c204303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837306365383064366362336331373736c3042e636f72653a3a736c6963653a3a6d656d6368723a3a6d656d6368723a3a6834653434386337323966353035343930c4048001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a6865376338616134366434653933636435c504533c636f72653a3a666d743a3a6275696c646572733a3a5061644164617074657220617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6831303966653662636331366463343332c60430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6863616233653737643232336562623862c7042f636f72653a3a666d743a3a57726974653a3a77726974655f636861723a3a6866353335666333343735643839373963c8042e636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a6838396132343964633663626538643835c9043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6839643838613837643735393063376538ca043b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a6863626539656365346539623261666163cb043a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a6836383566373362343736636232376133cc043e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863616638613466613733323737393335cd04066d656d736574ce04066d656d637079cf04076d656d6d6f7665d004066d656d636d70d104095f5f6173686c746933d204095f5f6c736872746933d304085f5f6d756c746933d404095f5f75646976746933d504095f5f756d6f64746933d6040c5f5f756469766d6f64746934005f0970726f64756365727302086c616e677561676502045275737400045275737404323031380c70726f6365737365642d62790105727573746325312e33382e302d6e696768746c79202863373938646666616320323031392d30372d323729", - "0x3ae31af9a378162eb2736f26855c9ad8": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0x1ba14d232d3c301a93e35f55e3d7aef2d98dbb9cc0ce48f457b81b421e0f704d": "0x0000c16ff28623000000000000000000", - "0xf14d23a9d4492a1efc9194e257b3c3d9": "0x00000000", - "0x90e2849b965314409e8bc00011f3004f": "0x04000000", - "0xeecb67c20ca6cc8ba4d4434687f61309": "0x109becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe969933201000000000000007932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f01000000000000005633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce44001000000000000003919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef0100000000000000", - "0x50a63a871aced22e88ee6466fe5aa5d9": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", - "0x686f6c72b7b80bad8dba022335cb7c9e4556ac7ea200008da8046e3178eb89c1": "0x0f0000c16ff286230f0000c16ff2862300", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973f409469434914add1f77b486e5d845d79fb97e50667a4fd4066fc59fc02b72ff": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x637414312dac3b280120bf15b4f66cee": "0x00000000", - "0xfd0cbba69a04d769ddcdbb15f5123c98041978f5241f33f78f62b48e3a02b740": "0x047374616b696e67200000c16ff28623000000000000000000ffffffffffffffff0e", - "0x78f4ad73d6b7279f8d06f359e363c829": "0x0000a49d8fc957363600000000000000", - "0x92f53c21a80e624b3c606bc8ec0ce2a3003c4fe385bed33998bf4dc79b8970f2": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d650f0000c16ff286230f0000c16ff2862300", - "0x77eef9fb1f954bfb3bbe274f703f6d00": "0x00000000", - "0x3a65787472696e7369635f696e646578": "0x00000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973424b9d3c8374bdf058222242204c46ade91b3190a50218823d53e9814b9557f0": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x8cb577756012d928f17362e0741f9f2c": "0x0100000000000000", - "0x775f52f99da6e72a0984c26ae28fbfcd": "0x0000000000000000", - "0xccea67b51b4fa33ecbff70a8977ad91d9c60d620f3ab5ac9626dea15cde023b7": "0x0f0000c16ff286230f0000c16ff2862300", - "0x3a686561707061676573": "0x0800000000000000", - "0xc1fdc3d212357bc2fa98f2a77b941f0c": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde789c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", - "0x68c8d2f39c4605e65218c22c5664917047e4900c797b7dd33999d94213c75049": "0x047374616b696e67200000c16ff28623000000000000000000ffffffffffffffff0e", - "0x52b963fbdb3d6e1b03808fc20071f07f": "0x0027060000000000", - "0x886726f904d8372fdabb7707870c2fad": "0x106e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91060100000000000000482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e0100000000000000482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a010000000000000000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f43780100000000000000", - "0xa8e78ad25e03ac0281ec709fd3f128efb7e112239d0a7c3e1c86375109bff334": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0xc1bc13c775b3406279618b05c28523cb": "0x00", - "0x0c41b62474c49057a4476d0b96853c6d44e9c86c5fa130b0da3831c5eef546a0": "0x00", - "0xbf18c0c65fb39f32ee7c8016685c0a6056f8f924192efb2655be9a692d0b03b6": "0x00", - "0xd368b9d9bb1cc910c9a2b8e5d0f5f2fc": "0x0000c16ff28623000000000000000000", - "0xe026dd082e3158e72eb7c985fc8bac4f": "0x4038000000000000", - "0xbde3e43a2a348359d103d64bc95928146bdd9ae3490e26da38d2e4d19c137507": "0x0000a0dec5adc9353600000000000000", - "0x4664fb5d4e16f894df23cadb3faaa9a6": "0x04000000", - "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579732a2afb49dfe38fc8b2b25f22f4b0d6acccac7d6d1b5fa7cd3852ad4dfabbcb6f": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", - "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b657973711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", - "0x040ff70c23416b89ce6afb75ee0d362e": "0x00000000", - "0xa5e869ecc1b914a6b0cf5f02b874f5eb90f1739fbd3edd01e5835d1517fd9f72": "0x781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276", - "0xf7327f83450f4e54b29a411237312742": "0x00", - "0x7e6064dc0e78ffebb59b3053826a9467": "0x109c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d1268655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", - "0x717a2ee9c64ad3424e10e4461ec08296": "0x0000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000008700000000000000af0000000000000001000000000000000100000000000000040000000000010010000000004000000020000000", - "0xf186665804ca50670311307912458ce448d82cb96e7e4fe71df38c283a8720f4": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d120f0000c16ff286230f0000c16ff2862300", - "0x6e4ab2ac5a7cf9b1829eacc84a75bde0804be01fc31c9419ea72407f50a33384": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663" - }, - { - }] + "raw": [ + { + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579730a299be621974fd19374a88f1dddd8442b21db25d2c923907dda6af815b657fe": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0xd368b9d9bb1cc910c9a2b8e5d0f5f2fc": "0xf6ffc06ff28623000000000000000000", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579731143fa96e07eb73af3db3a1b057d18899f864e6fc5d2f905f9296ca641565564": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797397dddc7aba561f16ac00da4bae75ab812aa7b81418bebdab74425f0d6aa31cee": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", + "0xbde3e43a2a348359d103d64bc95928146bdd9ae3490e26da38d2e4d19c137507": "0x0000a0dec5adc9353600000000000000", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797340944475c781bbdc9726766a78b1964888e039600b1c865c62586ab8f98c171e": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", + "0xf186665804ca50670311307912458ce448d82cb96e7e4fe71df38c283a8720f4": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d120f0000c16ff286230f0000c16ff2862300", + "0x50a63a871aced22e88ee6466fe5aa5d9": "0x9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809", + "0xaf837bb0dec545e1b97d62ed037898d1": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", + "0xe026dd082e3158e72eb7c985fc8bac4f": "0x80700000", + "0xb49a6659ec27619e87dd18e11b6838c0": "0x00", + "0x7c79972b34b7e51bdd5f168ba3accd35fbec396be75dfad19dd1121327f1a1ad": "0x000168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde7800", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797399a2fc4b1339e668345bac7e1aadd1a834b90939a4ea40b64f30433a1d475817": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0xbc3717660105a864bd63dcd430de64128d58bd0917fa8dd75aee827cf086e19c": "0x0000c16ff28623000000000000000000", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579732c1312343dce08149336968907c27cc602536aaf7a2b105d6fa07058a3803d31": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0x72143961950b9317e15506626c4524c4": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", + "0x9651d20f401bfac47731a01d6eba33b4": "0x00000000", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973dc4036f96ca26a30da6d8637ca1431896c1069bf172c419e98dc08109e7b23b5": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0xf14d23a9d4492a1efc9194e257b3c3d9": "0x00000000", + "0x90e2849b965314409e8bc00011f3004f": "0x04000000", + "0x52b963fbdb3d6e1b03808fc20071f07f": "0x004e0c00", + "0x87e6cbd186029472cea8c1748f99126b": "0x00000000", + "0x717a2ee9c64ad3424e10e4461ec08296": "0x0000000001000000000000000100000000000000010000000000000001000000000000000100000000000000010000000000000001000000000000008700000000000000af0000000000000001000000000000000100000000000000040000000000010010000000004000000020000000", + "0xeecb67c20ca6cc8ba4d4434687f61309": "0x103919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef01000000000000005633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce44001000000000000007932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f01000000000000009becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993320100000000000000", + "0x154ebcb2c318b2e1c23e43e65aea27cd1348c4c5157502d7669a31c7635019cc": "0x9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526", + "0x633daafcb669e97549c1b9d65660881016f969040bc16171709159437c31294a": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0xfacbe054606f2488121046f9c5539d98": "0x00", + "0x0c41b62474c49057a4476d0b96853c6d44e9c86c5fa130b0da3831c5eef546a0": "0x00", + "0xc1bc13c775b3406279618b05c28523cb": "0x00", + "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b657973711590f60a214f6f06502eb29dd14f55aa04e72e2fa12c098ba4fa5a00c57fa9": "0x7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e", + "0x75f6361fd25fec35714be80f2d9870af8c92e73cb6d299ba4774f5b0ad842275": "0x00", + "0x579ab55d37b1220812be3c3df29d4858": "0x00000000", + "0x4e62513de81454ce76df887573f7f98b101eb4585b1485a222b7db599f4e93e2": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", + "0xa902f1f0ef97177b8df9f9fd413768e7": "0x00000000", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973be035f25cd43adc80f1dcf505f5ffd158d1592ab3719f354a256a4c3b7571934": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", + "0x1ba14d232d3c301a93e35f55e3d7aef2d98dbb9cc0ce48f457b81b421e0f704d": "0x0000c16ff28623000000000000000000", + "0x2dce29f1a768624dc5343063cb77f77d": "0x07000000", + "0xa978690c6b811e943721dbb6cb9b6246": "0x0000000000000000", + "0x8b4621d5f16433d6024b5a31547c59ee24e749e051dbb4bc7e64502f2a4f62fb": "0x66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f", + "0x8cb577756012d928f17362e0741f9f2c": "0x01000000", + "0xc63b8a0db7e72fd87c88d8dcf4777b883f86728613c57148c4e5cdceb05b7a1a": "0x0001f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630168655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0x637414312dac3b280120bf15b4f66cee": "0x00000000", + "0xbf18c0c65fb39f32ee7c8016685c0a6056f8f924192efb2655be9a692d0b03b6": "0x00", + "0x3a636f6465": "0x0061736d01000000019f022660037f7f7f017f60027f7f017f60027f7f0060017f0060057f7f7f7f7f0060037f7f7f0060047f7f7f7f0060017f017e60057f7f7f7f7f017f60067f7f7f7f7f7f0060047f7f7f7f017f60017e0060067f7f7f7f7f7f017f60087f7f7f7f7f7f7f7f017f6000017f60077f7f7f7f7f7f7f017f60017f017f60027f7f017e60000060037e7f7f017f60047f7f7e7e0060077f7f7e7e7f7f7f0060087f7f7f7f7f7e7e7f0060057f7f7f7e7e0060077f7f7f7e7e7f7f0060037f7e7e0060057f7f7e7e7f0060077f7e7e7f7f7f7f0060067f7f7e7e7f7f0060077f7f7f7f7f7e7e0060047f7f7f7f017e6000017e60077f7f7f7e7e7e7f0060067f7f7f7e7e7f0060037f7e7f0060047f7e7e7f0060057f7e7e7e7e0060067f7e7e7e7e7f0002af082803656e760e6578745f626c616b65325f323536000503656e761f6578745f6765745f616c6c6f63617465645f6368696c645f73746f72616765000803656e76176578745f636c6561725f6368696c645f73746f72616765000603656e76146578745f6765745f73746f726167655f696e746f000803656e76166578745f6b696c6c5f6368696c645f73746f72616765000203656e76156578745f7365745f6368696c645f73746f72616765000903656e76196578745f6765745f616c6c6f63617465645f73746f72616765000003656e760f6578745f7365745f73746f72616765000603656e760c6578745f74776f785f313238000503656e76116578745f636c6561725f73746f72616765000203656e76126578745f737232353531395f766572696679000a03656e760e6578745f7072696e745f75746638000203656e760d6578745f7072696e745f6e756d000b03656e76166578745f6368696c645f73746f726167655f726f6f74000003656e76106578745f636c6561725f707265666978000203656e76166578745f73616e64626f785f6d656d6f72795f6e6577000103656e761b6578745f73616e64626f785f6d656d6f72795f74656172646f776e000303656e76176578745f73616e64626f785f696e7374616e7469617465000c03656e76126578745f73616e64626f785f696e766f6b65000d03656e761d6578745f73616e64626f785f696e7374616e63655f74656172646f776e000303656e76106578745f73746f726167655f726f6f74000303656e76186578745f73746f726167655f6368616e6765735f726f6f74000003656e76126578745f656432353531395f766572696679000a03656e76166578745f73616e64626f785f6d656d6f72795f676574000a03656e76166578745f73616e64626f785f6d656d6f72795f736574000a03656e760d6578745f7072696e745f686578000203656e76106578745f69735f76616c696461746f72000e03656e76156578745f6c6f63616c5f73746f726167655f676574000a03656e76216578745f6c6f63616c5f73746f726167655f636f6d706172655f616e645f736574000f03656e76116578745f6e6574776f726b5f7374617465001003656e76106578745f737232353531395f7369676e000803656e76166578745f7375626d69745f7472616e73616374696f6e000103656e76156578745f6c6f63616c5f73746f726167655f736574000403656e76146578745f656432353531395f67656e6572617465000603656e76146578745f737232353531395f67656e6572617465000603656e76236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74000603656e760a6578745f6d616c6c6f63001003656e76086578745f66726565000303656e76176578745f737232353531395f7075626c69635f6b657973000103656e760b6578745f74776f785f3634000503fd04fb0410100303000010101112030205001202060001010201021303070c0a0200060101011001010101010201060305030001010001010800010001010101010102030203030202020202020203020202020202020202020202020202020502020202050304050205010205020202140303020e02020303030202020201020102020405020202020202020202030202150101160509021706030505180602030202020205050505000314141212030212120501030303030303030303030303030303020202020202020502020202051202020303120e050502020502141406060505050502020205171919120503020302031a02020202021b020303030203140303051c1905050202020502050201010303020202020503020203020202060605030302020302020202020202021d0206030302020303030205020503030302020202020312020206020202030202050205060202051206090606060606060606060606060606060606060606060606061e02020203030203021f1203020302020505020203030302020203030202030303050510120202020202120202030202031010020202040302060202020303030203030202010a020202020202030b03030202030202020202020202020220030321060202020102010602030505020202030302021111021111050202111111021111110511031111111111111111030303030202020202020202030214020204020303020202020302020202020a0101010101010102010101010102010105020102050503050202010101050501010205050405220202020505040202050303030302020204020201050102060501050606050501040405050505060303010101000000002323242424250407017001de01de0105030100120619037f01418080c0000b7f004188b1c6000b7f004188b1c6000b078d0518066d656d6f72790200195f5f696e6469726563745f66756e6374696f6e5f7461626c6501000a5f5f646174615f656e6403010b5f5f686561705f62617365030209686173685f7465737400300c436f72655f76657273696f6e008c0412436f72655f657865637574655f626c6f636b008d0415436f72655f696e697469616c697a655f626c6f636b008f04114d657461646174615f6d657461646174610090041c426c6f636b4275696c6465725f6170706c795f65787472696e7369630094041b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b00950420426c6f636b4275696c6465725f696e686572656e745f65787472696e736963730096041c426c6f636b4275696c6465725f636865636b5f696e686572656e747300980418426c6f636b4275696c6465725f72616e646f6d5f736565640099042b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e009a04214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b6572009c041e4772616e6470614170695f6772616e6470615f617574686f726974696573009e0415426162654170695f636f6e66696775726174696f6e009f0421417574686f72697479446973636f766572794170695f617574686f72697469657300a0041a417574686f72697479446973636f766572794170695f7369676e00a1041c417574686f72697479446973636f766572794170695f76657269667900a2041d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e636500a30411436f6e7472616374734170695f63616c6c00a4042153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b65797300a50409a403010041010bdd013d4c5147e50448495ea201a401fd02ff0280038103820383038403850386038703880389038a038b038c038d038e038f0390039103920393039403950396039703d801ca04d0048605d2048205e604d804e204d4044f8c05d10497059405393a3b8901644155565758595a5b6160636566678a018b018d018e01900192014e4d9d03be04b301be01a701bf01a801b601c001bb01f20262ad03ac03d901b103a203a403d503d403d6039c039b03c403da01a202a002db01a402a904a804dc01b204dc02db02dd01dd02ba04b904de01bf04b603b503df01b703c802c702e001cb02d903d803e101b602b702d802d702e201e302e202e301e402e703e603e401ea0389048804e501a702a602e601b201e701a302cd02ef03f003c902b402b502b902b802ca02bb04d202d102d002cf02ce02cc02f303d902ac04de02e802e702e502f602f402f702f302f502a303a603a503b003af03ae03d703e903e803f403f203f103ee03ed03ec03eb038a04af04ae04ad04ab04aa04b304bd04bc04c304c204c104c004cc04ce04cb04c904c704c804cf04e104d5049505980596050ac3c540fb040600200010290b0600200010240b06002000102b0b0600200010250b0a00200020012002102d0b2801017f0240200210242203450d002003200020022001200120024b1b109a051a200010250b20030b06002000102f0b1c01017f0240200010242201450d002001410020001099051a0b20010bfa0202017f037e230041206b220224002001ad42adfed5e4d485fda8d8007e42c3007c210302400240024002400240200141084b0d00200141014b0d0120010d02420021040c030b0240200141104b0d00200241106a2000290000200385420042adfed5e4d485fda8d8004200109f05200241186a29030020022903107c200120006a41786a2900008521040c040b200120006a41786a2900002105200321040340200029000020048542adfed5e4d485fda8d8007e42178942adfed5e4d485fda8d8007e2003852103200041086a2100200442cf829ebbefefde82147c2104200141786a220141084b0d000b200320058521040c030b0240200141034b0d00200120006a417e6a33000042108620003300008420038521040c030b200120006a417c6a35000042208620003500008420038521040c020b200031000021040b200420038521040b20022004420042adfed5e4d485fda8d8004200109f05200241086a290300210420022903002103200241206a2400200420037c0b0a00418080c0001032000b5b02017f037e230041306b220124002000290208210220002902102103200029020021042001420437031020014201370204200120043703182001200141186a36020020012003370328200120023703202001200141206a103e000b870301067f230041306b2202240020012802002103024002402001280204220441037422050d00410021060c010b200341046a2107410021060340200728020020066a2106200741086a2107200541786a22050d000b0b024002400240024002400240200141146a2802000d00200621070c010b024020040d0041ac80c000410041001034000b024002402006410f4b0d002003280204450d010b200620066a220720064f0d010b4101210541002107200241086a21060c010b2007417f4c0d01200241086a2106024020070d0041012105410021070c010b200710282205450d020b200241003602102002200736020c200220053602082002200241086a360214200241186a41106a200141106a290200370300200241186a41086a200141086a29020037030020022001290200370318200241146a41bc80c000200241186a10350d0220002006290200370200200041086a200641086a280200360200200241306a24000f0b1036000b200741011037000b41d480c0004133200241186a418881c0001038000b6c01017f230041306b2203240020032002360204200320013602002003411c6a41023602002003412c6a41013602002003420237020c200341e883c000360208200341013602242003200341206a360218200320033602282003200341046a360220200341086a2000103e000bbd0801087f230041c0006b22032400200341246a2001360200200341346a200241146a2802002204360200200341033a00382003412c6a2002280210220520044103746a36020020034280808080800437030820032000360220410021062003410036021820034100360210200320053602302003200536022802400240024002400240200228020822070d0020022802002108200228020422092004200420094b1b220a450d0141012104200020082802002008280204200128020c1100000d04200841086a210241012106034002402005280200200341086a200541046a280200110100450d00410121040c060b2006200a4f0d02200241046a210020022802002101200541086a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110000450d000c050b0b20022802002108200228020422092002410c6a2802002205200520094b1b220a450d0041012104200020082802002008280204200128020c1100000d03200741106a2105200841086a21024101210603402003200541786a28020036020c2003200541106a2d00003a003820032005417c6a28020036020841002101410021040240024002400240200541086a2802000e0400010203000b2005410c6a2802002100410121040c020b02402005410c6a2802002207200328023422044f0d0041002104200328023020074103746a22072802044102470d0220072802002802002100410121040c020b41a089c000200720041034000b4100210420032802282207200328022c460d002003200741086a3602284100210420072802044102470d0020072802002802002100410121040b2003200036021420032004360210024002400240024002400240024020052802000e0404010006040b20032802282200200328022c470d010c050b200541046a2802002200200328023422044f0d01200328023020004103746a22002802044102470d04200028020028020021040c030b2003200041086a36022820002802044102470d03200028020028020021040c020b41a089c000200020041034000b200541046a28020021040b410121010b2003200436021c2003200136021802400240200541706a2802004101460d0020032802282204200328022c460d042003200441086a3602280c010b200541746a2802002204200328023422004f0d04200328023020044103746a21040b02402004280200200341086a200441046a280200110100450d00410121040c050b2006200a4f0d01200241046a210020022802002101200541246a2105200241086a210241012104200641016a2106200328022020012000280200200328022428020c110000450d000c040b0b0240200920064d0d00410121042003280220200820064103746a22052802002005280204200328022428020c1100000d030b410021040c020b41f087c0001032000b41b089c000200420001034000b200341c0006a240020040b05001031000b0e0041a6f4c500412210e70400000b810101017f230041c0006b220424002004200136020c2004200036020820042003360214200420023602102004412c6a41023602002004413c6a41033602002004420237021c200441b8c2c200360218200441043602342004200441306a3602282004200441106a3602382004200441086a360230200441186a4188afc000103e000bb10101037f0240024002400240200028020022002802042203200028020822046b2002490d00200028020021030c010b200420026a22052004490d02200341017422042005200420054b1b22044100480d020240024020030d002004102821030c010b200028020020032004102c21030b2003450d012000200436020420002003360200200028020821040b2000200420026a360208200320046a20012002109a051a41000f0b200441011037000b1031000ba70401047f230041106b220224002000280200210002400240024002400240024002402001418001490d002002410036020c2001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c040b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c030b0240200028020822032000280204470d00200341016a22042003490d06200341017422052004200520044b1b22044100480d060240024020030d002004102821030c010b200028020020032004102c21030b2003450d022000200436020420002003360200200028020821030b200028020020036a20013a00002000200028020841016a3602080c030b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010c010b200441011037000b0240024020002802042204200028020822036b2001490d00200028020021040c010b200320016a22052003490d03200441017422032005200320054b1b22034100480d030240024020040d002003102821040c010b200028020020042003102c21040b2004450d022000200336020420002004360200200028020821030b2000200320016a360208200420036a2002410c6a2001109a051a0b200241106a240041000f0b200341011037000b1031000b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41bc80c000200241086a10352101200241206a240020010b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c2002418486c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a419486c000103e000b0d00200035020041012001103f0b4702017f017e230041206b2202240020012902002103200241146a20012902083702002002200337020c20022000360208200241f883c0003602042002410136020020021040000bd40203027f017e037f230041306b22032400412721040240024020004290ce005a0d00200021050c010b412721040340200341096a20046a2206417c6a200020004290ce0080220542f0b17f7e7ca7220741ffff037141e4006e220841017441ba84c0006a2f00003b00002006417e6a2008419c7f6c20076a41ffff037141017441ba84c0006a2f00003b00002004417c6a2104200042ffc1d72f5621062005210020060d000b0b02402005a7220641e3004c0d00200341096a2004417e6a22046a2005a7220741ffff037141e4006e2206419c7f6c20076a41ffff037141017441ba84c0006a2f00003b00000b024002402006410a480d00200341096a2004417e6a22046a200641017441ba84c0006a2f00003b00000c010b200341096a2004417f6a22046a200641306a3a00000b2002200141b8aec6004100200341096a20046a412720046b10422104200341306a240020040b6601017f230041c0006b220124002001200036020c200141346a410136020020014201370224200141b0aec6003602202001410536023c2001200141386a36023020012001410c6a360238200141106a200141206a10332001280210200128021810e70400000b0d0042c8dfc497e99ce988eb000be00501057f024002402001450d00412b418080c4002000280200220641017122011b2107200120056a21080c010b200541016a210820002802002106412d21070b0240024020064104710d00410021020c010b4100210902402003450d002003210a200221010340200920012d000041c00171418001466a2109200141016a2101200a417f6a220a0d000b0b200820036a20096b21080b410121010240024020002802084101460d00200020072002200310430d012000280218200420052000411c6a28020028020c1100000f0b02402000410c6a280200220920084b0d00200020072002200310430d012000280218200420052000411c6a28020028020c1100000f0b0240024020064108710d00200920086b210941002101024002400240410120002d0030220a200a4103461b0e0402000100020b20092101410021090c010b20094101762101200941016a41017621090b200141016a210103402001417f6a2201450d0220002802182000280204200028021c280210110100450d000b41010f0b41012101200041013a003020004130360204200020072002200310430d01200920086b210941002101024002400240410120002d0030220a200a4103461b0e0402000100020b20092101410021090c010b20094101762101200941016a41017621090b200141016a2101024003402001417f6a2201450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210a41012101200028021820042005200028021c28020c1100000d01200941016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000c020b0b2000280204210a41012101200020072002200310430d00200028021820042005200028021c28020c1100000d00200941016a2109200028021c210320002802182100034002402009417f6a22090d0041000f0b410121012000200a2003280210110100450d000b0b20010b5401017f024002402001418080c400460d0041012104200028021820012000411c6a2802002802101101000d010b024020020d0041000f0b2000280218200220032000411c6a28020028020c11000021040b20040b6f01017f230041306b2202240020022001360204200220003602002002411c6a41023602002002412c6a41013602002002420237020c200241cc86c000360208200241013602242002200241206a3602182002200241046a36022820022002360220200241086a41dc86c000103e000b8307010c7f200028021021030240024002400240200028020822044101460d0020030d012000280218200120022000411c6a28020028020c11000021030c030b2003450d010b0240024020020d00410021020c010b200120026a2105200041146a28020041016a21064100210720012103200121080340200341016a210902400240024020032c0000220a417f4a0d000240024020092005470d004100210b200521030c010b20032d0001413f71210b200341026a220921030b200a411f71210c0240200a41ff0171220a41df014b0d00200b200c41067472210a0c020b0240024020032005470d004100210d2005210e0c010b20032d0000413f71210d200341016a2209210e0b200d200b41067472210b0240200a41f0014f0d00200b200c410c7472210a0c020b02400240200e2005470d004100210a200921030c010b200e41016a2103200e2d0000413f71210a0b200b410674200c411274418080f0007172200a72220a418080c400470d020c040b200a41ff0171210a0b200921030b02402006417f6a2206450d00200720086b20036a21072003210820052003470d010c020b0b200a418080c400460d00024002402007450d0020072002460d0041002103200720024f0d01200120076a2c00004140480d010b200121030b2007200220031b21022003200120031b21010b20040d002000280218200120022000411c6a28020028020c1100000f0b4100210902402002450d002002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b0240200220096b200028020c2206490d002000280218200120022000411c6a28020028020c1100000f0b410021074100210902402002450d00410021092002210a200121030340200920032d000041c00171418001466a2109200341016a2103200a417f6a220a0d000b0b200920026b20066a210a024002400240410020002d0030220320034103461b0e0402000100020b200a21074100210a0c010b200a4101762107200a41016a410176210a0b200741016a2103024003402003417f6a2203450d0120002802182000280204200028021c280210110100450d000b41010f0b2000280204210941012103200028021820012002200028021c28020c1100000d00200a41016a2103200028021c210a20002802182100034002402003417f6a22030d0041000f0b20002009200a280210110100450d000b41010f0b20030bcd0801067f230041f0006b220424002004200336020c20042002360208410121052001210602402001418102490d00410020016b2107418002210803400240200820014f0d00200020086a2c000041bf7f4c0d0041002105200821060c020b2008417f6a21064100210520084101460d01200720086a21092006210820094101470d000b0b200420063602142004200036021020044100410520051b36021c200441b8aec600419287c00020051b3602180240024002400240200220014b22080d00200320014b0d00200220034b0d01024002402002450d0020012002460d00200120024d0d01200020026a2c00004140480d010b200321020b200420023602202002450d0220022001460d02200141016a210903400240200220014f0d00200020026a2c000041404e0d040b2002417f6a210820024101460d0420092002462106200821022006450d000c040b0b20042002200320081b360228200441306a41146a4103360200200441c8006a41146a4104360200200441d4006a4104360200200442033702342004419887c0003602302004410136024c2004200441c8006a3602402004200441186a3602582004200441106a3602502004200441286a360248200441306a41b087c000103e000b200441e4006a4104360200200441c8006a41146a4104360200200441d4006a4101360200200441306a41146a410436020020044204370234200441c087c0003602302004410136024c2004200441c8006a3602402004200441186a3602602004200441106a36025820042004410c6a3602502004200441086a360248200441306a41e087c000103e000b200221080b024020082001460d00410121060240024002400240200020086a22092c00002202417f4a0d0041002105200020016a220621010240200941016a2006460d00200941026a210120092d0001413f7121050b2002411f712109200241ff017141df014b0d01200520094106747221010c020b2004200241ff0171360224200441286a21020c020b4100210020062107024020012006460d00200141016a210720012d0000413f7121000b200020054106747221010240200241ff017141f0014f0d0020012009410c747221010c010b41002102024020072006460d0020072d0000413f7121020b20014106742009411274418080f00071722002722201418080c400460d020b2004200136022441012106200441286a21022001418001490d00410221062001418010490d0041034104200141808004491b21060b200420083602282004200620086a36022c200441306a41146a4105360200200441ec006a4104360200200441e4006a4104360200200441c8006a41146a4106360200200441d4006a4107360200200442053702342004418888c000360230200420023602582004410136024c2004200441c8006a3602402004200441186a3602682004200441106a3602602004200441246a3602502004200441206a360248200441306a41b088c000103e000b41f087c0001032000b100020012000280200200028020410450b6c01037f230041206b22022400024020002001104b0d002001411c6a280200210320012802182104200242043703182002420137020c2002419889c00036020820042003200241086a10350d00200041046a2001104b2101200241206a240020010f0b200241206a240041010bd90a02077f017e410121020240200128021841272001411c6a2802002802101101000d0041022103024002400240024002402000280200220241776a2200411e4d0d00200241dc00470d010c020b41f40021040240024020000e1f05010202000202020202020202020202020202020202020202030202020203050b41f20021040c040b41ee0021040c030b02400240024002400240024002402002104a0d00024002400240024002400240200241808004490d00200241808008490d0120024190fc476a4190fc0b490d0a200241e28b746a41e28d2c490d0a2002419fa8746a419f18490d0a200241dee2746a410e490d0a200241feffff0071419ef00a460d0a200241a9b2756a4129490d0a200241cb91756a410a4d0d0a410121030c0e0b20024180fe0371410876210541d095c000210041002106200241ff017121040340200041026a2107200620002d000122036a2108024020002d000022002005460d00200020054b0d092008210620072100200741a296c000470d010c090b20082006490d02200841a5024b0d03200641a296c0006a2100024003402003450d012003417f6a210320002d00002106200041016a210020062004470d000c0c0b0b2008210620072100200741a296c000470d000c080b0b20024180fe0371410876210541819bc000210041002106200241ff017121040340200041026a2107200620002d000122036a2108024020002d000022002005460d00200020054b0d072008210620072100200741c79bc000470d010c070b20082006490d03200841a6014b0d04200641c79bc0006a2100024003402003450d012003417f6a210320002d00002106200041016a210020062004470d000c0b0b0b2008210620072100200741c79bc000470d000c060b0b200620081044000b200841a502103c000b200620081044000b200841a601103c000b200241017267410276410773ad4280808080d0008421090c040b200241ffff0371210441ed9cc00021034101210002400340200341016a21080240024020032d0000220641187441187522074100480d00200821030c010b20084185a0c000460d02200741ff007141087420032d0001722106200341026a21030b200420066b22044100480d032000410173210020034185a0c000470d000c030b0b41f087c0001032000b200241ffff0371210441c798c0002103410121000340200341016a21080240024020032d0000220641187441187522074100480d00200821030c010b200841819bc000460d05200741ff007141087420032d0001722106200341026a21030b200420066b22044100480d0120004101732100200341819bc000470d000b0b4101210320004101710d030b200241017267410276410773ad4280808080d0008421090b410321030c020b41f087c0001032000b0b200221040b03402003210641dc0021004101210241012103024002400240024020060e0401020300010b024002400240024002402009422088a741ff01710e06050403020100050b200942ffffffff8f60834280808080c000842109410321030c060b200942ffffffff8f608342808080803084210941f5002100410321030c050b200942ffffffff8f608342808080802084210941fb002100410321030c040b20042009a72206410274411c7176410f712203413072200341d7006a2003410a491b210002402006450d002009427f7c42ffffffff0f83200942808080807083842109410321030c040b200942ffffffff8f6083428080808010842109410321030c030b200942ffffffff8f6083210941fd002100410321030c020b20012802184127200128021c2802101101000f0b41002103200421000b20012802182000200128021c280210110100450d000b0b20020b950201017f024002402000418010490d00024002400240024002400240200041808004490d002000410c7641706a2201418002490d0141a8a0c00020014180021034000b200041067641606a220141df074b0d01200141f08bc0006a2d0000220141c9004b0d0220014103744180a1c0006a21010c060b200141d093c0006a2d00004106742000410676413f7172220141ff034b0d02200141d0a5c0006a2d0000220141394b0d03200141037441d0a9c0006a21010c050b4188a0c000200141e0071034000b4198a0c000200141ca001034000b41b8a0c00020014180041034000b41c8a0c0002001413a1034000b200041037641f8ffffff017141d889c0006a21010b200129030042012000413f71ad86834200520baf0201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001103f21000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b0d00200035020041012001103f0b1c00200128021841a1aec000410b2001411c6a28020028020c1100000b1c00200128021841acaec000410e2001411c6a28020028020c1100000b6901037f230041206b220224002001411c6a280200210320012802182104200241086a41106a2000280200220141106a290200370300200241086a41086a200141086a2902003703002002200129020037030820042003200241086a10352101200241206a240020010b5e01017f230041306b220224002002200136020c20022000360208200241246a410136020020024201370214200241b0aec6003602102002410436022c2002200241286a3602202002200241086a360228200241106a41f8aec000103e000b140020002802002001200028020428020c1101000bc30501077f410021040240024020024103712205450d00410420056b2205450d00200220032005200520034b1b22046a210641002105200141ff017121072004210820022109024003400240200620096b41034b0d0041002107200141ff0171210603402008450d04200920076a210a2008417f6a2108200741016a2107200a2d0000220a2006470d000b2005200a200141ff01714641016a4101716a20076a417f6a21050c020b200520092d0000220a2007476a2105200a2007460d012005200941016a2d0000220a2007476a2105200a2007460d012005200941026a2d0000220a2007476a2105200a2007460d012005200941036a2d0000220a2007476a21052008417c6a2108200941046a2109200a2007470d000b0b410121090c010b200141ff017121070240024020034108490d002004200341786a220a4b0d00200741818284086c210502400340200220046a220941046a2802002005732208417f73200841fffdfb776a7120092802002005732209417f73200941fffdfb776a7172418081828478710d01200441086a2204200a4d0d000b0b200420034b0d010b200220046a2109200220036a2102200320046b2108410021050240024003400240200220096b41034b0d0041002107200141ff0171210203402008450d04200920076a210a2008417f6a2108200741016a2107200a2d0000220a2002470d000b200a200141ff01714641016a41017120056a20076a417f6a21050c020b200520092d0000220a2007476a2105200a2007460d012005200941016a2d0000220a2007476a2105200a2007460d012005200941026a2d0000220a2007476a2105200a2007460d012005200941036a2d0000220a2007476a21052008417c6a2108200941046a2109200a2007470d000b0b41012109200520046a21050c020b41002109200520076a20046a21050c010b200420031044000b20002005360204200020093602000b2601017f200028020022012802002001280204200028020428020020002802082802001046000b850804057f017e017f017e02400240024002402002450d00410020016b410020014103711b2103200241796a4100200241074b1b210441002105034002400240200120056a2d000022064118744118752207417f4a0d0042808080801021080240200641e681c0006a2d0000417e6a220941024d0d0042808080808020210a0c070b0240024002400240024020090e03000102000b200541016a22062002490d024200210a0c090b4200210a200541016a220920024f0d08200120096a2d0000210902400240200641a07e6a2206410d4b0d000240024020060e0e0002020202020202020202020201000b200941e0017141a001460d0242808080808020210a0c0c0b02402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141a001490d0142808080808020210a0c0b0b02402007411f6a41ff0171410b4b0d0002402009411874411875417f4c0d0042808080808020210a0c0c0b200941ff017141c001490d0142808080808020210a0c0b0b0240200941ff017141bf014d0d0042808080808020210a0c0b0b0240200741fe017141ee01460d0042808080808020210a0c0b0b2009411874411875417f4c0d0042808080808020210a0c0a0b42002108200541026a220620024f0d09200120066a2d000041c00171418001460d020c070b4200210a200541016a220920024f0d07200120096a2d0000210902400240200641907e6a220641044b0d000240024020060e050002020201000b200941f0006a41ff01714130490d0242808080808020210a0c0b0b02402009411874411875417f4c0d0042808080808020210a0c0b0b200941ff0171419001490d0142808080808020210a0c0a0b0240200941ff017141bf014d0d0042808080808020210a0c0a0b02402007410f6a41ff017141024d0d0042808080808020210a0c0a0b2009411874411875417f4c0d0042808080808020210a0c090b200541026a220620024f0d07200120066a2d000041c00171418001470d0642002108200541036a220620024f0d08200120066a2d000041c00171418001460d01428080808080e000210a42808080801021080c080b42808080808020210a4280808080102108200120066a2d000041c00171418001470d070b200641016a21050c010b0240200320056b4103710d000240200520044f0d000340200120056a220641046a280200200628020072418081828478710d01200541086a22052004490d000b0b200520024f0d010340200120056a2c00004100480d022002200541016a2205470d000c040b0b200541016a21050b20052002490d000b0b20002001360204200041086a2002360200200041003602000f0b428080808080c000210a42808080801021080c010b420021080b2000200a2008842005ad84370204200041013602000b02000ba20401077f230041306b220324000240024020020d00410021040c010b200341286a210502400240024002400340024020002802082d0000450d00200028020041e4afc0004104200028020428020c1100000d050b2003410a3602282003428a808080103703202003200236021c200341003602182003200236021420032001360210200341086a410a200120021052024002400240024020032802084101470d00200328020c210403402003200420032802186a41016a2204360218024002402004200328022422064f0d00200328021421070c010b200328021422072004490d00200641054f0d072003280210200420066b22086a22092005460d04200920052006109c05450d040b200328021c22092004490d0220072009490d0220032006200341106a6a41176a2d0000200328021020046a200920046b10522003280204210420032802004101460d000b0b2003200328021c3602180b200028020841003a0000200221040c010b200028020841013a0000200841016a21040b2000280204210920002802002106024020044520022004467222070d00200220044d0d03200120046a2c000041bf7f4c0d030b200620012004200928020c1100000d04024020070d00200220044d0d04200120046a2c000041bf7f4c0d040b200120046a2101200220046b22020d000b410021040c040b20064104103c000b20012002410020041046000b20012002200420021046000b410121040b200341306a240020040bf90101017f230041106b220224002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a200110562101200241106a240020010b6001017f230041206b2202240020022000360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41ccafc000200241086a10352101200241206a240020010b0d0020002802002001200210560b800201017f230041106b22022400200028020021002002410036020c0240024002402001418001490d002001418010490d0102402001418080044f0d0020022001413f71418001723a000e20022001410676413f71418001723a000d20022001410c76410f7141e001723a000c410321010c030b20022001413f71418001723a000f2002200141127641f001723a000c20022001410676413f71418001723a000e20022001410c76413f71418001723a000d410421010c020b200220013a000c410121010c010b20022001413f71418001723a000d20022001410676411f7141c001723a000c410221010b20002002410c6a200110562101200241106a240020010b6301017f230041206b2202240020022000280200360204200241086a41106a200141106a290200370300200241086a41086a200141086a29020037030020022001290200370308200241046a41ccafc000200241086a10352101200241206a240020010bdb0302047f057e230041d0006b2205240041012106024020002d00040d0020002d000521070240200028020022082d00004104710d0041012106200828021841caafc00041e8afc000200741ff017122071b4102410320071b2008411c6a28020028020c1100000d014101210620002802002208280218200120022008411c6a28020028020c1100000d01410121062000280200220828021841b9a8c40041022008411c6a28020028020c1100000d0120032000280200200428020c11010021060c010b0240200741ff01710d0041012106200828021841ebafc00041032008411c6a28020028020c1100000d01200028020021080b41012106200541013a00172005200541176a360210200829020821092008290210210a200541346a41b0afc000360200200520082902183703082008290220210b2008290228210c200520082d00303a00482008290200210d2005200c3703402005200b3703382005200a370328200520093703202005200d3703182005200541086a360230200541086a2001200210560d00200541086a41b9a8c400410210560d002003200541186a200428020c1101000d00200528023041c8afc0004102200528023428020c11000021060b200041013a0005200020063a0004200541d0006a240020000bf30202047f057e230041d0006b2203240041012104024020002d00080d00200028020421050240200028020022062d00004104710d0041012104200628021841caafc00041f1afc00020051b4102410120051b2006411c6a28020028020c1100000d0120012000280200200228020c11010021040c010b024020050d0041012104200628021841f2afc00041022006411c6a28020028020c1100000d01200028020021060b41012104200341013a00172003200341176a3602102006290208210720062902102108200341346a41b0afc00036020020032006290218370308200629022021092006290228210a200320062d00303a00482006290200210b2003200a3703402003200937033820032008370328200320073703202003200b3703182003200341086a3602302001200341186a200228020c1101000d00200328023041c8afc0004102200328023428020c11000021040b200020043a00082000200028020441016a360204200341d0006a240020000b6401027f230041206b220224002001411c6a280200210320012802182101200241086a41106a200041106a290200370300200241086a41086a200041086a2902003703002002200029020037030820012003200241086a10352100200241206a240020000bb50f020d7f017e230041206b220324004101210402400240200228021841222002411c6a2802002802101101000d000240024020010d00410021050c010b200020016a21062000210741002105410021080240034020072109200741016a210a02400240024020072c0000220b417f4a0d0002400240200a2006470d004100210c200621070c010b20072d0001413f71210c200741026a220a21070b200b411f7121040240200b41ff0171220b41df014b0d00200c200441067472210b0c020b0240024020072006470d004100210d2006210e0c010b20072d0000413f71210d200741016a220a210e0b200d200c41067472210c0240200b41f0014f0d00200c2004410c7472210b0c020b02400240200e2006470d004100210b200a21070c010b200e41016a2107200e2d0000413f71210b0b200c4106742004411274418080f0007172200b72220b418080c400470d020c040b200b41ff0171210b0b200a21070b4102210a024002400240024002400240200b41776a220c411e4d0d00200b41dc00470d010c020b41f400210e02400240200c0e1f05010202000202020202020202020202020202020202020202030202020203050b41f200210e0c040b41ee00210e0c030b02400240200b104a0d00024002400240024002400240024002400240200b41808004490d00200b41808008490d01200b4190fc476a4190fc0b490d09200b41e28b746a41e28d2c490d09200b419fa8746a419f18490d09200b41dee2746a410e490d09200b41feffff0071419ef00a460d09200b41a9b2756a4129490d09200b41cb91756a410a4d0d090c0e0b200b4180fe0371410876210f41d095c000210c410021040340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d08200e2104200d210c200d41a296c000470d010c080b200e2004490d02200e41a5024b0d03200441a296c0006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c0b0b0b200e2104200d210c200d41a296c000470d000c070b0b200b4180fe0371410876210f41819bc000210c410021040340200c41026a210d2004200c2d0001220a6a210e0240200c2d0000220c200f460d00200c200f4b0d06200e2104200d210c200d41c79bc000470d010c060b200e2004490d03200e41a6014b0d04200441c79bc0006a210c02400340200a450d01200a417f6a210a200c2d00002104200c41016a210c2004200b41ff0171470d000c0a0b0b200e2104200d210c200d41c79bc000470d000c050b0b2004200e1044000b200e41a502103c000b2004200e1044000b200e41a601103c000b200b41ffff0371210e41ed9cc000210a4101210c02400340200a41016a210d02400240200a2d00002204411874411875220f4100480d00200d210a0c010b200d4185a0c000460d02200f41ff0071410874200a2d0001722104200a41026a210a0b200e20046b220e4100480d03200c410173210c200a4185a0c000470d000c030b0b41f087c0001032000b200b41ffff0371210e41c798c000210a4101210c0340200a41016a210d02400240200a2d00002204411874411875220f4100480d00200d210a0c010b200d41819bc000460d04200f41ff0071410874200a2d0001722104200a41026a210a0b200e20046b220e4100480d01200c410173210c200a41819bc000470d000b0b200c4101710d050b200b41017267410276410773ad4280808080d0008421104103210a0c020b41f087c0001032000b0b200b210e0b2003200136020420032000360200200320053602082003200836020c0240024020082005490d0002402005450d0020052001460d00200520014f0d01200020056a2c000041bf7f4c0d010b02402008450d0020082001460d00200820014f0d01200020086a2c000041bf7f4c0d010b2002280218200020056a200820056b200228021c28020c110000450d01410121040c060b20032003410c6a3602182003200341086a36021420032003360210200341106a1053000b0340200a210c4101210441dc0021054101210a024002400240024002400240200c0e0402010500020b02400240024002402010422088a741ff01710e06050302010006050b201042ffffffff8f60834280808080308421104103210a41f50021050c070b201042ffffffff8f60834280808080208421104103210a41fb0021050c060b200e2010a7220c410274411c7176410f71220a413072200a41d7006a200a410a491b21050240200c450d002010427f7c42ffffffff0f832010428080808070838421100c050b201042ffffffff8f60834280808080108421100c040b201042ffffffff8f608321104103210a41fd0021050c040b4100210a200e21050c030b4101210a0240200b418001490d004102210a200b418010490d0041034104200b41808004491b210a0b200a20086a21050c040b201042ffffffff8f60834280808080c0008421100b4103210a0b20022802182005200228021c2802101101000d050c000b0b200820096b20076a210820062007470d000b0b2005450d0020052001460d00200520014f0d02200020056a2c000041bf7f4c0d020b410121042002280218200020056a200120056b200228021c28020c1100000d0020022802184122200228021c28021011010021040b200341206a240020040f0b20002001200520011046000bc00201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff018341012001103f21000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b0b0020002802002001104b0b800201027f230041106b2202240020012802184198b0c00041092001411c6a28020028020c1100002103200241003a0005200220033a0004200220013602002002200036020c200241a1b0c000410b2002410c6a41f8afc000105c21012002200041046a36020c200141acb0c00041092002410c6a41b8b0c000105c1a20022d00042101024020022d0005450d00200141ff0171210041012101024020000d0020022802002201411c6a28020028020c210020012802182103024020012d00004104710d00200341eeafc0004102200011000021010c010b200341f0afc0004101200011000021010b200220013a00040b200241106a2400200141ff01714100470bb50201027f230041106b2202240002400240200028020022002d00004101460d00200128021841e0e2c50041042001411c6a28020028020c11000021010c010b2002200128021841e4e2c50041042001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200041016a36020c20022002410c6a4188b0c000105d1a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d0041012101200028021841f4afc00041012000411c6a28020028020c1100000d010b2002280200220128021841c8a4c60041012001411c6a28020028020c11000021010b200220013a00080b200141ff017141004721010b200241106a240020010b1c00200128021841b8aec60041052001411c6a28020028020c1100000b040041000b02000b02000b9e10020a7f017e23004180016b2202240002400240024020012802042203200128020022046b41e100490d000240024003402001200441206a3602002001280208220341186a280200210520032802102106200241e0006a41186a22034200370300200241e0006a41106a22074200370300200241e0006a41086a220842003703002002420037036020044120200241e0006a1000200241106a41186a22092003290300370300200241106a41106a220a2007290300370300200241106a41086a220b2008290300370300200220022903603703102002410036026020062005200241106a4120200241e0006a10012106024020022802602205417f460d0020022005360258200220053602542002200636025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c050b20012001280200220441206a3602002001280208220541186a2802002106200528021021052003420037030020074200370300200842003703002002420037036020044120200241e0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903603703102002410036026020052006200241106a4120200241e0006a10012106024020022802602205417f470d0020012001280200220441206a3602002001280208220541186a2802002106200528021021052003420037030020074200370300200842003703002002420037036020044120200241e0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903603703102002410036026020052006200241106a4120200241e0006a1001210620022802602205417f470d0320012001280200220441206a3602002001280208220541186a2802002106200528021021052003420037030020074200370300200842003703002002420037036020044120200241e0006a100020092003290300370300200a2007290300370300200b2008290300370300200220022903603703102002410036026020052006200241106a4120200241e0006a1001210720022802602203417f470d0220012802042203200128020022046b41e0004b0d010c040b0b20022005360258200220053602542002200636025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c030b20022003360258200220033602542002200736025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c020b20022005360258200220053602542002200636025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c010b024020042003460d0003402001200441206a3602002001280208220341186a280200210720032802102103200241e0006a41186a22084200370300200241e0006a41106a22094200370300200241e0006a41086a220a42003703002002420037036020044120200241e0006a1000200241106a41186a2008290300370300200241106a41106a2009290300370300200241106a41086a200a290300370300200220022903603703102002410036026020032007200241106a4120200241e0006a10012107024020022802602203417f460d0020022003360258200220033602542002200736025020012802082201280218210320012802102101200241e0006a41186a22074200370300200241e0006a41106a22084200370300200241e0006a41086a220942003703002002420037036020044120200241e0006a1000200241306a41186a2007290300370300200241306a41106a2008290300370300200241306a41086a20092903003703002002200229036037033020012003200241306a41201002200241086a2002280258360200200220022903503703000c030b200128020022042001280204470d000b0b200041003602000c010b200241e0006a41086a2002220141086a280200220336020020022001290200220c370360200020043602002000200c3702042000410c6a20033602000b20024180016a24000b950201057f230041e0026b22012400024020002802082202200028020c460d00200141b0016a4101722103200141d8016a210403402000200241b0016a36020820022d00002105200141b0016a200241016a41af01109a051a20054103460d01200141016a200141b0016a41af01109a051a200120053a00b0012003200141016a41af01109a051a02400240200541014b0d000240024020050e020001000b024020012802b801450d0020012802b401102a0b20012d00c0014105490d0220012802e801450d0220012802e401102a0c020b2004106a0c010b200128029802450d00200128029402102a0b20002802082202200028020c470d000b0b02402000280204450d002000280200102a0b200141e0026a24000baa0b01057f02402000280200220141124b0d00024002400240024002400240024002400240024002400240024020010e13000d0d010d0d020304050607080d090d0a0b0c000b0240200041086a280200220141054b0d0002400240024020010e06101000100102100b200041106a280200450d0f2000410c6a280200102a0f0b200041106a280200450d0e2000410c6a280200102a0f0b0240200041146a2802002202450d002000410c6a2802002101200241186c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141186a2101200241686a22020d000b0b200041106a280200450d0d200028020c102a0f0b0240200041146a2802002202450d002000410c6a28020021012002410c6c210203400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200041106a280200450d0c200028020c102a0f0b02402000410c6a2802002201450d0020002802042203200141f0006c6a2104034002402003410c6a2802002202450d0020032802042101200241246c210203400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012002415c6a22020d000b0b200341f0006a21010240200341086a280200450d002003280204102a0b2001210320012004470d000b0b200041086a280200450d0b2000280204102a0f0b0240200041086a2d00002201410c4b0d0020014106470d0b200041106a280200450d0b2000410c6a280200102a0f0b200041106a280200450d0a2000410c6a280200102a0f0b200041086a280200450d092000280204102a0f0b200041086a2d0000417f6a220141074b0d08024002400240024020010e08000c0c0c0c010203000b2000410c6a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b20002d0004417f6a220141024b0d0702400240024020010e03000102000b2000410c6a280200450d09200041086a280200102a0f0b200041086a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b20002d0004417f6a220141024b0d0602400240024020010e03000102000b2000410c6a280200450d08200041086a280200102a0f0b200041086a2201280200106a2001280200102a0f0b2000410c6a2201280200106a2001280200102a0f0b200041086a280200417f6a220141014b0d050240024020010e020001000b200041106a280200450d062000410c6a280200102a0f0b200041106a280200450d052000410c6a280200102a0f0b20002d00044104490d042000410c6a280200450d04200041086a280200102a0c040b200041086a280200450d032000280204102a0f0b200041086a2d0000417e6a220141024b0d0202400240024020010e03000102000b200041106a280200450d042000410c6a280200102a0f0b200041346a280200450d03200041306a280200102a0f0b200041306a280200450d022000412c6a280200102a0f0b02402000280204220141024b0d00024020010e03030003030b200041086a2201280200106a2001280200102a0f0b2000412c6a2201280200106a2001280200102a0f0b02402000410c6a280200450d00200041086a280200102a0b02402000411c6a2802002202450d00200041146a28020021012002410c6c210203400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0f0b0b960301097f230041106b2202240002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002006450d0020042d0001210720012003417e6a22063602042001200441026a3602002006450d0020042d0002210820012003417d6a22063602042001200441036a3602002006450d0020042d0003210620012003417c6a3602042001200441046a360200200241086a2001106c20022802080d022001280204200228020c2204490d022004417f4c0d0302400240024020040d004101210341010d010c050b2004102e2203450d0120012802042004490d03200320012802002004109a0521092001280204220a2004490d062001200a20046b3602042001200128020020046a3602002009450d040b20002004360208200020033602042000410c6a2004360200200020074108742005722008411074722006411874723602000c060b200441011037000b200041003602040c040b2003102a0b200041003602040c020b1036000b2004200a1044000b200241106a24000bcf0201067f0240024020012802042202450d00200128020022032d0000210420012002417f6a2205360204410121062001200341016a3602000240200441037122074103460d0002400240024020070e03000102000b20044102762107410021060c040b41012106024020050d000c040b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d03200141fcff03714102762107410021060c030b20054103490d01200341036a2d0000210620032f0001210720012002417c6a3602042001200341046a3602002007200641107472410874200472220141027621072001418080044921060c020b0240200441034d0d000c020b20054104490d012003280001210720012002417b6a3602042001200341056a36020020074180808080044921060c010b410121060b20002007360204200020063602000baf04010a7f230041d0006b2202240020022001106c0240024002400240024020022802000d00200128020422034160712204417f4c0d022002280204210502400240200341057622060d00410121070c010b200410282207450d040b02402005450d00410021080340200241003a00482008220941016a21082001280204417f6a21034100210402400240024003402003417f460d01200241286a20046a2001280200220a2d00003a0000200120033602042001200a41016a3602002002200441016a220a3a00482003417f6a2103200a2104200a4120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820062009470d020240200941017422032008200320084b1b220641ffffff3f712006470d002006410574220341004e0d020b1031000b0240200441ff0171450d00200241003a00480b200041003602002006450d052007102a0c050b0240024020090d002003102821070c010b200720094105742003102c21070b2007450d070b200720094105746a22032002290308370000200341186a2004290300370000200341106a200a290300370000200341086a200b29030037000020082005470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241d0006a24000f0b1036000b200441011037000b200341011037000b9203010a7f200041086a220228020021034100210420024100360200024002402003450d004100210541002106410021044100210702400340024002402004450d00200741057421080340200720034f0d062001200028020022096b2008460d02200920086a220a20014120109c05450d020240200620076a220b20034f0d00200920056a20086a2209200a290000370000200941186a200a41186a290000370000200941106a200a41106a290000370000200941086a200a41086a290000370000200841206a2108200741016a22072003490d010c050b0b41c4b2c000200b20031034000b200028020020074105746a21080340200720034f0d0520012008460d01200820014120109c05450d01200841206a2108200741016a22072003490d000b410021040c030b200541606a21052006417f6a2106200441016a2104200741016a22072003490d000b0b2004450d00200320074d0d00200028020020074105746a220820044105746b2008200320076b410574109b051a0b2002200320046b3602000f0b41e8b1c000200720031034000bfe0203017f017e0b7f024002400240024020012802082202ad42187e2203422088a70d002003a72204417f4c0d00200128020021050240024020040d00410421060c010b200410282206450d020b0240024020020d00410021070c010b2005200241186c6a210841002107200621010340200541086a2802002204417f4c0d02200528020021090240024020040d004101210a4100210b0c010b2004210b20041028220a450d050b200a20092004109a05210a200541146a2802002209417f4c0d022005410c6a280200210c0240024020090d004100210d4101210e0c010b2009210d20091028220e450d060b200e200c2009109a05210c200141146a2009360200200141106a200d3602002001410c6a200c360200200141086a2004360200200141046a200b3602002001200a360200200141186a2101200741016a2107200541186a22052008470d000b0b2000200736020820002002360204200020063602000f0b1036000b200441041037000b200441011037000b200941011037000bc90a03027f017e1c7f230041f0006b22022400024002400240024002400240024020012802082203ad42f0007e2204422088a70d002004a72205417f4c0d00200128020021060240024020050d00410421070c010b200510282207450d020b0240024020030d00410021080c010b2006200341f0006c6a2109410021082007210a0340200241c0006a41086a220b200641186a290000370300200241c0006a41106a220c200641206a290000370300200241c0006a41186a220d200641286a290000370300200241206a41086a220e200641386a29000037030020062900102104200241206a41106a220f200641c0006a290000370300200241206a41186a2210200641c8006a290000370300200241186a2211200641e8006a290000370300200241106a2212200641e0006a290000370300200241086a2213200641d8006a290000370300200220043703402002200629003037032020022006290050370300200628020c2214ad42247e2204422088a70d022004a72201417f4c0d0220062802002115200628020421160240024020010d00410421170c010b200110282217450d050b0240024020140d00410021180c010b201441246c211941002105410021180340024002400240024002400240201620056a22012d00000e050001020304000b2002200141146a2900003703602002200141196a290000370065200141056a2f0000200141076a2d000041107472211a200141106a280000211b2001410c6a280000211c200141086a280000211d200141016a280000211e4100211f0c040b200141106a280200221b417f4c0d08200141086a2802002120200141016a280000211e4101211f0240201b0d004100211c4101211d41012020201b109a051a0c040b201b211c201b1028221d450d0b201d2020201b109a051a0c030b200141106a280200221b417f4c0d07200141086a280200211f200141016a280000211e02400240201b0d004100211c4101211d0c010b201b211c201b1028221d450d0c0b201d201f201b109a051a4102211f0c020b200141106a280200221b417f4c0d06200141086a280200211f200141016a280000211e02400240201b0d004100211c4101211d0c010b201b211c201b1028221d450d0c0b201d201f201b109a051a4103211f0c010b2001410c6a280200221c417f4c0d05200141046a280200210102400240201c0d004101211a4100211d0c010b201c211d201c1028221a450d0c0b201a2001201c109a052201411874211e2001410876211a4104211f0b201720056a2201201f3a0000200141076a201a4110763a0000200141056a201a3b0000200141106a201b3600002001410c6a201c360000200141086a201d360000200141016a201e360000200141146a20022903603702002001411c6a200241e0006a41086a290300370200201841016a21182019200541246a2205470d000b0b200a2017360204200a410c6a2018360200200a41086a2014360200200a2002290340370210200a41186a200b290300370200200a2015360200200a2002290320370230200a41206a200c290300370200200a41286a200d290300370200200a41386a200e290300370200200a41c0006a200f290300370200200a41c8006a2010290300370200200a41e8006a2011290300370200200a41e0006a2012290300370200200a41d8006a2013290300370200200a2002290300370250200841016a2108200a41f0006a210a200641f0006a22062009470d000b0b200020083602082000200336020420002007360200200241f0006a24000f0b1036000b200541041037000b200141041037000b201b41011037000b201b41011037000b201b41011037000b201c41011037000b890203017f017e077f02400240024020012802082202ad420c7e2203422088a70d002003a72204417f4c0d00200128020021050240024020040d00410421060c010b200410282206450d020b0240024020020d00410021070c010b20052002410c6c6a210841002107200621040340200541086a2802002201417f4c0d02200528020021090240024020010d004101210a0c010b20011028220a450d050b200a20092001109a052109200441086a2001360200200441046a2001360200200420093602002004410c6a2104200741016a21072005410c6a22052008470d000b0b2000200736020820002002360204200020063602000f0b1036000b200441041037000b200141011037000bd70201037f024020002802082201450d002000280200220020014188016c6a2102200041f8006a2100034002400240200041887f6a22012d00002203410e4b0d00024002400240024020030e0f050505050500050501050205030505050b200041907f6a2d00004101470d042000419c7f6a280200450d04200041987f6a280200102a0c040b2000418c7f6a2d00004103470d030240200041947f6a280200450d00200041907f6a280200102a0b200041a07f6a280200450d032000419c7f6a280200102a0c030b2000418c7f6a2802000d02200041947f6a280200450d02200041907f6a280200102a0c020b200041907f6a2d00004105490d01200041b87f6a280200450d01200041b47f6a280200102a0c010b200041907f6a280200450d002000418c7f6a280200102a0b0240200141fc006a280200450d002000280200102a0b20004188016a210020014188016a2002470d000b0b0baf04010a7f230041d0006b2202240020022001106c0240024002400240024020022802000d00200128020422034160712204417f4c0d022002280204210502400240200341057622060d00410121070c010b200410282207450d040b02402005450d00410021080340200241003a00482008220941016a21082001280204417f6a21034100210402400240024003402003417f460d01200241286a20046a2001280200220a2d00003a0000200120033602042001200a41016a3602002002200441016a220a3a00482003417f6a2103200a2104200a4120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820062009470d020240200941017422032008200320084b1b220641ffffff3f712006470d002006410574220341004e0d020b1031000b0240200441ff0171450d00200241003a00480b200041003602002006450d052007102a0c050b0240024020090d002003102821070c010b200720094105742003102c21070b2007450d070b200720094105746a22032002290308370000200341186a2004290300370000200341106a200a290300370000200341086a200b29030037000020082005470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241d0006a24000f0b1036000b200441011037000b200341011037000b8a06030a7f037e017f23004190016b2202240020022001106c0240024002400240024020022802000d00200128020441216e220341216c2204417f4c0d01200228020421050240024020040d00410121060c010b200410282206450d030b02402005450d0041002107034020012802042208450d05200128020022092d0000210420012008417f6a220a3602042001200941016a360200200441014b0d054100210b0240024020040e020100010b41002104200241003a0088012008417e6a210803400240200a2004470d00200441ff0171450d08200241003a0088010c080b200241e8006a20046a200920046a220b41016a2d00003a0000200120083602042001200b41026a3602002002200441016a220b3a0088012008417f6a2108200b2104200b4120470d000b200241c8006a41186a200241e8006a41186a290300370300200241c8006a41106a200241e8006a41106a290300370300200241c8006a41086a200241e8006a41086a290300370300200220022903683703484101210b0b200741016a2108200241286a41186a200241c8006a41186a290300220c370300200241286a41106a200241c8006a41106a290300220d370300200241286a41086a200241c8006a41086a290300220e370300200241086a41086a2209200e370300200241086a41106a220a200d370300200241086a41186a220f200c37030020022002290348220c3703282002200c370308024020032007470d000240200741017422042008200420084b1b2203ad42217e220c422088a70d00200ca722044100480d000240024020070d002004102821060c010b2006200741216c2004102c21060b20060d01200441011037000b1031000b2006200741216c6a2204200b3a000020042002290308370001200441096a2009290300370000200441116a200a290300370000200441196a200f2903003700002008210720082005470d000b0b2000200336020420002006360200200041086a20053602000c040b200041003602000c030b1036000b200441011037000b200041003602002003450d002006102a0b20024190016a24000bc902010a7f230041106b22022400200241086a2001106c0240024020022802080d00024020012802042203417f4c0d00200228020c210402400240024020030d00410121050c010b200310282205450d010b02402004450d004100210641002107034002400240024020012802042208450d00200741016a21092001280200220a2d0000210b20012008417f6a3602042001200a41016a36020020072003460d010c020b200041003602002003450d072005102a0c070b024020062009200620094b1b22034100480d000240024020070d002003102821050c010b200520072003102c21050b20050d01200341011037000b1031000b200520076a200b3a0000200641026a21062009210720042009470d000b0b2000200336020420002005360200200041086a20043602000c030b200341011037000b1036000b200041003602000b200241106a24000b990a02137f017e230041e0006b22022400200241086a2001106c0240024020022802080d000240200128020441246e220341246c2204417f4c0d00200228020c210502400240024020040d00410421060c010b200410282206450d010b02400240024020050d00410021040c010b2002412d6a2107200241cb006a220841056a21094100210a4100210b0340024002402001280204220c450d002001280200220d2d000021042001200c417f6a220e3602042001200d41016a360200200441064b0d00024002400240024002400240024020040e0700070107030402000b20022001106c20022802000d0620012802042002280204220c490d06200c417f4c0d0c024002400240200c0d004101210441010d010c090b200c102e2204450d012001280204200c490d0620042001280200200c109a05210f2001280204220d200c490d072001200d200c6b36020420012001280200200c6a360200200f450d080b200241206a41086a200241386a41086a290200370300200220022902383703202004410876210f4104210d200c210e201041ffffff0771200441187472221021110c080b200c41011037000b41002104200241003a0058200c417e6a210c03400240200e2004470d00200441ff0171450d07200241003a00580c070b200241386a20046a200d20046a220f41016a2d00003a00002001200c3602042001200f41026a3602002002200441016a220f3a0058200c417f6a210c200f2104200f4120470d000b2002200829000037032020022009290000370025200228004721122002280043210e200228003f210c2002280238211120022f013c210420022d003e210f200741026a200241356a41026a2d00003a0000200720022f00353b00002004200f41107472210f4100210d0c060b200241386a2001106b200228023c220c450d04200228024421122002280240210e200228023821114101210d0c050b200241386a2001106b200228023c220c450d03200228024421122002280240210e200228023821114102210d0c040b200241386a2001106b200228023c220c450d02200228024421122002280240210e200228023821114103210d0c030b2004102a0c010b200c200d1044000b200041003602000240200b450d002006210403400240024020042d0000220141034b0d0002400240024020010e0404000102040b2004410c6a280200450d03200441086a280200102a0c030b2004410c6a280200450d02200441086a280200102a0c020b2004410c6a280200450d01200441086a280200102a0c010b200441086a280200450d00200441046a280200102a0b200441246a2104200a415c6a220a0d000b0b2003450d072006102a0c070b200241106a41086a2213200241206a41086a290300370300200220022903203703100240200b2003470d0002400240200341016a22042003490d00200341017422142004201420044b1b2204ad42247e2215422088a70d002015a7221441004e0d010b1031000b0240024020030d002014102821060c010b2006200341246c2014102c21060b2006450d03200421030b2006200b41246c6a220420123600102004200e36000c2004200c3600082004200f3b0005200420113600012004200d3a0000200441076a200f4110763a0000200420022903103700142004411c6a2013290300370000200a41246a210a200b41016a2204210b20042005470d000b0b2000200336020420002006360200200041086a20043602000c040b201441041037000b200441041037000b1036000b200041003602000b200241e0006a24000bb906020c7f047e230041b0016b2202240020022001106c02400240024002400240024020022802000d00200128020441286e220341286c2204417f4c0d02200228020421050240024020040d00410821060c010b200410282206450d040b02402005450d00410021070340200241003a00a8012007220841016a210720012802042109417f210a4100210402400240024002400240034020092004460d0120024188016a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a00a801200a417f6a210a200c2104200c4120470d000b200241e8006a41186a220420024188016a41186a290300370300200241e8006a41106a220a20024188016a41106a290300370300200241e8006a41086a220d20024188016a41086a29030037030020022002290388013703682009200c6b220c41074d0d01200b290001210e2001200b41096a3602002001200c41786a360204200241286a41086a200d290300220f370300200241286a41106a200a2903002210370300200241286a41186a20042903002211370300200241086a41086a220a200f370300200241086a41106a220c2010370300200241086a41186a2209201137030020022002290368220f3703282002200f37030820032008470d04200841017422042007200420074b1b2203ad42287e220f422088a70d0c200fa722044100480d0c20080d022004102821060c030b200441ff0171450d00200241003a00a8010b200241286a41186a200241c8006a41186a290300370300200241286a41106a200241c8006a41106a290300370300200241286a41086a200241c8006a41086a29030037030020022002290348370328200041003602002003450d062006102a0c060b2006200841286c2004102c21060b2006450d070b2006200841286c6a22042002290308370300200a290300210f200c2903002110200929030021112004200e370320200441186a2011370300200441106a2010370300200441086a200f37030020072005470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241b0016a24000f0b1036000b200441081037000b200441081037000b1031000bf80404097f027e027f017e230041d0006b2202240020022001106c024002400240024002400240024020022802000d00200128020441306e220341306c2204417f4c0d01200228020421050240024020040d00410821060c010b200410282206450d030b02402005450d00410021070340200128020422084110490d07200741016a21092001280200220a41086a290000210b200a290000210c2001200a41106a3602002001200841706a220d36020441002104200241003a00482008416f6a210803400240200d2004470d00200441ff0171450d09200241003a00480c090b200241286a20046a200a20046a220e41106a2d00003a0000200120083602042001200e41116a3602002002200441016a220e3a00482008417f6a2108200e2104200e4120470d000b200241086a41186a2208200241286a41186a290300370300200241086a41106a220e200241286a41106a290300370300200241086a41086a220a200241286a41086a29030037030020022002290328370308024020032007470d00200741017422042009200420094b1b2203ad42307e220f422088a70d07200fa722044100480d070240024020070d002004102821060c010b2006200741306c2004102c21060b2006450d060b2006200741306c6a2204200b3703082004200c37030020042002290308370310200441186a200a290300370300200441206a200e290300370300200441286a20082903003703002009210720092005470d000b0b2000200336020420002006360200200041086a20053602000c060b200041003602000c050b1036000b200441081037000b200441081037000b1031000b200041003602002003450d002006102a0b200241d0006a24000ba40303087f017e017f230041d0046b22022400200241086a2001106c02400240024002400240024020022802080d00200128020441a0026e220341a0026c2204417f4c0d02200228020c21050240024020040d00410821060c010b200410282206450d040b024002402005450d004100210741002104410021080340200241b0026a2001107a2002290398034203510d02200841016a2109200241106a200241b0026a41a002109a051a024020082003470d0020072009200720094b1b2203ad42a0027e220a422088a70d09200aa7220b4100480d090240024020080d00200b102821060c010b20062004200b102c21060b2006450d080b200620046a200241106a41a002109a051a200741026a2107200441a0026a21042009210820052009470d000b0b2000200336020420002006360200200041086a20053602000c020b2000410036020002402008450d0020064198016a210903402009106a200941a0026a2109200441e07d6a22040d000b0b2003450d012006102a0c010b200041003602000b200241d0046a24000f0b1036000b200441081037000b200b41081037000b1031000bae0c04047f017e097f067e23004180066b22022400200241286a2001106c02400240024002400240024020022802280d000240200228022c2203450d0003402003417f6a22030d000b0b20012802042203450d01200128020022042d0000210520012003417f6a3602042001200441016a36020002400240200541ff00714103470d0020054118744118754100480d01420221060c060b200042033703680c060b20024198046a200110a50120022d0098044102460d02200241f0036a41206a20024198046a41206a280200360200200241f0036a41186a20024198046a41186a290300370300200241f0036a41106a20024198046a41106a290300370300200241f0036a41086a20024198046a41086a29030037030020022002290398043703f00341002103200241003a00c00220012802042107417f2105024002400240034020072003460d0120024180026a20036a200128020022082d00003a00002001200720056a3602042001200841016a3602002002200341016a22043a00c0022005417f6a210520042103200441c000470d000b200241c0056a41386a220320024180026a41386a290300370300200241c0056a41306a220920024180026a41306a290300370300200241c0056a41286a220a20024180026a41286a290300370300200241c0056a41206a220b20024180026a41206a290300370300200241c0056a41186a220c20024180026a41186a290300370300200241c0056a41106a220d20024180026a41106a290300370300200241c0056a41086a220e20024180026a41086a29030037030020022002290380023703c005200441ff017141c000490d0520024180056a41386a220f200329030037030020024180056a41306a2009290300220637030020024180056a41286a200a290300221037030020024180056a41206a200b290300221137030020024180056a41186a200c290300221237030020024180056a41106a200d290300221337030020024180056a41086a200e2903002214370300200220022903c005221537038005200241c0046a41306a2006370300200241c0046a41286a2010370300200241c0046a41206a2011370300200241c0046a41186a2012370300200241c0046a41106a2013370300200241c0046a41086a2014370300200241c0046a41386a200f290300370300200220153703c00420072004460d05200831000121112001200720056a3602042001200841026a360200201150450d01420021060c020b200341ff0171450d04200241003a00c0020c040b2007417f6a2004460d03200831000221122001200841036a3602002001200720046b417e6a36020442022011420f838622104204540d034201210620124208862011844204882010420c882211420120114201561b7e221120105a0d030b200241206a2001106c20022802200d0220022802242105200241086a2001109f012002290308a70d02200241086a41106a290300211320022903102112200241e8026a41206a200241f0036a41206a280200360200200241e8026a41186a200241f0036a41186a290300370300200241e8026a41106a200241f0036a41106a290300370300200241e8026a41086a200241f0036a41086a29030037030020024194036a200241c0046a41086a2903003702002002419c036a200241c0046a41106a290300370200200241a4036a200241c0046a41186a290300370200200241ac036a200241c0046a41206a290300370200200241b4036a200241e8046a290300370200200241bc036a200241f0046a290300370200200241c4036a200241f8046a290300370200200220022903f0033703e802200220022903c00437028c0320024180026a200241e8026a41e800109a051a0c030b200042033703680c040b200042033703680c030b420221060b20024198016a20024180026a41e800109a051a024020064202520d00200042033703680c020b200241306a20024198016a41e800109a051a0b200241e8026a2001108101024020022802e8024113460d002000200241306a41e800109a0522034188016a201337030020034180016a201237030020034190016a2005360200200341f8006a2011370300200320103703702003200637036820034198016a200241e8026a418801109a051a0c010b200042033703680b20024180066a24000bfb1002147f037e230041c0026b22022400200241086a2001106c0240024020022802080d000240200128020441c4006e220341c4006c2204417f4c0d00200228020c210502400240024020040d00410421060c010b200410282206450d010b024002402005450d0020024198026a410772210741002108034002400240024002400240024020012802042209450d002001280200220a2d0000210420012009417f6a220b3602042001200a41016a360200200441014b0d000240024020040e020001000b200b41034d0d01200a280001210c20012009417b6a3602042001200a41056a360200200241d4016a41026a200241d8016a41026a2d00003a0000200241b8016a41086a200241f8016a41086a290200370300200241b8016a41106a200241f8016a41106a290200370300200241b8016a41186a200241f8016a41186a2d00003a000020024198016a41086a20024198026a41086a29010037030020024198016a41106a20024198026a41106a29010037030020024198016a41186a20024198026a41186a290100370300200220022f00d8013b01d401200220022902f8013703b801200220022901980237039801200220022f01f4013b0196014100210d0c030b4100210e200241003a00b8022009417e6a210d03400240200b200e2204470d000240200441ff0171450d00200241003a00b8020b4102210d0c040b20024198026a20046a200a20046a220e41016a2d00003a00002001200d3602042001200e41026a3602002002200441016a220e3a00b802200d417f6a210d200e4120470d000b200241f4016a41026a220f20022d009a023a0000200241d8016a41086a2210200741086a290000370300200241d8016a41106a2211200741106a290000370300200241d8016a41186a2212200741186a2d00003a0000200220022f0198023b01f401200220072900003703d801200b200e460d01200228009b022113200a200e6a220a41016a2d0000210b2001200d3602042001200a41026a360200200b41014b0d014100211402400240200b0e020100010b4100210d200241003a00b802200e20096b41026a210b200920046b417c6a210403400240200b200d6a0d00200d41ff0171450d04200241003a00b8020c040b20024198026a200d6a200a200d6a220e41026a2d00003a0000200120043602042001200e41036a3602002002200d41016a220e3a00b8022004417f6a2104200e210d200e4120470d000b200241f8016a41186a20024198026a41186a290300370300200241f8016a41106a20024198026a41106a290300370300200241f8016a41086a20024198026a41086a29030037030020022002290398023703f801410121140b20024198016a41186a200241f8016a41186a29030037030020024198016a41106a200241f8016a41106a29030037030020024198016a41086a200241f8016a41086a290300370300200241d4016a41026a200f2d00003a0000200241b8016a41086a2010290300370300200241b8016a41106a2011290300370300200241b8016a41186a20122d00003a0000200220022903f80137039801200220022f01f4013b01d401200220022903d8013703b8014101210d201421152013210c0c020b20024192016a41026a200241d4016a41026a2d00003a0000200241f8006a41086a200241b8016a41086a290300370300200241f8006a41106a200241b8016a41106a290300370300200241f8006a41186a200241b8016a41186a2d00003a0000200241d8006a41086a20024198016a41086a290300370300200241d8006a41106a20024198016a41106a290300370300200241d8006a41186a20024198016a41186a290300370300200220022f01d4013b019201200220022903b8013703782002200229039801370358200220022f0196013b01560c020b4102210d0b20024192016a41026a2204200241d4016a41026a2d00003a0000200241f8006a41086a220a200241b8016a41086a290300370300200241f8006a41106a220b200241b8016a41106a290300370300200241f8006a41186a2209200241b8016a41186a2d00003a0000200241d8006a41086a220f20024198016a41086a290300370300200241d8006a41106a221020024198016a41106a290300370300200241d8006a41186a221120024198016a41186a290300370300200220022f01d4013b019201200220022903b8013703782002200229039801370358200220022f0196013b0156200d4102460d00200841016a210e200241d2006a41026a221220042d00003a0000200241386a41086a2213200a290300370300200241386a41106a220a200b290300370300200241386a41186a220b20092d00003a0000200241186a41086a2209200f290300370300200241186a41106a220f2010290300370300200241186a41186a22102011290300370300200220022f0192013b01522002200229037837033820022002290358370318200220022f01563b011620032008470d02024020084101742204200e2004200e4b1b2203ad42c4007e2216422088a70d002016a7220441004e0d020b1031000b200041003602002003450d082006102a0c080b0240024020080d002004102821060c010b2006200841c4006c2004102c21060b2006450d030b2006200841c4006c6a2204200d3a00002004200c360004200441036a20122d00003a0000200420022f01523b0001200b2d0000210d200a29030021162013290300211720022903382118200420153a002120042018370008200441106a2017370000200441186a2016370000200441206a200d3a00002004413a6a2010290300370000200441326a200f2903003700002004412a6a200929030037000020042002290318370022200420022f01163b0042200e2108200e2005470d000b0b2000200336020420002006360200200041086a20053602000c040b200441041037000b200441041037000b1036000b200041003602000b200241c0026a24000baf04010a7f230041d0006b2202240020022001106c0240024002400240024020022802000d00200128020422034160712204417f4c0d022002280204210502400240200341057622060d00410121070c010b200410282207450d040b02402005450d00410021080340200241003a00482008220941016a21082001280204417f6a21034100210402400240024003402003417f460d01200241286a20046a2001280200220a2d00003a0000200120033602042001200a41016a3602002002200441016a220a3a00482003417f6a2103200a2104200a4120470d000b200241086a41186a2204200241286a41186a290300370300200241086a41106a220a200241286a41106a290300370300200241086a41086a220b200241286a41086a2903003703002002200229032837030820062009470d020240200941017422032008200320084b1b220641ffffff3f712006470d002006410574220341004e0d020b1031000b0240200441ff0171450d00200241003a00480b200041003602002006450d052007102a0c050b0240024020090d002003102821070c010b200720094105742003102c21070b2007450d070b200720094105746a22032002290308370000200341186a2004290300370000200341106a200a290300370000200341086a200b29030037000020082005470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241d0006a24000f0b1036000b200441011037000b200341011037000bb005020c7f037e230041f0006b2202240020022001106c0240024002400240024020022802000d00200128020441246e220341246c2204417f4c0d02200228020421050240024020040d00410421060c010b200410282206450d040b02402005450d00410021070340200241003a00682007220841016a210720012802042109417f210a410021040240024002400240034020092004460d01200241c8006a20046a2001280200220b2d00003a000020012009200a6a3602042001200b41016a3602002002200441016a220c3a0068200a417f6a210a200c2104200c4120470d000b200241286a41186a2204200241c8006a41186a290300370300200241286a41106a220a200241c8006a41106a290300370300200241286a41086a220d200241c8006a41086a290300370300200220022903483703282009200c6b220c4104490d01200b28000121092001200b41056a3602002001200c417c6a360204200241086a41086a220c200d290300370300200241086a41106a220b200a290300370300200241086a41186a220a20042903003703002002200229032837030820032008470d030240200841017422042007200420074b1b2203ad42247e220e422088a70d00200ea7220441004e0d030b1031000b200441ff0171450d00200241003a00680b200041003602002003450d052006102a0c050b0240024020080d002004102821060c010b2006200841246c2004102c21060b2006450d070b2006200841246c6a22042002290308370200200c290300210e200b290300210f200a290300211020042009360220200441186a2010370200200441106a200f370200200441086a200e37020020072005470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241f0006a24000f0b1036000b200441041037000b200441041037000be60403087f017e017f230041f0016b22022400200241086a2001106c02400240024002400240024020022802080d00200128020441f0006e220341f0006c2204417f4c0d02200228020c21050240024020040d00410421060c010b200410282206450d040b024002402005450d00410021074100210841002109034020024180016a2001107f200228028401450d02200941016a2104200241106a20024180016a41f000109a051a024020092003470d0020072004200720044b1b2203ad42f0007e220a422088a70d09200aa7220b4100480d090240024020090d00200b102821060c010b20062008200b102c21060b2006450d080b200620086a200241106a41f000109a051a200741026a2107200841f0006a21082004210920052004470d000b0b2000200336020420002006360200200041086a20053602000c020b2000410036020002402009450d00200620086a210120062107034002402007410c6a2802002209450d0020072802042104200941246c210903400240024020042d0000220841034b0d0002400240024020080e0404000102040b2004410c6a280200450d03200441086a280200102a0c030b2004410c6a280200450d02200441086a280200102a0c020b2004410c6a280200450d01200441086a280200102a0c010b200441086a280200450d00200441046a280200102a0b200441246a21042009415c6a22090d000b0b200741f0006a21040240200741086a280200450d002007280204102a0b2004210720012004470d000b0b2003450d012006102a0c010b200041003602000b200241f0016a24000f0b1036000b200441041037000b200b41041037000b1031000b9f0a03077f037e057f230041d0026b2202240041002103200241003a00c8022001280204417f6a210402400240024003402004417f460d01200241a8026a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a00c8022004417f6a21042005210320054120470d000b200241e8006a41086a200241a8026a41086a290300370300200241e8006a41106a200241a8026a41106a290300370300200241e8006a41186a200241a8026a41186a290300370300200220022903a80237036820022001106c2002280200450d01200041003602040c020b0240200341ff0171450d00200241003a00c8020b200041003602040c010b2002280204210641002104200241003a00c80220012802042107417f21030240034020072004460d01200241a8026a20046a200128020022082d00003a00002001200720036a3602042001200841016a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241a8016a41086a200241a8026a41086a2903002209370300200241a8016a41106a200241a8026a41106a290300220a370300200241a8016a41186a200241a8026a41186a290300220b37030020024188016a41086a200937030020024188016a41106a200a37030020024188016a41186a200b370300200220022903a80222093703a801200220093703880141002104200241003a00c802200720056b210c200720036a210303400240200c2004470d000240200441ff0171450d00200241003a00c8020b200041003602040c030b200241a8026a20046a200820046a220541016a2d00003a0000200120033602042001200541026a3602002002200441016a22053a00c8022003417f6a21032005210420054120470d000b200241e8016a41086a200241a8026a41086a2903002209370300200241e8016a41106a200241a8026a41106a290300220a370300200241e8016a41186a200241a8026a41186a290300220b370300200241c8016a41086a22042009370300200241c8016a41106a2203200a370300200241c8016a41186a2205200b370300200220022903a80222093703e801200220093703c801200241a8026a20011076024020022802a8022201450d00200241c8006a41086a2208200241e8006a41086a290300370300200241c8006a41106a2207200241e8006a41106a290300370300200241c8006a41186a220c200241e8006a41186a290300370300200241286a41086a220d20024188016a41086a290300370300200241286a41106a220e20024188016a41106a290300370300200241286a41186a220f20024188016a41186a29030037030020022002290368370348200220022903880137032820022902ac022109200241086a41186a22102005290300370300200241086a41106a22052003290300370300200241086a41086a22032004290300370300200220022903c801370308200020093702082000200136020420002006360200200041106a2002290348370200200041186a2008290300370200200041206a2007290300370200200041286a200c290300370200200041306a2002290328370200200041386a200d290300370200200041c0006a200e290300370200200041c8006a200f290300370200200041e8006a2010290300370200200041e0006a2005290300370200200041d8006a2003290300370200200041d0006a20022903083702000c020b200041003602040c010b0240200441ff0171450d00200241003a00c8020b200041003602040b200241d0026a24000b9505020c7f017e230041b0056b22022400200241086a2001106c0240024002400240024020022802080d0020012802044190016e22034190016c2204417f4c0d02200228020c21050240024020040d00410821060c010b200410282206450d040b02402005450d00200241a0036a410472210741002108410021044100210903400240024002402001280204220a450d002001280200220b2d0000210c2001200a417f6a3602042001200b41016a360200200c41014b0d004113210a024002400240200c0e020100010b200241a8046a200110810120022802a8044113460d02200241a0036a200241a8046a418801109a051a2001280204220c4104490d012001280200220a280000210d2001200c417c6a3602042001200a41046a36020020022802a003210a2002419c026a2007418401109a051a200a4113460d0220024198016a2002419c026a418401109a051a200a4114460d020b200941016a210c200241146a20024198016a418401109a051a20092003470d0302402008200c2008200c4b1b2203ad4290017e220e422088a70d00200ea7220b41004e0d030b1031000b200241a0036a106a0b2000410036020002402009450d00200621010340024020012802004113460d002001106a0b20014190016a2101200441f07e6a22040d000b0b2003450d052006102a0c050b0240024020090d00200b102821060c010b20062004200b102c21060b2006450d070b200620046a2209200a360200200941046a200241146a418401109a051a20094188016a200d360200200841026a210820044190016a2104200c21092005200c470d000b0b2000200336020420002006360200200041086a20053602000c010b200041003602000b200241b0056a24000f0b1036000b200441081037000b200b41081037000bf3910107087f017e067f087e087f017e017f230041f0096b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200200541144b0d16200141046a210720050e150102030405060708090a0b0c0d0e0f101112131415010b200041133602000c4c0b02402006450d0020042d0001210620012003417e6a22083602042001200441026a360200200641054b0d004101210902400240024002400240024020060e06510001020304510b20022001106c20022802000d05200128020420022802042204490d052004417f4c0d1e02400240024020040d00410121050c010b2004102e2205450d0120072802002004490d06200520012802002004109a051a200128020422032004490d212001200320046b3602042001200128020020046a3602000b2005450d062004ad220a422086200a84210a410221090c510b200441011037000b20084108490d042004290002210a2001200341766a36020420012004410a6a360200410321090c4f0b200241086a2001106c20022802080d032001280204200228020c2204490d032004417f4c0d1c02400240024020040d00410121050c010b2004102e2205450d0120072802002004490d04200520012802002004109a051a200128020422032004490d202001200320046b3602042001200128020020046a3602000b2005450d042004ad220a422086200a84210a410421090c4f0b200441011037000b200241206a2001106c20022802200d02200728020041186e220b41186c2204417f4c0d1b2002280224210c0240024020040d00410421050c010b200410282205450d1f0b0240200c450d004100210d41002106410021080340200241186a2001106c02400240024020022802180d002001280204200228021c2204490d002004417f4c0d2002400240024020040d004101210e0c010b2004102e220e450d3920072802002004490d01200e20012802002004109a051a200128020422032004490d262001200320046b3602042001200128020020046a3602000b200241106a2001106c024020022802100d00200128020420022802142203490d002003417f4c0d22024002400240024020030d004101210f0c010b2003102e220f450d0120072802002003490d02200f20012802002003109a051a200128020422092003490d2a2001200920036b3602042001200128020020036a3602000b200841016a21092008200b470d06200d2009200d20094b1b220bad42187e220a422088a70d55200aa7221041004e0d050c550b200341011037000b200f102a0b2004450d010b200e102a0b02402008450d002005210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141186a2101200641686a22060d000b0b200b0d050c060b0240024020080d002010102821050c010b200520062010102c21050b2005450d240b200520066a2208200e360200200841146a2003ad220a3e02002008410c6a200a422086200fad84370200200841046a2004ad220a422086200a84370200200d41026a210d200641186a210620092108200c2009470d000b0b2005450d02200cad422086200bad84210a410521090c4d0b200241306a2001106c20022802300d012007280200410c6e220e410c6c2204417f4c0d1a2002280234210f0240024020040d00410421050c010b200410282205450d220b024002400240200f450d004100210841002103410021090340200241286a2001106c20022802280d032001280204200228022c2204490d032004417f4c0d1e0240024020040d004101210d0c010b2004102e220d450d3720072802002004490d03200d20012802002004109a051a200128020422062004490d272001200620046b3602042001200128020020046a3602000b200941016a210602402009200e470d0020082006200820064b1b220ead420c7e220a422088a70d50200aa7220b4100480d500240024020090d00200b102821050c010b20052003200b102c21050b2005450d280b200520036a2209200d360200200941086a2004360200200941046a2004360200200841026a21082003410c6a210320062109200f2006470d000b0b2005450d03200fad422086200ead84210a410621090c4e0b200d102a0b02402009450d002005210103400240200141046a280200450d002001280200102a0b2001410c6a2101200341746a22030d000b0b200e450d010b2005102a0b200041133602000c4b0b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c4a0b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241386a2001109e012002290338a70d002002290340210a20004102360200200041086a200a370300200041106a200241e8086a41f800109a051a0c4a0b200041133602000c490b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e0076a2001107e20022802e00722010d130b200041133602000c480b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c470b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d00024002400240024020050e03000102000b200241e8086a200110a50120022d00e8084102460d0320024184096a290200210a200241fc086a2902002111200241e8086a41106a2802002107200241f4086a2802002104200241f0086a280200210320022802ec08210520022802e8082106200241c8006a2001109f0120022802480d03200241c8006a41106a290300211241012101200229035021130c020b200241e8086a200110a50120022d00e8084102460d02200241e0076a41086a20024180096a290300370300200241e0076a41106a20024188096a2802003602002002200241e8086a41106a2903003703e007200241f4086a2802002104200241e8086a41086a280200210320022802ec08210520022802e8082106200241f8006a2001109f012002290378a70d02200241f8006a41106a29030021122002290380012113200241e0006a2001109f012002290360a70d02200241e0006a41106a290300211420022903682115200241a8056a41106a200241e0076a41106a280200360200200241a8056a41086a200241e0076a41086a290300370300200220022903e00722163703a805200241b4056a290200210a20022902ac0521112016a7210741022101420021160c010b200241e8086a200110a50120022d00e8084102460d0120024184096a290200210a200241fc086a2902002111200241e8086a41106a22092802002107200241f4086a2802002104200241e8086a41086a2208280200210320022802ec08210520022802e8082106200241e8086a200110a50120022d00e8084102460d01200241e0076a41206a220d200241e8086a41206a280200360200200241e0076a41186a220e200241e8086a41186a290300370300200241e0076a41106a2009290300370300200241e0076a41086a2008290300370300200220022903e8083703e00720024190016a2001109f01200229039001a70d0120024190016a41106a29030021172002290398012118200241e8076a2903002112200241f0076a2903002115200e2903002114200d350200211620022903e0072113410321010b20004105360200200041e0006a2017370200200041d8006a2018370200200041c8006a2014370200200041c0006a2015370200200041386a2012370200200041306a2013370200200041286a200a370200200041206a2011370200200041d0006a20163702002000411c6a2007360200200041186a2004360200200041146a2003360200200041106a20053602002000410c6a2006360200200041086a2001360200200041e8006a200229038806370300200041f0006a20024188066a41086a290300370300200041f8006a20024188066a41106a29030037030020004180016a20024188066a41186a2903003703000c470b200041133602000c460b2006450d4120042d0001210520012003417e6a22193602042001200441026a3602002005410c4b0d41410421104100211a4100211b02400240024002400240024002400240024002400240024020050e0d0001024e030405060708090a0b000b200241e0076a200110a50120022d00e0074102460d4c200241ec076a290200211120024180086a280200210b200241ff076a2d00002108200241fe076a2d0000210d200241fd076a2d0000210c200241f9076a2800002104200241f5076a280000210f200241f4076a2d0000210e20022902e407210a20022802e0072106200241a8016a2001109f0120022903a801a70d4c20072802002203450d4c200241b8016a290300211320022903b0012112200128020022052d0000210920012003417f6a360204410121102001200541016a36020020094103492201450d4c200441807e71410020011b211b2004410020011b211a0c4d0b200241c0016a2001109f0120022903c001a70d4b200241d0016a290300211120022903c801210a410221104100211b0c4c0b200241d8016a2001109f0120022903d801a70d4a200241e8016a290300211120022903e001210a410321104100210c4100211a4100211b0c4b0b200241f0016a2001109f0120022903f001a70d4920024180026a290300211120022903f801210a410521104100211b0c4a0b20024188026a2001106c2002280288020d48200728020041246e221c41246c2204417f4c0d19200228028c02211d0240024020040d00410421060c010b200410282206450d240b0240201d450d0041232105200241f0076a211e41002107410021040340200241e0076a200110a501024020022d00e00722094102470d00201c450d4b2006102a0c4b0b200441016a2103201e290300210a20022903e807211120022d008308210820022d008208210d20022d008108210e20022800fd07210f20022800f907210b20022d00f807210c20022802e407211020022d00e307211b20022d00e207211920022d00e107211f02402004201c470d0020072003200720034b1b221cad42247e2212422088a70d4d2012a722204100480d4d0240024020040d002020102821060c010b20062005415d6a2020102c21060b2006450d270b200620056a220420083a0000200441656a2208200a370008200820113700002004417f6a200d3a00002004417e6a200e3a00002004417a6a200f360000200441766a200b360000200441756a200c3a0000200441616a2010360000200441606a201b3a00002004415f6a20193a00002004415e6a201f3a00002004415d6a20093a0000200741026a2107200541246a210520032104201d2003470d000b0b2006450d48201dad422086201cad84210a42002111410621104100211b0c490b410721104100211b0c480b2019450d4620042d0002210920012003417d6a3602042001200441036a360200200941034f0d46410821104100211b0c470b200241e0076a200110a50120022d00e0074102460d45200241f9076a280000221a41807e71211b200241ec076a290200211120024180086a280200210b200241ff076a2d00002108200241fe076a2d0000210d200241fd076a2d0000210c200241f5076a280000210f200241f4076a2d0000210e20022902e407210a20022802e0072106410921100c460b20024190026a2001106c2002280290020d442002280294022106410a21104100211b0c450b410b21104100211b0c440b410c21104100211b0c430b200241e0076a2001106d20022802e0072206450d4120022902e407210a42002111410d21104100211b0c420b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e8086a200110e80120022d00e8084101460d00200241e0076a200241e8086a41017241e000109a051a20024198026a2001106c2002280298020d002001280204200228029c022204490d002004417f4c0d12024002400240024020040d004101210341010d010c040b2004102e2203450d0120072802002004490d02200320012802002004109a052105200128020422062004490d212001200620046b3602042001200128020020046a3602002005450d030b20024188066a200241e0076a41e000109a051a200241a8056a20024188066a41e000109a051a2000410c6a2004360200200041086a20043602002000200336020420004107360200200041106a200241a8056a41e000109a051a20004180016a20024188076a41106a290300370300200041f8006a20024188076a41086a290300370300200041f0006a2002290388073703000c470b200441011037000b2003102a0b200041133602000c440b2006450d3e20042d0001210520012003417e6a221d3602042001200441026a360200200541104b0d3e410e211a4100211c024002400240024002400240024002400240024002400240024002400240024020050e11000102030405060708090a0b0c4d0d0e0f000b200241e0076a200110810120022802e0074113460d4d200241e8086a200241e0076a418801109a051a41880110282206450d382006200241e8086a418801109a052104200241a0026a2001109f01024020022903a002a7450d002004106a2004102a0c4e0b200241b0026a290300210a2004411876211c20022903a8022211422088a7211f2011a7211b4101211a0c4c0b200241b8026a2001106c20022802b8020d4c20022802bc022206411876211c4102211a0c4a0b200241c0026a2001106c20022802c0020d4b20072802002204450d4b20022802c4022106200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071220d41064b0d4b2006411876211c200341077621084103211a0c480b200241c8026a2001106c20022802c8020d4a20072802002204450d4a20022802cc022106200128020022052d0000210320012004417f6a3602042001200541016a360200200341ff0071220d41064b0d4a2006411876211c200341077621084104211a0c470b201d4104490d492004280002210620012003417a6a3602042001200441066a3602002006411876211c4105211a0c470b200241e0076a200110810120022802e0074113460d48200241e8086a200241e0076a418801109a051a41880110282206450d342006200241e8086a418801109a05411876211c4106211a0c460b200241e0076a200110810120022802e0074113460d47200241e8086a200241e0076a418801109a051a41880110282206450d342006200241e8086a418801109a05411876211c4107211a0c450b200241e0076a200110810120022802e0074113460d46200241e8086a200241e0076a418801109a051a41880110282206450d342006200241e8086a418801109a05411876211c4108211a0c440b41002105200241003a0088092003417e6a2109417d21060340024020092005470d00200541ff0171450d47200241003a0088090c470b200241e8086a20056a200420056a220741026a2d00003a00002001200320066a3602042001200741036a3602002002200541016a22073a0088092006417f6a21062007210520074120470d000b200241b0056a2205200241f1086a290000370300200241a8056a41106a200241f9086a290000370300200241bf056a220620024180096a290000370000200220022900e908220a3703a805200320076b2203417e6a4104490d4520022d00ac05210920022f01aa05210d200241b5056a330000211120023500b105211220052d0000211b20022f01ae05211a200241bd056a3100002113200241bb056a330000211620023500b705211820022d00e80821082006280000210f20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e200420076a220441026a280000210c20012003417a6a22053602042001200441066a220736020020054104490d45200d2009411074722106200aa7210d200728000021192001200341766a36020420012004410a6a36020020182016201342108684422086844208862012201142208684221142ffffffffffff3f83221242288884210a2012421886201a201b41107472ad42ffffff078384a7211b2011420888a7211f4109211a0c440b41002105200241003a0088092003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d46200241003a0088090c460b200241e8086a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0088092003417f6a21032006210520064120470d000b200241b0056a200241f1086a290000370300200241bf056a220120024180096a290000370000200241a8056a41106a200241f9086a290000370300200220022900e90822113703a80520022f01aa0520022d00ac0541107472210620022901ae052212422088a7211f20022d00e80821082001280000210f200241b6056a290100210a20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e2011a7210d2012a7211b410a211a0c430b200241d0026a2001106c20022802d0020d4320022802d4022206411876211c410b211a0c410b200241e8026a2001106c20022802e8020d4220022802ec022106200241e0026a2001106c20022802e0020d4220022802e402211b200241d8026a2001106c20022802d8020d4220022802dc02211f2006411876211c410c211a0c410b41002105200241003a0088092003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d43200241003a0088090c430b200241e8086a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0088092003417f6a21032006210520064120470d000b200241b0056a200241f1086a290000370300200241bf056a220120024180096a290000370000200241a8056a41106a200241f9086a290000370300200220022900e90822113703a80520022f01aa0520022d00ac0541107472210620022901ae052212422088a7211f20022d00e80821082001280000210f200241b6056a290100210a20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e2011a7210d2012a7211b410d211a0c400b41002105200241003a0088092003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d42200241003a0088090c420b200241e8086a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0088092003417f6a21032006210520064120470d000b200241b0056a2201200241f1086a290000370300200241a8056a41106a200241f9086a290000370300200241bf056a220420024180096a290000370000200220022900e90822123703a80520023500b705200241bb056a330000200241bd056a310000421086844220868442088620023500b105200241b5056a33000042208684221142288884210a201142188620023301ae0520013100004210868484a7211b20022f01aa0520022d00ac054110747221062011420888a7211f20022d00e80821082004280000210f20022d00ad05211c20022d00a905211020022800c305210b20022d00be05210e2012a7210d410f211a0c3f0b41002105200241003a0088092003417e6a21092003417d6a21060340024020092005470d00200541ff0171450d41200241003a0088090c410b200241e8086a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a0088092006417f6a21062007210520074120470d000b200241b0056a200241f1086a290000370300200241b8056a200241f9086a290000370300200241bf056a220520024180096a290000370000200220022900e908220a3703a805200241d8076a41046a20022d00ac053a0000200241e8066a41046a200241b5056a2f00003b01002002200a3e02d807200220022800b1053602e8062003417e6a2007460d3f20022d00e808210820022800ad05211c2005290000211120022900b705210a200420076a220441026a2d00002109200120063602042001200441036a360200200941064b0d3f20024190076a200241e8066a41046a2f01003b0100200220022802d807220d3602d007200220022802e80636028c072002201c360288072002200a37019207200a423888201142088684a7210e4110211a20022f01d207200241d8076a41046a2d00004110747221062011422088a7210b2002290089072212422088a7211f20024191076a290000210a20022d00d10721102011a7210f2012a7211b0c3e0b4111211a0c3d0b200241e0076a200110e90120022d00e0074105470d0d200041133602000c420b200241e0076a200110e90120022d00e0074105470d0d200041133602000c410b2006450d3720042d0001210520012003417e6a3602042001200441026a360200200541094b0d37024002400240024002400240024002400240024020050e0a00010203040506070809000b200241e0076a2001107520022802e0072204450d40200241e8076a280200210520022802e4072103200241f0026a2001106c024020022802f002450d0020030d400c410b0240200728020022094104490d0020022802f402210620012802002208280000210720012009417c6a220d3602042001200841046a360200200d4110490d002008410c6a29000021122008290004211320012009416c6a3602042001200841146a360200410121010c3f0b20030d3f0c400b200241e0076a2001107520022802e0072204450d3f200241e8076a280200210520022802e4072103200241f8026a2001106c024020022802f802450d002003450d400c3f0b0240200728020022094104490d0020022802fc02210620012802002208280000210720012009417c6a220d3602042001200841046a360200200d4110490d002008410c6a29000021122008290004211320012009416c6a3602042001200841146a360200410221010c3e0b20030d3e0c3f0b20024190036a2001106c2002280290030d3e2002280294032104200241e0076a200110a50120022d00e0074102460d3e20024188066a41086a200241f8076a29030037030020024188066a41106a20024180086a2802003602002002200241e0076a41106a29030037038806200241ec076a2802002107200241e0076a41086a280200210620022802e407210520022802e007210320024188036a2001106c2002280288030d3e200228028c03210920024180036a2001106c2002280280030d3e20024198066a280200210820024190066a29030021122002290388062113200228028403ad210a42002111410321010c3c0b20024198036a2001106c2002280298030d3d41042101200228029c0321040c3b0b200241a0036a2001106c20022802a0030d3c4105210120022802a40321040c3a0b200241e0076a200110a50120022d00e0074102460d3b20024188066a41086a200241f8076a29030037030020024188066a41106a20024180086a2802003602002002200241e0076a41106a29030037038806200241e0076a41086a290300211620022903e0072118200241b0036a2001109f0120022903b003a70d3b200241b0036a41106a290300211120022903b803210a200241a8036a2001106c20022802a8030d3b20022802ac032108200241a8056a41106a20024188066a41106a280200360200200241a8056a41086a20024188066a41086a290300370300200220022903880622173703a8052018422088a721032016422088a72106200241b4056a290200211220022902ac0521132017a721072018a721042016a72105410621010c390b200241c8036a2001106c20022802c8030d3a4107210120022802cc0321040c380b200241e0076a200110a50120022d00e0074102460d39200241fc076a2902002112200241f4076a2902002113200241f0076a2802002107200241ec076a280200210641082101200241e0076a41086a280200210520022802e407210320022802e00721040c370b200241d0036a2001106c20022802d0030d384109210120022802d40321040c360b200241d8036a2001106c20022802d8030d37410a210120022802dc0321040c350b2006450d3320042d0001210520012003417e6a3602042001200441026a360200200541034b0d33024002400240024020050e0400010203000b41002105200241003a0080082003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d38200241003a0080080c380b200241e0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0080082003417f6a21032006210520064120470d000b200241a8056a41106a200241f1076a290000370300200241b0056a200241e0076a41096a290000220a370300200241bf056a2201200241e0076a41186a290000370000200241e8066a41096a200a370000200241e8066a41106a200241b7056a290000370000200220022d00e007220d3a00e806200220022900e1073700e9062001280000210f20022800c305210b20022800ef06220c411876211020022800eb062201411876210820022d00ff06211b20022900f706211220022800f306211a20022d00ea06211920022d00e906211f4101211c0c350b41002105200241003a0080082003417e6a21072003417d6a21030340024020072005470d00200541ff0171450d37200241003a0080080c370b200241e0076a20056a200420056a220641026a2d00003a0000200120033602042001200641036a3602002002200541016a22063a0080082003417f6a21032006210520064120470d000b200241b0056a200241e9076a290000370300200241bf056a2204200241e0076a41186a290000370000200241a8056a41106a200241f1076a290000370300200220022900e107220a3703a80520022f01aa0520022d00ac0541107472210120022901ae052211a7220c41187621102011422088a7211a20022d00e007210d2004280000210f200241b6056a290100211220022d00ad05210820022d00a905211920022800c305210b20022d00be05211b200aa7211f4102211c0c340b41002105200241003a008008410220036b21092003417d6a210603400240200920056a0d00200541ff0171450d36200241003a0080080c360b200241e0076a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a0080082006417f6a21062007210520074120470d000b200241b0056a200241e9076a290000370300200241b8056a200241f1076a290000370300200241bf056a2205200241f8076a290000370000200220022900e107220a3703a805200241d8076a41046a20022d00ac053a0000200241e8066a41046a200241b5056a2f00003b01002002200a3e02d807200220022800b1053602e80620022d00e007210d20022800ad0521082005290000211320022900b705211241002105200241003a008008200420076a2109200720036b41026a210303400240200320056a0d00200541ff0171450d36200241003a0080080c360b200241e0076a20056a200920056a220441026a2d00003a0000200120063602042001200441036a3602002002200541016a22043a0080082006417f6a21062004210520044120470d000b200241bf056a2201200241f8076a290000370000200241a8056a41106a200241f1076a290000370300200241a8056a41086a2203200241e9076a290000370300200220022900e10722163703a80520022d00e007210420012800002109200241bb056a3300002111200241bd056a3100002118200241b5056a330000210a2003310000211720022801aa05210620022d00a905210520022800c305210e20022d00be05210720023500b705211520023500b105211420023301ae052121200241d0076a41046a2201200241d8076a41046a2d00003a0000200220022802d8073602d007200220083602880720024188076a41086a200241e8066a41046a2f01003b0100200220022802e80636028c0720022012370192072002419a076a20133701002014200a422086842214421886202120174210868484210a201520112018421086844220868442088620144228888421112012423888201342088684a7211b2008410876210c20022f01d20720012d00004110747221012013422088a7210b2002290091072112200228008d07211a20022d008c07211020022d00d107211920022d00d007211f2016a721032013a7210f4103211c0c330b200241e0076a2001106d20022802e0072201450d3320022802e407220c411876211020014118762108200241e8076a280200211a4104211c0c320b024002402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e0036a2001106c20022802e003450d010b200041133602000c3f0b20022802e40321012000410d36020020002001360204200041086a200241e8086a418001109a051a0c3e0b02402006450d0020042d0001210520012003417e6a3602042001200441026a36020020050d00200241e8036a2001106c20022802e8030d00200128020420022802ec032204490d002004417f4c0d0b024002400240024020040d00410121030c010b2004102e2203450d0120072802002004490d02200320012802002004109a051a200128020422052004490d1b2001200520046b3602042001200128020020046a3602000b2003450d02200020033602042000410e360200200041086a2004ad220a422086200a84370200200041106a200241e8086a41f800109a051a0c400b200441011037000b2003102a0b200041133602000c3d0b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541024b0d0002400240024020050e03000102000b200241f0036a2001109f0120022903f003a70d0220024180046a290300210a20022903f8032111200241e0076a200110a50120022d00e0074102460d02200241fc076a2902002112200241f4076a2902002113200241f0076a2802002101200241ec076a2802002104200241e8076a280200210320022802e407210520022802e0072106410121070c310b20024188046a2001106c2002280288040d0141022107200228028c0421060c300b20024190046a2001106c2002280290040d004103210720022802940421060c2f0b200041133602000c3c0b02402006450d0020042d0001210520012003417e6a3602042001200441026a360200200541044b0d0002400240024002400240024002400240024020050e050001020607000b200241e8086a200110ea0120022d00d8094102460d08200241e8076a20024198096a290300370300200241f0076a200241a0096a29030037030020022002290390093703e0072002418c096a280200210b20024184096a2802002104200241fd086a2800002108200241f9086a280000210d200228028809211b20022d008309210520022d008209210620022d008109210f20022d00f808210e20022903f008210a20022903e8082111200241d8096a2903002113200241b8096a2903002116200241c5096a2800002101200241c1096a280000210320022903d009211820022903b009211720022802cc09210720022d00cb09210c20022d00ca09211f20022d00c909211c20022d00c009211d20022903a8092112410121220c020b200241a0046a2001109e0120022903a004a70d0720022903a804210a20024198046a2001106c2002280298040d072001280204200228029c042204490d072004417f4c0d1002400240024020040d00410121090c010b2004102e2209450d0120072802002004490d08200920012802002004109a051a200128020422032004490d202001200320046b3602042001200128020020046a3602000b2009450d082004ad22114220862011842111200241e0076a41106a200241e8086a41106a290300370300200241e0076a41086a200241e8086a41086a290300370300200220022903e8083703e007410221220c350b200441011037000b200241e8086a200110a50120022d00e8084102460d06200241f4086a290200210a20024188096a280200210420024187096a2d0000210520024186096a2d0000210620024185096a2d0000210f20024181096a2800002108200241fd086a280000210d200241fc086a2d0000210e20022902ec08211120022802e8082109200241c8046a2001109f0120022903c804a70d06200241d8046a290300211320022903d0042116200241b8046a2001109e0120022903b804a70d0620022903c0042112200241b0046a2001106c20022802b0040d06200128020420022802b404220b490d06200b417f4c0d0f02400240200b0d004101211b41010d010c080b200b102e221b450d022007280200200b490d03201b2001280200200b109a05210320012802042207200b490d1f20012007200b6b36020420012001280200200b6a3602002003450d070b200241f0076a2013370300200220163703e8072002200b3602e007410321220b0c320b200b41011037000b201b102a0c030b200241f8046a2001109f0120022903f804a70d0220024188056a290300210a2002290380052111200241e8046a2001109e0120022903e804a70d0220022903f004211241002103200241003a0088092007280200417f6a21040240024002400240024003402004417f460d01200241e8086a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a0088092004417f6a21042005210320054120470d000b20024190076a200241e8086a410e6a290100221337030020024198076a200241e8086a41166a2204290100370300200241a0076a20024186096a2f01003b0100200241e8066a410e6a2013370100200241e8066a41166a20042f01003b0100200220022d00e80822103a00e806200220022800e9083600e906200220022d00ed083a00ed06200220022901ee0822133701ee062002201337038807200228019e072108200228019a07210d200241e0046a2001106c20022802e0040d07200128020420022802e404220b490d07200b417f4c0d10200b0d01410121040c020b200341ff0171450d06200241003a0088090c060b200b102e2204450d012007280200200b490d0220042001280200200b109a051a20012802042203200b490d1e20012003200b6b36020420012001280200200b6a3602000b2004450d04200220113703e007200220123703f0072002200a3703e807200241f7066a290000210a20022900ef06211120022d00ff06210e20022800eb06210920022d00ea06211a20022d00e906211941042122200b211b0c310b200b41011037000b2004102a0c020b41002105200241003a0088092003417e6a21092003417d6a21060340024020092005470d00200541ff0171450d03200241003a0088090c030b200241e8086a20056a200420056a220741026a2d00003a0000200120063602042001200741036a3602002002200541016a22073a0088092006417f6a21062007210520074120470d000b2003417e6a2007460d01200241f7086a290000210a20022900ef08211120022d00e808211020022d00e908211920022d00ea08211a20022800eb08210920022d00ff08210e200228028009210d2002280284092108200420076a220c41026a2d0000211f200120063602042001200c41036a360200201f41014b0d014100210f02400240201f0e020100010b41002104200241003a008809200720036b41036a2106200320076b417c6a210303400240200620046a0d00200441ff0171450d04200241003a0088090c040b200241e8086a20046a200c20046a220541036a2d00003a0000200120033602042001200541046a3602002002200441016a22053a0088092003417f6a21032005210420054120470d000b200241b0056a200241f1086a290000370300200241b8056a200241f9086a290000370300200241bf056a220120024180096a290000370000200220022900e90822123703a805200241d8076a41046a20022d00ac053a0000200241e8066a41046a2203200241b5056a2f00003b0100200220123e02d807200220022800b1053602e80620022d00e808210620022800ad05211b2001290000211320022900b705211220022802e806210b20022800d907210420022d00d8072105200220032f01003b0188074101210f0b200241ea076a2013370100200241f6076a200241ce076a2f01003b0100200220022f0188073b01e007200220123701e207200220022801ca073601f207410521220c2e0b2009102a0b200041133602000c3b0b2006450d2a20042d0001210520012003417e6a3602042001200441026a360200200541024b0d2a0240024002400240024020050e03000102000b200241e0076a200110810120022802e0074113470d020c2e0b200241e8086a200110a5014102210120022d00e8084102460d2d200241a8056a41106a20024188096a280200360200200241a8056a41086a20024180096a2903003703002002200241e8086a41106a29030022123703a80520022903e8082213422088a72103200241e8086a41086a2903002216422088a72105200241b4056a290200210a20022902ac0521112013a721042012a721062016a721070c020b200241e8086a200110a50120022d00e8084102460d2c20024184096a290200210a200241fc086a2902002111200241f8086a2802002106200241f4086a2802002105200241f0086a280200210720022802ec08210320022802e8082104200241e0076a200110810120022802e0074113460d2c200241e8086a200241e0076a418801109a051a41880110282209450d1b2009200241e8086a418801109a051a410321010c010b200241e8086a200241e0076a418801109a051a41880110282204450d192004200241e8086a418801109a051a410121010b2000200136020420004111360200200041246a200a3702002000411c6a20113702002000412c6a2009360200200041186a2006360200200041146a2005360200200041106a20073602002000410c6a2003360200200041086a2004360200200041306a20024188066a41d800109a051a0c3a0b2006450d2820042d0001210520012003417e6a22063602042001200441026a36020020050d2820064104490d282004280002210b20012003417a6a3602042001200441066a360200200241a0056a2001106c20022802a0050d28200128020420022802a4052205490d282005417f4c0d060240024020050d004101210c41010d010c2a0b2005102e220c450d2520072802002005490d28200c20012802002005109a052104200128020422032005490d1a2001200320056b3602042001200128020020056a3602002004450d290b20024198056a2001106c2002280298050d262007280200410c6e220f410c6c2204417f4c0d06200228029c0521100240024020040d004104210e0c010b20041028220e450d1b0b0240024002400240024002402010450d00410021084100210341002109034020024190056a2001106c2002280290050d0320012802042002280294052204490d032004417f4c0d0d0240024020040d004101210d0c010b2004102e220d450d2b20072802002004490d03200d20012802002004109a051a200128020422062004490d232001200620046b3602042001200128020020046a3602000b200941016a210602402009200f470d0020082006200820064b1b220fad420c7e220a422088a70d3f200aa7221b4100480d3f0240024020090d00201b1028210e0c010b200e2003201b102c210e0b200e450d240b200e20036a2209200d360200200941046a2004ad220a422086200a84370200200841026a21082003410c6a21032006210920102006470d000b0b200e450d2b200c450d2d200728020022034104490d0220012802002207280000210820012003417c6a22043602042001200741046a36020020044104490d032007280004210d2001200341786a22093602042001200741086a36020041002104200241003a00a809200341776a2103034020092004460d05200241e8086a20046a200720046a220641086a2d00003a0000200120033602042001200641096a3602002002200441016a22063a00a8092003417f6a210320062104200641c000470d000b200241e0076a41386a2201200241e8086a41386a290300370300200241e0076a41306a2204200241e8086a41306a290300370300200241e0076a41286a2203200241e8086a41286a290300370300200241e0076a41206a2207200241e8086a41206a290300370300200241e0076a41186a2209200241e8086a41186a290300370300200241e0076a41106a221b200241e8086a41106a290300370300200241e0076a41086a221a200241e8086a41086a290300370300200220022903e8083703e007200641ff017141c000490d2a20024188066a41386a2206200129030037030020024188066a41306a2004290300220a37030020024188066a41286a2003290300221137030020024188066a41206a2007290300221237030020024188066a41186a2009290300221337030020024188066a41106a201b290300221637030020024188066a41086a201a2903002218370300200220022903e007221737038806200241a8056a41306a200a370300200241a8056a41286a2011370300200241a8056a41206a2012370300200241a8056a41186a2013370300200241a8056a41106a2016370300200241a8056a41086a2018370300200241a8056a41386a2006290300370300200220173703a805200c450d2d20024188076a41386a2201200241a8056a41386a29030037030020024188076a41306a2204200241a8056a41306a29030037030020024188076a41286a2203200241a8056a41286a29030037030020024188076a41206a2206200241a8056a41206a29030037030020024188076a41186a2207200241a8056a41186a29030037030020024188076a41106a2209200241a8056a41106a29030037030020024188076a41086a221b200241a8056a41086a290300370300200220022903a80537038807200041246a200d360200200041206a20083602002000411c6a2010360200200041186a200f360200200041146a200e360200200041106a20053602002000410c6a2005360200200041086a200c3602002000200b36020420004112360200200041286a200229038807370200200041306a201b290300370200200041386a2009290300370200200041c0006a2007290300370200200041c8006a2006290300370200200041d0006a2003290300370200200041d8006a2004290300370200200041e0006a200129030037020020004180016a200241e8066a41186a290300370300200041f8006a200241e8066a41106a290300370300200041f0006a200241e8066a41086a290300370300200041e8006a20022903e8063703000c3e0b200d102a0b02402009450d00200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200341746a22030d000b0b200f450d29200e102a0c290b02402005450d00200c102a0b02402010450d002010410c6c2104200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200441746a22040d000b0b200f450d2a200e102a0c2a0b02402005450d00200c102a0b02402010450d002010410c6c2104200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200441746a22040d000b0b200f450d29200e102a0c290b200441ff0171450d25200241003a00a8090c250b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c380b02402006450d0020012003417e6a3602042001200441026a3602000b200041133602000c370b200041133602000c360b200041086a20022902e4073702002000200136020420004103360200200041106a200241e8086a41f800109a051a0c350b20024188066a41206a200241e0076a41206a290300220a37030020024188066a41186a200241e0076a41186a290300221137030020024188066a41106a200241e0076a41106a290300221237030020024188066a41086a200241e0076a41086a2903002213370300200220022903e00722163703880620004109360200200020163702042000410c6a2013370200200041146a20123702002000411c6a2011370200200041246a200a3702002000412c6a200241e8086a41dc00109a051a0c340b20024188066a41206a200241e0076a41206a290300220a37030020024188066a41186a200241e0076a41186a290300221137030020024188066a41106a200241e0076a41106a290300221237030020024188066a41086a200241e0076a41086a2903002213370300200220022903e0072216370388062000410a360200200020163702042000410c6a2013370200200041146a20123702002000411c6a2011370200200041246a200a3702002000412c6a200241e8086a41dc00109a051a0c330b1036000b200420031044000b200420031044000b200441041037000b200420031044000b200320091044000b201041041037000b200441041037000b200420061044000b200b41041037000b200441041037000b202041041037000b200420061044000b200420051044000b200420031044000b200b20071044000b200b20031044000b41880141081037000b41880141081037000b200520031044000b200441041037000b200420061044000b201b41041037000b200441011037000b200441011037000b41880141081037000b41880141081037000b41880141081037000b41880141081037000b200441011037000b200541011037000b02402005450d00200c102a0b02402010450d002010410c6c2104200e210103400240200141046a280200450d002001280200102a0b2001410c6a2101200441746a22040d000b0b200f450d02200e102a0c020b2005450d010b200c102a0b200041133602000c100b200041133602000c0f0b20024188066a41106a221e200241e0076a41106a29030037030020024188066a41086a2220200241e0076a41086a290300370300200220022903e00737038806200041346a200b360200200041306a201b3602002000412c6a2004360200200020053a002b200020063a002a2000200f3a0029200041256a2008360000200041216a200d360000200041206a200e3a0000200041186a200a370200200041106a20113700002000410c6a20093600002000201a3a000b200020193a000a200020103a0009200041086a20223a000020004110360200200041d0006a2012370200200041e9006a2003360000200041ed006a2001360000200041f4006a2007360200200041f8006a201837020020004180016a20133702002000200c3a00732000201f3a00722000201c3a0071200041e8006a201d3a0000200041d8006a2017370200200041e0006a2016370200200041386a200229038806370200200041c0006a2020290300370200200041c8006a201e2903003702000c0e0b2000410f360200200041386a200a370200200041306a2011370200200041286a2012370200200041206a20133702002000411c6a2001360200200041186a2004360200200041146a2003360200200041106a20053602002000410c6a2006360200200041086a2007360200200041c0006a200241e8086a41c800109a051a0c0d0b2000200e3600412000200936003d200020053a0027200020033a0026200020043a0025200020193a00072000201f3a00062000200d3a00052000201c3a00042000410c360200200041346a20113700002000412c6a200a3700002000413c6a20073a0000200041286a2006360000200041216a200b3600002000411d6a200f3600002000411c6a201b3a0000200041146a2012370000200041106a201a3600002000410c6a2010411874200c41ffffff077172360000200041086a2008411874200141ffffff07717236000020004180016a200241a0096a290300370300200041f8006a20024198096a290300370300200041f0006a200241e8086a41286a290300370300200041e8006a20024188096a290300370300200041e0006a200241e8086a41186a290300370300200041d8006a200241e8086a41106a290300370300200041d0006a200241e8086a41086a290300370300200041c8006a20022903e8083703000c0c0b200041133602000c0b0b2000410b360200200041c0006a2011370200200041386a200a370200200041286a2012370200200041206a2013370200200041346a2009360200200041306a20083602002000411c6a2007360200200041186a2006360200200041146a2005360200200041106a20033602002000410c6a2004360200200041086a2001360200200041c8006a20022903e808370300200041d0006a200241e8086a41086a290300370300200041d8006a200241e8086a41106a290300370300200041e0006a200241e8086a41186a290300370300200041e8006a200241e8086a41206a290300370300200041f0006a200241e8086a41286a290300370300200041f8006a200241e8086a41306a29030037030020004180016a200241e8086a41386a2903003703000c0a0b2004102a0b200041133602000c080b4100211f4200210a0c010b4100211f4200210a0b200020093a0029200020103a000b2000200d3a000a200020083a000920004108360200200041186a200a370200200041346a4100360200200041306a20193602002000412c6a200c360200200041256a200b360000200041216a200f360000200041206a200e3a0000200041086a201a3a00002000410c6a201c411874200641ffffff077172360200200041106a201fad422086201bad84370200200041386a20024188066a41d000109a051a0c050b200041133602000c040b200041133602000c030b200020083a002b2000200d3a002a2000200c3a0029200020093a000920004106360200200041386a2013370200200041306a2012370200200041186a2011370200200041106a200a3702002000412c6a200b360200200041216a200f360000200041206a200e3a00002000410c6a2006360200200041086a20103a0000200041256a201b201a41ff017172360000200041c0006a200241e8086a41c800109a051a0c020b1031000b20004100360200200041106a200a3702002000410c6a2005360200200041086a2009360200200041186a200241e8086a41f000109a051a0b200241f0096a24000bf602010b7f230041106b22022400200241086a2001106c0240024002400240024020022802080d0020012802042203417c712204417f4c0d02200228020c210502400240200341027622060d00410421070c010b200410282207450d040b02402005450d0041002108410021094100210403400240024002402001280204220a4104490d00200441016a21032001280200220b280000210c2001200a417c6a3602042001200b41046a36020020042006470d02024020082003200820034b1b220641ffffffff03712006470d002006410274220a41004e0d020b1031000b200041003602002006450d052007102a0c050b0240024020040d00200a102821070c010b20072009200a102c21070b2007450d070b200720096a200c360200200841026a2108200941046a21092003210420052003470d000b0b2000200636020420002007360200200041086a20053602000c010b200041003602000b200241106a24000f0b1036000b200441041037000b200a41041037000bbf0701107f230041f0006b22032400200341206a2001200228020c22041102000240024020032802200d002000410036020820004201370200200120022802001103002002280204450d012001102a0c010b200341c8006a41106a200341206a41106a290300370300200341c8006a41086a200341206a41086a290300370300200341c8006a41186a200341206a41186a290300370300200341c8006a41206a200341206a41206a280200360200200341086a200341d4006a290200370300200341106a200341dc006a290200370300200341186a200341e4006a290200370300200320032903203703482003200329024c370300200341c8006a2001200228021022051102000240417f2003280248220641016a220720072006491b220641ffffff3f712006470d0020064105742207417f4c0d004101210841012109024002402007450d00200710282209450d010b20092003290300370000200941186a200341186a220a290300370000200941106a200341106a220b290300370000200941086a200341086a220c290300370000200341206a200120041102000240024020032802200d002006210d0c010b200341c8006a41047221074120210e410121080340200341c8006a41206a200341206a41206a280200360200200341c8006a41186a220f200341206a41186a290300370300200341c8006a41106a2210200341206a41106a290300370300200341c8006a41086a2211200341206a41086a29030037030020032003290320370348200c200741086a290000370300200b200741106a290000370300200a200741186a29000037030020032007290000370300200f200a2903003703002010200b2903003703002011200c290300370300200320032903003703480240024020082006460d002006210d0c010b200341206a2001200511020002402006417f2003280220220d41016a22122012200d491b6a220d2006490d0020064101742212200d2012200d4b1b220d41ffffff3f71200d470d00200d41057422124100480d000240024020060d002012102821090c010b200920064105742012102c21090b20090d01201241011037000b1031000b2009200e6a22062003290348370000200641186a200f290300370000200641106a2010290300370000200641086a2011290300370000200341206a20012004110200200e41206a210e200841016a2108200d210620032802200d000b0b2001200228020011030002402002280204450d002001102a0b200020083602082000200d360204200020093602000c020b200741011037000b1036000b200341f0006a24000bad08040c7f017e057f037e23004180016b22022400024002400240200141086a220328020022042001410c6a2802002205460d002001280210220628020021072006280208220841014b210903402003200441206a220a360200200241e0006a41186a200441186a290000370300200241e0006a41106a200441106a290000370300200241e0006a41086a200441086a29000037030020022004290000370360410021040240024020090d0020080e020401040b2008210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a4120109c054101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a4120109c050d02200a2104200a2005470d000b0b20004100360208200042013702002001280204450d012001280200102a0c010b200241c0006a41086a2204200241e0006a41086a290300370300200241c0006a41106a220b200241e0006a41106a290300370300200241c0006a41186a220c200241e0006a41186a29030037030020022002290360220e3703002002200e370340024041201028220f450d00200f2002290340370000200f41186a200c290300370000200f41106a200b290300370000200f41086a2004290300370000200128020421102001280200211102400240200a2005470d0041012112410121130c010b41012112410121130340200628020821032006280200210702400340200241e0006a41186a2208200a41186a290000370300200241e0006a41106a2209200a41106a290000370300200241e0006a41086a2201200a41086a2900003703002002200a290000370360200a41206a210a4100210402400240200341014b0d0020030e020301030b2003210b0340200b410176220c20046a220d20042007200d4105746a200241e0006a4120109c054101481b2104200b200c6b220b41014b0d000b0b200720044105746a200241e0006a4120109c050d01200a2005470d000c030b0b200241c0006a41086a2001290300220e370300200241c0006a41106a20092903002214370300200241c0006a41186a20082903002215370300200220022903602216370340200241186a220b2015370300200241106a220c2014370300200241086a220d200e37030020022016370300024020132012470d000240201241016a22042012490d00201241017422072004200720044b1b221341ffffff3f712013470d00201341057422044100480d000240024020120d0020041028210f0c010b200f20124105742004102c210f0b200f0d01200441011037000b1031000b200f20124105746a22042002290300370000200441186a200b290300370000200441106a200c290300370000200441086a200d290300370000201241016a2112200a2005470d000b0b02402010450d002011102a0b20002012360208200020133602042000200f3602000c010b412041011037000b20024180016a24000bce0401057f23004180016b2202240002400240024020012802042203200128020022046b41e100490d0003402001200441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012001280200220441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012001280200220441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012001280200220441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b20012802042203200128020022046b41e0004b0d000b0b024020042003460d0003402001200441206a360200200241206a2004108601024020022802602204450d00200241206a21010c030b200128020022042001280204470d000b0b200041003602400c010b20002001290300370300200041386a200141386a290300370300200041306a200141306a290300370300200041286a200141286a290300370300200041206a200141206a290300370300200041186a200141186a290300370300200041106a200141106a290300370300200041086a200141086a290300370300200241086a2203200141cc006a290200370300200241106a2205200141d4006a290200370300200241186a2206200141dc006a2802003602002002200141c4006a2902003703002000200436024020002002290300370244200041cc006a2003290300370200200041d4006a2005290300370200200041dc006a20062802003602000b20024180016a24000bf00c030c7f017e067f230041a0026b22022400024002400240411010282203450d002003410029008ab740370000200341086a4100290092b7403700002002429080808080023702e401200220033602e0012002200241e0016a3602a0012001200241a0016a10c80120022802e001210320022802e8012101200241f8006a41186a22044200370300200241f8006a41106a22054200370300200241f8006a41086a220642003703002002420037037820032001200241f8006a1000200241d8006a41186a2004290300370300200241d8006a41106a2005290300370300200241d8006a41086a200629030037030020022002290378370358024020022802e401450d0020022802e001102a0b200241003602e001200241d8006a4120200241e0016a1006210420022802e0012205417f460d012004450d012002200536029c01200220043602980141002103200241003a0038024002400340024020052003470d002002410036029c01200341ff0171450d02200241003a00380c020b200241186a20036a200420036a22012d00003a00002002200141016a360298012002200341016a22013a00382001210320014120470d000b200241f8006a41086a2206200241186a41086a2207290300370300200241f8006a41106a2208200241186a41106a2209290300370300200241f8006a41186a220a200241186a41186a220b290300370300200220022903183703782002200520016b36029c01200241186a20024198016a10d40120022802382203450d00200241e0016a41186a220c200a290300370300200241e0016a41106a220a2008290300370300200241e0016a41086a220d2006290300370300200241e0016a41286a22062007290300370300200241e0016a41306a22072009290300370300200241e0016a41386a2208200b290300370300200220022903783703e00120022002290318370380022002413c6a2802002101200241186a41286a2209290300210e200241a0016a41086a200d290300370300200241a0016a41106a200a290300370300200241a0016a41186a200c290300370300200241a0016a41206a220a200229038002370300200241a0016a41286a220b2006290300370300200241a0016a41306a220c2007290300370300200241a0016a41386a220d2008290300370300200220022903e0013703a001200241186a20024198016a106d20022802180d012001450d002003102a0b41c4d1c3004133200241a0016a419cd9c3001038000b200241f8006a41086a220f200241186a41086a2210280200360200200241e0016a41086a2211200241a0016a41086a290300370300200241e0016a41106a2212200241a0016a41106a290300370300200241e0016a41186a2213200241a0016a41186a290300370300200241e0016a41206a2214200a2903003703002006200b2903003703002007200c2903003703002008200d29030037030020022002290318370378200220022903a0013703e00120102011290300370300200241186a41106a2012290300370300200241186a41186a2013290300370300200241186a41206a201429030037030020092006290300370300200241186a41306a2007290300370300200241186a41386a2008290300370300200241086a41086a200f280200360200200220022903e001370318200220022903783703082005450d022004102a0c020b411041011037000b410021030b200241e0016a41086a2204200241186a41086a290300370300200241e0016a41106a2205200241186a41106a290300370300200241e0016a41186a2206200241186a41186a290300370300200241e0016a41206a2207200241186a41206a290300370300200241e0016a41286a2208200241186a41286a290300370300200241e0016a41306a2209200241186a41306a290300370300200241e0016a41386a220a200241186a41386a290300370300200220022903183703e001200241a0016a41086a220b200241086a41086a280200360200200220022903083703a00102402003450d00200020022903e00137030020002001360244200041c8006a200e370200200041386a200a290300370300200041306a2009290300370300200041286a2008290300370300200041206a2007290300370300200041186a2006290300370300200041106a2005290300370300200041086a2004290300370300200041d8006a200b280200360200200041d0006a20022903a0013702000b20002003360240200241a0026a24000bb00705077f037e097f017e017f23004180016b22022400024002400240200141086a220328020022042001410c6a2802002205460d0020012802102106200241f4006a2107034020032004220841206a2204360200200841086a2903002109200841106a290300210a2008290300210b200241e0006a41186a200841186a290300370300200241e0006a41106a200a370300200241e0006a41086a20093703002002200b3703600240200aa720062802004d0d002001280214220c2007460d002007290000200c290000520d030b20052004470d000b0b20004100360208200042083702002001280204450d012001280200102a0c010b200241086a2204200241e0006a41086a290300370300200241106a2203200241e0006a41106a290300370300200241186a2207200241e0006a41186a29030037030020022002290360220a3703202002200a3703000240024002400240024041201028220d450d00200d2002290300370300200d41186a2007290300370300200d41106a2003290300370300200d41086a20042903003703002001280204210e2001280200210f200541606a2008460d03200841206a2110200541606a2111200241f4006a21014101211241012113200d21140340200c2001460d042010210802400340200241e0006a41186a2204200841186a290300370300200241e0006a41106a2203200841106a290300220a370300200241e0006a41086a2207200841086a290300370300200220082903003703600240200aa720062802004d0d002001290000200c290000520d020b2005200841206a2208470d000c070b0b200241206a41086a2007290300220a370300200241206a41106a20032903002209370300200241206a41186a2004290300220b3703002002200229036022153703202004200b370300200320093703002007200a37030020022015370360024020132012470d00201241016a22132012490d04201241017422102013201020134b1b221341ffffff3f712013470d04201341057422104100480d040240024020120d002010102821140c010b201420124105742010102c21140b2014450d030b200841206a2110201420124105746a22162002290360370300201641186a2004290300370300201641106a2003290300370300201641086a2007290300370300201241016a211220112008470d000c050b0b412041081037000b201041081037000b1031000b4101211241012113200d21140b0240200e450d00200f102a0b2000201236020820002013360204200020143602000b20024180016a24000bed0704067f017e0a7f027e230041f0006b22032400200341206a2001200228020c22041102000240024020032802200d002000410036020820004208370200200120022802001103002002280204450d012001102a0c010b200341c8006a41106a200341206a41106a290300370300200341c8006a41086a200341206a41086a290300370300200341c8006a41186a200341206a41186a290300370300200341c8006a41206a200341206a41206a280200360200200341086a200341d4006a290200370300200341106a200341dc006a290200370300200341186a200341e4006a290200370300200320032903203703482003200329024c370300200341c8006a2001200228021022051102000240024002400240417f2003280248220641016a220720072006491b2208ad42287e2209422088a70d002009a72206417f4c0d000240024020060d004108210a4108210b0c010b20061028220a450d02200a210b0b200a2003290300370300200a41186a200341186a220c290300370300200a41106a200341106a220d290300370300200a41086a200341086a290300370300200b4201370320200341206a200120041102000240024020032802200d004101210e0c010b200341c8006a410472210641c800210f4101210e0340200341c8006a41206a200341206a41206a280200360200200341c8006a41186a2210200341206a41186a290300370300200341c8006a41106a2211200341206a41106a290300370300200341c8006a41086a2212200341206a41086a29030037030020032003290320370348200341086a2207200641086a290200370300200d200641106a290200370300200c200641186a290200370300200320062902003703002010200c2903003703002011200d29030037030020122007290300370300200320032903003703480240200e2008470d00200341206a200120051102002008417f2003280220220741016a221320132007491b6a22072008490d06200841017422132007201320074b1b2213ad42287e2209422088a70d062009a722074100480d060240024020080d0020071028210a0c010b200a200841286c2007102c210a0b200a450d05200a210b201321080b200b200f6a221341606a2207200329034837030020122903002109201129030021142010290300211520134201370300200741186a2015370300200741106a2014370300200741086a2009370300200341206a20012004110200200f41286a210f200e41016a210e20032802200d000b0b2001200228020011030002402002280204450d002001102a0b2000200e360208200020083602042000200b3602000c040b1036000b200641081037000b200741081037000b1031000b200341f0006a24000b02000bef0101057f230041c0006b220524000240024020030d00200041003602000c010b2003280208210620032802002103200541206a41186a22074200370300200541206a41106a22084200370300200541206a41086a220942003703002005420037032020044120200541206a1000200541186a2007290300370300200541106a2008290300370300200541086a200929030037030020052005290320370300200541003602202003200620054120200541206a10012104024020052802202203417f460d002000200336020420002004360200200041086a20033602000c010b200041003602000b200541c0006a24000baf0201027f23004190016b2203240020032002108c010240024020032d000022024102470d00200041003a00000c010b200341e0006a200341286a290300370300200341e8006a200341306a290300370300200341d8006a41186a200341386a290300370300200341d8006a41206a200341c0006a290300370300200341d8006a41286a200341c8006a290300370300200341d8006a41306a200341d0006a2802003602002003200341206a29030037035802402002450d00200041003a00000c010b2003411c6a2802002102200341186a28020021042000200329026c370001200041013a0000200041196a20034184016a290200370000200041116a200341fc006a290200370000200041096a200341d8006a411c6a2902003700002002450d002004102a0b20034190016a24000bd60201057f230041d0016b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f00237027c200220033602782001200241f8006a108f01200228028001210320022802782101200241186a22044200370300200241106a22054200370300200241086a22064200370300200242003703002001200320021000200241d8006a41186a2004290300370300200241d8006a41106a2005290300370300200241d8006a41086a2006290300370300200220022903003703580240200228027c450d002002280278102a0b2002200241d8006a10960220022d00002103200241f8006a200241017241d700109a051a0240024020034102470d00200041023a00000c010b200020033a0000200041016a200241f8006a41d700109a051a0b200241d0016a24000f0b411741011037000b870102017f037e230041e0006b22032400200341086a2002108c010240024020032d000822024102470d00420021040c010b2002410173ad2104200341186a2903002105200341106a290300210620020d00200341246a280200450d00200341206a280200102a0b2000200637030820002004370300200041106a2005370300200341e0006a24000b940201057f230041d0006b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f002370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002412041014100410010032103200241d0006a24002003417f470f0b411741011037000b952801057f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141046a2202280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00003a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00013a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00023a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00033a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00043a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00053a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00063a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00073a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00083a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00093a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000e3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1020012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000f3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00103a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00113a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00123a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00133a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00143a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00153a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00163a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00173a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00183a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00193a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001e3a000002400240200228020020032802002202460d00200128020021040c010b200241016a22042002490d21200241017422052004200520044b1b22054100480d210240024020020d002005102821040c010b200128020020022005102c21040b2004450d2020012004360200200141046a2005360200200141086a28020021020b2003200241016a360200200420026a20002d001f3a00000f0b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200541011037000b1031000b3802017f017e230041106b2203240020032002109101200329030021042000200341086a29030037030820002004370300200341106a24000bf40202057f027e230041d0006b2202240002400240411410282203450d00200341002900cfe140370000200341106a41002800dfe140360000200341086a41002900d7e14037000020024294808080c002370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002410036023020024120200241306a100621030240024020022802302201417f470d0042002107420021080c010b20014110490d02200341086a2900002108200329000021072003102a0b2000200737030020002008370308200241d0006a24000f0b411441011037000b41c4d1c3004133200241306a419cd9c3001038000bbc200b067f017e0d7f067e047f037e017f027e0d7f027e067f230041c0046b22022400200241186a42003703002002420037031020024200370308200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b200241106a21072002413c6a20042f0106360200200241206a41186a4100360200200241346a2004360200200220033602402002410036023020024200370328200220013602242002410036022020024188016a200241206a109301024002400240024020022903a80122084202510d00200241bc016a210920024188016a412c6a210a20024188016a410472210b200241e5016a210c20024188016a41086a2103200241e8026a412c6a210d200241e8026a41106a210e200241b8016a210f200241d0016a21100340200241e8006a41186a220620024188016a41186a2201290300370300200241e8006a41106a221120024188016a41106a2204290300370300200241e8006a41086a22122003290300370300200241c8006a41086a2213200c41086a290000370300200241c8006a41106a2214200c41106a290000370300200241c8006a41186a2215200c41186a29000037030020022002290388013703682002200c290000370348200f29030021162010290300211720022903b001211820022903c801211920022903c001211a20022903d801211b20022802e001211c20022d00e401211d20022d008502210520024188026a41186a200629030037030020024188026a41106a201129030037030020024188026a41086a20122903003703002002200229036837038802200241a8026a41186a22122015290300370300200241a8026a41106a221e2014290300370300200241a8026a41086a221f2013290300370300200220022903483703a8020240024002402005ad42ff0183200820085022061b4201520d0020024188016a20024188026a4200201820061b4200201620061b10940120042903002120200229039001211820022d00a00121062002290388012121200241086a41106a221129030021082002290310211602400240024002400240024020022903084201510d0020214200510d022016201856200820205620082020511b0d04202020087d2018201654ad7d2121201820167d21220c010b20214200510d02427f200820207c201620187c22182016542213ad7c22162013201620085420162008511b22131b2121427f201820131b21220b420121080c030b427f200820207c201620187c22182016542213ad7c22162013201620085420162008511b22131b2121427f201820131b2122420021080c020b202020087d2018201654ad7d200820207d2016201854ad7d20182016562020200856202020085122131b22141b2121201820167d201620187d20141b21222018201658202020085820131bad21080c010b200820207d2016201854ad7d2121201620187d2122420021080b201120213703002002202237031020022008370308200641ff01710d010b024002400240201d41ff0171222341014622060d00200541ff01710d00201c201aa772450d010b20024188016a20024188026a108c010240024020022d0088012211417f6a221341014b0d00024020130e020002000b20110d0420022802a401450d0420022802a001102a0c040b200241c8026a41086a200941086a290200370300200241c8026a41106a200941106a290200370300200241c8026a41186a200941186a290200370300200220092902003703c80220042903002124200229039001212520022802dc01212620022802b801212720022802b401212820022802b001212920022802ac01212a20022802a801212b20022802a401212c20022802a001212d0c020b4102212820110d0120022802a401450d0120022802a001102a0c010b201ba7210402400240201b422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b2002201c3602a801200241003602a001200241003602980120024200370390012002200136028c0120024100360288012002200436029c01200220042f01063602a40120024188016a1095010c020b4102212e02400240024002400240024002400240024020284102460d00202b417f4c0d0102400240202b0d004100212f410121300c010b202b212f202b10282230450d030b2030202d202b109a051a2001200241c8026a41186a2903003703002004200241c8026a41106a2903003703002003200241c8026a41086a290300370300200220022903c802370388012028410146212e202b2131202a2132202521332024213420292135202721360b200241b8036a41186a22372001290300370300200241b8036a41106a22382004290300370300200241b8036a41086a22392003290300370300200241a0046a41086a221d201f290300370300200241a0046a41106a2214201e290300370300200241a0046a41186a2215201229030037030020022002290388013703b803200220022903a8023703a004200541ff0171450d030c020b1036000b202b41011037000b202e4102460d0120302031100420060d0320024188026a109601202f450d022030102a0c020b202e4102460d00200d20022903b803370200200d41086a2039290300370200200d41106a2038290300370200200d41186a2037290300370200200220333703e80220022036360290032002202e36028c032002203536028803200220323602840320022031360280032002202f3602fc02200220303602f802200220343703f0022035213a2033212020342121203221110c030b2006450d004108211120024188016a20024188026a109701109801213a200e41086a20024188016a41086a280200360200200e200229038801370200200d20022903a004370100200d41086a200241a0046a41086a290300370100200d41106a2014290300370100200d41186a2015290300370100427f21202002427f3703f0022002427f3703e80220024108360284034100212e2002410036028c032002203a36028803427f21210c020b20284102460d020240202c0d004100212c0c030b202d102a0c020b4108211120024188016a20024188026a109701109801213a200e41086a20024188016a41086a280200360200200e200229038801370200200d20022903a004370100200d41086a200241a0046a41086a290300370100200d41106a2014290300370100200d41186a2015290300370100427f21202002427f3703f0022002427f3703e80220024108360284034100212e2002410036028c032002203a360288030240202f450d002030102a427f21200b427f21210b0240201a4201520d00200220193703e802200220173703f00220192120201721210b02402023450d00200d20022903a802370000200d41186a2012290300370000200d41106a201e290300370000200d41086a201f2903003700000b0240201c450d0010980121054101212e2002410136028c0320022005360290030b201ba7210502400240201b422088a722120d00200521060c010b2012211320052106034020062802ec0321062013417f6a22130d000b0340200520052f01064102746a41ec036a28020021052012417f6a22120d000b0b20052f010621122002201c3602d803200220123602d403200241003602d003200220053602cc03200241003602c803200242003703c003200220063602bc03200241003602b80320024188016a200241b8036a10990102402002280288014101470d00200228028003211320022802f802211c0340200241e0036a41186a200b41186a2902002208370300200241e0036a41106a200b41106a290200221b370300200241e0036a41086a200b41086a29020022163703002002200b29020022183703e00320022802ac01210520022802b001211e20022802b401210620024180046a41186a200837030020024180046a41106a201b37030020024180046a41086a20163703002002201837038004200142003703002004420037030020034200370300200242003703880120024180046a412020024188016a10002015200129030037030020142004290300370300201d200329030037030020022002290388013703a0042002410036028801201c2013200241a0046a412020024188016a1001211f02402002280288012212417f460d00201120126b21112012450d00201f102a0b0240024020050d00200142003703002004420037030020034200370300200242003703880120024180046a412020024188016a10002015200129030037030020142004290300370300201d200329030037030020022002290388013703a004201c2013200241a0046a412010020c010b200142003703002004420037030020034200370300200242003703880120024180046a412020024188016a10002015200129030037030020142004290300370300201d200329030037030020022002290388013703a004201c2013200241a0046a4120200520061005201120066a2111201e450d002005102a0b20024188016a200241b8036a1099012002280288014101460d000b20022011360284030b200241b8036a1095012037200241c8026a41186a2903003703002038200241c8026a41106a2903003703002039200241c8026a41086a290300370300200220022903c8023703b8030240024020284102460d00200a20022903b803370200200a41086a2039290300370200200a41106a2038290300370200200a41186a20372903003702002002202537038801200220273602b001200220283602ac01200220293602a8012002202a3602a4012002202c36029c012002202d36029801200220263602d40120022024370390012002202b3602a001410121040240202b200228028003470d0002400240202d20022802f8022201460d00202d2001202b109c050d02202a2011470d020c010b202a2011470d010b200a200d4120109c050d0020252020852024202185844200520d002029203a470d0002402028202e470d004100210420284101470d012027200228029003460d010b410121040b0240202c450d00202d102a0b20044102460d002004450d010b2003200241e8026a41d000109a051a200241003a00880120024188026a20024188016a109a010c020b20022802fc02450d0120022802f802102a0c010b201ba7210402400240201b422088a722050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b2002201c3602a801200241003602a001200241003602980120024200370390012002200136028c0120024100360288012002200436029c01200220042f01063602a40120024188016a1095010b20024188016a200241206a10930120022903a80122084202520d000b20022903082108200241206a109b012008500d010c020b200241206a109b010b02402002290310200241186a29030084500d0041f4b5c0001032000b20022903084200520d00200220073602880120024188016a109c010c010b200220073602880120024188016a109d010b200241c0046a24000bf90503087f017e017f23004180026b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241186a2206200520034105746a220741206a290000370300200241106a2208200741186a290000370300200241086a2209200741106a2900003703002002200741086a290000370300200241206a2005200341e0006c6a41e8026a41e000109a051a2001200341016a36020c200120043602082001200536020420024180016a41186a200629030037030020024180016a41106a200829030037030020024180016a41086a2009290300370300200220022903003703800120024180016a41206a200241206a41e000109a051a200020024180016a418001109a051a0c020b200042023703200c010b2001280200210702400240200528020022030d002004ad210a410021030c010b200741016a210720053301044220862004ad84210a0b2005102a200aa7210402400240200a422088a7220620032f01064f0d00200321050c010b034002400240200328020022050d002004ad210a410021050c010b200741016a210720033301044220862004ad84210a0b2003102a200aa7210420052103200a422088a7220620052f01064f0d000b0b200241186a2208200520064105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220b200341106a2900003703002002200341086a290000370300200241206a2005200641e0006c6a41e8026a41e000109a051a200641027420056a418c0b6a280200210302402007417f6a2205450d00034020032802880b21032005417f6a22050d000b0b2001410036020c20012004360208200120033602042001410036020020024180016a41186a200829030037030020024180016a41106a200929030037030020024180016a41086a200b290300370300200220022903003703800120024180016a41206a200241206a41e000109a051a200020024180016a418001109a051a0b20024180026a24000ba90703067f027e017f230041a0016b220424000240024002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b0240200242ffffe883b1de1656200342005220035022051b0d00200a200b844200520d0020004200370300200041013a0018200041106a4200370300200041086a42003703000c040b4101210602402002428080e983b1de1654410020051b0d00411410282205450d0341002106200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202107200441306a41186a22084200370300200441306a41106a22094200370300200441306a41086a220c42003703002004420037033020072005200441306a1000200441186a2008290300370300200441106a2009290300370300200441086a200c2903003703002004200429033037030002402004280224450d002004280220102a0b200441204101410041001003417f470d002001109302200441e8006a2003370300200441e0006a200237030041002106200441306a41086a41003a0000200441396a2001290000370000200441c1006a200141086a290000370000200441c9006a200141106a290000370000200441d1006a200141186a290000370000200441023a003041014100200441306a10cc010b200120022003108f02200041106a200b20037d200a200254ad7d2003200b7d2002200a54ad7d200a200256200b200356200b2003511b22051b3703002000200a20027d2002200a7d20051b370308200020063a001820002005ad3703000c030b411441011037000b41c4d1c3004133200441306a419cd9c3001038000b411441011037000b200441a0016a24000bb00101037f230041306b2201240020012000109901024020012802004101470d000340024020012802242202450d002001280228450d002002102a0b2001200010990120012802004101460d000b0b02402000280204220241f8b9c000460d00200228020021032002102a2003450d00200328020021002003102a2000450d00024020002802002202450d0003402000102a2002210020022802002203210220030d000b0b2000102a0b200141306a24000b870201057f230041d0006b220124000240411710282202450d00200241002900f1d8433700002002410f6a4100290080d943370000200241086a41002900f9d84337000020014297808080f002370224200120023602202000200141206a108f012001280228210220012802202100200141306a41186a22034200370300200141306a41106a22044200370300200141306a41086a220542003703002001420037033020002002200141306a1000200141186a2003290300370300200141106a2004290300370300200141086a20052903003703002001200129033037030002402001280224450d002001280220102a0b200141201009200141d0006a24000f0b411741011037000ba60603037f017e017f230041c0006b22022400200241206a41086a220342003703002002420037032041d8fec5004117200241206a1008200241086a2003290300370300200220022903203703002002410036022020024110200241206a1006210302400240024002400240024020022802202204417f470d00420121050c010b024020030d00420121050c010b20044108490d01200329000021052003102a200542017c21050b200241206a41086a220342003703002002420037032041d8fec5004117200241206a1008200241086a2003290300370300200220022903203703002002200537032020024110200241206a41081007412010282203450d0120032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a2900003700002003412041c000102c2201450d0220012005370020200241206a41186a22034200370300200241206a41106a22044200370300200241206a41086a220642003703002002420037032020014128200241206a1000200241186a2003290300370300200241106a2004290300370300200241086a200629030037030020022002290320370300413710282203450d03200342bac6a1cbc68dd9aff300370000200342f4dec98bf6ac999de400370008200341e5cc85ab073600102003413a3a0016200341ece8013b001420032002290300370017200320022f01083b001f2003200228010a360021200320022f010e3b0025200320022d00103a0027200320022d00113a0028200320022d00123a0029200320022d00133a002a200320022d00143a002b200320022d00153a002c200320022d00163a002d200320022d00173a002e200320022d00183a002f200320022d00193a0030200320022d001a3a0031200320022d001b3a0032200320022d001c3a0033200320022d001d3a0034200320022d001e3a0035200320022d001f3a0036200041ed93c40041c593c4006b410f6a36020820004137360204200020033602002001102a200241c0006a24000f0b41c4d1c3004133200241206a419cd9c3001038000b412041011037000b41c00041011037000b413741011037000ba70101047f230041206b22002400200041106a41086a220142003703002000420037031041d9efc200410d200041106a1008200041086a200129030037030020002000290310370300410021022000410036021020004110200041106a100621010240024020002802102203417f460d002001450d0020034104490d01200128000021022001102a0b200041206a240020020f0b41c4d1c3004133200041106a419cd9c3001038000bdd0605057f047e017f017e047f23004190016b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2203200128020422052f01064f0d01200241e0006a41186a200520034105746a220641206a2900002207370300200241e0006a41106a200641186a2900002208370300200241e0006a41086a200641106a29000022093703002002200641086a290000220a370360200241306a41086a20052003410c6c6a220641f0026a280200220b360200200641e8026a290200210c2001200341016a36020c20012004360208200120053602042002200c3703302000200a3702042000410c6a2009370200200041146a20083702002000411c6a2007370200200041246a200c3702002000412c6a200b360200200041013602000c020b200041003602000c010b2001280200210602400240200528020022030d002004ad210c410021030c010b200641016a210620053301044220862004ad84210c0b2005102a200ca7210402400240200c422088a7220b20032f01064f0d00200321050c010b034002400240200328020022050d002004ad210c410021050c010b200641016a210620033301044220862004ad84210c0b2003102a200ca7210420052103200c422088a7220b20052f01064f0d000b0b200241306a41186a220d2005200b4105746a220341206a290000370300200241306a41106a220e200341186a290000370300200241306a41086a220f200341106a2900003703002002200341086a290000370330200241d0006a41086a22102005200b410c6c6a220341f0026a2802003602002002200341e8026a290200370350200b41027420056a41f0036a280200210302402006417f6a2205450d00034020032802ec0321032005417f6a22050d000b0b2001410036020c200120043602082001200336020420014100360200200241e0006a41186a200d290300220c370300200241e0006a41106a200e2903002207370300200241e0006a41086a200f290300220837030020024188016a201028020022033602002000200229033022093702042000410c6a2008370200200041146a20073702002000411c6a200c370200200041246a2002290350220c3702002000412c6a2003360200200220093703602002200c37038001200041013602000b20024190016a24000ba70201057f230041d0006b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f002370224200220033602202000200241206a108f012002280228210320022802202100200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020002003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002200110e203024020012d00000d002001411c6a280200450d00200141186a280200102a0b200241d0006a24000f0b411741011037000bca0201067f230041b0016b22012400200141086a2000109301024020012903284202510d000340200128026021022001280258210302400240200128025c22040d00200321050c010b2004210620032105034020052802ec0321052006417f6a22060d000b0340200320032f01064102746a41ec036a28020021032004417f6a22040d000b0b200120023602a801200141003602a001200141003602980120014200370390012001200536028c0120014100360288012001200336029c01200120032f01063602a40120014188016a109501200141086a200010930120012903284202520d000b0b02402000280204220341f8b9c000460d00200328020021042003102a2004450d00200428020021052004102a2005450d00024020052802002203450d0003402005102a2003210520032802002204210320040d000b0b2005102a0b200141b0016a24000bcf0204017f017e027f037e230041206b2201240042002102200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420021050c010b20044110490d01200341086a2900002105200329000021022003102a0b2000280200220341086a290300210620032903002107200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001427f200520067c200220077c22062002542203ad7c22022003200220055420022005511b22031b3703182001427f200620031b37031020014110200141106a41101007200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000bd00204017f017e027f037e230041206b2201240042002102200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420021050c010b20044110490d01200341086a2900002105200329000021022003102a0b2000280200220341086a290300210620032903002107200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a20032903003703002001200129031037030020014200200520067d2002200754ad7d2206200220077d2207200256200620055620062005511b22031b37031820014200200720031b37031020014110200141106a41101007200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000bb50404057f017e017f017e0240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602000240200441037122064103460d00024002400240024020060e03000102000b2004410276ad21070c020b41012106024020050d000c050b20032d0001210520012002417e6a3602042001200341026a3602002005410874200472220141ffff0371418002490d04200141fcff0371410276ad21070c010b410121060240200541034f0d000c040b200341036a2d0000210520032f0001210820012002417c6a3602042001200341046a3602002008200541107472410874200472220141808004490d032001410276ad21070b410021060c020b02402004410276220841044b0d000240024020080e050002020201000b20054104490d022003350001210720012002417b6a3602042001200341056a36020020074280808080045421060c030b20054108490d01200329000121072001200241776a3602042001200341096a3602002007428080808080808080015421060c020b200841046a220541084b0d002002417e6a2102200341026a2103410021044200210741012106034002402002417f470d000c030b2003417f6a310000210920012002360204200120033602002002417f6a2102200341016a210320092004410374413871ad862007842107200441016a220441ff01712005490d000b2007427f412820084103746b413871ad885821060c010b410121060b2000200737030820002006ad3703000bde0506067f017e017f017e017f017e230041206b220224000240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a360200024002400240200541037122074103460d0002400240024020070e03000102000b2005410276ad21080c040b410121072006450d0220042d0001210620012003417e6a3602042001200441026a3602002006410874200572220141ffff0371418002490d02200141fcff0371410276ad21080c030b4101210720064103490d01200441036a2d0000210620042f0001210920012003417c6a3602042001200441046a3602002009200641107472410874200572220141808004490d012001410276ad21080c020b024020054102762209410c4b0d0002400240024020090e0d00030303010303030303030302000b20064104490d052004350001210820012003417b6a3602042001200441056a36020020084280808080045421074200210a0c060b20064108490d04200429000121082001200341776a3602042001200441096a3602002008428080808080808080015421074200210a0c050b20064110490d03200441096a290000210a2004290001210820012003416f6a3602042001200441116a360200200a428080808080808080015421070c040b200941046a220641104b0d022003417e6a2103200441026a21044100210541012107200241186a210b420021084200210a03402003417f460d01200241106a2004417f6a3100004200200541037441f80071109d0520012003360204200120043602002003417f6a2103200441016a2104200b290300200a84210a20022903102008842108200541016a220541ff01712006490d000b2002427f427f41e80020094103746b41f80071109e052008200229030058200a200241086a290300220c58200a200c511b21070c030b0c020b4200210a410021070c010b410121070b20002008370308200041106a200a37030020002007ad370300200241206a24000b9e0701037f02400240024002400240024020002802002202413f4b0d0002400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d06200041017422042003200420034b1b22044100480d060240024020000d002004102821030c010b200128020020002004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20024102743a00000f0b200241808001490d032002418080808004490d020c010b200441011037000b0240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102821030c010b200128020020022004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280200210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d05200241017422002004200020044b1b22004100480d050240024020020d002000102821020c010b200128020020022000102c21020b2002450d0220012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b200441011037000b200041011037000b024002400240200141046a2802002203200141086a28020022006b4104490d00200128020021030c010b200041046a22042000490d03200341017422002004200020044b1b22004100480d030240024020030d002000102821030c010b200128020020032000102c21030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20024102744102723600000f0b200041011037000b024002400240200141046a2802002203200141086a28020022006b4102490d00200128020021030c010b200041026a22042000490d02200341017422002004200020044b1b22004100480d020240024020030d002000102821030c010b200128020020032000102c21030b2003450d0120012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20024102744101723b00000f0b200041011037000b1031000bac0903017f017e057f230041e0006b220224000240024002400240024002400240024002400240024020002903002203423f560d0002400240200141046a280200200141086a2802002200460d00200128020021040c010b200041016a22042000490d0b200041017422052004200520044b1b22054100480d0b0240024020000d002005102821040c010b200128020020002005102c21040b2004450d0220012004360200200141046a2005360200200141086a28020021000b200141086a200041016a360200200420006a2003a74102743a00000c080b200342808001540d062003428080808004540d054108200379a741037622056b4104490d0402400240200141046a280200200141086a2802002204460d00200128020021060c010b200441016a22072004490d0a200441017422062007200620074b1b22074100480d0a0240024020040d002007102821060c010b200128020020042007102c21060b2006450d0220012006360200200141046a2007360200200141086a28020021040b200141086a2207200441016a360200200620046a411320054102746b3a0000200220002903002203370308200541786a2104200141046a2106034002400240200628020020072802002200460d00200128020021050c010b200041016a22052000490d0b200041017422082005200820054b1b22084100480d0b0240024020000d002008102821050c010b200128020020002008102c21050b2005450d042001200536020020062008360200200728020021000b2007200041016a360200200520006a2003a73a000020034208882103200441016a22002004492105200021042005450d000b20022003370308200350450d030c070b200541011037000b200741011037000b200841011037000b200241286a41146a4108360200200241346a4109360200200241106a41146a41033602002002200241086a360240200241f8b9c00036024420024203370214200241c8afc6003602102002410936022c200242043703582002420137024c20024180bac0003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a4188bac000103e000b41dcb9c0001032000b024002400240200141046a2802002204200141086a28020022006b4104490d00200128020021040c010b200041046a22052000490d05200441017422002005200020054b1b22004100480d050240024020040d002000102821040c010b200128020020042000102c21040b2004450d0120012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a2003a74102744102723600000c020b200041011037000b02400240200141046a2802002204200141086a28020022006b4102490d00200128020021040c010b200041026a22052000490d03200441017422002005200020054b1b22004100480d030240024020040d002000102821040c010b200128020020042000102c21040b2004450d0220012004360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200420006a2003a74102744101723b00000b200241e0006a24000f0b200041011037000b1031000bbf0202027f017e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d01200441012001103f21000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20034180011044000b20034180011044000b800a03017f027e057f230041e0006b2202240002400240024002400240024002400240024002400240200028020022002903002203423f56200041086a290300220442005220045022051b0d0002400240200141046a280200200141086a2802002200460d00200128020021050c010b200041016a22052000490d0b200041017422062005200620054b1b22064100480d0b0240024020000d002006102821050c010b200128020020002006102c21050b2005450d0220012005360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200520006a2003a74102743a00000c080b20034280800154410020051b0d06200342808080800454410020051b0d05411020047920037942c0007c20044200521ba741037622066b4104490d0402400240200141046a280200200141086a2802002205460d00200128020021070c010b200541016a22082005490d0a200541017422072008200720084b1b22084100480d0a0240024020050d002008102821070c010b200128020020052008102c21070b2007450d0220012007360200200141046a2008360200200141086a28020021050b200141086a2208200541016a360200200720056a413320064102746b3a0000200029030021032002200041086a290300220437030820022003370300200641706a2105200141046a2107034002400240200728020020082802002200460d00200128020021060c010b200041016a22062000490d0b200041017422092006200920064b1b22094100480d0b0240024020000d002009102821060c010b200128020020002009102c21060b2006450d042001200636020020072009360200200828020021000b2008200041016a360200200620006a2003a73a00002003420888200442388684210320044208882104200541016a22002005492106200021052006450d000b2002200337030020022004370308200320048450450d030c070b200641011037000b200841011037000b200941011037000b200241286a41146a4108360200200241346a410a360200200241106a41146a410336020020022002360240200241a8bbc00036024420024203370214200241c8afc6003602102002410a36022c200242043703582002420137024c20024180bac0003602482002200241286a3602202002200241c8006a3602382002200241c4006a3602302002200241c0006a360228200241106a41b8bbc000103e000b418cbbc0001032000b024002400240200141046a2802002205200141086a28020022006b4104490d00200128020021050c010b200041046a22062000490d05200541017422002006200020064b1b22004100480d050240024020050d002000102821050c010b200128020020052000102c21050b2005450d0120012005360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200520006a2003a74102744102723600000c020b200041011037000b02400240200141046a2802002205200141086a28020022006b4102490d00200128020021050c010b200041026a22062000490d03200541017422002006200020064b1b22004100480d030240024020050d002000102821050c010b200128020020052000102c21050b2005450d0220012005360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200520006a2003a74102744101723b00000b200241e0006a24000f0b200041011037000b1031000b810605027f027e017f027e027f230041a0016b220224002000280200210002400240024002400240024002400240200128020022034110710d00200041086a29030021042000290300210520034120710d0220054290ce005441002004501b450d012005a72103412721000c060b200041086a2903002105200029030021044180012100024003402000450d01200241206a20006a417f6a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a210020044204882005423c8684220420054204882205844200520d000b0b20004181014f0d0220014101419087c0004102200241206a20006a41800120006b104221000c060b41272100200241186a21060340200241106a200520044290ce00420010a0052002200229031022072006290300220842f0b17f427f109f05200241206a20006a2203417c6a200520022903007ca7220941ffff037141e4006e220a41017441ba84c0006a2f00003b00002003417e6a200a419c7f6c20096a41ffff037141017441ba84c0006a2f00003b0000200542ffc1d72f56210320044200522109200450210a2000417c6a2100200721052008210420032009200a1b0d000c040b0b4180012100024003402000450d01200241206a20006a417f6a2005a7410f712203413072200341376a2003410a491b3a00002000417f6a210020054204882004423c8684220520044204882204844200520d000b0b20004181014f0d0120014101419087c0004102200241206a20006a41800120006b104221000c040b20004180011044000b20004180011044000b2007a721030b02400240200341e3004a0d00200321090c010b200241206a2000417e6a22006a2003200341ffff037141e4006e2209419c7f6c6a41ffff037141017441ba84c0006a2f00003b00000b024002402009410a480d00200241206a2000417e6a22006a200941017441ba84c0006a2f00003b00000c010b200241206a2000417f6a22006a200941306a3a00000b2001410141b8aec6004100200241206a20006a412720006b104221000b200241a0016a240020000bf40601067f230041f0006b21020240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a2206360204410121072001200441016a360200200541f001490d0a200541847e6a220541034b0d0420050e0401020803010b200041023a00000f0b20064102490d0320042f0001210520012003417d6a3602042001200441036a360200200541ef014b0d04200041023a00000f0b20064104490d042004280001210520012003417b6a3602042001200441056a36020041012107200541ffff034b0d07200041023a00000f0b41002105200241003a00682003417f6a21062003417e6a210302400340024020062005470d000240200541ff0171450d00200241003a00680b410121010c020b200241c8006a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00682003417f6a21032007210520074120470d000b200241c6006a20022d004a3a0000200241306a200241d7006a290000370300200241386a200241df006a290000370300200241c0006a200241e7006a2d00003a0000200220022f01483b01442002200229004f370328200228004b2105410021010b200241246a41026a2203200241c4006a41026a2d00003a0000200241086a41086a2207200241286a41086a290300370300200241086a41106a2204200241286a41106a290300370300200241086a41186a2206200241286a41186a2d00003a0000200220022f01443b0124200220022903283703082001450d05200041023a00000f0b200041023a00000f0b200041023a00000f0b410121070c030b200041023a00000f0b0240200641044f0d00200041023a00000f0b200041023a000020012003417b6a3602042001200441056a3602000f0b200241286a41026a20032d00003a0000200241c8006a41086a2007290300370300200241c8006a41106a2004290300370300200241c8006a41186a20062d00003a0000200220022f01243b012820022002290308370348410021070b200020073a0000200020022f01283b0001200041046a2005360200200041086a2002290348370200200041036a2002412a6a2d00003a0000200041106a200241c8006a41086a290300370200200041186a200241c8006a41106a290300370200200041206a200241c8006a41186a2802003602000bb30801037f0240024002400240024002400240024020002d00004101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d08200241017422042003200420034b1b22044100480d080240024020020d002004102821030c010b200128020020022004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41ff013a0000200041016a2001108f010f0b0240024002400240200041046a280200220241ffff034b0d00200241ef014b0d03200141046a280200200141086a2802002200460d01200128020021030c020b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d0a200041017422042003200420034b1b22044100480d0a0240024020000d002004102821030c010b200128020020002004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fd013a000002400240200141046a2802002203200428020022006b4104490d00200128020021030c010b200041046a22042000490d0a200341017422002004200020044b1b22004100480d0a0240024020030d002000102821030c010b200128020020032000102c21030b2003450d0620012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20023600000f0b200041016a22032000490d08200041017422042003200420034b1b22044100480d080240024020000d002004102821030c010b200128020020002004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a20023a00000f0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d07200041017422042003200420034b1b22044100480d070240024020000d002004102821030c010b200128020020002004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021000b200141086a2204200041016a360200200320006a41fc013a000002400240200141046a2802002203200428020022006b4102490d00200128020021030c010b200041026a22042000490d07200341017422002004200020044b1b22004100480d070240024020030d002000102821030c010b200128020020032000102c21030b2003450d0620012003360200200141046a2000360200200141086a28020021000b200141086a200041026a360200200320006a20023b00000f0b200441011037000b200441011037000b200041011037000b200441011037000b200441011037000b200041011037000b1031000bd80402097f017e230041106b22052400024002400240200128020041016a220641004c0d0020012006360200200141046a2106200141086a28020021070240024003402006280200220841086a210920082f0106220a41057421064100210b0240024003402006450d01200220094120109c05220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b2007450d022007417f6a21072008200a4102746a41880b6a21060c010b0b2008200b41e0006c6a22094198036a2106200941e8026a210d2009419c036a2802002107024003402006280200220841086a210920082f0106220a41057421064100210b0240024003402006450d01200420094120109c05220c450d02200641606a2106200b41016a210b200941206a2109200c417f4a0d000b200b417f6a210a0b024020070d004100210c0c030b2007417f6a21072008200a4102746a41ec036a21060c010b0b4101210c0240200841e8026a200b410c6c6a2206280200220b0d00410021060c010b20062802082209417f4c0d040240024020090d0020054200370300410121060c010b200910282206450d0620054100360204200520093602000b200520093602042006200b2009109a051a2005290300210e0b02400240200d2d005d450d0020064100200c1b21060c010b200c450d010b2000200e370204200020063602000c010b20002001280210200220032004200141146a28020028020c1104000b20012001280200417f6a360200200541106a24000f0b41b8b8c0004118200541086a41e0b8c0001038000b1036000b200941011037000bfc0202097f037e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d01200220084120109c05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a22054190036a290300210c20054188036a290300210d20054180036a290300210e0240200541c5036a2d00000d00200ea721054201210e2005450d010c020b200e4202520d010b200320012802102002200141146a280200280214110500200341106a290300210c200128020021042003290308210d2003290300210e0b20012004417f6a360200200041106a200c3703002000200d3703082000200e370300200341206a24000f0b41b8b8c0004118200341186a41e0b8c0001038000bd70501037f024002400240024002400240024020002d00004101460d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d07200241017422042003200420034b1b22044100480d070240024020020d002004102821030c010b200128020020022004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41003a00000c010b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d06200241017422042003200420034b1b22044100480d060240024020020d002004102821030c010b200128020020022004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41013a0000200041016a2001108f010b024020002d00214101460d0002400240200141046a280200200141086a2802002200460d00200128020021020c010b200041016a22022000490d06200041017422032002200320024b1b22034100480d060240024020000d002003102821020c010b200128020020002003102c21020b2002450d0420012002360200200141046a2003360200200141086a28020021000b200141086a200041016a360200200220006a41003a00000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102821030c010b200128020020022004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a41013a0000200041226a2001108f010f0b200441011037000b200441011037000b200341011037000b200441011037000b1031000bbf0501047f200141046a2802002102200141086a28020021030240024002400240024002400240200028020022040d000240024020022003460d00200128020021020c010b200341016a22022003490d07200341017422042002200420024b1b22044100480d070240024020030d002004102821020c010b200128020020032004102c21020b2002450d0320012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a41003a00000c010b0240024020022003460d00200128020021020c010b200341016a22022003490d06200341017422052002200520024b1b22054100480d060240024020030d002005102821020c010b200128020020032005102c21020b2002450d0320012002360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200220036a41013a000020042001108f010b200141046a2802002102200141086a28020021030240200028020422040d000240024020022003460d00200128020021000c010b200341016a22002003490d06200341017422022000200220004b1b22024100480d060240024020030d002002102821000c010b200128020020032002102c21000b2000450d0420012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b0240024020022003460d00200128020021000c010b200341016a22002003490d05200341017422022000200220004b1b22024100480d050240024020030d002002102821000c010b200128020020032002102c21000b2000450d0420012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41013a000020042001108f010f0b200441011037000b200541011037000b200241011037000b200241011037000b1031000b860a05037f047e057f027e047f230022022103200241c0016b41607122022400200141186a220429000021052004200229039801370000200129001021062001200229039001370010200129000821072001200229038801370008200241003a00800120012900002108200120022903800137000020022005370378200220063703702002200737036820022008370360200141206a2d0000210420024180016a41176a2209200537000020024180016a41106a220a200229007137030020024180016a41086a220b2002290069370300200220022900613703800102402008a741ff01714101460d0020004200370300200324000f0b200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b2903003703002002200229038001370318200220043a0037200241386a200241186a10ac012002410036028001200241386a412020024180016a1006210c02400240200228028001220d417f460d002002200d36025c2002200c3602582002200241d8006a109f012002290300a70d01200228025c2204450d01200241106a290300210e2002290308210f20022004417f6a220a36025c20022002280258221041016a220b36025820102d0000220441014b0d01410021110240024020040e020100010b4100210403400240200a2004470d002002410036025c0c040b2002201020046a41026a360258200441016a2209210420094120470d000b2002200a20096b220a36025c41012111201020096a41016a210b0b200a450d012002200a417f6a220a36025c2002200b41016a360258200b2d0000220941014b0d01410021040240024020090e020100010b41002104200241003a00a00103400240200a2004470d002002410036025c200441ff0171450d04200241003a00a0010c040b20024180016a20046a200b20046a220941016a2d00003a00002002200941026a3602582002200441016a22093a00a0012009210420094120470d000b200241e0006a41086a20024180016a41086a290300370300200241e0006a41106a20024180016a41106a290300370300200241e0006a41186a20024180016a41186a29030037030020022002290380013703602002200a20096b36025c410121040b20024180016a41186a2209200241e0006a41186a220a29030037030020024180016a41106a220b200241e0006a41106a221029030037030020024180016a41086a2212200241e0006a41086a2213290300370300200220022903603703800120114102460d01200a20092903003703002010200b2903003703002013201229030037030020022002290380013703600240200d450d00200c102a0b20024180016a41186a200241e0006a41186a2209290300220537030020024180016a41106a200241e0006a41106a220a290300220837030020024180016a41086a200241e0006a41086a220b29030022063703002002200229036022073703800120092005370300200a2008370300200b200637030020022007370360200120043a000020012007370001200141096a2006370000200141116a2008370000200141196a2005370000200041306a200e370300200041286a200f3703002000420137030020002002290318370008200041106a200241186a41086a290300370000200041186a200241186a41106a290300370000200041206a200241186a41186a290300370000200324000f0b41c9b4c00041dd001050000b41c4d1c3004133200241b8016a419cd9c3001038000bfc0101057f230041306b220224000240411210282203450d00200341002900c1ae44370000200341106a41002f00d1ae443b0000200341086a41002900c9ae4437000020024292808080a0023702042002200336020020012002108f012002280208210320022802002101200241106a41186a22044200370300200241106a41106a22054200370300200241106a41086a220642003703002002420037031020012003200241106a1000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700002000200229031037000002402002280204450d002002280200102a0b200241306a24000f0b411241011037000b910a03037f047e0c7f230022022103200241c0016b41607122022400200141186a220429000021052004200229039801370000200129001021062001200229039001370010200129000821072001200229038801370008200241003a00800120012900002108200120022903800137000020022005370378200220063703702002200737036820022008370360200141206a2d0000210420024180016a41176a2209200537000020024180016a41106a220a200229007137030020024180016a41086a220b2002290069370300200220022900613703800102402008a741ff01714101460d0020004100360220200324000f0b200241086a41176a2009290000370000200241086a41106a200a290300370300200241086a41086a200b2903003703002002200229038001370308200220043a0027200241286a200241086a10ae012002410036028001200241286a412020024180016a1006210c024002400240200228028001220d417f460d002002200d36024c2002200c360248200241d0006a200241c8006a106d2002280250220e450d022002280254210f200228024c2204450d01200241d8006a280200211020022004417f6a220a36024c20022002280248221141016a220b36024820112d0000220441014b0d01410021120240024020040e020100010b4100210403400240200a2004470d002002410036024c0c040b2002201120046a41026a360248200441016a2209210420094120470d000b2002200a20096b220a36024c41012112201120096a41016a210b0b200a450d012002200a417f6a220a36024c2002200b41016a360248200b2d0000220941014b0d01410021040240024020090e020100010b41002104200241003a00a00103400240200a2004470d002002410036024c200441ff0171450d04200241003a00a0010c040b20024180016a20046a200b20046a220941016a2d00003a00002002200941026a3602482002200441016a22093a00a0012009210420094120470d000b200241e0006a41086a20024180016a41086a290300370300200241e0006a41106a20024180016a41106a290300370300200241e0006a41186a20024180016a41186a29030037030020022002290380013703602002200a20096b36024c410121040b20024180016a41186a2209200241e0006a41186a220a29030037030020024180016a41106a220b200241e0006a41106a221129030037030020024180016a41086a2213200241e0006a41086a2214290300370300200220022903603703800120124102460d02200a20092903003703002011200b2903003703002014201329030037030020022002290380013703600240200d450d00200c102a0b20024180016a41186a200241e0006a41186a2209290300220537030020024180016a41106a200241e0006a41106a220a290300220837030020024180016a41086a200241e0006a41086a220b29030022063703002002200229036022073703800120092005370300200a2008370300200b200637030020022007370360200120043a000020012007370001200141096a2006370000200141116a2008370000200141196a2005370000200041286a20103602002000200f3602242000200e36022020002002290308370000200041086a200241086a41086a290300370000200041106a200241086a41106a290300370000200041186a200241086a41186a290300370000200324000f0b41c9b4c00041dd001050000b200f450d00200e102a0b41c4d1c3004133200241d0006a419cd9c3001038000bfc0101057f230041306b220224000240411210282203450d0020034100290095ae44370000200341106a41002f00a5ae443b0000200341086a410029009dae4437000020024292808080a0023702042002200336020020012002108f012002280208210320022802002101200241106a41186a22044200370300200241106a41106a22054200370300200241106a41086a220642003703002002420037031020012003200241106a1000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700002000200229031037000002402002280204450d002002280200102a0b200241306a24000f0b411241011037000bfe0703037f047e0a7f23002202210320024180036b41607122022400200141186a220429000021052004200229039802370000200129001021062001200229039002370010200129000821072001200229038802370008200241003a0080022001290000210820012002290380023700002002200537039801200220063703900120022007370388012002200837038001200141206a2d0000210420024180026a41176a2209200537000020024180026a41106a220a20022900910137030020024180026a41086a220b20022900890137030020022002290081013703800202402008a741ff01714101460d00200041073a0040200324000f0b200241186a41176a2009290000370000200241186a41106a200a290300370300200241186a41086a200b2903003703002002200229038002370318200220043a0037200241e0006a200241186a10b0012002410036028002200241e0006a412020024180026a1006210c0240200228028002220d417f460d002002200d36023c2002200c36023820024180026a200241386a10b101024020022d00a1024102460d00200241d8016a41206a220420024180026a41206a2d00003a0000200241d8016a41186a220920024180026a41186a220e290300370300200241d8016a41106a220a20024180026a41106a220f290300370300200241d8016a41086a220b20024180026a41086a221029030037030020022002290380023703d80120024180016a200241a2026a41c100109a051a0240200d450d00200c102a0b200241386a41206a220d20042d00003a0000200241386a41186a220c2009290300370300200241386a41106a2211200a290300370300200241386a41086a2212200b290300370300200220022903d80137033820024180026a20024180016a41c100109a051a2004200d2d00003a00002009200c290300370300200a2011290300370300200b2012290300370300200220022903383703d80120024180016a20024180026a41c100109a051a200141206a20024180016a41c0006a2d00003a0000200141186a20024180016a41386a290000370000200141106a20024180016a41306a290000370000200141086a20024180016a41286a290000370000200120022900a001370000200e200241186a41186a290300370300200f200241186a41106a2903003703002010200241186a41086a290300370300200220022903183703800220024180026a41286a200b29030037030020024180026a41306a200a29030037030020024180026a41386a200929030037030020024180026a41c0006a20042d00003a0000200220022903d8013703a002200020024180026a41c100109a051a200324000f0b41c4d1c300413320024180016a419cd9c3001038000b41c9b4c00041dd001050000bfc0101057f230041306b220224000240411510282203450d00200341002900d088453700002003410d6a41002900dd8845370000200341086a41002900d8884537000020024295808080d0023702042002200336020020012002108f012002280208210320022802002101200241106a41186a22044200370300200241106a41106a22054200370300200241106a41086a220642003703002002420037031020012003200241106a1000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700002000200229031037000002402002280204450d002002280200102a0b200241306a24000f0b411541011037000bd30b03097f017e017f23004190026b2202240041002103200241003a00880220012802042204417d6a2105417f21060240024002400240024002400240034020042003460d01200241e8016a20036a200128020022072d00003a00002001200420066a3602042001200741016a3602002002200341016a22083a0088022005417f6a21052006417f6a21062008210320084120470d000b200241c8016a41186a200241e8016a41186a290300370300200241c8016a41106a200241e8016a41106a290300370300200241c8016a41086a200241e8016a41086a290300370300200220022903e8013703c80120042008460d0120072d000121092001200420066a3602042001200741026a360200200941074f0d01200241086a41186a200241c8016a41186a290300370300200241086a41106a200241c8016a41106a290300370300200241086a41086a200241c8016a41086a290300370300200220022903c8013703082004417f6a2008460d0520072d000221032001200741036a220a3602002001200420086b2206417e6a2208360204200341014b0d0520030e020302030b200341ff0171450d00200241003a0088020b200041023a00210c040b41002103200241003a0088022006417e6a2104417d21080340024020042003470d00200341ff0171450d04200241003a0088020c040b200241e8016a20036a200720036a220641036a2d00003a00002001200520036b3602042001200641046a3602002002200341016a22063a0088022008417f6a21082006210320064120470d000b200241a8016a41086a200241e8016a41086a290300220b37030020024188016a41186a200241e8016a41186a29030037030020024188016a41106a200241e8016a41106a29030037030020024188016a41086a200b370300200220022903e801220b3703a8012002200b370388014101210c200520066b41016a2108200720066a41036a210a0c010b4100210c0b200241e8006a41186a20024188016a41186a290300370300200241e8006a41106a20024188016a41106a290300370300200241e8006a41086a20024188016a41086a29030037030020022002290388013703682008450d00200a2d0000210320012008417f6a3602042001200a41016a360200200341014b0d00410021060240024020030e020100010b41002103200241003a0088022008417f6a21042008417e6a21060340024020042003470d00200341ff0171450d03200241003a0088020c030b200241e8016a20036a200a20036a220841016a2d00003a0000200120063602042001200841026a3602002002200341016a22083a0088022006417f6a21062008210320084120470d000b200241a8016a41086a200241e8016a41086a290300220b37030020024188016a41186a200241e8016a41186a29030037030020024188016a41106a200241e8016a41106a29030037030020024188016a41086a200b370300200220022903e801220b3703a8012002200b37038801410121060b200241286a41186a220320024188016a41186a290300370300200241286a41106a220120024188016a41106a290300370300200241286a41086a220820024188016a41086a290300370300200241c8006a41086a2204200241e8006a41086a290300370300200241c8006a41106a2205200241e8006a41106a290300370300200241c8006a41186a2207200241e8006a41186a290300370300200220022903880137032820022002290368370348200041186a200241086a41186a290300370000200041106a200241086a41106a290300370000200041086a200241086a41086a290300370000200020022903083700002000200c3a0021200020093a0020200041c2006a20063a0000200020022903483700222000412a6a2004290300370000200041326a20052903003700002000413a6a2007290300370000200041c3006a2002290328370000200041cb006a2008290300370000200041d3006a2001290300370000200041db006a20032903003700000c010b200041023a00210b20024190026a24000b340020004197dbc00036020420004100360200200041146a4103360200200041106a41bcbcc000360200200041086a42083702000b5201027f230041106b2202240002404104102822030d00410441011037000b20024204370204200220033602004100200210b401200041086a200228020836020020002002290300370200200241106a24000b920701037f0240024002400240024002402000413f4b0d0002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d06200241017422042003200420034b1b22044100480d060240024020020d002004102821030c010b200128020020022004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20004102743a00000f0b200041808001490d032000418080808004490d020c010b200441011037000b0240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d05200241017422042003200420034b1b22044100480d050240024020020d002004102821030c010b200128020020022004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a000002400240200141046a2802002203200428020022026b4104490d00200128020021030c010b200241046a22042002490d05200341017422022004200220044b1b22024100480d050240024020030d002002102821030c010b200128020020032002102c21030b2003450d0220012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20003600000f0b200441011037000b200241011037000b024002400240200141046a2802002203200141086a28020022026b4104490d00200128020021030c010b200241046a22042002490d03200341017422022004200220044b1b22024100480d030240024020030d002002102821030c010b200128020020032002102c21030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241046a360200200320026a20004102744102723600000f0b200241011037000b024002400240200141046a2802002203200141086a28020022026b4102490d00200128020021030c010b200241026a22042002490d02200341017422022004200220044b1b22024100480d020240024020030d002002102821030c010b200128020020032002102c21030b2003450d0120012003360200200141046a2002360200200141086a28020021020b200141086a200241026a360200200320026a20004102744101723b00000f0b200241011037000b1031000bd82504027f027e087f037e230041b00d6b220724000240024002402001280230200128024022082802b801460d002004420020042903082209200841c0006a2903007d220a200a20095622081b3703082008450d0120004188c5c00036020420004101360200200041086a412a3602002000410c6a2006290200370200200041146a200641086a2802003602000c020b200041f3c3c00036020420004101360200200041086a41293602002000410c6a2006290200370200200041146a200641086a2802003602000c010b200741186a41186a200141e8006a290000370300200741186a41106a200141e0006a290000370300200741186a41086a200141d8006a290000370300200720012900503703182006280208210b20062802002108200741b0026a41186a220c4200370300200741b0026a41106a220d4200370300200741b0026a41086a220e4200370300200742003703b0022008200b200741b0026a1000200741d00a6a41186a200c290300370300200741d00a6a41106a200d290300370300200741d00a6a41086a200e290300370300200720072903b0023703d00a0240024002400240024002400240024002400240412010282208450d0020082005290000370000200841186a200541186a290000370000200841106a200541106a290000370000200841086a200541086a2900003700002008412041c000102c2208450d01200820072903d00a370020200841386a200741d00a6a41186a290300370000200841306a200741d00a6a41106a290300370000200841286a200741d00a6a41086a290300370000200841c000418001102c2208450d0220082007290318370040200841d8006a200741186a41186a290300370000200841d0006a200741186a41106a290300370000200841c8006a200741186a41086a290300370000200741b0026a41186a220c4200370300200741b0026a41106a220d4200370300200741b0026a41086a220e4200370300200742003703b002200841e000200741b0026a1000200741386a41186a220f200c290300370300200741386a41106a220c200d290300370300200741386a41086a220d200e290300370300200720072903b0023703382008102a20062902002109200741d8006a41d8006a200d290300370300200741d8006a41e0006a200c290300370300200741c0016a200f29030037030020074194016a410036020020074184016a419cc4c000360200200741f8006a4200370300200741f4006a221041f8b9c00036020020072001360260200741d8006a41286a200141186a2211360200200720072903383703a8012007420837028c012007410036027020074100360264200720012802483602a00120072001290340370398012007200128023041016a360288012001290300210a2007200128024c3602a4012007200a370358200741c8016a41186a200541186a290000370300200741c8016a41106a200541106a290000370300200741c8016a41086a200541086a29000037030020074101360270200720052900003703c8012011200741386a10b601210620072007280270417f6a2208360270024020060d0020080d042007417f36027020074190026a41186a200741386a41186a29030037030020074190026a41106a200741386a41106a29030037030020074190026a41086a200741386a41086a2903003703002007200729033837039002024002402007280274220e41f8b9c000460d002007280278210f0c010b4100210f200741d00a6a410041e0021099051a200741b0026a410041a0081099051a41880b1028220e450d06200e41003b0106200e4100360200200e41086a200741d00a6a41e002109a051a200e41e8026a200741b0026a41a008109a051a200741003602782007200e3602740b024002400340200e41086a2108200e2f0106221241057421064100210c0240024003402006450d0120074190026a20084120109c05220d450d02200641606a2106200c41016a210c200841206a2108200d417f4a0d000b200c417f6a21120b200f450d02200f417f6a210f200e20124102746a41880b6a280200210e0c010b0b200e200c41e0006c6a41e8026a21060c010b200741f0016a41186a20074190026a41186a290300220a370300200741f0016a41106a20074190026a41106a2903002213370300200741f0016a41086a20074190026a41086a2903002214370300200720072903900222153703f001200741ec0a6a2014370200200741d00a6a41246a2013370200200741fc0a6a200a3702002007200741d8006a41246a3602e00a200720123602dc0a200720103602d80a2007200e3602d40a200741003602d00a200720153702e40a200741e4026a4200370200200741003a00ec02200742003703b002200741003a008d03200741f8b9c0003602e002200742003703c802200741d00a6a200741b0026a10b70121060b200741e0016a290300210a20064201370318200641013a003c200641286a427f370300200641206a427f3703002006413d6a20072903c801370000200641d5006a200a370000200641cd006a200741d8016a290300370000200641c5006a200741d0016a2903003700002007200728027041016a360270200741106a20044101200741186a200741386a20022003200741d8006a10b8012007280210220e0d06200741b0026a200520072802a00128020010b901024020072802b0024101470d002009422088a72106200741b8026a280200210520072802b402210e2009a721010c0b0b20074190026a41186a200741b0026a410472220641186a2802002208360200200741d00a6a41106a200641086a290200370300200741d00a6a41186a200641106a290200370300200741f00a6a2008360200200741063602d40a200741b38dc6003602d00a200720062902003703d80a200728029c0121062007200741d8006a3602c8022007290358210a20072802a4012108200741d8026a200741186a41086a290300370300200741e0026a200741186a41106a290300370300200741e8026a200741186a41186a290300370300200720033703b802200720023703b002200720083602cc022007200a3703c002200720072903183703d0022007200b3602f801200720093703f00120074190026a2006200741d00a6a200741b0026a200741f0016a200410ba012007419c026a290200210220074190026a41086a2802002112200728029402210f02402007280290024101470d002002422088a72106200741a4026a280200210b2002a7210120122105200f210e0c0a0b200728027041016a220b41004c0d072007200b360270200728027821040240024003402010280200220541086a210820052f0106220e41057421064100210c0240024003402006450d01200741386a20084120109c05220d450d02200641606a2106200c41016a210c200841206a2108200d417f4a0d000b200c417f6a210e0b2004450d022004417f6a21042005200e4102746a41880b6a21100c010b0b2005200c41e0006c6a220641c5036a310000200641e8026a290300220320035022081ba7450d004200200641f8026a29030020081b21034200200641f0026a29030020081b21090c010b2007200728028001200741386a20072802840128021c110500200741086a2903002103200729030021092007280270210b0b2007200b417f6a3602702009200728029801220629037854200320064180016a29030022095420032009511b450d082002a7210b41c0c4c000210e411e2105200f2101201221060c090b2009422088a721062009a7210141dec4c000210e412a21050c090b412041011037000b41c00041011037000b41800141011037000b41a8b8c0004110200741b0026a41d0b8c0001038000b41880b41081037000b200728021421052009422088a721062009a721010c030b41b8b8c0004118200741b0026a41e0b8c0001038000b20074190026a41086a2208200741186a41086a29030037030020074190026a41106a220c200741186a41106a29030037030020074190026a41186a220d200741186a41186a290300370300200741f0016a41086a2205200741386a41086a290300370300200741f0016a41106a2204200741386a41106a290300370300200741f0016a41186a220e200741386a41186a2903003703002007200729031837039002200720072903383703f00102400240024002402007280294012206200728029001470d00200641016a220b2006490d0320064101742210200b2010200b4b1b2210ad42b0017e2203422088a70d032003a7220b4100480d030240024020060d00200b102821060c010b200728028c01200641b0016c200b102c21060b2006450d0120072010360290012007200636028c0120072802940121060b200728028c01200641b0016c6a220641003a0000200620072f00ed013b0001200641013a00102006410036000c200642013700042006200729039002370011200620072903f001370031200641036a200741ef016a2d00003a0000200641196a2008290300370000200641216a200c290300370000200641296a200d290300370000200641396a2005290300370000200641c1006a2004290300370000200641c9006a200e290300370000200641e0006a200741d7016a290000370000200641d9006a200741c8016a41086a290000370000200620072900c801370051200641e8006a200741b0026a41c800109a051a200720072802940141016a2208360294010240200741d00a6a41186a280200450d00200741e40a6a280200102a20072802940121080b200728029001210e200728028c012105200728027c210b2007280278210d2007280274210602402007280264220c450d00200741e8006a280200450d00200c102a0b0240024020024280808080f01f8350450d002007200b3602b8022007200d3602b402200720063602b0022011200741b0026a10bb012007200e3602b402200720053602b00220072005200841b0016c22086a22043602bc0202400240200141386a280200220c2001413c6a28020022066b200841b0016d220d490d002001280234210c0c010b2006200d6a220e2006490d05200c4101742206200e2006200e4b1b2206ad42b0017e2203422088a70d052003a7220e4100480d0502400240200c0d00200e1028210c0c010b2001280234200c41b0016c200e102c210c0b200c450d042001200c360234200141386a20063602002001413c6a28020021060b200c200641b0016c6a20052008109a051a2001413c6a22062006280200200d6a360200200720043602b802200741b0026a10690c010b02402008450d00200841b0016c210441002108034002400240200520086a220c2d0000220141014b0d000240024020010e020001000b0240200c41086a280200450d00200c41046a280200102a0b200c41106a2d00004105490d02200c41386a280200450d02200c41346a280200102a0c020b200c41286a106a0c010b200c41e8006a280200450d00200c41e4006a280200102a0b2004200841b0016a2208470d000b0b0240200e450d002005102a0b02400240200d0d00200621080c010b200d210c20062108034020082802880b2108200c417f6a220c0d000b0340200620062f01064102746a41880b6a2802002106200d417f6a220d0d000b0b200741cc026a20062f0106360200200741c8026a4100360200200741c4026a20063602002007200b3602d002200741003602c002200742003703b802200720083602b402200741003602b002200741b0026a109b010b20002007290338370004200041003602002000412c6a2002370200200041286a2012360200200041246a200f3602002000411c6a200741d0006a290300370000200041146a200741c8006a2903003700002000410c6a200741c0006a2903003700000c050b200b41081037000b200e41081037000b1031000b200741e80a6a280200450d00200741e40a6a280200102a0b024020072802642208450d00200741e8006a280200450d002008102a0b2006ad2102200728027c21042007280274210602400240200728027822080d002006210c0c010b2008210d2006210c0340200c2802880b210c200d417f6a220d0d000b0340200620062f01064102746a41880b6a28020021062008417f6a22080d000b0b200242208621022001ad2103200741cc026a20062f010636020041002108200741c8026a4100360200200741c4026a2006360200200720043602d002200741003602c002200742003703b8022007200c3602b402200741003602b002200741b0026a109b0102402007280294012206450d00200728028c01210d200641b0016c2101034002400240200d20086a22062d0000220c41014b0d0002400240200c0e020001000b0240200641086a280200450d00200641046a280200102a0b200641106a2d00004105490d02200641386a280200450d02200641346a280200102a0c020b200641286a106a0c010b200641e8006a280200450d00200641e4006a280200102a0b2001200841b0016a2208470d000b0b200220038421020240200728029001450d00200728028c01102a0b2000200e36020420004101360200200041146a200b3602002000410c6a2002370200200041086a20053602000b200741b00d6a24000bb80201097f230041106b220224000240200028020041016a220341004c0d0020002003360200200041046a2104200041086a280200210502400240024003402004280200220641086a210720062f010622084105742104410021090240024003402004450d01200120074120109c05220a450d02200441606a2104200941016a2109200741206a2107200a417f4a0d000b2009417f6a21080b2005450d022005417f6a2105200620084102746a41880b6a21040c010b0b2006200941e0006c6a220441a4036a2d000022074101410220074101461b200441c5036a2d00001b22044102470d010b20002802102001200041146a2802002802181101002104200028020021030c010b200441014621040b20002003417f6a360200200241106a240020040f0b41b8b8c0004118200241086a41e0b8c0001038000b8f1901187f230041d0116b2202240020002802102203200328020041016a360200200028020c21042000280208210520002802042103200241206a41186a22062000412c6a290000370300200241206a41106a2207200041246a290000370300200241206a41086a22082000411c6a29000037030020022000290014370320200241a0026a200141e000109a051a024002400240024020032f01062201410b490d00200241b0036a410041e0021099051a20024198066a410041a0081099051a0240024041880b10282209450d00200941003b010620094100360200200941086a200241b0036a41e002109a052101200941e8026a20024198066a41a008109a052106200220032f00c8013b01ac032002200341ca016a2d00003a00ae03200220032900db01370398032002200341e0016a29000037009d03200341cb016a280000210a200341cf016a280000210b200341d3016a280000210c200341d7016a280000210d20024198066a200341a8076a41e000109a051a2001200341e8016a20032f010641796a2200410574109a052101200620034188086a200041e0006c109a052106200341063b0106200920003b0106200220022f01ac033b019403200220022d00ae033a0096032002200229039803370380032002200229009d0337008503200241b0036a20024198066a41e000109a051a0240024020044107490d00200441057420016a41c07e6a2001200441796a22074105746a2201200041ffff037120076b410574109b051a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200441e0006c20066a220041c07b6a200041e07a6a220e200941066a22002f010020076b41e0006c109b051a200e200241a0026a41e000109a051a0c010b200341086a20044105746a220141206a2001200341066a22002f010020046b410574109b051a200141186a200241206a41186a290300370000200141106a200241206a41106a290300370000200141086a200241206a41086a29030037000020012002290320370000200341e8026a200441e0006c6a220e41e0006a200e20002f010020046b41e0006c109b051a200e200241a0026a41e000109a051a0b20024188026a41026a220420022d0096033a0000200020002f010041016a3b0100200220022f0194033b01880220022002290380033703800120022002290085033700850120024190016a200241b0036a41e000109a051a2002411c6a41026a220f20042d00003a0000200220022f0188023b011c2002200229038001370308200220022900850137000d200241206a20024190016a41e000109a051a20032802002206450d0320032f0104211020024198066a410272211103402002419c026a41026a2212200f2d00003a0000200220022f011c3b019c0220022002290308370388022002200229000d37008d02200241a0026a200241206a41e000109a051a201041ffff0371210702400240024020062f01062203410b490d002011410041b20b1099051a41b80b10282201450d0520014100360200200141046a20024198066a41b40b109a051a200220062f00c8013b01ac032002200641ca016a2d00003a00ae03200220062900db01370398032002200641e0016a29000037009d03200641cb016a2800002113200641cf016a2800002114200641d3016a2800002115200641d7016a280000211620024198066a200641a8076a41e000109a051a200141086a200641e8016a20062f0106220041796a2203410574109a052117200141e8026a20064188086a200341e0006c109a052118200141880b6a200641a40b6a2000417a6a2208410274109a052119200641063b0106200120033b010602402008450d00410021032019210003402000280200220420033b010420042001360200200041046a21002008200341016a2203470d000b0b200241b0036a20024198066a41e000109a051a200220022d00ae0322033a009603200220022f01ac0322003b0194032002200229009d033700850320022002290398033703800320024194066a41026a220820033a0000200220003b01940620022002290380033703800120022002290085033700850120024198066a200241b0036a41e000109a051a201041ffff037122004107490d0120172007417a6a22044105746a2017200741796a22034105746a220020012f010620036b410574109b051a200041186a200229008d023700002000200d36000f2000200c36000b2000200b3600072000200a360003200041026a20122d00003a0000200020022f019c023b00002000200229038802370013200741e0006c20186a220041c07b6a200041e07a6a220020012f010620036b41e0006c109b051a2000200241a0026a41e000109a051a200120012f010641016a22003b01062007410274220a20196a416c6a201920044102746a2210200041ffff0371220720046b410274109b051a2010200936020020072004490d022001200a6a41f00a6a2100034020002802002204200341016a22033b010420042001360200200041046a210020032007490d000c030b0b200641086a2200200741016a22044105746a200020074105746a2200200320076b2201410574109b051a2000200d36000f2000200c36000b2000200b3600072000200a360003200041026a2002419c026a41026a2d00003a0000200020022f019c023b00002000200229038802370013200041186a200229008d023700002006200741e0006c6a220041c8036a200041e8026a2200200141e0006c109b051a2000200241a0026a41e000109a051a2006200341016a22033b01062007410274200641880b6a22006a41086a200020044102746a2200200341ffff037120046b410274109b051a20002009360200201041ffff037120062f010622034f0d07200920043b010420092006360200200420034f0d072003417f6a210120062004417f6a22034102746a41900b6a2100034020002802002204200341026a3b010420042006360200200041046a21002001200341016a2203470d000c080b0b200641086a2203200741016a22044105746a200320074105746a220320062f0106221020076b2219410574109b051a2003200d36000f2003200c36000b2003200b3600072003200a360003200341026a20122d00003a0000200320022f019c023b00002003200229038802370013200341186a200229008d02370000200641e8026a200741e0006c6a220341e0006a2003201941e0006c109b051a2003200241a0026a41e000109a051a2006201041016a22033b010620074102742219200641880b6a22106a41086a201020044102746a2210200341ffff037120046b410274109b051a20102009360200200020062f010622044f0d00200620196a418c0b6a2103034020032802002200200741016a22073b010420002006360200200341046a210320042007470d000b0b20024184026a41026a220320082d00003a0000200220022f0194063b01840220022002290380013703f00120022002290085013700f50120024190016a20024198066a41e000109a051a200f20032d00003a0000200220022f0184023b011c200220022903f001370308200220022900f50137000d200241206a20024190016a41e000109a051a0240200628020022030d002013210a2016210d2015210c2014210b200121090c050b20062f010421102013210a2016210d2015210c2014210b20032106200121090c000b0b41880b41081037000b41b80b41081037000b200320044105746a220041286a200041086a2210200120046b410574109b051a200041206a2006290300370000200041186a2007290300370000200041106a2008290300370000201020022903203700002003200441e0006c6a220041c8036a200041e8026a220e20032f010620046b41e0006c109b051a200e200241a0026a41e000109a051a200320032f010641016a3b01060c010b20024198066a410272410041b20b1099051a41b80b10282203450d0120034100360200200341046a20024198066a41b40b109a051a2003200528020022003602880b200520033602002005200528020441016a360204200041003b010420002003360200200320032f010622044105746a220041086a20022f011c3b00002000410a6a2002411c6a41026a2d00003a0000200041176a200d360000200041136a200c3600002000410f6a200b3600002000410b6a200a3600002000411b6a2002290308370000200041206a200229000d3700002003200441e0006c6a41e8026a200241206a41e000109a051a200341880b6a200441016a22004102746a2009360200200320003b0106200920003b0104200920033602000b200241d0116a2400200e0f0b41b80b41081037000b9f19020a7f087e230041800c6b220824000240024002400240024002400240024002400240200728021841016a220941004c0d0020072009360218200741206a280200210a2007411c6a220b210c024002400340200c280200220d41086a210e200d2f0106220f410574210c41002110024002400340200c450d012004200e4120109c052211450d02200c41606a210c201041016a2110200e41206a210e2011417f4a0d000b2010417f6a210f0b200a450d02200a417f6a210a200d200f4102746a41880b6a210c0c010b0b200d201041e0006c6a220c41c5036a310000200c41e8026a2903002212201250220e1ba7450d004200200c41f8026a290300200e1b21134200200c41f0026a290300200e1b21140c010b200841286a200741286a28020020042007412c6a28020028021c110500200841306a290300211320072802182109200829032821140b20072009417f6a360218200141186a29030021122007280240210c20012903102115024002400240024041004101410220142013842216501b20021b0e03010200010b200c41a8016a210c0c020b200c4188016a210c0c010b200c4198016a210c0b20152012844200510d01200841186a200c290300200c41086a2903002015201210a00520014200200129030822122008290318427f200841186a41086a290300501b7d22152015201256220c1b3703080240200c450d0041b2c5c000210c4122210e0c0a0b200728021841016a220141004c0d02200720013602182007280220210a200b210c024002400340200c280200220d41086a210e200d2f0106220f410574210c41002110024002400340200c450d012003200e4120109c052211450d02200c41606a210c201041016a2110200e41206a210e2011417f4a0d000b2010417f6a210f0b200a450d02200a417f6a210a200d200f4102746a41880b6a210c0c010b0b200d201041e0006c6a220c41c5036a310000200c41e8026a2903002212201250220e1ba7450d004200200c41f8026a290300200e1b21124200200c41f0026a290300200e1b21150c010b200841086a200741286a28020020032007412c6a28020028021c110500200841106a290300211220072802182101200829030821150b20072001417f6a3602180240201520057d2217201556201220067d2015200554ad7d221520125620152012511b4101470d00419893c100210c411d210e0c0a0b024020164200520d002007280240220c290378200556200c4180016a290300221220065620122006511b450d0041e293c100210c411f210e0c0a0b2008200341022017201510bc0102402008280200220c450d002008280204210e0c0a0b0240201420057c2216201454220c201320067c200cad7c221220135420122013511b450d0041b593c100210c412d210e0c0a0b4100210c024020032004470d000c0a0b0240200320044120109c050d000c0a0b20072802180d032007417f360218200841e0006a41186a200341186a290000370300200841e0006a41106a200341106a290000370300200841e0006a41086a200341086a2900003703002008200329000037036002400240200728021c221141f8b9c000460d002007280220210a0c010b4100210a200841a0096a410041e0021099051a20084180016a410041a0081099051a41880b10282211450d05201141003b010620114100360200201141086a200841a0096a41e002109a051a201141e8026a20084180016a41a008109a051a200741003602202007201136021c0b02400240034020112f0106220f410574210d4100210c4100210e02400340200d200c460d01200841e0006a2011200c6a41086a4120109c052210450d03200c41206a210c200e41016a210e2010417f4a0d000b200e417f6a210f0b0240200a450d00200a417f6a210a2011200f4102746a41880b6a28020021110c010b0b200841c0006a41186a200841e0006a41186a2903002213370300200841c0006a41106a200841e0006a41106a2903002214370300200841c0006a41086a200841e0006a41086a2903002218370300200820082903602219370340200841bc096a2018370200200841a0096a41246a2014370200200841cc096a20133702002008200741246a22013602b0092008200f3602ac092008200b3602a809200820113602a409200841003602a009200820193702b409200841b4016a4200370200200841bc016a41003a0000200841f8b9c0003602b00120084200370398012008420037038001200841003a00dd01200841a0096a20084180016a10b701210c0c010b20084198016a420037030020084194016a41f8b9c000360200200841003602a00120084100360290012008420037038801200841f8b9c000360284012008410036028001200741246a21012011200e41e0006c6a41e8026a210c20084180016a1095010b200c41106a2015370300200c2017370308200c420137030020072007280218220c41016a220e360218200e200c4f0d052007417f360218200841e0006a41186a200441186a290000370300200841e0006a41106a200441106a290000370300200841e0006a41086a200441086a2900003703002008200429000037036002400240200728021c221141f8b9c000460d002007280220210a0c010b4100210a200841a0096a410041e0021099051a20084180016a410041a0081099051a41880b10282211450d07201141003b010620114100360200201141086a200841a0096a41e002109a051a201141e8026a20084180016a41a008109a051a200741003602202007201136021c0b02400240034020112f0106220f410574210d4100210c4100210e02400340200d200c460d01200841e0006a2011200c6a41086a4120109c052210450d03200c41206a210c200e41016a210e2010417f4a0d000b200e417f6a210f0b0240200a450d00200a417f6a210a2011200f4102746a41880b6a28020021110c010b0b200841c0006a41186a200841e0006a41186a2903002215370300200841c0006a41106a200841e0006a41106a2903002213370300200841c0006a41086a200841e0006a41086a2903002214370300200820082903602217370340200841bc096a2014370200200841c4096a2013370200200841cc096a2015370200200820013602b0092008200f3602ac092008200b3602a809200820113602a409200841003602a009200820173702b409200841b4016a4200370200200841bc016a41003a0000200841f8b9c0003602b00120084200370398012008420037038001200841003a00dd01200841a0096a20084180016a10b701210c0c010b20084198016a420037030020084194016a41f8b9c000360200200841003602a00120084100360290012008420037038801200841f8b9c0003602840120084100360280012011200e41e0006c6a41e8026a210c20084180016a1095010b200c41106a2012370300200c2016370308200c42013703002007200728021841016a360218200841a0096a41086a2210200341086a290000370300200841a0096a41106a2211200341106a290000370300200841a0096a41186a220d200341186a290000370300200841e0006a41086a220a200441086a290000370300200841e0006a41106a220f200441106a290000370300200841e0006a41186a2201200441186a290000370300200820032900003703a0092008200429000037036002402007413c6a280200220e200741386a280200470d00200e41016a220c200e490d09200e4101742204200c2004200c4b1b2203ad42b0017e2212422088a70d092012a722044100480d0902400240200e0d0020041028210c0c010b2007280234200e41b0016c2004102c210c0b200c450d082007200c360234200741386a2003360200200728023c210e0b4100210c2007280234200e41b0016c6a220e41003a0000200e20082f003d3b0001200e4200370008200e4101360004200e20082903a009370011200e2008290360370031200e41036a2008413f6a2d00003a0000200e41106a41003a0000200e41196a2010290300370000200e41216a2011290300370000200e41296a200d290300370000200e41396a200a290300370000200e41c1006a200f290300370000200e41c9006a2001290300370000200e2005370358200e41e0006a2006370300200e41d4006a200841c0006a41036a280000360000200e2008280040360051200e41e8006a20084180016a41c800109a051a2007200728023c41016a36023c0c090b41b8b8c000411820084180016a41e0b8c0001038000b419cb7c0001032000b41b8b8c000411820084180016a41e0b8c0001038000b41a8b8c000411020084180016a41d0b8c0001038000b41880b41081037000b41a8b8c000411020084180016a41d0b8c0001038000b41880b41081037000b200441081037000b1031000b2000200e3602042000200c360200200841800c6a24000bb011030b7f017e047f230041b0016b220324000240024002400240024002400240024002400240411410282204450d00200441002900ddd843370000200441106a41002800edd843360000200441086a41002900e5d84337000020034294808080c00237023c200320043602382003200341386a36028001200120034180016a10c801200328023821042003280240210520034180016a41186a2206420037030020034180016a41106a2207420037030020034180016a41086a2208420037030020034200370380012004200520034180016a1000200341d8006a41186a2006290300370300200341d8006a41106a2007290300370300200341d8006a41086a200829030037030020032003290380013703580240200328023c450d002003280238102a0b2003410036028001200341d8006a412020034180016a100621062003280280012209417f460d032006450d0320032009360284012003200636028001200341286a20034180016a106c20032802280d02200328022c2105200341206a20034180016a106c20032802200d0220032802242108200341186a20034180016a106c20032802180d022003280284012204450d02200328021c210a20032004417f6a360284012003200328028001220441016a3602800120042d0000220441014b0d024100210b0240024020040e020100010b4101210b0b200341106a20034180016a106c20032802100d02200328028401220c20032802142204490d022004417f4c0d050240024020040d00410121070c010b2004102e2207450d022007200328028001220d2004109a051a2003200c20046b360284012003200d20046a360280010b2007450d02200341a0016a41026a220c200341386a41026a220d2d00003a0000200320032f00383b01a00102402009450d002006102a0b200d200c2d000022063a0000200341346a41026a20063a0000200320032f01a00122063b0138200320063b0134410021060c040b411441011037000b200441011037000b41c4d1c3004133200341386a419cd9c3001038000b4101210641d2bfc2002105411121084102210b0b200341306a41026a2209200341346a41026a220c2d00003a0000200320032f01343b013002402006450d002000200536020420004101360200200041086a20083602000c050b200c20092d00003a0000200320032f01303b013402400240200228025820054b0d002004210620042102200721090c010b411510282205450d02200541002900c8d8433700002005410d6a41002900d5d843370000200541086a41002900d0d84337000020034295808080d00237023c200320053602382003200341386a36028001200120034180016a10c801200328023821052003280240210620034180016a41186a2208420037030020034180016a41106a2209420037030020034180016a41086a220b420037030020034200370380012005200620034180016a1000200341d8006a41186a2008290300370300200341d8006a41106a2009290300370300200341d8006a41086a200b29030037030020032003290380013703580240200328023c450d002003280238102a0b2003410036028001200341d8006a412020034180016a100621060240024002402003280280012208417f460d002006450d0020032008360284012003200636028001200341086a20034180016a106c02400240024020032802080d002003280284012209200328020c2205490d002005417f4c0d070240024020050d004101210c0c010b2005102e220c450d02200c200328028001220b2005109a051a2003200920056b360284012003200b20056a360280010b200c0d020b41c4d1c3004133200341386a419cd9c3001038000b200541011037000b2005ad220e422086200e84210e02402008450d002006102a0b20034180016a200c200e422088a7200210f802200ea7210d20034180016a41086a280200210820032802840121052003280280014101470d022000200536020420004101360200200041086a2008360200200d450d01200c102a0c010b200041e3bfc20036020420004101360200200041086a411a3602000b2004450d062007102a0c060b200341d8006a41026a220f2003419f016a2d00003a0000200320032f009d013b01582003419c016a2d0000210b20034198016a280200210620034194016a280200210220034190016a28020021092003418c016a280200210a02402004450d002007102a0b200341346a41026a200f2d00003a0000200320032f01583b01342006417f4c0d010240024020060d0041002107410121040c010b20062107200610282204450d040b200420092006109a05210f200341386a41146a2006360200200341386a41106a20073602002003200a3602402003200836023c200320053602382003200f3602442003200b41ff01714101463a0050411410282204450d04200441002900ddd843370000200441106a41002800edd843360000200441086a41002900e5d84337000020034294808080c0023702a401200320043602a0012003200341a0016a36028001200120034180016a10c80120032802a001210420032802a801210120034180016a41186a2210420037030020034180016a41106a2211420037030020034180016a41086a2212420037030020034200370380012004200120034180016a1000200341d8006a41186a2010290300370300200341d8006a41106a2011290300370300200341d8006a41086a20122903003703002003200329038001370358024020032802a401450d0020032802a001102a0b20034120360284012003200341d8006a36028001200341386a20034180016a10f90202402007450d00200f102a0b200d450d00200c102a0b20002005360204200020032f01343b001d200041003602002000411c6a200b3a0000200041186a2006360200200041146a2002360200200041106a20093602002000410c6a200a360200200041086a20083602002000411f6a200341366a2d00003a00000c040b1036000b411541011037000b200641011037000b411441011037000b200341b0016a24000b821d02097f017e230041e0006b22062400024002402002410c6a280200200241106a280200100f2207417f460d00410c102822080d01410c41041037000b10fc02000b200820073602082008428180808010370200200641186a420037030020064280808080c0003703102006420437030802400240024002400240024002400240024002400240024002400240024002402008280200220741016a220941014d0d00200820093602002007417e460d002008200741026a3602000240200628021c22072006280218470d00200741016a22092007490d0b2007410174220a2009200a20094b1b220941ffffffff03712009470d0b2009410274220b4100480d0b0240024020070d00200b1028210a0c010b20062802142007410274200b102c210a0b200a450d02200620093602182006200a3602140b200628021420074102746a20083602002006200628021c41016a36021c2008280208210b410310282209450d02200941026a41002d00fae2453a0000200941002f00f8e2453b000041061028220a450d03200a41046a41002f00cf8f443b0000200a41002800cb8f44360000024020062802102207200628020c470d00200741016a220c2007490d0b2007410174220d200c200d200c4b1b220c41ffffff3f71200c470d0b200c410574220e4100480d0b0240024020070d00200e1028210d0c010b20062802082007410574200e102c210d0b200d450d052006200c36020c2006200d3602080b200628020820074105746a220741013602182007200a36020c2007428380808030370204200720093602002007411c6a200b360200200741106a4286808080e0003702002006200628021041016a36021020082008280200417f6a2207360200024020070d002008280208101020082008280204417f6a220736020420070d002008102a0b200641086a41f8e2c500410341effec5004103410b10fe02200641086a41f8e2c500410341f2fec500410f410c10fe02200641086a41f8e2c50041034181ffc500410f410d10fe02200641086a41f8e2c50041034190ffc5004108410e10fe02200641086a41f8e2c50041034198ffc500410f410f10fe02200641086a41f8e2c500410341a7ffc500410a411010fe02200641086a41f8e2c500410341b1ffc500410a411110fe02200641086a41f8e2c500410341bbffc500410b411210fe02200641086a41f8e2c500410341c6ffc500410d411310fe02200641086a41f8e2c500410341d3ffc500410c411410fe02200641086a41f8e2c500410341dfffc500410b411510fe02200641086a41f8e2c500410341eaffc5004115411610fe02200641086a41f8e2c500410341ffffc500410a411710fe02200641086a41f8e2c5004103418980c6004107411810fe02200641086a41f8e2c5004103419080c6004113411910fe02200641086a41f8e2c500410341a380c6004111411a10fe02200641086a41f8e2c500410341b480c600410e411b10fe02200641086a41f8e2c500410341c280c6004110411c10fe02200641086a41f8e2c500410341d280c6004110411d10fe02200641086a41f8e2c500410341e280c6004111411e10fe02200641086a41f8e2c500410341f380c6004111411f10fe02200641086a41f8e2c5004103418481c6004116412010fe02200641086a41f8e2c5004103419a81c6004112412110fe02200641086a41f8e2c500410341ac81c600410b412210fe02200641086a41f8e2c500410341b781c6004110412310fe02200641206a410c6a200441086a280200360200200620033602204100210d2006410036023c20062005360238200620083602342006200429020037022420062001280200360230200241146a280200210b2002411c6a280200210c200628020821072006280210210820064100360258200642013703502008200641d0006a10b40102402008450d00200720084105746a2105034020072802002104200741086a2802002208200641d0006a10b401024002402006280254220a200628025822096b2008490d002006280250210a0c010b200920086a22012009490d0d200a41017422032001200320014b1b22014100480d0d02400240200a0d0020011028210a0c010b2006280250200a2001102c210a0b200a450d08200620013602542006200a3602500b2006200920086a360258200a20096a20042008109a051a2007410c6a2802002103200741146a280200220a200641d0006a10b4010240024020062802542209200628025822046b200a490d00200628025021080c010b2004200a6a22082004490d0d200941017422012008200120084b1b22014100480d0d0240024020090d002001102821080c010b200628025020092001102c21080b2008450d092006200136025420062008360250200121090b20062004200a6a2201360258200820046a2003200a109a051a02400240200741186a2802004101460d000240024020092001460d002009210a0c010b200941016a220a2009490d0f20094101742204200a2004200a4b1b220a4100480d0f0240024020090d00200a102821080c010b20082009200a102c21080b2008450d0c2006200a360254200620083602500b2006200141016a2209360258200820016a41013a000020062007411c6a2802002204360248200641c8006a21010c010b0240024020092001460d002009210a0c010b200941016a220a2009490d0e20094101742204200a2004200a4b1b220a4100480d0e0240024020090d00200a102821080c010b20082009200a102c21080b2008450d0c2006200a360254200620083602500b2006200141016a2209360258200820016a41023a000020062007411c6a2802002204360248200641c8006a21010b0240200a20096b41034b0d00200941046a22042009490d0d200a41017422032004200320044b1b22044100480d0d02400240200a0d002004102821080c010b2008200a2004102c21080b2008450d0c2006200436025420062008360250200128020021040b2006200941046a360258200820096a2004360000200741206a22072005470d000b0b2006280254210302404124200b200c2006280250220e2006280258200641206a1011220b41036a220841024b0d000240024020080e03000201000b4102210d0b41012104024020030d000c110b200e102a0c100b200628021c220541ffffffff03712005470d0b20054102742207417f4c0d0b200628021421080240024020070d004104210c0c010b20071028220c450d0d0b0240024020050d004100210a0c010b200541027421044100210a200c210703402008280200220928020041016a220141014d0d022009200136020020072009360200200a41016a210a200741046a2107200841046a21082004417c6a22040d000b0b02402003450d00200e102a0b200228020421092002280200210420064100360258200642013703504100200641d0006a10b401200628025821012006280254210220062802502107410a102e2208450d0d0240024002400240200b20042009200720012008410a200641206a101241036a220941034b0d004101210420090e0402000001020b41a8c7c2001032000b2006410936024c410121042006200841016a36024820082d0000220941014b0d01410421010240024020090e020100010b200641d0006a200641c8006a109803200628025022014104460d02200628025421030b410021040b2008102a2002450d0f2007102a0c0f0b2008102a024020020d000c0f0b2007102a0c0e0b00000b200b41041037000b410341011037000b410641011037000b200e41041037000b200141011037000b200141011037000b200a41011037000b200a41011037000b200441011037000b1031000b1036000b200741041037000b410a41011037000b200b10130240200a450d00200a4102742107200c21080340200828020022092009280200417f6a3602000240200828020022092802000d0020092802081010200828020022092009280204417f6a360204200828020022092802040d002009102a0b200841046a21082007417c6a22070d000b0b4102210d2005450d00200c102a0b200641206a41086a28020021072006280234210820062802242109024002400240024002400240024002400240200628023c220a0d002006412c6a290200210f20040d04200141044b0d0320010e050203030301020b2000200a36020420004100360200200041106a41003a0000200041086a200641c0006a29030037020002402007450d002009102a0b20082008280200417f6a220736020020070d072008280208101020082008280204417f6a22073602042007450d060c070b2000200936020441002109200041106a41003a00002000410c6a4100360200200041086a20073602000c040b20002009360204200041106a20033a00002000410c6a200f3e0200200041086a2007360200410021090c030b200041aa9cc400360204200041146a200f3e0200200041106a20073602002000410c6a2009360200200041086a41113602000c010b0240200d450d00200041cb9cc400360204200041146a200f3e0200200041106a20073602002000410c6a2009360200200041086a41103602000c010b200041bb9cc400360204200041146a200f3e0200200041106a20073602002000410c6a2009360200200041086a41103602000b410121090b2000200936020020082008280200417f6a220736020020070d012008280208101020082008280204417f6a220736020420070d010b2008102a0b024020062802102207450d00200628020821082007410574210703400240200841046a280200450d002008280200102a0b0240200841106a280200450d002008410c6a280200102a0b200841206a2108200741606a22070d000b0b0240200628020c450d002006280208102a0b0240200628021c2207450d0020062802142108200741027421070340200828020022092009280200417f6a3602000240200828020022092802000d0020092802081010200828020022092009280204417f6a360204200828020022092802040d002009102a0b200841046a21082007417c6a22070d000b0b02402006280218450d002006280214102a0b200641e0006a24000b8a1409057f017e0c7f047e037f017e037f047e097f230041f00c6b22022400024020002802000d002000417f360200200128020821032001280200210402400240200128020422050d00200421010c010b2005210620042101034020012802880b21012006417f6a22060d000b0340200420042f01064102746a41880b6a28020021042005417f6a22050d000b0b2002411c6a20042f0106360200200241186a4100360200200241146a20043602002002200336022020024100360210200242003703082002200136020420024100360200200241f0016a2002109301024020022903900222074202510d002000410c6a2108200041046a2109200241900a6a41146a210a200241900a6a41206a210b200241f0016a4104722103200241f0016a413d6a210c200241cd026a210d200241b8026a210e200241f0016a41306a210f200241f0016a41286a21100340200241c8006a41086a2204200241f0016a41086a2211290300370300200241c8006a41106a2201200241f0016a41106a2212290300370300200241c8006a41186a2205200241f0016a41186a2213290300370300200220022903f001370348200e2903002114200f290300211520022903b0022116200229039802211720022f01ee02211820022d00ed02211920022d00cc02211a20022903a802211b20022802c002211c20022802c402211d20022802c802211e200241286a41186a200d41186a290000221f370300200241286a41106a200d41106a2900002220370300200241286a41086a200d41086a29000022213703002002200d2900002222370328200241e8006a41186a2223201f370300200241e8006a41106a22242020370300200241e8006a41086a222520213703002002202237036820024188016a41186a2226200529030037030020024188016a41106a2227200129030037030020024188016a41086a222820042903003703002002200229034837038801024002400240024002402009280200222941f8b9c000460d002000280208212a0c010b200241900a6a410041e0021099051a200241f0016a410041a0081099051a41880b10282229450d014100212a202941003b010620294100360200202941086a200241900a6a41e002109a051a202941e8026a200241f0016a41a008109a051a20004100360208200020293602040b0340202941086a210120292f0106222b410574210441002105024003402004450d0120024188016a20014120109c052206450d04200441606a2104200541016a2105200141206a21012006417f4a0d000b2005417f6a212b0b0240202a450d00202a417f6a212a2029202b4102746a41880b6a28020021290c010b0b200241c0016a41186a2026290300221f370300200241c0016a41106a20272903002220370300200241c0016a41086a20282903002221370300200220022903880122223703c001200a2022370200200a41086a2021370200200a41106a2020370200200a41186a201f370200200220083602a00a2002202b36029c0a200220093602980a200220293602940a200241003602900a20102014370300201220153703002002201637039002200220173703f8012002201a3a00ac022002201e3602a8022002201d3602a4022002201c3602a0022002201b37038802200220073703f001200c2002290368370000200c41086a2025290300370000200c41106a2024290300370000200c41186a2023290300370000200220183b01ce02200220193a00cd02200241900a6a200241f0016a10b7011a0c020b41880b41081037000b202941e8026a200541e0006c6a2129024020194101710d0020292029290300200720075022041b37030020292029290308201720041b370308202941106a22012001290300201520041b370300200241900a6a41186a22062023290300370300200241900a6a41106a222a2024290300370300200241900a6a41086a222b2025290300370300200220022903683703900a20292d003c21012013202941d5006a22052900003703002012202941cd006a22192900003703002011202941c5006a222329000037030020022029413d6a22242900003703f0012028200241900a6a200241f0016a201a41ff0171410146221a1b220441086a2900003703002027200441106a2900003703002026200441186a2900003703002002200429000037038801202941012001201a1b3a003c2024200229038801370000202320282903003700002019202729030037000020052026290300370000202920162029290320201ba722041b370320202941286a22012014200129030020041b3703002029201b202929031820041b37031802400240201d0d00201c21040c010b201d2101201c2104034020042802ec0321042001417f6a22010d000b0340201c201c2f01064102746a41ec036a280200211c201d417f6a221d0d000b0b201c2f010621012002201e3602a801200220013602a401200241003602a0012002201c36029c01200241003602980120024200370390012002200436028c012002410036028801200241f0016a20024188016a109901024020022802f0014101470d00202941306a211c0340200241900a6a41286a200341286a280200360200200b200341206a2902003703002006200341186a2204290200370300202a200341106a2201290200370300202b200341086a2205290200370300200220032902003703900a200241c0016a41186a2004290000370300200241c0016a41106a2001290000370300200241c0016a41086a2005290000370300200220032900003703c001200241e0016a41086a200b41086a2802003602002002200b2902003703e001200241b0016a201c200241c0016a200241e0016a10bd01024020022802b001450d0020022802b4012204450d0020022802b801450d002004102a0b200241f0016a20024188016a10990120022802f0014101460d000b0b20024188016a1095010c010b202941386a212b202941306a212a202928023821262029280230210402400240202941346a28020022050d00200421010c010b2005210620042101034020012802ec0321012006417f6a22060d000b0340200420042f01064102746a41ec036a28020021042005417f6a22050d000b0b200220263602900220024100360288022002410036028002200242003703f801200220013602f401200241003602f0012002200436028402200220042f010636028c02200241f0016a109501202941286a201437030020292016370320202941106a2015370300202920173703082029201b37031820292007370300202a201d360204202a201c360200202b201e3602002029201a3a003c2029413d6a2002290368370000202941c5006a2025290300370000202941cd006a2024290300370000202941d5006a2023290300370000202920183b015e202920193a005d0b200241f0016a200210930120022903900222074202520d000b0b2002109b012000200028020041016a360200200241f00c6a24000f0b41a8b8c0004110200241f0016a41d0b8c0001038000bf00203027f017e037f230041306b22052400024002400240200241ff0171417e6a220641024b0d000240024020060e03000201000b200520011099022005290300200358200541086a290300220720045820072004511b0d010c020b200541106a20011099022005290310200356200541186a290300220720045620072004511b0d010b200541206a2001109a020240200528022822010d0002402005280224450d002005280220102a0b410021010c020b200141057421061098012108200528022421092005280220220a2101024002400240034002402008200141106a2802004f0d002001290300200358200141086a290300220720045820072004511b0d002001411c6a2d000020027141ff0171200241ff0171460d020b200141206a2101200641606a22060d000b4100210120090d010c020b4184dfc00021012009450d010b200a102a0b413121060c010b41dedec0002101412621060b2000200636020420002001360200200541306a24000bc31e03087f037e127f23004180076b22042400200441e0006a41186a200241186a290000370300200441e0006a41106a200241106a290000370300200441e0006a41086a200241086a290000370300200420022900003703600240024002400240024002400240024002402001280200220541f8b9c000460d00200128020421060c010b41002106200441e8026a410041e0021099051a200441c0016a41004184011099051a41ec0310282205450d01200541003b010620054100360200200541086a200441e8026a41e002109a051a200541e8026a200441c0016a418401109a051a20014100360204200120053602000b02400340200541086a2107200541066a210820052f0106220941057421024100210a0240024003402002450d01200441e0006a20074120109c05220b450d02200241606a2102200a41016a210a200741206a2107200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200520094102746a41ec036a28020021050c010b0b200441e8026a41086a22022005200a410c6c6a220741f0026a220a2802003602002004200741e8026a22072902003703e80220072003290200370200200a200341086a280200360200200441c0016a41086a20022802002202360200200420042903e802220c3703c0012000410c6a20023602002000200c370204200041013602000c060b200441086a41186a220b200441e0006a41186a2202290300370300200441086a41106a200441e0006a41106a2207290300220c370300200441086a41086a200441e0006a41086a220a290300220d37030020042004290360220e3703082001200128020841016a3602082007200c370300200a200d3703002002200b2903003703002004200e370360200441d8026a41086a2206200341086a280200360200200420032902003703d802024020082f01002203410b490d00200441e8026a410041e0021099051a200441c0016a41004184011099051a41ec031028220f450d02200f41003b0106200f4100360200200f41086a200441e8026a41e002109a052107200f41e8026a200441c0016a418401109a05210a200441e8026a41086a220b200541b8036a280200360200200420052900db013703a8012004200541e0016a2900003700ad01200420052902b0033703e802200420052f00c8013b01bc012004200541ca016a2d00003a00be01200541cb016a2800002110200541cf016a2800002111200541d3016a2800002112200541d7016a28000021132007200541e8016a20052f010641796a2202410574109a052107200a200541bc036a2002410c6c109a05210a200541063b0106200f20023b0106200420042f01bc013b01a401200420042d00be013a00a601200420042903a8013703c001200420042900ad013700c501200441286a41086a200b280200360200200420042903e8023703280240024020094107490d00200941057420076a41c07e6a2007200941796a220b4105746a2207200241ffff0371200b6b410574109b051a200741186a200441e0006a41186a290300370000200741106a200441e0006a41106a290300370000200741086a200441e0006a41086a290300370000200720042903603700002009410c6c200a6a220241b87f6a200241ac7f6a2202200f41066a22082f0100200b6b410c6c109b051a200241086a200441d8026a41086a280200360200200220042903d8023702000c010b200541086a20094105746a220241206a200220082f010020096b410574109b051a200241186a200441e0006a41186a290300370000200241106a200441e0006a41106a290300370000200241086a200441e0006a41086a29030037000020022004290360370000200541e8026a2009410c6c6a2202410c6a200220082f010020096b410c6c109b051a200241086a200441d8026a41086a280200360200200220042903d8023702000b200820082f010041016a3b010020044198016a41026a220220042d00a6013a0000200441c8026a41086a2214200441286a41086a280200360200200420042f01a4013b019801200420042903c001370350200420042900c501370055200420042903283703c8022004413c6a41026a221520022d00003a0000200420042f0198013b013c2004200429005537002d20042004290350370328200441c0006a41086a22162014280200360200200420042903c80237034020052802002206450d0420052f01042103200441e8026a4102722117034020044194016a41026a221820152d00003a0000200420042f013c3b019401200420042903283703602004200429002d37006520044198016a41086a221920162802003602002004200429034037039801200341ffff0371210502400240024020062f01062202410b490d00201741004196041099051a419c041028220b450d07200b4100360200200b41046a200441e8026a419804109a051a200420062f00c8013b01bc012004200641ca016a2d00003a00be012004200641db016a2900003703a8012004200641e0016a2900003700ad01200641cb016a280000211a200641cf016a280000211b200641d3016a280000211c200641d7016a280000211d200441e8026a41086a221e200641b8036a2802003602002004200641b0036a2902003703e802200b41086a200641e8016a20062f0106220741796a2202410574109a05211f200b41e8026a200641bc036a2002410c6c109a052120200b41ec036a20064188046a2007417a6a2209410274109a052108200641063b0106200b20023b010602402009450d00410021022008210703402007280200220a20023b0104200a200b360200200741046a21072009200241016a2202470d000b0b200441d8026a41086a2202201e280200360200200420042d00be0122073a00a601200420042f01bc01220a3b01a401200420042903a8013703c001200420042900ad013700c501200420042903e8023703d802200441c4026a41026a220920073a00002004200a3b01c402200420042903c0013703e802200420042900c5013700ed0220142002280200360200200420042903d8023703c802200341ffff037122074107490d01201f2005417a6a220a4105746a201f200541796a22024105746a2207200b2f010620026b410574109b051a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20182d00003a0000200720042f0194013b0000200720042903603700132005410c6c20206a220741b87f6a200741ac7f6a2207200b2f0106220320026b410c6c109b051a200741086a20192802003602002007200429039801370200200b200341016a22073b01062005410274221020086a416c6a2008200a4102746a2203200741ffff03712205200a6b410274109b051a2003200f3602002005200a490d02200b20106a41d4036a210703402007280200220a200241016a22023b0104200a200b360200200741046a210720022005490d000c030b0b200641086a2207200541016a220a4105746a200720054105746a2207200220056b410574109b051a200741186a20042900653700002007201336000f2007201236000b2007201136000720072010360003200741026a20044194016a41026a2d00003a0000200720042f0194013b00002007200429036037001320062005410c6c6a220241f4026a200241e8026a220720062f0106220b20056b410c6c109b051a200241f0026a20044198016a41086a28020036020020072004290398013702002006200b41016a22023b01062005410274200641ec036a22076a41086a2007200a4102746a2207200241ffff0371220b200a6b410274109b051a2007200f360200200341ffff0371200b4f0d082006200a417f6a22024102746a41f0036a210703402007280200220a200241016a22023b0104200a2006360200200741046a21072002200b490d000c090b0b200641086a2202200541016a22034105746a200220054105746a220220062f010620056b410574109b051a200241186a20042900653700002002201336000f2002201236000b2002201136000720022010360003200241026a20182d00003a0000200220042f0194013b000020022004290360370013200641e8026a2005410c6c6a2202410c6a200220062f0106220a20056b410c6c109b051a200241086a201928020036020020022004290398013702002006200a41016a22023b010620054102742210200641ec036a220a6a41086a200a20034102746a2208200241ffff0371220a20036b410274109b051a2008200f3602002007200a4f0d00200620106a41f0036a2102034020022802002207200541016a22053b010420072006360200200241046a2102200a2005470d000b0b20044190016a41026a220220092d00003a000020044180016a41086a22072014280200360200200420042f01c402220a3b019001200420042903e802370350200420042900ed02370055200420042903c80237038001201520022d00003a00002004200a3b013c2004200429005537002d200420042903503703282016200728020036020020042004290380013703400240200628020022020d00201a2110201d2113201c2112201b2111200b210f0c060b20062f01042103201a2110201d2113201c2112201b211120022106200b210f0c000b0b200520094105746a220b41286a200b41086a2201200320096b410574109b051a200b41206a2002290300370000200b41186a2007290300370000200b41106a200a2903003700002001200429036037000020052009410c6c6a220241f4026a200241e8026a220720052f010620096b410c6c109b051a200241f0026a2006280200360200200720042903d802370200200520052f010641016a3b01060c040b41ec0341041037000b41ec0341041037000b419c0441041037000b200441e8026a41027241004196041099051a419c0410282202450d0220024100360200200241046a200441e8026a419804109a051a2002200128020022073602ec03200120023602002001200128020441016a360204200741003b010420072002360200200220022f0106220a4105746a220741086a20042f013c3b00002007410a6a2004413c6a41026a2d00003a0000200741176a2013360000200741136a20123600002007410f6a20113600002007410b6a20103600002007411b6a2004290328370000200741206a200429002d3700002002200a410c6c6a220741f0026a200441c0006a41086a280200360200200741e8026a2004290340370200200241ec036a200a41016a22074102746a200f360200200220073b0106200f20073b0104200f20023602000b200041003602000b20044180076a24000f0b419c0441041037000bc50101057f230041306b220124002000410c6a28020021022000280204210302400240200041086a28020022040d00200321000c010b2004210520032100034020002802880b21002005417f6a22050d000b0340200320032f01064102746a41880b6a28020021032004417f6a22040d000b0b200141246a20032f0106360200200141206a41003602002001411c6a20033602002001200236022820014100360218200142003703102001200036020c20014100360208200141086a109b01200141306a24000bcb0401097f230041c0006b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a280200210602400240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d01200220084120109c05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a220841e8026a210502400240200841c5036a2d00000d00200341206a41086a220a200541c5006a290000370300200341206a41106a220b200541cd006a290000370300200341206a41186a2207200541d5006a29000037030020032005413d6a2900003703204102210820052d003c4101470d01200341186a2007290300370300200341106a200b290300370300200341086a200a29030037030020032003290320370300410121080c010b200341086a200541c5006a290000370300200341106a200541cd006a290000370300200341186a200541d5006a29000037030020032005413d6a29000037030020052d003c21080b200841ff01714102470d010b200020012802102002200141146a280200280210110500200128020021040c010b200020083a000020002003290300370001200041096a200341086a290300370000200041116a200341106a290300370000200041196a200341186a2903003700000b20012004417f6a360200200341c0006a24000f0b41b8b8c0004118200341206a41e0b8c0001038000be80202097f027e230041206b220324000240200128020041016a220441004c0d0020012004360200200141046a2105200141086a28020021060240024003402005280200220741086a210820072f0106220941057421054100210a0240024003402005450d01200220084120109c05220b450d02200541606a2105200a41016a210a200841206a2108200b417f4a0d000b200a417f6a21090b2006450d022006417f6a2106200720094102746a41880b6a21050c010b0b2007200a41e0006c6a220541c5036a310000200541e8026a290300220c200c5022081ba7450d004200200541f8026a29030020081b210c4200200541f0026a29030020081b210d0c010b200341086a20012802102002200141146a28020028021c110500200341106a290300210c200128020021042003290308210d0b20012004417f6a3602002000200c3703082000200d370300200341206a24000f0b41b8b8c0004118200341186a41e0b8c0001038000ba62a020c7f037e230022072108200741800f6b41607122072400200720043703382007200337033020072005360244024002400240024002402001280230200128024022092802b801460d002005420020052903082203200941386a2903007d2204200420035622091b37030820090d0120074180046a20024100410110c201200741a4046a280200210a200741a0046a280200210b20072d008804220541037122094103460d0220090e03030203030b200041d4c5c00036020420004101360200200041086a41293602002000410c6a2006290200370200200041146a200641086a2802003602000c030b200041fdc5c00036020420004101360200200041086a41233602002000410c6a2006290200370200200041146a200641086a280200360200200824000f0b200041a0c6c00036020420004101360200200041086a41193602002000410c6a2006290200370200200041146a200641086a28020036020020050d01200a450d01200b102a200824000f0b200741a8046a2802002109200741c8006a41186a220c200141e8006a290000370300200741c8006a41106a220d200141e0006a290000370300200741c8006a41086a220e200141d8006a290000370300200720012900503703484100210f4100211002400240024002400240024002400240024002400240024002400240024020050d002009417f4c0d010240024020090d002007420037038004410121100c010b200910282210450d03200741003602840420072009360280040b20072009360284042010200b2009109a051a2007290380042103200a450d00200b102a0b200741a4016a410036020020074194016a419cc4c000360200200741e8006a41206a420037030020074184016a41f8b9c000360200200741e8006a41106a2003370300200741e8006a41d8006a200241086a290000370300200741e8006a41e0006a200241106a290000370300200741e8006a41e8006a200241186a29000037030020072001360270200741e8006a41286a200141186a22113602002007420837029c01200741003602800120072010360274200720022900003703b801200720012802483602b001200720012903403703a8012007200128023041016a36029801200129030021032007200128024c3602b40120072003370368200741d8016a41206a200e290300370300200741d8016a41286a200d29030037030020074188026a200c290300370300200741ec016a200641086a280200360200200720023602e001200720072903483703f001200720062902003702e4012007200741c4006a3602dc012007200741306a3602d8010240024020072903302203200741306a41086a290300220484500d00200741286a20072802444100200741f0016a200220032004200741e8006a10b801200728022822060d01200728028001210f20072802e00121020b200f41016a220d41004c0d03200741d8016a41186a210e200741e4016a210f2007200d36028001200741e8006a41206a280200210a20074184016a2212210602400240024003402006280200220b41086a2105200b2f0106220c4105742106410021090240024003402006450d01200220054120109c052210450d02200641606a2106200941016a2109200541206a21052010417f4a0d000b2009417f6a210c0b200a450d02200a417f6a210a200b200c4102746a41880b6a21060c010b0b200b200941e0006c6a220541e8026a210602400240200541c5036a2d00000d0020074180046a41086a2209200641c5006a29000037030020074180046a41106a2210200641cd006a29000037030020074180046a41186a220b200641d5006a29000037030020072006413d6a290000370380044102210520062d003c4101470d01200741a00c6a41186a200b290300370300200741a00c6a41106a2010290300370300200741a00c6a41086a200929030037030020072007290380043703a00c410121050c010b200741a80c6a200641c5006a290000370300200741b00c6a200641cd006a290000370300200741b80c6a200641d5006a29000037030020072006413d6a2900003703a00c20062d003c21050b200541ff01714102470d010b20074190026a2007280290012002200728029401280210110500200728028001210d20072d00900221050c010b20074199026a200741a80c6a290300370000200741a1026a200741b00c6a290300370000200741a9026a200741b80c6a290300370000200720053a009002200720072903a00c370091020b2007200d417f6a360280014101210a0240200541ff01714101470d00200741b8026a41186a200741a9026a290000370300200741b8026a41106a200741a1026a290000370300200741b8026a41086a20074199026a29000037030020072007290091023703b80220074180046a200741b8026a20072802b00128020010b90102402007280280044101470d0020072902e4012203422088a7210520074180046a41086a28020021092007280284042106200741ec016a28020021102003a721020c100b200741a00c6a41186a220520074180046a410472220641186a2802002209360200200741d8026a41106a200641086a290200370300200741d8026a41186a200641106a290200370300200741f8026a2009360200200741043602dc02200741af8dc6003602d802200720062902003703e00220072802ac0121062005200e41186a2900002203370300200741a00c6a41106a200e41106a2900002204370300200741a00c6a41086a2205200e41086a2900002213370300200741a8046a2013370300200741b0046a2004370300200741b8046a20033703002007200e29000022033703a00c200720033703a00420072802d801220941086a29030021032007200741e8006a36029804200929030021042007290368211320072802b4012109200720033703880420072004370380042007200936029c0420072013370390042005200f41086a2802003602002007200f2902003703a00c200741e0036a2006200741d8026a20074180046a200741a00c6a20072802dc0128020010ba01200741ec036a2902002103200741e0036a41086a280200210c20072802e403210a024020072802e0034101470d002003422088a72105200741f4036a28020021102003a72102200c2109200a21060c0f0b20072802800141016a220f41004c0d0520072802e00121022007200f36028001200728028801210d201221060240024003402006280200220b41086a2105200b2f0106220e4105742106410021090240024003402006450d01200220054120109c052210450d02200641606a2106200941016a2109200541206a21052010417f4a0d000b2009417f6a210e0b200d450d02200d417f6a210d200b200e4102746a41880b6a21060c010b0b200b200941e0006c6a220641c5036a310000200641e8026a290300220420045022051ba7450d004200200641f8026a29030020051b21044200200641f0026a29030020051b21130c010b200741186a200728029001200220072802940128021c110500200741206a290300210420072903182113200728028001210f0b2007200f417f6a221036028001201320072802a801220629037854200420064180016a29030022135420042013511b0d060c070b4100210c420021030240200741e8016a280200450d0020072802e401102a0b420021040c070b200728022c210920072902e4012203422088a721052003a72102200741ec016a28020021100c0d0b1036000b200941011037000b41b8b8c000411820074180046a41e0b8c0001038000b41b8b8c000411820074180046a41e0b8c0001038000b20072802702206450d020240024020072802e0012205200641d0006a2209460d00200920054120109c05450d00034020062802082206450d022005200641d0006a2209460d01200920054120109c050d000b0b2003a7211041b9c6c000210641372109200c2105200a21020c080b20100d032007417f36028001200741003a00bc03200742003702b403200741013a009d03200741f8b9c0003602b003200741e0036a41186a200541186a290000370300200741e0036a41106a200541106a290000370300200741e0036a41086a200541086a290000370300200720052900003703e00302400240200728028401221041f8b9c000460d00200728028801210b0c010b200741a00c6a410041e0021099051a20074180046a410041a0081099051a41880b10282210450d054100210b201041003b010620104100360200201041086a200741a00c6a41e002109a051a201041e8026a20074180046a41a008109a051a200741003602880120072010360284010b02400240034020102f0106220d4105742102410021064100210502400240034020022006460d01200741e0036a201020066a41086a4120109c052209450d02200641206a2106200541016a21052009417f4a0d000b2005417f6a210d0b200b450d02200b417f6a210b2010200d4102746a41880b6a28020021100c010b0b2010200541e0006c6a22064190036a20072903a80337030020064188036a20072903a003370300200641c0036a200729039803370000200641b8036a200729039003370000200641b0036a200729038803370000200641a8036a20072903800337000020064180036a4200370300200641e8026a2205290300211320054200370300200641a0036a22052802002102200520072903b80337030020064198036a22062903002104200620072903b0033703002004a721062004422088a721050c010b200741c0036a41186a200741e0036a41186a2903002204370300200741c0036a41106a200741e0036a41106a2903002213370300200741c0036a41086a200741e0036a41086a2903002214370300200720072903e00322153703c003200741bc0c6a2014370200200741a00c6a41246a2013370200200741cc0c6a20043702002007200741e8006a41246a3602b00c2007200d3602ac0c200720123602a80c200720103602a40c200741003602a00c200720153702b40c20074180046a41186a42003703002007420037038004200741b8046a20072903b803370300200741b0046a20072903b003370300200741a8046a20072903a803370300200741a0046a20072903a003370300200741d8046a200729039803370300200741d0046a200729039003370300200741c8046a200729038803370300200741c0046a200729038003370300200741a00c6a20074180046a10b7011a420221130b024020134202510d000240024020050d00200621090c010b2005211020062109034020092802ec0321092010417f6a22100d000b0340200620062f01064102746a41ec036a28020021062005417f6a22050d000b0b2007419c046a20062f010636020020074198046a410036020020074194046a2006360200200720023602a004200741003602900420074200370388042007200936028404200741003602800420074180046a1095010b200720072802800141016a360280010b0240200741f0026a280200450d00200741ec026a280200102a0b200342ffffffff0f83210420034280808080708321030b20072802a401210520072802a001210d200728029c01210b200728028c01210e20072802880121102007280284012106024020072802742209450d00200741f8006a280200450d002009102a0b200420038421040240024020034280808080f01f8350450d002007200e3602880420072010360284042007200636028004201120074180046a10bb012007200d360284042007200b360280042007200b200541b0016c22056a220236028c0402400240200141386a28020022092001413c6a28020022066b200541b0016d2210490d00200128023421090c010b200620106a220d2006490d0720094101742206200d2006200d4b1b2206ad42b0017e2203422088a70d072003a7220d4100480d070240024020090d00200d102821090c010b2001280234200941b0016c200d102c21090b2009450d0620012009360234200141386a20063602002001413c6a28020021060b2009200641b0016c6a200b2005109a051a2001413c6a2206200628020020106a360200200720023602880420074180046a10692000410c6a2004370200200041086a200c3602002000200a3602040c010b2000200a3602042000410c6a2004370200200041086a200c36020002402005450d00200541b0016c210141002105034002400240200b20056a22092d0000220241014b0d000240024020020e020001000b0240200941086a280200450d00200941046a280200102a0b200941106a2d00004105490d02200941386a280200450d02200941346a280200102a0c020b200941286a106a0c010b200941e8006a280200450d00200941e4006a280200102a0b2001200541b0016a2205470d000b0b0240200d450d00200b102a0b0240024020100d00200621050c010b2010210920062105034020052802880b21052009417f6a22090d000b0340200620062f01064102746a41880b6a28020021062010417f6a22100d000b0b2007419c046a20062f010636020020074198046a410036020020074194046a20063602002007200e3602a004200741003602900420074200370388042007200536028404200741003602800420074180046a109b010b20004100360200200824000f0b41f0c6c00041321050000b41a8b8c000411020074180046a41d0b8c0001038000b41880b41081037000b200d41081037000b1031000b200741f0026a280200450d00200741ec026a280200102a0b2000200636020420004101360200200041146a2010360200200041086a20093602002000410c6a2005ad4220862002ad84370200024020072802742206450d00200741f8006a280200450d002006102a0b200741e8006a411c6a2802002106200728028c0121000240024020072802880122050d00200621090c010b2005211020062109034020092802880b21092010417f6a22100d000b0340200620062f01064102746a41880b6a28020021062005417f6a22050d000b0b20074180046a411c6a20062f01063602004100210520074198046a410036020020074194046a2006360200200720003602a004200741003602900420074200370388042007200936028404200741003602800420074180046a109b01024020072802a4012206450d00200728029c012110200641b0016c2100034002400240201020056a22062d0000220941014b0d000240024020090e020001000b0240200641086a280200450d00200641046a280200102a0b200641106a2d00004105490d02200641386a280200450d02200641346a280200102a0c020b200641286a106a0c010b200641e8006a280200450d00200641e4006a280200102a0b2000200541b0016a2205470d000b0b20072802a001450d00200728029c01102a200824000f0b200824000b871304057f027e0a7f077e230041f0026b22042400200441d0006a2001108c010240024020042d00502205417f6a41ff017141024f0d00200041003a0000200041086a200441d0006a41d800109a051a0c010b200441a8016a41086a2206200441d0006a413c6a290200370300200441a8016a41106a2207200441d0006a41c4006a290200370300200441a8016a41186a2208200441d0006a41cc006a2902003703002004200441d0006a41346a2902003703a801200441d0006a41106a2903002109200441d0006a41086a290300210a200441d0006a41306a280200210b200441d0006a412c6a280200210c200441d0006a41246a280200210d200441d0006a41206a280200210e200441ec006a280200210f200441d0006a41186a2802002110200441d0006a41d4006a2802002111200441d0006a41286a28020021120240024002400240024002400240024002400240024041004100109801221320026b2202200220134b1b220220126b2214201420024b1b2214450d00200441c0006a2001109101200441306a20042903402215200441c0006a41086a2903002216428080a8ec85afd1b101420010a0054200200dad2217200429033022187d221920192017564200200441306a41086a2903002017201854ad7c7d22174200522017501b22021b22184200201720021b221784500d042015428080d287e2bc2d5441002016501b0d01200441186a2014ad420020182017109f05200441086a2004290318200441186a41086a290300428080e983b1de164200109f05200441286a20014108420020152015428080aef89dc3527c2217200a200a201756200920162017201554ad7c427f7c22175620092017511b22021b22182004290308221920182019542017200920021b2218200441086a41086a29030022175420182017511b22021b221a7d221b201b20155620162018201720021b22187d2015201a54ad7d221520165620152016511b22141b4200201520141b10bc010240024020042802280d000240024020020d002003450d010b20044188026a2001201a201841081098022004280288024101460d08200420044198026a2903003703f001200420044188026a41086a2903003703e8012004200441e8016a3602880220044188026a109d010b20020d0020030d01200041003a0008200041023a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903a801370000200041c4006a200441b0016a290300370000200041cc006a200441a8016a41106a290300370000200041d4006a200441a8016a41186a290300370000200041dc006a2011360000200541037122004103460d0520000e030d05050d0b20044100360288022010200e20044188026a100d21142004280288022213417f460d07200441e8016a41186a200441a8016a41186a290300370300200441e8016a41106a200441a8016a41106a290300370300200441e8016a41086a200441a8016a41086a290300370300200420042903a8013703e801200441003602e802200442013703e00220142013200441e0026a10b2020240024020042802e402220320042802e802220d6b4120490d00200d41206a211220042802e00221020c010b200d41206a2212200d490d0a200341017422022012200220124b1b220b4100480d0a0240024020030d00200b102821020c010b20042802e0022003200b102c21020b2002450d092004200b3602e402200420023602e002200b21030b200420123602e8022002200d6a220d20042903e801370000200d41086a200441e8016a41086a290300370000200d41106a200441e8016a41106a290300370000200d41186a200441e8016a41186a29030037000020044188026a41186a220d420037030020044188026a41106a220b420037030020044188026a41086a220c420037030020044200370388022002201220044188026a1000200441c8016a41186a2212200d290300370300200441c8016a41106a220d200b290300370300200441c8016a41086a220b200c29030037030020042004290388023703c80102402003450d002002102a0b200441a1026a201229030037000020044199026a200d29030037000020044191026a200b290300370000200420042903c80137008902200441013a008802200120044188026a10b3022010200e1004200041013a0000200041086a20044188026a41d800109a051a2013450d032014102a0c030b200441b8026a200b360200200441b4026a200c360200200441b0026a2013360200200441ac026a200d360200200441a8026a200e360200200441a4026a200f36020020044188026a41186a2010360200200441bc026a20042903a801370200200441c4026a200441a8016a41086a290300370200200441cc026a200441a8016a41106a290300370200200441d4026a200441a8016a41186a29030037020020044188026a41106a200920177d200a201954ad7d370300200441003a0088022004200a20197d37039002200120044188026a10b302200041023a0000200041086a20044188026a41d800109a051a0c090b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903a801370000200041c4006a2006290300370000200041cc006a2007290300370000200041d4006a2008290300370000200041dc006a20113600000c080b20011096012010200e1004200041023a0008200041013a00000b200f450d062010102a0c060b200f450d070c060b200041003a0008200041003a0000200041186a2009370000200041106a200a370000200041386a200b360000200041346a200c360000200041306a20123600002000412c6a200d360000200041286a200e360000200041246a200f360000200041206a20103600002000413c6a20042903a801370000200041c4006a200441b0016a290300370000200041cc006a200441a8016a41106a290300370000200041d4006a200441a8016a41186a290300370000200041dc006a20113600000c040b2004200429028c023703e80141f896c10041fe00200441e8016a41f897c1001038000b41eef3c50041381050000b200b41011037000b1031000b0240200541037122004103460d0020000e03020000020b200f450d010b2010102a0b200441f0026a24000be20d03047f017e027f230041106b2202240020024100360208200242013703000240024002400240024002400240024002400240024002400240024002402001280200220341044b0d000240024002400240024020030e050001020304000b410110282203450d05200242818080801037020420022003360200200341013a0000200128020421042001410c6a2802002203200210b40102402003450d002004200341286c6a2105034020042002108f01200441206a29030021060240024020022802042207200228020822036b4108490d00200228020021070c010b200341086a22082003490d15200741017422032008200320084b1b22034100480d150240024020070d002003102821070c010b200228020020072003102c21070b2007450d092002200336020420022007360200200228020821030b2002200341086a360208200720036a20063700002005200441286a2204470d000b0b200141106a28020021070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d13200441017422032008200320084b1b22034100480d130240024020040d002003102821040c010b200228020020042003102c21040b2004450d082002200336020420022004360200200228020821030b2002200341046a360208200420036a20073600000c040b410110282203450d07200242818080801037020420022003360200200341023a0000200128020421070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d12200441017422052008200520084b1b22084100480d120240024020040d002008102821040c010b200228020020042008102c21040b2004450d0920022008360204200220043602000b2002200341046a360208200420036a200736000020012802082104200141106a2802002203200210b40102402003450d002004200341286c6a2105034020042002108f01200441206a29030021060240024020022802042207200228020822036b4108490d00200228020021070c010b200341086a22082003490d14200741017422032008200320084b1b22034100480d140240024020070d002003102821070c010b200228020020072003102c21070b2007450d0c2002200336020420022007360200200228020821030b2002200341086a360208200720036a20063700002005200441286a2204470d000b0b200141146a28020021070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d12200441017422032008200320084b1b22034100480d120240024020040d002003102821040c010b200228020020042003102c21040b2004450d0b2002200336020420022004360200200228020821030b2002200341046a360208200420036a20073600000c030b410110282203450d0a200242818080801037020420022003360200200341033a0000200141086a29030021060240024020022802042207200228020822036b4108490d00200341086a2104200228020021070c010b200341086a22042003490d11200741017422082004200820044b1b22084100480d110240024020070d002008102821070c010b200228020020072008102c21070b2007450d0c20022008360204200220073602000b20022004360208200720036a20063700000c020b410110282203450d0b200242818080801037020420022003360200200341043a0000200128020421070240024020022802042204200228020822036b4104490d00200228020021040c010b200341046a22082003490d10200441017422012008200120084b1b22084100480d100240024020040d002008102821040c010b200228020020042008102c21040b2004450d0d20022008360204200220043602000b2002200341046a360208200420036a20073600000c010b410110282203450d0c200242818080801037020420022003360200200341053a0000200128020421080240024020022802042207200228020822036b4104490d00200341046a2104200228020021070c010b200341046a22042003490d0f200741017422012004200120044b1b22014100480d0f0240024020070d002001102821070c010b200228020020072001102c21070b2007450d0e20022001360204200220073602000b20022004360208200720036a20083600000b20002002290300370200200041086a200241086a280200360200200241106a24000f0b410141011037000b200341011037000b200341011037000b410141011037000b200841011037000b200341011037000b200341011037000b410141011037000b200841011037000b410141011037000b200841011037000b410141011037000b200141011037000b1031000bfb0101077f230041106b220124002001410036020820014201370300200110c40120012802042102200128020021030240024002400240200041046a2802002204200041086a28020022056b20012802082206490d00200028020021040c010b200520066a22072005490d02200441017422052007200520074b1b22054100480d020240024020040d002005102821040c010b200028020020042005102c21040b2004450d0120002004360200200041046a2005360200200041086a28020021050b200041086a200520066a360200200420056a20032006109a051a02402002450d002003102a0b200141106a24000f0b200541011037000b1031000ba5900108027f017e0b7f037e2f7f027e057f0e7e23004190106b220224000240024002400240024002400240024002400240024002400240200141106a2802002203ad42d0007e2204422088a70d002004a72205417f4c0d00200128020821060240024002400240024002400240024020050d00410821070c010b200510282207450d010b0240024020030d00410021080c010b2006200341d0006c6a2109410021082007210a0340200241c8046a41186a220b200641186a290300370300200241c8046a41106a220c200641106a290300370300200241c8046a41086a220d200641086a290300370300200220062903003703c8042006280248220ead42307e2204422088a70d082004a7220f417f4c0d08200641386a2903002104200641286a290300211020062903302111200629032021122006280240210502400240200f0d00410821130c010b200f10282213450d040b200641d0006a210602400240200e0d00410021140c010b2005200e41306c6a2115410021142013210f0340200f2005290300370300200f200541086a290300370308200f41106a200541106a290300370300200f41186a200541186a290300370300200f41206a200541206a290300370300200f41286a200541286a290300370300200f41306a210f201441016a2114200541306a22052015470d000b0b200a2012370320200a20022903c804370300200a41386a2004370300200a41306a2011370300200a41286a2010370300200a41c8006a2014360200200a41c4006a200e360200200a41c0006a2013360200200a41186a200b290300370300200a41106a200c290300370300200a41086a200d290300370300200841016a2108200a41d0006a210a20062009470d000b0b200028020821162000280204211720002802002118200128020421192001280200210b41041028221a450d02201a200b36000020024284808080c0003702bc072002201a3602b807411b10282205450d03200541176a41002800f39646360000200541106a41002900ec9646370000200541086a41002900e49646370000200541002900dc96463700002002429b808080b00337028c08200220053602880841a2c7c00020024188086a10c601200228029008210f2002280288082105200241c8046a41186a22144200370300200241c8046a41106a22154200370300200241c8046a41086a22064200370300200242003703c8042005200f200241c8046a1000200241b00f6a41186a2014290300370300200241b00f6a41106a2015290300370300200241b00f6a41086a2006290300370300200220022903c8043703b00f0240200228028c08450d002005102a0b2002410036028808200241b00f6a412020024188086a100621142002280288082215417f460d042014450d042002201536028c082002201436028808200241d0026a20024188086a106c02400240024020022802d0020d00200228028c08220620022802d402220f490d00200f417f4c0d0902400240200f0d00410121050c010b200f102e2205450d022005200228028808220a200f109a051a20022006200f6b36028c082002200a200f6a360288080b20050d020b41c4d1c3004133200241f8056a419cd9c3001038000b200f41011037000b200fad220442208620048421042015450d052014102a0c050b200541081037000b200f41081037000b410441011037000b411b41011037000b410021050b20022005410120051b22133602b00f20022004420020051b22104220883e02b40f200241c8026a200241b00f6a106c20022802cc02210e41002106024020022802c8020d0020022802b40f220541246e220a41246c220f417f4c0d0102400240024002400240200f0d00410421060c010b200f10282206450d010b200e450d034100210c034020054104490d03200c41016a210d20022005417c6a22143602b40f200220022802b00f221541046a3602b00f2015280000210941002105200241003a00a8080340024020142005470d00200241003602b40f200541ff0171450d05200241003a00a8080c050b20024188086a20056a201520056a220f41046a2d00003a00002002200f41056a3602b00f2002200541016a220f3a00a808200f2105200f4120470d000b200241c8046a41086a221520024188086a41086a290300370300200241c8046a41106a220020024188086a41106a290300370300200241c8046a41186a221b20024188086a41186a29030037030020022002290388083703c80420022014200f6b22053602b40f0240200a200c470d00200c410174220f200d200f200d4b1b220aad42247e2204422088a70d122004a7220f4100480d1202400240200c0d00200f102821060c010b2006200c41246c200f102c21060b2006450d030b2006200c41246c6a220f2009360200200f20022903c804370204200f410c6a2015290300370200200f41146a2000290300370200200f411c6a201b290300370200200d210c200d200e470d000c040b0b200f41041037000b200f41041037000b0240200a0d00410021060c010b2006102a410021060b200241b00f6a200241b8076a10c70120022802b80f210f20022802b00f210520024100360288082005200f20024188086a1006210f024002402002280288082214417f460d00200f450d00200220143602dc062002200f3602d80620024188086a200241d8066a106d0240200228028808221c450d00200229028c0821042014450d02200f102a0c020b41c4d1c3004133200241f8056a419cd9c3001038000b420021044101211c0b024020022802b40f450d002005102a0b2004422088211102402010a7450d002013102a0b200e410020061b211d200a410020061b211e2006410420061b210c2011a7211f2004a72120200242003702dc02200241f8b9c0003602d8022007200841d0006c6a21210240024020080d00200721130c010b200241b8036a41306a212220024188086a410c6a212320164101742205201641ffffff3f712224200520244b1b222541ffffff3f71202547212620254105742127202420164721282016410574222941606a41057641016a212a20024188086a41306a212b20024188086a41206a212c20024188086a410272212d20024198056a41046a212e20024188086a41c0006a212f200241b00f6a41106a2130200241b8076a4104722131200241b8036a41c4006a21322018201820296a4621332007211302400240034020024188086a41386a22062013220541386a290300370300202b200541306a29030037030020024188086a41286a220a200541286a290300370300202c200541206a29030037030020024188086a41186a2234200541186a29030037030020024188086a41106a2235200541106a29030037030020024188086a41086a2236200541086a290300370300200241b00f6a41086a221b200541cc006a28020036020020022005290300370388082002200541c4006a2902003703b00f200541d0006a2113200541c0006a2802002205450d03200241f8026a41386a220f2006290300370300200241f8026a41306a2214202b290300370300200241f8026a41286a2215200a290300370300200241f8026a41206a220e202c290300370300200241f8026a41186a220d2034290300370300200241f8026a41106a22092035290300370300200241f8026a41086a22002036290300370300200241e8026a41086a2237201b28020036020020022002290388083703f802200220022903b00f3703e802200241b8036a41386a2238200f29030037030020222014290300370300200241b8036a41286a22392015290300370300200241b8036a41206a2215200e290300370300200241b8036a41186a223a200d290300370300200241b8036a41106a223b2009290300370300200241b8036a41086a223c2000290300370300200220022903f8023703b803200220053602f803203220022903e802370200203241086a20372802003602000240024002400240024002400240410410282214450d002014200b360000202341002900a2c740370000202341086a41002900aac74037000020024284808080c00037028c0820022014360288082002200241b8036a3602a408410810282205450d01200242083702b40f200220053602b00f2023200241b00f6a10c6014104200241b00f6a10b4010240024020022802b40f220f20022802b80f22056b4104490d0020022802b00f210f0c010b200541046a220e2005490d18200f4101742205200e2005200e4b1b22054100480d1802400240200f0d0020051028210f0c010b20022802b00f200f2005102c210f0b200f450d03200220053602b40f2002200f3602b00f20022802b80f21050b2002200541046a3602b80f200f20056a2014280000360000200241b8036a200241b00f6a108f01200220153602b807200241b8076a200241b00f6a10a301200220223602b807200241b8076a200241b00f6a10a30120022802f8032105200228028004220f200241b00f6a10b4010240200f450d00200f41306c210f0340200541106a200241b00f6a108f01200220053602b807200541306a2105200241b8076a200241b00f6a10a301200f41506a220f0d000b0b20022802b40f210f20022802b80f211520022802b00f2105200241c8046a41186a220d4200370300200241c8046a41106a22094200370300200241c8046a41086a22004200370300200242003703c80420052015200241c8046a100020024188046a41186a223d200d29030037030020024188046a41106a223e200929030037030020024188046a41086a223f2000290300370300200220022903c804370388040240200f450d002005102a0b2014102a411010282205450d032005410029008ab7402204370000200541086a4100290092b740221037000020024290808080800237028c082002200536028808200220024188086a3602b80720024188046a200241b8076a10c8012002280288082105200228029008210f200d42003703002009420037030020004200370300200242003703c8042005200f200241c8046a1000200241b00f6a41186a2240200d29030037030020302009290300370300201b2000290300370300200220022903c8043703b00f0240200228028c08450d00200228028808102a0b200241b00f6a41204101410041001003417f460d050c040b410441011037000b410841011037000b200541011037000b411041011037000b20022802fc03450d0120022802f803102a0c010b200241a8046a41186a2241203a290300370300200241a8046a41106a223a203b290300370300200241a8046a41086a223b203c290300370300200220022903b8033703a804200228028004220ead42307e2211422088a70d052011a7220f417f4c0d05203829030021112039290300211220022903e803214220022903d803214320022802f8032105024002400240024002400240024002400240024002400240200f0d00410821370c010b200f10282237450d010b02400240200e0d00410021140c010b2005200e41306c6a2115410021142037210f0340200f2005290300370300200f200541086a290300370308200f41106a200541106a290300370300200f41186a200541186a290300370300200f41206a200541206a290300370300200f41286a200541286a290300370300200f41306a210f201441016a2114200541306a22052015470d000b0b200241b00f6a41386a2011370300200241b00f6a41286a2012370300204020412903003703002030203a290300370300201b203b290300370300200220423703e00f200220433703d00f200220022903a8043703b00f200220143602f80f2002200e3602f40f200220373602f00f0240024020022802d802220541f8b9c000460d0020022802dc02210f0c010b20024188086a410041f0061099051a41f80610282205450d024100210f200541003b010620054100360200200541086a20024188086a41f006109a051a200241003602dc02200220053602d8020b2002200536028c082002200f360288082002200241d8026a36029008200241b8076a20024188086a200241b00f6a10c901024020022802b8074101470d00202f20312902003702002036203041086a2903003703002035203041106a2903003703002034203041186a290300370300202c203041206a290300370300200a203041286a290300370300202b203041306a2903003703002006203041386a290300370300202f41086a203141086a290200370200200220302903003703880820022802bc0f2115202e41086a220f201b280200360200202e20022903b00f370200200241c8046a20024188086a41d000109a051a200241a8056a200241c8046a41d000109a051a200220022802e00241016a3602e00220022802f005214120022802f405211420022802ec052105200241d8066a41086a22442000290300370300200241d8066a41106a220e2009290300370300200241d8066a41186a2237200d290300370300200241d8066a41206a2239200241c8046a41206a290300370300200241d8066a41286a223a200241c8046a41286a290300370300200241d8066a41306a223b200241c8046a41306a290300370300200241d8066a41386a223c200241c8046a41386a290300370300200241c8066a41086a2245200f280200360200200220022903c8043703d8062002202e2902003703c80620052f01062238410b490d0520024188086a410041f0061099051a41f80610282238450d03203841003b010620384100360200203841086a20024188086a41f006109a05210f20024188086a4108200541086a2246200541f8b9c0004622471b224841e0036a41d000109a051a200f204841b0046a20052f010641796a224841d0006c109a05210f200541063b0106203820483b0106200241b00f6a20024188086a41d000109a051a0240024020144107490d00201441d0006c4108200f203841f8b9c0004622061b6a220f41a07c6a200f41d07b6a220f4100204841ffff037120061b20146b41d0006c41b0046a109b051a200f201536020c200f41086a2045280200360200200f20022903c806370300200f20022903d806370310200f41186a2044290300370300200f41206a200e290300370300200f41286a2037290300370300200f41306a2039290300370300200f41386a203a290300370300200f41c0006a203b290300370300200f41c8006a203c290300370300203820382f010641016a3b01060c010b4108210f200241a8076a41086a200241c8066a41086a28020036020020024188086a41086a200241d8066a41086a2903003703002035200e29030037030020342037290300370300202c2039290300370300200a203a290300370300202b203b2903003703002006203c290300370300200220022903c8063703a807200220022903d80637038808024002402047450d004100210e0c010b20052f0106210e2046210f0b200f201441d0006c6a220f41d0006a200f200e20146b41d0006c109b051a200f201536020c200f41086a200241a8076a41086a280200360200200f20022903a807370300200f200229038808370310200f41186a2036290300370300200f41206a2035290300370300200f41286a2034290300370300200f41306a202c290300370300200f41386a200a290300370300200f41c0006a202b290300370300200f41c8006a2006290300370300200520052f010641016a3b01060b200241b8076a200241b00f6a41d000109a051a200241f8056a200241b8076a41d000109a051a2005280200220e450d0620052f010421370340200241d8066a200241f8056a41d000109a051a203741ffff0371210602400240024002400240200e2f01062205410b490d00202d410041a2071099051a41a80710282215450d0a20154100360200201541046a20024188086a41a407109a051a20024188086a4108200e41086a223b200e41f8b9c00046223c1b220541e0036a41d000109a051a201541086a223a200541b0046a200e2f0106220541796a220f41d0006c109a051a201541f8066a200e4194076a2005417a6a220a410274109a052139200e41063b01062015200f3b01060240200a450d00410021052039210f0340200f280200221420053b010420142015360200200f41046a210f200a200541016a2205470d000b0b200241b00f6a20024188086a41d000109a051a200241b8076a200241b00f6a41d000109a051a203741ffff037122054107490d0320024188086a200241d8066a41d000109a051a200641796a210541f8b9c0002114201541f8b9c000470d014108213a4100210a0c020b4108200e41086a200e41f8b9c0004622141b200641d0006c6a220f41d0006a200f4100200520141b20066b41d0006c109b051a200f200241d8066a41d000109a051a200e200e2f010641016a220f3b01062006410274200e41f8066a22146a41086a2014200641016a22054102746a2214200f41ffff0371220f20056b410274109b051a201420383602002006200f4f0d0c203820053b01042038200e3602002005200f4f0d0c200f417f6a2115200e2005417f6a22054102746a4180076a210f0340200f2802002214200541026a3b01042014200e360200200f41046a210f2015200541016a2205470d000c0d0b0b20152f0106210a201521140b203a2006417a6a220f41d0006c6a203a200541d0006c6a2237200a20056b41d0006c109b051a203720024188086a41d000109a051a201520152f010641016a220a3b01062006410274223720396a416c6a2039200f4102746a2206200a41ffff0371200f6b410274109b051a20062038360200200f20142f010622064b0d01201520376a41e0066a210f0340200f2802002214200541016a22053b010420142015360200200f41046a210f20052006490d000c020b0b200e41f8066a210f20024188086a200241d8066a41d000109a051a02400240203c450d004108213b4100210a0c010b200e2f0106210a0b203b200641d0006c6a221441d0006a2014200a20066b41d0006c109b051a201420024188086a41d000109a051a200e200e2f010641016a22143b010620064102742237200f6a41086a200f200641016a220a4102746a220f201441ffff0371200a6b410274109b051a200f20383602002005200e2f010622144f0d00200e20376a41fc066a210503402005280200220f200641016a22063b0104200f200e360200200541046a210520142006470d000b0b200241f8056a200241b8076a41d000109a051a0240200e28020022050d00201521380c080b200e2f010421372005210e201521380c000b0b20024198056a41086a203141086a2902003703002002203129020037039805200e450d062037102a0c060b200f41081037000b41f80641081037000b41f80641081037000b41a80741081037000b4108200541086a200541f8b9c0004622061b201441d0006c6a220f41d0006a200f4100203820061b20146b41d0006c109b051a200f201536020c200f41086a2045280200360200200f20022903c806370300200f20022903d806370310200f41186a2044290300370300200f41206a200e290300370300200f41286a2037290300370300200f41306a2039290300370300200f41386a203a290300370300200f41c0006a203b290300370300200f41c8006a203c290300370300200520052f010641016a3b01060c010b202d410041a2071099051a41a80710282205450d0120054100360200200541046a20024188086a41a407109a051a20052041280200220f3602f806204120053602002041204128020441016a360204200f41003b0104200f20053602004108200541086a200541f8b9c000461b20052f0106220f41d0006c6a200241f8056a41d000109a051a200541f8066a200f41016a220f4102746a2038360200200520052f010641016a3b01062038200f3b0104203820053602000b200241b00f6a200241b8036a41d000109a051a20280d082029417f4c0d080240024020290d00410121150c010b202910282215450d020b024020162024490d00201621060c030b20262027410048720d140240024020160d002027102821150c010b201520292027102c21150b2025210620150d02202741011037000b41a80741081037000b202941011037000b024002402033450d00410021050c010b20292114201521052018210f03402005200f290000370000200541186a200f41186a290000370000200541106a200f41106a290000370000200541086a200f41086a290000370000200541206a2105200f41206a210f201441606a22140d000b202a21050b20024188086a200241b00f6a41d000109a051a200220053602e008200220063602dc08200220153602d808024002400240411010282205450d0020052004370000200541086a20103700002002429080808080023702bc07200220053602b8072002200241b8076a3602d80620024188046a200241d8066a10c80120022802b807210520022802c007210f200d42003703002009420037030020004200370300200242003703c8042005200f200241c8046a10002040200d29030037030020302009290300370300201b2000290300370300200220022903c8043703b00f024020022802bc07450d0020022802b807102a0b200241003602c007200242013703b80720024188086a200241b8076a108f012002202c3602d806200241d8066a200241b8076a10a3012002202b3602d806200241d8066a200241b8076a10a30120022802c808210520022802d008220f200241b8076a10b4010240200f450d00200f41306c210f0340200541106a200241b8076a108f01200220053602d806200541306a2105200241d8066a200241b8076a10a301200f41506a220f0d000b0b20022802d808210520022802e008220f200241b8076a10b4010240200f450d00200f410574210f03402005200241b8076a108f01200541206a2105200f41606a220f0d000b0b20022802bc072105200241b00f6a412020022802b807220f20022802c007100702402005450d00200f102a0b024020022802cc08450d0020022802c808102a0b024020022802dc08450d0020022802d808102a0b200241b8076a41186a2206203d290300370300200241b8076a41106a220a203e290300370300200241b8076a41086a220e203f29030037030020022002290388043703b807410021050240201d41014b0d000240201d0e020003000b203420062903003703002035200a2903003703002036200e290300370300200220022903b80737038808410021050c030b201d210f03402005200f410176221420056a2215200c201541246c6a280200200b4b1b2105200f20146b220f41014b0d000c020b0b411041011037000b0240200c200541246c6a280200220f200b460d002005200f200b496a21050b203420062903003703002035200a2903003703002036200e290300370300200220022903b80737038808201d20054f0d0041f8b0c0001032000b0240201d201e470d00201d41016a220f201d490d12201d4101742214200f2014200f4b1b221ead42247e2204422088a70d122004a7220f4100480d1202400240201d0d00200f1028210c0c010b200c201d41246c200f102c210c0b200c450d030b200c200541246c6a220f41246a200f201d20056b41246c109b051a200f200b360200200f411c6a2034290300370200200f41146a2035290300370200200f410c6a2036290300370200200f200229038808370204204020062903003703002030200a290300370300201b200e290300370300200220022903b8073703b00f0240201f2020470d00201f41016a2205201f490d12201f410174220f2005200f20054b1b222041ffffff3f712020470d12202041057422054100480d1202400240201f0d0020051028211c0c010b201c201f4105742005102c211c0b201c450d040b201d41016a211d201c201f4105746a220520022903b00f370000200541186a2040290300370000200541106a2030290300370000200541086a201b290300370000201f41016a211f0b20132021470d000b202121130c020b200f41041037000b200541011037000b024020132021460d002007200841d0006c6a21140340201341c0006a280200220f450d01201341d0006a21050240201341c4006a280200450d00200f102a0b2005211320142005470d000b0b02402003450d002007102a0b0240024002400240024002400240024002400240024020022802e0020d0020022802d80220022802dc02410010ca01201a102a02402020450d00201c102a0b0240201e450d00200c102a0b2017450d012018102a0c010b2002201c3602d8062002201c201f4105746a3602dc06200241b00f6a200241d8066a10850102400240200241f00f6a2802000d004108210841002109410021230c010b20024188086a200241b00f6a41e000109a051a41e00010282208450d03200820024188086a41e000109a051a200220022903d8063703b807200241b00f6a200241b8076a1085010240200241f00f6a2802000d0041012109410121230c010b4102210f41e00021054101210941012123034020024188086a200241b00f6a41e000109a051a024020092023470d00200941016a22142009490d19200f2014200f20144b1b2223ad42e0007e2204422088a70d192004a722144100480d190240024020090d002014102821080c010b200820052014102c21080b2008450d060b200820056a20024188086a41e000109a051a200f41026a210f200541e0006a2105200941016a2109200241b00f6a200241b8076a10850120022802f00f0d000b0b200241a8086a201d360200200241a4086a201e36020020024198086a201fad4220862020ad843703002002201c3602940820024284808080c00037028c082002201a360288082002200c3602a008200241003602b80f200242013703b00f201d200241b00f6a10b4010240201d450d00200c201d41246c6a210a200c210f0340200f28020021150240024020022802b40f221420022802b80f22056b4104490d0020022802b00f21140c010b200541046a22062005490d19201441017422052006200520064b1b22054100480d190240024020140d002005102821140c010b20022802b00f20142005102c21140b2014450d07200220053602b40f200220143602b00f20022802b80f21050b2002200541046a3602b80f201420056a20153600002002200241b00f6a3602b807200f41046a200241b8076a10c801200f41246a220f200a470d000b0b20022802b80f211420022802b40f211520022802b00f210f411b10282205450d05200541176a41002800f39646360000200541106a41002900ec9646370000200541086a41002900e49646370000200541002900dc96463700002002429b808080b0033702bc07200220053602b80741a2c7c000200241b8076a10c60120022802c007210620022802b8072105200241c8046a41186a220a4200370300200241c8046a41106a220e4200370300200241c8046a41086a22134200370300200242003703c80420052006200241c8046a1000200241b00f6a41186a200a290300370300200241b00f6a41106a200e290300370300200241b00f6a41086a2013290300370300200220022903c8043703b00f024020022802bc07450d002005102a0b200241203602bc072002200241b00f6a3602b807200f2014200241b8076a10cb0102402015450d00200f102a0b200241b8076a20024188086a10c70120022802c007211520022802b8072114200241003602b80f200242013703b00f201f200241b00f6a10b4010240201f450d00201f410574210f201c210503402002200241b00f6a3602d8062005200241d8066a10c801200541206a2105200f41606a220f0d000b0b20022802b40f21052014201520022802b00f220f20022802b80f100702402005450d00200f102a0b024020022802bc07450d002014102a0b201a102a02402020450d00201c102a0b0240201e450d00200c102a0b20022802d802210520022902dc02210402402017450d002018102a0b20050d010b20012802082114024020012802102205450d00200541d0006c210f201441c0006a210503400240200541046a280200450d002005280200102a0b200541d0006a2105200f41b07f6a220f0d000b0b2001410c6a280200450d142014102a0c140b200220043702bc03200220053602b803410410282205450d042005200b36000020024190086a4284808080c00037030020024198086a41002900a2c740370300200241a0086a41002900aac7403703002002200536028c082002410f3a0088084101410020024188086a10cc012019418094ebdc036e22054101200541014b1b220520194b0d052019200941036c417d6a220f200f20194b1b20056ead428094ebdc037e201920056ead221080a741146e2215211420092004422088a76b220f0d060c070b41e00041081037000b201441081037000b200541011037000b411b41011037000b410441011037000b41acaac3001032000b2002418094ebdc0336028c082002418094ebdc03201941002009200f6b2214201420094b1b41036c417d6a2214201420194b1b20056ead428094ebdc037e201080a741146e22056bad4100201520056b2205200520154b1bad7e428094ebdc0380a722053602880820024188086a2005418094ebdc034b4102746a28020021140b200941e0006c220541e0006e2129410021130240024020050d0041042138410021290c010b2029410274220610282238450d020b0240200820056a2008460d000240200f0d00200941e0006c210f4100211320382105034020052014360200201341016a2113200541046a2105200f41a07f6a220f0d000c020b0b2008200941e0006c6a2106200941057441606a210a203821052008210f0340200220022802b8033602b40f200220022802bc033602b00f2002200241b8036a3602b80f20024188086a200241b00f6a200f10c9012005201420152002280288084101461b360200200541046a21052006200f41e0006a220f470d000b200a41057641016a21130b20024188086a41086a220542003703002002420037038808419e9dc600411b20024188086a1008200241b00f6a41086a200529030037030020022002290388083703b00f4100211b2002410036028808200241b00f6a411020024188086a100621050240200228028808220f417f460d002005450d00200f4104490d032005280000211b2005102a0b20024188086a41086a22054200370300200242003703880841bb9cc600411220024188086a1008200241b00f6a41086a200529030037030020022002290388083703b00f4100213b2002410036028808200241b00f6a411020024188086a100621050240200228028808220f417f460d002005450d00200f4104490d042005280000213b2005102a0b411710282205450d042005410f6a41002900d3fe44370000200541086a41002900ccfe44370000200541002900c4fe4437000020054117412e102c2205450d052005203b36001742002149200241f8056a41186a220f4200370300200241f8056a41106a22144200370300200241f8056a41086a22154200370300200242003703f8052005411b200241f8056a1000200241a8056a41186a200f290300370300200241a8056a41106a2014290300370300200241a8056a41086a2015290300370300200220022903f8053703a8052005102a2002410036028808200241a8056a412020024188086a100621002002280288082230417f460d092000450d09200220303602fc02200220003602f802200241c0026a200241f8026a106c20022802c0020d0820022802fc0222154140712205417f4c0d0020022802c402210d024002402015410676220e0d004108211d0c010b20051028221d450d070b0240200d450d004100210a0340200241003a00a808200a220641016a210a41002105024002400240034020152005460d0120024188086a20056a20022802f80222142d00003a00002002201441016a3602f8022002200541016a220f3a00a808200f2105200f4120470d000b200241f8056a41186a220520024188086a41186a290300370300200241f8056a41106a220b20024188086a41106a290300370300200241f8056a41086a220c20024188086a41086a29030037030020022002290388083703f8052015200f6b220f4110490d012002201441116a3602f802200f41706a410f4b0d02200f41706a210f0c010b0240200541ff0171450d00200241003a00a8080b4100210f0b200241b8076a41086a200241b00f6a41086a290300370300200220022903b00f3703b8072002200f3602fc02200e450d0b201d102a0c0b0b201441096a290000210420142900012110200241b8076a41086a2215200c290300370300200241b8076a41106a220c200b290300370300200241b8076a41186a220b20052903003703002002201441216a3602f802200220022903f80522113703b00f200220113703b807201441196a290000211120142900112112200241d8066a41186a2214200b290300370300200241d8066a41106a220b200c290300370300200241d8066a41086a220c2015290300370300200220022903b8073703d8060240200e2006470d0020064101742205200a2005200a4b1b220e41ffffff1f71200e470d0f200e41067422054100480d0f0240024020060d0020051028211d0c010b201d20064106742005102c211d0b201d450d0a0b200f41606a2115201d20064106746a220520123703102005200437030820052010370300200541186a2011370300200520022903d806370320200541286a200c290300370300200541306a200b290300370300200541386a2014290300370300200a200d470d000b2002200f41606a3602fc020b201d450d08200dad422086200ead84214902402030450d002000102a0b2049422088a7210f2049a7210e0c0a0b1036000b200641041037000b41c4d1c3004133200241f8056a419cd9c3001038000b41c4d1c3004133200241f8056a419cd9c3001038000b411741011037000b412e41011037000b200541081037000b200541081037000b41c4d1c3004133200241f8056a419cd9c3001038000b4108211d4100210f4100210e0b0240024020132009200920134b1b221f0d004200214a4200214b0c010b200241b00f6a4105722122200241b8076a41036a213920024188086a410572213220024188086a41086a2113201bad214c20024191086a2135200241e8016a41186a213a2008210b4200214a4200214b41002130034020134200370300200242003703880841c8ffc400411520024188086a1008200241b00f6a41086a2236201329030037030020022002290388083703b00f2002410036028808200241b00f6a411020024188086a100621140240024002400240024002400240024002400240024002400240024002400240024002400240200228028808220f417f460d002002200f3602bc07200220143602b80720024188086a200241b8076a106d2002280288082205450d02200229028c082104200f450d012014102a0c010b42002104410121050b20052004422088a72008203041e0006c6a220f10cd01211402402004a7450d002005102a0b20140d10200241b0026a200f41206a22342903002204203441086a222c290300428094ebdc03420010a005200241a0026a20022903b0022210200241b0026a41086a29030022114280ec94a37c427f109f0520024190026a20102011203820304102746a35020022124200109f0520022903900222102012200420022903a0027c7e428094ebdc038042ffffffff0f837c220420024190026a41086a2903002004201054ad7c2210844200510d1020134200370300200242003703880841c785c200411220024188086a100820024198056a41086a220c2013290300370300200220022903880837039805200241003602880820024198056a411020024188086a10062105024002402002280288082214417f460d002005450d00200220143602b40f200220053602b00f20024188086a200241b00f6a106d2002280288082237450d03200229028c0821122014450d012005102a0c010b41012137420021120b20372012422088a74105746a21064100211420372105024003400240200620056b41e0004b0d004102212b20052006460d080340200b2005460d0320142005200f4120109c0522154100476a21142015450d032006200541206a2205470d000c090b0b2005200f460d0120142005200f4120109c0522154100476a21142015450d01200541206a2215200f460d0120142015200f4120109c0522154100476a21142015450d01200541c0006a2215200f460d0120142015200f4120109c0522154100476a21142015450d01200541e0006a2215200f460d0120142015200f4120109c0522154100476a211420054180016a210520150d000b0b20134200370300200242003703880841bd99c600411a20024188086a1008200c2013290300370300200220022903880837039805200241003602880820024198056a411020024188086a100621052002280288082206417f460d032005450d03200220063602b40f200220053602b00f20024188086a200241b00f6a1082012002280288082215450d02200229028c0821112006450d042005102a0c040b41c4d1c3004133200241f8056a419cd9c3001038000b41c4d1c3004133200241f8056a419cd9c3001038000b41c4d1c3004133200241f8056a419cd9c3001038000b410021150b2015410420151b21004100210502400240024002402011420020151b22114220882242a7220e41014b0d00200e0e020201020b200e2115034020052015410176220620056a220a20142000200a4102746a280200491b2105201520066b221541014b0d000b0b4100212b02402014200020054102746a2802002215470d00410021400c020b2005201420154b6a21050b20134200370300200242003703880841c785c200411220024188086a1008200c2013290300370300200220022903880837039805200241003602880820024198056a411020024188086a1006210602400240200228028808220a417f470d00410021150c010b024020060d00410021150c010b2002200a36028c08200220063602880820024188026a20024188086a106c024002402002280288020d00200228028c0221150c010b410021150b200a450d002006102a0b20152015418094ebdc036e22064180ec94a37c6c6aad4280fd87d1007e428094ebdc038021432005200e4b0d020240200e2011a7470d00200e41016a2215200e490d11200e410174220a20152015200a491b221541ffffffff03712015470d112015410274220a4100480d1102400240200e0d00200a102821000c010b2000200e410274200a102c21000b2000450d042015ad21110b200020054102746a221541046a2015200e20056b410274109b051a2015201436020041012140201142ffffffff0f83200e41016a2205ad2242422086842111200520064180fd87d1006c2043a76a4b212b0b20134200370300200242003703880841bd99c600411a20024188086a1008200c20132903003703002002200229038808370398050240024020000d0020024198056a411010090c010b200241003602900820024201370388082042a7221520024188086a10b4010240024020150d00200228029008210c200228028c08210e20022802880821150c010b410020022802900822056b2106200020154102746a211b200228028c08210e2000210a0340200a280200210d02400240200e20066a4104490d0020022802880821150c010b200541046a22152005490d13200e410174220c2015200c20154b1b220c4100480d1302400240200e0d00200c102821150c010b200228028808200e200c102c21150b2015450d072002200c36028c082002201536028808200c210e0b2002200541046a220c36029008201520056a200d3600002006417c6a2106200c2105201b200a41046a220a470d000b0b2011a7210520024198056a41102015200c10070240200e450d002015102a0b2005450d002000102a0b2040450d00200241023602b00f20022014ad3703b80f20024188086a200241b00f6a10c301203941086a221520132802003600002039200229038808370000203220022900b807370000203241076a200241b8076a41076a2206290000370000200241c6a4b9da0436008908200241023a00880820024188086a10ce012002201436028c082002410136028808200241003602b80f200242013703b00f410110282205450d04200220053602b00f200520022802b80f22146a41023a0000200241013602b40f2002201441016a22053602b80f200228028c08210a02400240410020146b4104490d0020022802b00f21140c010b200541046a22142005490d10410141017422052014200520144b1b22054100480d100240024041010d002005102821140c010b20022802b00f41012005102c21140b2014450d06200220053602b40f200220143602b00f20022802b80f21050b2002200541046a3602b80f201420056a200a360000200241d8066a41086a20022802b80f2205360200200220022903b00f22113703d8062015200536000020392011370000202220022900b807370000202241076a2006290000370000200241c28289aa043600b10f200241023a00b00f200241b00f6a10ce012002280288080d00200228029008450d00200228028c08102a0b02402012a7450d002037102a0b0240202b4102460d00202b410171450d00201342003703002002420037038808418e9dc600411020024188086a10082036201329030037030020022002290388083703b00f410110282205450d06200541013a0000200241b00f6a41102005410110072005102a0b202c2903002212201020342903002243200454201220105420122010511b22051b214d2043200420051b214e024002402049422088224fa722060d0042002110420021040c010b20064106742114201d41206a21054200211042002104034002400240200b2005460d002005200f4120109c050d010b427f2004200541706a221541086a2903007c201020152903007c22112010542215ad7c22102015201020045420102004511b22151b2104427f201120151b21100b200541c0006a2105201441406a22140d000b0b200241e8016a200f204e4200200f290330221120107d22422042201156200f41386a290300224220047d2011201054ad7d220420425620042042511b22051b22102010204e564200200420051b2204204d562004204d511b22051b2210204d200420051b220410cf01200241e8016a41086a290300215020022903e80121510240204e201020022903f80122527d22537d2254204d2004203a2903007d2010205254ad7d22557d204e205354ad7d225284500d00204320117d2210201220427d2043201154ad7d220484500d00200f2802482214450d00200f2802402205201441306c6a2115200241c8016a20542052428094ebdc03420010a005200241d8016a20102004428094ebdc03420010a005200241b8016a20022903c8012252200241c8016a41086a29030022564280ec94a37c427f109f05200241d8016a41086a2903002211420020022903d801224242015620114200522011501b22141b21122042420120141b2142205420022903b8017c21540340200241a8016a2010200529030022112011201056200541086a290300221120045620112004511b22141b2004201120141b2042201210a00520022903a8012243428080808010544100200241a8016a41086a290300501b450d0820024198016a201020042042201210a005200229039801221142808080801054410020024198016a41086a290300501b450d092011a7450d0a200241e8006a20522056204342ffffffff0f83428094ebdc037e201142ffffffff0f838042ffffffff0f8322114200109f05200241f8006a200541106a20022903682243201120547e428094ebdc038042ffffffff0f837c2211200241e8006a41086a2903002011204354ad7c10cf01427f2050200241f8006a41086a2903007c205120022903787c22432051542214ad7c22112014201120505420112050511b22141b2150427f204320141b2151200541306a22052015470d000b0b200241a8056a41186a2215200f41186a220a290300370300200241a8056a41106a220e200f41106a220c290300370300200241a8056a41086a220d200f41086a22002903003703002002200f2903003703a8050240024020062049a7460d00200621140c010b200641016a22052006490d0f204fa72214410174221b20052005201b491b220541ffffff1f712005470d0f2005410674221b4100480d0f0240024020060d00201b1028211d0c010b201d2014410674201b102c211d0b201d450d0a2005ad21490b200241d8006a20512050428094ebdc03420010a005200241c8006a20022903582204200241d8006a41086a29030022104280ec94a37c427f109f05200241386a20042010204c4200109f05201d20144106746a220520533703102005204d3703082005204e370300200541186a2055370300200520022903a805370320200541286a200d290300370300200541306a200e290300370300200541386a2015290300370300200241013a009008200241033a008808200a2900002104200c290000211020002900002111200f290000211220024188086a41386a204d37030020352012370000203541086a2011370000203541106a2010370000203541186a20043700002002204e3703b8084101410020024188086a10cc01204942ffffffff0f83201441016aad4220868421490240024020022903382210205120022903487c204c7e428094ebdc038042ffffffff0f837c2204200241386a41086a2903002004201054ad7c221084500d00200f41d8006a28020022050d010b427f204b20507c204a20517c2210204a542205ad7c220420052004204b542004204b511b22051b214b427f201020051b214a0c0b0b200241286a200420512051200456205020105620502010511b22141b22542010205020141b224d2005ad420010a00520054105742114200f2802502105200241286a41086a29030021522002290328215620542112204d21420340200241186a2005205620122012205656204220525620422052511b220f1b220420522042200f1b221010d00120024188086a41106a2010200241186a41086a29030022437d20042002290318221154ad7d204320107d2011200454ad7d201120045820432010582043201051220f1b22151b3703002002200420117d201120047d20151b37039008200220112004562043201056200f1b220fad37038808204220107d21102012200454ad211102400240200f0d00200220133602b00f200241b00f6a109d010c010b200220133602b00f200241b00f6a109c010b201020117d2142201220047d2112200541206a2105201441606a22140d000b427f427f204b20427c204a20127c2210204a542205ad7c220420052004204b542004204b511b22051b22042050204d7d2051205454ad7d7c427f201020051b2210205120547d7c22112010542205ad7c22102005201020045420102004511b22051b214b427f201120051b214a0c0a0b41f8b0c0001032000b200a41041037000b200c41011037000b410141011037000b200541011037000b410141011037000b10d101000b10d201000b41acaac3001032000b201b41081037000b200b41e0006a210b203041016a2230201f490d000b2049422088a7210f2049a7210e0b024002400240024002400240411710282205450d002005410f6a41002900d3fe44370000200541086a41002900ccfe44370000200541002900c4fe4437000020054117412e102c2205450d012005203b360017200241f8056a41186a22144200370300200241f8056a41106a22154200370300200241f8056a41086a22064200370300200242003703f8052005411b200241f8056a1000200241a8056a41186a2014290300370300200241a8056a41106a2015290300370300200241a8056a41086a2006290300370300200220022903f8053703a8052005102a20024100360290082002420137038808200f20024188086a10b401200f450d02200f410674210a201d21050340200541206a20024188086a108f01200541086a29030021042005290300211002400240200228028c08221420022802900822156b4110490d00200228028808210f0c010b201541106a220f2015490d0920144101742215200f2015200f4b1b22064100480d090240024020140d0020061028210f0c010b20022802880820142006102c210f0b200f450d052002200636028c082002200f360288082002280290082115200621140b200f20156a22062004370008200620103700002002201541106a221536029008200541186a2903002104200541106a290300211002400240201420156b410f4d0d00201421060c010b201541106a22062015490d09201441017422152006201520064b1b22064100480d090240024020140d0020061028210f0c010b200f20142006102c210f0b200f450d062002200636028c082002200f3602880820022802900821150b200541c0006a2105200f20156a22142004370008201420103700002002201541106a221436029008200a41406a220a0d000c060b0b411741011037000b412e41011037000b2002280290082114200228028c082106200228028808210f0c020b200641011037000b200641011037000b200241a8056a4120200f2014100702402006450d00200f102a0b0240200e450d00201d102a0b20024188086a10d301200241086a20024188086a204a204b10d001200241c00f6a204b200241086a41086a29030022107d204a2002290308220454ad7d2010204b7d2004204a54ad7d2004204a582010204b582010204b5122051b220f1b3703002002204a20047d2004204a7d200f1b3703b80f20022004204a562010204b5620051b2205ad3703b00f200241b00f6a41086a210f0240024020050d002002200f3602b807200241b8076a109d010c010b2002200f3602b807200241b8076a109c010b02402029450d002038102a0b02402009450d00200941e0006c210f200841d4006a210503400240200541706a280200450d002005416c6a280200102a0b02402005280200450d002005417c6a280200102a0b200541e0006a2105200f41a07f6a220f0d000b0b02402023450d002008102a0b20022802b80320022802bc0320022802c00310ca0120012802082114024020012802102205450d00200541d0006c210f201441c0006a210503400240200541046a280200450d002005280200102a0b200541d0006a2105200f41b07f6a220f0d000b0b2001410c6a280200450d002014102a0b20024190106a24000f0b1031000b8c1501037f0240024002400240024002400240024002400240024002400240024002400240024002400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00003a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00013a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00023a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00033a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00043a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00053a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00063a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0820012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00073a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0920012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00083a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0a20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d00093a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0b20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000a3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0c20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000b3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0d20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000c3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0e20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000d3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d0f20012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a20002d000e3a000002400240200141046a28020020042802002202460d00200128020021030c010b200241016a22032002490d11200241017422042003200420034b1b22044100480d110240024020020d002004102821030c010b200128020020022004102c21030b2003450d1020012003360200200141046a2004360200200141086a28020021020b200141086a200241016a360200200320026a20002d000f3a00000f0b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b1031000bba0601087f230041d0006b220224000240024002400240024002400240411f10282203450d00200341176a41002900c9c740370000200341106a41002900c2c740370000200341086a41002900bac740370000200341002900b2c7403700002002429f808080f0033702242002200336022041a2c7c000200241206a10c6012002280228210420022802202103200241306a41186a22054200370300200241306a41106a22064200370300200241306a41086a220742003703002002420037033020032004200241306a1000200241186a2005290300370300200241106a2006290300370300200241086a20072903003703002002200229033037030002402002280224450d002003102a0b412010282203450d0120032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a2903003700002001280208220441046a2205417f4c0d02200128020021070240024020050d00410121010c010b200510282201450d040b2002410036023820022005360234200220013602302004200241306a10b4010240024020022802342206200228023822016b2004490d00200228023021050c010b200120046a22052001490d06200641017422082005200820054b1b22084100480d060240024020060d002008102821050c010b200228023020062008102c21050b2005450d052002200836023420022005360230200821060b200520016a20072004109a051a200241306a41186a22074200370300200241306a41106a22084200370300200241306a41086a22094200370300200242003703302005200120046a200241306a1000200241186a2007290300370300200241106a2008290300370300200241086a20092903003703002002200229033037030002402006450d002005102a0b2003412041c000102c2203450d0620032002290300370020200341386a200241186a290300370000200341306a200241106a290300370000200341286a200241086a290300370000200042c0808080800837020420002003360200200241d0006a24000f0b411f41011037000b412041011037000b1036000b200541011037000b200841011037000b1031000b41c00041011037000bba0501037f02400240024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f024002402001280200220041046a2802002203200041086a28020022016b4120490d00200028020021030c010b200141206a22042001490d08200341017422012004200120044b1b22014100480d080240024020030d002001102821030c010b200028020020032001102c21030b2003450d0720002003360200200041046a2001360200200041086a28020021010b200041086a200141206a360200200320016a220041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a290000370000200020022900003700002002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b200141011037000b1031000b9705060a7f047e037f027e047f027e200128020821032001280204210420012802002105200241386a2106200241286a2107034002400240200441f8b9c000462208450d00410021094108210a4108210b0c010b20042f01062109200441086a220a210b0b200b200941d0006c6a210c2006290300210d2007290300210e2002290330210f2002290320211020022802482111200228024021124100210b0240024002400340200b21090240200a200c470d0002402008450d00410021090c030b20042f010621090c020b024002402002200a4120109c05220b450d00417f4101200b4100481b21130c010b417f2010200a290320221485200e200a41286a290300221585844200522010201454200e201554200e2015511b1b22130d00417f200f200a41306a290300221485200d200a41386a29030022158584420052200f201454200d201554200d2015511b1b22130d00200a41c8006a28020022162011201120164b1b2117200a280240210b417f21182012211903400240201841016a22182017490d00417f201120164720112016491b21130c020b0240201941106a200b41106a4120109c052213450d00417f410120134100481b21130c020b2019290300221a200b290300221b54201941086a2903002215200b41086a29030022145420152014511b0d03200b41306a210b201941306a211941012113201a201b85201520148584500d000b0b200941016a210b200a41d0006a210a0240201341016a0e03020001020b0b4100210a0c010b20050d014101210a410021050b200020053602042000200a360200200041106a20093602002000410c6a2003360200200041086a20043602000f0b2001200336020820012005417f6a22053602002001200420094102746a41f8066a28020022043602040c000b0bee0303047f017e017f02402001450d00034020002802f80621002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d004108200041086a200041f8b9c000461b200141d0006c6a22042802442105200441c0006a2802002106200141016a21010c010b02400240200028020022010d002003ad210741002104410021010c010b20003301044220862003ad842107410121040b2000102a2007a72103024002402007422088a7220820012f01064f0d00200121000c010b034002400240200128020022000d002003ad2107410021000c010b200441016a210420013301044220862003ad8421070b2001102a2007a72103200021012007422088a7220820002f01064f0d000b0b4108200041086a200041f8b9c000461b200841d0006c6a22012802442105200141c0006a2802002106200841027420006a41fc066a280200210002402004417f6a2201450d00034020002802f80621002001417f6a22010d000b0b410021010b2006450d012002417f6a210202402005450d002006102a0b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021002001102a2000450d00024020002802002201450d0003402000102a2001210020012802002203210120030d000b0b2000102a0b0b9d0201057f230041106b220324000240024002400240200141046a2204417f4c0d000240024020040d00410121050c010b200410282205450d020b2003410036020820032004360204200320053602002001200310b4010240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d04200641017422072004200720044b1b22074100480d040240024020060d002007102821040c010b200328020020062007102c21040b2004450d032003200736020420032004360200200721060b200420056a20002001109a051a200228020020022802042004200520016a100702402006450d002004102a0b200341106a24000f0b1036000b200441011037000b200741011037000b1031000bcd1f03087f047e017f230041a0036b2203240020034100360288014188e8c200411020034188016a10062104024002402003280288012205417f460d002004450d00024020054104490d00200428000021062004102a410021070c020b41c4d1c300413320034188016a419cd9c3001038000b410121070b0240024002400240024002400240024002400240024020010d004101210841002105410021090c010b200141057422044100480d07200410282208450d012001410574220941606a410576210a2008210420002105034020034188016a41186a200541186a290000220b37030020034188016a41106a200541106a290000220c37030020034188016a41086a200541086a290000220d37030020032005290000220e37038801200441186a200b370000200441106a200c370000200441086a200d3700002004200e370000200441206a2104200541206a2105200941606a22090d000b200a41016a2109200121050b200341f4006a2006360200200320073602702003200241f000109a0522044180016a2009360200200441fc006a20053602002004200836027820044190026a41086a22054200370300200442003703900241eea0c600411120044190026a1008200441b0026a41086a200529030037030020042004290390023703b0022004410036028801200441b0026a411020044188016a10062105024002400240024002400240024002402004280288012203417f470d00410021080c010b024020050d00410021080c010b20034104490d01200528000021082005102a0b0240200841016a22032008490d0020044190026a41086a22054200370300200442003703900241eea0c600411120044190026a1008200441b0026a41086a2209200529030037030020042004290390023703b0022004200336028801200441b0026a411020044188016a4104100720044188016a2004418801109a051a20054200370300200442003703900241d4f2c200410d20044190026a10082009200529030037030020042004290390023703b0022004410036029002200441b0026a411020044190026a10062103024002402004280290022205417f460d002005210920030d010b2004410036028003200442083703f80220044100360298022004420137039002410020044190026a10b401200428029802210520042802940221092004280290022103200441f8026a10720b200420053602c802200420093602c402200420033602c002024002402005450d0020044190026a20032005410110d6022004280290024101470d0120042802c402450d0c20042802c002102a0c0c0b4101200441c0026a10b40120044188016a200441c0026a10aa030c090b200428029402210202402004419c026a280200220520044198026a2802002203460d0020042802c802200520036b6a22094188016a2207417f4c0d100240024020070d00410121060c010b200710282206450d040b200420073602d402200420063602d002200420093602d8022004200441d0026a36029002200220044190026a200510d70120092005490d0420042802d80222022009490d0520042802c80222022003490d0620042802d002210720042802c00221062004200920056b22093602dc022004200220036b22023602940320092002470d07200720056a200620036a2009109a051a20044188016a200441d0026a10aa0320042802d802210320042802d402210920042802d002210520042802c402450d0a20042802c002102a0c0a0b2004200441c0026a36029002200220044190026a200310d70120044188016a200441c0026a10aa030c080b200410ab030c0b0b41c4d1c300413320044188016a419cd9c3001038000b200741011037000b200520091044000b20092002103c000b200320021044000b200441f8026a41146a410836020020044184036a4125360200200441e0026a41146a4103360200200442033702e402200441c8afc6003602e002200441253602fc022004200441dc026a36029803200420044194036a36029c03200442043703a00220044201370294022004419cb0c600360290022004200441f8026a3602f002200420044190026a3602880320042004419c036a36028003200420044198036a3602f802200441e0026a41d8b0c600103e000b200441011037000b20042802c802210320042802c402210920042802c00221050b20050d010b20044188016a10ab030c010b200441b0026a411020052003100702402009450d002005102a0b20044188016a10ab0320044190026a41086a22054200370300200442003703900241d9efc200410d20044190026a1008200441b0026a41086a200529030037030020042004290390023703b0024100210f2004410036028801200441b0026a411020044188016a1006210502402004280288012203417f460d002005450d0020034104490d032005280000210f2005102a0b2001450d002001410574210a02400340200420083602d4022004200f3602d0020240024002400240024002400240024002400240024002400240024002400240411210282205450d00200541106a41002f00f1f2423b0000200541086a41002900e9f242370000200541002900e1f24237000020044188016a41186a2203420037030020044188016a41106a2209420037030020044188016a41086a2201420037030020044200370388012005411220044188016a100020044190026a41186a2202200329030037030020044190026a41106a2207200929030037030020044190026a41086a220620012903003703002004200429038801370390022005102a412010282205450d012005200429039002370000200541186a2002290300370000200541106a2007290300370000200541086a200629030037000020044188016a200010e0022005412041c000102c2205450d022005200429008801370020200541386a2003290000370000200541306a2009290000370000200541286a20012900003700002004410036028801200541c00020044188016a10062109024002402004280288012201417f460d00200121030c010b20044100360290012004420137038801410020044188016a10b4012004280290012103200428028c01210120042802880121090b200420033602b802200420013602b402200420093602b002024002400240024002402003450d0020044188016a20092003410110d6022004280288014101460d04200428028c01210220042802940122032004280290012209460d0320042802b802200320096b6a220141086a2207417f4c0d1a20070d01410121060c020b4101200441b0026a10b40120042802d00221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d18200941017422032002200320024b1b22034100480d180240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d08200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a200136000020042802d40221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d18200941017422032002200320024b1b22034100480d180240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d09200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a20013600000c120b200710282206450d080b200420073602e402200420063602e002200420013602e8022004200441e0026a36028801200220044188016a200310d70120012003490d0820042802e80222022001490d0920042802b80222022009490d0a20042802e002210720042802b00221062004200120036b2201360294032004200220096b22023602980320012002470d0b200720036a200620096a2001109a051a20042802d00221010240024020042802e402220920042802e80222036b4104490d0020042802e00221090c010b200341046a22022003490d16200941017422032002200320024b1b22034100480d160240024020090d002003102821090c010b20042802e00220092003102c21090b2009450d0d200420033602e402200420093602e00220042802e80221030b2004200341046a3602e802200920036a200136000020042802d40221010240024020042802e402220920042802e80222036b4104490d0020042802e00221090c010b200341046a22022003490d16200941017422032002200320024b1b22034100480d160240024020090d002003102821090c010b20042802e00220092003102c21090b2009450d0e200420033602e402200420093602e00220042802e80221030b2004200341046a3602e802200920036a200136000020042802e802210920042802e402210120042802e002210320042802b402450d1120042802b002102a0c110b2004200441b0026a36028801200220044188016a200910d70120042802d00221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d15200941017422032002200320024b1b22034100480d150240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d0e200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a200136000020042802d40221010240024020042802b402220920042802b80222036b4104490d0020042802b00221090c010b200341046a22022003490d15200941017422032002200320024b1b22034100480d150240024020090d002003102821090c010b20042802b00220092003102c21090b2009450d0f200420033602b402200420093602b00220042802b80221030b2004200341046a3602b802200920036a20013600000c0f0b20042802b402450d1120042802b002102a0c110b411241011037000b412041011037000b41c00041011037000b200341011037000b200341011037000b200741011037000b200320011044000b20012002103c000b200920021044000b200441f8026a41146a410836020020044184036a412536020020044190026a41146a41033602002004420337029402200441c8afc60036029002200441253602fc02200420044194036a36029c03200420044198036a3602c00220044204370398012004420137028c012004419cb0c600360288012004200441f8026a3602a002200420044188016a360288032004200441c0026a3602800320042004419c036a3602f80220044190026a41d8b0c600103e000b200341011037000b200341011037000b200341011037000b200341011037000b20042802b802210920042802b402210120042802b00221030b2003450d01200541c00020032009100702402001450d002003102a0b200041206a21002005102a200a41606a220a0d000c020b0b2005102a0b200441a0036a24000f0b1031000b41c4d1c300413320044188016a419cd9c3001038000b1036000bcd0101047f200020014105746a210320002104024003400240200320046b41e0004b0d00024020042003460d00200020014105746a210503404101210620022004460d04200420024120109c05450d042005200441206a2204470d000b0b41000f0b4101210620042002460d01200420024120109c05450d01200441206a22052002460d01200520024120109c05450d01200441c0006a22052002460d01200520024120109c05450d01200441e0006a22052002460d0120044180016a2104200520024120109c050d000b0b20060bba0604017f017e047f027e230041c0006b2201240042002102200141186a41086a220342003703002001420037031841b1f0c200410d200141186a1008200141086a200329030037030020012001290318370300410021032001410036021820014110200141186a100621040240024002400240024020012802182205417f460d002001200536021420012004360210200141186a200141106a107620012802182206450d02200129021c210202402005450d002004102a0b2002422088a721032002a721050c010b41042106410021050b200141186a41206a200041206a280200360200200141186a41186a200041186a290200370300200141186a41106a200041106a290200370300200141186a41086a200041086a29020037030020012000290200370318024020032005470d00024020032002a7470d00200341016a22002003490d04200341017422052000200520004b1bad220742247e2208422088a70d042008a722004100480d040240024020030d002000102821060c010b2006200341246c2000102c21060b2006450d0320024280808080708320078421020b2002422088a721030b2006200341246c22056a22002001290318370200200041206a200141186a41206a280200360200200041186a200141186a41186a290300370200200041106a200141186a41106a290300370200200041086a200141186a41086a2200290300370200200042003703002001420037031841b1f0c200410d200141186a1008200141086a2000290300370300200120012903183703002001411036021c200120013602182006200341016a2200200141186a10e102024020002003490d00200541246a21002006210303400240024020032d0000220541034b0d0002400240024020050e0404000102040b2003410c6a280200450d03200341086a280200102a0c030b2003410c6a280200450d02200341086a280200102a0c020b2003410c6a280200450d01200341086a280200102a0c010b200341086a280200450d00200341046a280200102a0b200341246a21032000415c6a22000d000b0b02402002a7450d002006102a0b200141c0006a24000f0b41c4d1c3004133200141186a419cd9c3001038000b200041041037000b1031000b8c0702067f067e230041d0006b220424000240024002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b2001200a2002200a200a200256200b200356200b2003511b22051b220c7d200b2003200b20051b220d7d200a200c54ad7d108f02024002402002200c7d220b2003200d7d2002200c54ad7d220e8450450d004200210a4200210e0c010b411810282205450d03200541002900e3e140370000200541106a41002900f3e140370000200541086a41002900ebe140370000200442988080808003370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d0042002102420021030c010b20064110490d05200541086a2900002103200529000021022005102a0b20012002200b20022002200b562003200e562003200e511b22051b220a7d2003200e200320051b220f7d2002200a54ad7d109002200e200f7d200b200a54ad7d210e200f200d7c200a200c7c2202200a54ad7c2103200b200a7d210a0b2000200a37031020002002370300200041186a200e37030020002003370308200441d0006a24000f0b411441011037000b41c4d1c3004133200441306a419cd9c3001038000b411841011037000b41c4d1c3004133200441306a419cd9c3001038000be20302067f027e230041d0006b2204240002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b200441306a2001200a20027c2202200b20037c2002200a54ad7c109401200441106a200441306a41106a290300220a370300200420042903382202370308200420042903302203370300024020034200510d002004200441086a360230200441306a109d01420021024200210a0b200020023703002000200a370308200441d0006a24000f0b411441011037000b41c4d1c3004133200441306a419cd9c3001038000b0a0041a8acc3001032000b0a0041b8abc3001032000bbf0301077f230041d0006b22012400024002400240024002400240410110282202450d00200241ed003a0000200241014102102c2202450d01200241ef003a0001200241024104102c2202450d02200241e4d8013b0002200241044108102c2202450d03200241f0f2bda107360004200241084110102c2203450d04200341f2e6c9cb07360008200141003a0048410c210220032104410021050340200141003a0008200141086a200420024100472206109a051a024020020d00200141003a00080b20022006490d06200141286a20056a20012d00083a00002001200541016a22073a0048200220066b2102200420066a21042007210520074120470d000b200141086a41186a2202200141286a41186a290300370300200141086a41106a2206200141286a41106a290300370300200141086a41086a2204200141286a41086a290300370300200120012903283703082003102a200041186a2002290300370000200041106a2006290300370000200041086a200429030037000020002001290308370000200141d0006a24000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b200620021044000b940705017f047e087f057e017f23004180026b22022400200241c0006a2001109f01024002402002290340a7450d00200041003602200c010b200241c0006a41106a290300210320022903482104200241286a2001109f0102402002290328a7450d00200041003602200c010b200241286a41106a290300210520022903302106200241206a2001106c0240024002400240024020022802200d00200128020441306e220741306c2208417f4c0d02200228022421090240024020080d004108210a0c010b20081028220a450d040b02402009450d004100210b0340200241003a00f801200b220c41016a210b2001280204417f6a21084100210d024002400240024003402008417f460d01200241d8016a200d6a2001280200220e2d00003a0000200120083602042001200e41016a3602002002200d41016a220e3a00f8012008417f6a2108200e210d200e4120470d000b200241b8016a41186a2208200241d8016a41186a290300370300200241b8016a41106a220d200241d8016a41106a290300370300200241b8016a41086a220e200241d8016a41086a290300370300200220022903d8013703b801200241086a2001109f012002290308a70d01200241086a41106a290300210f20022903102110200241f8006a41086a200e2903002211370300200241f8006a41106a200d2903002212370300200241f8006a41186a20082903002213370300200241d8006a41086a220d2011370300200241d8006a41106a220e2012370300200241d8006a41186a22142013370300200220022903b8012211370378200220113703582007200c470d030240200c4101742208200b2008200b4b1b2207ad42307e2211422088a70d002011a7220841004e0d030b1031000b200d41ff0171450d00200241003a00f8010b200241f8006a41086a20024198016a41086a2903003703002007450d04200a102a0c040b02400240200c0d0020081028210a0c010b200a200c41306c2008102c210a0b200a450d070b200a200c41306c6a2208200f3703082008201037030020082002290358370310200841186a200d290300370300200841206a200e290300370300200841286a2014290300370300200b2009470d000b0b200a0d010b200041003602200c040b20002004370300200020073602242000200a3602202000200637031020002003370308200041286a2009360200200041186a20053703000c030b1036000b200841081037000b200841081037000b20024180026a24000b0a0041f0b8c0001032000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a360210200041ccb9c000103e000b8d0301027f230041e0006b22032400200341003a0005024002402000413f4b0d0041012104200341013a0005200320004102743a00000c010b02400240200041808001490d0020004180808080044f0d0141042104200341043a0005200320004102744102723602000c020b41022104200341023a0005200320004102744101723b01000c010b41052104200341053a0005200341033a0000200320003600010b024002402001280200220028020822012002490d0020002802002100200320023602082003200436020c20042002470d01200020032002109a051a200341e0006a24000f0b20022001103c000b200341286a41146a4108360200200341346a4125360200200341106a41146a410336020020034203370214200341c8afc6003602102003412536022c2003200341086a36024020032003410c6a360244200342043703582003420137024c2003419cb0c6003602482003200341286a3602202003200341c8006a3602382003200341c4006a3602302003200341c0006a360228200341106a41d8b0c600103e000bb60201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001103f21000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b130020004102360204200041cc9dc6003602000b130020004101360204200041b8a8c3003602000b130020004103360204200041a8dcc0003602000b130020004103360204200041bcaac4003602000b130020004101360204200041d899c6003602000b13002000410b3602042000418082c5003602000b13002000410636020420004198e8c2003602000b130020004104360204200041d09ec1003602000b130020004105360204200041f8aec3003602000b130020004103360204200041ec91c6003602000b130020004105360204200041ac81c2003602000b130020004106360204200041f8d1c3003602000b130020004103360204200041a896c4003602000b13002000410136020420004190e0c0003602000b130020004101360204200041f896c6003602000b8b0701077f23004190026b2202240041002103200241003a002820012802042104417f210502400240034020042003460d01200241086a20036a200128020022062d00003a00002001200420056a3602042001200641016a3602002002200341016a22073a00282005417f6a21052007210320074120470d000b200241e8006a41086a200241086a41086a290300370300200241e8006a41106a200241086a41106a290300370300200241e8006a41186a200241086a41186a2903003703002002200229030837036841002103200241003a0028200420076b2108200420056a21050340024020082003470d000240200341ff0171450d00200241003a00280b200041013a00000c030b200241086a20036a200620036a220741016a2d00003a0000200120053602042001200741026a3602002002200341016a22073a00282005417f6a21052007210320074120470d000b20024188016a41086a200241086a41086a29030037030020024188016a41106a200241086a41106a29030037030020024188016a41186a200241086a41186a290300370300200220022903083703880141002103200241003a008802200620076a2106034002402005417f470d000240200341ff0171450d00200241003a0088020b200041013a00000c030b200241e8016a20036a200620036a220741016a2d00003a0000200120053602042001200741026a3602002002200341016a22073a0088022005417f6a21052007210320074120470d000b200241a8016a41086a2201200241e8016a41086a290300370300200241a8016a41106a2203200241e8016a41106a290300370300200241a8016a41186a2205200241e8016a41186a290300370300200241086a41086a200241e8006a41086a290300370300200241086a41106a200241e8006a41106a290300370300200241086a41186a200241e8006a41186a290300370300200220022903e8013703a80120022002290368370308200241c0006a20024188016a41186a290300370300200241386a20024188016a41106a290300370300200241306a20024188016a41086a2903003703002002200229038801370328200241e0006a2005290300370300200241d8006a2003290300370300200241d0006a2001290300370300200220022903a801370348200041016a200241086a41e000109a051a200041003a00000c010b0240200341ff0171450d00200241003a00280b200041013a00000b20024190026a24000bf90802067f047e230041d0026b220224000240024002400240024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a3602042001200441016a360200200541034b0d0620050e0401020304010b200041053a00000c090b200241206a2001106d20022802200d03200041053a00000c080b200241c0006a20011081010240024020022802404113460d00200241c8016a200241c0006a418801109a051a418801102822050d0141880141081037000b200041053a00000c080b2005200241c8016a418801109a052105200041023a0000200020022f00103b0001200041036a200241106a41026a2d00003a0000200041046a2005360200200041086a2002290220370200200041106a200241206a41086a290200370200200041186a200241206a41106a290200370200200041206a200241206a41186a2902003702000c070b20022001106c20022802000d0520022802042105200241c0006a200110810120022802404113460d05200241c8016a200241c0006a418801109a051a41880110282201450d032001200241c8016a418801109a052101200041033a0000200020022f00103b0001200041036a200241126a2d00003a0000200041086a2001360200200041046a20053602002000410c6a2002290220370200200041146a200241206a41086a2902003702002000411c6a200241306a290200370200200041246a200241386a2802003602000c060b41002105200241003a00e8012003417f6a21062003417e6a21030340024020062005470d00200541ff0171450d05200241003a00e8010c050b200241c8016a20056a200420056a220741016a2d00003a0000200120033602042001200741026a3602002002200541016a22073a00e8012003417f6a21032007210520074120470d000b200241c0006a41186a200241c8016a41186a290300370300200241c0006a41106a200241c8016a41106a290300370300200241c0006a41086a200241c8016a41086a290300370300200220022903c801370340200241086a2001106c20022802080d0320012802042205450d03200228020c2103200128020022072d0000210420012005417f6a3602042001200741016a360200200241206a41086a200241c0006a41086a2903002208370300200241206a41106a200241c0006a41106a2903002209370300200241206a41186a200241c0006a41186a290300220a37030020022002290340220b370320200041043a00002000200b370001200041096a2008370000200041116a2009370000200041196a200a370000200041246a2003360200200041216a20043a00000c050b200241cb006a200241206a41086a28020036000020022002290320370043200041013a000020002002290040370001200041086a200241c7006a290000370000200041106a20022902c801370200200041186a200241c8016a41086a290200370200200041206a200241c8016a41106a2902003702000c040b200041053a00000c030b41880141081037000b200041053a00000c010b200041053a00000b200241d0026a24000bd50603057f0b7e057f230041106b21020240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a36020020064108490d00200429000421072001200341746a220636020420012004410c6a36020020064108490d00200429000c210820012003416c6a22063602042001200441146a36020020064108490d00200429001421092001200341646a220636020420012004411c6a36020020064108490d00200429001c210a20012003415c6a22063602042001200441246a36020020064108490d002004290024210b2001200341546a220636020420012004412c6a36020020064108490d00200429002c210c20012003414c6a22063602042001200441346a36020020064108490d002004290034210d2001200341446a220636020420012004413c6a36020020064108490d00200429003c210e2001200341bc7f6a22063602042001200441c4006a36020020064108490d002004290044210f2001200341b47f6a22063602042001200441cc006a36020020064108490d00200429004c21102001200341ac7f6a22063602042001200441d4006a36020020064108490d00200429005421112001200341a47f6a22063602042001200441dc006a36020020064104490d00200428005c21122001200341a07f6a22063602042001200441e0006a36020020064104490d002004280060211320012003419c7f6a22063602042001200441e4006a36020020064104490d00200428006421142001200341987f6a22063602042001200441e8006a36020020064104490d00200428006821152001200341947f6a22063602042001200441ec006a22043602002006450d0020042d000021162001200341937f6a22063602042001200441016a36020020064104490d00200020163a00702000201536026820002014360264200020133602602000201236025c2000200536025820002011370350200020103703482000200f3703402000200e3703382000200d3703302000200c3703282000200b3703202000200a3703182000200937031020002008370308200020073703002004280001210620012003418f7f6a3602042001200441056a3602002000200636026c200041f4006a2002410c6a280000360000200020022800093600710f0b200041023a00700bfb910205057f017e067f017e017f230041206b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000280200220341144b0d00024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020030e15000102030405060708090a0b0c0d0e0f1011121314000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d62200341017422052004200520044b1b22054100480d620240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208417f6a220341054b0d1502400240024002400240024020030e06000102030405000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d67200341017422042000200420004b1b22044100480d670240024020030d002004102821000c010b200128020020032004102c21000b2000450d1d20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c1a0b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d66200341017422052004200520044b1b22054100480d660240024020030d002005102821040c010b200128020020032005102c21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200028020c2106200041146a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d66200441017422002005200020054b1b22004100480d660240024020040d002000102821040c010b200128020020042000102c21040b2004450d1e20012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c190b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d65200341017422052004200520044b1b22054100480d650240024020030d002005102821040c010b200128020020032005102c21040b2004450d1e20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000290310210702400240200141046a2802002200200528020022036b4108490d00200128020021000c010b200341086a22042003490d65200041017422032004200320044b1b22034100480d650240024020000d002003102821000c010b200128020020002003102c21000b2000450d1f20012000360200200141046a2003360200200141086a28020021030b200141086a200341086a360200200020036a20073700000c180b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d64200341017422052004200520044b1b22054100480d640240024020030d002005102821040c010b200128020020032005102c21040b2004450d1f20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c2106200041146a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d64200441017422002005200020054b1b22004100480d640240024020040d002000102821040c010b200128020020042000102c21040b2004450d2020012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c170b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021050c010b200341016a22042003490d63200341017422052004200520044b1b22044100480d630240024020030d002004102821050c010b200128020020032004102c21050b2005450d2020012005360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200520036a41043a0000200028020c2103200041146a2802002200200110b4012000450d162003200041186c6a2108200141046a2106034020032802002109200341086a2802002200200110b401024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d64200a4101742205200b2005200b4b1b22054100480d6402400240200a0d0020051028210a0c010b2001280200200a2005102c210a0b200a450d222001200a36020020062005360200200428020021050b2004200520006a360200200a20056a20092000109a051a2003410c6a2802002109200341146a2802002200200110b401024002402006280200220a200428020022056b2000490d002001280200210a0c010b200520006a220b2005490d64200a4101742205200b2005200b4b1b22054100480d6402400240200a0d0020051028210a0c010b2001280200200a2005102c210a0b200a450d232001200a36020020062005360200200428020021050b2004200520006a360200200a20056a20092000109a051a200341186a22032008470d000c170b0b200241053a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d62200341017422052004200520044b1b22054100480d620240024020030d002005102821040c010b200128020020032005102c21040b2004450d2220012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41053a0000200028020c2104200041146a2802002203200110b4012003450d1520042003410c6c6a2108200141046a210903402004280200210a200441086a2802002203200110b4010240024020092802002205200628020022006b2003490d00200128020021050c010b200020036a220b2000490d6320054101742200200b2000200b4b1b22004100480d630240024020050d002000102821050c010b200128020020052000102c21050b2005450d242001200536020020092000360200200628020021000b2006200020036a360200200520006a200a2003109a051a2004410c6a22042008470d000c160b0b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d61200341017422042000200420004b1b22044100480d610240024020030d002004102821000c010b200128020020032004102c21000b2000450d2320012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000c130b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d2320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041086a200110a1010c130b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2520012004360200200141046a2005360200200141086a28020021030b200141086a220a200341016a360200200420036a41003a00002000280204210c2000410c6a2802002203200110b4012003450d12200c200341f0006c6a210d200141046a210b034020022001360208200c41106a200241086a10c801200c200110a00120022001360208200c41306a200241086a10c80120022001360208200c41d0006a200241086a10c801200c2802042104200c28020c2203200110b40102402003450d00200341246c21090340200241086a200410ec012002280208210602400240200b2802002205200a28020022036b20022802102200490d00200128020021050c010b200320006a22082003490d62200541017422032008200320084b1b22034100480d620240024020050d002003102821050c010b200128020020052003102c21050b2005450d2920012005360200200b2003360200200a28020021030b200a200320006a360200200520036a20062000109a051a0240200228020c450d002006102a0b200441246a21042009415c6a22090d000b0b200c41f0006a220c200d470d000c130b0b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d5e200341017422042000200420004b1b22044100480d5e0240024020030d002004102821000c010b200128020020032004102c21000b2000450d2620012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41043a00000c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5d200341017422052004200520044b1b22054100480d5d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000280208417f6a220341024b0d10024002400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d60200341017422052004200520044b1b22044100480d600240024020030d002004102821050c010b200128020020032004102c21050b2005450d2a20012005360200200141046a2004360200200141086a28020021030b200041306a2104200141086a200341016a360200200520036a41003a00002000410c6a200110a601200241146a21030c020b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d5f200341017422052004200520044b1b22044100480d5f0240024020030d002004102821050c010b200128020020032004102c21050b2005450d2a20012005360200200141046a2004360200200141086a28020021030b200041c0006a2104200141086a200341016a360200200520036a41013a00002000410c6a200110a6012002200041306a360218200241186a200110a3012002411c6a21030c010b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22042003490d5e200341017422052004200520044b1b22044100480d5e0240024020030d002004102821050c010b200128020020032004102c21050b2005450d2a20012005360200200141046a2004360200200141086a28020021030b200041d8006a2104200141086a200341016a360200200520036a41023a00002000410c6a200110a601200041306a200110a601200241086a21030b200320043602002003200110a3010c100b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a000020002d0008417f6a2203410c4b0d0f024002400240024002400240024002400240024002400240024020030e0d000102030405060708090a0b0c000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d68200341017422052004200520044b1b22054100480d680240024020030d002005102821040c010b200128020020032005102c21040b2004450d3620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000410c6a200110a6012002200041306a360208200241086a200110a30120002d0009220341024b0d1b02400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d6a200341017422042000200420004b1b22044100480d6a0240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c1d0b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d69200341017422042000200420004b1b22044100480d690240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000c1c0b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d68200341017422042000200420004b1b22044100480d680240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41023a00000c1b0b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d67200341017422052004200520044b1b22054100480d670240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002002200041106a360208200241086a200110a3010c1a0b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d66200341017422052004200520044b1b22054100480d660240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200041106a360208200241086a200110a3010c190b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d65200341017422042000200420004b1b22044100480d650240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41033a00000c180b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021040c010b200341016a22042003490d64200341017422052004200520044b1b22054100480d640240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002002200041106a360208200241086a200110a3010c170b200241053a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d63200341017422052004200520044b1b22054100480d630240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200028020c2103200041146a2802002200200110b4012000450d16200041246c210003402003200110a601200341246a21032000415c6a22000d000c170b0b200241063a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d62200341017422042000200420004b1b22044100480d620240024020030d002004102821000c010b200128020020032004102c21000b2000450d3920012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41063a00000c150b200241073a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d61200341017422052004200520044b1b22054100480d610240024020030d002005102821040c010b200128020020032005102c21040b2004450d3920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a000020002d0009220341024b0d1402400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d63200341017422042000200420004b1b22044100480d630240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c160b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d62200341017422042000200420004b1b22044100480d620240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000c150b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d61200341017422042000200420004b1b22044100480d610240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41023a00000c140b200141046a2802002104200241083a0018024002402004200141086a2802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a00002000410c6a200110a6010c130b200241093a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a200110a0010c120b2002410a3a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d5e200341017422042000200420004b1b22044100480d5e0240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410a3a00000c110b2002410b3a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d5d200341017422042000200420004b1b22044100480d5d0240024020030d002004102821000c010b200128020020032004102c21000b2000450d3c20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410b3a00000c100b2002410c3a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a0000200028020c2103200041146a2802002200200110b4012000450d0f20004105742100034020032001108f01200341206a2103200041606a22000d000c100b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41073a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d3d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041106a2001108f01200041306a2001108f01200041d0006a2001108f01200028020421062000410c6a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d5b200441017422002005200020054b1b22004100480d5b0240024020040d002000102821040c010b200128020020042000102c21040b2004450d3e20012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c0e0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d5a2003410174220a2005200a20054b1b220a4100480d5a0240024020030d00200a102821050c010b20012802002003200a102c21050b2005450d3e20012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41083a0000200041086a22052d0000417f6a220341104b0d0d0240024002400240024002400240024002400240024002400240024002400240024020030e11000102030405060708090a0b0c0d0e0f10000b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d6a200341017422052004200520044b1b22054100480d6a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d4f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020c200110eb012002200041106a360208200241086a200110a3010c1d0b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d69200341017422052004200520044b1b22054100480d690240024020030d002005102821040c010b200128020020032005102c21040b2004450d4f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110a0010c1c0b02400240200628020020042802002203460d00200128020021060c010b200341016a22062003490d682003410174220a2006200a20064b1b220a4100480d680240024020030d00200a102821060c010b20012802002003200a102c21060b2006450d4f20012006360200200141046a200a360200200141086a28020021030b200141086a220a200341016a360200200620036a41023a00002000410c6a200110a00120052d00012106200541026a2d0000210502400240200141046a280200200a2802002203460d00200128020021000c010b200341016a22002003490d682003410174220a2000200a20004b1b220a4100480d680240024020030d00200a102821000c010b20012802002003200a102c21000b2000450d5020012000360200200141046a200a360200200141086a28020021030b2004200341016a360200200020036a20064100474107742005723a00000c1b0b02400240200628020020042802002203460d00200128020021060c010b200341016a22062003490d672003410174220a2006200a20064b1b220a4100480d670240024020030d00200a102821060c010b20012802002003200a102c21060b2006450d5020012006360200200141046a200a360200200141086a28020021030b200141086a220a200341016a360200200620036a41033a00002000410c6a200110a00120052d00012106200541026a2d0000210502400240200141046a280200200a2802002203460d00200128020021000c010b200341016a22002003490d672003410174220a2000200a20004b1b220a4100480d670240024020030d00200a102821000c010b20012802002003200a102c21000b2000450d5120012000360200200141046a200a360200200141086a28020021030b2004200341016a360200200020036a20064100474107742005723a00000c1a0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d662003410174220a2005200a20054b1b220a4100480d660240024020030d00200a102821050c010b20012802002003200a102c21050b2005450d5120012005360200200141046a200a360200200141086a28020021030b2004200341016a360200200520036a41043a0000200028020c21050240024020062802002200200428020022036b4104490d00200128020021000c010b200341046a22062003490d66200041017422032006200320064b1b22034100480d660240024020000d002003102821000c010b200128020020002003102c21000b2000450d5220012000360200200141046a2003360200200141086a28020021030b2004200341046a360200200020036a20053600000c190b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d65200341017422052004200520044b1b22054100480d650240024020030d002005102821040c010b200128020020032005102c21040b2004450d5220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a0000200028020c200110eb010c180b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d64200341017422052004200520044b1b22054100480d640240024020030d002005102821040c010b200128020020032005102c21040b2004450d5220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a0000200028020c200110eb010c170b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d63200341017422052004200520044b1b22054100480d630240024020030d002005102821040c010b200128020020032005102c21040b2004450d5220012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200028020c200110eb010c160b02400240200628020020042802002203460d002001280200210a0c010b200341016a220a2003490d6220034101742209200a2009200a4b1b22094100480d620240024020030d0020091028210a0c010b200128020020032009102c210a0b200a450d522001200a360200200141046a2009360200200141086a28020021030b200141086a2209200341016a360200200a20036a41083a000020022001360208200541016a200241086a10c801200028022c210a02400240200141046a2802002205200928020022036b4104490d00200128020021050c010b200341046a22092003490d62200541017422032009200320094b1b22034100480d620240024020050d002003102821050c010b200128020020052003102c21050b2005450d5320012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200a360000200028023021050240024020062802002200200428020022036b4104490d00200128020021000c010b200341046a22062003490d62200041017422032006200320064b1b22034100480d620240024020000d002003102821000c010b200128020020002003102c21000b2000450d5420012000360200200141046a2003360200200141086a28020021030b2004200341046a360200200020036a20053600000c150b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d61200341017422042000200420004b1b22044100480d610240024020030d002004102821000c010b200128020020032004102c21000b2000450d5420012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41093a000020022001360208200541016a200241086a10c8010c140b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d5420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a00002000410c6a200110a0010c130b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d5f200341017422052004200520044b1b22054100480d5f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d5420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000410c6a200110a001200041106a200110a001200041146a200110a0010c120b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5e200341017422042000200420004b1b22044100480d5e0240024020030d002004102821000c010b200128020020032004102c21000b2000450d5420012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410c3a0000200541016a2001108f010c110b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5d200341017422052000200520004b1b22054100480d5d0240024020030d002005102821000c010b200128020020032005102c21000b2000450d5420012000360200200141046a2005360200200141086a28020021030b2004200341016a360200200020036a410d3a00000c100b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5c200341017422042000200420004b1b22044100480d5c0240024020030d002004102821000c010b200128020020032004102c21000b2000450d5420012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a410e3a0000200541016a2001108f010c0f0b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5b2003410174220a2000200a20004b1b220a4100480d5b0240024020030d00200a102821000c010b20012802002003200a102c21000b2000450d5420012000360200200141046a200a360200200141086a28020021030b200141086a200341016a360200200020036a410f3a0000200541016a2001108f0120052d0021220341064b0d0e0240024002400240024002400240024020030e0700010203040506000b410021000c060b410121000c050b410221000c040b410321000c030b410421000c020b410521000c010b410621000b200220003a001802400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5b200341017422062005200620054b1b22064100480d5b0240024020030d002006102821050c010b200128020020032006102c21050b2005450d5520012005360200200141046a2006360200200141086a28020021030b2004200341016a360200200520036a20003a00000c0e0b02400240200628020020042802002203460d00200128020021000c010b200341016a22002003490d5a200341017422052000200520004b1b22054100480d5a0240024020030d002005102821000c010b200128020020032005102c21000b2000450d5520012000360200200141046a2005360200200141086a28020021030b2004200341016a360200200020036a41103a00000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041046a200110ed010c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a0000200041046a200110ed010c0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d57200341017422052004200520044b1b22054100480d570240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a00002000280208417f6a220341094b0d0a024002400240024002400240024002400240024020030e0a00010203040506070809000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d60200341017422052004200520044b1b22054100480d600240024020030d002005102821040c010b200128020020032005102c21040b2004450d5f20012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41003a0000200028020c2104200041146a280200220a200110b4010240200a450d00200141046a2109034002400240200928020020062802002203460d00200128020021050c010b200341016a22052003490dad012003410174220b2005200b20054b1b220b4100480dad010240024020030d00200b102821050c010b20012802002003200b102c21050b2005450d63200120053602002009200b360200200628020021030b2006200341016a360200200520036a20042d00003a0000200441016a2104200a417f6a220a0d000b0b200041186a200110a001200028021c210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490dab01200441017422032006200320064b1b22034100480dab010240024020040d002003102821040c010b200128020020042003102c21040b2004450d6220012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041286a29030021072000290320210e02400240200141046a2802002200200628020022036b4110490d00200128020021000c010b200341106a22042003490dab01200041017422032004200320044b1b22034100480dab010240024020000d002003102821000c010b200128020020002003102c21000b2000450d6320012000360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200020036a220320073700082003200e3700000c130b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490daa01200341017422052004200520044b1b22054100480daa010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6320012004360200200141046a2005360200200141086a28020021030b200141086a2206200341016a360200200420036a41013a0000200028020c2104200041146a280200220a200110b4010240200a450d00200141046a2109034002400240200928020020062802002203460d00200128020021050c010b200341016a22052003490dac012003410174220b2005200b20054b1b220b4100480dac010240024020030d00200b102821050c010b20012802002003200b102c21050b2005450d66200120053602002009200b360200200628020021030b2006200341016a360200200520036a20042d00003a0000200441016a2104200a417f6a220a0d000b0b200041186a200110a001200028021c210502400240200141046a2802002204200628020022036b4104490d00200128020021040c010b200341046a22062003490daa01200441017422032006200320064b1b22034100480daa010240024020040d002003102821040c010b200128020020042003102c21040b2004450d6520012004360200200141046a2003360200200141086a28020021030b200141086a2206200341046a360200200420036a2005360000200041286a29030021072000290320210e02400240200141046a2802002200200628020022036b4110490d00200128020021000c010b200341106a22042003490daa01200041017422032004200320044b1b22034100480daa010240024020000d002003102821000c010b200128020020002003102c21000b2000450d6620012000360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200020036a220320073700082003200e3700000c120b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da901200341017422052004200520044b1b22054100480da9010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a200110a001200041106a200110a601200041346a200110a001200041386a200110a0010c110b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da801200341017422052004200520044b1b22054100480da8010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002000410c6a200110a0010c100b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021040c010b200341016a22042003490da701200341017422052004200520044b1b22054100480da7010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41043a00002000410c6a200110a0010c0f0b200241053a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da601200341017422052004200520044b1b22054100480da6010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41053a00002000410c6a200110a6012002200041386a360208200241086a200110a301200041306a200110a0010c0e0b200241063a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da501200341017422052004200520044b1b22054100480da5010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a00002000410c6a200110a0010c0d0b200241073a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da401200341017422052004200520044b1b22054100480da4010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a00002000410c6a200110a6010c0c0b200141046a2802002104200241083a0018024002402004200141086a2802002203460d00200128020021040c010b200341016a22042003490da301200341017422052004200520044b1b22054100480da3010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a00002000410c6a200110a0010c0b0b200241093a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da201200341017422052004200520044b1b22054100480da2010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a00002000410c6a200110a0010c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da101200341017422052004200520044b1b22054100480da1010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a0000200041046a22042d0000417f6a220341034b0d09024002400240024020030e0400010203000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490da401200341017422052000200520004b1b22054100480da4010240024020030d002005102821000c010b200128020020032005102c21000b2000450d6a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41003a0000200441016a2001108f010c0c0b200141086a2802002103200141046a2802002100200241013a00180240024020002003460d00200128020021000c010b200341016a22002003490da301200341017422052000200520004b1b22054100480da3010240024020030d002005102821000c010b200128020020032005102c21000b2000450d6a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41013a0000200441016a2001108f010c0b0b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490da201200341017422052000200520004b1b22054100480da2010240024020030d002005102821000c010b200128020020032005102c21000b2000450d6a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41023a0000200441016a2001108f01200441216a2001108f010c0a0b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da101200341017422052004200520044b1b22054100480da1010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002802082103200041106a2802002200200110b4012000450d0920004105742100034020032001108f01200341206a2103200041606a22000d000c0a0b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410d3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6b20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041046a200110a0010c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410e3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020421062000410c6a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d9f01200441017422002005200020054b1b22004100480d9f010240024020040d002000102821040c010b200128020020042000102c21040b2004450d6d20012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9e01200341017422052004200520044b1b22054100480d9e010240024020030d002005102821040c010b200128020020032005102c21040b2004450d6d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410f3a00002000280208417f6a220341024b0d0602400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002002200041306a360208200241086a200110a3012000410c6a200110a6010c080b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000410c6a200110a0010c070b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9e01200341017422052004200520044b1b22054100480d9e010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002000410c6a200110a0010c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9d01200341017422052004200520044b1b22054100480d9d010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41103a0000200041086a22042d0000417f6a220341044b0d050240024002400240024020030e050001020304000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da101200341017422052004200520044b1b22054100480da1010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041106a200110ee010c090b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490da001200341017422052004200520044b1b22054100480da0010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a200110a101200028020c2106200041146a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490da001200441017422002005200020054b1b22004100480da0010240024020040d002000102821040c010b200128020020042000102c21040b2004450d7620012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c080b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9f01200341017422052004200520044b1b22054100480d9f010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000410c6a200110a6012002200041c0006a360208200241086a200110a301200041d0006a200110a10120002802302106200041386a2802002203200110b40102400240200141046a2802002204200528020022006b2003490d00200128020021040c010b200020036a22052000490d9f01200441017422002005200020054b1b22004100480d9f010240024020040d002000102821040c010b200128020020042000102c21040b2004450d7720012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20062003109a051a0c070b200241033a001802400240200141046a280200200141086a2802002203460d00200128020021050c010b200341016a22052003490d9e01200341017422062005200620054b1b22064100480d9e010240024020030d002006102821050c010b200128020020032006102c21050b2005450d7720012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a41033a00002002200041386a360208200241086a200110a301200041c8006a200110a10120022001360208200441016a200241086a10c801200028022c2105200041346a2802002203200110b40102400240200141046a2802002204200628020022006b2003490d00200128020021040c010b200020036a22062000490d9e01200441017422002006200020064b1b22004100480d9e010240024020040d002000102821040c010b200128020020042000102c21040b2004450d7820012004360200200141046a2000360200200141086a28020021000b200141086a200020036a360200200420006a20052003109a051a0c060b200141086a2802002103200241043a0018024002402003200141046a280200460d00200128020021000c010b200341016a22002003490d9d01200341017422052000200520004b1b22054100480d9d010240024020030d002005102821000c010b200128020020032005102c21000b2000450d7820012000360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200020036a41043a0000200441016a2001108f01024020042d00214101460d00200241003a001802400240200141046a28020020052802002203460d00200128020021000c010b200341016a22002003490d9e01200341017422042000200420004b1b22044100480d9e010240024020030d002004102821000c010b200128020020032004102c21000b2000450d7a20012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c060b200241013a001802400240200141046a28020020052802002203460d00200128020021000c010b200341016a22002003490d9d01200341017422052000200520004b1b22054100480d9d010240024020030d002005102821000c010b200128020020032005102c21000b2000450d7a20012000360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200020036a41013a0000200441226a2001108f010c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9c01200341017422052004200520044b1b22054100480d9c010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41113a00002000280204417f6a220341024b0d0402400240024020030e03000102000b200241003a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9e01200341017422052004200520044b1b22054100480d9e010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00002000280208200110eb010c060b200241013a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9d01200341017422052004200520044b1b22054100480d9d010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041086a200110a6010c050b200241023a001802400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d9c01200341017422052004200520044b1b22054100480d9c010240024020030d002005102821040c010b200128020020032005102c21040b2004450d7d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041086a200110a601200028022c200110eb010c040b02400240200141046a220a280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d9b01200441017422062005200620054b1b22064100480d9b010240024020040d002006102821050c010b200128020020042006102c21050b2005450d7d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a41123a000002400240200a28020020032802002204460d00200128020021050c010b200441016a22052004490d9b01200441017422062005200620054b1b22064100480d9b010240024020040d002006102821050c010b200128020020042006102c21050b2005450d7e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a41003a00002000280204210602400240200a2802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d9b01200541017422042009200420094b1b22044100480d9b010240024020050d002004102821050c010b200128020020052004102c21050b2005450d7f20012005360200200141046a2004360200200141086a28020021040b200141086a2209200441046a360200200520046a2006360000200041086a280200210b200041106a2802002204200110b40102400240200141046a2802002206200928020022056b2004490d00200128020021060c010b200520046a22092005490d9b01200641017422052009200520094b1b22054100480d9b010240024020060d002005102821060c010b200128020020062005102c21060b2006450d800120012006360200200141046a2005360200200141086a28020021050b200141086a2208200520046a360200200620056a200b2004109a051a200041146a28020021062000411c6a2802002204200110b40102402004450d0020062004410c6c6a210f200141046a210c03402006280200210b200641086a2802002204200110b40102400240200c2802002209200828020022056b2004490d00200128020021090c010b200520046a220d2005490d9d0120094101742205200d2005200d4b1b22054100480d9d010240024020090d002005102821090c010b200128020020092005102c21090b2009450d830120012009360200200c2005360200200828020021050b2003200520046a360200200920056a200b2004109a051a2006410c6a2206200f470d000b0b200041206a280200210602400240200a2802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d9b01200541017422042009200420094b1b22044100480d9b010240024020050d002004102821050c010b200128020020052004102c21050b2005450d820120012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a2006360000200041246a280200210602400240200a2802002205200328020022046b4104490d00200128020021050c010b200441046a22092004490d9b01200541017422042009200420094b1b22044100480d9b010240024020050d002004102821050c010b200128020020052004102c21050b2005450d830120012005360200200141046a2004360200200141086a28020021040b2003200441046a360200200520046a200636000002400240200a28020020032802002204460d00200128020021050c010b200441016a22052004490d9b01200441017422062005200620054b1b22064100480d9b010240024020040d002006102821050c010b200128020020042006102c21050b2005450d840120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a200041286a22042d00003a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d850120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00013a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d860120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d002a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d870120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00033a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d880120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d002c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d890120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00053a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8a0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d002e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8b0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00073a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8c0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00303a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8d0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00093a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8e0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00323a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d8f0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d000b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d900120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00343a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d910120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d000d3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d920120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00363a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d930120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d000f3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d940120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00383a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d950120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00113a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d960120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d003a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d970120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00133a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d980120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d003c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d990120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00153a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490d9b01200541017422092006200920064b1b22094100480d9b010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9a0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d003e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9c0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00173a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9d0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00403a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9e0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00193a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450d9f0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00423a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da00120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d001b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da10120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00443a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da20120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d001d3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da30120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00463a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da40120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d001f3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da50120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00483a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da60120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00213a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da70120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d004a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da80120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00233a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450da90120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d004c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450daa0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00253a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dab0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d004e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dac0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00273a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dad0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00503a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dae0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00293a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450daf0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00523a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db00120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d002b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db10120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00543a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db20120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d002d3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db30120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00563a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db40120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d002f3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db50120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00583a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db60120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00313a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db70120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d005a3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db80120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00333a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450db90120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d005c3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dba0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00353a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbb0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d005e3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbc0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00373a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbd0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00603a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbe0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d00393a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dbf0120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00623a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dc00120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20042d003b3a000002400240200a28020020032802002205460d00200128020021060c010b200541016a22062005490dc701200541017422092006200920064b1b22094100480dc7010240024020050d002009102821060c010b200128020020052009102c21060b2006450dc10120012006360200200141046a2009360200200141086a28020021050b2003200541016a360200200620056a20002d00643a000002400240200a28020020032802002200460d00200128020021050c010b200041016a22052000490dc701200041017422062005200620054b1b22064100480dc7010240024020000d002006102821050c010b200128020020002006102c21050b2005450dc20120012005360200200141046a2006360200200141086a28020021000b2003200041016a360200200520006a20042d003d3a000002400240200a28020020032802002200460d00200128020021050c010b200041016a22052000490dc701200041017422062005200620054b1b22064100480dc7010240024020000d002006102821050c010b200128020020002006102c21050b2005450dc30120012005360200200141046a2006360200200141086a28020021000b2003200041016a360200200520006a20042d003e3a000002400240200a28020020032802002200460d00200128020021050c010b200041016a22052000490dc701200041017422062005200620054b1b22064100480dc7010240024020000d002006102821050c010b200128020020002006102c21050b2005450dc40120012005360200200141046a2006360200200141086a28020021000b2003200041016a360200200520006a20042d003f3a00000c030b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490dc601200341017422042000200420004b1b22044100480dc6010240024020030d002004102821000c010b200128020020032004102c21000b2000450dc40120012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41133a00000c010b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490dc501200341017422042000200420004b1b22044100480dc5010240024020030d002004102821000c010b200128020020032004102c21000b2000450dc40120012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41143a00000b200110c4010b200241206a24000f0b200541011037000b200441011037000b200541011037000b200041011037000b200541011037000b200341011037000b200541011037000b200041011037000b200441011037000b200541011037000b200541011037000b200541011037000b200041011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200341011037000b200441011037000b200541011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200441011037000b200541011037000b200541011037000b200441011037000b200541011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200541011037000b200541011037000b200541011037000b200041011037000b200a41011037000b200541011037000b200541011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200341011037000b200541011037000b200541011037000b200541011037000b200941011037000b200341011037000b200341011037000b200441011037000b200541011037000b200541011037000b200441011037000b200541011037000b200441011037000b200a41011037000b200641011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1031000b200b41011037000b200341011037000b200341011037000b200541011037000b200b41011037000b200341011037000b200341011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200041011037000b200641011037000b200041011037000b200541011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b200641011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200641011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b1031000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200941011037000b200641011037000b200641011037000b200641011037000b200441011037000b200441011037000b1031000bb31601067f230041106b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e050003010204000b2002410036020820024201370300410110282203450d05200242818080801037020420022003360200200341023a00002002200236020c200141016a2002410c6a10c8010c040b2002410036020820024201370300410110282203450d05200242818080801037020420022003360200200341043a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0720022005360204200220043602000b2002200341016a360208200420036a20012d00013a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0820022005360204200220043602000b2002200341016a360208200420036a20012d00023a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0920022005360204200220043602000b2002200341016a360208200420036a20012d00033a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d1a200341017422052004200520044b1b22054100480d1a0240024020030d002005102821040c010b200228020020032005102c21040b2004450d0a20022005360204200220043602000b2002200341016a360208200420036a20012d00043a000020012802082105200141106a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d1a200441017422072006200720064b1b22064100480d1a0240024020040d002006102821040c010b200228020020042006102c21040b2004450d0b20022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0c030b2002410036020820024201370300410110282203450d0a200242818080801037020420022003360200200341053a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0c20022005360204200220043602000b2002200341016a360208200420036a20012d00013a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0d20022005360204200220043602000b2002200341016a360208200420036a20012d00023a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0e20022005360204200220043602000b2002200341016a360208200420036a20012d00033a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d19200341017422052004200520044b1b22054100480d190240024020030d002005102821040c010b200228020020032005102c21040b2004450d0f20022005360204200220043602000b2002200341016a360208200420036a20012d00043a000020012802082105200141106a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d19200441017422072006200720064b1b22064100480d190240024020040d002006102821040c010b200228020020042006102c21040b2004450d1020022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0c020b2002410036020820024201370300410110282203450d0f200242818080801037020420022003360200200341063a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1120022005360204200220043602000b2002200341016a360208200420036a20012d00013a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1220022005360204200220043602000b2002200341016a360208200420036a20012d00023a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1320022005360204200220043602000b2002200341016a360208200420036a20012d00033a000002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d18200341017422052004200520044b1b22054100480d180240024020030d002005102821040c010b200228020020032005102c21040b2004450d1420022005360204200220043602000b2002200341016a360208200420036a20012d00043a000020012802082105200141106a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d18200441017422072006200720064b1b22064100480d180240024020040d002006102821040c010b200228020020042006102c21040b2004450d1520022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0c010b2002410036020820024201370300410110282203450d14200242818080801037020420022003360200200341003a0000200141046a28020021052001410c6a2802002201200210b4010240024020022802042204200228020822036b2001490d00200228020021040c010b200320016a22062003490d17200441017422072006200720064b1b22064100480d170240024020040d002006102821040c010b200228020020042006102c21040b2004450d1620022006360204200220043602000b2002200320016a360208200420036a20052001109a051a0b200020022201290200370200200041086a200141086a280200360200200241106a24000f0b410141011037000b410141011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b410141011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b410141011037000b200541011037000b200541011037000b200541011037000b200541011037000b200641011037000b410141011037000b200641011037000b1031000b800801047f230041106b22022400024002400240024002400240024020002d0000417f6a220341034b0d00024002400240024020030e0400010203000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0a200341017422052004200520044b1b22054100480d0a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200028020421032000410c6a2802002200200110b4012000450d0320004105742100034020032001108f01200341206a2103200041606a22000d000c040b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d09200341017422052004200520044b1b22054100480d090240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00002000280204200110eb010c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a0000200041046a200110a0012000280208200110eb010c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102821040c010b200128020020032005102c21040b2004450d0520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a00002002200136020c200041016a2002410c6a10c801200041246a200110a00102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d07200341017422052004200520044b1b22054100480d070240024020030d002005102821040c010b200128020020032005102c21040b2004450d0620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00213a00000b200241106a24000f0b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1031000bf71802047f017e20002802582102024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141046a2802002203200141086a28020022046b4104490d00200128020021030c010b200441046a22052004490d13200341017422042005200420054b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0120012003360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200320046a20023600002000290300210602400240200141046a2802002203200528020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0220012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290308210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0320012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290310210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290318210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290320210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0620012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290328210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0720012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290330210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0820012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290338210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0920012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290340210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0a20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290348210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0b20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a20063700002000290350210602400240200141046a2802002203200228020022046b4108490d00200128020021030c010b200441086a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0c20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441086a360200200320046a2006370000200028025c210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0d20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280260210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0e20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280264210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d0f20012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a20053600002000280268210502400240200141046a2802002203200228020022046b4104490d00200128020021030c010b200441046a22022004490d13200341017422042002200420024b1b22044100480d130240024020030d002004102821030c010b200128020020032004102c21030b2003450d1020012003360200200141046a2004360200200141086a28020021040b200141086a2202200441046a360200200320046a200536000002400240200141046a28020020022802002204460d00200128020021030c010b200441016a22032004490d13200441017422022003200220034b1b22024100480d130240024020040d002002102821030c010b200128020020042002102c21030b2003450d1120012003360200200141046a2002360200200141086a28020021040b200141086a2202200441016a360200200320046a20002d00703a0000200028026c210302400240200141046a2802002204200228020022006b4104490d00200128020021040c010b200041046a22022000490d13200441017422002002200020024b1b22004100480d130240024020040d002000102821040c010b200128020020042000102c21040b2004450d1220012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20033600000f0b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200241011037000b200041011037000b1031000bb90201057f230041106b2203240020034100360208200342013703002001200310b4010240024002402001450d00200141b0016c2104034020004188016a28020021050240024020032802042206200328020822016b4104490d00200328020021060c010b200141046a22072001490d04200641017422012007200120074b1b22014100480d040240024020060d002001102821060c010b200328020020062001102c21060b2006450d032003200136020420032006360200200328020821010b2003200141046a360208200620016a20053600002000200310eb012000418c016a2003108f01200041b0016a2100200441d07e6a22040d000b0b2003280204210020022802002002280204200328020022012003280208100702402000450d002001102a0b200341106a24000f0b200141011037000b1031000bee1405177f017e017f027e047f230041206b220224000240024020014115490d0002402001410176220341ffffff3f712003470d0020034105742204417f4c0d0041012105024002402004450d00200410282205450d010b200041606a2106200041a07f6a210741002108410021094104210a4100210b2001210c034002400240200c220d417f6a220e0d004101210f4100210c0c010b0240024002400240024002402000200e4105746a200d410574221020006a41406a4120109c054100480d004102200d6b210e200720106a21044101210f03400240200e200f6a4101470d004100210c200d210f0c080b200f41016a210f200441206a20044120109c052111200441606a21042011417f4a0d000b200d200f6b210e0c010b200720106a2104024003400240200e4101470d004100210e0c020b200e417f6a210e200441206a20044120109c052111200441606a210420114100480d000b0b200d200e490d01200d20014b0d03200d200e6b220f4101762212450d00200620106a21042000200e4105746a21110340200241186a2210201141186a2213290000370300200241106a2214201141106a2215290000370300200241086a2216201141086a221729000037030020022011290000370300200441086a22182900002119200441106a221a290000211b200441186a220c290000211c201120042900003700002013201c3700002015201b37000020172019370000200c2010290300370000201a20142903003700002018201629030037000020042002290300370000200441606a2104201141206a21112012417f6a22120d000b0b0240200e0d00200e210c0c050b0240200f41094d0d00200e210c0c050b200d20014b0d01200d200e6b21122000200e4105746a21100340200d200e417f6a220c490d040240200d200c6b220f4102490d002000200e4105746a22042000200c4105746a220e4120109c05417f4a0d00200e2900002119200e2004290000370000200241186a2216200e41186a2211290000370300200241106a2217200e41106a2213290000370300200241086a2218200e41086a22142900003703002014200441086a2900003700002013200441106a2900003700002011200441186a29000037000020022019370300410121150240200f4103490d00200e41c0006a20024120109c05417f4a0d00410221112010210402400340200441186a200441386a290000370000200441106a200441306a290000370000200441086a200441286a2900003700002004200441206a221329000037000020122011460d01200441c0006a21142011211520132104201141016a2111201420024120109c05417f4a0d020c000b0b201121150b200e20154105746a22042002290300370000200441186a2016290300370000200441106a2017290300370000200441086a20182903003700000b200c450d05201041606a2110201241016a2112200c210e200f410a4f0d050c000b0b200e200d1044000b200d200e417f6a220c490d010b200d2001103c000b200c200d1044000b024002400240200b2009470d0002400240200941016a22042009490d00200941017422112004201120044b1b220441ffffffff01712004470d002004410374221141004e0d010b1031000b0240024020090d0020111028210a0c010b200a20094103742011102c210a0b200a450d01200421092008210b0b200a200b4103746a2204200f3602042004200c360200200841016a220b2108200b4102490d01024003400240024002400240200a200b417f6a22084103746a2204280200450d00200b410374200a6a220f41746a280200220e200428020422114d0d000240200b41024b0d00200b21084102210b0c080b200a200b417d6a22164103746a28020422042011200e6a4d0d010240200b41034b0d00200b21084103210b0c080b200f41646a2802002004200e6a4d0d01200b21080c070b200b4103490d0120042802042111200a200b417d6a22164103746a28020421040b20042011490d010b200b417e6a21160b024002400240024002400240200b201641016a221d4b221e450d00200b20164b221f450d01200a20164103746a2217280204222020172802006a2204200a201d4103746a2218280200221a490d02200420014b0d032000201a4105746a22142018280204221541057422116a210f2004410574210e2004201a6b220d20156b220420154f0d042005200f20044105742211109a05221320116a21120240024020154101480d00200441014e0d010b200f2104201321110c060b2006200e6a210e200f21040340200e200441606a220f201241606a220d200d200f4120109c0541004822101b2211290000370000200e41186a201141186a290000370000200e41106a201141106a290000370000200e41086a201141086a2900003700002012200d20101b211202402014200f200420101b2204490d00201321110c070b200e41606a210e2013211120132012490d000c060b0b41b8dbc000201d200b1034000b41b8dbc0002016200b1034000b201a20041044000b20042001103c000b200520142011109a05221320116a21120240024020154101480d00200d20154a0d010b20142104201321110c010b2000200e6a2110201321112014210403402004200f2011200f20114120109c05410048220d1b220e290000370000200441186a200e41186a290000370000200441106a200e41106a290000370000200441086a200e41086a2900003700002011201141206a200d1b2111200441206a2104200f41206a200f200d1b220f20104f0d01201220114b0d000b0b20042011201220116b416071109a051a0240201f450d002017201a360200201741046a202020156a360200201e450d022018201841086a200b201d417f736a410374109b051a2008210b200841014d0d040c010b0b41c8dbc0002016200b1034000b41b0b1c0001032000b201141041037000b200c0d000b02402009450d00200a102a0b2003450d032005102a0c030b200441011037000b1036000b20014102490d002001417f6a2111200141057420006a41206a2110410121120340024002400240024020112204417f6a221120014b0d00200120116b220e4102490d03200020044105746a2204200020114105746a220d4120109c05417f4a0d03200d2900002119200d2004290000370000200241186a2214200d41186a220f290000370300200241106a220b200d41106a2213290000370300200241086a2215200d41086a220a290000370300200a200441086a2900003700002013200441106a290000370000200f200441186a2900003700002002201937030041012104200e4103490d02200d41c0006a20024120109c05417f4a0d0241002113201021040340200441406a220e200441606a220f290000370000200e41186a200f41186a290000370000200e41106a200f41106a290000370000200e41086a200f41086a29000037000020122013220e460d02200e417f6a2113200420024120109c05210f200441206a2104200f417f4a0d020c000b0b201120011044000b4102200e6b21040b200d20044105746a22042002290300370000200441186a2014290300370000200441106a200b290300370000200441086a20152903003700000b201041606a21102012417f6a211220110d000b0b200241206a24000ba3950103057f027e027f230041106b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000e10000102030405060708090a0b0c0d0e0f000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200141046a28020021042005280200210302402000410c6a2d000022054102470d000240024020042003460d00200128020021000c010b200341016a22002003490d5d200341017422042000200420004b1b22044100480d5d0240024020030d002004102821000c010b200128020020032004102c21000b2000450d1320012000360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000c100b0240024020042003460d00200128020021040c010b200341016a22042003490d5c200341017422062004200620044b1b22064100480d5c0240024020030d002006102821040c010b200128020020032006102c21040b2004450d1320012004360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200420036a41013a00000240024020054101460d0002400240200141046a28020020062802002203460d00200128020021040c010b200341016a22042003490d5e200341017422052004200520044b1b22054100480d5e0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a00000c010b02400240200141046a28020020062802002203460d00200128020021040c010b200341016a22042003490d5d200341017422052004200520044b1b22054100480d5d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5d200341017422052004200520044b1b22054100480d5d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d000d3a00000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d000e3a00000c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041086a2001108f012000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d5b200341017422002005200020054b1b22004100480d5b0240024020030d002000102821030c010b200128020020032000102c21030b2003450d1920012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a200341017422052004200520044b1b22054100480d5a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a000020002d0008220341024b0d0d02400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5c200341017422052004200520044b1b22054100480d5c0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041096a2001108f01200041386a29030021072000290330210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5c200341017422002004200020044b1b22004100480d5c0240024020030d002000102821030c010b200128020020032000102c21030b2003450d1d20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0f0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041096a2001108f010c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a200341017422052004200520044b1b22054100480d5a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d1d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200041096a2001108f01200041296a2001108f01200041d8006a29030021072000290350210802400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d5a200441017422032005200320054b1b22034100480d5a0240024020040d002003102821040c010b200128020020042003102c21040b2004450d1e20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341106a360200200420036a2203200737000820032008370000200041e8006a29030021072000290360210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5a200341017422002004200020044b1b22004100480d5a0240024020030d002000102821030c010b200128020020032000102c21030b2003450d1f20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d1f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002d0008220341024b0d0c02400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5b200341017422052004200520044b1b22054100480d5b0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5b200341017422002004200020044b1b22004100480d5b0240024020030d002000102821030c010b200128020020032000102c21030b2003450d2320012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0e0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d5a200341017422052004200520044b1b22054100480d5a0240024020030d002005102821040c010b200128020020032005102c21040b2004450d2320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041096a2001108f01200041386a29030021072000290330210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d5a200341017422002004200020044b1b22004100480d5a0240024020030d002000102821030c010b200128020020032000102c21030b2003450d2420012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c0d0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d2420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d59200341017422002005200020054b1b22004100480d590240024020030d002000102821030c010b200128020020032000102c21030b2003450d2520012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0c0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d2520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d2620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280204210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d58200341017422002005200020054b1b22004100480d580240024020030d002000102821030c010b200128020020032000102c21030b2003450d2720012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c0b0b02400240200141046a2206280200200141086a22042802002203460d00200128020021050c010b200341016a22052003490d57200341017422092005200920054b1b22094100480d570240024020030d002009102821050c010b200128020020032009102c21050b2005450d2720012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41053a000020002d00082203410a4b0d0a0240024002400240024002400240024002400240024020030e0b000102030405060708090a000b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d61200341017422092005200920054b1b22094100480d610240024020030d002009102821050c010b200128020020032009102c21050b2005450d3220012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41003a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d6120054101742203200a2003200a4b1b22034100480d610240024020050d002003102821050c010b200128020020052003102c21050b2005450d3320012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2009360000200041186a2903002107200029031021080240024020062802002203200428020022006b4110490d00200128020021030c010b200041106a22052000490d61200341017422002005200020054b1b22004100480d610240024020030d002000102821030c010b200128020020032000102c21030b2003450d3420012003360200200141046a2000360200200141086a28020021000b2004200041106a360200200320006a22012007370008200120083700000c140b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d60200341017422092005200920054b1b22094100480d600240024020030d002009102821050c010b200128020020032009102c21050b2005450d3420012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41013a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d6020054101742203200a2003200a4b1b22034100480d600240024020050d002003102821050c010b200128020020052003102c21050b2005450d3520012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a2009360000200041286a2903002107200029032021080240024020062802002205200428020022036b4110490d00200128020021040c010b200341106a22042003490d60200541017422032004200320044b1b22034100480d600240024020050d002003102821040c010b200128020020052003102c21040b2004450d3620012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a220320073700082003200837000020002802102103200041186a2802002200200110b4012000450d1320004105742100034020032001108f01200341206a2103200041606a22000d000c140b0b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5f200041017422052003200520034b1b22054100480d5f0240024020000d002005102821030c010b200128020020002005102c21030b2003450d3620012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c120b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5e200341017422092005200920054b1b22094100480d5e0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3620012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41033a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5e20054101742203200a2003200a4b1b22034100480d5e0240024020050d002003102821050c010b200128020020052003102c21050b2005450d3720012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200936000020002d0009220041024b0d1102400240024020000e03000102000b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d60200041017422052003200520034b1b22054100480d600240024020000d002005102821030c010b200128020020002005102c21030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41003a00000c130b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5f200041017422052003200520034b1b22054100480d5f0240024020000d002005102821030c010b200128020020002005102c21030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41013a00000c120b02400240200628020020042802002200460d00200128020021030c010b200041016a22032000490d5e200041017422052003200520034b1b22054100480d5e0240024020000d002005102821030c010b200128020020002005102c21030b2003450d3a20012003360200200141046a2005360200200141086a28020021000b2004200041016a360200200320006a41023a00000c110b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5d200341017422092005200920054b1b22094100480d5d0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3a20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41043a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d5d200341017422002006200020064b1b22004100480d5d0240024020030d002000102821030c010b200128020020032000102c21030b2003450d3b20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c100b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5c200341017422092005200920054b1b22094100480d5c0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3b20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41053a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d5c200341017422002006200020064b1b22004100480d5c0240024020030d002000102821030c010b200128020020032000102c21030b2003450d3c20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0f0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5b200341017422092005200920054b1b22094100480d5b0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3c20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41063a0000200028020c21050240024020062802002203200428020022006b4104490d00200128020021030c010b200041046a22062000490d5b200341017422002006200020064b1b22004100480d5b0240024020030d002000102821030c010b200128020020032000102c21030b2003450d3d20012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0e0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5a200341017422092005200920054b1b22094100480d5a0240024020030d002009102821050c010b200128020020032009102c21050b2005450d3d20012005360200200141046a2009360200200141086a28020021030b2004200341016a360200200520036a41073a0000200028020c21090240024020062802002205200428020022036b4104490d00200128020021050c010b200341046a220a2003490d5a20054101742203200a2003200a4b1b22034100480d5a0240024020050d002003102821050c010b200128020020052003102c21050b2005450d3e20012005360200200141046a2003360200200141086a28020021030b2004200341046a360200200520036a200936000002400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d5a200341017422062005200620054b1b22064100480d5a0240024020030d002006102821050c010b200128020020032006102c21050b2005450d3f20012005360200200141046a2006360200200141086a28020021030b2004200341016a360200200520036a20002d00093a00000c0d0b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d59200341017422052004200520044b1b22054100480d590240024020030d002005102821040c010b200128020020032005102c21040b2004450d3f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41083a0000200041096a2001108f01200041296a2001108f010c0c0b02400240200628020020042802002203460d00200128020021040c010b200341016a22042003490d58200341017422052004200520044b1b22054100480d580240024020030d002005102821040c010b200128020020032005102c21040b2004450d3f20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a0000200041096a2001108f010c0b0b02400240200628020020042802002203460d00200128020021050c010b200341016a22052003490d57200341017422062005200620054b1b22064100480d570240024020030d002006102821050c010b200128020020032006102c21050b2005450d3f20012005360200200141046a2006360200200141086a28020021030b200141086a2206200341016a360200200520036a410a3a0000200041096a2001108f0120022001360208200041296a200241086a10c801200028024c210502400240200141046a2802002203200628020022006b4104490d00200128020021030c010b200041046a22062000490d57200341017422002006200020064b1b22004100480d570240024020030d002000102821030c010b200128020020032000102c21030b2003450d4020012003360200200141046a2000360200200141086a28020021000b2004200041046a360200200320006a20053600000c0a0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d56200341017422052004200520044b1b22054100480d560240024020030d002005102821040c010b200128020020032005102c21040b2004450d4020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41063a0000200041046a200110f2010c090b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d55200341017422052004200520044b1b22054100480d550240024020030d002005102821040c010b200128020020032005102c21040b2004450d4020012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41073a0000200041046a200110f2010c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d54200341017422052004200520044b1b22054100480d540240024020030d002005102821040c010b200128020020032005102c21040b2004450d4020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41083a0000024002400240024020002d00040e0400010203000b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d57200341017422052004200520044b1b22054100480d570240024020030d002005102821040c010b200128020020032005102c21040b2004450d4420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041056a2001108f01200041256a2001108f010c0a0b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d56200341017422052004200520044b1b22054100480d560240024020030d002005102821040c010b200128020020032005102c21040b2004450d4420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041056a2001108f010c090b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d55200341017422052004200520044b1b22054100480d550240024020030d002005102821040c010b200128020020032005102c21040b2004450d4420012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a00002000280208210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d55200341017422002005200020054b1b22004100480d550240024020030d002000102821030c010b200128020020032000102c21030b2003450d4520012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c080b02400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d54200341017422052004200520044b1b22054100480d540240024020030d002005102821040c010b200128020020032005102c21040b2004450d4520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a000020002802082103200041106a2802002204200110b40102402004450d0020044105742104034020032001108f01200341206a2103200441606a22040d000b0b200028021421032000411c6a2802002200200110b4012000450d0720004105742100034020032001108f01200341206a2103200041606a22000d000c080b0b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d53200341017422052004200520044b1b22054100480d530240024020030d002005102821040c010b200128020020032005102c21040b2004450d4520012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41093a000020002d0001220041044b0d060240024002400240024020000e050001020304000b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d57200041017422042003200420034b1b22044100480d570240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41003a00000c0a0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d56200041017422042003200420034b1b22044100480d560240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c090b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d55200041017422042003200420034b1b22044100480d550240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c080b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d54200041017422042003200420034b1b22044100480d540240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41033a00000c070b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d53200041017422042003200420034b1b22044100480d530240024020000d002004102821030c010b200128020020002004102c21030b2003450d4a20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41043a00000c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d52200341017422052004200520044b1b22054100480d520240024020030d002005102821040c010b200128020020032005102c21040b2004450d4a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410a3a00002000280204220341024b0d0502400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d54200341017422052004200520044b1b22054100480d540240024020030d002005102821040c010b200128020020032005102c21040b2004450d4d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000020002802082103200041106a2802002200200110b4012000450d072003200041286c6a210a200141046a2106034020032001108f01200341206a29030021070240024020062802002204200528020022006b4108490d00200128020021040c010b200041086a22092000490d55200441017422002009200020094b1b22004100480d550240024020040d002000102821040c010b200128020020042000102c21040b2004450d4f2001200436020020062000360200200528020021000b2005200041086a360200200420006a2007370000200a200341286a2203470d000c080b0b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d53200041017422042003200420034b1b22044100480d530240024020000d002004102821030c010b200128020020002004102c21030b2003450d4e20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41013a00000c060b02400240200141046a280200200141086a2802002200460d00200128020021030c010b200041016a22032000490d52200041017422042003200420034b1b22044100480d520240024020000d002004102821030c010b200128020020002004102c21030b2003450d4e20012003360200200141046a2004360200200141086a28020021000b200141086a200041016a360200200320006a41023a00000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d51200341017422052004200520044b1b22054100480d510240024020030d002005102821040c010b200128020020032005102c21040b2004450d4e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410b3a000020002d0008220341044b0d040240024002400240024020030e050001020304000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d55200341017422052004200520044b1b22054100480d550240024020030d002005102821040c010b200128020020032005102c21040b2004450d5320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d55200341017422002005200020054b1b22004100480d550240024020030d002000102821030c010b200128020020032000102c21030b2003450d5420012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d74200341017422052004200520044b1b22054100480d740240024020030d002005102821040c010b200128020020032005102c21040b2004450d5520012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d74200341017422002004200020044b1b22004100480d740240024020030d002000102821030c010b200128020020032000102c21030b2003450d5620012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d73200341017422052004200520044b1b22054100480d730240024020030d002005102821040c010b200128020020032005102c21040b2004450d5620012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a0000200028022c210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d73200441017422032005200320054b1b22034100480d730240024020040d002003102821040c010b200128020020042003102c21040b2004450d5720012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a2006360000200041386a29030021072000290330210802400240200141046a2802002204200528020022036b4110490d00200128020021040c010b200341106a22052003490d73200441017422032005200320054b1b22034100480d730240024020040d002003102821040c010b200128020020042003102c21040b2004450d5820012004360200200141046a2003360200200141086a28020021030b200141086a200341106a360200200420036a2203200737000820032008370000200041096a2001108f010c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d72200341017422052004200520044b1b22054100480d720240024020030d002005102821040c010b200128020020032005102c21040b2004450d5820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d72200341017422002004200020044b1b22004100480d720240024020030d002000102821030c010b200128020020032000102c21030b2003450d5920012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d5920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041186a29030021072000290310210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d71200341017422002004200020044b1b22004100480d710240024020030d002000102821030c010b200128020020032000102c21030b2003450d5a20012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d70200341017422052004200520044b1b22054100480d700240024020030d002005102821040c010b200128020020032005102c21040b2004450d5a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410c3a000020002d0008220341054b0d0302400240024002400240024020030e06000102030405000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d75200341017422052004200520044b1b22054100480d750240024020030d002005102821040c010b200128020020032005102c21040b2004450d6020012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041096a2001108f01200041296a2001108f01200041d8006a29030021072000290350210802400240200141046a2802002203200528020022006b4110490d00200128020021030c010b200041106a22042000490d75200341017422002004200020044b1b22004100480d750240024020030d002000102821030c010b200128020020032000102c21030b2003450d6120012003360200200141046a2000360200200141086a28020021000b200141086a200041106a360200200320006a22012007370008200120083700000c080b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d74200341017422052004200520044b1b22054100480d740240024020030d002005102821040c010b200128020020032005102c21040b2004450d6120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041096a2001108f01200041296a2001108f010c070b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d73200341017422052004200520044b1b22054100480d730240024020030d002005102821040c010b200128020020032005102c21040b2004450d6120012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200136020c200041096a2002410c6a10c8010c060b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d72200341017422052004200520044b1b22054100480d720240024020030d002005102821040c010b200128020020032005102c21040b2004450d6120012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41033a0000200028020c210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d72200341017422002005200020054b1b22004100480d720240024020030d002000102821030c010b200128020020032000102c21030b2003450d6220012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6220012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a0000200041096a2001108f0102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6320012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00293a00000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d70200341017422052004200520044b1b22054100480d700240024020030d002005102821040c010b200128020020032005102c21040b2004450d6320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a0000200041096a2001108f01200028022c2106200041346a2802002200200110b40102400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d70200441017422032005200320054b1b22034100480d700240024020040d002003102821040c010b200128020020042003102c21040b2004450d6420012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a20062000109a051a0c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6f200341017422052004200520044b1b22054100480d6f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a410d3a000020002d0001220341024b0d0202400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d71200341017422052004200520044b1b22054100480d710240024020030d002005102821040c010b200128020020032005102c21040b2004450d6820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00023a00000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d70200341017422052004200520044b1b22054100480d700240024020030d002005102821040c010b200128020020032005102c21040b2004450d6820012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a0000200041026a2001108f010c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6f200341017422052004200520044b1b22054100480d6f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6820012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41023a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d6f200341017422052004200520044b1b22054100480d6f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6920012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00023a00000c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6e200341017422052004200520044b1b22054100480d6e0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410e3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d6e200341017422052004200520044b1b22054100480d6e0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41003a0000200041016a2001108f010c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d6d200341017422052004200520044b1b22054100480d6d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a410f3a000002400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d6d200341017422052004200520044b1b22054100480d6d0240024020030d002005102821040c010b200128020020032005102c21040b2004450d6b20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041106a200110c601200028020421062000410c6a2802002200200110b40102400240200141046a2802002204200528020022036b2000490d00200128020021040c010b200320006a22052003490d6d200441017422032005200320054b1b22034100480d6d0240024020040d002003102821040c010b200128020020042003102c21040b2004450d6c20012004360200200141046a2003360200200141086a28020021030b200141086a200320006a360200200420036a20062000109a051a0b200241106a24000f0b200541011037000b200441011037000b200641011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200341011037000b200041011037000b200541011037000b200541011037000b200041011037000b200541011037000b200041011037000b200541011037000b200041011037000b200541011037000b200541011037000b200041011037000b200941011037000b200941011037000b200341011037000b200041011037000b200941011037000b200341011037000b200341011037000b200541011037000b200941011037000b200341011037000b200541011037000b200541011037000b200541011037000b200941011037000b200041011037000b200941011037000b200041011037000b200941011037000b200041011037000b200941011037000b200341011037000b200641011037000b200541011037000b200541011037000b200641011037000b200041011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200541011037000b200541011037000b200041011037000b200441011037000b200441011037000b200541011037000b200541011037000b200041011037000b1031000b200541011037000b200041011037000b200541011037000b200341011037000b200341011037000b200541011037000b200041011037000b200541011037000b200041011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200541011037000b200041011037000b200541011037000b200541011037000b200541011037000b200341011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200341011037000b1031000bfd1201057f230041106b2202240002400240024002400240024002400240024002400240024002400240024020002d0000220341054b0d0002400240024002400240024020030e06000102030405000b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d14200341017422052004200520044b1b22054100480d140240024020030d002005102821040c010b200128020020032005102c21040b2004450d0720012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a0000200041016a2001108f012000280244210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d14200441017422032005200320054b1b22034100480d140240024020040d002003102821040c010b200128020020042003102c21040b2004450d0820012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a20063600002002200136020c200041216a2002410c6a10c8012000280248210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d14200341017422002005200020054b1b22004100480d140240024020030d002000102821030c010b200128020020032000102c21030b2003450d0920012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c050b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102821040c010b200128020020032005102c21040b2004450d0920012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41013a0000200041016a2001108f012002200136020c200041216a2002410c6a10c80102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d13200341017422052004200520044b1b22054100480d130240024020030d002005102821040c010b200128020020032005102c21040b2004450d0a20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a20002d00413a00002000280244210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d13200441017422032005200320054b1b22034100480d130240024020040d002003102821040c010b200128020020042003102c21040b2004450d0b20012004360200200141046a2003360200200141086a28020021030b200141086a2205200341046a360200200420036a20063600002000280248210402400240200141046a2802002203200528020022006b4104490d00200128020021030c010b200041046a22052000490d13200341017422002005200020054b1b22004100480d130240024020030d002000102821030c010b200128020020032000102c21030b2003450d0c20012003360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200320006a20043600000c040b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102821040c010b200128020020032005102c21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41023a00002002200136020c200041016a2002410c6a10c8010c030b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d11200341017422052004200520044b1b22054100480d110240024020030d002005102821040c010b200128020020032005102c21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41033a00002002200136020c200041016a2002410c6a10c8010c020b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102821040c010b200128020020032005102c21040b2004450d0c20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41043a00002002200136020c200041016a2002410c6a10c80102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d10200341017422052004200520044b1b22054100480d100240024020030d002005102821040c010b200128020020032005102c21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00213a00000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d0d20012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41053a00002002200136020c200041016a2002410c6a10c80102400240200141046a28020020052802002203460d00200128020021040c010b200341016a22042003490d0f200341017422052004200520044b1b22054100480d0f0240024020030d002005102821040c010b200128020020032005102c21040b2004450d0e20012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a20002d00213a00000b200241106a24000f0b200541011037000b200341011037000b200041011037000b200541011037000b200541011037000b200341011037000b200041011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1031000bf40501027f4190ce0021024100210302400240024002400240024002400240024002400240024002400240024020012802000e15000e08080e01020304050607090e0e0a0e0c0e0e0e000b417f2102200141086a280200417f6a220141054b0d0a41012103024020010e060e0b0d000d0d0e0b41c09a0c21020c0d0b200141086a280200417f6a220141024b0d0941c0843d210241002103024020010e030d000d0d0b4101210341d0860321020c0c0b200141086a2d0000417f6a2201410c4b0d0841a0c21e21024100210302400240024020010e0d0e0e000001010e0e01020808080e0b4180b5182102410021030c0d0b41b0e32d2102410021030c0c0b4101210341f0930921020c0b0b41f093092102410021030c0a0b200141086a2d0000417f6a220141104b0d0641c096b102210241002103024002400240024020010e110d0d0101000d0d0d0101070702020203030d0b4101210341a0c21e21020c0c0b41c09a0c2102410021030c0b0b41a08d062102410021030c0a0b41a0c21e2102410021030c090b20012d0004417f6a220141034b0d054101210341a08d0621020240024020010e040a0a00010a0b41c096b10221020c090b41c09a0c21020c080b20012d0004417f6a220141034b0d044101210341a08d0621020240024020010e0409090001090b41c096b10221020c080b41c09a0c21020c070b200141086a280200417f6a220141094b0d0341a0cb98012102410021030240024020010e0a08080800080102020202080b41d0a5cc002102410021030c070b4180ade2042102410021030c060b410121030c040b41d086034190ce0020012d0004411d7441808080807e6a411d75417f4a1b2102410021030c040b200141086a280200417f6a220141024b0d0041a0c21e210241002103024020010e03040000040b4101210341a08d0621020c030b4190ce002102410021030c020b02402001280204417f6a220141024b0d00410121034100210220010e03020002020b410021030b4190ce0021020b200020033a0004200020023602000be6fe0109017f017e067f017e047f017e0a7f037e177f230041d0076b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e15000102031e1c1b1a191817160f0e0d0c0b0a090807000b200141106a29030021042001410c6a280200210520022d0001210620022d000021020240024002400240024002400240200141086a28020022070e0700060102030405000b200341d4066a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a4188a6c300103e000b2004a7210702400240200241ff01710d00200641ff01714101460d010b2007450d2d2005102a0c2d0b2007450d2a2005102a0c2a0b200220067241ff01710d2a410810282202450d09200220043700004198a6c300410a2002410810072002102a0c290b2004a721070240200220067241ff0171450d002007450d2a2005102a0c2a0b41a2a6c300410520052004422088a710072007450d282005102a0c280b2004422088a721082004a721090240200220067241ff0171450d0002402008450d00200841186c21062005210203400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b410121064100210a4105210820090d260c270b0240200841186c2202450d00200520026a21062005210203402002280200200241086a2802002002410c6a280200200241146a2802001007200241186a22022006470d000b0b02402008450d00200841186c21062005210203400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b410121064100210a4107210820090d250c260b2004422088a721082004a721090240200220067241ff0171450d0002402008450d002008410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b410021064101210a410521082009450d260c250b02402008410c6c2202450d00200520026a21062005210203402002280200200241086a28020010092002410c6a22022006470d000b0b02402008450d002008410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b410021064101210a4107210820090d240c250b200220067241ff01710d260c250b10f501000b024020022d00000d0020022d000141ff01714102470d00200141086a290300210420034180056a41086a22024200370300200342003703800541d8a1c600411320034180056a1008200341b8026a41086a2206200229030037030020032003290380053703b8020240200341b8026a41104101410041001003417f470d0020024200370300200342003703800541feb3c300410d20034180056a10082006200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621020240024020032802c0062206417f460d002002450d0020064108490d012002290000210b2002102a200b500d004200210b20034180056a41086a22024200370300200342003703800541feb3c300410d20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a10062102024020032802c0062206417f460d002002450d0020064108490d072002290000210b2002102a0b200b42dc0b7c2004560d050b20034180056a41086a22024200370300200342003703800541feb3c300410d20034180056a1008200341b8026a41086a2206200229030037030020032003290380053703b802200320043703c006200341b8026a4110200341c0066a4108100741012105200341013a00c00620024200370300200342003703800541d8a1c600411320034180056a10082006200229030037030020032003290380053703b802200341b8026a4110200341c0066a41011007200041023a0008410121060c2b0b41c4d1c3004133200341c8076a419cd9c3001038000b41c8adc3001032000b20004181043b01082000410f360204200041ea9fc6003602002000410a6a41003a00000c1a0b2001410c6a2802002105200141086a280200210c2001280204210d41ea9fc600210e410f210f20022d00000d1e20022d000141ff01714102470d1e20034180056a41086a22024200370300200342003703800541c8fbc500411720034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a10062102024002400240024020032802c0062206417f460d002002450d002006450d0120022d000021062002102a20064102460d002006410171450d0041a4cdc200210e411c210f0c220b200341013a00c00620034180056a41086a22024200370300200342003703800541c8fbc500411720034180056a1008200341b8026a41086a2206200229030037030020032003290380053703b802200341b8026a4110200341c0066a4101100710980121082002420037030020034200370380054193cdc200411120034180056a10082006200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a1006210202400240024020032802c0062206417f460d002002450d0020032006360294012003200236029001200341c0066a20034190016a107b20032802c0062207450d0520032902c406210402402006450d002002102a0b200320073602980302402004422088220ba722022004a7470d00200341c0066a21060c020b200341c0066a21060c020b4104210720034104360298034200210441002102200341c0066a21060b024020022004a7470d00200241016a220a2002490d1120024101742209200a2009200a4b1bad220b42c4007e2210422088a70d112010a7220a4100480d110240024020020d00200a102821070c010b2007200241c4006c200a102c21070b2007450d032003200736029803200442808080807083200b8421040b2004422088220ba721020b2007200241c4006c6a22022008360204200241003a000020022006290200370208200241106a200641086a290200370200200241186a200641106a290200370200200241206a200641186a290200370200200241286a200641206a290200370200200241306a200641286a290200370200200241386a200641306a290200370200200241c0006a200641386a280200360200200b422086200442ffffffff0f83844280808080107c2104200d200541f0006c6a2108024020050d00200d21070c200b200341e0056a417f6a210a20034193046a2111200341d7046a21122003419b056a2113200341c0066a41106a2114200341c0066a41086a211520034180056a41186a2116200d2107024003402007280204210220072802002106200341c0066a200741086a41e800109a051a200741f0006a21072002450d2120034190016a200341c0066a41e800109a051a200320023602c406200320063602c006201520034190016a41e800109a051a20032802980321171098012102200341e0056a200341c0066a10f60102400240024020032802c00622060d0041d6cdc200210e4110210f0c010b0240200620024d0d00411a210f41e6cdc200210e0c010b20034198046a2006417f6a10f701024020034198046a20144120109c05450d004119210f4180cec200210e0c010b024020032802c006221841002002417b6a2206200620024b1b4f0d004126210f4199cec200210e0c010b20172004422088220ba7220941c4006c22196a21052017210202400240201941cd01490d00201721020340024020022d00004101470d00200241016a2106200a2002460d032006200341e0056a4120109c05450d030b0240200241c4006a2d00004101470d00200241c5006a210620132002460d032006200341e0056a4120109c05450d030b024020024188016a2d00004101470d0020024189016a210620122002460d032006200341e0056a4120109c05450d030b0240200241cc016a2d00004101470d00200241cd016a210620112002460d032006200341e0056a4120109c05450d030b200520024190026a22026b41cc014b0d000b0b024020022005460d000340024020022d00004101470d00200241016a2106200a2002460d032006200341e0056a4120109c05450d030b2005200241c4006a2202470d000b0b410021060b20034198046a201810f70120034198046a200341e0056a4120109c052102200341b8036a41086a221a20034180056a41086a2205290200370300200341b8036a41106a20034180056a41106a221829020037030020032003290280053703b80341c0cdc200210e4116210f20060d2220020d010c220b200341b8036a41086a20034180056a41086a290200370300200341b8036a41106a20034180056a41106a29020037030020032003290280053703b8030c210b200341b8026a410e6a2206200341b8036a410e6a290100370100200341b8026a41086a220e201a290300370300200320032903b8033703b80220034198046a200341c0066a10f6012016420037030020184200370300200542003703002003420037038005024041c80010282202450d0020034198026a10f8012002410236022020024101360244200241186a20034198026a41186a290300370200200241106a20034198026a41106a290300370200200241086a20034198026a41086a290300370200200220032903980237020020022003290380053700242002412c6a2005290300370000200241346a20182903003700002002413c6a2016290300370000200320023602e00520034282808080203702e405200341e0056a10f901200341f8016a41086a220520034198046a41086a290300370300200341f8016a41106a221820034198046a41106a290300370300200341f8016a41186a220f20034198046a41186a290300370300200341e0056a41086a221a200e290300370300200341e0056a410e6a220e200629010037010020032003290398043703f801200320032903b8023703e0050240024020092004a7460d00200421100c010b200941016a22022009490d13200ba74101742206200220022006491bad221042c4007e220b422088a70d13200ba722064100480d130240024020090d002006102821020c010b201720192006102c21020b2002450d0320032002360298032004422088220ba721090b200328029803200941c4006c6a220241013a0000200f29030021042018290300211b2005290300211c20032903f801211d20024116360028200241c0cdc200360024200241003a00212002413a6a200e290100370000200241346a201a290300370000200220032903e00537002c2002201d370001200241096a201c370000200241116a201b370000200241196a2004370000201042ffffffff0f832104200b422086210b024020032802cc062206450d0020032802c4062102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200b2004842104024020032802c806450d0020032802c406102a0b20044280808080107c210420072008470d010c230b0b41c80041041037000b200641041037000b41c4d1c3004133200341c8076a419cd9c3001038000b200a41041037000b41c4d1c3004133200341c8076a419cd9c3001038000b4190aec3001032000b41c4d1c3004133200341c8076a419cd9c3001038000b410841011037000b10d601000b10fa01000b200141246a280200211a200141206a280200210f2001411c6a280200210a200141186a2802002118200141146a2802002109200141106a28020021132001410c6a280200210e200141086a280200211920022d0001210620022d000021022001280204210820034190016a41386a200141e0006a29000037030020034190016a41306a200141d8006a29000037030020034190016a41286a200141d0006a29000037030020034190016a41206a200141c8006a29000037030020034190016a41186a200141c0006a29000037030020034190016a41106a200141386a29000037030020034190016a41086a200141306a2900003703002003200141286a2900003703900141ea9fc6002105410f21070240024020020d00200641ff01714102470d00024010fb01200f460d0041fb91c1002105411c21070c010b200341c0066a200f201a10fc0120032802c006220220032802c80641014100410010032106024020032802c406450d002002102a0b20034180056a41086a22024200370300200342003703800541c2e1c000410d20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a1006210202400240024002400240024002400240024002400240024020032802c0062205417f460d002002450d002003200536029c042003200236029804200341c0066a20034198046a107c20032802c006220c450d0220032902c40621042005450d012002102a0c010b420021044101210c0b02402006417f460d0041b392c1002105411521070c030b200c201a4105746a4100201a2004422088a7491b22120d0141c892c1002105411821070c020b41c4d1c3004133200341c8076a419cd9c3001038000b200341003602c806200342013703c00602400240024002400240410410282202450d0020034284808080c0003702c406200320023602c006200220083600002013200341c0066a10b4010240024020032802c406220620032802c80622026b2013490d0020032802c00621060c010b200220136a22052002490d16200641017422072005200720054b1b22054100480d160240024020060d002005102821060c010b20032802c00620062005102c21060b2006450d02200320053602c406200320063602c0060b2003200220136a3602c806200620026a20192013109a051a200a200341c0066a10b4012009200a410c6c6a2116200a450d0220092106034020062802002117200641086a2802002202200341c0066a10b4010240024020032802c406220720032802c80622056b2002490d0020032802c00621080c010b200520026a22082005490d172007410174220d2008200d20084b1b220d4100480d170240024020070d00200d102821080c010b20032802c0062007200d102c21080b2008450d052003200d3602c406200320083602c006200d21070b2003200520026a220d3602c806200820056a20172002109a051a2006410c6a22062016470d000c050b0b410441011037000b200541011037000b20032802c406210720032802c806210d0c010b200d41011037000b024002402007200d6b4104490d0020032802c00621020c010b200d41046a2202200d490d11200741017422062002200620024b1b22064100480d110240024020070d002006102821020c010b20032802c00620072006102c21020b2002450d03200320063602c406200320023602c006200621070b2003200d41046a22063602c8062002200d6a200f36000002400240200720066b41034d0d00200721050c010b200641046a22052006490d11200741017422082005200820054b1b22054100480d110240024020070d002005102821020c010b200220072005102c21020b2002450d04200320053602c406200320023602c0060b200220066a201a3600002002200d41086a20034190016a2012100a210602402005450d002002102a0b2006450d01419792c1002105411c21070b2004a7450d07200c102a0c070b201241086a290000210b201241106a29000021102012290000211b20034198026a41186a201241186a290000221c37030020034198026a41106a201037030020034198026a41086a200b3703002003201b37039802200341c9066a200b370000200341d1066a2010370000200341d9066a201c3700002003410e3a00c0062003201b3700c10641014100200341c0066a10cc01200341003602c806200342013703c0062013200341c0066a10b4010240024020032802c406220620032802c80622026b2013490d0020032802c00621060c010b200220136a22052002490d0f200641017422072005200720054b1b22054100480d0f0240024020060d002005102821060c010b20032802c00620062005102c21060b2006450d03200320053602c406200320063602c0060b2003200220136a3602c806200620026a20192013109a051a200a200341c0066a10b401200a450d0320092106034020062802002117200641086a2802002202200341c0066a10b4010240024020032802c406220820032802c80622056b2002490d0020032802c00621070c010b200520026a22072005490d102008410174220d2007200d20074b1b220d4100480d100240024020080d00200d102821070c010b20032802c0062008200d102c21070b2007450d062003200d3602c406200320073602c006200d21080b2003200520026a220d3602c806200720056a20172002109a051a2006410c6a22062016470d000c060b0b200641011037000b200541011037000b200541011037000b20032802c806210d20032802c406210820032802c00621070c010b200d41011037000b200341c0066a200f201a10fc0120032802c0062102200320032802c80636029c0420032002360298042007200d20034198046a10cb01024020032802c406450d002002102a0b02402008450d002007102a0b02402004a7450d00200c102a0b0240200e450d002019102a0b0240200a450d00200a410c6c21062009210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b02402018450d002009102a0b200041023a0008410021160c010b0240200e450d002019102a0b0240200a450d00200a410c6c21062009210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b02402018450d002009102a0b20004181243b01082000200736020420002005360200410021162000410a6a41003a00000b410121054101210641012107410121084101210a41012109410121174101210d410121184101210e4101210f410121190c2b0b2002411a6a2901002104200241196a2d00002119200241186a2d00002116200241166a2f0100211a200241156a2d00002113200241146a2d0000210c200241126a2f01002112200241116a2d00002111200241106a2d000021092002410e6a2f010021172002410d6a2d0000210d2002410c6a2d000021182002410a6a2f0100210e200241096a2d0000210f200241086a2d00002106200241066a2f01002105200241056a2d00002107200241046a2d00002115200241026a2f01002114200141216a290000210b200141206a2d0000211e2001411d6a2f0000211f2001411c6a2d00002120200141196a2f00002121200141186a2d00002122200141156a2f00002123200141146a2d00002124200141116a2f00002125200141106a2d000021262001410c6a2802002127200141086a280200210a20022d0001210820022d0000210220012d001f212820012d001b212920012d0017212a20012d0013212b024002400240024002400240024002400240024020012802040e0400010203000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41b49dc400103e000b410420054108742006411874722007724104200841ff017141014622061b200241ff017122021b21050240024020020d0020060d010b410f210641ea9fc600210202400240024002400240024020050e070001020304050a000b200e410874200f7220184118747221022017410874200d7220094118747221060c090b410e210641dc9fc60021020c080b410c210641d09fc60021020c070b4109210641c79fc60021020c060b4113210641b49fc60021020c050b4111210641a39fc60021020c040b200320043703b004200320193a00af04200320163a00ae042003201a3b01ac04200320133a00ab042003200c3a00aa04200320123b01a804200320113a00a704200320093a00a604200320173b01a4042003200d3a00a304200320183a00a2042003200e3b01a0042003200f3a009f042003200536009b04200320153a009a04200320143b01980420034180056a41086a22024200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a200341b8026a411010fd010240024020032d00c0064101460d00200341a8016a420037030020034190016a41106a420037030020034190016a41086a420037030020034200370390010c010b200320032f00c1063b019001200320032d00c3063a009201200320032802c406360093012003200341c0066a41086a2d00003a0097012003200341d9066a2900003703a8012003200341c9066a290000370398012003200341d1066a2900003703a0010b024020034198046a20034190016a4120109c05450d0041c49dc4002102412221060c040b200341c0066a200a418801109a051a200341003b019001200341e0056a200341c0066a20034190016a10f40141012102024020032d00e80522064102460d00200341e9056a310000210b20033100ea05210420032802e405210720032802e005210541f19ec600410d100b02402006450d00200b100c0b2004100c410021022005450d0020052007100b0b200320023a00c2062003410d3b01c00641014100200341c0066a10cc01200a102a0c060b410420054108742006411874722007724104200841ff017141014622061b200241ff017122021b21050240024020020d0020060d010b410f210641ea9fc600210202400240024002400240024020050e070001020304050a000b200e410874200f7220184118747221022017410874200d7220094118747221060c090b410e210641dc9fc60021020c080b410c210641d09fc60021020c070b4109210641c79fc60021020c060b4113210641b49fc60021020c050b4111210641a39fc60021020c040b200320043703b004200320193a00af04200320163a00ae042003201a3b01ac04200320133a00ab042003200c3a00aa04200320123b01a804200320113a00a704200320093a00a604200320173b01a4042003200d3a00a304200320183a00a2042003200e3b01a0042003200f3a009f042003200536009b04200320153a009a04200320143b01980420034180056a41086a22024200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a200341b8026a411010fd010240024020032d00c0064101460d00200341a8016a420037030020034190016a41106a420037030020034190016a41086a420037030020034200370390010c010b200320032f00c1063b019001200320032d00c3063a009201200320032802c406360093012003200341c0066a41086a2d00003a0097012003200341d9066a2900003703a8012003200341c9066a290000370398012003200341d1066a2900003703a0010b024020034198046a20034190016a4120109c05450d0041ee9dc4002102413121060c050b0240200a41ff01714101460d00200a4118762105200a41087621070c020b200341c0066a202741067610fe0120032802c00621060240024020032802c8062027413f7122024b0d00410021020c010b200620024105746a2202290018210b20022d0017211e20022d0016212820022f0014211f20022d0013212020022d0012212920022f0010212120022d000f212220022d000e212a20022f000c212320022d000b212420022d000a212b20022f0008212520022d000721262002280003212720022d0002210520022f00002107410121020b024020032802c406450d002006102a0b20020d0141dc9fc6002102410e21060c040b2001412c6a280200212c410420054108742007722006411874724104200841ff017141014622061b200241ff017122021b210502400240024020020d0020060d010b410f210641ea9fc600210202400240024002400240024020050e0700010203040507000b200e410874200f7220184118747221022017410874200d7220094118747221060c060b410e210641dc9fc60021020c050b410c210641d09fc60021020c040b4109210641c79fc60021020c030b4113210641b49fc60021020c020b4111210641a39fc60021020c010b200320043703b004200320193a00af04200320163a00ae042003201a3b01ac04200320133a00ab042003200c3a00aa04200320123b01a804200320113a00a704200320093a00a604200320173b01a4042003200d3a00a304200320183a00a2042003200e3b01a0042003200f3a009f042003200536009b04200320153a009a04200320143b01980420034180056a41086a22024200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a200341b8026a411010fd010240024020032d00c0064101460d00200341a8016a420037030020034190016a41106a420037030020034190016a41086a420037030020034200370390010c010b200320032f00c1063b019001200320032d00c3063a009201200320032802c406360093012003200341c0066a41086a2d00003a0097012003200341d9066a2900003703a8012003200341c9066a290000370398012003200341d1066a2900003703a0010b024020034198046a20034190016a4120109c05450d0041c49dc4002102412221060c010b4101210602400240200a41ff01714101460d00200a4118762105200a41087621020c010b200341c0066a202741067610fe0120032802c00621070240024020032802c8062027413f7122024b0d00410021080c010b200720024105746a2202290018210b20022d0017211e20022d0016212820022f0014211f20022d0013212020022d0012212920022f0010212120022d000f212220022d000e212a20022f000c212320022d000b212420022d000a212b20022f0008212520022d000721262002280003212720022d0002210520022f00002102410121080b024020032802c406450d002007102a0b20080d0041dc9fc6002102410e21060c010b200341c0066a202c418801109a051a200341aa016a200b370100200341a9016a201e3a0000200341a8016a20283a0000200341a6016a201f3b0100200341a5016a20203a0000200341a4016a20293a0000200341a2016a20213b0100200341a1016a20223a0000200341a0016a202a3a00002003419e016a20233b010020034190016a410d6a20243a00002003419c016a202b3a00002003419a016a20253b010020034190016a41096a20263a00002003202736009501200320053a009401200320023b01920120034180023b019001200341e0056a200341c0066a20034190016a10f401024020032d00e80522024102460d00200341e0056a41096a310000210b20033100ea05210420032802e405210720032802e005210541f19ec600410d100b02402002450d00200b100c0b2004100c410021062005450d0020052007100b0b200320063a00c2062003418d043b01c00641014100200341c0066a10cc01202c102a0c050b202c106a202c102a0c020b20034180056a41086a22064200370300200342003703800541e69dc400410820034180056a1008200341b8026a41086a2208200629030037030020032003290380053703b802200341c0066a200341b8026a411010fd01200341c0066a41086a2d0000210a200341c9066a22092f00002117200341cb066a2d0000210d200341cc066a22182d0000210e200341cd066a220f2f00002119200341cf066a2d00002116200341c0066a41106a221a2d00002113200341d1066a220c2f00002112200341d3066a2d00002111200341d4066a22152d00002114200341d5066a222c2f0000212d200341d7066a2d0000212e200341d8066a222f2d0000213020032f00c106213120032d00c306213220032802c4062133200341da066a200341d9066a2234290000420020032d00c00641014622021b37010020342030410020021b3a0000202f202e410020021b3a0000200341d6066a202d410020021b3b0100202c2014410020021b3a000020152011410020021b3a0000200341d2066a2012410020021b3b0100200c2013410020021b3a0000201a2016410020021b3a0000200341ce066a2019410020021b3b0100200f200e410020021b3a00002018200d410020021b3a0000200341ca066a2017410020021b3b01002009200a410020021b3a000020032033410020021b3600c50620032032410020021b3a00c40620032031410020021b3b01c2062003418d023b01c00641014100200341c0066a10cc012003200b3703d8062003201e3a00d706200320283a00d6062003201f3b01d406200320203a00d306200320293a00d206200320213b01d006200320223a00cf062003202a3a00ce06200320233b01cc06200320243a00cb062003202b3a00ca06200320253b01c806200320263a00c706200320273600c306200320053a00c206200320073b01c00620064200370300200342003703800541e69dc400410820034180056a10082008200629030037030020032003290380053703b80220034110360294012003200341b8026a36029001200341c0066a20034190016a10ff010c030b200a106a200a102a0b2002450d010b20004181223b01082000200636020420002002360200410021192000410a6a41003a00000c010b200041023a0008410021190b410121054101210641012107410121084101210a41012109410121174101210d410121184101210e4101210f0c290b200341c0066a200141086a418001109a051a20034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a290200370300200320022902003703900120034188016a200341c0066a20034190016a1080020240024020032802880122020d00200041023a00084100210f0c010b200328028c01210620004181203b0108200020023602004100210f2000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a41012109410121174101210d410121184101210e410121190c280b200341b8036a41086a22092001411c6a290200370300200341b8036a41106a2217200141246a290200370300200341b8036a41186a220d2001412c6a2802003602002003200141146a2902003703b803200241086a28020021062001410c6a280200210a410e2105200241046a280200210820022d000021070240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141086a2802000e0400010203000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41e4c4c200103e000b200641107621182006410876210e200141386a290300210b200141306a29030021042002411a6a2901002110200241196a2d00002113200241186a2d0000210c200241166a2f01002112200241156a2d00002111200241146a2d00002115200241126a2f01002114200241116a2d00002127200241106a2d0000210f2002410e6a2f010021192002410d6a2d000021162002410c6a2d0000211a200241026a2f0100211e200141106a280200210520022d0001210220034198046a41186a200d28020036020020034198046a41106a201729030037030020034198046a41086a2009290300370300200320032903b80337039804410420084108762006411874724104200241014622091b200741ff017122021b21060240024020020d0020090d010b410f210541ea9fc600210202400240024002400240024020060e0700010203040516000b200e41ff0171201841087472201a4118747221022019410874201672200f4118747221050c150b410e210541dc9fc60021020c140b410c210541d09fc60021020c130b4109210541c79fc60021020c120b4113210541b49fc60021020c110b4111210541a39fc60021020c100b200320103703a801200320133a00a7012003200c3a00a601200320123b01a401200320113a00a301200320153a00a201200320143b01a001200320273a009f012003200f3a009e01200320193b019c01200320163a009b012003201a3a009a01200320183b0198012003200e3a0097012003200636009301200320083a0092012003201e3b019001200341c0066a41186a220220034198046a41186a280200360200200341c0066a41106a220720034198046a41106a290300370300200341c0066a41086a220820034198046a41086a29030037030020032003290398043703c0060240200a41ff01714101460d00200a4108762106200341e0056a41186a20022d00003a0000200341e0056a41106a2007290300370300200341e0056a41086a2008290300370300200320032903c0063703e0050c0f0b20034198026a200541067610fe0120032802980221070240024020032802a0022005413f7122024b0d00410021020c010b200341e8056a200720024105746a2202410f6a290000370300200341e0056a41106a200241176a290000370300200341f8056a2002411f6a2d00003a0000200320022900073703e00520022f0000200241026a2d000041107472210620022800032105410121020b0240200328029c02450d002007102a0b20020d0e200341b8026a41086a20034180056a41086a290000370300200341b8026a41106a20034180056a41106a29000037030041dc9fc6002102410e21050c0f0b41a6f5c5002102200741ff01714101470d0f20064102490d0f200841ff01710d0f411210282202450d01200241106a41002f008086423b0000200241086a41002900f88542370000200241002900f08542370000200241124124102c2202450d022002200a36001220034198026a41186a2206420037030020034198026a41106a2205420037030020034198026a41086a2207420037030020034200370398022002411620034198026a1000200341f8016a41186a2006290300370300200341f8016a41106a2005290300370300200341f8016a41086a200729030037030020032003290398023703f8012002102a200341003602c006200341f8016a4120200341c0066a1006210220032802c0062206417f460d092002450d09200320063602bc02200320023602b802200341c0066a200341b8026a10810220032903c0064201510d0320032802c806210520034198046a200341cc066a41dc00109a051a02402006450d002002102a0b200341c0066a20034198046a41dc00109a051a200341f8016a41201009410121020c0a0b41a6f5c5002102200741ff01714101470d0e20064104490d0e200841ff01710d0e411210282202450d03200241106a41002f008086423b0000200241086a41002900f88542370000200241002900f08542370000200241124124102c2202450d042002200a36001220034198026a41186a2206420037030020034198026a41106a2205420037030020034198026a41086a2207420037030020034200370398022002411620034198026a1000200341f8016a41186a2006290300370300200341f8016a41106a2005290300370300200341f8016a41086a200729030037030020032003290398023703f8012002102a200341f8016a41204101410041001003417f460d0a20034180056a41086a2202420037030020034200370380054181a2c600411220034180056a1008200341b8026a41086a200229030037030020032003290380053703b80241002102200341003602c006200341b8026a4110200341c0066a100621060240024020032802c0062205417f470d000c010b024020060d000c010b20032005360294012003200636029001200341c0066a20034190016a10820120032802c0062202450d0620032902c40621042005450d002006102a0b2002410420021b210d02402004420020021b2204422088220ba722022004a7470d00200241016a22062002490d19200ba722074101742205200620062005491b220641ffffffff03712006470d19200641027422054100480d190240024020020d0020051028210d0c010b200d20074102742005102c210d0b200d450d072004422088220ba721022006ad21040b200d20024102746a200a36020020034180056a41086a2202420037030020034200370380054181a2c600411220034180056a1008200341b8026a41086a200229030037030020032003290380053703b8020240200d0d00200341b8026a411010090c100b200341003602c806200342013703c006200ba741016a2206200341c0066a10b4010240024020060d0020032802c806210a20032802c406210820032802c00621060c010b410020032802c80622026b2105200d20064102746a211720032802c4062108200d210703402007280200210902400240200820056a4104490d0020032802c00621060c010b200241046a22062002490d1b2008410174220a2006200a20064b1b220a4100480d1b0240024020080d00200a102821060c010b20032802c0062008200a102c21060b2006450d0a2003200a3602c406200320063602c006200a21080b2003200241046a220a3602c806200620026a20093600002005417c6a2105200a21022017200741046a2207470d000b0b2004a72102200341b8026a41102006200a100702402008450d002006102a0b2002450d0f200d102a0c0f0b411241011037000b412441011037000b41c4d1c3004133200341c8076a419cd9c3001038000b411241011037000b412441011037000b41c4d1c3004133200341c8076a419cd9c3001038000b200541041037000b200a41011037000b410021020b200341e0056a200341c0066a41dc00109a051a200341c0066a200341e0056a41dc00109a051a20020d010b418ec5c2002102411921050c030b20034180056a200341c0066a41dc00109a051a200320053602900120034190016a41047220034180056a41dc00109a051a200341f8006a200341b0016a20032903a001200341a8016a29030010820220032903782104200320034180016a2903003703c806200320043703c0062003200341c0066a3602980420034198046a109d010c030b200341e0006a2004200b42c0843d420010a005200341d0006a20032903602210200341e0006a41086a290300221b42c0fb42427f109f05200341c0006a2010201b42d086034200109f0520034198036a41086a200341e0056a41086a29030037030020034198036a41106a200341e0056a41106a29030037030020034198036a41186a200341e0056a41186a2d00003a0000200320032903e00522103703b8022003201037039803200341f0006a20034190016a2003290340221b200420032903507c42148042ffffffff0f837c2210428080e983b1de162010428080e983b1de1656200341c0006a41086a2903002010201b54ad7c22104200522010501b22021b221b2010420020021b221010830202402003280270450d0041f4c4c2002102411a21050c010b20034180056a41086a22024200370300200342003703800541eba1c600411620034180056a1008200341b8026a41086a200229030037030020032003290380053703b80241002107200341003602c006200341b8026a4110200341c0066a10062102024020032802c0062208417f460d002002450d0020084104490d04200228000021072002102a0b20034180056a41086a22024200370300200342003703800541eba1c600411620034180056a1008200341b8026a41086a200229030037030020032003290380053703b8022003200741016a3602c006200341b8026a4110200341c0066a41041007200341f8066a20034190016a41186a290300370300200341f0066a20034190016a41106a290300370300200341e8066a20034190016a41086a29030037030020034183076a200536000020034187076a2003290398033700002003418f076a20034198036a41086a29030037000020034197076a20034198036a41106a2903003700002003419f076a20034198036a41186a2d00003a0000200320063b01800720034182076a20064110763a00002003200b3703c806200320043703c00620032003290390013703e006200341c0066a41186a20103703002003201b3703d006411210282202450d04200241106a41002f008086423b0000200241086a41002900f88542370000200241002900f08542370000200241124124102c2202450d052002200736001220034198026a41186a2206420037030020034198026a41106a2205420037030020034198026a41086a2208420037030020034200370398022002411620034198026a1000200341f8016a41186a2006290300370300200341f8016a41106a2005290300370300200341f8016a41086a200829030037030020032003290398023703f8012002102a200341003602e805200342013703e005200341e0066a200341e0056a108f01200341c0066a41086a290300210420032903c006210b0240024020032802e405220620032802e80522026b4110490d0020032802e00521060c010b200241106a22052002490d0c200641017422022005200220054b1b22024100480d0c0240024020060d002002102821060c010b20032802e00520062002102c21060b2006450d07200320023602e405200320063602e00520032802e80521020b200620026a220620043700082006200b3700002003200241106a3602e80520034180076a200341e0056a108f01200341d8066a290300210420032903d006210b0240024020032802e405220520032802e80522066b4110490d0020032802e00521020c010b200641106a22022006490d0c200541017422062002200620024b1b22084100480d0c0240024020050d002008102821020c010b20032802e00520052008102c21020b2002450d08200320083602e405200320023602e00520032802e8052106200821050b200220066a220820043700082008200b370000200341f8016a41202002200641106a100702402005450d002002102a0b200341cc066a200736020041002102200341c8066a41003a00002003410b3a00c00641014100200341c0066a10cc010b2002450d010b200041811e3b010820002005360204200020023602002000410a6a41003a00000c160b200041023a00080c150b41c4d1c3004133200341c8076a419cd9c3001038000b411241011037000b412441011037000b200241011037000b200841011037000b200141086a28020021062001280204210502400240024020022d00000d0020022d000141ff01714101460d010b02402006450d002005102a0b200041811c3b010820004113360204200041b49fc6003602004100210e2000410a6a41003a00000c010b02402006450d002005102a0b200041023a00084100210e0b410121054101210641012107410121084101210a41012109410121174101210d410121180c250b02400240024020022d00000d0020022d000141ff01714102470d002001280204210220034180056a41086a220642003703002003420037038005418194c100411020034180056a1008200341b8026a41086a200629030037030020032003290380053703b802200341b8026a41104101410041001003417f470d011098012002490d0220034180056a41086a220642003703002003420037038005418194c100411020034180056a1008200341b8026a41086a200629030037030020032003290380053703b802200320023602c006200341b8026a4110200341c0066a41041007200041023a00080c110b200041811a3b01082000410f360204200041ea9fc6003602002000410a6a41003a00000c100b41a894c1001032000b41bc95c1001032000b200341b8036a41026a2205200141076a2d00003a000020034190016a41086a22072001411c6a29020037030020034190016a41106a220a200141246a29020037030020034190016a41186a2001412c6a290200370300200341b0016a200141346a290200370300200341b8016a2001413c6a290200370300200341c0016a200141c4006a2d00003a0000200320012f00053b01b8032003200141146a29020037039001200141086a28020021082001410c6a2802002109200141106a280200210620022f0001200241036a2d000041107472210d2002410c6a2802002118200241086a280200210e200241046a280200210f20022d0000210202400240024002400240024002400240024002400240024020012d000422170e050001020304000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41e8cfc300103e000b200341af046a2007290300370000200341b7046a200a2d00003a0000200320032f01b8033b019804200320063600a3042003200936009f042003200836009b0420032003290390013700a704200320052d00003a009a04024002402002417f6a220641024b0d00024020060e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0041a3d0c3002105410a2118410021060c0e0b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a1006210202400240024002400240024002400240024020032802c0062206417f460d002002450d00200320063602e405200320023602e005200341c0066a200341e0056a106d20032802c006220a450d0c20032902c406210420032802c406211802402006450d002002102a0b2003200a3602e0052004a7210e410021022004422088a7220d41014b0d02200d0e020103010b4101210a200341013602e005410021184100210e0b200341f8016a41186a20034198046a41186a290300370300200341f8016a41106a20034198046a41106a290300370300200341f8016a41086a20034198046a41086a29030037030020032003290398043703f8014100210d200341f8016a2106410021050c020b200d210603402006410176220520026a22072002200a20074105746a20034198046a4120109c054101481b2102200620056b220641014b0d000b0b0240200a20024105746a20034198046a4120109c0522060d004193d0c3002105200e450d05200a102a0c050b200341f8016a41186a20034198046a41186a290300370300200341f8016a41106a20034198046a41106a290300370300200341f8016a41086a20034198046a41086a29030037030020032003290398043703f8012006411f7620026a2205200d4b0d01200341f8016a21060b200d200e460d012018210e0c020b41f8b0c0001032000b02402018200d460d002018210e0c010b201841016a22022018490d0c201841017422072002200720024b1b220e41ffffff3f71200e470d0c200e41057422024100480d0c0240024020180d0020021028210a0c010b200a20184105742002102c210a0b200a450d062003200a3602e0050b200a20054105746a220241206a2002200d20056b410574109b051a200241186a200641186a290000370000200241106a200641106a290000370000200241086a200641086a2900003700002002200629000037000020034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b80220032802e0052102200341003602c806200342013703c006200d41016a2207200341c0066a10b40102402007200d490d00200d41057441206a210603402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b200341c0066a41186a20034198046a41186a290300370300200341c0066a41106a20034198046a41106a290300370300200341c0066a41086a20034198046a41086a29030037030020032003290398043703c006410021054101410020032802e00522022007108402200341093b01c00641014100200341c0066a10cc01200e450d002002102a0b41102118410021060c0d0b200341af046a2007290300370000200341b7046a200a2d00003a0000200320032f01b8033b019804200320063600a3042003200936009f042003200836009b0420032003290390013700a704200320052d00003a009a04024002402002417f6a220641024b0d00024020060e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0041a3d0c3002105410a2118410021060c0d0b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621020240024020032802c0062206417f460d002002450d00200320063602e405200320023602e005200341c0066a200341e0056a106d20032802c006220a450d0620032902c40621042006450d012002102a0c010b420021044101210a0b41002102024002400240024002402004422088a7220d41014b0d00200d0e020201020b200d210603402006410176220520026a22072002200a20074105746a20034198046a4120109c054101481b2102200620056b220641014b0d000b0b200a20024105746a20034198046a4120109c05450d010b41add0c3002105410c21182004a7450d01200a102a410021060c0e0b2002200d4f0d06200a20024105746a2206200641206a2002417f73200d6a410574109b051a20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c806200342013703c006200d417f6a2205200341c0066a10b40102402005450d00200d41057441606a2106200a210203402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b200341c0066a41186a20034198046a41186a290300370300200341c0066a41106a20034198046a41106a290300370300200341c0066a41086a20034198046a41086a29030037030020032003290398043703c006200341c0066a4101200a200510840220034189023b01c0064100210541014100200341c0066a10cc0102402004a7450d00200a102a0b0b410021060c0c0b200341f7056a2007290300370000200341ff056a200a2d00003a0000200320032f01b8033b01e005200320063600eb05200320093600e705200320083600e30520032003290390013700ef05200320052d00003a00e20520034198046a41186a200341b9016a29000037030020034198046a41106a200341b1016a29000037030020034198046a41086a200341a9016a290000370300200320032900a10137039804024002402002417f6a220641024b0d00024020060e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0041a3d0c3002105410a2118410021060c0c0b02400240200341e0056a20034198046a4120109c050d00410021050c010b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621020240024020032802c0062206417f460d002002450d0020032006360284052003200236028005200341c0066a20034180056a106d20032802c006220d450d0820032902c40621042006450d012002102a0c010b4101210d420021040b41add0c3002105410c211841002102024002402004422088a7220e41014b0d00200e0e020c010c0b200e210603402006410176220720026a220a2002200d200a4105746a200341e0056a4120109c054101481b2102200620076b220641014b0d000b0b200d20024105746a2206200341e0056a4120109c050d0a20034198026a41186a220520034198046a41186a29030037030020034198026a41106a220720034198046a41106a29030037030020034198026a41086a220a20034198046a41086a2903003703002003200329039804370398022002200e4f0d072006200329039802370000200641186a2005290300370000200641106a2007290300370000200641086a200a290300370000410021020240200e4101460d0041002102200e210603402006410176220520026a22072002200d20074105746a20034198046a4120109c054101481b2102200620056b220641014b0d000b0b0240200d20024105746a20034198046a4120109c050d004193d0c3002105411021180c0b0b200d200e10f00120034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c806200342013703c006200e200341c0066a10b4010240200e450d00200e4105742106200d210203402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b200341c0066a41186a200341e0056a41186a290300370300200341c0066a41106a200341e0056a41106a290300370300200341c0066a41086a200341e0056a41086a290300370300200320032903e0053703c006200341c0066a4101200d200e10840220034189043b01c0064100210541014100200341c0066a10cc012004a7450d00200d102a0b0c0a0b024002402002417f6a220541024b0d00024020050e03000102000b200e41017420184d0d00200f41ff0171450d010b2002200d7241ff0171450d0002402009450d002008102a0b41a3d0c3002105410a21180c0c0b2008200610f00120034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c006200341b8026a4110200341c0066a100621050240024020032802c0062207417f460d002005450d002003200736029c042003200536029804200341c0066a20034198046a106d20032802c0062202450d0820032902c40621042007450d012005102a0c010b42002104410121020b2008200620022004422088a710850202402004a7450d002002102a0b20034180056a41086a22024200370300200342003703800541f8cfc300411b20034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341003602c806200342013703c0062006200341c0066a10b40102402006450d00200641057421062008210203402002200341c0066a108f01200241206a2102200641606a22060d000b0b20032802c4062102200341b8026a411020032802c006220620032802c806100702402002450d002006102a0b02402009450d002008102a0b20034189063b01c006410021054101210641014100200341c0066a10cc010c0a0b41c4d1c3004133200341c8076a419cd9c3001038000b200241011037000b41c4d1c3004133200341c8076a419cd9c3001038000b41b0b1c0001032000b41c4d1c3004133200341c8076a419cd9c3001038000b41bcd0c3002002200e1034000b41c4d1c3004133200341c8076a419cd9c3001038000b1031000b2004a7450d00200d102a410021060c010b410021060b0240024002402017417f6a220241034b0d00024020020e0403030300030b200620094572450d010c020b20174104490d012009450d010b2008102a0b20050d00200041023a0008410021180c010b20004181183b01082000201836020420002005360200410021182000410a6a41003a00000b410121054101210641012107410121084101210a41012109410121174101210d0c1c0b200341c0066a41386a200141c0006a290300370300200341c0066a41306a200141386a290300370300200341c0066a41286a200141306a290300370300200341c0066a41206a200141286a290300370300200341c0066a41186a200141206a290300370300200341c0066a41106a200141186a290300370300200341c0066a41086a200141106a2903003703002003200141086a2903003703c00620034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a2902003703002003200229020037039001200341386a200341c0066a20034190016a10860202400240200328023822020d00200041023a00084100210d0c010b200328023c210620004181163b0108200020023602004100210d2000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a41012109410121170c1a0b20034190016a41206a200141246a29020037030020034190016a41186a2001411c6a29020037030020034190016a41106a200141146a29020037030020034190016a41086a2001410c6a2902003703002003200129020437039001200341c0066a41206a200241206a290200370300200341c0066a41186a200241186a290200370300200341c0066a41106a200241106a290200370300200341c0066a41086a200241086a290200370300200320022902003703c006200341306a20034190016a200341c0066a10870202400240200328023022020d00200041023a0008410021170c010b2003280234210620004181143b010820002002360200410021172000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a410121090c180b20034190016a41206a200141246a29020037030020034190016a41186a2001411c6a29020037030020034190016a41106a200141146a29020037030020034190016a41086a2001410c6a2902003703002003200129020437039001200341c0066a41206a200241206a290200370300200341c0066a41186a200241186a290200370300200341c0066a41106a200241106a290200370300200341c0066a41086a200241086a290200370300200320022902003703c006200341286a20034190016a200341c0066a10880202400240200328022822020d00200041023a0008410021090c010b200328022c210620004181123b010820002002360200410021092000410a6a41003a0000200020063602040b410121054101210641012107410121084101210a0c160b200341c0066a41286a200141306a290300370300200341c0066a41206a200141286a290300370300200341c0066a41186a200141206a290300370300200341c0066a41106a200141186a290300370300200341c0066a41086a200141106a2903003703002003200141086a2903003703c00620034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a2902003703002003200229020037039001200341206a200341c0066a20034190016a10890202400240200328022022020d00200041023a00084100210a0c010b2003280224210620004181103b0108200020023602004100210a2000410a6a41003a0000200020063602040b410121054101210641012107410121080c140b200141086a28020021162001280204211a200341c0066a2001410c6a41e400109a051a2002411a6a2901002104200241196a2d00002118200241186a2d0000210e200241166a2f0100210f200241156a2d00002119200241146a2d00002113200241126a2f0100210c200241116a2d00002112200241106a2d000021072002410e6a2f010021082002410d6a2d0000210a2002410c6a2d000021092002410a6a2f01002117200241096a2d0000210d200241046a2d00002111200241026a2f01002115200241056a280000210520022d0000210620022d00012102200341b8026a200341c0066a41046a41e000109a051a410420054104200241014622021b20061b21050240024002400240024020060d0020020d010b410f210641ea9fc600210202400240024002400240024020050e0700010203040507000b2017410874200d7220094118747221022008410874200a7220074118747221060c060b410e210641dc9fc60021020c050b410c210641d09fc60021020c040b4109210641c79fc60021020c030b4113210641b49fc60021020c020b4111210641a39fc60021020c010b2003200437039805200320183a0097052003200e3a0096052003200f3b019405200320193a009305200320133a0092052003200c3b019005200320123a008f05200320073a008e05200320083b018c052003200a3a008b05200320093a008a05200320173b0188052003200d3a0087052003200536008305200320113a008205200320153b018005024002400240024002400240410e10282202450d002002410029008aaf44370000200241066a4100290090af443700002003428e808080e00137029401200320023602900120034180056a20034190016a108f012003280298012102200328029001210620034198026a41186a2205420037030020034198026a41106a2207420037030020034198026a41086a2208420037030020034200370398022006200220034198026a1000200341f8016a41186a2005290300370300200341f8016a41106a2007290300370300200341f8016a41086a200829030037030020032003290398023703f8010240200328029401450d00200328029001102a0b2003410036029001200341f8016a412020034190016a100621022003280290012206417f460d022002450d022003200636029c02200320023602980220034190016a20034198026a108a0220032802b0012217450d0120034198046a41086a2205200341c0016a29030037030020034198046a41106a2207200341c8016a29030037030020034198046a41186a2208200341d0016a29030037030020034198046a41206a220a200341d8016a2802003602002003200341b8016a2903003703980420032802b401210902402006450d002002102a0b200341e0056a41086a20052903002204370300200341e0056a41106a2007290300220b370300200341e0056a41186a20082903002210370300200341e0056a41206a200a28020022023602002003200329039804221b3703e00520034190016a41106a200b37030020034190016a41086a200437030020034190016a41186a201037030020034190016a41206a2002360200200341f8016a41086a2003419c016a290200370300200341f8016a41106a200341a4016a290200370300200341f8016a41186a200341ac016a2902003703002003201b3703900120032003290294013703f80102402009450d002017102a0b20034198036a41086a200341f8016a41086a29030037030020034198036a41106a200341f8016a41106a29030037030020034198036a41186a200341f8016a41186a290300370300200320032903f80137039803200341b8036a200341b8026a41e000109a051a20034198026a20034198036a108b0220032802a0022106200328029802210220034100360290012002200620034190016a100621062003280290012205417f460d042006450d042003200536028405200320063602800520034190016a20034180056a10e80120032d0090014101460d03200341e0056a20034190016a41017241e000109a051a02402005450d002006102a0b20034180056a200341e0056a41e000109a051a20034190016a20034180056a41e000109a051a200341013a00980420034198046a41017220034190016a41e000109a051a0c050b410e41011037000b41c4d1c3004133200341c8076a419cd9c3001038000b41a5c4c2002102412721060c030b41c4d1c3004133200341c8076a419cd9c3001038000b20034190016a20034180056a41e000109a051a200341003a0098040b0240200328029c02450d002002102a0b200341b9046a2112200341d9046a2111200341b8036a41206a2113200341f8036a210c20034198046a410172211520034190016a41017221054104210741e7e485f30621060240024003400240024002400240200641e9dabdf30646220f0d000240200641e7e485f306470d00200341b8036a210a0c020b200641e2c289ab06470d022013210a0c010b200c210a0b41202102410021084120102822090d01412041011037000b41012108410021024101210a410121090b2009200a2002109a052109200320023602a402200320023602a0022003200936029c022003200636029802200341f8016a20034198026a108c0220034190016a20032802f801221720032802800210fd0120034180056a41086a220d200541086a29000037030020034180056a41106a2218200541106a29000037030020034180056a41186a220e200541186a29000037030020032005290000370380050240024020032d0090014101470d00200341e0056a41186a2219200e290300370300200341e0056a41106a220e2018290300370300200341e0056a41086a2218200d29030037030020032003290380053703e005024020032802fc01450d002017102a0b024020080d002009102a0b20034190016a41186a201929030037030020034190016a41106a200e29030037030020034190016a41086a2018290300370300200320032903e0053703900120034190016a20034198036a4120109c05450d0141ccc4c2002102411821060c050b024020032802fc01450d002017102a0b20080d002009102a0b0240024020032d0098044101470d00024002400240200641e2c289ab06460d00200f0d010240200641e7e485f306460d0041002109410121170c030b41202109201521170c020b41202109201221170c010b41202109201121170b024020022009470d00200a2017460d02200a20172002109c05450d020b0240024020090d004100210d410121180c010b2009210d200910282218450d040b201820172009109a0521172003200936029c012003200d3602980120032017360294012003200636029001200341e0056a20034190016a108c0220032802e005220920032802e8051009024020032802e405450d002009102a0b200d450d002017102a0b41012109024020080d00200210282209450d040b2009200a2002109a05210a2003200236029c0120032002360298012003200a360294012003200636029001200341e0056a20034190016a108c0220032802e0052102200320032802e80536028405200320023602800520034198036a20034180056a10ff01024020032802e405450d002002102a0b20080d00200a102a0b02402007410c460d00200741f8c8c0006a2800002106200741046a21070c010b0b200341e0056a20034198036a108b0220032802e805210620032802e005210220034100360298012003420137039001200341b8036a20034190016a108f01201320034190016a108f01200c20034190016a108f012003280294012105200220062003280290012207200328029801100702402005450d002007102a0b024020032802e405450d002002102a0b2016450d03201a102a0c030b200941011037000b200241011037000b02402016450d00201a102a0b2002450d00200041810e3b01082000200636020420002002360200410021082000410a6a41003a00000c010b200041023a0008410021080b4101210541012106410121070c120b200341c0066a41306a200141386a290300370300200341c0066a41286a200141306a290300370300200341c0066a41206a200141286a290300370300200341c0066a41186a200141206a290300370300200341c0066a41106a200141186a290300370300200341c0066a41086a200141106a2903003703002003200141086a2903003703c00620034190016a41206a200241206a29020037030020034190016a41186a200241186a29020037030020034190016a41106a200241106a29020037030020034190016a41086a200241086a2902003703002003200229020037039001200341186a200341c0066a20034190016a108d0202400240200328021822020d00200041023a0008410021070c010b200328021c2106200041810c3b010820002002360200410021072000410a6a41003a0000200020063602040b41012105410121060c100b200141256a2900002110200141246a2d0000211a200141216a2f00002113200141206a2d0000210c2001411d6a2f000021122001411c6a2d00002111200141196a2f00002109200141186a2d00002117200141156a2f0000210d200141146a2d00002118200141106a28020021052001410d6a2f0000210e2001410c6a2d00002127200141086a2802002107200141306a2903002104200141386a290300210b20012d0023211520012d001f211420012d001b210f20012d0017211920012d000f211620034198046a41106a200141d0006a2d00003a000020034198046a41086a221e200141c8006a2903003703002003200141c0006a290300370398044111210620022d0001210820022d0000210a02400240024002400240024002400240024002400240024002400240024020070e0400010203000b200341c0066a41146a4101360200200342013702c406200341ccd1c5003602c006200341043602e405200341c4d1c5003602e0052003200341e0056a3602d006200341c0066a41e092c100103e000b200241106a2d0000211e2002410e6a2f0100211f2002410d6a2d000021202002410c6a2d000021212002410a6a2f01002122200241096a2d000021234104200241056a2800004104200841ff017141014622081b200a41ff017122061b21070240024020060d0020080d010b410f210641ea9fc600210202400240024002400240024020070e0700010203040511000b20224108742023722021411874722102201f410874202072201e4118747221060c100b410e210641dc9fc60021020c0f0b410c210641d09fc60021020c0e0b4109210641c79fc60021020c0d0b4113210641b49fc60021020c0c0b4111210641a39fc60021020c0b0b200241196a2d00002106200241186a2d00002108200241166a2f0100210a200241156a2d00002124200241146a2d00002125200241126a2f01002126200241116a2d00002128200241046a2d00002129200241026a2f0100212a20032002411a6a2901003703a801200320063a00a701200320083a00a6012003200a3b01a401200320243a00a301200320253a00a201200320263b01a001200320283a009f012003201e3a009e012003201f3b019c01200320203a009b01200320213a009a01200320223b019801200320233a0097012003200736009301200320293a0092012003202a3b01900102400240202741ff01714101470d00200341e0056a200541067610fe0120032802e00521060240024020032802e8052005413f7122024b0d00410021020c010b200620024105746a2202290018211020022d0017211a20022d0016211520022f0014211320022d0013210c20022d0012211420022f0010211220022d000f211120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210520022d0002211620022f0000210e410121020b024020032802e405450d002006102a0b20020d00410121020c010b410021020b20032010370390022003201a3a008f02200320153a008e02200320133b018c022003200c3a008b02200320143a008a02200320123b018802200320113a0087022003200f3a008602200320093b018402200320173a008302200320193a0082022003200d3b018002200320183a00ff01200320053600fb01200320163a00fa012003200e3b01f80120020d09200341c0066a41186a200341f8016a41186a290300370300200341c0066a41106a200341f8016a41106a290300370300200341c0066a41086a200341f8016a41086a290300370300200320032903f8013703c006200341086a20034190016a200341c0066a2004200b108e0220032802082202450d0b200328020c21060c0a0b41a39fc60021022008200a7241ff01710d0b201e290300211b200329039804211c0240202741ff01714101470d0020034190016a200541067610fe012003280290012106024002402003280298012005413f7122024b0d00410021020c010b200620024105746a2202290018211020022d0017211a20022d0016211520022f0014211320022d0013210c20022d0012211420022f0010211220022d000f211120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210520022d0002211620022f0000210e410121020b0240200328029401450d002006102a0b2002450d080b200320103703d8062003201a3a00d706200320153a00d606200320133b01d4062003200c3a00d306200320143a00d206200320123b01d006200320113a00cf062003200f3a00ce06200320093b01cc06200320173a00cb06200320193a00ca062003200d3b01c806200320183a00c706200320053600c306200320163a00c2062003200e3b01c006411410282202450d01200241002900cfe140370000200241106a41002800dfe140360000200241086a41002900d7e14037000020034294808080c002370294012003200236029001200341c0066a20034190016a108f012003280298012102200328029001210620034198026a41186a2205420037030020034198026a41106a2207420037030020034198026a41086a2208420037030020034200370398022006200220034198026a1000200341f8016a41186a2005290300370300200341f8016a41106a2007290300370300200341f8016a41086a200829030037030020032003290398023703f8010240200328029401450d00200328029001102a0b2003410036029001200341f8016a412020034190016a100621022003280290012206417f460d052002450d0520064110490d02200241086a29000021102002290000211d2002102a0c060b41a39fc60021022008200a7241ff01710d0a200141e0006a290300211c200141d8006a290300211d20032900a104211b20032d00a004210720032d009f04210820032f009d04210a20032d009c04211e20032d009b04211f20032f009904212020032d00980421210240202741ff01714101470d00200341c0066a200541067610fe0120032802c00621060240024020032802c8062005413f7122024b0d00410021020c010b200620024105746a2202290018211020022d0017211a20022d0016211520022f0014211320022d0013210c20022d0012211420022f0010211220022d000f211120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210520022d0002211620022f0000210e410121020b024020032802c406450d002006102a0b2002450d070b2004422088a72106200320103703a8012003201a3a00a701200320153a00a601200320133b01a4012003200c3a00a301200320143a00a201200320123b01a001200320113a009f012003200f3a009e01200320093b019c01200320173a009b01200320193a009a012003200d3b019801200320183a0097012003200536009301200320163a0092012003200e3b01900102402004a741ff01714101460d00200ba72118200b423888a7210f200b422888a72109200b422088a72117200b421888a72119200b420888a7210d2004421888a721162004420888a7210e0c030b200341e0056a2004422688a710fe0120032802e00521050240024020032802e8052006413f7122024b0d00410021022013210a200c211e2014211f201221202011212120152108201a21072010211b0c010b200520024105746a2202290018211b20022d0017210720022d0016210820022f0014210a20022d0013211e20022d0012211f20022f0010212020022d000f212120022d000e210f20022f000c210920022d000b211720022d000a211920022f0008210d20022d000721182002280003210620022d0002211620022f0000210e410121020b024020032802e405450d002005102a0b20020d02410121020c030b411441011037000b41c4d1c3004133200341c8076a419cd9c3001038000b410021020b2003201b37039002200320073a008f02200320083a008e022003200a3b018c022003201e3a008b022003201f3a008a02200320203b018802200320213a0087022003200f3a008602200320093b018402200320173a008302200320193a0082022003200d3b018002200320183a00ff01200320063600fb01200320163a00fa012003200e3b01f80120020d03200341c0066a41186a200341f8016a41186a290300370300200341c0066a41106a200341f8016a41106a290300370300200341c0066a41086a200341f8016a41086a290300370300200320032903f8013703c006200341106a20034190016a200341c0066a201d201c108e0220032802102202450d05200328021421060c040b4200211d420021100b02400240201d20045422062010200b542010200b5122021b0d00201d2004562010200b5620021b450d012003201d20047d3703900120032010200b7d2006ad7d37039801200320034190016a3602e005200341e0056a109d010c010b20032004201d7d370390012003200b20107d2004201d54ad7d37039801200320034190016a3602e005200341e0056a109c010b200341c0066a2004200b108f020240024002400240411810282202450d00200241002900e3e140370000200241106a41002900f3e140370000200241086a41002900ebe140370000200342988080808003370294012003200236029001200341c0066a20034190016a108f012003280298012102200328029001210620034198026a41186a2205420037030020034198026a41106a2207420037030020034198026a41086a2208420037030020034200370398022006200220034198026a1000200341f8016a41186a2005290300370300200341f8016a41106a2007290300370300200341f8016a41086a200829030037030020032003290398023703f8010240200328029401450d00200328029001102a0b2003410036029001200341f8016a412020034190016a100621022003280290012206417f460d022002450d0220064110490d01200241086a29000021042002290000210b2002102a0c030b411841011037000b41c4d1c3004133200341c8076a419cd9c3001038000b4200210b420021040b02400240200b201c5422062004201b542004201b5122021b0d00200b201c562004201b5620021b450d012003200b201c7d3703900120032004201b7d2006ad7d37039801200320034190016a3602e005200341e0056a109d010c010b2003201c200b7d370390012003201b20047d201c200b54ad7d37039801200320034190016a3602e005200341e0056a109c010b200341c0066a201c201b1090020c030b41dc9fc6002102410e21060c030b41dc9fc6002102410e21060b20020d010b200041023a00080c010b200041810a3b010820002006360204200020023602002000410a6a41003a00000b41012105410121060c0d0b109102000b024020032802cc062206450d0020032802c4062102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b024020032802c806450d0020032802c406102a0b024020072008460d0003402007280204220a450d01200741086a280200210902402007410c6a2802002202450d00200241246c2106200a210203400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200741f0006a210702402009450d00200a102a0b20072008470d000b0b0240200c450d00200d102a0b2004a7450d032017102a0c030b20072008460d0003402007280204220a450d01200741086a280200210902402007410c6a2802002202450d00200241246c2106200a210203400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200741f0006a210702402009450d00200a102a0b20072008470d000b0b0240200c450d00200d102a0b20034180056a41086a2202420037030020034200370380054193cdc200411120034180056a1008200341b8026a41086a200229030037030020032003290380053703b802200341c0066a20032802980322022004422088a7109202200341b8026a411020032802c006220620032802c8061007024020032802c406450d002006102a0b02402004a7450d002002102a0b200041023a000841002106410121050c090b02402005450d00200d200541f0006c6a2108200d2107034002402007410c6a2802002206450d0020072802042102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200741f0006a21020240200741086a280200450d002007280204102a0b2002210720022008470d000b0b200c450d00200d102a0b20004181063b01082000200f3602042000200e360200410021062000410a6a41003a0000410121050c070b2005102a0b0240024002402007417f6a220241054b0d00024002400240024020020e06060006010203060b41000d052004a70d040c050b41000d042004a70d030c040b200a450d0302402004422088a72202450d00200241186c21062005210203400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b2004a70d020c030b2006450d0202402004422088a72202450d002002410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b2004a70d010c020b02402004422088a72202450d002002410c6c21062005210203400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b2004a7450d010b2005102a0b410f210241ea9fc6002105410621072008417c6a0e0402010300020b200041023a0008410121060c030b4111210241a39fc6002105410521070c010b4113210241b49fc6002105410421070b41012106200041013b010820002002360204200020053602002000410a6a20073a00000b410021050b410121070b410121080b4101210a0b410121090b410121170b4101210d0b410121180b4101210e0b4101210f410121190b410121160b02402001280200220241124b0d00024002400240024002400240024002400240024002400240024020020e13000d0d010d0d020304050607080d090d0a0b0c000b2005450d0c0240200141086a280200220241054b0d0002400240024020020e06101000100102100b200141106a280200450d0f2001410c6a280200102a0c0f0b200141106a280200450d0e2001410c6a280200102a0c0e0b0240200141146a2802002206450d002001410c6a2802002102200641186c210603400240200241046a280200450d002002280200102a0b0240200241106a280200450d002002410c6a280200102a0b200241186a2102200641686a22060d000b0b200141106a280200450d0d200128020c102a0c0d0b0240200141146a2802002206450d002001410c6a28020021022006410c6c210603400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b200141106a280200450d0c200128020c102a0c0c0b2006450d0b02402001410c6a2802002202450d0020012802042200200241f0006c6a2107034002402000410c6a2802002206450d0020002802042102200641246c210603400240024020022d0000220541034b0d0002400240024020050e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022006415c6a22060d000b0b200041f0006a21020240200041086a280200450d002000280204102a0b2002210020022007470d000b0b200141086a280200450d0b2001280204102a0c0b0b2007450d0a0240200141086a2d00002202410c4b0d0020024106470d0b200141106a280200450d0b2001410c6a280200102a0c0b0b200141106a280200450d0a2001410c6a280200102a0c0a0b2008450d09200141086a280200450d092001280204102a0c090b200a450d08200141086a2d0000417f6a220241074b0d08024002400240024020020e08000c0c0c0c010203000b2001410c6a2202280200106a2002280200102a0c0b0b2001410c6a2202280200106a2002280200102a0c0a0b2001410c6a2202280200106a2002280200102a0c090b2001410c6a2202280200106a2002280200102a0c080b2009450d0720012d0004417f6a220241024b0d0702400240024020020e03000102000b2001410c6a280200450d09200141086a280200102a0c090b200141086a2202280200106a2002280200102a0c080b2001410c6a2202280200106a2002280200102a0c070b2017450d0620012d0004417f6a220241024b0d0602400240024020020e03000102000b2001410c6a280200450d08200141086a280200102a0c080b200141086a2202280200106a2002280200102a0c070b2001410c6a2202280200106a2002280200102a0c060b200d450d05200141086a280200417f6a220241014b0d050240024020020e020001000b200141106a280200450d062001410c6a280200102a0c060b200141106a280200450d052001410c6a280200102a0c050b2018450d0420012d00044104490d042001410c6a280200450d04200141086a280200102a0c040b200e450d03200141086a280200450d032001280204102a0c030b200f450d02200141086a2d0000417e6a220241024b0d0202400240024020020e03000102000b200141106a280200450d042001410c6a280200102a0c040b200141346a280200450d03200141306a280200102a0c030b200141306a280200450d022001412c6a280200102a0c020b2019450d0102402001280204220241024b0d00024020020e03030003030b200141086a2202280200106a2002280200102a0c020b2001412c6a2202280200106a2002280200102a0c010b2016450d0002402001410c6a280200450d00200141086a280200102a0b02402001411c6a2802002206450d00200141146a28020021022006410c6c210603400240200241046a280200450d002002280200102a0b2002410c6a2102200641746a22060d000b0b200141186a280200450d002001280214102a0b200341d0076a24000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a360210200041a8c6c200103e000bfa0301077f230041306b22022400200241003602082002420137030020022002360210200141106a200241106a10c8012001200210a00120022002360210200141306a200241106a10c80120022002360210200141d0006a200241106a10c801200128020421032001410c6a2802002201200210b4010240024002402001450d00200141246c21040340200241106a200310ec01200228021021050240024020022802042206200228020822016b20022802182207490d00200228020021060c010b200120076a22082001490d04200641017422012008200120084b1b22014100480d040240024020060d002001102821060c010b200228020020062001102c21060b2006450d032002200136020420022006360200200228020821010b2002200120076a360208200620016a20052007109a051a02402002280214450d002005102a0b200341246a21032004415c6a22040d000b0b200228020421072002280208210320022802002101200241106a41186a22064200370300200241106a41106a22054200370300200241106a41086a220442003703002002420037031020012003200241106a1000200041186a2006290300370000200041106a2005290300370000200041086a20042903003700002000200229031037000002402007450d002001102a0b200241306a24000f0b200141011037000b1031000ba80301047f230041f0006b2202240002400240411010282203450d00200341086a41002900c6f042370000200341002900bef042370000200341104120102c2203450d0120032001360010200241086a41186a22014200370300200241086a41106a22044200370300200241086a41086a220542003703002002420037030820034114200241086a1000200241306a41186a2001290300370300200241306a41106a2004290300370300200241306a41086a2005290300370300200220022903083703302003102a200241086a200241306a412010a703200241d0006a41086a200241116a290000370300200241d0006a41106a2203200241196a290000370300200241d0006a41186a2201200241216a290000370300200220022900093703500240024020022d00084101460d0020004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20002002290350370000200041186a2001290300370000200041106a2003290300370000200041086a200241d0006a41086a2903003700000b200241f0006a24000f0b411041011037000b412041011037000bd50c04077f017e027f017e230041b0016b22012400200141306a41086a220242003703002001420037033041afc5c2004111200141306a1008200141086a200229030037030020012001290330370300200141c0006a2001411010fd0120012d00402103200141106a41186a2204200141d9006a290000370300200141106a41106a2205200141c0006a41116a290000370300200141106a41086a2206200141c9006a290000370300200120012900413703100240024020034101470d0020002001290310370000200041186a2004290300370000200041106a2005290300370000200041086a20062903003700000c010b200141c0006a41086a220342003703002001420037034041b1f0c200410d200141c0006a1008200220032903003703002001200129034037033020014100360240200141306a4110200141c0006a1006210202400240024020012802402203417f460d002002450d002001200336021420012002360210200141c0006a200141106a107620012802402207450d02200129024421082003450d012002102a0c010b41042107420021080b20072008422088a7220941246c6a2104200721020240024002400240034002400240200420026b41ed00490d0003400240200222032d00004101470d00200341246a210a200341106a2105200341086a2106200341016a21020c030b0240200341246a2d00004101470d00200341c8006a210a200341346a21052003412c6a2106200341256a21020c030b0240200341c8006a2d00004101470d00200341ec006a210a200341d8006a2105200341d0006a2106200341c9006a21020c030b0240200341ec006a2d00004101470d0020034190016a210a200341fc006a2105200341f4006a2106200341ed006a21020c030b200420034190016a22026b41ec004b0d000b20034190016a21020b20022004460d020240034020022d00004101460d012004200241246a2202460d040c000b0b200241246a210a200241106a2105200241086a2106200241016a21020b200228000021022006280200210320012005280200360214200120033602100240200241c28289aa04460d00200a21020c010b0b200141c0006a200141106a10ba0220012d004022024102460d00200141a4016a28020021062001280244210a4200210b200141306a41086a220342003703002001420037033041c785c2004112200141306a1008200141c0006a41086a20032903003703002001200129033037034020014100360210200141c0006a4110200141106a100621050240024020012802102203417f460d002001200336023420012005360230200141106a200141306a106d20012802102204450d052001290214210b2003450d012005102a0c010b410121040b410021030240200a200620024101711b2202200b422088a74f0d00200420024105746a2202450d00200141106a41186a200241186a290000370300200141106a41106a200241106a290000370300200141106a41086a200241086a29000037030020012002290000370310410121030b0240200ba7450d002004102a0b20030d010b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b200141c0006a41186a2202200141106a41186a290300370300200141c0006a41106a2203200141106a41106a290300370300200141c0006a41086a2204200141106a41086a29030037030020012001290310370340200141306a41086a220542003703002001420037033041afc5c2004111200141306a1008200141086a2005290300370300200120012903303703002001411036023420012001360230200141c0006a200141306a10ff01200041186a2002290300370000200041106a2003290300370000200041086a2004290300370000200020012903403700000b02402009450d00200941246c21032007210203400240024020022d0000220441034b0d0002400240024020040e0404000102040b2002410c6a280200450d03200241086a280200102a0c030b2002410c6a280200450d02200241086a280200102a0c020b2002410c6a280200450d01200241086a280200102a0c010b200241086a280200450d00200241046a280200102a0b200241246a21022003415c6a22030d000b0b2008a7450d022007102a0c020b41c4d1c30041332001419cd9c3001038000b41c4d1c30041332001419cd9c3001038000b200141b0016a24000b860c07057f017e047f027e037f027e047f230041c0006b22012400200141106a41086a220242003703002001420037031041f09cc600411e200141106a1008200141086a2203200229030037030020012001290310370300200141106a200110de03200128021021042001280214210520012903182106200028020821072000280204210820002802002109200242003703002001420037031041a5afc4004116200141106a100820032002290300370300200120012903103703002001410036021020014110200141106a100621000240024002400240024002400240024020012802102202417f460d002000450d002001200236023420012000360230200141106a200141306a106d2001280210220a450d022001290214210b2002450d012000102a0c010b4101210a4200210b0b2006420020051b210c2004410020051b21042005410420051b210d02402007450d002009200741246c6a210e200a200b422088a74105746a21032009210203402002280220210f200241086a2900002106200241106a290000211020022900002111200141106a41186a200241186a290000370300200141106a41106a2010370300200141106a41086a200637030020012011370310200241246a2102200a2105410021000240024003400240200320056b41e0004b0d0020052003460d030340200141106a2005460d0320002005200141106a4120109c0522074100476a21002007450d032003200541206a2205470d000c040b0b200141106a2005460d0120002005200141106a4120109c0522074100476a21002007450d01200541206a2207200141106a460d0120002007200141106a4120109c0522074100476a21002007450d01200541c0006a2207200141106a460d0120002007200141106a4120109c0522074100476a21002007450d01200541e0006a2207200141106a460d0120054180016a210520002007200141106a4120109c0522074100476a210020070d000b0b2004200f6a22072004490d000240200041016a2204200c422088a722054d0d000240200ca7221220056b20042005200420054b1b221320056b22044f0d00200520046a22142005490d0a201241017422152014201520144b1b221441ffffffff03712014470d0a201441027422154100480d0a0240024020120d0020151028210d0c010b200d20124102742015102c210d0b200d450d062014ad210c0b200d20054102746a21120240024020044102490d002012410020132005417f736a22044102741099051a200d200520136a20056b4102746a417c6a2112200420056a21050c010b2004450d010b20124100360200200541016a21050b200520004d0d05200d20004102746a22002000280200200f6a360200200c42ffffffff0f832005ad42208684210c200721040b2002200e470d000b0b02402008450d002009102a0b0240200ba7450d00200a102a0b200141106a41086a220542003703002001420037031041f09cc600411e200141106a1008200141086a20052903003703002001200129031037030002400240200d0d002001411010090c010b2001410036021820014201370310410410282205450d042005200436000020014284808080c00037021420012005360210200c422088a72205200141106a10b4010240024020050d002001280218210420012802142103200128021021000c010b2005410274210f4100200128021822056b210220012802142103200d210703402007280200210a02400240200320026a4104490d00200128021021000c010b200541046a22002005490d09200341017422042000200420004b1b22044100480d090240024020030d002004102821000c010b200128021020032004102c21000b2000450d082001200436021420012000360210200421030b200741046a21072001200541046a2204360218200020056a200a3600002002417c6a210220042105200f417c6a220f0d000b0b200ca721052001411020002004100702402003450d002000102a0b2005450d00200d102a0b200141c0006a24000f0b41c4d1c3004133200141386a419cd9c3001038000b201541041037000b41ac9bc600200020051034000b410441011037000b200441011037000b1031000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a3602102000419896c400103e000ba70101047f230041206b22002400200041106a41086a2201420037030020004200370310419499c6004114200041106a1008200041086a200129030037030020002000290310370300410021022000410036021020004110200041106a100621010240024020002802102203417f460d002001450d0020034104490d01200128000021022001102a0b200041206a240020020f0b41c4d1c3004133200041106a419cd9c3001038000b9d0401067f230041d0006b220324000240024002400240411b10282204450d00200441176a41002800d89646360000200441106a41002900d19646370000200441086a41002900c99646370000200441002900c196463700002004411b4136102c2204450d012004200136001b200341306a41186a22014200370300200341306a41106a22054200370300200341306a41086a22064200370300200342003703302004411f200341306a1000200341086a41186a22072001290300370300200341086a41106a2005290300370300200341086a41086a2006290300370300200320032903303703082004102a412010282204450d0220042003290308370000200441186a2007290300370000200441106a200341086a41106a2205290300370000200441086a200341086a41086a22062903003700002003200236022c20014200370300200341306a41106a22024200370300200341306a41086a22084200370300200342003703302003412c6a4104200341306a1000200720012903003703002005200229030037030020062008290300370300200320032903303703082004412041c000102c2204450d0320042003290308370020200441386a200341206a290300370000200441306a2005290300370000200441286a2006290300370000200042c0808080800837020420002004360200200341d0006a24000f0b411b41011037000b413641011037000b412041011037000b41c00041011037000bcb0201047f230041d0006b220324002003410036022820012002200341286a1006210402400240024020032802282205417f460d0020040d010b200041003a00000c010b41002101200341003a00480340024020052001470d000240200141ff0171450d00200341003a00480b41c4d1c3004133200341286a419cd9c3001038000b200341286a20016a200420016a2d00003a00002003200141016a22023a00482002210120024120470d000b200341086a41186a2201200341286a41186a290300370300200341086a41106a2202200341286a41106a290300370300200341086a41086a2206200341286a41086a2903003703002003200329032837030802402005450d002004102a0b20002003290308370001200041013a0000200041196a2001290300370000200041116a2002290300370000200041096a20062903003700000b200341d0006a24000bec0202047f017e230041d0006b22022400024002400240410f10282203450d00200341076a4100290092b4433700002003410029008bb4433700002003410f411e102c2203450d012003200136000f200241286a41186a22014200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820034113200241286a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903283703002003102a2002410036022820024120200241286a100621010240024020022802282203417f460d002002200336022420022001360220200241286a200241206a106d20022802282204450d04200229022c210602402003450d002001102a0b20002006370204200020043602000c010b20004100360208200042013702000b200241d0006a24000f0b410f41011037000b411e41011037000b41c4d1c3004133200241c8006a419cd9c3001038000bdf0301017f024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f200128020020012802042002412010072002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000bf54606077f027e0f7f047e117f017e230041800a6b2203240002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e06000102030405000b200341cc026a4101360200200342013702bc02200341ccd1c5003602b802200341043602b406200341c4d1c5003602b0062003200341b0066a3602c802200341b8026a41e893c400103e000b200141e0006a2802002104200341b0066a200141086a41d800109a051a20034198056a200141fc006a28020036020020034190056a200141f4006a29020037030020034180056a41086a200141ec006a2902003703002003200141e4006a29020037038005024020022d000120022d000072450d0041a39fc600210541112104410121060c120b200341b8026a10f70302402003280290032004490d0041f893c400210541352104410121060c120b200341b8026a41086a41033a00002003410c3a00b802200341b8026a410c6a20043602004100210541014100200341b8026a10cc01200341b8026a200341b0066a41d800109a051a2003419c036a20034180056a41086a290300370200200341a4036a20034180056a41106a290300370200200341ac036a20034180056a41186a2802003602002003200436029003200320032903800537029403200341c0086a41086a22024200370300200342003703c00841c0fec5004118200341c0086a100820034180046a41086a2002290300370300200320032903c00837038004200341003602c808200342013703c008200341b8026a200341c0086a10ee0120032802c408210220034180046a411020032802c008220420032802c80810072002450d0f2004102a0c0f0b2001410c6a2802002107200141086a280200210841042104200141046a2802002109200141106a290300210a2002411a6a290100210b200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d00002118200241046a2d00002119200241026a2f0100211a0240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002105200241086a2d00002102410021060c010b4101210641002102410021050b200541ffff0371410874200241187472200441ff017172210202402006450d0041ea9fc6002105410f210402400240024002400240024020020e0700010203040513000b20174108742018722016411874722105201441087420157220134118747221040c120b41dc9fc6002105410e21040c110b41d09fc6002105410c21040c100b41c79fc6002105410921040c0f0b41b49fc6002105411321040c0e0b41a39fc6002105411121040c0d0b2003200b370398042003200c3a0097042003200d3a0096042003200e3b0194042003200f3a009304200320103a009204200320113b019004200320123a008f04200320133a008e04200320143b018c04200320153a008b04200320163a008a04200320173b018804200320183a0087042003200236008304200320193a0082042003201a3b018004200341e8006a10f603024002402003290368220b200341e8006a41086a290300221b8450450d004200211c4200211d0c010b200341c8006a201b4200200a4200109f05200341d8006a200b4200200a4200109f05200341386a42004200200b4200109f0502402003290350200329034084420052200341e0006a290300221c200329034820032903387c7c221d201c5472450d0041a6b5c0002105412721040c0e0b2003290358211c0b200341b8026a20034180046a201c201d4108109802024020032802b8024101470d0020032802c002210420032802bc0221050c0d0b200341c8026a290300211c20032903c002211d200341b8026a10f703200341286a20032903b80242002007ad4200109f050240200a427f200329032820032903304200521b7d221e200a562205450d0041fdbfc2002102412c21040c0b0b200341b0066a20092007200341b8026a10f802024020032802b0064101470d00200341b8066a280200210420032802b40621020c0b0b200341c8096a41186a2206200341b0066a410472220241186a280200360200200341c8096a41106a2216200241106a290200370300200341c8096a41086a2217200241086a290200370300200320022902003703c80920034180056a41186a2213420037030020034180056a41106a2214420037030020034180056a41086a2215420037030020034200370380052009200720034180056a1000200341da016a221820032d0082053a000020034198026a41086a220c20034180056a41136a290000370300200341a5026a220d2013290000370000200320032f0180053b01d8012003200329008b053703980220032800830521022003280087052104200341e0076a41186a2006280200360200200341e0076a41106a2016290300370300200341e0076a41086a2017290300370300200320032903c8093703e007200320043600b706200320023600b306200320182d00003a00b206200320032f01d8013b01b006200341b0066a41136a200c290300370000200341b0066a41186a200d29000037000020032003290398023700bb06411410282206450d03200641002900ddd843370000200641106a41002800edd843360000200641086a41002900e5d84337000020034294808080c0023702fc01200320063602f8012003200341f8016a36028005200341b0066a20034180056a10c80120032802f8012106200328028002211620134200370300201442003703002015420037030020034200370380052006201620034180056a1000200341c0086a41186a2013290300370300200341c0086a41106a2014290300370300200341c0086a41086a201529030037030020032003290380053703c008024020032802fc01450d0020032802f801102a0b200341203602b4062003200341c0086a3602b006200341e0076a200341b0066a10f9020240200341f0076a280200450d0020032802ec07102a0b200341c3066a20034198026a41086a290300370000200341b0066a41186a20034198026a410d6a2900003700002003200341da016a2d00003a00b206200320032f01d8013b01b006200320043600b706200320023600b30620032003290398023700bb06411510282206450d04200641002900c8d8433700002006410d6a41002900d5d843370000200641086a41002900d0d84337000020034295808080d0023702e407200320063602e0072003200341e0076a36028005200341b0066a20034180056a10c80120032802e007210620032802e807211320034180056a41186a2214420037030020034180056a41106a2215420037030020034180056a41086a2216420037030020034200370380052006201320034180056a1000200341c0086a41186a2014290300370300200341c0086a41106a2015290300370300200341c0086a41086a201629030037030020032003290380053703c008024020032802e407450d0020032802e007102a0b200341203602b4062003200341c0086a3602b00620092007200341b0066a10cb0102402008450d002009102a0b200341f8016a41026a200341d8016a41026a2d000022063a000020034180056a41086a221320034198026a41086a29030037030020034180056a410d6a220820034198026a410d6a290000370000200320032f01d80122093b01f801200320032903980237038005200341b0066a41086a41023a0000200341b9066a20093b0000200341bb066a20063a0000200341c0066a20043602002003410c3a00b006200341b0066a410c6a2002360200200341c4066a200329038005370200200341cc066a2013290300370200200341d1066a20082900003700004100211341014100200341b0066a10cc010c0b0b200141c0006a290300210b200141386a290300211d2002411a6a290100211c200241196a2d0000211f200241186a2d00002120200241166a2f01002121200241156a2d00002122200241146a2d00002123200241126a2f01002124200241116a2d00002125200241106a2d000021262002410e6a2f010021272002410d6a2d000021282002410c6a2d000021292002410a6a2f0100212a200241096a2d0000212b41042104200241046a2d0000212c200241026a2f0100212d200141306a280200212e2001412c6a2802002108200141286a28020021092001411d6a290000210a2001411c6a2d000021142001411b6a2d00002115200141196a2f00002116200141186a2d00002117200141176a2d00002118200141156a2f0000210c200141146a2d0000210d200141136a2d0000210e200141116a2f0000210f200141106a2d000021102001410f6a2d000021112001410d6a2f000021122001410c6a2d00002119200141086a2802002105200141076a2d0000211a200141056a2f00002107200141046a2d0000212f200141c8006a290300211b0240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002106200241086a2d00002102410021130c010b4101211341002102410021060b200641ffff0371410874200241187472200441ff01717221060240024002402013450d0041ea9fc6002105410f21040240024002400240024020060e0700060102030410000b202a410874202b722029411874722105202741087420287220264118747221040c0f0b41d09fc6002105410c21040c0e0b41c79fc6002105410921040c0d0b41b49fc6002105411321040c0c0b41a39fc6002105411121040c0b0b202f41ff01714101470d01200341b8026a200541067610fe0120032802b80221040240024020032802c0022005413f7122024b0d00410021020c010b200420024105746a2202290018210a20022d0017211420022d0016211520022f0014211620022d0013211720022d0012211820022f0010210c20022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d000721192002280003210520022d0002211a20022f00002107410121020b024020032802bc02450d002004102a0b20020d010b41dc9fc6002105410e21040c090b2003201c3703c8062003201f3a00c706200320203a00c606200320213b01c406200320223a00c306200320233a00c206200320243b01c006200320253a00bf06200320263a00be06200320273b01bc06200320283a00bb06200320293a00ba062003202a3b01b8062003202b3a00b706200320063600b3062003202c3a00b2062003202d3b01b0062003200a3703d002200320143a00cf02200320153a00ce02200320163b01cc02200320173a00cb02200320183a00ca022003200c3b01c8022003200d3a00c7022003200e3a00c6022003200f3b01c402200320103a00c302200320113a00c202200320123b01c002200320193a00bf02200320053600bb022003201a3a00ba02200320073b01b8022003202e3602c808200320083602c408200320093602c00820034180056a200341b0066a200341b8026a201d200b201b200341c0086a10f5030240024002402003280280054101460d00024020034188056a280200450d00200328028405102a0b41002113410121060c010b4101210620032802840522050d01410021130b41012108410021050c110b20034188056a2802002104024020034190056a280200450d002003418c056a280200102a0b41002113410121080c100b200141386a290300211c200141306a290300211b200141c0006a290300210a200341d8016a41186a200141196a290000370300200341d8016a41106a200141116a290000370300200341d8016a41086a200141096a290000370300200320012900013703d8012002411a6a290100210b200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021092002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d0000211841042104200241046a2d00002119200241026a2f0100211a2001412c6a2802002107200141286a2802002106200141246a28020021080240024020022d00000d0020022d00014101470d00200241056a2d00002104200241066a2f01002105200241086a2d00002102410021130c010b4101211341002105410021020b200541ffff0371410874200441ff017172200241187472210202402013450d00410f210441ea9fc6002105024002400240024002400240024020020e0700010203040506000b20174108742018722016411874722105201441087420157220094118747221040c050b410e210441dc9fc60021050c040b410c210441d09fc60021050c030b4109210441c79fc60021050c020b4113210441b49fc60021050c010b4111210441a39fc60021050b2006450d072008102a0c070b2003200b370390022003200c3a008f022003200d3a008e022003200e3b018c022003200f3a008b02200320103a008a02200320113b018802200320123a008702200320093a008602200320143b018402200320153a008302200320163a008202200320173b018002200320183a00ff01200320023600fb01200320193a00fa012003201a3b01f801200341c8016a10f603024002400240024020032903c801220b200341c8016a41086a29030022308450450d004200211e4200211d0c010b200341a8016a20304200200a4200109f05200341b8016a200b4200200a4200109f0520034198016a42004200200b4200109f05024020032903b00120032903a00184420052200341c0016a290300221e20032903a8012003290398017c7c221d201e5472450d004127210441a6b5c00021050c020b20032903b801211e0b200341b8026a200341f8016a201e201d410810980220032802b8024101470d0120032802c002210420032802bc0221050b2006450d072008102a0c070b200341b8026a41106a290300211e20032903c002211d20034198026a41186a20303703002003200b3703a8022003200a3703a0022003200a37039802200341b8026a10f703200341b8036a4200370300200341e8036a4200370300200341d8036a4200370300200341c8036a42003703002003428080e983b1de163703b00320034280a094a58d1d3703e00320034280a094a58d1d3703d00320034280a094a58d1d3703c003200342808880808080103703f0032003200341b8026a3602f8032003200341b8026a3602fc03200341b0066a41186a2204200341f8016a41186a290300370300200341b0066a41106a2202200341f8016a41106a290300370300200341b0066a41086a2205200341f8016a41086a290300370300200320032903f8013703b00610a003210a1098012113200341b8046a420037030020034180046a412c6a41d0b5c00036020020034180046a41286a4101360200200341a0046a42003703002003419c046a41f8b9c000360200200341d8046a2005290300370300200341e0046a2002290300370300200341e8046a200429030037030020034200370388042003428080808080013703b004410021122003410036029804200320032903b0063703d0042003200341fc036a3602c8042003200341f8036a3602c4042003200341b8026a3602c004200320133602cc042003200a37038004200320073602880520032006360284052003200836028005200341b0066a20034180046a201b201c20034198026a200341d8016a20034180056a10b50120032802b0064101470d0420022802002207410876212f200341bc066a2802002126200341b0066a41086a280200210420032802b406211a41012112410121190c050b200141216a2d0000210620034180056a41186a200141196a29000037030020034180056a41106a200141116a29000037030020034180056a41086a200141096a290000370300200320012900013703800541ad94c400210541e900210420022d00000d0c200228000121130240200641ff01714101460d00201341ff01714101470d0d20134118762104201341087621052002411a6a290100210a200241196a2d00002106200241186a2d00002113200241166a2f01002108200241156a2d00002109200241146a2d00002114200241126a2f01002115200241116a2d00002116200241106a2d000021172002410e6a2f010021182002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241056a2800002102410221100c030b201341ff01714102470d0c2001413a6a290000210a200141396a2d00002106200141386a2d00002113200141366a2f00002108200141356a2d00002109200141346a2d00002114200141326a2f00002115200141316a2d00002116200141306a2d000021172001412e6a2f000021182001412d6a2d0000210c2001412c6a2d0000210d2001412a6a2f0000210e200141296a2d0000210f200141256a2800002102200141246a2d00002104200141226a2f00002105410021100c020b411441011037000b411541011037000b2003200a3703c806200320063a00c706200320133a00c606200320083b01c406200320093a00c306200320143a00c206200320153b01c006200320163a00bf06200320173a00be06200320183b01bc062003200c3a00bb062003200d3a00ba062003200e3b01b8062003200f3a00b706200320023600b306200320043a00b206200320053b01b006200341b8026a20034180056a2010410010c20120032d00b8022102024020032d00c0020d00200341dc026a280200450d00200341d8026a280200102a0b0240200241ff01714101470d00200341b8026a200341b0066a42808086bdbacdd21a420010a502024020032802b8024101470d0020032802c002210420032802bc022105410121060c0c0b200320032903c0023703c0082003200341c8026a2903003703c8082003200341c0086a3602800420034180046a109c010b410021050c080b200341e0066a2802002207410876212f200341b0066a412c6a2802002126200341b0066a41286a2802002104200341d4066a280200211a41012119200741ff01710d00200341b0066a41086a200341a0046a29030037030020034180056a41086a200341bc066a28020036020020032003290398043703b006200320032902b40637038005200341f8096a20034180056a1092014100210741002112410021190b200341f8006a20032903a802200341b0026a29030020032903a002220a4200109f05200329039802200a7d10e50320034188016a200341f8016a2003290378200341f8006a41086a29030010d001200341c0066a201e20034188016a41086a290300220b7d201d200329038801220a54ad7d200b201e7d200a201d54ad7d200a201d58200b201e58200b201e5122021b22051b221c3703002003201d200a7d200a201d7d20051b221b3703b8062003200a201d56200b201e5620021b2202ad220a3703b00641012105024020020d002003201b370380052003201c37038805200320034180056a3602c008200341c0086a109d014100210520032903b006210a0b200341b0066a41086a210202400240200a4200520d002005450d01200320023602800520034180056a109d010c010b200320023602800520034180056a109c010b20032802bc04210520032802b8042106200320032802b40422023602f804200320063602f404200320023602f00420032002200541b0016c6a22163602fc0402402005450d00200341c0086a410172210e200341e7076a210f200341e0076a4102722113200341b0066a41106a2110200341d8066a210d20034194076a2118200341f1066a2108200341d1066a2109200341b0066a4101722117200341a8076a2111034020022d0000210520034180056a200241016a41af01109a051a0240024020054103460d00200320053a00b006201720034180056a41af01109a052106024002400240024020050e03000102000b20032802b806211520032802bc06210620032802b4062105200f201041d800109a051a2003410c3a00c008200e200341e0076a41df00109a051a20052006200341c0086a10cc01410121064100211402402015450d002005102a0b410021150c020b20032f00b106210520032d00b306211420032802b406211520032d00b806210c20032900b906210a20032900c106210b20032900c906211d200341c0086a200d418801109a051a20132006290000370000201341086a200641086a290000370000201341106a200641106a290000370000201341186a200641186a29000037000020034180023b01e007200341c8096a200341c0086a200341e0076a10f401200320032d00d0094102463a00e9082003201d3700e1082003200b3700d9082003200a3700d1082003200c3a00d008200320153602cc08200320143a00cb08200320053b00c908200341043a00c8082003410c3a00c008410021064101211441014100200341c0086a10cc01410021150c010b2011290300210a20032903a007210b200341c8096a41186a200641186a290000370300200341c8096a41106a200641106a290000370300200341c8096a41086a200641086a290000370300200320062900003703c809200341e0076a41186a200941186a290000370300200341e0076a41106a200941106a290000370300200341e0076a41086a200941086a290000370300200320092900003703e007200341c0086a41186a200841186a290000370300200341c0086a41106a200841106a290000370300200341c0086a41086a200841086a290000370300200320082900003703c008200341e8096a41086a201841086a280200360200200320182902003703e809200341c8096a200341e0076a200341c0086a200b200a200341e8096a10f8034101211441012106410121150b024020032d00b006220541014b0d000240024020050e020001000b2014450d03024020032802b806450d0020032802b406102a0b20032d00c0064105490d0320032802e806450d0320032802e406102a0c030b2006450d02200d106a0c020b201520032802980745720d01200328029407102a0c010b2003200241b0016a3602f8040c020b200241b0016a22022016470d000b200320163602f8040b200341f0046a10690240200328028c042202450d0020034190046a280200450d002002102a0b02402019450d0020034180046a411c6a280200210220032802a40421080240024020032802a00422060d00200221050c010b2006211320022105034020052802880b21052013417f6a22130d000b0340200220022f01064102746a41880b6a28020021022006417f6a22060d000b0b200341b0066a411c6a20022f0106360200200341c8066a4100360200200341c4066a2002360200200320083602d006200341003602c006200342003703b806200320053602b406200341003602b006200341b0066a109b010b024020120d0041002105024020040d00410021040c020b201a102a0c010b0240201a0d00410021050c010b0240202f410874200741ff017172450d002026102a0b201a21050b4100210841012106410121130c080b41002113410121062008450d032009102a410121080c070b410121132008450d002009102a0b200341086a200b201b4200201e20051b221e4200109f05200a201e7d10e503200341186a20034180046a2003290308200341086a41086a29030010d001200341c0066a201c200341186a41086a290300220b7d201d2003290318220a54ad7d200b201c7d200a201d54ad7d200a201d58200b201c58200b201c5122051b22061b221b3703002003201d200a7d200a201d7d20061b221e3703b8062003200a201d56200b201c5620051b2205ad220a3703b00641012106024020050d002003201e3703c0082003201b3703c8082003200341c0086a3602e007200341e0076a109d014100210620032903b006210a0b200341b0066a41086a210502400240200a4200520d002006450d01200320053602c008200341c0086a109d010c010b200320053602c008200341c0086a109c010b41002106410021052013450d04200221050c040b41012113410021062008450d002009102a0b410121080c030b0b410121060b41012113410121080b024020012d0000417e6a220241024b0d00024002400240024020020e03000102000b2006450d03200141086a280200450d03200141046a280200102a0c030b20130d010c020b2008450d01200141286a280200450d01200141246a280200102a0c010b2001412c6a280200450d00200141286a280200102a0b2000200436020420002005360200200341800a6a24000be90604057f027e067f027e23004190016b2202240041002103200241003a008801200128020421040240024003402004450d01200241e8006a20036a200128020022052d00003a000020012004417f6a22043602042001200541016a3602002002200341016a22063a0088012006210320064120470d000b200241086a41086a200241e8006a41086a290300370300200241086a41106a200241e8006a41106a290300370300200241086a41186a200241e8006a41186a29030037030020022002290368370308024020044110490d00200541096a2900002107200529000121082001200441706a22093602042001200541116a36020041002103200241003a008801416f210a0340024020092003470d000240200341ff0171450d00200241003a0088010b200042013703000c040b200241e8006a20036a200520036a220641116a2d00003a00002001200420036b416f6a3602042001200641126a3602002002200341016a22063a008801200a417f6a210a2006210320064120470d000b200241286a41086a220b200241e8006a41086a2203290300370300200241286a41106a220c200241e8006a41106a220a290300370300200241286a41186a220d200241e8006a41186a2209290300370300200220022903683703280240200420066b220441706a4110490d002003200241086a41086a290300370300200a200241086a41106a2903003703002009200241086a41186a290300370300200241c8006a41086a220e200b290300370300200241c8006a41106a220b200c290300370300200241c8006a41186a220c200d290300370300200520066a220641116a290000210f200641196a29000021102001200441606a3602042001200641216a3602002002200229030837036820022002290328370348200041206a2010370300200041186a200f370300200041106a200737030020002008370308200041286a2002290368370300200041306a2003290300370300200041386a200a290300370300200041c0006a2009290300370300200041c8006a2002290348370300200041d0006a200e290300370300200041d8006a200b290300370300200041e0006a200c290300370300200042003703000c030b200042013703000c020b200042013703000c010b0240200341ff0171450d00200241003a0088010b200042013703000b20024190016a24000ba80302067f027e230041d0006b2204240002400240411810282205450d00200541002900e3e140370000200541106a41002900f3e140370000200541086a41002900ebe140370000200442988080808003370224200420053602202001200441206a108f012004280228210520042802202106200441306a41186a22074200370300200441306a41106a22084200370300200441306a41086a220942003703002004420037033020062005200441306a1000200441186a2007290300370300200441106a2008290300370300200441086a20092903003703002004200429033037030002402004280224450d002004280220102a0b2004410036023020044120200441306a100621050240024020042802302206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b2001200a2002200a200a200256200b200356200b2003511b22051b22027d200b2003200b20051b22037d200a200254ad7d1090022000200337030820002002370300200441d0006a24000f0b411841011037000b41c4d1c3004133200441306a419cd9c3001038000be40602067f047e230041e0006b22042400024002400240024002400240411410282205450d00200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370234200420053602302001200441306a108f012004280238210520042802302106200441c0006a41186a22074200370300200441c0006a41106a22084200370300200441c0006a41086a220942003703002004420037034020062005200441c0006a1000200441106a41186a2007290300370300200441106a41106a2008290300370300200441106a41086a20092903003703002004200429034037031002402004280234450d002004280230102a0b20044100360240200441106a4120200441c0006a100621050240024020042802402206417f470d004200210a4200210b0c010b20064110490d02200541086a290000210b2005290000210a2005102a0b0240200a2002542205200b200354200b2003511b450d00418991c1002105411521010c060b200441086a20014104200a20027d220a200b20037d2005ad7d220b10bc01200428020822050d04411810282205450d02200541002900e3e140370000200541106a41002900f3e140370000200541086a41002900ebe140370000200442988080808003370234200420053602302001200441306a108f012004280238210520042802302106200441c0006a41186a22074200370300200441c0006a41106a22084200370300200441c0006a41086a220942003703002004420037034020062005200441c0006a1000200441106a41186a2007290300370300200441106a41106a2008290300370300200441106a41086a20092903003703002004200429034037031002402004280234450d002004280230102a0b20044100360240200441106a4120200441c0006a100621050240024020042802402206417f470d004200210c4200210d0c010b20064110490d04200541086a290000210d2005290000210c2005102a0b2001200c20027c2202200d20037c2002200c54ad7c1090022001200a200b108f02410021050c050b411441011037000b41c4d1c3004133200441c0006a419cd9c3001038000b411841011037000b41c4d1c3004133200441c0006a419cd9c3001038000b200428020c21010b2000200136020420002005360200200441e0006a24000bd9140a057f017e067f037e037f017e017f027e077f057e23002204210520044180026b4160712204240002400240200141ffffff3f712001470d0020014105742206417f4c0d0002400240024020060d00410121070c010b200610282207450d010b410021084100210602402001450d002001410574210820072106034020062000290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a290000370000200641206a2106200041206a2100200841606a22080d000b200141057441606a41057641016a2106200121080b20042006360218200420083602142004200736021020072006410041202006676b10c40242002109200441b0016a41086a22004200370300200442003703b00141cf96c300411d200441b0016a1008200441e0016a41086a2000290300370300200420042903b0013703e001200441003602b001200441e0016a4110200441b0016a1006210602400240024020042802b0012200417f460d0020042000360294012004200636029001200441b0016a20044190016a106d20042802b001220a450d0220042902b40121092000450d012006102a0c010b4101210a0b2009422088a72200450d032000410574210b200441e0016a410c6a210c200441e0016a411472210d200441e0016a410872210e200441c0006a410c72210f200a210002400340200041086a2900002110200041106a290000211120002900002112200441206a41186a2213200041186a290000370300200441206a41106a22142011370300200441206a41086a22152010370300200420123703200240024002400240411a10282206450d00200641002900ec96432216370000200641186a41002f0084974322173b0000200641106a41002900fc96432218370000200641086a41002900f4964322193700002004429a808080a0033702b401200420063602b0012004200441b0016a3602e001200441206a200441e0016a10c80120042802b001210720042802b801211a200441e0016a41186a22014200370300200441e0016a41106a22064200370300200441e0016a41086a22084200370300200442003703e0012007201a200441e0016a100020044190016a41186a221b200129030037030020044190016a41106a221c200629030037030020044190016a41086a221a2008290300370300200420042903e00137039001024020042802b401450d0020042802b001102a0b200441003602e00120044190016a4120200441e0016a1006211d20042802e0012207417f460d02200420073602642004201d360260200441e0016a200441e0006a10b30320042802e801221e450d01200441b0016a41086a221f200c41086a290200370300200441b0016a41106a2220200c41106a2802003602002004200c2902003703b00120042903e001211002402007450d00201d102a0b200f20042903b00122113702002006202028020022073602002008201f2903002212370300200f41086a2012370200200f41106a2007360200200420113703e001200420103703400c030b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b2006200441b0016a41106a2802003602002008200441b0016a41086a290300370300200420042903b0013703e0014100211e0b2004201e360248200441003602e80120042903582112200420042903f801222137035820042903502122200420042903f001222337035020042903402124200420042903e001221137034020042903482110200420042903e80122253703482025a72107024002402010a7221d0d002025211020232122202121120c010b200420243703e001200420103703e801200420223703f001200420123703f8012004201d2022a74105746a3602bc012004201d3602b80120042010422088a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200e41086a201a280200360200200e20042903900137020020042022422088a7221d2012422088a74105746a3602bc012004201d3602b80120042012a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200d41086a201a280200360200200d20042903900137020020042903e801211020042903e001211120042903f801211220042903f001212202402007450d002021a7211d02402025422088a7450d002007102a0b201d450d002023422088a7102a0b200420113703402004201037034820042022370350200420123703582010a721070b2004201137036020042010370368200420223703702004201237037802400240024020070d00200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0220072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b20044190016a412010090c010b200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0320072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b200441203602e401200420044190016a3602e001200441e0006a200441e0016a10b4030b02402010a72206450d002012a7210802402010422088a7450d002006102a0b2008450d002022422088a7102a0b200041206a2100200b41606a220b0d010c060b0b411a41011037000b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b200641011037000b1036000b02402009a7450d00200a102a0b200441003602e801200442013703e0012003200441e0016a10b40102402003450d002003410574210003402002200441e0016a108f01200241206a2102200041606a22000d000b0b20042802e401210620042802e801210820042802e0012100200441b0016a41086a22014200370300200442003703b0014196f0c200411b200441b0016a1008200441e0016a41086a2001290300370300200420042903b0013703e001200441e0016a411020002008100702402006450d002000102a0b02402004280214450d002004280210102a0b200524000bb80901177f230041206b220424002002410020031b21052000410020011b2106200241206a200220031b2107200041206a200020011b2108200020014105746a2109200220034105746a210a4100210b4100210c4101210d4100210e4100210f41012110024002400340200b4101742111200b4105742112024002400240024002400340024020050d0020072113200d2114200c2115200b21160c040b2005210220072103200d2114200c2115200b2116201221172011211802400340024002402006450d0020022006460d06200220064120109c052213450d062013417f4c0d01200321072014210d2015210c2016210b200221050c080b200441186a2203200541186a290000370300200441106a2216200541106a290000370300200441086a2206200541086a290000370300200420052900003703000240200b200c470d00200b41016a2202200b490d0c200b41017422172002201720024b1b220c41ffffff3f71200c470d0c200c41057422024100480d0c02400240200b0d0020021028210d0c010b200d200b4105742002102c210d0b200d450d030b200d200b4105746a22022004290300370000200241186a2003290300370000200241106a2016290300370000200241086a200629030037000041002106410020072007200a4622021b2105201141026a2111201241206a2112200b41016a210b2007200741206a20021b21070c030b200441186a2213200241186a290000370300200441106a2219200241106a290000370300200441086a221a200241086a29000037030020042002290000370300024020162015470d00201641016a22022016490d0b20182002201820024b1b221541ffffff3f712015470d0b201541057422024100480d0b0240024020160d002002102821140c010b201420172002102c21140b2014450d040b201420176a22022004290300370000200241186a2013290300370000200241106a2019290300370000200241086a201a290300370000410020032003200a4622131b2102201841026a2118201741206a2117201641016a21162003200341206a20131b221321032002450d050c000b0b0b200241011037000b200241011037000b2014210d2015210c2016210b2003200341206a2003200a4622021b210741002008200820094622161b21064100200320021b21052008200841206a20161b21080c030b410021052006450d01201321072014210d2015210c2016210b0b200441186a2203200641186a290000370300200441106a2216200641106a290000370300200441086a2217200641086a290000370300200420062900003703000240200e200f470d00200e41016a2202200e490d04200e41017422062002200620024b1b220f41ffffff3f71200f470d04200f41057422024100480d0402400240200e0d002002102821100c010b2010200e4105742002102c21100b2010450d030b2010200e4105746a22022004290300370000200241186a2003290300370000200241106a2016290300370000200241086a201729030037000041002008200820094622021b2106200e41016a210e2008200841206a20021b21080c010b0b201420162000200110840202402015450d002014102a0b0240200f450d002010102a0b200441206a24000f0b200241011037000b1031000ba8ca0106017f027e057f017e217f0b7e230041e0046b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e0b000102030405060c0d0e0f000b20034184036a4101360200200342013702f402200341ccd1c5003602f002200341043602b404200341c4d1c5003602b0042003200341b0046a36028003200341f0026a41a0f8c100103e000b200141206a2903002104200141186a29030021052001410c6a2802002106200141086a2802002107200141146a2802002108200141106a28020021092001280204210a2002411a6a290100210b200241196a2d0000210c200241186a2d0000210d200241166a2f0100210e200241156a2d0000210f200241146a2d00002110200241126a2f01002111200241116a2d00002112200241106a2d000021132002410e6a2f010021142002410d6a2d000021152002410c6a2d000021162002410a6a2f01002117200241096a2d0000211841042119200241046a2d0000211a200241026a2f0100211b0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d410021024100211c0b2003200b370380012003200c3a007f2003200d3a007e2003200e3b017c2003200f3a007b200320103a007a200320113b0178200320123a0077200320133a0076200320143b0174200320153a0073200320163a0072200320173b0170200320183a006f2003201a3a006a2003201b3b01682003201c41ffff0371410874200241187472201941ff017172221c36006b201d450d0e410f210241ea9fc60021190240024002400240024002400240201c0e0700010203040506000b200328006f2119200328007321020c050b410e210241dc9fc60021190c040b410c210241d09fc60021190c030b4109210241c79fc60021190c020b4113210241b49fc60021190c010b4111210241a39fc60021190b4100210c4101211d2007450d43200a102a0c430b200141206a2903002104200141186a29030021052001410c6a2802002106200141086a280200211b200141146a2802002108200141106a28020021092001280204210a2002411a6a290100210b200241196a2d0000210c200241186a2d00002107200241166a2f0100210d200241156a2d0000210e200241146a2d0000210f200241126a2f01002110200241116a2d00002111200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d0000211741042119200241046a2d00002118200241026a2f0100211a0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d410021024100211c0b2003200b3703e8022003200c3a00e702200320073a00e6022003200d3b01e4022003200e3a00e3022003200f3a00e202200320103b01e002200320113a00df02200320123a00de02200320133b01dc02200320143a00db02200320153a00da02200320163b01d802200320173a00d702200320183a00d2022003201a3b01d0022003201c41ffff0371410874200241187472201941ff017172221c3600d3020240201d450d00410f210241ea9fc6002119024002400240024002400240201c0e0700010203040548000b20032800d702211920032800db0221020c470b410e210241dc9fc60021190c460b410c210241d09fc60021190c450b4109210241c79fc60021190c440b4113210241b49fc60021190c430b4111210241a39fc60021190c420b20034188046a41186a200341d0026a41186a29030037030020034188046a41106a200341d0026a41106a29030037030020034188046a41086a200341d0026a41086a290300370300200320032903d00237038804410d10282202450d0e200241002900b0f841370000200241056a41002900b5f8413700002003428d808080d0013702f402200320023602f00220034188046a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341e8006a41186a201c290300370300200341e8006a41106a201d290300370300200341e8006a41086a200c290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b200341003602f002200341e8006a4120200341f0026a1006211c20032802f002221d417f460d3f201c450d3f41002102200341003a009003024002400340201d2002460d01200341f0026a20026a201c20026a2d00003a00002003200241016a22193a0090032019210220194120470d000b200341b0046a41186a2202200341f0026a41186a290300370300200341b0046a41106a200341f0026a41106a290300370300200341b0046a41086a200341f0026a41086a290300370300200320032903f0023703b004201941ff0171411f4d0d01200341e0036a41086a2219200341c3046a290000370300200341e0036a410d6a220c2002290000370000200341e8016a41026a220720032d00b2043a0000200341a8026a41086a2019290300370300200341a8026a410d6a220d200c290000370000200320032f01b0043b01e801200320032900bb043703a80220032800b304211920032800b70421020240201d450d00201c102a0b200341b0046a41026a20072d00003a0000200341f0026a41086a200341a8026a41086a290300370300200341f0026a410d6a200d290000370000200320032f01e8013b01b004200320032903a8023703f0024101211c0c420b200241ff0171450d00200341003a0090030b41c4d1c3004133200341d8046a419cd9c3001038000b200141216a290000210b200141206a2d000021072001411d6a2f0000210d2001411c6a2d0000210e200141196a2f0000210f200141186a2d00002110200141156a2f00002111200141146a2d00002112200141116a2f00002113200141106a2d000021142001410c6a280200211c200141086a2d0000211e200141306a280200211f2001412c6a280200212020012d001f211520012d001b211620012d0017211720012d0013211820012d000b211a20012f0009211b200128020421212002411a6a2901002104200241196a2d00002122200241186a2d00002123200241166a2f01002124200241156a2d00002125200241146a2d00002126200241126a2f01002127200241116a2d00002128200241106a2d0000210a2002410e6a2f010021062002410d6a2d000021082002410c6a2d000021092002410a6a2f01002129200241096a2d0000212a41042119200241046a2d0000212b200241026a2f0100212c0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211d200241086a2d000021024100210c0c010b4101210c410021024100211d0b201d41ffff0371410874200241187472201941ff017172211d0240200c450d00410f210241ea9fc60021190240201d0e0700050607083e3f000b2029410874202a7220094118747221192006410874200872200a4118747221020c3e0b200320043703a002200320223a009f02200320233a009e02200320243b019c02200320253a009b02200320263a009a02200320273b019802200320283a0097022003200a3a009602200320063b019402200320083a009302200320093a009202200320293b0190022003202a3a008f022003201d36008b022003202b3a008a022003202c3b0188020240201e41ff01714101470d00200341f0026a201c41067610fe0120032802f00221190240024020032802f802201c413f7122024b0d00410021020c010b201920024105746a2202290018210b20022d0017210720022d0016211520022f0014210d20022d0013210e20022d0012211620022f0010210f20022d000f211020022d000e211720022f000c211120022d000b211220022d000a211820022f0008211320022d000721142002280003211c20022d0002211a20022f0000211b410121020b024020032802f402450d002019102a0b2002450d3c0b2003200b3703c002200320073a00bf02200320153a00be022003200d3b01bc022003200e3a00bb02200320163a00ba022003200f3b01b802200320103a00b702200320173a00b602200320113b01b402200320123a00b302200320183a00b202200320133b01b002200320143a00af022003201c3600ab022003201a3a00aa022003201b3b01a802200341b0046a41086a22024200370300200342003703b00441b8a2c1004114200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703680240200341e8006a41104101410041001003417f460d0041bdf8c1002119412621020c3e0b411310282202450d0e200241002900c2a3413700002002410f6a41002800d1a341360000200241086a41002900caa34137000020034293808080b0023702f402200320023602f00220034188026a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341d0026a41186a201c290300370300200341d0026a41106a201d290300370300200341d0026a41086a200c290300370300200320032903b0043703d002024020032802f402450d0020032802f002102a0b200341003602f002200341d0026a4120200341f0026a1006210220032802f0022219417f460d102002450d10200320193602b404200320023602b004200341f0026a200341b0046a10c20220032903f0024201510d0f02402019450d002002102a0b411310282202450d11200241002900c2a3413700002002410f6a41002800d1a341360000200241086a41002900caa34137000020034293808080b0023702f402200320023602f002200341a8026a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341d0026a41186a201c290300370300200341d0026a41106a201d290300370300200341d0026a41086a200c290300370300200320032903b0043703d002024020032802f402450d0020032802f002102a0b200341003602f002200341d0026a4120200341f0026a1006210220032802f0022219417f460d132002450d13200320193602b404200320023602b004200341f0026a200341b0046a10c20220032903f0024201510d1220034198036a280200211002402019450d002002102a0b200341b0046a41086a22024200370300200342003703b004418891c6004111200341b0046a1008200341e8006a41086a2002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221c417f460d002002450d00201c4104490d15200228000021192002102a0b02402019201f460d0041e3f8c1002119411621020c3e0b0240201041016a201f490d0041f9f8c1002119411f21020c3e0b410e10282202450d15200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2202450d162002202141067636000e200341b0046a41186a22194200370300200341b0046a41106a221c4200370300200341b0046a41086a221d4200370300200342003703b00420024112200341b0046a1000200341d0026a41186a2019290300370300200341d0026a41106a201c290300370300200341d0026a41086a201d290300370300200320032903b0043703d0022002102a200341003602f002200341d0026a4120200341f0026a1006210220032802f0022219417f460d342002450d34200320193602b404200320023602b004200341f0026a200341b0046a107420032802f002220c450d172021413f71211c20032902f402210b02402019450d002002102a0b4100211d201c200b422088a74f0d32200c201c41216c6a22192d00004101470d32200341a6016a201941036a2d00003a000020034188016a41086a201941146a29000037030020034195016a201941196a290000370000200320192f00013b01a40120032019410c6a29000037038801201941086a2800002102201941046a28000021194101211d0c330b2001280204211b2002411a6a290100210b200241196a2d0000210c200241186a2d00002107200241166a2f0100210d200241156a2d0000210e200241146a2d0000210f200241126a2f01002110200241116a2d00002111200241106a2d000021122002410e6a2f010021132002410d6a2d000021142002410c6a2d000021152002410a6a2f01002116200241096a2d0000211741042119200241046a2d00002118200241026a2f0100211a0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d410021024100211c0b2003200b3703e8022003200c3a00e702200320073a00e6022003200d3b01e4022003200e3a00e3022003200f3a00e202200320103b01e002200320113a00df02200320123a00de02200320133b01dc02200320143a00db02200320153a00da02200320163b01d802200320173a00d702200320183a00d2022003201a3b01d0022003201c41ffff0371410874200241187472201941ff017172221c3600d3020240201d450d00410f210241ea9fc60021190240201c0e0700040506073d3e000b20032800d702211920032800db0221020c3d0b20034188046a41186a200341d0026a41186a29030037030020034188046a41106a200341d0026a41106a29030037030020034188046a41086a200341d0026a41086a290300370300200320032903d00237038804200341b0046a41086a22024200370300200342003703b00441b8a2c1004114200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703680240200341e8006a41104101410041001003417f460d0041d9fac1002119411e21020c3d0b411310282202450d17200241002900c2a3413700002002410f6a41002800d1a341360000200241086a41002900caa34137000020034293808080b0023702f402200320023602f00220034188046a200341f0026a108f0120032802f802211920032802f002211c41182102200341b0046a41186a221d4200370300200341b0046a41106a220c4200370300200341b0046a41086a22074200370300200342003703b004201c2019200341b0046a1000200341d0026a41186a201d290300370300200341d0026a41106a200c290300370300200341d0026a41086a2007290300370300200320032903b0043703d002024020032802f402450d0020032802f002102a0b0240200341d0026a41204101410041001003417f470d0041f7fac10021190c3d0b410e10282202450d18200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2219450d192019201b41067636000e41182102200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420194112200341b0046a1000200341e8006a41186a201c290300370300200341e8006a41106a201d290300370300200341e8006a41086a200c290300370300200320032903b0043703682019102a200341003602b004200341e8006a4120200341b0046a1006211c20032802b0042219417f460d1b200320193602e4032003201c3602e003200341b0046a200341e0036a107420032802b004221d450d1a201b413f71210220032902b404210b02402019450d00201c102a0b4100211c2002200b422088a74f0d2e201d200241216c6a22192d00004101470d2e20034186026a201941036a2d00003a0000200341e8016a41086a201941146a290000370300200341f5016a201941196a290000370000200320192f00013b01840220032019410c6a2900003703e801201941086a2800002102201941046a28000021194101211c0c2f0b2001280204210c2002411a6a290100210b200241196a2d00002112200241186a2d00002113200241166a2f01002114200241156a2d00002115200241146a2d00002116200241126a2f01002117200241116a2d00002118200241106a2d000021072002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d0000211141042119200241046a2d0000211a200241026a2f0100211b0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d4100211c410021020b201c41ffff0371410874201941ff017172200241187472211c0240201d450d00410f210241ea9fc60021190240201c0e0700030405063c3d000b2010410874201172200f411874722119200d410874200e7220074118747221020c3c0b2003200b3703a004200320123a009f04200320133a009e04200320143b019c04200320153a009b04200320163a009a04200320173b019804200320183a009704200320073a0096042003200d3b0194042003200e3a0093042003200f3a009204200320103b019004200320113a008f042003201c36008b042003201a3a008a042003201b3b018804411610282202450d1b20024100290093a2413700002002410e6a41002900a1a241370000200241086a410029009ba24137000020034296808080e0023702f402200320023602f00220034188046a200341f0026a108f0120032802f802210220032802f0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a22074200370300200342003703b00420192002200341b0046a1000200341e8006a41186a201c290300370300200341e8006a41106a201d290300370300200341e8006a41086a2007290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b4101211d0240200341e8006a41204101410041001003417f460d00418ffbc1002119411e21024101210c0c400b200341b0046a41086a22024200370300200342003703b00441bf91c6004116200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703684100211c200341003602f002200341e8006a4110200341f0026a10062102024020032802f0022219417f460d002002450d0020194104490d1d2002280000211c2002102a0b200341b0046a41086a22024200370300200342003703b00441b0a3c1004112200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a100621020240024020032802f0022219417f460d002002450d00200320193602b404200320023602b004200341f0026a200341b0046a106d20032802f0022207450d1f20032902f402210b02402019450d002002102a0b200b422088a7210d0c010b4100210d4200210b410121070b0240024002400240201c200c470d00200d200c460d010b41adfbc100211941162102200d200c4d0d01200c200b422088a7220d4f0d2120034188036a420037030020034180036a4200370300200341f8026a4200370300200342003703f0022007200c4105746a220d200341f0026a460d00200d200341f0026a4120109c050d010b200341306a20034188046a4280809aa6eaafe30142001083022003280230450d0141c3fbc1002119411e21020b0240200ba7450d002007102a0b4101210c0c400b200341b0046a41086a22024200370300200342003703b004418891c6004111200341b0046a1008200341e8006a41086a2002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221d417f460d002002450d00201d4104490d20200228000021192002102a0b411610282202450d2020024100290093a2413700002002410e6a41002900a1a241370000200241086a410029009ba24137000020034296808080e0023702f402200320023602f00220034188046a200341f0026a108f0120032802f802210220032802f002211d200341b0046a41186a220d4200370300200341b0046a41106a220e4200370300200341b0046a41086a220f4200370300200342003703b004201d2002200341b0046a1000200341e8006a41186a200d290300370300200341e8006a41106a200e290300370300200341e8006a41086a200f290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b410810282202450d212002200c36000420022019360000200341e8006a41202002410810072002102a200ba7211d02400240200c200b422088a72202460d00200341d0026a41186a220d20034188046a41186a290300370300200341d0026a41106a220e20034188046a41106a290300370300200341d0026a41086a20034188046a41086a29030037030020032003290388043703d002200c20024f0d242007200c4105746a221920032903d002370000201941186a200d290300370000201941106a200e290300370000201941086a200341d0026a41086a2903003700000c010b200341d0026a41186a221920034188046a41186a290300370300200341d0026a41106a220d20034188046a41106a290300370300200341d0026a41086a20034188046a41086a29030037030020032003290388043703d0020240200c201d470d00200c41016a2202200c490d38200c410174221d2002201d20024b1b221d41ffffff3f71201d470d38201d41057422024100480d3802400240200c0d002002102821070c010b2007200c4105742002102c21070b2007450d25200b422088a7210c0b2007200c4105746a220220032903d002370000200241186a2019290300370000200241106a200d290300370000200241086a200341d0026a41086a290300370000200c41016a21020b200341b0046a41086a22194200370300200342003703b00441b0a3c1004112200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200341003602f802200342013703f0022002200341f0026a10b40102402002450d00200241057421192007210203402002200341f0026a108f01200241206a2102201941606a22190d000b0b20032802f4022102200341e8006a411020032802f002221920032802f802100702402002450d002019102a0b0240201d450d002007102a0b200341b0046a41086a22024200370300200342003703b00441bf91c6004116200341b0046a1008200341e8006a41086a2002290300370300200320032903b0043703684101211d2003201c41016a3602f002200341e8006a4110200341f0026a41041007410021194101210c0c3f0b200141386a2903002104200141306a29030021052001411d6a290000210b2001411c6a2d00002112200141196a2f00002113200141186a2d00002114200141156a2f00002115200141146a2d00002116200141116a2f00002117200141106a2d000021182001410d6a2f0000211a2001410c6a2d0000211b200141086a280200210c200141286a280200211f20012d001b210a20012d0017210620012d0013210820012d000f210920012d0007212920012f0005212a20012d0004212c2002411a6a290100212d200241196a2d0000211e200241186a2d00002122200241166a2f01002123200241156a2d00002124200241146a2d00002125200241126a2f01002126200241116a2d00002127200241106a2d000021072002410e6a2f0100210d2002410d6a2d0000210e2002410c6a2d0000210f2002410a6a2f01002110200241096a2d0000211141042119200241046a2d00002128200241026a2f0100212b0240024020022d00000d0020022d00014101470d00200241056a2d00002119200241066a2f0100211c200241086a2d000021024100211d0c010b4101211d4100211c410021020b201c41ffff0371410874201941ff017172200241187472211c201d450d04410f210241ea9fc60021190240201c0e0700010203043a3b000b2010410874201172200f411874722119200d410874200e7220074118747221020c3a0b410e210241dc9fc60021190c390b410c210241d09fc60021190c380b4109210241c79fc60021190c370b4113210241b49fc60021190c360b2003202d3703f8032003201e3a00f703200320223a00f603200320233b01f403200320243a00f303200320253a00f203200320263b01f003200320273a00ef03200320073a00ee032003200d3b01ec032003200e3a00eb032003200f3a00ea03200320103b01e803200320113a00e7032003201c3600e303200320283a00e2032003202b3b01e0030240200520048450450d00419ffcc100211941d00021020c360b02400240202c41ff01714101470d00200341f0026a200c41067610fe0120032802f00221190240024020032802f802200c413f7122024b0d00410021020c010b201920024105746a2202290018210b20022d0017211220022d0016210a20022f0014211320022d0013211420022d0012210620022f0010211520022d000f211620022d000e210820022f000c211720022d000b211820022d000a210920022f0008211a20022d0007211b2002280003210c20022d0002212920022f0000212a410121020b024020032802f402450d002019102a0b20020d00410121020c010b410021020b2003200b3701e802200320123a00e7022003200a3a00e602200320133b01e402200320143a00e302200320063a00e202200320153b01e002200320163a00df02200320083a00de02200320173b01dc02200320183a00db02200320093a00da022003201a3b01d8022003201b3a00d7022003200c3600d302200320293a00d2022003202a3b01d00220020d3320034188046a41186a200341d0026a41186a29010037030020034188046a41106a200341d0026a41106a29010037030020034188046a41086a200341d0026a41086a290100370300200320032901d00237038804200341b0046a41086a22024200370300200342003703b004418891c6004111200341b0046a1008200341e8006a41086a2002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221c417f460d002002450d00201c4104490d1f200228000021192002102a0b02402019201f460d00418efcc1002119411121020c360b200341b0046a41086a22024200370300200342003703b00441b8a2c1004114200341b0046a1008200341e8006a41086a22192002290300370300200320032903b004370368200341f0026a200341e8006a10be02024020032802f802220d0d0041e1fbc1002119412d21020c360b20032902fc02212e20024200370300200342003703b00441ad91c6004112200341b0046a100820192002290300370300200320032903b00437036841002119200341003602f002200341e8006a4110200341f0026a10062102024020032802f002221c417f460d002002450d00201c4104490d20200228000021192002102a0b200341d8006a2019ad42004280a094a58d1d4200109f05200341d8006a41086a290300210b411410282202450d202003290358212f200241002900cfe140370000200241106a41002800dfe140360000200241086a41002900d7e14037000020034294808080c0023702d402200320023602d002200341e0036a200341d0026a108f0120032802d802210220032802d0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341f0026a41186a201c290300370300200341f0026a41106a201d290300370300200341f0026a41086a200c290300370300200320032903b0043703f002024020032802d402450d0020032802d002102a0b200341003602b004200341f0026a4120200341b0046a1006210220032802b0042219417f460d252002450d2520194110490d21200241086a290000212d200229000021302002102a0c260b4101211d20022d000120022d0000720d2320012802042102200341b0046a41086a22194200370300200342003703b00441f490c6004114200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200320023602f002200341e8006a4110200341f0026a41041007410021194101210c0c380b024020022d000120022d000072450d0041a39fc6002119411121020c340b200141086a2802002119024020012d00044101460d00200141106a2d0000211c200141146a2d0000211d200141186a2d0000210c2001411c6a2d0000210720012f0005210220012d0007210d20012d000c210e20012f000d210f20012d000f211020012f0011211120012d0013211220012f0015211320012d0017211420012f0019211520012d001b2116200129001d210b0c210b200341f0026a201941067610fe0120032802f00221170240024020032802f8022019413f7122024b0d00410021180c010b201720024105746a2202290018210b20022d0017210720022d0016211620022f0014211520022d0013210c20022d0012211420022f0010211320022d000f211d20022d000e211220022f000c211120022d000b211c20022d000a211020022f0008210f20022d0007210e2002280003211920022d0002210d20022f00002102410121180b024020032802f402450d002017102a0b20180d20410121170c210b4101211d20022d000120022d0000720d2120012802042102200341b0046a41086a22194200370300200342003703b00441f0a2c100411c200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200320023602f002200341e8006a4110200341f0026a41041007410021194101210c0c360b4101211d20022d000120022d0000720d2020012802042102200341b0046a41086a22194200370300200342003703b00441dca2c1004114200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200320023602f002200341e8006a4110200341f0026a41041007410021194101210c0c350b200341d0026a41186a200341e8006a41186a290300220b370300200341d0026a41106a200341e8006a41106a290300222d370300200341d0026a41086a200341e8006a41086a290300222e37030020032003290368222f3703d002200341f0026a41186a200b370300200341f0026a41106a202d370300200341f0026a41086a202e3703002003202f3703f002200320063602b804200320073602b4042003200a3602b0042003200341f0026a200341b0046a200920082005200410d40220032802042102200328020021194100210c4101211d0c340b410d41011037000b411341011037000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4f9c1002119411821020c2c0b411341011037000b41c4d1c3004133200341d8046a419cd9c3001038000b4198f9c1002119412c21020c290b41c4d1c3004133200341d8046a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200341d8046a419cd9c3001038000b411341011037000b410e41011037000b411c41011037000b41c4d1c3004133200341d8046a419cd9c3001038000b4101211c41a8fac10021190c140b411641011037000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b41cca2c100200c200d1034000b41c4d1c3004133200341d8046a419cd9c3001038000b411641011037000b410841011037000b41a0a3c100200c20021034000b200241011037000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b411441011037000b41c4d1c3004133200341d8046a419cd9c3001038000b410021170b2003200b37018001200320073a007f200320163a007e200320153b017c2003200c3a007b200320143a007a200320133b01782003201d3a0077200320123a0076200320113b01742003201c3a0073200320103a00722003200f3b01702003200e3a006f2003201936006b2003200d3a006a200320023b016820170d0f200341d0026a41186a200341e8006a41186a290100370300200341d0026a41106a200341e8006a41106a290100370300200341d0026a41086a200341e8006a41086a2202290100370300200320032901683703d002200341b0046a41086a22194200370300200342003703b00441a9a2c100410f200341b0046a100820022019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a10062102024002400240024002400240024020032802f0022219417f460d002002450d00200320193602b404200320023602b004200341f0026a200341b0046a107d20032802f002221c450d0220032902f402210b2019450d012002102a0c010b4200210b4104211c0b200ba72111024002400240200b422088a72207450d00201c200741246c221d6a210c410021190340200341f0026a41206a201c20196a220241206a280200360200200341f0026a41186a200241186a290200370300200341f0026a41106a200241106a290200370300200341f0026a41086a200241086a290200370300200320022902003703f002200341f0026a200341d0026a4120109c050d02201d201941246a2219470d000b0b4104210f4100210d024020110d00410021100c020b201c102a410021100c010b20034188046a41086a200341f0026a41086a290300220b370300200341e0036a41086a221d200b370300200341e0036a41106a220d200341f0026a41106a290300370300200341e0036a41186a220e200341f0026a41186a290300370300200341e0036a41206a2210200341f0026a41206a280200360200200320032903f002220b370388042003200b3703e00341241028220f450d02200f20032903e003370200200f41206a2010280200360200200f41186a200e290300370200200f41106a200d290300370200200f41086a201d29030037020002400240200741246c415c6a2019470d004101210d410121100c010b200241246a2113200c415c6a21144101210d4101211003402013210202400340200341f0026a41206a2219200241206a280200360200200341f0026a41186a221d200241186a290200370300200341f0026a41106a2207200241106a290200370300200341f0026a41086a220e200241086a290200370300200320022902003703f002200341f0026a200341d0026a4120109c050d01200c200241246a2202470d000c030b0b200341b0046a41206a2019280200221236020020034188046a41086a200e290300220b37030020034188046a41106a2007290300220437030020034188046a41186a201d290300220537030020034188046a41206a2012360200200320032903f002222d3703880420192012360200201d200537030020072004370300200e200b3703002003202d3703f00202402010200d470d00200d41016a2210200d490d15200d41017422122010201220104b1b2210ad42247e220b422088a70d15200ba722124100480d1502400240200d0d0020121028210f0c010b200f200d41246c2012102c210f0b200f450d060b200241246a2113200f200d41246c6a221220032903f002370200201241206a2019280200360200201241186a201d290300370200201241106a2007290300370200201241086a200e290300370200200d41016a210d20142002470d000b0b2011450d00201c102a0b200341b0046a41086a22024200370300200342003703b00441a9a2c100410f200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f802200342013703f002200d200341f0026a10b4010240200d450d00200f200d41246c6a2107200f211903402019200341f0026a108f01201941206a280200211d0240024020032802f402221c20032802f80222026b4104490d0020032802f002211c0c010b200241046a220c2002490d14201c4101742202200c2002200c4b1b22024100480d1402400240201c0d0020021028211c0c010b20032802f002201c2002102c211c0b201c450d06200320023602f4022003201c3602f00220032802f80221020b2003200241046a3602f802201c20026a201d3600002007201941246a2219470d000b0b20032802f4022102200341e8006a411020032802f002221920032802f802100702402002450d002019102a0b200d41246c220241246d210c4100211c0240024020020d00410121074100210c0c010b200c41ffffff3f71200c470d12200c41057422024100480d12200210282207450d050b0240200d450d00200d41246c211d4100211c20072102200f21190340201941086a290000210b201941106a290000210420192900002105200241186a201941186a290000370000200241106a2004370000200241086a200b37000020022005370000201c41016a211c200241206a2102201941246a2119201d415c6a221d0d000b0b02402010450d00200f102a0b200341f0026a41186a200341d0026a41186a290300370300200341f0026a41106a200341d0026a41106a290300370300200341f0026a41086a200341d0026a41086a290300370300200320032903d0023703f002410021192007201c41004120201c676b10c4024101211d200341f0026a41012007201c10c5020240200c450d002007102a0b4101210c0c1a0b41c4d1c3004133200341d8046a419cd9c3001038000b412441041037000b201241041037000b200241011037000b200241011037000b41a39fc6002119411121024101210c0c140b420021304200212d0b024002402030202f54202d200b54202d200b511b450d0041a0fdc1002119412e21020c010b200341b0046a41086a22024200370300200342003703b004418ca3c1004113200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a1006210202400240024002400240024002400240024020032802f0022219417f460d002002450d00200320193602b404200320023602b004200341f0026a200341b0046a107820032802f0022210450d0320032902f402212d02402019450d002002102a0b202d422088a72217450d05202da7211441f1fdc1002119412321022010290300200554201041086a290300223020045420302004511b450d07200341b0046a41086a22194200370300200342003703b00441a9a2c100410f200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a1006211920032802f002221c417f460d012019450d012003201c3602b404200320193602b004200341f0026a200341b0046a107d20032802f0022207450d0420032902f4022130201c450d022019102a0c020b41effcc1002119413121020c080b42002130410421070b20072030422088a7220e41246c6a210c200721194100211c024003400240200c20196b41ec004b0d00200c2019460d062007200e41246c6a210c034020034188046a2019460d03201c201920034188046a4120109c05221d4100476a211c201d450d03200c201941246a2219470d000c070b0b201920034188046a460d01201c201920034188046a4120109c05221d4100476a211c201d450d01201941246a221d20034188046a460d01201c201d20034188046a4120109c05221d4100476a211c201d450d01201941c8006a221d20034188046a460d01201c201d20034188046a4120109c05221d4100476a211c201d450d01201941ec006a221d20034188046a460d0120194190016a2119201c201d20034188046a4120109c05221d4100476a211c201d0d000b0b201c202e422088a7490d034194fec1002119413621022030a7450d042007102a0c040b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b41cca2c100410041001034000b02402030a7450d002007102a0b200341a8026a10c002200341f0026a20034188046a10bf0220032802f0024101460d01024020032802ac02450d0020032802a802102a0b41cefdc10021190b2014450d012010102a0c010b20032802a80221260240024002400240024002400240024002400240024020032802b00222020d0042002131420021320c010b20032802f4022111200241216c211c202641016a2102200341f8026a2802002219410876211241012019411f7174211520194105764107712213417f7321164200213142002132034002402002417f6a2d00004101470d00411310282219450d06201941002900c2a3413700002019410f6a41002800d1a341360000201941086a41002900caa34137000020034293808080b0023702f402200320193602f0022002200341f0026a108f0120032802f802211d20032802f002210c200341b0046a41186a22074200370300200341b0046a41106a220e4200370300200341b0046a41086a22194200370300200342003703b004200c201d200341b0046a1000200341e8006a41186a2007290300370300200341e8006a41106a200e290300370300200341e8006a41086a22072019290300370300200320032903b004370368024020032802f402450d0020032802f002102a0b200341003602f002200341e8006a4120200341f0026a1006210c20032802f002221d417f460d002003201d3602b4042003200c3602b004200341f0026a200341b0046a10c20220032903f0024201510d05200341f0026a41206a2903002133200341f0026a41106a220f2903002134200329038803213520032903f8022136200328029803210e0240201d450d00200c102a0b200e2011490d0020194200370300200342003703b004418891c6004111200341b0046a100820072019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a10062119024020032802f002221d417f460d00201d41034d0d052019102a0b200341f0026a41186a200241186a290000370300200f200241106a290000370300200341f0026a41086a200241086a290000370300200320022900003703f0022003201236029003200341b0046a200341f0026a10c10242002130420021370240201320032802b80422194f0d00201920166a221d20194f0d04203320347c203520367c2230203554ad7c420020032802b004201d4102746a28020020157122191b21372030420020191b21300b024020032802b404450d0020032802b004102a0b203720327c203020317c2231203054ad7c21320b200241216a2102201c415f6a221c0d000b0b2010201741306c6a210920102102024002400240024003400240200920026b4190014b0d00024020022009460d0003404101211c200241106a220220034188046a460d04200220034188046a4120109c05450d04200241206a22022009470d000b0b4100211c203120058520322004858450450d02200341d0026a41186a220220034188046a41186a290300370300200341d0026a41106a221920034188046a41106a290300370300200341d0026a41086a221c20034188046a41086a29030037030020032003290388043703d0022010200437030820102005370300201020032903d002370310201041186a201c290300370300201041206a2019290300370300201041286a200229030037030020174115490d0a202d422188220b42307e2204422088a70d182004a72202417f4c0d1820020d03410821254108210f0c040b4101211c200241106a221920034188046a460d01201920034188046a4120109c05450d01200241c0006a221920034188046a460d01201920034188046a4120109c05450d01200241f0006a221920034188046a460d01201920034188046a4120109c05450d01200241a0016a221920034188046a460d01200241c0016a2102201920034188046a4120109c050d000b0b200341386a200341e0036a202f200b10cf012003290338210b2003200341c0006a2903003703f8022003200b3703f00241cafec10041e0fec100201c1b21194116410f201c1b21022003200341f0026a3602b004200341b0046a109d014101211c0c090b200210282225450d012025210f0b200ba7211f201041506a2128201041306a212c201041f07e6a212b410421154100212741002106410021122017210a0340200a21074100210a4101210c02402007417f6a221c450d000240024002400240024002402010201c41306c6a2202290300200741306c221120106a41a07f6a2219290300220454200241086a2903002205201941086a290300220b542005200b511b0d002007417e6a210e202b20116a21024100210a4100211903400240200e2019470d002007210c0c080b20042002290300222d5a211c200b200241086a290300220551211d200b20055a210c200241506a2102201941016a2119202d21042005210b201c200c201d1b0d000b201941016a210c2019417f7320076a211c0c010b202b20116a2102024003400240201c4101470d004100211c0c020b20042002290300222d542119200b200241086a290300220551211d200b200554210c200241506a2102201c417f6a211c202d21042005210b2019200c201d1b0d000b0b2007201c490d01200720174b0d032007201c6b220c410176221d450d00202820116a21022010201c41306c6a21190340200341f0026a41286a220e201941286a2211290300370300200341f0026a41206a2213201941206a2216290300370300200341f0026a41186a2218201941186a221a290300370300200341f0026a41106a221b201941106a220a290300370300200341f0026a41086a2208201941086a2229290300370300200320192903003703f002200241086a222a290300210b200241106a221e2903002104200241186a22222903002105200241206a2223290300212d200241286a2224290300212f201920022903003703002011202f3703002016202d370300201a2005370300200a20043703002029200b3703002024200e2903003703002023201329030037030020222018290300370300201e201b290300370300202a2008290300370300200220032903f002370300201941306a2119200241506a2102201d417f6a221d0d000b0b0240201c0d00201c210a0c050b0240200c41094d0d00201c210a0c050b200720174b0d012007201c6b211d202c201c41306c6a210e03402007201c417f6a220a490d0402402007200a6b220c4102490d002010201c41306c6a22022903002010200a41306c6a221c29030022055a200241086a22192903002204201c41086a2211290300220b5a2004200b511b0d00200341b0046a41186a2216201c41286a2213290300370300200341b0046a41106a2218201c41206a221a290300370300200341b0046a41086a221b201c41186a22082903003703002003201c2903103703b004201c200229030037030020112019290300370300201c41106a200241106a2903003703002008200241186a290300370300201a200241206a2903003703002013200241286a290300370300410121190240200c4103490d00201c29036020055a201c41e8006a2903002204200b5a2004200b511b0d0041022111200e211303402013220241506a22192002290300370300201941286a200241286a290300370300201941206a200241206a290300370300201941186a200241186a290300370300201941106a200241106a290300370300201941086a200241086a290300370300201d20112219460d01201941016a2111200241306a221329030020055a200241386a2903002204200b5a2004200b511b450d000b0b200220053703002002200b370308201c201941306c6a220241286a2016290300370300200241206a2018290300370300200241186a201b290300370300200220032903b0043703100b200a450d05200e41506a210e201d41016a211d200a211c200c410a4f0d050c000b0b201c20071044000b2007201c417f6a220a490d010b20072017103c000b200a20071044000b02400240024020122027470d00202741016a22022027490d18202741017422192002201920024b1b220241ffffffff01712002470d18200241037422194100480d180240024020270d002019102821150c010b201520274103742019102c21150b2015450d0120022127200621120b201520124103746a2202200c3602042002200a360200200641016a2212210620124102490d0102400340024002400240024020152012417f6a22064103746a2202280200450d00201241037420156a221d41746a280200221c200228020422194d0d000240201241024b0d0020122106410221120c080b20152012417d6a22164103746a28020422022019201c6a4d0d010240201241034b0d0020122106410321120c080b201d41646a2802002002201c6a4d0d01201221060c070b20124103490d012002280204211920152012417d6a22164103746a28020421020b20022019490d010b2012417e6a21160b0240024002400240024002402012201641016a22084b2229450d00201220164b222a450d01201520164103746a2218280204221e20182802006a2202201520084103746a221a280200221b490d02200220174b0d032010201b41306c6a2211201a280204221341306c22196a211d200241306c211c2002201b6b220720136b220220134f0d042025201d200241306c2219109a051a200f20196a210c0240024020134101480d00200241014e0d010b201d2102200f21190c060b2028201c6a211c201d21020340201c200241506a221d200c41506a22072007290300201d29030054200741086a290300220b201d41086a290300220454200b2004511b220e1b2219290300370300201c41086a201941086a290300370300201c41106a201941106a290300370300201c41186a201941186a290300370300201c41206a201941206a290300370300201c41286a201941286a290300370300200c2007200e1b210c02402011201d2002200e1b2202490d00200f21190c070b201c41506a211c200f2119200f200c490d000c060b0b41b8dbc000200820121034000b41b8dbc000201620121034000b201b20021044000b20022017103c000b202520112019109a051a200f20196a210c0240024020134101480d00200720134a0d010b20112102200f21190c010b2010201c6a210e200f21192011210203402002201d2019201d290300201929030054201d41086a290300220b201941086a290300220454200b2004511b22071b221c290300370300200241086a201c41086a290300370300200241106a201c41106a290300370300200241186a201c41186a290300370300200241206a201c41206a290300370300200241286a201c41286a2903003703002019201941306a20071b2119200241306a2102201d41306a201d20071b221d200e4f0d01200c20194b0d000b0b20022019200c20196b221c201c4130706b109a051a0240202a450d002018201b360200201841046a201e20136a3602002029450d02201a201a41086a20122008417f736a410374109b051a20062112200641014d0d040c010b0b41c8dbc000201620121034000b41b0b1c0001032000b201941041037000b200a0d000b02402027450d002015102a0b201f450d062025102a0c060b200241081037000b41cca2c100201d20191034000b41c4d1c3004133200341d8046a419cd9c3001038000b41c4d1c3004133200341d8046a419cd9c3001038000b411341011037000b20174102490d002017417f6a211c2010201741306c6a21074101211d03400240024002400240201c2202417f6a221c20174b0d002017201c6b22194102490d032010200241306c6a22022903002010201c41306c6a220c29030022055a200241086a220e2903002204200c41086a220f290300220b5a2004200b511b0d03200341b0046a41186a2211200c41286a2212290300370300200341b0046a41106a2213200c41206a2215290300370300200341b0046a41086a2216200c41186a22182903003703002003200c2903103703b004200c2002290300370300200f200e290300370300200c41106a200241106a2903003703002018200241186a2903003703002015200241206a2903003703002012200241286a2903003703004101210e20194103490d02200c29036020055a200c41e8006a2903002204200b5a2004200b511b0d024100210e2007211903402019220241506a22192002290300370300201941286a200241286a290300370300201941206a200241206a290300370300201941186a200241186a290300370300201941106a200241106a290300370300201941086a200241086a290300370300201d200e220f460d02200f417f6a210e200241306a221929030020055a200241386a2903002204200b5a2004200b511b0d020c000b0b201c20171044000b4102200f6b210e0b200220053703002002200b370308200c200e41306c6a220241286a2011290300370300200241206a2013290300370300200241186a2016290300370300200220032903b0043703100b200741506a2107201d417f6a211d201c0d000b0b200341b0046a41086a22024200370300200342003703b004418ca3c1004113200341b0046a1008200341e8006a41086a2002290300370300200320032903b004370368200341003602f802200342013703f0022017200341f0026a10b401201021020340200241086a290300210b200229030021040240024020032802f402221c20032802f80222196b4110490d0020032802f002211c0c010b201941106a221d2019490d0f201c4101742219201d2019201d4b1b22194100480d0f02400240201c0d0020191028211c0c010b20032802f002201c2019102c211c0b201c450d03200320193602f4022003201c3602f00220032802f80221190b201c20196a221c200b370008201c20043700002003201941106a3602f802200241106a200341f0026a108f01200241306a22022009470d000b20032802f4022102200341e8006a411020032802f002221920032802f802100702402002450d002019102a0b02402014450d002010102a0b4100211c410021190b024020032802ac02450d002026102a0b0240201c0d00202ea7450d120c020b02402014450d002010102a0b202ea7450d110c010b201941011037000b200d102a0c0f0b202ea7450d0e200d102a0c0e0b0b024002400240200ba7450d00201d102a201c0d010c020b201c450d010b200341e4016a41026a20034184026a41026a2d00003a0000200341c8016a41086a200341e8016a41086a290300370300200341c8016a410d6a200341e8016a410d6a290000370000200320032f0184023b01e401200320032903e8013703c8014100211c0c010b4101211c4118210241a8fac10021190b200341c4016a41026a221d200341e4016a41026a2d00003a0000200341a8016a41086a220c200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200320032f01e4013b01c401200320032903c8013703a801201c0d0b20034183036a200c29030037000020034188036a200341b5016a290000370000200320032f01c4013b01f002200320023600f702200320193600f302200320032903a8013700fb022003201d2d00003a00f2020240200341f0026a20034188046a4120109c050d0020034188046a201b10d50220034188046a428080e983b1de16420010aa02200342f0f2bda9c6add9b1f4003703d00220031098013602a802200341b0046a20034188046a109a0220032802b404211920032802b004210220032802b804211c200341c4046a200341d0026a36020020032002201c4105746a3602bc04200320023602b804200320193602b404200320023602b0042003200341a8026a3602c004200341e0036a200341b0046a108701200341b0046a41086a200341e0036a41086a280200360200200320032903e0033703b00420034188046a200341b0046a109c02410021190c0c0b41c0fac1002119411921020c0b0b0b0240200ba7450d00200c102a201d450d010c020b201d0d010b4101211c4116210241dcf9c10021190c010b200341b0046a41026a200341a4016a41026a2d00003a0000200341f0026a41086a20034188016a41086a290300370300200341f0026a410d6a20034188016a410d6a290000370000200320032f01a4013b01b00420032003290388013703f0024100211c0b200341e8006a41026a221d200341b0046a41026a2d00003a000020034188046a41086a220c200341f0026a41086a29030037030020034188046a41106a200341f0026a41106a290300370300200320032f01b0043b0168200320032903f00237038804201c0d06200341f3036a200c290300370000200341f8036a20034195046a290000370000200320032f01683b01e003200320023600e703200320193600e30320032003290388043700eb032003201d2d00003a00e20302400240024002400240024002400240410e10282202450d00200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2202450d012002202041067636000e200341b0046a41186a22194200370300200341b0046a41106a221c4200370300200341b0046a41086a221d4200370300200342003703b00420024112200341b0046a1000200341e8006a41186a2019290300370300200341e8006a41106a201c290300370300200341e8006a41086a201d290300370300200320032903b0043703682002102a200341003602f002200341e8006a4120200341f0026a1006210220032802f0022219417f460d052002450d05200320193602b404200320023602b004200341f0026a200341b0046a107420032802f002220c450d022020413f71211c20032902f402210b02402019450d002002102a0b4100211d201c200b422088a74f0d03200c201c41216c6a22192d00004101470d0320034186026a201941036a2d00003a0000200341e8016a41086a201941146a290000370300200341f5016a201941196a290000370000200320192f00013b01840220032019410c6a2900003703e801201941086a2800002102201941046a28000021194101211d0c040b410e41011037000b411c41011037000b41c4d1c3004133200341d8046a419cd9c3001038000b0b0240200ba7450d00200c102a201d450d010c020b201d0d010b4101211c4114210241f2f9c10021190c010b200341e4016a41026a20034184026a41026a2d00003a0000200341c8016a41086a200341e8016a41086a290300370300200341c8016a410d6a200341e8016a410d6a290000370000200320032f0184023b01e401200320032903e8013703c8014100211c0b200341c4016a41026a221d200341e4016a41026a2d00003a0000200341a8016a41086a220c200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200320032f01e4013b01c401200320032903c8013703a801201c0d062003419b046a200c290300370000200341a0046a200341b5016a290000370000200320032f01c4013b0188042003200236008f042003201936008b04200320032903a801370093042003201d2d00003a008a040240200341e0036a20034188026a4120109c05450d004186fac1002119411221020c070b024020034188046a200341a8026a4120109c05450d004198fac1002119411021020c070b200341f0026a41186a2217200341a8026a41186a2218290300370300200341f0026a41106a221a200341a8026a41106a221b290300370300200341f0026a41086a220a200341a8026a41086a2206290300370300200320032903a8023703f002410021022003410036029003200341b0046a200341f0026a10c1020240024020032802b804220d0d0041012112410021130c010b410021114100211341012112410021150340200d417f4c0d0220032802b404211620032802b00421140240024002400240200d1028220e450d0002400240200d41027422020d00410021070c010b201420026a210f410021072014210c0340200c2802002119412010282202450d0320022019411f763a001f200220194101713a000020022019411e764101713a001e20022019411d764101713a001d20022019411c764101713a001c20022019411b764101713a001b20022019411a764101713a001a200220194119764101713a0019200220194118764101713a0018200220194117764101713a0017200220194116764101713a0016200220194115764101713a0015200220194114764101713a0014200220194113764101713a0013200220194112764101713a0012200220194111764101713a0011200220194110764101713a001020022019410f764101713a000f20022019410e764101713a000e20022019410d764101713a000d20022019410c764101713a000c20022019410b764101713a000b20022019410a764101713a000a200220194109764101713a0009200220194108764101713a00082002201941ff017122194107763a0007200220194106764101713a0006200220194105764101713a0005200220194104764101713a0004200220194103764101713a0003200220194102764101713a0002200220194101764101713a0001200c41046a210c4100211902400240024002400340201941206a221c41034d0d010240200220196a221c411f6a2d0000450d002019411f6a211d0c040b0240201c411e6a2d0000450d002019411e6a211d0c040b0240201c411d6a2d00000d002019417c6a2119201c411c6a2d00000d030c010b0b2019411d6a211d0c020b0340201c450d032002201c6a2119201c417f6a221d211c2019417f6a2d0000450d000c020b0b201941206a211d0b201d41016a221c201d490d000240200d20076b201c4120201c4120491b22194f0d00200720196a22192007490d0b200d410174221d2019201d20194b1b22194100480d0b02400240200d0d0020191028210e0c010b200e200d2019102c210e0b200e450d062019210d0b200e20076a211d410021190240034020194120460d01201d20196a200220196a2d00004101713a0000201c201941016a2219470d000b0b200720196a21070b2002102a200c200f470d000b0b02402016450d002014102a0b0240201320116b2007490d00201120076a21020c040b201120076a22022011490d07201341017422192002201920024b1b22194100480d070240024020130d002019102821120c010b201220132019102c21120b02402012450d00201921130c040b201941011037000b200d41011037000b412041011037000b201941011037000b201220116a200e2007109a051a0240200d450d00200e102a0b20172018290300370300201a201b290300370300200a2006290300370300200320032903a8023703f0022003201541016a221536029003200341b0046a200341f0026a10c1022002211120032802b804220d0d000b0b024020032802b404450d0020032802b004102a0b200341b0046a41086a22194200370300200342003703b00441b0a3c1004112200341b0046a1008200341e8006a41086a2019290300370300200320032903b004370368200341003602f002200341e8006a4110200341f0026a1006211902400240024020032802f002221c417f460d002019450d002003201c3602b404200320193602b004200341f0026a200341b0046a106d20032802f002220e450d0220032902f402210b201c450d012019102a0c010b4101210e4200210b0b200b422088a741ffffff3f7122192002200220194b1b221c450d034100211920034188036a211d20034180036a210c200341f8026a2107200e210203400240201220196a2d0000450d00201d4200370300200c420037030020074200370300200342003703f002200341f0026a2002460d002002200341f0026a4120109c05450d00200341f0026a200210bf024101210d20032802f0024101470d0020032802f40220104d0d060b200241206a2102201941016a2219201c4f0d040c000b0b41c4d1c3004133200341d8046a419cd9c3001038000b1036000b1031000b4100210d0b0240200ba7450d00200e102a0b02402013450d002012102a0b20034188026a200341a8026a200d1b221920212020200d1b10d502200342f0f2bda9c6add9b1f4003703c80220031098013602d002200341f0026a2019109a0220032802f402211c20032802f002210220032802f802211d20034184036a200341c8026a36020020032002201d4105746a3602fc02200320023602f8022003201c3602f402200320023602f0022003200341d0026a36028003200341b0046a200341f0026a108701200341f0026a41086a200341b0046a41086a280200360200200320032903b0043703f0022019200341f0026a109c020240024002400240024002400240200d450d00200341106a20034188026a428080e983b1de1642001082022003290310210b2003200341106a41086a2903003703f8022003200b3703f0022003200341f0026a3602b004200341b0046a109d01200341013a00f402200341083a00f002200341f0026a4105722102200341f0026a211c0c010b200341206a20034188026a109d022003290320200341206a41086a29030084500d02411810282202450d03200241002900e3e140370000200241106a41002900f3e140370000200241086a41002900ebe1403700002003429880808080033702d402200320023602d002200341a8026a200341d0026a108f0120032802d802210220032802d0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341f0026a41186a201c290300370300200341f0026a41106a201d290300370300200341f0026a41086a200c290300370300200320032903b0043703f002024020032802d402450d0020032802d002102a0b200341003602b004200341f0026a4120200341b0046a1006210202400240024020032802b0042219417f470d004200210b420021050c010b20194110490d06200241086a29000021052002290000210b2002102a428080e983b1de1621044200212d200b428080e983b1de165441002005501b450d010b200b21042005212d0b411410282202450d05200241002900cfe140370000200241106a41002800dfe140360000200241086a41002900d7e14037000020034294808080c0023702d402200320023602d00220034188026a200341d0026a108f0120032802d802210220032802d0022119200341b0046a41186a221c4200370300200341b0046a41106a221d4200370300200341b0046a41086a220c4200370300200342003703b00420192002200341b0046a1000200341f0026a41186a201c290300370300200341f0026a41106a201d290300370300200341f0026a41086a200c290300370300200320032903b0043703f002024020032802d402450d0020032802d002102a0b200341003602b004200341f0026a4120200341b0046a100621020240024020032802b0042219417f470d004200212e4200212f0c010b20194110490d02200241086a290000212f2002290000212e2002102a0b20034188026a202e20047c2230202f202d7c2030202e54ad7c108f02200341a8026a200b20047d2005202d7d200b200454ad7d10900220034185036a200341b8026a2903003700002003418d036a200341c0026a290300370000200341083a00f002200341fd026a200341a8026a41086a290300370000200341003a00f402200320032903a8023700f50220034195036a2102200341f0026a211c0b2002200329038802370000200241186a20034188026a41186a290300370000200241106a20034188026a41106a290300370000200241086a20034188026a41086a290300370000410021194101211d41014100201c10cc014101210c0c0b0b41c4d1c3004133200341d8046a419cd9c3001038000b41b5dfc0002119412221020c050b411841011037000b41c4d1c3004133200341d8046a419cd9c3001038000b411441011037000b41dc9fc6002119410e21020c010b4111210241a39fc60021190b4101211d4101210c0c030b4100211c0b20034184026a41026a221d200341b0046a41026a2d00003a0000200341e8016a41086a220c200341f0026a41086a290300370300200341e8016a410d6a2207200341f0026a410d6a290000370000200320032f01b0043b018402200320032903f0023703e80102400240201c0d004101211c410b210241d8d2c50021190c010b200341e4016a41026a201d2d00003a0000200341c8016a41086a200c290300370300200341c8016a410d6a2007290000370000200320032f0184023b01e401200320032903e8013703c8014100211c0b200341c4016a41026a200341e4016a41026a2d00003a0000200341a8016a41086a200341c8016a41086a290300370300200341a8016a41106a200341c8016a41106a290300370300200320032f01e4013b01c401200320032903c8013703a801201c0d00200341a4016a41026a200341c4016a41026a2d0000221c3a000020034188016a41086a221d200341a8016a41086a29030037030020034188016a410d6a220c200341a8016a410d6a290000370000200320032f01c40122073b01a401200320032903a8013703880120034183036a201d29030037000020034188036a200c2900003700002003201c3a00f202200320073b01f002200320023600f702200320193600f30220032003290388013700fb02200320063602b8042003201b3602b4042003200a3602b004200341086a200341f0026a200341b0046a200920082005200410d402200328020c2102200328020821194101210c4100211d0c010b4101210c4100211d201b450d00200a102a0b02402001280200417f6a221c41014b0d0002400240201c0e020100010b201d450d01200141086a280200450d012001280204102a0c010b200c450d00200141086a280200450d002001280204102a0b2000200236020420002019360200200341e0046a24000bb55304087f017e097f027e23004190056b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d000022040e050001020304000b2003418c046a4101360200200342013702fc03200341ccd1c5003602f803200341043602f402200341c4d1c5003602f0022003200341f0026a36028804200341f8036a41a8a6c300103e000b200141086a2802002105200141046a2802002106024020022d000020022d000172450d0041a39fc600210741112108410021094101210a02402005450d002006102a0b410121060c230b20062001410c6a280200220210f0014200210b200341f8036a41086a22074200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621090240024020032802f8032208417f460d00200320083602ec01200320093602e801200341f8036a200341e8016a106d20032802f8032207450d0520032902fc03210b2008450d012009102a0c010b410121070b200620022007200b422088a71085020240200ba7450d002007102a0b200341f8036a41086a22074200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f0022003410036028004200342013703f8032002200341f8036a10b40102402002450d00200241057421072006210203402002200341f8036a108f01200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b4101210a2005450d212006102a0c210b200141046a280200210941b49fc60021074113210820022d00000d1e2002280001220a41ff01714101470d1e2003200a4118763a00622003200a4108763b01602003200241216a2d00003a007f2003200241196a2900003700772003200241116a29000037006f2003200241096a2900003700672003200241056a2800003600634200210b200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621080240024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f8032202450d0520032902fc03210b2007450d012008102a0c010b410121020b2002200b422088a7200341e0006a10cd0121070240200ba7450d002002102a0b024020070d0041b8a6c3002107411521080c1f0b4100210a2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a22064200370300200341f0026a41106a22054200370300200341f0026a41086a220c4200370300200342003703f00220022008200341f0026a1000200341e8016a41186a22082006290300370300200341e8016a41106a220d2005290300370300200341e8016a41086a2205200c290300370300200320032903f0023703e80102402007450d002002102a0b200341f8036a2009418801109a051a200341f0026a410d6a200341e0006a41086a290300370000200341f0026a41156a200341e0006a41106a290300370000200341f0026a411d6a200341e0006a41186a29030037000041012106200341013a00f402200320032903603700f502200341023a00f002200341c0006a200341f8036a200341f0026a10f40120032d00482102200341f8036a410d6a2005290300370000200341f8036a41156a200d290300370000200341f8036a411d6a20082903003700002003419d046a20024102463a0000200341053a00fc03200341073a00f803200320032903e8013700fd0341014100200341f8036a10cc012009102a0c170b200141086a280200210941b49fc60021074113210820022d00000d1c2002280001220a41ff01714101470d1c200141046a28020021062003200a4118763a00422003200a4108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0520032902fc03210b2008450d012007102a0c010b4200210b410121020b2002200b422088a7200341c0006a10cd0121070240200ba7450d002002102a0b024020070d0041b8a6c3002107411521080c1d0b2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a220a4200370300200341f0026a41106a22054200370300200341f0026a41086a220c4200370300200342003703f00220022008200341f0026a1000200341e0006a41186a2208200a290300370300200341e0006a41106a220a2005290300370300200341e0006a41086a2205200c290300370300200320032903f00237036002402007450d002002102a0b200341f8036a41186a2008290300370300200341f8036a41106a200a290300370300200341f8036a41086a2005290300370300200320032903603703f803411e10282202450d04200241002900f6a743370000200241166a410029008ca843370000200241106a4100290086a843370000200241086a41002900fea7433700002003429e808080e0033702ec01200320023602e8012003200341e8016a3602f002200341f8036a200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22084200370300200341f0026a41106a220a4200370300200341f0026a41086a22054200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a200a290300370300200341206a41086a2005290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341206a41204101410041001003417f470d05200341f8036a41086a22024200370300200342003703f803024020064102490d004194a8c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f0024100210a200341003602f803200341f0026a4110200341f8036a10062102024020032802f8032207417f460d002002450d0020074104490d082002280000210a2002102a0b200341f8036a41086a22024200370300200342003703f8034194a8c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621020240024020032802f8032207417f460d002002450d00024020074104490d00200228000021072002102a200741016a21070c020b41c4d1c300413320034188056a419cd9c3001038000b410121070b200341f8036a41086a22024200370300200342003703f8034194a8c3004121200341f8036a1008200341f0026a41086a22082002290300370300200320032903f8033703f002200320073602f803200341f0026a4110200341f8036a4104100720024200370300200342003703f80341cf96c300411d200341f8036a100820082002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d092002450d09200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f8032208450d0820032902fc03210b02402007450d002002102a0b200320083602e8012003200b3702ec01200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a2107200b422088a72202200ba72208470d150c140b4196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f00241002102200341003602f803200341f0026a4110200341f8036a10062108024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f803220a450d0a20032902fc03210b02402007450d002008102a0b200b422088a72102200ba7450d00200a102a0b200341f8036a2009418801109a051a200341fc026a2002360200200341f0026a41086a4101360200200341003a00f402200341023a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341e0006a41086a2903003700002003418d046a200341f0006a29030037000020034195046a200341f8006a2903003700002003419d046a20024102463a0000200341043a00fc03200341073a00f803200320032903603700fd03200341f8036a21020c150b200141216a2d0000210a200141246a2802002109200341186a200141196a290000370300200341106a200141116a290000370300200341086a200141096a290000370300200320012900013703000240024020022d00000d002002280001220741ff01714101460d010b41b49fc60021070c110b200320074118763a0042200320074108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0b20032902fc03210b2008450d012007102a0c010b4200210b410121020b2002200b422088a7200341c0006a10cd0121070240200ba7450d002002102a0b024020070d0041bea7c3002107411221080c120b411a10282202450d0a200241002900ec9643370000200241186a41002f008497433b0000200241106a41002900fc9643370000200241086a41002900f496433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321022003280280042107200341f0026a41186a22084200370300200341f0026a41106a22064200370300200341f0026a41086a22054200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a2006290300370300200341206a41086a2005290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a1006210220032802f8032207417f460d0f2002450d0f200320073602f402200320023602f002200341f8036a200341f0026a10b3032003280280042205450d0b20034194046a280200210e20034190046a280200210f2003418c046a280200210c41102108200341f8036a41106a2802002110200328028404211120032802fc03211220032802f803210602402007450d002002102a0b41d0a7c300210720062009470d0e200520104105746a21062005210241002108024003400240200620026b41e0004b0d0020022006470d02410021130c100b200341c0006a2002460d0e20082002200341c0006a4120109c0522074100476a21082007450d0e200241206a2207200341c0006a460d0e20082007200341c0006a4120109c0522074100476a21082007450d0e200241c0006a2207200341c0006a460d0e20082007200341c0006a4120109c0522074100476a21082007450d0e200241e0006a2207200341c0006a460d0e20024180016a210220082007200341c0006a4120109c0522074100476a210820070d000c0e0b0b200520104105746a21060340200341c0006a2002460d0d20082002200341c0006a4120109c0522074100476a21082007450d0d410021132006200241206a2202470d000c0e0b0b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b411e41011037000b41cda6c3002107411f21080c160b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b41002102200341003602f001200342013703e801200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a21070c0a0b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b410121130b200c200e4105746a210d200c21024100210702400240024003400240200d20026b41e0004b0d002002200d470d02410021060c040b200341c0006a2002460d0220072002200341c0006a4120109c0522064100476a21072006450d02200241206a2206200341c0006a460d0220072006200341c0006a4120109c0522064100476a21072006450d02200241c0006a2206200341c0006a460d0220072006200341c0006a4120109c0522064100476a21072006450d02200241e0006a2206200341c0006a460d0220024180016a210220072006200341c0006a4120109c0522064100476a210720060d000c020b0b0340200341c0006a2002460d0120072002200341c0006a4120109c0522064100476a21072006450d0141002106200d200241206a2202470d000c020b0b410121060b024002400240024002400240024002400240200a41ff01710d002006450d010c080b20130d07200341f8036a41186a220d200341c0006a41186a290300370300200341f8036a41106a2213200341c0006a41106a290300370300200341f8036a41086a2214200341c0006a41086a290300370300200320032903403703f803024020102011460d0020112108201021110c020b201141016a22022011490d10201141017422082002200820024b1b220841ffffff3f712008470d10200841057422024100480d100240024020110d002002102821050c010b200520114105742002102c21050b20050d01200241011037000b200341f8036a41186a2206200341c0006a41186a290300370300200341f8036a41106a220d200341c0006a41106a290300370300200341f8036a41086a2214200341c0006a41086a290300370300200320032903403703f80302400240200e200f460d00200f2107200e210f0c010b200f41016a2202200f490d10200f41017422072002200720024b1b220741ffffff3f712007470d10200741057422024100480d1002400240200f0d0020021028210c0c010b200c200f4105742002102c210c0b200c0d00200241011037000b200c200f4105746a220220032903f803370000200241186a2006290300370000200241106a200d290300370000200241086a2014290300370000200e41016a210e024002402013450d00201020084d0d0120052010417f6a22104105746a2202290000210b2002290008211520022900102116200520084105746a220841186a200241186a29000037000020082016370010200820153700082008200b3700000b2007210f201121080c020b41c4f2c200200820101034000b200520114105746a220220032903f803370000200241186a200d290300370000200241106a2013290300370000200241086a2014290300370000201041016a21102006450d00200e20074d0d01200c200e417f6a220e4105746a2202290000210b2002290008211520022900102116200c20074105746a220741186a200241186a29000037000020072016370010200720153700082007200b3700000b2003419d046a200329030037000020034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a290300370000200341a5046a200341086a290300370000200341ad046a200341106a290300370000200341b5046a200341186a290300370000200341013a00fc03200341073a00f803200320032903403700fd03200341c4046a200e360200200341c0046a2010360200200341bd046a200a3a000041014100200341f8036a10cc01200341f8036a41086a22024200370300200342003703f8034196f0c200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d022002450d02200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f803220a450d0120032902fc03210b02402007450d002002102a0b200b422088a72102200ba7450d03200a102a0c030b41c4f2c2002007200e1034000b41c4d1c300413320034188056a419cd9c3001038000b410021020b024002400240024002400240024002400240201020124f22070d0041002002200e6b220a200a20024b1b2012490d0020034194046a200e360200200341f8036a41186a200f360200200341f8036a41106a201036020020034184046a20083602002003200c36028c042003200536028004200320123602fc03200320093602f803411a10282202450d01200241002900ec9643370000200241186a41002f008497433b0000200241106a41002900fc9643370000200241086a41002900f496433700002003429a808080a0033702ec01200320023602e8012003200341e8016a3602f0022003200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22094200370300200341f0026a41106a220a4200370300200341f0026a41086a22064200370300200342003703f00220022007200341f0026a1000200341206a41186a2009290300370300200341206a41106a200a290300370300200341206a41086a2006290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341203602f4022003200341206a3602f002200341f8036a200341f0026a10b40302402008450d002005102a0b200f0d050c060b024020070d0020034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341033a00fc03200341073a00f803200320032903003700fd0341014100200341f8036a10cc010c040b20034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341023a00fc03200341073a00f803200320032903003700fd0341014100200341f8036a10cc01411e10282207450d01200741002900f6a743370000200741166a410029008ca843370000200741106a4100290086a843370000200741086a41002900fea7433700002003429e808080e0033702fc03200320073602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a22064200370300200341f0026a41086a220d4200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a2006290300370300200341206a41086a200d290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a100621090240024020032802f803220a417f470d00411321070c010b024020090d00411321070c010b2003200a360284052003200936028005200341f8036a20034180056a10810120032802f80322074113460d03200341f0026a200341f8036a410472418401109a051a0240200a450d002009102a0b200341206a412010090b200341e8016a200341f0026a418401109a051a200341f8036a200341e8016a418401109a051a20074113460d03200341e0006a200341f8036a418401109a051a200320073602f803200341f8036a410472200341e0006a418401109a051a200341fc026a2002360200200341f0026a41086a2012360200200341003a00f402200341023a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a2903003700002003419d046a20024102463a0000200341043a00fc03200341073a00f803200320032903003700fd0341014100200341f8036a10cc010c030b411a41011037000b411e41011037000b41c4d1c300413320034188056a419cd9c3001038000b411a10282202450d02200241002900ec9643370000200241186a41002f008497433b0000200241106a41002900fc9643370000200241086a41002900f496433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a22064200370300200341f0026a41086a22024200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a2006290300370300200341206a41086a2002290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341206a41201009200341f8036a41086a22074200370300200342003703f80341cf96c300411d200341f8036a100820022007290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032202417f460d00200320023602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032209450d0520032902fc03210b02402002450d002007102a0b2003200b3702ec01200320093602e8010c010b200341003602f001200342013703e8010b200341e8016a2003106e20032802f001210220032802ec01210a20032802e8012109200341f8036a41086a22074200370300200342003703f80341cf96c300411d200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f0020240024020090d00200341f0026a411010090c010b2003410036028004200342013703f8032002200341f8036a10b40102402002450d00200241057421072009210203402003200341f8036a3602602002200341e0006a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b200a450d002009102a0b02402008450d002005102a0b200f450d010b200c102a0b410021074101210a41012106410121090c140b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b41e0a7c3002107411621080b02402011450d002005102a0b200f450d02200c102a0c020b41aba7c30021070b411321080b4101210a410121060c0b0b200741046a28020022082002470d00200241016a22082002490d03200241017422052008200520084b1b220841ffffff3f712008470d03200841057422054100480d030240024020020d002005102821020c010b200728020020024105742005102c21020b2002450d0420072002360200200741046a200836020020032802f00121020b200728020022052002410574220d6a22072003290320370000200741186a200341206a41186a290300370000200741106a200341206a41106a290300370000200741086a200341206a41086a2903003700002003200241016a22073602f001200341f8036a41086a220c4200370300200342003703f80341cf96c300411d200341f8036a1008200341f0026a41086a200c290300370300200320032903f8033703f0022003410036028004200342013703f8032007200341f8036a10b401024020072002490d00200d41206a21072005210203402003200341f8036a3602202002200341206a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b02402008450d002005102a0b200341f8036a2009418801109a051a200341e8016a41186a200341e0006a41186a290300370300200341e8016a41106a200341e0006a41106a290300370300200341e8016a41086a200341e0006a41086a290300370300200320032903603703e801411e10282202450d04200241002900f6a743370000200241166a410029008ca843370000200241106a4100290086a843370000200241086a41002900fea7433700002003429e808080e00337020420032002360200200320033602f002200341e8016a200341f0026a10c8012003280200210220032802082107200341f0026a41186a22084200370300200341f0026a41106a22054200370300200341f0026a41086a220c4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a2005290300370300200341206a41086a200c290300370300200320032903f00237032002402003280204450d002003280200102a0b200341003602f802200342013703f002200341f8036a200341f0026a10eb0120032802f4022102200341206a412020032802f002220720032802f802100702402002450d002007102a0b200341f8036a106a412010282202450d0520022003290340370000200241186a200341c0006a41186a290300370000200241106a200341c0006a41106a290300370000200241086a200341c0006a41086a29030037000020034184026a4100360200200341f4016a428180808010370200200342013702fc01200320023602f001200320063602ec012003200a3602e801200341f8036a41186a200341e0006a41186a290300370300200341f8036a41106a200341e0006a41106a290300370300200341f8036a41086a200341e0006a41086a290300370300200320032903603703f803411a10282207450d06200741002900ec9643370000200741186a41002f008497433b0000200741106a41002900fc9643370000200741086a41002900f496433700002003429a808080a00337020420032007360200200320033602f002200341f8036a200341f0026a10c8012003280200210720032802082108200341f0026a41186a22054200370300200341f0026a41106a220c4200370300200341f0026a41086a220d4200370300200342003703f00220072008200341f0026a1000200341206a41186a2005290300370300200341206a41106a200c290300370300200341206a41086a200d290300370300200320032903f00237032002402003280204450d002003280200102a0b200341203602fc032003200341206a3602f803200341e8016a200341f8036a10b4032002102a20034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a2903003700002003419d046a2003290360370000200341a5046a200341e0006a41086a290300370000200341ad046a200341e0006a41106a290300370000200341b5046a200341e0006a41186a290300370000200341c4046a2006360200200341c0046a200a360200200341003a00fc03200341073a00f803200320032903403700fd03200341f8036a21020b410021064101210a41014100200210cc012009102a0b41012109410021070c090b1031000b200541011037000b411e41011037000b412041011037000b411a41011037000b2009106a2009102a410021064101210a0c010b2009106a2009102a410121064100210a0b410121090c010b4100210941012106410021070b02402004410771417f6a220241024b0d0002400240024020020e03000102000b2009450d02200141086a280200450d02200141046a280200102a0c020b200a450d01200141046a2802002202106a2002102a0c010b2006450d00200141086a2802002202106a2002102a0b200020083602042000200736020020034190056a24000bf35c040b7f017e127f027e23004190056b220324000240024002400240024002400240024002400240024002400240024002400240024020012d000022040e0500010a0302000b2003418c046a4101360200200342013702fc03200341ccd1c5003602f803200341043602f402200341c4d1c5003602f0022003200341f0026a36028804200341f8036a41a8a6c300103e000b200141086a2802002105200141046a2802002106024020022d000020022d000172450d0041a39fc600210741112108410021094101210a02402005450d002006102a0b4101210b0c0f0b20062001410c6a280200220c10f001200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210202400240024020032802f8032207417f460d002002450d00200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f803220d450d0220032902fc03210e2007450d012002102a0c010b4101210d4200210e0b20064100200c1b2109200d41206a200d200e422088a722021b210f200641206a2006200c1b2110200d410020021b21112006200c4105746a2112200d20024105746a2113410021144100211541012116410021174100211841012119024003402014410174211a2014410574211b024002400240024002400340024020110d00200f211c2016211d2015211e201421080c040b20112102200f21072016211d2015211e20142108201b210a201a210b02400340024002402009450d0020022009460d06200220094120109c05221c450d06201c417f4c0d012007210f201d2116201e211520082114200221110c080b200341f8036a41186a2207201141186a290000370300200341f8036a41106a2208201141106a290000370300200341f8036a41086a2209201141086a290000370300200320112900003703f803024020142015470d00201441016a22022014490d0f2014410174220a2002200a20024b1b221541ffffff3f712015470d0f201541057422024100480d0f0240024020140d002002102821160c010b201620144105742002102c21160b2016450d030b201620144105746a220220032903f803370000200241186a2007290300370000200241106a2008290300370000200241086a2009290300370000410021094100200f200f20134622021b2111201a41026a211a201b41206a211b201441016a2114200f200f41206a20021b210f0c030b200341f8036a41186a221c200241186a290000370300200341f8036a41106a221f200241106a290000370300200341f8036a41086a2220200241086a290000370300200320022900003703f80302402008201e470d00200841016a22022008490d0e200b2002200b20024b1b221e41ffffff3f71201e470d0e201e41057422024100480d0e0240024020080d0020021028211d0c010b201d200a2002102c211d0b201d450d040b201d200a6a220220032903f803370000200241186a201c290300370000200241106a201f290300370000200241086a2020290300370000410020072007201346221c1b2102200b41026a210b200a41206a210a200841016a21082007200741206a201c1b221c21072002450d050c000b0b0b200241011037000b200241011037000b201d2116201e2115200821142007200741206a200720134622021b210f41002010201020124622081b21094100200720021b21112010201041206a20081b21100c030b410021112009450d01201c210f201d2116201e2115200821140b200341206a41186a2207200941186a290000370300200341206a41106a2208200941106a290000370300200341206a41086a220a200941086a29000037030020032009290000370320024020172018470d00201741016a22022017490d07201741017422092002200920024b1b221841ffffff3f712018470d07201841057422024100480d070240024020170d002002102821190c010b201920174105742002102c21190b2019450d030b201920174105746a22022003290320370000200241186a2007290300370000200241106a2008290300370000200241086a200a29030037000041002010201020124622021b2109201741016a21172010201041206a20021b21100c010b0b201d20082006200c10c5020240201e450d00201d102a0b02402018450d002019102a0b0240200ea7450d00200d102a0b200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f0022003410036028004200342013703f803200c200341f8036a10b4010240200c450d00200c41057421072006210203402002200341f8036a108f01200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b4101210a2005450d0f2006102a0c0f0b200241011037000b41c4d1c300413320034188056a419cd9c3001038000b200141216a2d0000210a200141246a2802002109200341186a200141196a290000370300200341106a200141116a290000370300200341086a200141096a29000037030020032001290001370300024002400240024020022d00000d002002280001220741ff01714101460d010b41b49fc60021070c010b200320074118763a0042200320074108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210702400240024002400240024002400240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0220032902fc03210e2008450d012007102a0c010b4200210e410121020b2002200e422088a7200341c0006a10cd0121070240200ea7450d002002102a0b024020070d0041bea7c3002107411221080c090b411a10282202450d01200241002900b59643370000200241186a41002f00cd96433b0000200241106a41002900c59643370000200241086a41002900bd96433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321022003280280042107200341f0026a41186a22084200370300200341f0026a41106a220b4200370300200341f0026a41086a221e4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a200b290300370300200341206a41086a201e290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a1006210220032802f8032207417f460d062002450d06200320073602f402200320023602f002200341f8036a200341f0026a10b303200328028004221e450d0220034194046a280200211420034190046a28020021202003418c046a280200211d41102108200341f8036a41106a280200211f200328028404211320032802fc03211020032802f803210b02402007450d002002102a0b41d0a7c3002107200b2009470d05201e201f4105746a210b201e210241002108024003400240200b20026b41e0004b0d002002200b470d02410021110c070b200341c0006a2002460d0520082002200341c0006a4120109c0522074100476a21082007450d05200241206a2207200341c0006a460d0520082007200341c0006a4120109c0522074100476a21082007450d05200241c0006a2207200341c0006a460d0520082007200341c0006a4120109c0522074100476a21082007450d05200241e0006a2207200341c0006a460d0520024180016a210220082007200341c0006a4120109c0522074100476a210820070d000c050b0b201e201f4105746a210b0340200341c0006a2002460d0420082002200341c0006a4120109c0522074100476a21082007450d0441002111200b200241206a2202470d000c050b0b41c4d1c300413320034188056a419cd9c3001038000b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b410121110b201d20144105746a211c201d21024100210702400240024003400240201c20026b41e0004b0d002002201c470d024100210b0c040b200341c0006a2002460d0220072002200341c0006a4120109c05220b4100476a2107200b450d02200241206a220b200341c0006a460d022007200b200341c0006a4120109c05220b4100476a2107200b450d02200241c0006a220b200341c0006a460d022007200b200341c0006a4120109c05220b4100476a2107200b450d02200241e0006a220b200341c0006a460d0220024180016a21022007200b200341c0006a4120109c05220b4100476a2107200b0d000c020b0b0340200341c0006a2002460d0120072002200341c0006a4120109c05220b4100476a2107200b450d014100210b201c200241206a2202470d000c020b0b4101210b0b024002400240024002400240024002400240200a41ff01710d00200b450d010c080b20110d07200341f8036a41186a221c200341c0006a41186a290300370300200341f8036a41106a2211200341c0006a41106a290300370300200341f8036a41086a220f200341c0006a41086a290300370300200320032903403703f8030240201f2013460d0020132108201f21130c020b201341016a22022013490d0d201341017422082002200820024b1b220841ffffff3f712008470d0d200841057422024100480d0d0240024020130d0020021028211e0c010b201e20134105742002102c211e0b201e0d01200241011037000b200341f8036a41186a220b200341c0006a41186a290300370300200341f8036a41106a221c200341c0006a41106a290300370300200341f8036a41086a220f200341c0006a41086a290300370300200320032903403703f8030240024020142020460d0020202107201421200c010b202041016a22022020490d0d202041017422072002200720024b1b220741ffffff3f712007470d0d200741057422024100480d0d0240024020200d0020021028211d0c010b201d20204105742002102c211d0b201d0d00200241011037000b201d20204105746a220220032903f803370000200241186a200b290300370000200241106a201c290300370000200241086a200f290300370000201441016a2114024002402011450d00201f20084d0d01201e201f417f6a221f4105746a2202290000210e2002290008212120022900102122201e20084105746a220841186a200241186a29000037000020082022370010200820213700082008200e3700000b20072120201321080c020b41c4f2c2002008201f1034000b201e20134105746a220220032903f803370000200241186a201c290300370000200241106a2011290300370000200241086a200f290300370000201f41016a211f200b450d00201420074d0d01201d2014417f6a22144105746a2202290000210e2002290008212120022900102122201d20074105746a220741186a200241186a29000037000020072022370010200720213700082007200e3700000b2003419d046a200329030037000020034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a290300370000200341a5046a200341086a290300370000200341ad046a200341106a290300370000200341b5046a200341186a290300370000200341013a00fc03200341063a00f803200320032903403700fd03200341c4046a2014360200200341c0046a201f360200200341bd046a200a3a000041014100200341f8036a10cc01200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d022002450d02200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f803220a450d0120032902fc03210e02402007450d002002102a0b200e422088a72102200ea7450d03200a102a0c030b41c4f2c200200720141034000b41c4d1c300413320034188056a419cd9c3001038000b410021020b024002400240024002400240024002400240201f20104f22070d004100200220146b220a200a20024b1b2010490d0020034194046a2014360200200341f8036a41186a2020360200200341f8036a41106a201f36020020034184046a20083602002003201d36028c042003201e36028004200320103602fc03200320093602f803411a10282202450d01200241002900b59643370000200241186a41002f00cd96433b0000200241106a41002900c59643370000200241086a41002900bd96433700002003429a808080a0033702ec01200320023602e8012003200341e8016a3602f0022003200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22094200370300200341f0026a41106a220a4200370300200341f0026a41086a220b4200370300200342003703f00220022007200341f0026a1000200341206a41186a2009290300370300200341206a41106a200a290300370300200341206a41086a200b290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341203602f4022003200341206a3602f002200341f8036a200341f0026a10b40302402008450d00201e102a0b20200d050c060b024020070d0020034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341033a00fc03200341063a00f803200320032903003700fd0341014100200341f8036a10cc010c040b20034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a290300370000200341023a00fc03200341063a00f803200320032903003700fd0341014100200341f8036a10cc01411e10282207450d01200741002900eca643370000200741166a4100290082a743370000200741106a41002900fca643370000200741086a41002900f4a6433700002003429e808080e0033702fc03200320073602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a220b4200370300200341f0026a41086a221c4200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a200b290300370300200341206a41086a201c290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341003602f803200341206a4120200341f8036a100621090240024020032802f803220a417f470d00411321070c010b024020090d00411321070c010b2003200a360284052003200936028005200341f8036a20034180056a10810120032802f80322074113460d03200341f0026a200341f8036a410472418401109a051a0240200a450d002009102a0b200341206a412010090b200341e8016a200341f0026a418401109a051a200341f8036a200341e8016a418401109a051a20074113460d03200341e0006a200341f8036a418401109a051a200320073602f803200341f8036a410472200341e0006a418401109a051a200341fc026a2002360200200341f0026a41086a2010360200200341003a00f402200341013a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341086a2903003700002003418d046a200341106a29030037000020034195046a200341186a2903003700002003419d046a20024102463a0000200341043a00fc03200341063a00f803200320032903003700fd0341014100200341f8036a10cc010c030b411a41011037000b411e41011037000b41c4d1c300413320034188056a419cd9c3001038000b411a10282202450d02200241002900b59643370000200241186a41002f00cd96433b0000200241106a41002900c59643370000200241086a41002900bd96433700002003429a808080a0033702fc03200320023602f8032003200341f8036a3602f0022003200341f0026a10c80120032802f80321072003280280042109200341f0026a41186a220a4200370300200341f0026a41106a220b4200370300200341f0026a41086a22024200370300200342003703f00220072009200341f0026a1000200341206a41186a200a290300370300200341206a41106a200b290300370300200341206a41086a2002290300370300200320032903f002370320024020032802fc03450d0020032802f803102a0b200341206a41201009200341f8036a41086a22074200370300200342003703f803419896c300411d200341f8036a100820022007290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621070240024020032802f8032202417f460d00200320023602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032209450d0520032902fc03210e02402002450d002007102a0b2003200e3702ec01200320093602e8010c010b200341003602f001200342013703e8010b200341e8016a2003106e20032802f001210220032802ec01210a20032802e8012109200341f8036a41086a22074200370300200342003703f803419896c300411d200341f8036a1008200341f0026a41086a2007290300370300200320032903f8033703f0020240024020090d00200341f0026a411010090c010b2003410036028004200342013703f8032002200341f8036a10b40102402002450d00200241057421072009210203402003200341f8036a3602602002200341e0006a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b200a450d002009102a0b02402008450d00201e102a0b2020450d010b201d102a0b410021074101210a4101210b410121090c140b411a41011037000b41c4d1c300413320034188056a419cd9c3001038000b41e0a7c3002107411621080b02402013450d00201e102a0b2020450d02201d102a0c020b41aba7c30021070b411321080b4101210a4101210b0c0b0b200141086a280200210941b49fc60021074113210820022d00000d052002280001220a41ff01714101470d05200141046a280200210b2003200a4118763a00422003200a4108763b01402003200241216a2d00003a005f2003200241196a2900003700572003200241116a29000037004f2003200241096a2900003700472003200241056a280000360043200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210702400240024002400240024002400240024002400240024020032802f8032208417f460d002007450d00200320083602ec01200320073602e801200341f8036a200341e8016a106d20032802f8032202450d0220032902fc03210e2008450d012007102a0c010b4200210e410121020b2002200e422088a7200341c0006a10cd0121070240200ea7450d002002102a0b024020070d0041b8a6c3002107411521080c100b2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a220a4200370300200341f0026a41106a221e4200370300200341f0026a41086a221d4200370300200342003703f00220022008200341f0026a1000200341e0006a41186a2208200a290300370300200341e0006a41106a220a201e290300370300200341e0006a41086a221e201d290300370300200320032903f00237036002402007450d002002102a0b200341f8036a41186a2008290300370300200341f8036a41106a200a290300370300200341f8036a41086a201e290300370300200320032903603703f803411e10282202450d01200241002900eca643370000200241166a4100290082a743370000200241106a41002900fca643370000200241086a41002900f4a6433700002003429e808080e0033702ec01200320023602e8012003200341e8016a3602f002200341f8036a200341f0026a10c80120032802e801210220032802f0012107200341f0026a41186a22084200370300200341f0026a41106a220a4200370300200341f0026a41086a221e4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a200a290300370300200341206a41086a201e290300370300200320032903f002370320024020032802ec01450d0020032802e801102a0b200341206a41204101410041001003417f470d02200341f8036a41086a22024200370300200342003703f8030240200b4102490d00418aa7c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f0024100210a200341003602f803200341f0026a4110200341f8036a10062102024020032802f8032207417f460d002002450d0020074104490d052002280000210a2002102a0b200341f8036a41086a22024200370300200342003703f803418aa7c3004121200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621020240024020032802f8032207417f460d002002450d00024020074104490d00200228000021072002102a200741016a21070c020b41c4d1c300413320034188056a419cd9c3001038000b410121070b200341f8036a41086a22024200370300200342003703f803418aa7c3004121200341f8036a1008200341f0026a41086a22082002290300370300200320032903f8033703f002200320073602f803200341f0026a4110200341f8036a4104100720024200370300200342003703f803419896c300411d200341f8036a100820082002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a1006210220032802f8032207417f460d062002450d06200320073602ec01200320023602e801200341f8036a200341e8016a106d20032802f8032208450d0520032902fc03210e02402007450d002002102a0b200320083602e8012003200e3702ec01200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a2107200e422088a72202200ea72208470d090c080b41fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f00241002102200341003602f803200341f0026a4110200341f8036a10062108024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f803220a450d0720032902fc03210e02402007450d002008102a0b200e422088a72102200ea7450d00200a102a0b200341f8036a2009418801109a051a200341fc026a2002360200200341f0026a41086a4101360200200341003a00f402200341013a00f002200341e8016a200341f8036a200341f0026a10f40120032d00f001210220034185046a200341e0006a41086a2903003700002003418d046a200341f0006a29030037000020034195046a200341f8006a2903003700002003419d046a20024102463a0000200341043a00fc03200341063a00f803200320032903603700fd03200341f8036a21020c090b41c4d1c300413320034188056a419cd9c3001038000b411e41011037000b41cda6c3002107411f21080c0c0b41c4d1c300413320034188056a419cd9c3001038000b41c4d1c300413320034188056a419cd9c3001038000b41002102200341003602f001200342013703e801200341206a41186a200341e0006a41186a290300370300200341206a41106a200341e0006a41106a290300370300200341206a41086a200341e0006a41086a29030037030020032003290360370320200341e8016a21070c010b41c4d1c300413320034188056a419cd9c3001038000b200741046a28020022082002470d00200241016a22082002490d022002410174221e2008201e20084b1b220841ffffff3f712008470d022008410574221e4100480d020240024020020d00201e102821020c010b20072802002002410574201e102c21020b2002450d0320072002360200200741046a200836020020032802f00121020b2007280200221e2002410574221c6a22072003290320370000200741186a200341206a41186a290300370000200741106a200341206a41106a290300370000200741086a200341206a41086a2903003700002003200241016a22073602f001200341f8036a41086a221d4200370300200342003703f803419896c300411d200341f8036a1008200341f0026a41086a201d290300370300200320032903f8033703f0022003410036028004200342013703f8032007200341f8036a10b401024020072002490d00201c41206a2107201e210203402003200341f8036a3602202002200341206a10c801200241206a2102200741606a22070d000b0b20032802fc032102200341f0026a411020032802f8032207200328028004100702402002450d002007102a0b02402008450d00201e102a0b200341f8036a2009418801109a051a200341e8016a41186a200341e0006a41186a290300370300200341e8016a41106a200341e0006a41106a290300370300200341e8016a41086a200341e0006a41086a290300370300200320032903603703e801411e10282202450d03200241002900eca643370000200241166a4100290082a743370000200241106a41002900fca643370000200241086a41002900f4a6433700002003429e808080e00337020420032002360200200320033602f002200341e8016a200341f0026a10c8012003280200210220032802082107200341f0026a41186a22084200370300200341f0026a41106a221e4200370300200341f0026a41086a221d4200370300200342003703f00220022007200341f0026a1000200341206a41186a2008290300370300200341206a41106a201e290300370300200341206a41086a201d290300370300200320032903f00237032002402003280204450d002003280200102a0b200341003602f802200342013703f002200341f8036a200341f0026a10eb0120032802f4022102200341206a412020032802f002220720032802f802100702402002450d002007102a0b200341f8036a106a412010282202450d0420022003290340370000200241186a200341c0006a41186a290300370000200241106a200341c0006a41106a290300370000200241086a200341c0006a41086a29030037000020034184026a4100360200200341f4016a428180808010370200200342013702fc01200320023602f0012003200b3602ec012003200a3602e801200341f8036a41186a200341e0006a41186a290300370300200341f8036a41106a200341e0006a41106a290300370300200341f8036a41086a200341e0006a41086a290300370300200320032903603703f803411a10282207450d05200741002900b59643370000200741186a41002f00cd96433b0000200741106a41002900c59643370000200741086a41002900bd96433700002003429a808080a00337020420032007360200200320033602f002200341f8036a200341f0026a10c8012003280200210720032802082108200341f0026a41186a221e4200370300200341f0026a41106a221d4200370300200341f0026a41086a221c4200370300200342003703f00220072008200341f0026a1000200341206a41186a201e290300370300200341206a41106a201d290300370300200341206a41086a201c290300370300200320032903f00237032002402003280204450d002003280200102a0b200341203602fc032003200341206a3602f803200341e8016a200341f8036a10b4032002102a20034185046a200341c0006a41086a2903003700002003418d046a200341c0006a41106a29030037000020034195046a200341c0006a41186a2903003700002003419d046a2003290360370000200341a5046a200341e0006a41086a290300370000200341ad046a200341e0006a41106a290300370000200341b5046a200341e0006a41186a290300370000200341c4046a200b360200200341c0046a200a360200200341003a00fc03200341063a00f803200320032903403700fd03200341f8036a21020b4100210b4101210a41014100200210cc012009102a0c070b1031000b201e41011037000b411e41011037000b412041011037000b411a41011037000b2009106a2009102a4100210b4101210a0c040b200141046a280200210941b49fc60021074113210820022d00000d022002280001220a41ff01714101470d022003200a4118763a00622003200a4108763b01602003200241216a2d00003a007f2003200241196a2900003700772003200241116a29000037006f2003200241096a2900003700672003200241056a2800003600634200210e200341f8036a41086a22024200370300200342003703f80341fbefc200411b200341f8036a1008200341f0026a41086a2002290300370300200320032903f8033703f002200341003602f803200341f0026a4110200341f8036a100621080240024020032802f8032207417f460d00200320073602ec01200320083602e801200341f8036a200341e8016a106d20032802f8032202450d0320032902fc03210e2007450d012008102a0c010b410121020b2002200e422088a7200341e0006a10cd0121070240200ea7450d002002102a0b024020070d0041b8a6c3002107411521080c030b4100210a2003410036028004200342013703f8032009200341f8036a10eb0120032802fc032107200328028004210820032802f8032102200341f0026a41186a220b4200370300200341f0026a41106a221e4200370300200341f0026a41086a221d4200370300200342003703f00220022008200341f0026a1000200341e8016a41186a2208200b290300370300200341e8016a41106a221c201e290300370300200341e8016a41086a221e201d290300370300200320032903f0023703e80102402007450d002002102a0b200341f8036a2009418801109a051a200341f0026a410d6a200341e0006a41086a290300370000200341f0026a41156a200341e0006a41106a290300370000200341f0026a411d6a200341e0006a41186a2903003700004101210b200341013a00f402200320032903603700f502200341013a00f002200341c0006a200341f8036a200341f0026a10f40120032d00482102200341f8036a410d6a201e290300370000200341f8036a41156a201c290300370000200341f8036a411d6a20082903003700002003419d046a20024102463a0000200341053a00fc03200341063a00f803200320032903e8013700fd0341014100200341f8036a10cc012009102a0b41012109410021070c040b41c4d1c300413320034188056a419cd9c3001038000b2009106a2009102a4101210b4100210a0b410121090c010b410021094101210b410021070b02402004410771417f6a220241024b0d0002400240024020020e03000102000b2009450d02200141086a280200450d02200141046a280200102a0c020b200a450d01200141046a2802002202106a2002102a0c010b200b450d00200141086a2802002202106a2002102a0b200020083602042000200736020020034190056a24000bfad30106017f027e017f017e157f017e230041b0086b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e12000102030405060708090a0b0c0d0e0f1013000b200341ac066a41013602002003420137029c06200341ccd1c5003602980620034104360254200341c4d1c5003602502003200341d0006a3602a80620034198066a41d4d1c500103e000b200141106a2903002104200141086a2903002105200141046a28020021062002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d0000210b200241146a2d0000210c200241126a2f0100210d200241116a2d0000210e200241106a2d0000210f2002410e6a2f010021102002410d6a2d000021112002410c6a2d000021122002410a6a2f01002113200241096a2d00002114200241046a2d00002115200241026a2f0100211602400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002118200241056a2d0000211920022d0001211a200320073703980641002102201a41ff01714101460d010b410121024104211941002117410021180b20032007370348200320083a0047200320093a00462003200a3b01442003200b3a00432003200c3a00422003200d3b01402003200e3a003f2003200f3a003e200320103b013c200320113a003b200320123a003a200320133b0138200320143a0037200320153a0032200320163b01302003201841ffff0371410874201741187472201941ff017172220a36003302402002450d00410f210841ea9fc6002109024002400240024002400240200a0e0700010203040565000b20032800372109200328003b21080c640b410e210841dc9fc60021090c630b410c210841d09fc60021090c620b4109210841c79fc60021090c610b4113210841b49fc60021090c600b4111210841a39fc60021090c5f0b200341b8036a41186a200341306a41186a290300370300200341b8036a41106a200341306a41106a290300370300200341b8036a41086a200341306a41086a290300370300200320032903303703b8030240200542808084fea6dee1115441002004501b450d0041e4d1c5002109410d21080c5f0b2003200341b8036a2005200410830202402003280200450d0041f1d1c5002109411a21080c5f0b20034188086a41086a220242003703002003420037038808419090c600411920034188086a1008200341e8076a41086a200229030037030020032003290388083703e807410021082003410036029806200341e8076a411020034198066a1006210202402003280298062209417f460d002002450d0020094104490d18200228000021082002102a0b20034188086a41086a220942003703002003420037038808419090c600411920034188086a1008200341e8076a41086a220a200929030037030020032003290388083703e8072003200841016a36029806200341e8076a411020034198066a41041007412010282202450d18200220032903b803370000200341ac066a428180808010370200200241186a200341b8036a41186a2217290300370000200241106a200341b8036a41106a2218290300370000200241086a200341b8036a41086a22192903003700002003200537039806200320023602a806200320043703a006200820034198066a10c404200341a0026a200610cf03200341d0006a200341a0026a418801109a051a200341e4016a2019290300370200200341ec016a2018290300370200200341f4016a2017290300370200200320083602d801200320032903b8033702dc0120094200370300200342003703880841ac89c500411520034188086a1008200a200929030037030020032003290388083703e8072003410036029806200341e8076a411020034198066a10062109024002402003280298062202417f460d002002210a20090d010b200341003602a0062003420137039806410020034198066a10b40120032802a0062102200328029c06210a20032802980621090b200320023602d0072003200a3602cc07200320093602c807024002402002450d0020034198066a20092002410110d6022003280298064101470d0120032802cc07450d5d20032802c807102a0c5d0b4101200341c8076a10b40120032802d801210a0240024020032802cc07220920032802d00722026b4104490d0020032802c80721090c010b200241046a22172002490d4b200941017422022017200220174b1b22024100480d4b0240024020090d002002102821090c010b20032802c80720092002102c21090b2009450d1b200320023602cc07200320093602c80720032802d00721020b2003200241046a3602d007200920026a200a360000200341d0006a200341c8076a10eb01200341dc016a200341c8076a108f010c5a0b200328029c0621170240200341a4066a2802002202200341a0066a2802002209460d0020032802d007200220096b6a220a41b0016a2218417f4c0d1b0240024020180d00410121190c010b201810282219450d1d0b2003201836028c0820032019360288082003200a36029008200320034188086a36029806201720034198066a200210d701200a2002490d1d2003280290082217200a490d1e20032802d00722172009490d1f200328028808211820032802c80721192003200a20026b220a3602302003201720096b221736028002200a2017470d20201820026a201920096a200a109a051a20032802d801210a02400240200328028c08220920032802900822026b4104490d0020032802880821090c010b200241046a22172002490d4b200941017422022017200220174b1b22024100480d4b0240024020090d002002102821090c010b20032802880820092002102c21090b2009450d222003200236028c08200320093602880820032802900821020b2003200241046a36029008200920026a200a360000200341d0006a20034188086a10eb01200341dc016a20034188086a108f012003280290082109200328028c08210a200328028808210220032802cc07450d5b20032802c807102a0c5b0b2003200341c8076a36029806201720034198066a200910d70120032802d801210a0240024020032802cc07220920032802d00722026b4104490d0020032802c80721090c010b200241046a22172002490d4a200941017422022017200220174b1b22024100480d4a0240024020090d002002102821090c010b20032802c80720092002102c21090b2009450d22200320023602cc07200320093602c80720032802d00721020b2003200241046a3602d007200920026a200a360000200341d0006a200341c8076a10eb01200341dc016a200341c8076a108f010c590b200141046a28020021162002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211a200320073703980641002102201a41ff01714101460d010b410121024104211841002117410021060b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201741187472201841ff017172220a3600830202402002450d00410f210841ea9fc6002109200a0e070f1213141555560f0b200341d0006a41186a20034180026a41186a290300370300200341d0006a41106a20034180026a41106a290300370300200341d0006a41086a20034180026a41086a290300370300200320032903800237035020034198066a201610b804024020032802a80622170d00418bd2c5002109412421084101210a0c570b200341b4066a280200210920034198066a41186a280200210820032802ac062102200341086a200341d0006a200329029c062207422086200335029806842204200341a4066a350200422086200742208884220710830220032802080d53200341306a41186a200341d0006a41186a290300370300200341306a41106a220a200341d0006a41106a290300370300200341306a41086a2218200341d0006a41086a29030037030020032003290350370330024020082002460d0020022106200821020c520b200241016a22062002490d48200241017422192006201920064b1b220641ffffff3f712006470d48200641057422194100480d480240024020020d002019102821170c010b201720024105742019102c21170b20170d51201941011037000b200141026a2d00002116200141046a280200211a20012d0001211b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211c200320073703980641002102201c41ff01714101460d010b410121024104211841002117410021060b20032007370348200320083a0047200320093a00462003200a3b0144200320193a00432003200b3a00422003200c3b01402003200d3a003f2003200e3a003e2003200f3b013c200320103a003b200320113a003a200320123b0138200320133a0037200320143a0032200320153b01302003200641ffff0371410874201741187472201841ff017172220a36003302402002450d00410f210841ea9fc60021090240200a0e0700121314155556000b20032800372109200328003b21084101210a0c560b20034180026a41186a200341306a41186a290300220737030020034180026a41106a200341306a41106a290300220437030020034180026a41086a200341306a41086a290300220537030020032003290330221d3703800220034198066a41186a200737030020034198066a41106a200437030020034198066a41086a20053703002003201d3703980620034198066a201a201b41ff0171410047201610c50421090c4f0b200141026a2d00002116200141046a280200211a20012d0001211b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211c200320073703980641002102201c41ff01714101460d010b410121024104211841002117410021060b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201741187472201841ff017172220a3600830202402002450d00410f210841ea9fc6002109200a0e070d1011121353540d0b200341d0006a41186a20034180026a41186a290300370300200341d0006a41106a20034180026a41106a290300370300200341d0006a41086a20034180026a41086a2903003703002003200329038002370350410f10282202450d1f200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f00137029c062003200236029806200341d0006a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b20034198066a200341306a412010fd01200341e8046a41026a220a20032d009b063a0000200341e8076a41086a200341ac066a290200370300200341e8076a410d6a2217200341b1066a290000370000200320032f0099063b01e8042003200341a4066a2902003703e807410121020240024020032d0098064101460d00410b210841d8d2c50021090c010b20034198066a41086a2802002108200328029c062109200341c0046a41026a200a2d00003a000020034188056a41086a200341e8076a41086a29030037030020034188056a410d6a2017290000370000200320032f01e8043b01c004200320032903e80737038805410021020b200341106a41026a200341c0046a41026a2d00003a000020034188086a41086a220a20034188056a41086a29030037030020034188086a41106a20034188056a41106a290300370300200320032f01c0043b011020032003290388053703880820020d53200341d0056a41026a200341106a41026a2d000022023a0000200341b8036a41086a2217200a290300370300200341b8036a410d6a220a20034188086a410d6a290000370000200320032f011022063b01d00520032003290388083703b803200341ab066a2017290300370000200341b0066a200a290000370000200320023a009a06200320063b0198062003200836009f062003200936009b06200320032903b8033700a30620034198066a201a201b41ff0171410047201610c50421090c4e0b41a6f5c5002109410e210820022d0000417f6a221941024b0d52200141046a280200210b4101210a4101210641012118410121170240024020190e03005d01000b200241046a2d00000d534101210a410121064101211841012117200241086a28020041036c2002410c6a280200410174490d5c0b20034198066a200b10ca03024020032802980622024113470d0041f3d4c5002109410d21084101210a0c540b200341a0026a20034198066a410472419401109a051a20032002360250200341d0006a410472200341a0026a419401109a051a200341003602a0062003420137039806200341d0006a20034198066a10eb01200328029c06210820032802a00621092003280298062102200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022009200341a0026a1000200341b8036a41186a2209200a290300370300200341b8036a41106a220a2017290300370300200341b8036a41086a22172006290300370300200320032903a0023703b80302402008450d002002102a0b20034198066a41186a200929030037030020034198066a41106a200a29030037030020034198066a41086a2017290300370300200320032903b80337039806411710282202450d1f200241002900e3d2453700002002410f6a41002900f2d245370000200241086a41002900ebd24537000020034297808080f0023702d405200320023602d0052003200341d0056a3602a00220034198066a200341a0026a10c80120032802d005210220032802d8052108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220022008200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b4101210a200341306a41204101410041001003417f460d4c200341d0006a106a4180d5c5002109412521080c530b200141046a280200210a41a6f5c5002109410e210820022d0000417f6a221741024b0d4a0240024020170e03004c01000b200241086a2802004101742002410c6a280200490d4b200241046a28020041ff01710d4b0b20034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e8070240200341e8076a41104101410041001003417f460d004194d3c5002109411521080c4b0b200341003602a0062003420137039806200a20034198066a10eb01200328029c06210820032802a00621092003280298062102200341a0026a41186a22174200370300200341a0026a41106a22064200370300200341a0026a41086a22184200370300200342003703a00220022009200341a0026a1000200341d0006a41186a22092017290300370300200341d0006a41106a2006290300370300200341d0006a41086a2018290300370300200320032903a00237035002402008450d002002102a0b20034198066a41186a200929030037030020034198066a41106a200341d0006a41106a29030037030020034198066a41086a200341d0006a41086a2903003703002003200329035037039806411310282202450d1f200241002900a9d3453700002002410f6a41002800b8d345360000200241086a41002900b1d34537000020034293808080b0023702d405200320023602d0052003200341d0056a3602a00220034198066a200341a0026a10c80120032802d005210220032802d8052108200341a0026a41186a22094200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022008200341a0026a1000200341306a41186a2009290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b200341b8036a200341306a10e103024020032802bc032202450d0020032802b803210820032802c0032109109801211702402009450d002002102a0b201720084f0d0041fad2c5002109411a21080c4b0b20034198066a200a418801109b051a200341003a00a00720034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341003602a802200342013703a00220034198066a200341a0026a10eb01024020032d00a007220241024b0d00024002400240024020020e03000102000b410021080c020b410121080c010b410221080b200320083a00a8080240024020032802a40220032802a8022202460d0020032802a00221090c010b200241016a22082002490d46200241017422092008200920084b1b22084100480d460240024020020d002008102821090c010b20032802a00220022008102c21090b2009450d22200320083602a402200320093602a00220032d00a808210820032802a80221020b2003200241016a3602a802200920026a20083a00000b20032802a4022102200341e8076a411020032802a002220820032802a802100702402002450d002008102a0b20034198066a106a200a102a4100210a410121060c480b200141046a28020021080240024020022d0000417f6a220941024b0d00024020090e03000102000b200241046a2d00000d00200241086a2802004102742002410c6a28020041036c4f0d010b2008106a2008102a41a6f5c5002109410e2108410021064101210a410121180c530b20034198066a2008418801109a051a200341023a00a00720034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341003602582003420137035020034198066a200341d0006a10eb01024020032d00a007220241024b0d00024002400240024020020e03000102000b410021090c020b410121090c010b410221090b200320093a00a80802400240200328025420032802582202460d002003280250210a0c010b200241016a22092002490d452002410174220a2009200a20094b1b22094100480d450240024020020d0020091028210a0c010b200328025020022009102c210a0b200a450d22200320093602542003200a36025020032d00a8082109200328025821020b2003200241016a360258200a20026a20093a00000b20032802542102200341e8076a4110200328025022092003280258100702402002450d002009102a0b20034198066a106a2008102a410021064101210a0c470b200141046a28020021080240024020022d0000417f6a220941024b0d00024020090e03000102000b200241086a2802002002410c6a280200490d00200241046a28020041ff0171450d010b2008106a2008102a41a6f5c5002109410e2108410021184101210a410121060c520b20034198066a2008418801109a051a200341013a00a00720034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341003602582003420137035020034198066a200341d0006a10eb01024020032d00a007220241024b0d00024002400240024020020e03000102000b410021090c020b410121090c010b410221090b200320093a00a80802400240200328025420032802582202460d002003280250210a0c010b200241016a22092002490d442002410174220a2009200a20094b1b22094100480d440240024020020d0020091028210a0c010b200328025020022009102c210a0b200a450d22200320093602542003200a36025020032d00a8082109200328025821020b2003200241016a360258200a20026a20093a00000b20032802542102200341e8076a4110200328025022092003280258100702402002450d002009102a0b20034198066a106a2008102a410021184101210a410121060c470b200141286a2802002118200141246a2802002106200341e8056a200141196a290000370300200341e0056a200141116a290000370300200341d0056a41086a200141096a290000370300200320012900013703d0054101210a41a6f5c5002109410e210820022d0000417e6a221741014b0d4f0240024020170e020001000b200241046a2d00000d50200241086a28020041036c2002410c6a280200410174490d500b20034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e80720034198066a200341e8076a10df032003280298062102200341a0026a20034198066a410472418401109a051a200320032800a107360288082003200341a4076a28000036008b08024020024113470d0041f2d3c5002109411021080c500b200341a0076a2d00002108200341b8036a200341a0026a418401109a051a20032002360250200341d0006a410472200341b8036a418401109a051a200841ff01710d4341c8d3c5002109412a21080c440b200341a0056a200141196a29000037030020034188056a41106a200141116a29000037030020034188056a41086a200141096a2900003703002003200129000137038805200241216a2f0000200241236a2d00004110747221082002411d6a2f00002002411f6a2d00004110747221092002410d6a2f00002002410f6a2d000041107472210a200241096a2f00002002410b6a2d0000411074722117200241056a2f0000200241076a2d0000411074722106200241206a2d0000210b200241106a2d0000210c2002410c6a2d0000210d200241086a2d0000210e0240024020022d00004102460d00410121180c010b200241246a2802002119200241116a2900002107200241046a2d0000210f2003200241196a2800003602a0062003200737039806410121180240200f4101460d000c010b2007421888a7210f2007a7210241002118200329029c0621070b200320083b019c022003419e026a20084110763a0000200320093b0198022003419a026a20094110763a0000200320023b018c02410e210820034180026a410e6a20024110763a00002003200a3b0188022003418a026a200a4110763a0000200320193a009f022003200b3a009b0220032007370390022003200f3a008f022003200c3a008b022003200d3a0087022003200e3a008302200320173b018402200320174110763a008602200320063b018002200320064110763a00820202402018450d0041a6f5c50021094101210a0c4f0b200341d0056a41186a20034180026a41186a290300370300200341d0056a41106a20034180026a41106a290300370300200341d0056a41086a20034180026a41086a29030037030020032003290380023703d00520034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e80720034198066a200341e8076a10df032003280298062102200341a0026a20034198066a4104722208418401109a051a2003200341a4076a28000036008b08200320032800a10736028808024020024113460d00200341d0006a200341a0026a418401109a051a20032002360298062008200341d0006a418401109a051a200341003602a802200342013703a00220034198066a200341a0026a10eb0120032802a402210820032802a802210920032802a0022102200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022009200341a0026a1000200341b8036a41186a200a290300370300200341b8036a41106a2017290300370300200341b8036a41086a2006290300370300200320032903a0023703b80302402008450d002002102a0b20034188056a200341b8036a4120109c05210220034198066a106a02402002450d00411021084182d4c50021094101210a0c500b411310282202450d20200241002900a9d3453700002002410f6a41002800b8d345360000200241086a41002900b1d34537000020034293808080b002370254200320023602502003200341d0006a3602a00220034188056a200341a0026a10c8012003280250210220032802582108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220022008200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a00237033002402003280254450d002003280250102a0b20034198066a200341306a10e103200328029c0622170d374101211741002118410021190c380b411421084192d4c50021094101210a0c4e0b4101210a20022d000120022d0000720d34200141046a28020010ce03410021090c490b4101210a20022d000120022d0000720d332001410c6a2802002119200141086a2802002108200141046a2802002109411710282202450d1e2002410f6a41002900918945370000200241086a410029008a894537000020024100290082894537000020024117412e102c2202450d1f2002200936001742002107200341a0026a41186a22174200370300200341a0026a41106a22064200370300200341a0026a41086a22184200370300200342003703a0022002411b200341a0026a1000200341306a41186a2017290300370300200341306a41106a2006290300370300200341306a41086a2018290300370300200320032903a0023703302002102a2003410036029806200341306a412020034198066a10062102024002402003280298062206417f470d00410821170c010b024020020d00410821170c010b200320063602542003200236025020034198066a200341d0006a1080012003280298062217450d21200329029c0621072006450d002002102a0b2007422088a721020240024002400240201720084190016c6a2206450d00200820024f0d0020062802004113460d01201720084190016c6a22084188016a2802002019470d012006106a20064113360200200841046a200341a0026a418401109a051a2008418c016a2003418b086a28000036000020084189016a200328008808360000411710282208450d252008410f6a41002900918945370000200841086a410029008a894537000020084100290082894537000020084117412e102c2208450d2620082009360017200341a0026a41186a22094200370300200341a0026a41106a22064200370300200341a0026a41086a22184200370300200342003703a0022008411b200341a0026a1000200341306a41186a2009290300370300200341306a41106a2006290300370300200341306a41086a2018290300370300200320032903a0023703302008102a20034198066a2017200210ac02200341306a4120200328029806220820032802a00610070240200328029c06450d002008102a0b20024190016c2108201721020340024020022802004113460d002002106a0b20024190016a2102200841f07e6a22080d000b410021092007a70d030c4c0b2002450d010b20024190016c2108201721020340024020022802004113460d002002106a0b20024190016a2102200841f07e6a22080d000b0b41a5d5c5002109411221082007a7450d4d2017102a0c4d0b2017102a0c480b200341b8036a41186a200141196a290000370300200341b8036a41106a200141116a290000370300200341b8036a41086a200141096a290000370300200320012900013703b8032002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d00012116200320073703980641002102201641ff01714101460d010b410121024100210641042118410021170b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201841ff017172201741187472220a3600830202402002450d00410f210841ea9fc6002109200a0e07040708090a4a4b040b200341c0046a41186a20034180026a41186a290300370300200341c0046a41106a20034180026a41106a290300370300200341c0046a41086a20034180026a41086a29030037030020032003290380023703c004410f10282202450d22200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f00137029c062003200236029806200341b8036a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b0240200341306a41204101410041001003417f460d0041ccd4c5002109410f21084101210a0c4c0b200341d0006a41186a200341c0046a41186a290300370300200341d0006a41106a200341c0046a41106a290300370300200341d0006a41086a200341c0046a41086a290300370300200320032903c00437035020034198066a41186a200341b8036a41186a29030037030020034198066a41106a200341b8036a41106a29030037030020034198066a41086a200341b8036a41086a290300370300200320032903b80337039806410f10282202450d2341002109200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702d405200320023602d00520034198066a200341d0056a108f0120032802d805210220032802d0052108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220082002200341a0026a1000200341306a41186a200a290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b2003412036029c062003200341306a36029806200341d0006a20034198066a10ff014101210a0c4b0b2002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d00012116200320073703980641002102201641ff01714101460d010b410121024100210641042118410021170b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201841ff017172201741187472220a3600830202402002450d00410f210841ea9fc6002109200a0e070306070809494a030b200341c0046a41186a20034180026a41186a2903002207370300200341c0046a41106a20034180026a41106a2903002204370300200341c0046a41086a20034180026a41086a29030022053703002003200329038002221d3703c00420034198066a41186a200737030020034198066a41106a200437030020034198066a41086a20053703002003201d37039806410f10282202450d2341002109200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702542003200236025020034198066a200341d0006a108f012003280258210220032802502108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220082002200341a0026a1000200341306a41186a200a290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a00237033002402003280254450d002003280250102a0b200341306a412010094101210a0c460b200341d0056a41186a200141196a290000370300200341d0056a41106a200141116a290000370300200341d0056a41086a200141096a290000370300200320012900013703d0052002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d00012116200320073703980641002102201641ff01714101460d010b410121024100210641042118410021170b200320073703d804200320083a00d704200320093a00d6042003200a3b01d404200320193a00d3042003200b3a00d2042003200c3b01d0042003200d3a00cf042003200e3a00ce042003200f3b01cc04200320103a00cb04200320113a00ca04200320123b01c804200320133a00c704200320143a00c204200320153b01c0042003200641ffff0371410874201841ff017172201741187472220a3600c30402402002450d00410f210841ea9fc60021090240200a0e070006070809494a000b20032800c704210920032800cb0421084101210a0c4a0b200341b8036a41186a200341c0046a41186a290300370300200341b8036a41106a200341c0046a41106a290300370300200341b8036a41086a200341c0046a41086a290300370300200320032903c0043703b803410f10282202450d23200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702cc07200320023602c807200341d0056a200341c8076a108f0120032802d007210220032802c8072108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a002370330024020032802cc07450d0020032802c807102a0b20034198066a200341306a412010fd0120034180026a41086a200341a1066a29000037030020034190026a200341a9066a29000037030020034180026a41186a200341b1066a290000370300200320032900990637038002410121020240024020032d0098064101460d00410b210841d8d2c50021090c010b200341e8046a41026a20032d00820222023a0000200341e8076a41086a220a20034193026a290000370300200341e8076a410d6a221720034198026a290000370000200341c0046a41026a20023a0000200320032f01800222023b01e8042003200329008b0222073703e807200320023b01c0042003280083022109200328008702210820034188056a410d6a201729000037000020034188056a41086a200a2903003703002003200737038805410021020b200341106a41026a220a200341c0046a41026a2d00003a000020034188086a41086a221720034188056a41086a29030037030020034188086a41106a20034188056a41106a290300370300200320032f01c0043b011020032003290388053703880820020d48200341e3006a2017290300370000200341d0006a41186a20034195086a290000370000200320032f01103b01502003200836005720032009360053200320032903880837005b2003200a2d00003a00520240200341d0006a200341b8036a4120109c05450d0041dbd4c5002109410b21084101210a0c4a0b20034198066a41186a200341d0056a41186a29030037030020034198066a41106a200341d0056a41106a29030037030020034198066a41086a200341d0056a41086a290300370300200320032903d00537039806410f10282202450d2441002109200241002900c9d245370000200241076a41002900d0d2453700002003428f808080f0013702542003200236025020034198066a200341d0006a108f012003280258210220032802502108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220082002200341a0026a100020034180026a41186a200a29030037030020034180026a41106a201729030037030020034180026a41086a2006290300370300200320032903a0023703800202402003280254450d002003280250102a0b20034180026a412010094101210a0c490b200141216a2d00002116200341106a41186a200141196a290000370300200341106a41106a200141116a290000370300200341106a41086a200141096a290000370300200320012900013703102002411a6a2901002107200241196a2d00002108200241186a2d00002109200241166a2f0100210a200241156a2d00002119200241146a2d0000210b200241126a2f0100210c200241116a2d0000210d200241106a2d0000210e2002410e6a2f0100210f2002410d6a2d000021102002410c6a2d000021112002410a6a2f01002112200241096a2d00002113200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320083a009b06200320093a009a062003200a3b0198060c010b200241086a2d00002117200241066a2f01002106200241056a2d0000211820022d0001211a200320073703980641002102201a41ff01714101460d010b410121024100210641042118410021170b2003200737039802200320083a009702200320093a0096022003200a3b019402200320193a0093022003200b3a0092022003200c3b0190022003200d3a008f022003200e3a008e022003200f3b018c02200320103a008b02200320113a008a02200320123b018802200320133a008702200320143a008202200320153b0180022003200641ffff0371410874201841ff017172201741187472220a360083022002450d01410f210841ea9fc6002109200a0e0700030405064647000b2003280087022109200328008b0221084101210a0c470b200341c0046a41186a20034180026a41186a2903002207370300200341c0046a41106a20034180026a41106a2903002204370300200341c0046a41086a20034180026a41086a29030022053703002003200329038002221d3703c004200341e8046a41186a2007370300200341e8046a41106a2004370300200341e8046a41086a20053703002003201d3703e80420034188056a41186a200341106a41186a29030037030020034188056a41106a200341106a41106a29030037030020034188056a41086a200341106a41086a2903003703002003200329031037038805200320163a00a805411510282202450d22200241002900d088453700002002410d6a41002900dd8845370000200241086a41002900d8884537000020034295808080d00237029c062003200236029806200341e8046a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341306a41186a2009290300370300200341306a41106a200a290300370300200341306a41086a2017290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b2003410036029806200341306a412020034198066a1006210202400240200328029806220a417f460d002002450d002003200a3602bc03200320023602b80320034198066a200341b8036a10b10120032d00b90622084102460d25200341d0006a41186a2217200341d2066a290100370300200341d0006a41106a2206200341ca066a290100370300200341d0006a41086a2218200341c2066a290100370300200341a0026a41086a2219200341e3066a290000370300200341a0026a41106a220b200341eb066a290000370300200341a0026a41186a220c200341f3066a290000370300200320032901ba063703502003200341db066a2900003703a002200341da066a2d000021090240200a450d002002102a0b200341b8036a41186a2017290300370300200341b8036a41106a2006290300370300200341b8036a41086a201829030037030020034188086a41086a201929030037030020034188086a41106a200b29030037030020034188086a41186a200c290300370300200320032903503703b803200320032903a002370388080c010b200341a0026a41186a22024200370300200341a0026a41106a22084200370300200341a0026a41086a22094200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a220a200229030037030020034198066a41106a2217200829030037030020034198066a41086a22062009290300370300200320032903a00237039806200341d0056a20034198066a412010fd010240024020032d00d0050d00200242003703002008420037030020094200370300200342003703a00241e588c500411d200341a0026a1000200a20022903003703002017200829030037030020062009290300370300200320032903a0023703980620034120360254200320034198066a360250200341e8046a200341d0006a10ff01410021090c010b200341c8076a41186a200341e9056a290000370300200341c8076a41106a200341e1056a290000370300200341c8076a41086a200341d9056a290000370300200320032900d1053703c807200341e8076a200341c8076a10b0012003410036029806200341e8076a412020034198066a100621022003280298062208417f460d272002450d27200320083602542003200236025020034198066a200341d0006a10b10120032d00b906220a4102460d2620034188086a41186a220920034198066a41186a29030037030020034188086a41106a221720034198066a41106a29030037030020034188086a41086a220620034198066a41086a29030037030020032003290398063703880820032d00b8062118200341a0026a200341ba066a221941c100109a051a02402008450d002002102a0b200341d0006a41186a22022009290300370300200341d0006a41106a22082017290300370300200341d0006a41086a220920062903003703002003200329038808370350200341b8036a200341a0026a41c100109a051a200341a0026a41186a22172002290300370300200341a0026a41106a22062008290300370300200341a0026a41086a220b2009290300370300200320032903503703a0022003200a3a00980620034198066a410172200341b8036a41c100109a051a20022017290300370300200820062903003703002009200b290300370300200341f8006a2019410020032d00b9064101461b360200200320032903a002370350200320183a00702003200341e8046a360274200341003602c003200342013703b803200341d0006a200341b8036a108f01024020032d0070220241064b0d000240024002400240024002400240024020020e0700010203040506000b410021080c060b410121080c050b410221080c040b410321080c030b410421080c020b410521080c010b410621080b200320083a00a8080240024020032802bc0320032802c0032202460d0020032802b80321090c010b200241016a22082002490d3c200241017422092008200920084b1b22084100480d3c0240024020020d002008102821090c010b20032802b80320022008102c21090b2009450d2a200320083602bc03200320093602b80320032d00a808210820032802c00321020b2003200241016a3602c003200920026a20083a00000b200341f4006a200341b8036a10aa0120032802bc032102200341e8076a412020032802b803220820032802c003100702402002450d002008102a0b200341a0026a41186a22024200370300200341a0026a41106a22084200370300200341a0026a41086a22094200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a200229030037030020034198066a41106a200829030037030020034198066a41086a2009290300370300200320032903a0023703980620034120360254200320034198066a360250200341e8046a200341d0006a10ff0120034188086a41086a200341c8076a41086a29030037030020034188086a41106a200341c8076a41106a29030037030020034188086a41186a200341c8076a41186a290300370300200320032903c80737038808410121090b410021080b200341a5066a200341b8036a41086a290300370000200341ad066a200341b8036a41106a290300370000200341b5066a200341b8036a41186a290300370000200341bd066a20093a0000200341be066a200329038808370100200341c6066a20034188086a41086a290300370100200341ce066a20034188086a41106a290300370100200341d6066a20034188086a41186a290300370100200320083a009c06200320032903b80337009d06200320034188056a36029806200341003602582003420137035020034188056a200341d0006a108f01024020032d00a805220241064b0d000240024002400240024002400240024020020e0700010203040506000b410021080c060b410121080c050b410221080c040b410321080c030b410421080c020b410521080c010b410621080b200320083a00a80802400240200328025420032802582202460d00200328025021090c010b200241016a22082002490d3a200241017422092008200920084b1b22084100480d3a0240024020020d002008102821090c010b200328025020022008102c21090b2009450d29200320083602542003200936025020032d00a8082108200328025821020b2003200241016a360258200920026a20083a00000b20034198066a410472200341d0006a10a90120032802542102200341306a4120200328025022082003280258100702402002450d002008102a0b200342e4cab5fbb6ccdcb0e3003703e004200341e0046a200341c0046a417f10a80220034198066a41086a41083a0000200341a1066a20032903c004370000200341a9066a200341c0046a41086a290300370000200341b1066a200341c0046a41106a290300370000200341b9066a200341c0046a41186a290300370000200341c1066a2003290310370000200341c9066a200341106a41086a290300370000200341d1066a200341106a41106a290300370000200341d9066a200341106a41186a290300370000200341053a009806410021094101210a4101410020034198066a10cc010c420b2002411a6a2901002107200241196a2d00002117200241186a2d00002106200241166a2f01002118200241156a2d00002110200241146a2d00002111200241126a2f01002112200241116a2d00002113200241106a2d000021192002410e6a2f0100210b2002410d6a2d0000210c2002410c6a2d0000210d2002410a6a2f0100210e200241096a2d0000210f200241046a2d00002114200241026a2f0100211502400240024020022d0000450d002003200737029c06200320173a009b06200320063a009a06200320183b0198060c010b200241086a2d00002108200241066a2f01002109200241056a2d0000210a20022d00012116200320073703980641002102201641ff01714101460d010b41012102410021094104210a410021080b200941ffff0371410874200a41ff017172200841187472210a2002450d04410f210841ea9fc60021090240200a0e0700010203044445000b200e410874200f72200d411874722109200b410874200c7220194118747221084101210a0c450b410e210841dc9fc60021094101210a0c440b410c210841d09fc60021094101210a0c430b4109210841c79fc60021094101210a0c420b4113210841b49fc60021094101210a0c410b2003200737038005200320173a00ff04200320063a00fe04200320183b01fc04200320103a00fb04200320113a00fa04200320123b01f804200320133a00f704200320193a00f6042003200b3b01f4042003200c3a00f3042003200d3a00f2042003200e3b01f0042003200f3a00ef042003200a3600eb04200320143a00ea04200320153b01e804411510282202450d22200241002900d08845370000410d21082002410d6a41002900dd8845370000200241086a41002900d8884537000020034295808080d00237025420032002360250200341e8046a200341d0006a108f012003280258210220032802502109200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220092002200341a0026a100020034198066a41186a200a29030037030020034198066a41106a201729030037030020034198066a41086a2006290300370300200320032903a0023703980602402003280254450d002003280250102a0b024020034198066a41204101410041001003417f470d0041e6d4c50021094101210a0c410b411510282202450d23200241002900d088453700002002410d6a41002900dd8845370000200241086a41002900d8884537000020034295808080d00237029c062003200236029806200341e8046a20034198066a108f0120032802a00621022003280298062108200341a0026a41186a22094200370300200341a0026a41106a220a4200370300200341a0026a41086a22174200370300200342003703a00220082002200341a0026a1000200341c0046a41186a2009290300370300200341c0046a41106a200a290300370300200341c0046a41086a2017290300370300200320032903a0023703c0040240200328029c06450d00200328029806102a0b2003410036029806200341c0046a412020034198066a100621022003280298062209417f460d252002450d25200320093602542003200236025020034198066a200341d0006a10b10120032d00b90622084102460d2420034188086a41186a20034198066a41186a29030037030020034188086a41106a20034198066a41106a29030037030020034188086a41086a20034198066a41086a29030037030020032003290398063703880820032d00b8062117200341a0026a200341ba066a41c100109a051a02402009450d002002102a0b200341c0046a412010090c260b41c4d1c3004133200341a8086a419cd9c3001038000b412041011037000b200241011037000b1036000b201841011037000b2002200a1044000b200a2017103c000b200920171044000b200341d0056a41146a4108360200200341dc056a412536020020034188056a41146a41033602002003420337028c05200341c8afc60036028805200341253602d4052003200341306a3602c004200320034180026a3602e804200342043703a8062003420137029c062003419cb0c600360298062003200341d0056a36029805200320034198066a3602e0052003200341e8046a3602d8052003200341c0046a3602d00520034188056a41d8b0c600103e000b200241011037000b200241011037000b410f41011037000b411741011037000b411341011037000b200841011037000b200941011037000b200941011037000b411341011037000b411741011037000b412e41011037000b41c4d1c3004133200341a8086a419cd9c3001038000b411741011037000b412e41011037000b410f41011037000b410f41011037000b410f41011037000b410f41011037000b410f41011037000b411541011037000b41c4d1c3004133200341a8086a419cd9c3001038000b41c4d1c3004133200341a8086a419cd9c3001038000b41b7b3c0004192011050000b200841011037000b200841011037000b411541011037000b411541011037000b41c4d1c3004133200341a8086a419cd9c3001038000b410221080b200341c8076a41186a220220034188086a41186a290300370300200341c8076a41106a220920034188086a41106a290300370300200341c8076a41086a220a20034188086a41086a29030037030020032003290388083703c80720034188056a200341a0026a41c100109a051a200341306a41086a2206200a290300370300200341306a41106a220a2009290300370300200341306a41186a22092002290300370300200320032903c807370330200341d0056a20034188056a41c100109a051a41072102024020084102460d0020034180026a41186a200929030037030020034180026a41106a200a29030037030020034180026a41086a20062903003703002003200329033037038002200320083a0050200341d0006a410172200341d0056a41c100109a05210a200341f2006a21094100210202400240024002400240024002400240024020032d00714101470d0020034198066a200910b001200341a0026a41186a20034198066a41186a22082900002207370300200341a0026a41106a20034198066a41106a22062900002204370300200341a0026a41086a20034198066a41086a221829000022053703002003200329009806221d3703a0022008200737030020062004370300201820053703002003201d37039806412010282202450d012002200329039806370000200241186a2008290300370000200241106a2006290300370000200241086a201829030037000020032d005021080b0240200841ff01714101460d0020032d00714101460d03200341a0026a41186a22084200370300200341a0026a41106a22094200370300200341a0026a41086a220a4200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a200829030037030020034198066a41106a200929030037030020034198066a41086a200a290300370300200320032903a0023703980620034198066a412010090c070b20034198066a200a10b001200341a0026a41186a20034198066a41186a2903002207370300200341a0026a41106a20034198066a41106a2903002204370300200341a0026a41086a20034198066a41086a29030022053703002003200329039806221d3703a002200341e8076a41186a22092007370300200341e8076a41106a220a2004370300200341e8076a41086a220620053703002003201d3703e807412010282208450d01200820032903e807370000200841186a2009290300370000200841106a200a290300370000200841086a200629030037000020034100360298062008412020034198066a1006210a2003280298062206417f460d04200a450d042003200636028c082003200a3602880820034198066a20034188086a10b10120032d00b90622194102460d03200341f1006a2109200341a0026a41206a220b20034198066a41206a22182d00003a0000200341a0026a41186a220c20034198066a41186a220d290300370300200341a0026a41106a220e20034198066a41106a220f290300370300200341a0026a41086a221020034198066a41086a221129030037030020032003290398063703a002200341b8036a200341ba066a221241c100109a051a02402006450d00200a102a0b201220032900b8033701002018200b2d00003a0000200d200c290300370300200f200e29030037030020112010290300370300200341c2066a200341b8036a41086a290000370100200341ca066a200341b8036a41106a290000370100200341d2066a200341b8036a41186a290000370100200320032903a00237039806200320193a00b906200341fa066a200941206a2d00003a0000200341f2066a200941186a290000370100200341ea066a200941106a290000370100200341e2066a200941086a290000370100200341da066a2009290000370100200341003602a802200342013703a00220034198066a200341a0026a108f01024020182d0000220941064b0d000240024002400240024002400240024020090e0700010203040506000b4100210a0c060b4101210a0c050b4102210a0c040b4103210a0c030b4104210a0c020b4105210a0c010b4106210a0b2003200a3a00a8080240024020032802a40220032802a8022209460d0020032802a00221060c010b200941016a220a2009490d1620094101742206200a2006200a4b1b220a4100480d160240024020090d00200a102821060c010b20032802a0022009200a102c21060b2006450d072003200a3602a402200320063602a00220032d00a808210a20032802a80221090b2003200941016a3602a802200620096a200a3a00000b200341b9066a200341a0026a10a90120032802a40221092008412020032802a002220a20032802a802100702402009450d00200a102a0b2008102a4101210a0c070b412041011037000b412041011037000b200341a0026a41186a22084200370300200341a0026a41106a220a4200370300200341a0026a41086a22064200370300200342003703a00241e588c500411d200341a0026a100020034198066a41186a200829030037030020034198066a41106a200a29030037030020034198066a41086a2006290300370300200320032903a00237039806200341203602a402200320034198066a3602a0022009200341a0026a10ff010c030b41c4d1c3004133200341a8086a419cd9c3001038000b41e2bbc00041d8001050000b200a41011037000b410021084100210a0b024002400240024002400240024020020d00410021090c010b20034100360298062002412020034198066a100621092003280298062206417f460d022009450d02200320063602bc03200320093602b80320034198066a200341b8036a10b10120032d00b9064102460d0120034188086a41186a221820034198066a41186a221929030037030020034188086a41106a220b20034198066a41106a220c29030037030020034188086a41086a220d20034198066a41086a220e29030037030020032003290398063703880820032d00b806210f200341a0026a200341ba066a221041c100109a051a02402006450d002009102a0b20192018290300370300200c200b290300370300200e200d2903003703002003200329038808370398062003200f3a00b8062010200341a0026a41c100109a051a200341c1066a200341d0006a41086a290300370000200341c9066a200341d0006a41106a290300370000200341d1066a200341d0006a41186a29030037000020034198066a41c1006a200341d0006a41206a2d00003a0000200320032903503700b906200341003602a802200342013703a00220034198066a200341a0026a108f01024020032d00b806220941064b0d000240024002400240024002400240024020090e0700010203040506000b410021060c060b410121060c050b410221060c040b410321060c030b410421060c020b410521060c010b410621060b200320063a00a8080240024020032802a40220032802a8022209460d0020032802a00221180c010b200941016a22062009490d14200941017422182006201820064b1b22064100480d140240024020090d002006102821180c010b20032802a00220092006102c21180b2018450d05200320063602a402200320183602a00220032d00a808210620032802a80221090b2003200941016a3602a802201820096a20063a00000b200341b9066a200341a0026a10a90120032802a40221092002412020032802a002220620032802a802100702402009450d002006102a0b2002102a410121090b200a20084572450d030c040b41c4d1c3004133200341a8086a419cd9c3001038000b41e2bbc00041d8001050000b200641011037000b2008102a0b02402002452009720d002002102a0b201721020b1098012108200342e4cab5fbb6ccdcb0e30037035041002109200341d0006a200341e8046a427f427f200841002002200241ff01714107461b41187441187541027441f48fc6006a2802004180de346c6a410210a90220034198066a41086a41093a000020034198066a41096a20032903e804370000200341a9066a200341e8046a41086a290300370000200341b1066a200341e8046a41106a290300370000200341b9066a200341e8046a41186a290300370000200341053a0098064101410020034198066a10cc014101210a0c190b41a39fc6002109411121080c180b20032802a006211820032903a0062207a7211941002102024002402007422088a7220641014b0d0020060e020201020b2006210803402008410176220920026a220a20022017200a4105746a200341d0056a4120109c054101481b2102200820096b220841014b0d000b0b201720024105746a200341d0056a4120109c052208450d0a0c010b20034198066a41186a200341d0056a41186a29030037030020034198066a41106a200341d0056a41106a29030037030020034198066a41086a200341d0056a41086a290300370300200320032903d005370398064100210620034198066a2108410021090c010b20034198066a41186a200341d0056a41186a29030037030020034198066a41106a200341d0056a41106a29030037030020034198066a41086a200341d0056a41086a290300370300200320032903d005370398062008411f7620026a220920064b0d0120034198066a21080b20062019460d012018210a0c020b41f8b0c0001032000b024020182006460d002018210a0c010b201841016a22022018490d042018410174220a2002200a20024b1b220a41ffffff3f71200a470d04200a41057422024100480d040240024020180d002002102821170c010b201720184105742002102c21170b2017450d010b201720094105746a220241206a2002200620096b410574109b051a200241186a200841186a290000370000200241106a200841106a290000370000200241086a200841086a290000370000200220082900003700001098012108411310282202450d01200241002900a9d3453700002002410f6a41002800b8d345360000200241086a41002900b1d34537000020034293808080b00237029c062003200236029806200320034198066a36025020034188056a200341d0006a10c801200328029806210220032802a0062109200341a0026a41186a22184200370300200341a0026a41106a22194200370300200341a0026a41086a220b4200370300200342003703a00220022009200341a0026a1000200341306a41186a2018290300370300200341306a41106a2019290300370300200341306a41086a200b290300370300200320032903a0023703300240200328029c06450d00200328029806102a0b410410282202450d0220034284808080c00037029c0620032002360298062002200841809c316a2209360000200641016a220220034198066a10b40102402002450d00200641057441206a2108201721020340200220034198066a108f01200241206a2102200841606a22080d000b0b200328029c062102200341306a4120200328029806220820032802a006100702402002450d002008102a0b0240200a450d002017102a0b20034198066a41086a410a3a0000200341a1066a20032903d005370000200341c1066a200329038805370000200341a9066a200341d0056a41086a290300370000200341b1066a200341d0056a41106a290300370000200341b9066a200341d0056a41186a290300370000200341c9066a20034188056a41086a290300370000200341d1066a20034188056a41106a290300370000200341d9066a20034188056a41186a290300370000200341053a009806200341e4066a2009360200410021094101410020034198066a10cc0120034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341e8076a411010094101210a0c110b200241011037000b411341011037000b410441011037000b1031000b41a6d4c5002109412621082019450d0b2017102a4101210a0c0c0b200341003602a0062003420137039806200341d0006a20034198066a10eb01200328029c06210920032802a00621172003280298062102200341a0026a41186a22194200370300200341a0026a41106a220b4200370300200341a0026a41086a220c4200370300200342003703a00220022017200341a0026a100020034198066a41186a201929030037030020034198066a41106a200b29030037030020034198066a41086a200c290300370300200320032903a0023703980602402009450d002002102a0b0240200341d0056a20034198066a4120109c05450d0041bcd3c5002109410c21080c010b20034188086a41086a22024200370300200342003703880841988bc500411620034188086a1008200341e8076a41086a200229030037030020032003290388083703e807200341e8076a41101009109801210220034198066a200341d0006a418801109a051a200341a0026a200220064180a30520064180a3054b1b6a20034198066a2008201810b704024020032802a0024101470d0020032802a4022209450d00200341a0026a41086a28020021080c0c0b410021090c0b0b200341d0006a106a0c0a0b410121180b41012117410021090c100b200a106a200a102a410121064100210a410121180c080b200341013a00880520034198066a41186a200341b8036a41186a29030037030020034198066a41106a200341b8036a41106a29030037030020034198066a41086a200341b8036a41086a290300370300200320032903b803370398060240411710282202450d0041002109200241002900e3d2453700002002410f6a41002900f2d245370000200241086a41002900ebd24537000020034297808080f0023702d405200320023602d0052003200341d0056a3602a00220034198066a200341a0026a10c80120032802d005210220032802d8052108200341a0026a41186a220a4200370300200341a0026a41106a22174200370300200341a0026a41086a22064200370300200342003703a00220022008200341a0026a1000200341306a41186a200a290300370300200341306a41106a2017290300370300200341306a41086a2006290300370300200320032903a002370330024020032802d405450d0020032802d005102a0b4101210a200341306a412020034188056a41011007200b10ce03200341d0006a106a0c030b411741011037000b412221084101210a0c050b201720024105746a22022003290330370000200241186a200341306a41186a290300370000200241106a200a290300370000200241086a20182903003700004101210a20034198066a41186a200841016a360200200341ac066a2006360200200320073703a0062003200437039806200320093602b406200320173602a806201620034198066a10c404410021090b4101210641012118410121170c0b0b41afd2c5002109411a21082002450d012017102a4101210a0c020b4111210841a39fc60021090b4101210a0b41012106410121180b410121170c060b20032802d007210920032802cc07210a20032802c80721020b2002450d00200341e8076a4110200220091007200a450d012002102a0c010b41b00110282202450d01200320032802d8013602a00720034198066a200341d0006a10cf0320034198066a41a4016a200341d0006a41a4016a29020037020020034198066a419c016a200341d0006a419c016a29020037020020034198066a4194016a200341d0006a4194016a290200370200200320032902dc013702a407200220034198066a41b001109a05210220034188086a41086a22094200370300200342003703880841ac89c500411520034188086a1008200341e8076a41086a200929030037030020032003290388083703e8072003411036029c062003200341e8076a360298062002410120034198066a10ef012002106a2002102a0b200341d0006a106a200341b0066a2004370300200341a8066a2005370300200341a4066a200836020041002117200341a0066a41003a0000200341053a0098064101210a4101410020034198066a10cc012006106a2006102a4101210641012118410021090c020b41b00141081037000b2006106a2006102a410021174101210a41012106410121180b0240024020012d0000417f6a2202410f4b0d00024002400240024020020e1000040404040102030404040405040505000b2017450d04200141046a2202280200106a2002280200102a0c040b200a450d03200141046a2202280200106a2002280200102a0c030b2006450d02200141046a2202280200106a2002280200102a0c020b2018450d01200141046a2202280200106a2002280200102a0c010b200241074b0d00024002400240024020020e080004040404010203000b200141046a2202280200106a2002280200102a0c030b200141046a2202280200106a2002280200102a0c020b200141046a2202280200106a2002280200102a0c010b200141046a2202280200106a2002280200102a0b2000200836020420002009360200200341b0086a24000b8b0708047f047e057f027e017f017e017f017e230041a0016b2202240041002103200241003a0098012001280204417f6a210402400240024003402004417f460d01200241f8006a20036a200128020022052d00003a0000200120043602042001200541016a3602002002200341016a22053a0098012004417f6a21042005210320054120470d000b200241d8006a41186a200241f8006a41186a290300370300200241d8006a41106a200241f8006a41106a290300370300200241d8006a41086a200241f8006a41086a29030037030020022002290378370358200241c0006a2001109f012002290340a7450d01200041003602200c020b0240200341ff0171450d00200241003a0098010b200041003602200c010b200241c0006a41106a290300210620022903482107200241286a2001109f0102402002290328a7450d00200041003602200c010b200241286a41106a290300210820022903302109200241206a2001106c02400240024002400240024020022802200d00200128020441186e220a41186c2204417f4c0d022002280224210b0240024020040d004108210c0c010b20041028220c450d040b0240200b450d00200241086a41106a210d4100210e41002105410021030340200241086a2001109f01024002402002290308a70d00200d290300210f2002290310211020022001106c2002280200450d010b200a450d03200c102a0c030b200341016a21042002280204211102402003200a470d00200e2004200e20044b1b220aad42187e2212422088a70d082012a722134100480d080240024020030d0020131028210c0c010b200c20052013102c210c0b200c450d070b200c20056a2203200f37030820032010370300200341106a2011360200200e41026a210e200541186a210520042103200b2004470d000b0b200c0d010b200041003602200c050b200241f8006a41186a200241d8006a41186a290300220f370300200241f8006a41106a200241d8006a41106a2903002210370300200241f8006a41086a200241d8006a41086a2903002212370300200220022903582214370378200041186a2008370300200020093703102000200637030820002007370300200041286a200b3602002000200a3602242000200c3602202000412c6a2014370200200041346a20123702002000413c6a2010370200200041c4006a200f3702000c040b1036000b200441081037000b201341081037000b1031000b200241a0016a24000bde0401067f230041306b2202240002400240024002400240411010282203450d00200341086a4100290097a5423700002003410029008fa54237000020024290808080800237021420022003360210410d200241106a10b40102400240024020022802142204200228021822056b410d490d002005410d6a2106200228021021030c010b2005410d6a22062005490d01200441017422032006200320064b1b22074100480d010240024020040d002007102821030c010b200228021020042007102c21030b2003450d032002200736021420022003360210200721040b20022006360218200320056a22054100290082a542370000200541056a4100290087a54237000020022003200610df0202402004450d002003102a0b20022802082203417f4c0d03200228020021050240024020030d0041012106410021040c010b20032104200310282206450d050b200620052003109a05210702402002280204450d002005102a0b200241106a200110e0020240200420036b4120490d00200341206a21050c060b200341206a22052003490d00200441017422062005200620054b1b22014100480d000240024020040d002001102821060c010b200720042001102c21060b02402006450d00200121040c060b200141011037000b1031000b411041011037000b200741011037000b1036000b200341011037000b200620036a22032002290010370000200341186a200241106a41186a290000370000200341106a200241106a41106a290000370000200341086a200241106a41086a290000370000200020053602082000200436020420002006360200200241306a24000bd00a010b7f230041c0006b2202240002400240024002400240024002400240024002400240411010282203450d00200341086a41002900b1c042370000200341002900a9c04237000020024290808080800237022420022003360220410d200241206a10b40102400240024020022802242204200228022822056b410d490d002005410d6a2106200228022021030c010b2005410d6a22062005490d01200441017422032006200320064b1b22074100480d010240024020040d002007102821030c010b200228022020042007102c21030b2003450d032002200736022420022003360220200721040b20022006360228200320056a22054100290082a542370000200541056a4100290087a54237000020022003200610df0202402004450d002003102a0b20022802082206417f4c0d03200228020021030240024020060d0041012107410021080c010b20062108200610282207450d050b200720032006109a05210902402002280204450d002003102a0b2001410c6a28020041046a2204417f4c0d03024002402004450d00200410282203450d0720024100360228200220043602240c010b200241003602282002200436022420024101360220410110282203450d07200241013602240b2002200336022020024101360228200320012d00003a00000240200228022422044101470d0041000d014102410241024102491b22044100480d01200341012004102c2203450d0820022004360224200220033602200b20024102360228200320012d00013a00010240024020044102460d00200421050c010b200441016a22052004490d012004410174220a2005200a20054b1b22054100480d010240024020040d002005102821030c010b200320042005102c21030b2003450d0920022005360224200220033602200b20024103360228200341026a20012d00023a0000024020054103470d00200541016a22042005490d012005410174220a2004200a20044b1b22044100480d010240024020050d002004102821030c010b200320052004102c21030b2003450d0a20022004360224200220033602200b20024104360228200341036a20012d00033a00002001280204210a200128020c2201200241206a10b4010240024020022802242205200228022822046b2001490d00200228022021030c010b200420016a22032004490d012005410174220b2003200b20034b1b220b4100480d010240024020050d00200b102821030c010b20022802202005200b102c21030b2003450d0b2002200b36022420022003360220200b21050b200320046a200a2001109a051a200241206a41186a220a4200370300200241206a41106a220b4200370300200241206a41086a220c4200370300200242003703202003200420016a200241206a1000200241186a200a290300370300200241106a200b290300370300200241086a200c2903003703002002200229032037030002402005450d002003102a0b0240200820066b4120490d00200641206a21010c0c0b200641206a22012006490d00200841017422032001200320014b1b22034100480d000240024020080d002003102821070c010b200920082003102c21070b02402007450d00200321080c0c0b200341011037000b1031000b411041011037000b200741011037000b1036000b200641011037000b200441011037000b410141011037000b200441011037000b200541011037000b200441011037000b200b41011037000b200720066a22032002290300370000200341186a200241186a290300370000200341106a200241106a290300370000200341086a200241086a290300370000200020013602082000200836020420002007360200200241c0006a24000be6e80106017f037e137f017e117f057e230041c0056b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e0e000102030405060708090f101112000b20034184056a4101360200200342013702f404200341ccd1c5003602f004200341043602b401200341c4d1c5003602b0012003200341b0016a36028005200341f0046a41bc80c500103e000b200141306a2903002104200141286a29030021052001411d6a29000021062001411c6a2d000021072001411b6a2d00002108200141196a2f00002109200141186a2d0000210a200141176a2d0000210b200141156a2f0000210c200141146a2d0000210d200141136a2d0000210e200141116a2f0000210f200141106a2d000021102001410f6a2d000021112001410d6a2f000021122001410c6a2d00002113200141086a2802002114200141076a2d00002115200141056a2f0000211641042117200141046a2d0000211820012d000121192002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d00002127200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e07000a0b0c0d5253000b20264108742027722025411874722102202341087420247220224118747221170c520b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d11200241002900fcae44370000200241066a4100290082af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b4101212b0240200341d0006a41204101410041001003417f460d00419681c500210241142117410121220c530b0240201841ff01714101470d00200341f0046a201441067610fe0120032802f00421170240024020032802f8042014413f7122024b0d00410021020c010b201720024105746a2202290018210620022d0017210720022d0016210820022f0014210920022d0013210a20022d0012210b20022f0010210c20022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d000721132002280003211420022d0002211520022f00002116410121020b024020032802f404450d002017102a0b20020d0041dc9fc6002102410e2117410121220c530b200320063703c801200320073a00c701200320083a00c601200320093b01c4012003200a3a00c3012003200b3a00c2012003200c3b01c0012003200d3a00bf012003200e3a00be012003200f3b01bc01200320103a00bb01200320113a00ba01200320123b01b801200320133a00b701200320143600b301200320153a00b201200320163b01b001410e10282202450d122002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341b0016a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a2222420037030020034188046a41086a2223420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a2022290300370300200341d0006a41086a20232903003703002003200329038804370350024020032802f404450d0020032802f004102a0b0240200341d0006a41204101410041001003417f460d0041cc80c500210241192117410121220c530b02402005428080e983b1de165441002004501b450d0041e580c500210241312117410121220c530b200341f0046a41186a200341b0016a41186a290300370300200341f0046a41106a200341b0016a41106a290300370300200341f0046a41086a200341b0016a41086a290300370300200320032903b0013703f004410e10282202450d13200241002900fcae44370000200241066a4100290082af443700002003428e808080e0013702d404200320023602d004200341a0036a200341d0046a108f0120032802d804210220032802d004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802d404450d0020032802d004102a0b200341203602d4042003200341d0006a3602d004200341f0046a200341d0046a10ff01410d10282202450d1420024100290098af44370000200241056a410029009daf443700002003428d808080d0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b024002400240024002400240201941037122024103460d0020020e03010203010b200341d0006a41204101410010070c040b410021170c020b410121170c010b410221170b200320173a00f004410110282202450d16200220173a0000200341d0006a41202002410110072002102a0b2003200341a0036a109101200341086a290300211a200329030021064100210220034198056a41003602002003419e056a20032d00a2033a00002003419f056a20032800a303360000200341a3056a20032d00a7033a0000200341b4056a20032903b803370200200341a4056a20032903a803370200200341ac056a20032903b00337020020034188056a201a20042006200554201a200454201a2004511b22171b221a370300200320032f01a0033b019c0520034208370390052003201a3703f80420032006200520171b221a3703f0042003201a37038005200341b0016a200341f0046a10b50420034194056a280200450d4f200328029005102a0c4f0b200141106a2903002106200141086a29030021042002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e0700090a0b0c5152000b20264108742027722025411874722102202341087420247220224118747221170c510b2003201a3703e8042003201b3a00e7042003201c3a00e6042003201d3b01e4042003201e3a00e3042003201f3a00e204200320203b01e004200320213a00df04200320223a00de04200320233b01dc04200320243a00db04200320253a00da04200320263b01d804200320273a00d7042003202a3600d304200320283a00d204200320293b01d004200341f0046a200341d0046a10b1044101212a0240024020032d00f0044101460d00410b211741aa81c50021020c010b2003418a046a20032d00f3043a0000200341b0016a41086a20034184056a290200370300200341bd016a20034189056a290000370000200320032f00f1043b0188042003200341fc046a2902003703b001200341f0046a41086a28020021174100212a20032802f40421020b20034180036a41026a222b20034188046a41026a2d00003a0000200341a8046a41086a2222200341b0016a41086a290300370300200341a8046a41106a200341b0016a41106a290300370300200320032f0188043b018003200320032903b0013703a804202a0d50200341b3036a2022290300370000200341a0036a41186a200341b5046a290000370000200320032f0180033b01a003200320173600a703200320023600a303200320032903a8043700ab032003202b2d00003a00a203410e10282202450d152002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006211720032802f0042202417f460d2e200320023602ac04200320173602a804200341f0046a200341a8046a108a02200328029005222a450d16200341f0046a41186a290300212c200341f0046a410c6a350200211a200341bc056a280200212b200341f0046a41c4006a2902002105200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412f6a28000021262003419c056a2f01002127200329038005212d20032902f404212e20032d00b305211b20032d00b205211c20032d00af05211d20032d00ae05211e20032d00ab05211f20032d00aa05212020032d00a705212120032d00a605212820032d00a305212920032d009e052114200329029405212f20032802f004210702402002450d002017102a0b200341b0016a41186a202c370300200341b0016a410c6a201a3e0200200341b0016a41c4006a2005370200200341f3016a201b3a0000200341f2016a201c3a0000200341b0016a41c0006a20223b0100200341ef016a201d3a0000200341ee016a201e3a0000200341b0016a413c6a20233b0100200341eb016a201f3a0000200341ea016a20203a0000200341b0016a41386a20243b0100200341e7016a20213a0000200341e6016a20283a0000200341b0016a41346a20253b0100200341e3016a20293a0000200341b0016a412f6a2026360000200341de016a20143a0000200341d4016a202f3702002003202d3703c0012003202e3702b4012003202b3602fc01200320273b01dc012003202a3602d001200320073602b001200341106a200341d0046a10910102402003290310221a20032903b001222e7d222f201a56200341106a41086a2903002205200341b0016a41086a29030022307d201a202e54ad7d221a200556201a2005511b0d0020032004202f202f200456201a200656201a2006511b22021b2204202d7c22053703c001200341c8016a2006201a20021b221a202c7c2005200454ad7c37030020032004202e7c22063703b0012003201a20307c2006200454ad7c3703b801200341a0036a200341b0016a10b5040b20032802d401450d4d20032802d001102a0c4d0b200141106a2903002106200141086a29030021042002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e070008090a0b5051000b20264108742027722025411874722102202341087420247220224118747221170c500b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d162002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d2d2002450d2d200320173602d404200320023602d004200341f0046a200341d0046a108a02200328029005222a450d17200341f0046a41186a290300211a200341f0046a410c6a350200212d200341bc056a280200212b200341f0046a41c4006a290200212e200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412f6a28000021262003419c056a2f01002127200329038005212c20032902f404212f20032d00b305211b20032d00b205211c20032d00af05211d20032d00ae05211e20032d00ab05211f20032d00aa05212020032d00a705212120032d00a605212820032d00a305212920032d009e052114200329029405210520032802f004210702402017450d002002102a0b200341b0016a41186a201a370300200341b0016a410c6a202d3e0200200341b0016a41c4006a202e370200200341f3016a201b3a0000200341f2016a201c3a0000200341b0016a41c0006a20223b0100200341ef016a201d3a0000200341ee016a201e3a0000200341b0016a413c6a20233b0100200341eb016a201f3a0000200341ea016a20203a0000200341b0016a41386a20243b0100200341e7016a20213a0000200341e6016a20283a0000200341b0016a41346a20253b0100200341e3016a20293a0000200341b0016a412f6a2026360000200341de016a20143a0000200341d4016a20053702002003202c3703c0012003202f3702b4012003202b3602fc01200320273b01dc012003202a3602d001200320073602b0012005a7212b02400240024002402005422088a7411f4b0d00202c2004202c200454201a200654201a2006511b22021b2204201a200620021b220684500d03200341c8016a4200201a20067d202c200454ad7d2205202c20047d222d428080e983b1de165441002005501b22171b37030020034200202d20171b3703c001200341f0046a41086a22024200370300200342003703f00441bb9cc6004112200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d004200341003602f004200341d0046a4110200341f0046a1006210220032802f004222a417f470d0141a005212a0c020b41c581c500210241232117202b450d52202a102a0c520b024020020d0041a005212a0c010b202a4104490d1a2002280000212a2002102a202a41a0056a212a0b024020032802d801220220032802d401470d00200241016a222b2002490d4720024101742222202b2022202b4b1b2222ad42187e2205422088a70d472005a7222b4100480d470240024020020d00202b102821020c010b20032802d001200241186c202b102c21020b2002450d1b200320223602d401200320023602d00120032802d80121020b20032802d001200241186c6a2202201a200620171b3703082002202c200420171b3703002002202a360210200320032802d80141016a3602d801200341a0036a200341b0016a10b50420032802d401212b0b202b450d4c20032802d001102a410021020c4d0b2002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e07000708090a4f50000b20264108742027722025411874722102202341087420247220224118747221170c4f0b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d192002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d2c2002450d2c200320173602b401200320023602b001200341f0046a200341b0016a108a022003280290052224450d1a20034188056a290300212c200341fc046a350200211a200341b4056a290200212e200341b0056a2f01002126200341ac056a2f01002127200341a8056a2f0100211b200341a4056a2f0100211c2003419c056a2f0100211d200329038005212d20032902f404210620032d00b305211e20032d00b205211f20032d00af05212020032d00ae05212120032d00ab05212820032d00aa05212920032d00a705211420032d00a605210720032d00a3052108200328009f05210920032d009e05210a200329029405210420032802f004212a02402017450d002002102a0b200341f0046a41086a22024200370300200342003703f00441bb9cc6004112200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d0044100212b200341003602f004200341d0046a4110200341f0046a10062102024020032802f0042217417f460d002002450d0020174104490d1d2002280000212b2002102a0b201a422086200642208884211a2006422086202aad8421062004a7210b0240024002402004422088a7222541186c2202450d00202420026a2122200241686a2117202421020340200241086a290300210520022903002104202b200241106a280200222a490d024200201a20057d2006200454ad7d2205200620047d22042006562005201a562005201a511b222a1b211a42002004202a1b2106201741686a2117200241186a22022022470d000b0b410821234100212a0240200b0d00410021250c020b2024102a410021250c010b411810282223450d1e202320043703002023202a360210202320053703080240024020170d004101212a410121250c010b200241186a210c202541186c20246a41686a210e4101212a410121250340200c210202400340200241086a290300210520022903002104202b200241106a2802002217490d014200201a20057d2006200454ad7d2205200620047d22042006562005201a562005201a511b22171b211a4200200420171b2106200241186a22022022470d000c030b0b02402025202a470d00202a41016a2225202a490d48202a410174220c2025200c20254b1b2225ad42187e222f422088a70d48202fa7220c4100480d4802400240202a0d00200c102821230c010b2023202a41186c200c102c21230b2023450d220b200241186a210c2023202a41186c6a220d2005370308200d2004370300200d2017360210202a41016a212a200e2002470d000b0b200b450d002024102a0b200341b4056a202e370200200341b3056a201e3a0000200341b2056a201f3a0000200341b0056a20263b0100200341af056a20203a0000200341ae056a20213a0000200341ac056a20273b0100200341ab056a20283a0000200341aa056a20293a0000200341a8056a201b3b0100200341a7056a20143a0000200341a6056a20073a0000200341a4056a201c3b0100200341a3056a20083a00002003419f056a20093600002003419e056a200a3a000020034198056a202a36020020034194056a20253602002003202d3703800520034188056a202c370300200320063703f0042003201d3b019c0520032023360290052003201a3703f8040240202d202c844200520d00202a450d1c0b200341a0036a200341f0046a10b5040c4a0b200141106a2903002106200141086a29030021042002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b410021024100212a0b202a41ffff0371410874200241187472201741ff017172212a0240202b450d00410f211741ea9fc60021020240202a0e0700060708094e4f000b20264108742027722025411874722102202341087420247220224118747221170c4e0b2003201a370398012003201b3a0097012003201c3a0096012003201d3b0194012003201e3a0093012003201f3a009201200320203b019001200320213a008f01200320223a008e01200320233b018c01200320243a008b01200320253a008a01200320263b018801200320273a0087012003202a36008301200320283a008201200320293b018001410e10282202450d1e2002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f00420034180016a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d2b2002450d2b200320173602a403200320023602a003200341f0046a200341a0036a108a02200328029005222a450d1f200341f0046a41186a290300211a200341f0046a410c6a3502002105200341bc056a280200212b200341f0046a41c4006a290200212c200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005212d20032902f404212e20032d00b305212720032d00b205211b20032d00af05211c20032d00ae05211d20032d00ab05211e20032d00aa05211f20032d00a705212020032d00a605212120032d00a3052128200328009f05212920032d009e052114200329029405212f20032802f004210702402017450d002002102a0b200341b0016a41186a201a370300200341b0016a410c6a20053e0200200341b0016a41c4006a202c370200200341f3016a20273a0000200341f2016a201b3a0000200341b0016a41c0006a20223b0100200341ef016a201c3a0000200341ee016a201d3a0000200341b0016a413c6a20233b0100200341eb016a201e3a0000200341ea016a201f3a0000200341b0016a41386a20243b0100200341e7016a20203a0000200341e6016a20213a0000200341b0016a41346a20253b0100200341e3016a20283a0000200341df016a2029360000200341de016a20143a0000200341d4016a202f3702002003202d3703c0012003202e3702b4012003202b3602fc01200320263b01dc012003202a3602d001200320073602b001200341b0016a412c6a222310a7042003200637037820032004370370411210282202450d20200241002900c1ae44370000200241106a41002f00d1ae443b0000200241086a41002900c9ae4437000020034292808080a0023702f404200320023602f0042023200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a100621250240024020032802f0042226417f460d002025450d00200320263602ec03200320253602e803200341386a200341e8036a109f0120032802380d4a20032802ec032202450d4a20032002417f6a222a3602ec03200320032802e803222241016a222b3602e80320222d0000220241014b0d4a410021240240024020020e020100010b41002102200341003a00900503400240202a2002470d00200341003602ec03200241ff0171450d4d200341003a0090050c4d0b200341f0046a20026a202220026a221741016a2d00003a00002003201741026a3602e8032003200241016a22173a0090052017210220174120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202a20176b222a3602ec0341012124202220176a41016a212b0b20034188046a41186a200341a0036a41186a29030037030020034188046a41106a200341a0036a41106a29030037030020034188046a41086a200341a0036a41086a290300370300200320032903a00337038804202a450d4a2003202a417f6a222a3602ec032003202b41016a3602e803202b2d0000221741014b0d4a410021020240024020170e020100010b41002102200341003a00900503400240202a2002470d00200341003602ec03200241ff0171450d4d200341003a0090050c4d0b200341f0046a20026a202b20026a221741016a2d00003a00002003201741026a3602e8032003200241016a22173a0090052017210220174120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202a20176b3602ec03410121020b200341c0026a41186a2222200341a0036a41186a2217290300370300200341c0026a41106a2223200341a0036a41106a222a290300370300200341c0026a41086a2227200341a0036a41086a222b290300370300200341e0026a41086a221b20034188046a41086a290300370300200341e0026a41106a221c20034188046a41106a290300370300200341e0026a41186a221d20034188046a41186a290300370300200320032903a0033703c00220032003290388043703e002200341a0026a41186a221e201d290300370300200341a0026a41106a221d201c290300370300200341a0026a41086a221c201b290300370300200320032903e0023703a00220034180026a41186a221b202229030037030020034180026a41106a2222202329030037030020034180026a41086a22232027290300370300200320032903c00237038002200341f0046a41186a2227201e290300370300200341f0046a41106a221e201d290300370300200341f0046a41086a221d201c290300370300200320032903a0023703f0042017201b290300370300202a2022290300370300202b202329030037030020032003290380023703a00320244102460d4a200341d0046a41186a2027290300370300200341d0046a41106a201e290300370300200341d0046a41086a201d290300370300200341a8046a41086a202b290300370300200341a8046a41106a202a290300370300200341a8046a41186a2017290300370300200320032903f0043703d004200320032903a0033703a80402402026450d002025102a0b200341a0036a41186a200341d0046a41186a290300370300200341a0036a41106a200341d0046a41106a290300370300200341a0036a41086a200341d0046a41086a29030037030020034188046a41086a200341a8046a41086a29030037030020034188046a41106a200341a8046a41106a29030037030020034188046a41186a200341a8046a41186a290300370300200320032903d0043703a003200320032903a804370388040c010b200341e8036a41186a22024200370300200341e8036a41106a22174200370300200341e8036a41086a222a4200370300200342003703e80341d3aec400411a200341e8036a1000200341f0046a41186a222b2002290300370300200341f0046a41106a22222017290300370300200341f0046a41086a2224202a290300370300200320032903e8033703f004200341a0036a200341f0046a412010fd01024020032d00a0030d002002420037030020174200370300202a4200370300200342003703e80341d3aec400411a200341e8036a1000202b2002290300370300202220172903003703002024202a290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d0042023200341d0046a10ff0141002102410021240c010b200341c8036a41186a200341b9036a290000370300200341c8036a41106a200341b1036a290000370300200341c8036a41086a200341a9036a290000370300200320032900a1033703c80320034180036a200341c8036a10ac01200341003602f00420034180036a4120200341f0046a1006212420032802f0042226417f460d222024450d22200320263602a401200320243602a001200341206a200341a0016a109f012003290320a70d4820032802a4012202450d48200341306a290300211a2003290328210620032002417f6a222a3602a401200320032802a001222241016a222b3602a00120222d0000220241014b0d48410021250240024020020e020100010b41002102200341003a00900503400240202a2002470d00200341003602a401200241ff0171450d4b200341003a0090050c4b0b200341f0046a20026a202220026a221741016a2d00003a00002003201741026a3602a0012003200241016a22173a0090052017210220174120470d000b20034188046a41086a200341f0046a41086a2903002204370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a20043703002003202a20176b222a3602a401200320032903f004220437038804200320043703d00441012125202220176a41016a212b0b200341e8036a41186a200341d0046a41186a290300370300200341e8036a41106a200341d0046a41106a290300370300200341e8036a41086a200341d0046a41086a290300370300200320032903d0043703e80341002122200341003a00f004202a450d482003202a417f6a222a3602a4012003202b41016a3602a001202b2d0000220241014b0d480240024020020e020100010b41002102200341003a00900503400240202a2002470d00200341003602a401200241ff0171450d4b200341003a0090050c4b0b200341f0046a20026a202b20026a221741016a2d00003a00002003201741026a3602a0012003200241016a22173a0090052017210220174120470d000b200341a8046a41086a200341f0046a41086a2903002204370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a20043703002003202a20176b3602a401200320032903f00422043703a804200320043703d004410121220b200341c0026a41186a222b200341d0046a41186a2202290300370300200341c0026a41106a2227200341d0046a41106a2217290300370300200341c0026a41086a221b200341d0046a41086a222a290300370300200341e0026a41086a221c200341e8036a41086a290300370300200341e0026a41106a221d200341e8036a41106a290300370300200341e0026a41186a221e200341e8036a41186a290300370300200320032903d0043703c002200320032903e8033703e002200341a0026a41186a221f201e290300370300200341a0026a41106a221e201d290300370300200341a0026a41086a221d201c290300370300200320032903e0023703a00220034180026a41186a221c202b29030037030020034180026a41106a222b202729030037030020034180026a41086a2227201b290300370300200320032903c00237038002200341f0046a41186a221b201f290300370300200341f0046a41106a221f201e290300370300200341f0046a41086a221e201d290300370300200320032903a0023703f0042002201c2903003703002017202b290300370300202a202729030037030020032003290380023703d00420254102460d48200341a8046a41186a201b290300370300200341a8046a41106a201f290300370300200341a8046a41086a201e29030037030020034188046a41086a202a29030037030020034188046a41106a201729030037030020034188046a41186a2002290300370300200320032903f0043703a804200320032903d0043703880402402026450d002024102a0b200341d0046a41186a2224200341a8046a41186a290300370300200341d0046a41106a222b200341a8046a41106a290300370300200341d0046a41086a2226200341a8046a41086a290300370300200341e8036a41086a220220034188046a41086a2227290300370300200341e8036a41106a221720034188046a41106a221b290300370300200341e8036a41186a222a20034188046a41186a221c290300370300200320032903a8043703d00420032003290388043703e803200320253a00f004200341f9046a202629030037000020034181056a202b29030037000020034189056a2024290300370000200320032903d0043700f104200320223a00910520034192056a222520032903e8033701002003419a056a2002290300370100200341a2056a2017290300370100200341aa056a202a29030037010041002124200341e4046a2025410020221b3602002003201a3703d804200320063703d004200320233602e004200341003602b004200342013703a8042003200341d0046a3602880420034188046a200341a8046a10a301202b200341a8046a10aa0120032802ac04212b20034180036a412020032802a804222220032802b00410070240202b450d002022102a0b202a42003703002017420037030020024200370300200342003703e80341d3aec400411a200341e8036a1000200341f0046a41186a202a290300370300200341f0046a41106a2017290300370300200341f0046a41086a2002290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d0042023200341d0046a10ff012027200341c8036a41086a290300370300201b200341c8036a41106a290300370300201c200341c8036a41186a290300370300200320032903c80337038804410121020b200341fd046a200341a0036a41086a29030037000020034185056a200341a0036a41106a2903003700002003418d056a200341a0036a41186a29030037000020034195056a20023a000020034196056a2003290388043701002003419e056a20034188046a41086a290300370100200341a6056a20034188046a41106a290300370100200341ae056a20034188046a41186a290300370100200320243a00f404200320032903a0033700f5042003200341f0006a3602f004200341003602d804200342013703d0042003200341f0006a3602a804200341a8046a200341d0046a10a301200341f0046a410472200341d0046a10a90120032802d4042102200341d0006a412020032802d004221720032802d804100702402002450d002017102a0b20032802d401450d4a20032802d001102a410021020c4b0b2001410c6a2802002108200141086a280200211b41042117200141046a280200211c2002411a6a290100211a200241196a2d0000211d200241186a2d0000211e200241166a2f0100211f200241156a2d00002120200241146a2d00002121200241126a2f01002128200241116a2d00002129200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d00002127200241046a2d00002114200241026a2f010021070240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a0240202b450d00410f211741ea9fc6002102024002400240024002400240202a0e070001020304054c000b20264108742027722025411874722102202341087420247220224118747221170c4b0b410e211741dc9fc60021020c4a0b410c211741d09fc60021020c490b4109211741c79fc60021020c480b4113211741b49fc60021020c470b4111211741a39fc60021020c460b2003201a370398012003201d3a0097012003201e3a0096012003201f3b019401200320203a009301200320213a009201200320283b019001200320293a008f01200320223a008e01200320233b018c01200320243a008b01200320253a008a01200320263b018801200320273a0087012003202a36008301200320143a008201200320073b018001410e10282202450d212002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f00420034180016a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a10062102024020032802f0042217417f460d002002450d00200320173602a403200320023602a003200341f0046a200341a0036a108a02200328029005222a450d23200341f0046a41186a2903002106200341f0046a410c6a3502002104200341bc056a280200212b200341f0046a41c4006a2902002105200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005212c20032902f404212d20032d00b305212720032d00b205211d20032d00af05211e20032d00ae05211f20032d00ab05212020032d00aa05212120032d00a705212820032d00a605212920032d00a3052114200328009f05210720032d009e052109200329029405211a20032802f004210a02402017450d002002102a0b200341b0016a41186a2006370300200341b0016a410c6a20043e0200200341b0016a41c4006a2005370200200341f3016a20273a0000200341f2016a201d3a0000200341b0016a41c0006a20223b0100200341ef016a201e3a0000200341ee016a201f3a0000200341b0016a413c6a20233b0100200341eb016a20203a0000200341ea016a20213a0000200341b0016a41386a20243b0100200341e7016a20283a0000200341e6016a20293a0000200341b0016a41346a20253b0100200341e3016a20143a0000200341df016a2007360000200341de016a20093a0000200341b0016a41246a201a3702002003202c3703c0012003202d3702b4012003202b3602fc01200320263b01dc012003202a3602d0012003200a3602b0012008450d44200341003a00a804200341103602e0042003201c200841246c6a3602dc042003201c3602d8042003201b3602d4042003201c3602d0042003200341a8046a3602e404200341f0046a200341d0046a1085040240024020032d00f0044101460d0020032802dc04212a20032802d8042102024003400240202a2002470d002002212b0c020b20022d00002117200241246a222b210220174102470d000b0b2003202b3602d8044100212441012123024020032802d4040d00410021020c020b20032802d004102a410021020c010b412010282223450d25202320032900f104370000202341186a20034189056a290000370000202341106a20034181056a290000370000202341086a200341f9046a290000370000200341a0036a41106a200341d0046a41106a290300370300200341a0036a41086a200341d0046a41086a290300370300200320032903d0043703a003200341f0046a200341a0036a1085040240024020032d00f0040d0041012102410121240c010b200341f0046a4101722117410221224120212b4101210241012124034020034188046a41186a2225201741186a29000037030020034188046a41106a2226201741106a29000037030020034188046a41086a2227201741086a2900003703002003201729000037038804024020022024470d00200241016a222a2002490d472022202a2022202a4b1b222441ffffff3f712024470d472024410574222a4100480d470240024020020d00202a102821230c010b2023202b202a102c21230b20230d00202a41011037000b2023202b6a222a200329038804370000202a41186a2025290300370000202a41106a2026290300370000202a41086a2027290300370000202241026a2122202b41206a212b200241016a2102200341f0046a200341a0036a10850420032d00f0040d000b0b20032802ac03212b20032802a8032117024003400240202b2017470d00201721220c020b20172d0000212a201741246a22222117202a4102470d000b0b200320223602a80320032802a403450d0020032802a003102a0b024020032d00a804450d002024450d432023102a0c430b2023450d42200341b0016a412c6a222a10a604200320023602a801200320243602a401200320233602a001411210282202450d2520024100290095ae44370000200241106a41002f00a5ae443b0000200241086a410029009dae4437000020034292808080a0023702f404200320023602f004202a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222b420037030020034188046a41106a2222420037030020034188046a41086a2223420037030020034200370388042017200220034188046a1000200341d0006a41186a202b290300370300200341d0006a41106a2022290300370300200341d0006a41086a20232903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006212b024020032802f0042222417f460d00202b450d00200320223602ec032003202b3602e803200341d0046a200341e8036a106d20032802d0042224450d3f20032802d404212a20032802ec032202450d3e20032002417f6a22233602ec03200320032802e803222541016a22263602e80320252d0000221741014b0d3e410021020240024020170e020100010b41002102200341003a0090050340024020232002470d00200341003602ec03200241ff0171450d41200341003a0090050c410b200341f0046a20026a202520026a221741016a2d00003a00002003201741026a3602e8032003200241016a22173a0090052017210220174120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202320176b22233602ec0341012102202520176a41016a21260b20034188046a41186a200341a0036a41186a29030037030020034188046a41106a200341a0036a41106a29030037030020034188046a41086a200341a0036a41086a290300370300200320032903a003370388042023450d3e20032023417f6a22253602ec032003202641016a3602e80320262d0000222341014b0d3e410021170240024020230e020100010b41002117200341003a0090050340024020252017470d00200341003602ec03201741ff0171450d41200341003a0090050c410b200341f0046a20176a202620176a222341016a2d00003a00002003202341026a3602e8032003201741016a22233a0090052023211720234120470d000b200341a0036a41086a200341f0046a41086a290300370300200341a0036a41106a200341f0046a41106a290300370300200341a0036a41186a200341f0046a41186a290300370300200320032903f0043703a0032003202520236b3602ec03410121170b200341c0026a41186a2223200341a0036a41186a2225290300370300200341c0026a41106a2226200341a0036a41106a2227290300370300200341c0026a41086a221b200341a0036a41086a221c290300370300200341e0026a41086a221d20034188046a41086a290300370300200341e0026a41106a221e20034188046a41106a290300370300200341e0026a41186a221f20034188046a41186a290300370300200320032903a0033703c00220032003290388043703e002200341a0026a41186a2220201f290300370300200341a0026a41106a221f201e290300370300200341a0026a41086a221e201d290300370300200320032903e0023703a00220034180026a41186a221d202329030037030020034180026a41106a2223202629030037030020034180026a41086a2226201b290300370300200320032903c00237038002200341f0046a41186a2020290300370300200341f0046a41106a201f290300370300200341f0046a41086a201e290300370300200320032903a0023703f0042025201d29030037030020272023290300370300201c202629030037030020032003290380023703a0030c400b200341e8036a41186a22024200370300200341e8036a41106a22174200370300200341e8036a41086a222b4200370300200342003703e80341a7aec400411a200341e8036a1000200341f0046a41186a22222002290300370300200341f0046a41106a22232017290300370300200341f0046a41086a2224202b290300370300200320032903e8033703f004200341a0036a200341f0046a412010fd01024020032d00a0030d002002420037030020174200370300202b4200370300200342003703e80341a7aec400411a200341e8036a100020222002290300370300202320172903003703002024202b290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d004202a200341d0046a10ff01410021170c3c0b200341c8036a41186a200341b9036a290000370300200341c8036a41106a200341b1036a290000370300200341c8036a41086a200341a9036a290000370300200320032900a1033703c80320034180036a200341c8036a10ae01200341003602f00420034180036a4120200341f0046a1006212320032802f0042226417f460d262023450d26200320263602cc04200320233602c804200341f0006a200341c8046a106d20032802702224450d392003280274212220032802cc042202450d38200341f8006a280200212b20032002417f6a22273602cc04200320032802c804221b41016a221c3602c804201b2d0000220241014b0d38410021250240024020020e020100010b41002102200341003a0090050340024020272002470d00200341003602cc04200241ff0171450d3b200341003a0090050c3b0b200341f0046a20026a201b20026a221741016a2d00003a00002003201741026a3602c8042003200241016a22173a0090052017210220174120470d000b20034188046a41086a200341f0046a41086a290300221a370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a201a3703002003202720176b22273602cc04200320032903f004221a370388042003201a3703d00441012125201b20176a41016a211c0b200341e8036a41186a200341d0046a41186a290300370300200341e8036a41106a200341d0046a41106a290300370300200341e8036a41086a200341d0046a41086a290300370300200320032903d0043703e80341002117200341003a00f0042027450d3820032027417f6a22273602cc042003201c41016a3602c804201c2d0000220241014b0d380240024020020e020100010b41002102200341003a0090050340024020272002470d00200341003602cc04200241ff0171450d3b200341003a0090050c3b0b200341f0046a20026a201c20026a221741016a2d00003a00002003201741026a3602c8042003200241016a22173a0090052017210220174120470d000b200341a8046a41086a200341f0046a41086a290300221a370300200341d0046a41186a200341f0046a41186a290300370300200341d0046a41106a200341f0046a41106a290300370300200341d0046a41086a201a3703002003202720176b3602cc04200320032903f004221a3703a8042003201a3703d004410121170b200341c0026a41186a2202200341d0046a41186a2227290300370300200341c0026a41106a221b200341d0046a41106a221c290300370300200341c0026a41086a221d200341d0046a41086a221e290300370300200341e0026a41086a221f200341e8036a41086a290300370300200341e0026a41106a2220200341e8036a41106a290300370300200341e0026a41186a2221200341e8036a41186a290300370300200320032903d0043703c002200320032903e8033703e002200341a0026a41186a22282021290300370300200341a0026a41106a22212020290300370300200341a0026a41086a2220201f290300370300200320032903e0023703a00220034180026a41186a221f200229030037030020034180026a41106a2202201b29030037030020034180026a41086a221b201d290300370300200320032903c00237038002200341f0046a41186a2028290300370300200341f0046a41106a2021290300370300200341f0046a41086a2020290300370300200320032903a0023703f0042027201f290300370300201c2002290300370300201e201b29030037030020032003290380023703d0040c3a0b4110211741b581c50021020c450b2002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a0240202b450d00410f211741ea9fc60021020240202a0e0700040506074c4d000b20264108742027722025411874722102202341087420247220224118747221170c4c0b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d252002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006211720032802f0042202417f460d29200320023602d404200320173602d004200341f0046a200341d0046a108a02200328029005222a450d26200341f0046a41186a290300211a200341f0046a410c6a3502002106200341bc056a280200212b200341f0046a41c4006a2902002104200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005210520032902f404212c20032d00b305212720032d00b205211b20032d00af05211c20032d00ae05211d20032d00ab05211e20032d00aa05211f20032d00a705212020032d00a605212120032d00a3052128200328009f05212920032d009e052114200329029405212d20032802f004210702402002450d002017102a0b200341b0016a41186a201a370300200341b0016a410c6a20063e0200200341b0016a41c4006a2004370200200341f3016a20273a0000200341f2016a201b3a0000200341b0016a41c0006a20223b0100200341ef016a201c3a0000200341ee016a201d3a0000200341b0016a413c6a20233b0100200341eb016a201e3a0000200341ea016a201f3a0000200341b0016a41386a20243b0100200341e7016a20203a0000200341e6016a20213a0000200341b0016a41346a20253b0100200341e3016a20283a0000200341df016a2029360000200341de016a20143a0000200341d4016a2202202d370200200320053703c0012003202c3702b4012003202b3602fc01200320263b01dc012003202a3602d001200320073602b001200341b0016a412c6a221710a604201710a7042002280200450d4820032802d001102a410021020c490b20012d000121142002411a6a290100211a200241196a2d0000211b200241186a2d0000211c200241166a2f0100211d200241156a2d0000211e200241146a2d0000211f200241126a2f01002120200241116a2d00002121200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d0000212741042117200241046a2d00002128200241026a2f010021290240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a0240202b450d00410f211741ea9fc60021020240202a0e0700030405064b4c000b20264108742027722025411874722102202341087420247220224118747221170c4b0b2003201a3703b8032003201b3a00b7032003201c3a00b6032003201d3b01b4032003201e3a00b3032003201f3a00b203200320203b01b003200320213a00af03200320223a00ae03200320233b01ac03200320243a00ab03200320253a00aa03200320263b01a803200320273a00a7032003202a3600a303200320283a00a203200320293b01a003410e10282202450d262002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a0036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006210220032802f0042217417f460d282002450d28200320173602d404200320023602d004200341f0046a200341d0046a108a02200328029005222a450d27200341f0046a41186a290300211a200341f0046a410c6a3502002106200341bc056a280200212b200341f0046a41c4006a2902002104200341f0046a41c0006a2f01002122200341f0046a413c6a2f01002123200341f0046a41386a2f01002124200341f0046a41346a2f01002125200341f0046a412c6a2f01002126200329038005210520032902f404212c20032d00b305212720032d00b205211b20032d00af05211c20032d00ae05211d20032d00ab05211e20032d00aa05211f20032d00a705212020032d00a605212120032d00a3052128200328009f05212920032d009e052107200329029405212d20032802f004210802402017450d002002102a0b200341b0016a41186a201a370300200341b0016a410c6a20063e0200200341b0016a41c4006a2004370200200341f3016a20273a0000200341f2016a201b3a0000200341b0016a41c0006a20223b0100200341ef016a201c3a0000200341ee016a201d3a0000200341b0016a413c6a20233b0100200341eb016a201e3a0000200341ea016a201f3a0000200341b0016a41386a20243b0100200341e7016a20203a0000200341e6016a20213a0000200341b0016a41346a20253b0100200341e3016a20283a0000200341df016a2029360000200341de016a20073a0000200341d4016a202d370200200320053703c0012003202c3702b4012003202b3602fc01200320263b01dc012003202a3602d001200320083602b001410d10282202450d2920024100290098af44370000200241056a410029009daf443700002003428d808080d0013702f404200320023602f004200341b0016a412c6a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b024002400240024002400240201441037122024103460d0020020e03010203010b200341d0006a41204101410010070c040b410021170c020b410121170c010b410221170b200320173a00f004410110282202450d2b200220173a0000200341d0006a41202002410110072002102a0b20032802d401450d4720032802d001102a410021020c480b2001411d6a29000021062001411c6a2d000021072001411b6a2d00002108200141196a2f00002109200141186a2d0000210a200141176a2d0000210b200141156a2f0000210c200141146a2d0000210d200141136a2d0000210e200141116a2f0000210f200141106a2d000021102001410f6a2d000021112001410d6a2f000021122001410c6a2d00002113200141086a280200211b200141076a2d00002115200141056a2f0000211641042117200141046a2d000021182002411a6a290100211a200241196a2d0000211c200241186a2d0000211d200241166a2f0100211e200241156a2d0000211f200241146a2d00002120200241126a2f01002121200241116a2d00002128200241106a2d000021222002410e6a2f010021232002410d6a2d000021242002410c6a2d000021252002410a6a2f01002126200241096a2d00002127200241046a2d00002129200241026a2f010021140240024020022d00000d0020022d00014101470d00200241056a2d00002117200241066a2f0100212a200241086a2d000021024100212b0c010b4101212b4100212a410021020b202a41ffff0371410874201741ff017172200241187472212a202b450d04410f211741ea9fc60021020240202a0e070001020304494a000b20264108742027722025411874722102202341087420247220224118747221170c490b410e211741dc9fc60021020c480b410c211741d09fc60021020c470b4109211741c79fc60021020c460b4113211741b49fc60021020c450b2003201a3703e0032003201c3a00df032003201d3a00de032003201e3b01dc032003201f3a00db03200320203a00da03200320213b01d803200320283a00d703200320223a00d603200320233b01d403200320243a00d303200320253a00d203200320263b01d003200320273a00cf032003202a3600cb03200320293a00ca03200320143b01c803200341f0046a200341c8036a10b1044101212a0240024020032d00f0044101460d00410b211741aa81c50021020c010b2003418a046a20032d00f3043a0000200341b0016a41086a20034184056a290200370300200341bd016a20034189056a290000370000200320032f00f1043b0188042003200341fc046a2902003703b001200341f0046a41086a28020021174100212a20032802f40421020b20034180036a41026a222b20034188046a41026a2d00003a0000200341a8046a41086a2222200341b0016a41086a290300370300200341a8046a41106a200341b0016a41106a290300370300200320032f0188043b018003200320032903b0013703a804202a0d44200341fb036a202229030037000020034180046a200341b5046a290000370000200320032f0180033b01e803200320173600ef03200320023600eb03200320032903a8043700f3032003202b2d00003a00ea030240201841ff01714101470d00200341f0046a201b41067610fe0120032802f00421170240024020032802f804201b413f7122024b0d00410021020c010b201720024105746a2202290018210620022d0017210720022d0016210820022f0014210920022d0013210a20022d0012210b20022f0010210c20022d000f210d20022d000e210e20022f000c210f20022d000b211020022d000a211120022f0008211220022d000721132002280003211b20022d0002211520022f00002116410121020b024020032802f404450d002017102a0b20020d0041dc9fc6002102410e21170c450b200320063703c004200320073a00bf04200320083a00be04200320093b01bc042003200a3a00bb042003200b3a00ba042003200c3b01b8042003200d3a00b7042003200e3a00b6042003200f3b01b404200320103a00b304200320113a00b204200320123b01b004200320133a00af042003201b3600ab04200320153a00aa04200320163b01a804410e10282202450d252002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341a8046a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b0240200341d0006a41204101410041001003417f460d0041cc80c5002102411921170c450b200341a8046a200341e8036a4120109c05450d41410e10282202450d26200241002900fcae44370000200241066a4100290082af443700002003428e808080e0013702f404200320023602f004200341c8036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341203602f4042003200341d0006a3602f004200341a8046a200341f0046a10ff01410e10282202450d272002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702f404200320023602f004200341e8036a200341f0046a108f0120032802f804210220032802f004211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802f404450d0020032802f004102a0b200341003602f004200341d0006a4120200341f0046a1006212a0240024020032802f0042217417f470d00410021020c010b2003201736028c042003202a36028804200341f0046a20034188046a108a022003280290052202450d29200341b0016a41186a200341f0046a41186a290300370300200341b0016a41106a200341f0046a41106a290300370300200341b0016a41086a200341f0046a41086a290300370300200320032903f0043703b0012003419c056a2f010021222003419f056a2800002124200341a4056a2f01002126200341a8056a2f0100211c200341ac056a2f0100211f200341b0056a2f01002128200341b4056a290200212d200341bc056a2802002107200329029405212c20032d009e05212320032d00a305212520032d00a605212720032d00a705211b20032d00aa05211d20032d00ab05211e20032d00ae05212020032d00af05212120032d00b205212920032d00b305211402402017450d00202a102a0b200341d0006a412010090b200341a0036a41186a200341b0016a41186a290300221a370300200341a0036a41106a200341b0016a41106a2903002206370300200341a0036a41086a200341b0016a41086a2903002204370300200320032903b00122053703a003200341f0046a41186a2217201a370300200341f0046a41106a222a2006370300200341f0046a41086a222b2004370300200320053703f0042002450d41200341d0046a41186a2017290300221a370300200341d0046a41106a202a2903002206370300200341d0046a41086a202b2903002204370300200320032903f00422053703d0042017201a370300202a2006370300202b2004370300200341b4056a202d370200200341b3056a20143a0000200341b2056a20293a0000200341b0056a20283b0100200341af056a20213a0000200341ae056a20203a0000200341ac056a201f3b0100200341ab056a201e3a0000200341aa056a201d3a0000200341a8056a201c3b0100200341a7056a201b3a0000200341a6056a20273a0000200341a4056a20263b0100200341a3056a20253a00002003419f056a20243600002003419e056a20233a000020034194056a202c370200200320053703f004200320073602bc05200320223b019c052003200236029005410e10282202450d292002410029008aaf44370000200241066a4100290090af443700002003428e808080e0013702b401200320023602b001200341a8046a200341b0016a108f0120032802b801210220032802b001211720034188046a41186a222a420037030020034188046a41106a222b420037030020034188046a41086a2222420037030020034200370388042017200220034188046a1000200341d0006a41186a202a290300370300200341d0006a41106a202b290300370300200341d0006a41086a20222903003703002003200329038804370350024020032802b401450d0020032802b001102a0b200341203602b4012003200341d0006a3602b001200341f0046a200341b0016a10b604200328029405450d41200328029005102a410021020c420b4101212b024020022d000120022d000072450d0041a39fc600210241112117410121220c450b200141046a2802002102200341f0046a41086a22174200370300200342003703f00441889cc6004116200341f0046a1008200341d0046a41086a2017290300370300200320032903f0043703d004200320023602f004200341d0046a4110200341f0046a410410070c2c0b20022d000120022d0000720d2c200341f0046a41086a22024200370300200342003703f004418e9dc6004110200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d004200341023a00f0044101212b410110282202450d28200241023a0000200341d0046a41102002410110072002102a0c2b0b20022d000120022d0000720d2b200341f0046a41086a22024200370300200342003703f004418e9dc6004110200341f0046a1008200341d0046a41086a2002290300370300200320032903f0043703d0044101212b200341013a00f004410110282202450d28200241013a0000200341d0046a41102002410110072002102a0c2a0b200141086a280200212a200141046a2802002123024020022d000120022d000072450d0041a39fc600210241112117410021224101212b202a450d422023102a0c420b2001410c6a2802002102200341f0046a41086a22174200370300200342003703f00441c8ffc4004115200341f0046a1008200341d0046a41086a2017290300370300200320032903f0043703d004200341003602f804200342013703f0042002200341f0046a10b40102402002450d00200241057421172023210203402002200341f0046a108f01200241206a2102201741606a22170d000b0b20032802f4042102200341d0046a411020032802f004221720032802f804100702402002450d002017102a0b4101212b202a450d282023102a0c280b410e41011037000b410e41011037000b410e41011037000b410d41011037000b410141011037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b41c4d1c3004133200341e0026a419cd9c3001038000b202b41081037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b200341c8016a200341b4056a290200370300200341c0016a200341ac056a290200370300200341b0016a41086a200341a4056a2902003703002003200329029c053703b001200342f3e885db96cddbb3203703e803200310980136028804200341d0046a200341b0016a109a0220032802d404211720032802d004210220032802d804212a200341e4046a200341e8036a36020020032002202a4105746a3602dc04200320023602d804200320173602d404200320023602d004200320034188046a3602e004200341a8046a200341d0046a108701200341d0046a41086a200341a8046a41086a280200360200200320032903a8043703d004200341b0016a200341d0046a109c02200341b0016a1095020c2e0b41c4d1c3004133200341e0026a419cd9c3001038000b411841081037000b200c41081037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b411241011037000b41b7b3c0004192011050000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b412041011037000b411241011037000b41b7b3c0004192011050000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b41b581c5002102411021170c210b410d41011037000b410141011037000b410e41011037000b410e41011037000b410e41011037000b41c4d1c3004133200341e0026a419cd9c3001038000b410e41011037000b410141011037000b410141011037000b41002122410021020c180b41002102410121220c170b41a39fc6002102411121170c150b2022450d002024102a0b410221250b20254102460d01200341a8046a41186a221c200341f0046a41186a290300370300200341a8046a41106a221d200341f0046a41106a290300370300200341a8046a41086a221e200341f0046a41086a29030037030020034188046a41086a221f200341d0046a41086a222729030037030020034188046a41106a2220200341d0046a41106a220229030037030020034188046a41186a2221200341d0046a41186a221b290300370300200320032903f0043703a804200320032903d0043703880402402026450d002023102a0b201b201c2903003703002002201d2903003703002027201e290300370300200341e8036a41086a2223201f290300370300200341e8036a41106a22262020290300370300200341e8036a41186a221c2021290300370300200320032903a8043703d00420032003290388043703e803200320253a00f004200341f9046a202729030037000020034181056a200229030037000020034189056a201b290300370000200320032903d0043700f104200320173a00910520034192056a222520032903e8033701002003419a056a2023290300370100200341a2056a2026290300370100200341aa056a201c290300370100200220254100201741ff01714101461b3602002003202a3602dc042003202b3602d804200320223602d404200320243602d004200341003602b004200342013703a804202b200341a8046a10b401200341dc046a21230240202b450d00202b41057421172024210203402002200341a8046a108f01200241206a2102201741606a22170d000b0b2023200341a8046a10aa0120032802ac04210220034180036a412020032802a804221720032802b004100702402002450d002017102a0b02402022450d002024102a0b200341e8036a41186a22024200370300200341e8036a41106a22174200370300200341e8036a41086a222b4200370300200342003703e80341a7aec400411a200341e8036a1000200341f0046a41186a2002290300370300200341f0046a41106a2017290300370300200341f0046a41086a202b290300370300200320032903e8033703f004200341203602d4042003200341f0046a3602d004202a200341d0046a10ff0120034188046a41086a200341c8036a41086a29030037030020034188046a41106a200341c8036a41106a29030037030020034188046a41186a200341c8036a41186a290300370300200320032903c80337038804410121170b410021020c040b41c4d1c3004133200341e0026a419cd9c3001038000b202a450d002024102a0b410221020b20024102460d01200341d0046a41186a2223200341f0046a41186a290300370300200341d0046a41106a2225200341f0046a41106a290300370300200341d0046a41086a2226200341f0046a41086a290300370300200341a8046a41086a2227200341a0036a41086a221b290300370300200341a8046a41106a221c200341a0036a41106a221d290300370300200341a8046a41186a221e200341a0036a41186a221f290300370300200320032903f0043703d004200320032903a0033703a80402402022450d00202b102a0b201f2023290300370300201d2025290300370300201b202629030037030020034188046a41086a202729030037030020034188046a41106a201c29030037030020034188046a41186a201e290300370300200320032903d0043703a003200320032903a80437038804202a450d002024102a0b200341fd046a200341a0036a41086a29030037000020034185056a200341a0036a41106a2903003700002003418d056a200341a0036a41186a29030037000020034195056a20173a000020034196056a2003290388043701002003419e056a20034188046a41086a290300370100200341a6056a20034188046a41106a290300370100200341ae056a20034188046a41186a290300370100200320023a00f404200320032903a0033700f5042003200341a0016a3602f004200341003602d804200342013703d00420032802a001210220032802a8012217200341d0046a10b401200341f0046a410472212a02402017450d002017410574211703402002200341d0046a108f01200241206a2102201741606a22170d000b0b202a200341d0046a10a90120032802d4042102200341d0006a412020032802d004221720032802d804100702402002450d002017102a0b024020032802a401450d0020032802a001102a0b024020032802d401450d0020032802d001102a0b4100212b41012122410021020c0d0b41c4d1c3004133200341e0026a419cd9c3001038000b41dc9fc6002102410e21174100212b20032802d401212a0c020b1031000b201aa7212a41e881c5002102411721174101212b0b0240202a450d0020032802d001102a0b202b0d00410121224100212b0c080b410121224100212b201b450d07201c102a0c070b41c4d1c3004133200341e0026a419cd9c3001038000b41c4d1c3004133200341e0026a419cd9c3001038000b200328029405450d00200328029005102a410021020c010b410021020b4101212b410121220c020b4111211741a39fc60021020b4101212b410121220b0240024020012d0000222a410d4b0d004101202a7441be3f710d010240202a4106460d00202a410d470d012022450d02200141086a280200450d02200141046a280200102a0c020b202b450d01200141086a280200450d01200141046a280200102a0c010b200141086a280200450d00200141046a280200102a0b2000201736020420002002360200200341c0056a24000b990d02067f077e230041b0016b22052400024002400240024002400240411410282206450d00200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302001200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b20054100360240200541106a4120200541c0006a100621060240024020052802402207417f470d004200210b4200210c0c010b20074110490d02200641086a290000210c2006290000210b2006102a0b411410282206450d02200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302002200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b20054100360240200541106a4120200541c0006a100621060240024020052802402207417f470d004200210d4200210e0c010b20074110490d04200641086a290000210e2006290000210d2006102a0b024020034280a094a58d1d7c220f200354220620042006ad7c2210200454200f20035a1b450d0041f092c1002106412821010c060b0240200b200f7d2211200b56200c20107d200b200f54ad7d220f200c56200f200c511b4101470d00419893c1002106411d21010c060b0240200342ffffe883b1de165620044200522004501b0d00200d200e8450450d0041e293c1002106411f21010c060b200541086a200141022011200f10bc01024020052802082206450d00200528020c21010c060b0240200d20037c220c200d542206200e20047c2006ad7c220b200e54200b200e511b450d0041b593c1002106412d21010c060b41002106024020012002470d000c060b0240200120024120109c050d000c060b20012011200f108f02411410282206450d04200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302002200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b0240200541106a41204101410041001003417f470d002002109302200541f8006a200b370300200541f0006a200c370300200541c0006a41086a41003a0000200541c9006a2002290000370000200541d1006a200241086a290000370000200541d9006a200241106a290000370000200541e1006a200241186a290000370000200541023a004041014100200541c0006a10cc010b2002200c200b108f022005420037034820054280a094a58d1d3703402005200541c0006a360210200541106a109d01200541a8016a4200370300200541a0016a4280a094a58d1d37030020054198016a200437030020054190016a2003370300200541c0006a41086a41023a0000200541c9006a2001290000370000200541d1006a200141086a290000370000200541d9006a200141106a290000370000200541e1006a200141186a290000370000200541e9006a2002290000370000200541f1006a200241086a290000370000200541f9006a200241106a29000037000020054181016a200241186a290000370000200541023a00404100210641014100200541c0006a10cc010c050b411441011037000b41c4d1c3004133200541c0006a419cd9c3001038000b411441011037000b41c4d1c3004133200541c0006a419cd9c3001038000b411441011037000b2000200136020420002006360200200541b0016a24000b881201097f230041f0026b22032400024002400240024002400240024002400240411410282204450d00200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b200320013703202003200237032820034180026a4120200341206a41101007200142ffffe883b1de165620024200522002501b0d06411410282204450d01200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b200341086a20034180026a109402200341086a41106a29030021022003290310210120032802082109410e10282204450d02200441002900fbe140370000200441066a4100290081e2403700002003428e808080e001370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b20034180026a4120100902402001200284500d002009450d0020032001370320200320023703282003200341206a3602800220034180026a109d010b2000109502411710282204450d03200441002900f1d8433700002004410f6a4100290080d943370000200441086a41002900f9d84337000020034297808080f002370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b200341206a20034180026a109602024020032d002022044102460d0020034180026a412010090b2003413c6a2802002106200341386a2802002105024020040d002005200341c0006a28020010042006450d060c050b20044103710d0520060d040c050b411441011037000b411441011037000b410e41011037000b411741011037000b2005102a0b200341f0016a2000108b0220032802f001210420032802f8012105410021062003410036022020042005200341206a10062108024002400240024020032802202207417f460d00200320073602e402200320083602e002200341206a200341e0026a10e80120032d00204101460d0120034180026a200341206a41017241e000109a051a02402007450d002008102a0b200341206a20034180026a41e000109a051a200420051009410121060b20034190016a200341206a41e000109a051a200341206a20034190016a41e000109a051a2006450d0120034180026a200341206a41e000109a051a024020032802f401450d002004102a0b200341206a20034180026a41e000109a051a200341c0006a210a200341e0006a210b4104210641e7e485f30621040340200b210702400240200441e9dabdf306460d000240200441e7e485f306470d00200341206a21070c010b200a2107200441e2c289ab06460d00410121084100210541012107410121090c010b41202105410021084120102822090d00412041011037000b200920072005109a0521072003200536029c01200320053602980120032007360294012003200436029001200341f0016a20034190016a108c0220032802f001220420032802f8011009024020032802f401450d002004102a0b024020080d002007102a0b2006410c460d03200641f8c8c0006a2800002104200641046a21060c000b0b41c4d1c3004133200341e8026a419cd9c3001038000b20032802f401450d002004102a0b411810282204450d01200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370294012003200436029001200020034190016a108f0120032802980121042003280290012105200341206a41186a22064200370300200341206a41106a22074200370300200341206a41086a220842003703002003420037032020052004200341206a100020034180026a41186a200629030037030020034180026a41106a200729030037030020034180026a41086a200829030037030020032003290320370380020240200328029401450d00200328029001102a0b2003410036022020034180026a4120200341206a10062104024020032802202205417f460d0020054110490d03200441086a2900002102200429000021012004102a200120028450450d010b2000109702200341206a41086a41013a0000200341296a2000290000370000200341316a200041086a290000370000200341396a200041106a290000370000200341c1006a200041186a290000370000200341023a002041014100200341206a10cc010b200341f0026a24000f0b411841011037000b41c4d1c3004133200341e8026a419cd9c3001038000bd40801067f230041c0016b220324000240024002400240411810282204450d00200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370244200320043602402000200341c0006a108f012003280248210420032802402105200341d0006a41186a22064200370300200341d0006a41106a22074200370300200341d0006a41086a220842003703002003420037035020052004200341d0006a1000200341206a41186a2006290300370300200341206a41106a2007290300370300200341206a41086a20082903003703002003200329035037032002402003280244450d002003280240102a0b2003200137035020032002370358200341206a4120200341d0006a411010070240200142ffffe883b1de165620024200522002501b0d00411810282204450d02200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370244200320043602402000200341c0006a108f012003280248210420032802402105200341d0006a41186a22064200370300200341d0006a41106a22074200370300200341d0006a41086a220842003703002003420037035020052004200341d0006a1000200341206a41186a2006290300370300200341206a41106a2007290300370300200341206a41086a20082903003703002003200329035037032002402003280244450d002003280240102a0b200341086a200341206a109402024020032903102202200341086a41106a290300220184500d002003280208450d0020032002370350200320013703582003200341d0006a360220200341206a109d010b411410282204450d03200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370244200320043602402000200341c0006a108f012003280248210420032802402105200341d0006a41186a22064200370300200341d0006a41106a22074200370300200341d0006a41086a220842003703002003420037035020052004200341d0006a1000200341206a41186a2006290300370300200341206a41106a2007290300370300200341206a41086a20082903003703002003200329035037032002402003280244450d002003280240102a0b20034100360250200341206a4120200341d0006a10062104024020032802502205417f460d0020054110490d05200441086a2900002102200429000021012004102a200120028450450d010b2000109702200341d0006a41086a41013a0000200341d9006a2000290000370000200341e1006a200041086a290000370000200341e9006a200041106a290000370000200341f1006a200041186a290000370000200341023a005041014100200341d0006a10cc010b200341c0016a24000f0b411841011037000b411841011037000b411441011037000b41c4d1c3004133200341d0006a419cd9c3001038000b4d01017f230041206b22002400200041146a410136020020004201370204200041ccd1c5003602002000410436021c200041c4d1c5003602182000200041186a360210200041e8b5c300103e000bb30701057f230041106b2203240020034100360208200342013703002002200310b40102400240024002400240024002402002450d00200241c4006c210403400240024020012d00004101460d0002400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d0a200241017422062005200620054b1b22064100480d0a0240024020020d002006102821050c010b200328020020022006102c21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a0000200141046a28020021060240024020032802042205200328020822026b4104490d00200328020021050c010b200241046a22072002490d0a200541017422022007200220074b1b22024100480d0a0240024020050d002002102821050c010b200328020020052002102c21050b2005450d062003200236020420032005360200200328020821020b2003200241046a360208200520026a20063600000c010b02400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d09200241017422062005200620054b1b22064100480d090240024020020d002006102821050c010b200328020020022006102c21050b2005450d062003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a00002003200336020c200141016a2003410c6a10c8010240200141216a2d00004101460d0002400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d0a200241017422062005200620054b1b22064100480d0a0240024020020d002006102821050c010b200328020020022006102c21050b2005450d082003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a00000c010b02400240200328020420032802082202460d00200328020021050c010b200241016a22052002490d09200241017422062005200620054b1b22064100480d090240024020020d002006102821050c010b200328020020022006102c21050b2005450d082003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a0000200141226a2003108f010b200141c4006a2101200441bc7f6a22040d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b200641011037000b200241011037000b200641011037000b200641011037000b200641011037000b1031000bcc0b03057f037e047f230041a0016b22012400200141306a41086a220242003703002001420037033041f5b8c3004113200141306a1008200141206a41086a2002290300370300200120012903303703204100210220014100360230200141206a4110200141306a100621030240024002400240024002400240024002400240024020012802302204417f460d002003450d0020044104490d01200328000021022003102a0b410110282203450d01200320002d00003a0000200341014102102c2203450d02200320002d00013a0001200341024104102c2203450d03200320002d00023a0002200320002d00033a0003200341044108102c2203450d04200320002d00043a0004200320002d00053a0005200320002d00063a0006200320002d00073a0007200341084110102c2203450d05200320002d00083a0008200320002d00093a0009200320002d000a3a000a200320002d000b3a000b200320002d000c3a000c200320002d000d3a000d200320002d000e3a000e200320002d000f3a000f200341104120102c2203450d06200320002d00103a0010200320002d00113a0011200320002d00123a0012200320002d00133a0013200320002d00143a0014200320002d00153a0015200320002d00163a0016200320002d00173a0017200320002d00183a0018200320002d00193a0019200320002d001a3a001a200320002d001b3a001b200320002d001c3a001c200320002d001d3a001d200320002d001e3a001e200320002d001f3a001f20032d0000210420032d000121052003102a200141206a2004200541087472410676220510fe0102402004413f71220320012802284f0d002001200128022020034105746a2203109d022001290300200141086a290300844200520d00200041086a2900002106200041106a2900002107200041186a290000210820032000290000370000200341186a2008370000200341106a2007370000200341086a2006370000200141306a41086a200141206a41086a280200360200200120012903203703302005200141306a10c5030c0a0b02402001280224450d002001280220102a0b200141306a200210fe010240200128023841c000490d000340200241016a210202402001280234450d002001280230102a0b200141306a200210fe012001280238413f4b0d000b0b200141106a41086a200141306a41086a2205280200220336020020012001290330370310200141306a41186a2209200041186a290000370300200141306a41106a220a200041106a2900003703002005200041086a29000037030020012000290000370330024020032001280214470d00200341016a22042003490d092003410174220b2004200b20044b1b220441ffffff3f712004470d092004410574220c4100480d090240024020030d00200c1028210b0c010b20012802102003410574200c102c210b0b200b450d08200120043602142001200b3602100b200320024106746a210b200128021020034105746a22042001290330370000200441086a2005290300370000200441106a200a290300370000200441186a20092903003700002001200341016a22033602180240200341c000470d00200141306a41086a220342003703002001420037033041f5b8c3004113200141306a1008200141206a41086a2003290300370300200120012903303703202001200241016a360230200141206a4110200141306a410410070b200141306a41086a2203200141106a41086a280200360200200120012903103703302002200141306a10c50320032000290000370300200141306a41106a200041086a290000370300200141306a41186a200041106a290000370300200141d0006a200041186a2900003703002001200b360234200141013a003041014100200141306a10cc010c090b41c4d1c3004133200141306a419cd9c3001038000b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b200c41011037000b1031000b200141a0016a24000b980102037f037e230041106b220224002002410036020420014120200241046a1006210302400240024020022802042204417f470d00420021050c010b20044110490d01200341086a2900002106200329000021072003102a200141201009420121050b2000200537030020002007370308200041106a2006370300200241106a24000f0b41c4d1c3004133200241086a419cd9c3001038000ba00803067f047e027f230041b0016b22012400024002400240410e10282202450d00200241002900fcae44370000200241066a4100290082af443700002001428e808080e00137026c200120023602682000200141e8006a108f01200128027021022001280268210320014188016a41186a2204420037030020014188016a41106a2205420037030020014188016a41086a2206420037030020014200370388012003200220014188016a1000200141286a41186a2004290300370300200141286a41106a2005290300370300200141286a41086a200629030037030020012001290388013703280240200128026c450d002001280268102a0b20014188016a200141286a412010fd01024020012d00880141014722020d00200141286a412010090b200141c8006a41186a2203200141a1016a2900002207370300200141c8006a41106a220420014199016a2900002208370300200141c8006a41086a220520014191016a29000022093703002001200129008901220a370348200141e8006a41186a22062007370300200141e8006a41106a220b2008370300200141e8006a41086a220c20093703002001200a370368024020020d00200141086a41186a20062903002207370300200141086a41106a200b2903002208370300200141086a41086a200c290300220937030020012001290368220a3703082003200737030020042008370300200520093703002001200a370348410e10282202450d022002410029008aaf44370000200241066a4100290090af443700002001428e808080e00137022c20012002360228200141c8006a200141286a108f01200128023021022001280228210320014188016a41186a2204420037030020014188016a41106a2205420037030020014188016a41086a2206420037030020014200370388012003200220014188016a1000200141e8006a41186a2004290300370300200141e8006a41106a2005290300370300200141e8006a41086a200629030037030020012001290388013703680240200128022c450d002001280228102a0b200141e8006a412010090b410d10282202450d0220024100290098af44370000200241056a410029009daf443700002001428d808080d00137024c200120023602482000200141c8006a108f01200128025021022001280248210320014188016a41186a2204420037030020014188016a41106a2205420037030020014188016a41086a2206420037030020014200370388012003200220014188016a1000200141e8006a41186a2004290300370300200141e8006a41106a2005290300370300200141e8006a41086a200629030037030020012001290388013703680240200128024c450d002001280248102a0b200141e8006a41201009200010a604200010a704200141b0016a24000f0b410e41011037000b410e41011037000b410d41011037000bd00a050a7f027e037f027e017f230041e0006b220224002002410036023820014120200241386a1006210302400240024002400240024002400240024020022802382204417f460d0020030d010b200041023a00000c010b2002200436021c200220033602182004450d0520032d0000210120022004417f6a36021c2002200341016a360218200141014b0d0502400240024020010e020001000b200241086a200241186a106c20022802080d07200228021c200228020c2205490d072005417f4c0d030240024020050d0041012106200228021c21070c010b2005102e2206450d092006200228021822012005109a051a200228021c22042005490d052002200420056b220736021c2002200120056a3602180b20074104490d0520022802182208280000210920022007417c6a220a36021c2002200841046a36021841002101200241003a0058417b210b03400240200a2001470d000240200141ff0171450d00200241003a00580b20050d080c090b200241386a20016a200820016a220441046a2d00003a000020022007200b6a36021c2002200441056a3602182002200141016a22043a0058200b417f6a210b2004210120044120470d000b200220022802383602302002200228003b3600330240024002400240200720046b220b417c6a4110490d00200241c7006a290000210c200229003f210d20022d0057210a2002280053210e200228004f210f2002200820046a220141146a22083602182002200b416c6a221036021c20104104490d002001410c6a2900002111200141046a2900002112200828000021082002200b41686a36021c2002200141186a2210360218200741686a2004460d0320102d000021102002200b41676a221336021c2002200141196a360218201041014b0d034100210420100e020201020b20050d090c0a0b20134104490d01200141196a28000021072002200b41636a36021c20022001411d6a360218410121040b2002200228003336002b20022002280230360228200220022802283602382002200228002b36003b200220022800203602102002200241236a280000360013410021012005210b0c020b2005450d070c060b41002101200241003a00582004417f6a21072004417e6a21040340024020072001470d00200141ff0171450d08200241003a00580c080b200241386a20016a200320016a220b41016a2d00003a00002002200b41026a3602182002200141016a220b3a00582002200436021c2004417f6a2104200b2101200b4120470d000b2002200228003b360033200220022802383602302002200228003336002b20022002280230360228200220022802283602102002200228002b360013200241c7006a2900002111200229003f2112200228004f21062002280053210b20022d005721052002200241236a28000036003b20022002280020360238410121010b2002200228021036023020022002280013360033200220022802383602282002200228003b36002b2003102a200041106a2011370300200041086a2012370300200041c3006a200c3700002000413b6a200d370000200020013a0000200041306a20073602002000412c6a2004360200200041286a2008360200200041246a2009360200200041206a20053602002000411c6a200b360200200041186a2006360200200041d3006a200a3a0000200041cf006a200e360000200041cb006a200f36000020002002280230360001200041046a2002280033360000200041346a2002280228360200200041376a200228002b3600000b200241e0006a24000f0b1036000b200520041044000b2005450d010b2006102a0b41c4d1c3004133200241206a419cd9c3001038000b200541011037000b870201057f230041d0006b220124000240411310282202450d00200241002900cef0423700002002410f6a41002800ddf042360000200241086a41002900d6f04237000020014293808080b002370224200120023602202000200141206a108f012001280228210220012802202100200141306a41186a22034200370300200141306a41106a22044200370300200141306a41086a220542003703002001420037033020002002200141306a1000200141186a2003290300370300200141106a2004290300370300200141086a20052903003703002001200129033037030002402001280224450d002001280220102a0b200141201009200141d0006a24000f0b411341011037000bd10402067f037e230041e0006b22052400024002400240411410282206450d00200641002900cfe140370000200641106a41002800dfe140360000200641086a41002900d7e14037000020054294808080c002370234200520063602302001200541306a108f012005280238210620052802302107200541c0006a41186a22084200370300200541c0006a41106a22094200370300200541c0006a41086a220a42003703002005420037034020072006200541c0006a1000200541106a41186a2008290300370300200541106a41106a2009290300370300200541106a41086a200a2903003703002005200529034037031002402005280234450d002005280230102a0b20054100360240200541106a4120200541c0006a100621060240024020052802402207417f470d004200210b4200210c0c010b20074110490d02200641086a290000210c2006290000210b2006102a0b410121060240200b20027d220d200b56200c20037d200b200254ad7d220b200c56200b200c511b4101470d00200041d7dfc000360204200041086a411d3602000c030b024002400240200d428080e983b1de16544100200b501b0d00200541086a20012004200d200b10bc0120052802082206450d02200528020c210120002006360204200041086a20013602000c010b200041f4dfc000360204200041086a411a3602000b410121060c030b2001200d200b108f02200041106a2003370300200041086a2002370300410021060c020b411441011037000b41c4d1c3004133200541c0006a419cd9c3001038000b20002006360200200541e0006a24000bdb0702067f087e23004180016b22022400024002400240411010282203450d0020034100290089e240370000200341086a4100290091e240370000200242908080808002370254200220033602502001200241d0006a108f012002280258210320022802502104200241e0006a41186a22054200370300200241e0006a41106a22064200370300200241e0006a41086a220742003703002002420037036020042003200241e0006a1000200241306a41186a2005290300370300200241306a41106a2006290300370300200241306a41086a20072903003703002002200229036037033002402002280254450d002002280250102a0b20024100360260200241306a4120200241e0006a1006210302400240024020022802602204417f460d002003450d00024020044110490d0020044170714110460d002004417c714120470d020b41c4d1c3004133200241e0006a419cd9c3001038000b42002108420021090c010b200341086a290000210a2003290000210b200341186a290000210c20032900102108200328002021042003102a411410282203450d02200341002900cfe140370000200341106a41002800dfe140360000200341086a41002900d7e14037000020024294808080c002370254200220033602502001200241d0006a108f012002280258210320022802502101200241e0006a41186a22054200370300200241e0006a41106a22064200370300200241e0006a41086a220742003703002002420037036020012003200241e0006a1000200241306a41186a2005290300370300200241306a41106a2006290300370300200241306a41086a20072903003703002002200229036037033002402002280254450d002002280250102a0b20024100360260200241306a4120200241e0006a100621030240024020022802602201417f470d004200210d420021090c010b20014110490d04200341086a29000021092003290000210d2003102a0b4200210e200241106a200c42004100109801220320046b2201200120034b1bad220f4200109f05200241206a200f420020084200109f0520024200420020084200109f054200210802402002290308200229031884420052200241286a290300220f200229030020022903107c7c220c200f54720d00200a200c200b2002290320220e56200a200c56200a200c511b22031b200c7d200b200e20031b220c200e54ad7d2108200c200e7d210e0b20082009200d200e56200920085620092008511b22031b2109200e200d20031b21080b200020083703002000200937030820024180016a24000f0b411041011037000b411441011037000b41c4d1c3004133200241e0006a419cd9c3001038000baf07030b7f037e037f230041f0006b22022400024002400240024002400240410e10282203450d00200341002900fbe140370000200341066a4100290081e2403700002002428e808080e001370234200220033602302001200241306a108f012002280238210320022802302101200241c0006a41186a22044200370300200241c0006a41106a22054200370300200241c0006a41086a220642003703002002420037034020012003200241c0006a1000200241106a41186a2004290300370300200241106a41106a2005290300370300200241106a41086a20062903003703002002200229034037031002402002280234450d002002280230102a0b20024100360240200241106a4120200241c0006a100621070240024020022802402208417f460d002002200836023420022007360230200241086a200241306a106c20022802080d07200228023422034160712201417f4c0d03200228020c2109024002402003410576220a0d004108210b0c010b20011028220b450d050b02402009450d004100210c41002106410021050340200241c0006a200241306a109b020240024020022d00404101460d00200228023422014110490d002002290041210d20022002280230220341106a3602302002200141706a220436023420044104490d00200341086a290000210e2003290000210f20022001416c6a22043602342002200341146a36023020040d010b200a450d0a200b102a0c0a0b200541016a210420032800102110200241e6006a41026a200241ed006a41026a2d000022113a0000200241e2006a41026a221220113a000020022001416b6a3602342002200341156a360230200220022f006d22013b0166200220013b016220032d0014210102402005200a470d00200c2004200c20044b1b220a41ffffff3f71200a470d09200a41057422034100480d090240024020050d0020031028210b0c010b200b20062003102c210b0b200b450d080b200b20066a2203411c6a20013a00002003200e3703082003200f370300200341146a200d370200200341106a20103602002003411d6a20022f01623b00002003411f6a20122d00003a0000200c41026a210c200641206a21062004210520092004470d000b0b200b450d072009ad422086200aad84210d02402008450d002007102a0b2000200d3702042000200b3602000c010b20004100360208200042083702000b200241f0006a24000f0b410e41011037000b1036000b200141081037000b200341081037000b1031000b41c4d1c3004133200241c0006a419cd9c3001038000bf00204027f017e017f077e0240024020012802042202450d0020012802002203310000210420012002417f6a22053602042001200341016a3602002005450d012003310001210620012002417e6a22053602042001200341026a3602002005450d012003310002210720012002417d6a22053602042001200341036a3602002005450d012003310003210820012002417c6a22053602042001200341046a3602002005450d012003310004210920012002417b6a22053602042001200341056a3602002005450d012003310005210a20012002417a6a22053602042001200341066a3602002005450d012003310006210b2001200241796a22053602042001200341076a3602002005450d01200041003a00002003310007210c2001200241786a3602042001200341086a3602002000200c423886200b42308684200a422886842009422086842008421886842007421086842006420886842004843700010f0b200041013a00000f0b200041013a00000bce1003077f027e027f230041d0006b220224000240024002400240024002400240024002400240024002400240410e10282203450d00200341002900fbe140370000200341066a4100290081e2403700002002428e808080e001370224200220033602202000200241206a108f012002280228210320022802202100200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020002003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b200128020021072001280208210320024100360238200242013703302003200241306a10b40102402003450d002003410574210841002106034002400240200228023420022802382203460d00200228023021000c010b200341016a22002003490d0f200341017422042000200420004b1b22044100480d0f0240024020030d002004102821000c010b200228023020032004102c21000b2000450d042002200436023420022000360230200228023821030b2002200341016a360238200020036a200720066a220341146a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d052002200536023420022004360230200228023821000b2002200041016a360238200420006a200341156a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d062002200536023420022004360230200228023821000b2002200041016a360238200420006a200341166a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d072002200536023420022004360230200228023821000b2002200041016a360238200420006a200341176a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d082002200536023420022004360230200228023821000b2002200041016a360238200420006a200341186a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d092002200536023420022004360230200228023821000b2002200041016a360238200420006a200341196a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d0a2002200536023420022004360230200228023821000b2002200041016a360238200420006a2003411a6a2d00003a000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d0b2002200536023420022004360230200228023821000b2002200041016a360238200420006a2003411b6a2d00003a0000200341086a29030021092003290300210a0240024020022802342205200228023822046b4110490d00200228023021000c010b200441106a22002004490d0f200541017422042000200420004b1b220b4100480d0f0240024020050d00200b102821000c010b20022802302005200b102c21000b2000450d0c2002200b3602342002200036023020022802382104200b21050b200020046a220b2009370008200b200a3700002002200441106a2204360238200341106a280200210b0240200520046b41034b0d00200441046a220c2004490d0f20054101742204200c2004200c4b1b22044100480d0f0240024020050d002004102821000c010b200020052004102c21000b2000450d0d2002200436023420022000360230200228023821040b2002200441046a360238200020046a200b36000002400240200228023420022802382200460d00200228023021040c010b200041016a22042000490d0f200041017422052004200520044b1b22054100480d0f0240024020000d002005102821040c010b200228023020002005102c21040b2004450d0e2002200536023420022004360230200228023821000b2002200041016a360238200420006a2003411c6a2d00003a00002008200641206a2206470d000b0b2002280234210320024120200228023022002002280238100702402003450d002000102a0b0240200141046a280200450d002007102a0b200241d0006a24000f0b410e41011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200b41011037000b200441011037000b200541011037000b1031000bd00502067f047e230041d0006b220224000240024002400240411410282203450d00200341002900cfe140370000200341106a41002800dfe140360000200341086a41002900d7e14037000020024294808080c002370224200220033602202001200241206a108f012002280228210320022802202104200241306a41186a22054200370300200241306a41106a22064200370300200241306a41086a220742003703002002420037033020042003200241306a1000200241186a2005290300370300200241106a2006290300370300200241086a20072903003703002002200229033037030002402002280224450d002002280220102a0b2002410036023020024120200241306a100621030240024020022802302204417f470d0042002108420021090c010b20044110490d02200341086a2900002109200329000021082003102a0b411810282203450d02200341002900e3e140370000200341106a41002900f3e140370000200341086a41002900ebe140370000200242988080808003370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002410036023020024120200241306a100621030240024020022802302201417f470d004200210a4200210b0c010b20014110490d04200341086a290000210b2003290000210a2003102a0b2000200a20087c22083703002000200b20097c2008200a54ad7c370308200241d0006a24000f0b411441011037000b41c4d1c3004133200241306a419cd9c3001038000b411841011037000b41c4d1c3004133200241306a419cd9c3001038000bf00906017f037e017f017e017f037e230041c0016b220724004200210842002109024020050d00200741f0006a2006ad42004280c8afa0254200109f05200741f8006a2903002007290370220a4280a094a58d1d7c2208200a54ad7c21090b20074180016a41086a22054200370300200742003703800141bfa0c600411b20074180016a1008200741a0016a41086a220b200529030037030020072007290380013703a001200741e0006a200741a0016a109f02200728026021052007290368210a2007418094ebdc03360284012007200a420020051b220a200a423f87220c7c200c85220c200c428094ebdc037f220c4280ec94a37c7e7ca7220536028001200741d0006a417f2004418094ebdc032004418094ebdc03491b2204417f417f2004ad200ca7417f200c428080808010541bad7e220ca7200c422088a71b220620074180016a2005418094ebdc034b4102746a28020022052004418094ebdc036e220d6c2005ad2004200d4180ec94a37c6c6aad7e428094ebdc0380a76a6a220520052006491b22056a220620062004491b4100200420056b2205200520044b1b200a4200551bad420042e8074200109f0520074180016a2003427f200820072903507c220a20017c220c200c200a5422042009200741d0006a41086a2903007c200a200854ad7c220820027c2004ad7c220a200854200a2008511b22041b220e427f200a20041b220f4101109802024002402007280280014101470d0020004180023b0001200041013a0000200041036a41003a00000c010b200741206a2007290388012209420042044200109f05200741106a4200420020094200109f05200741306a2007290320200741206a41086a290300220820074180016a41106a290300220a42028620072903107c7c220c4205420010a00520072903182101200741306a41086a29030021022007290330211020074180016a10d301200741c0006a20074180016a42b3e6cc99b3e6cc99332010200a200a42ffffffffffffffff3f8352200142005272200c2008547222041b22082009200820095442b3e6cc99b3e6cc9933200220041b220c200a54200c200a511b22041b2208200c200a20041b220c10d001200741a0016a41106a200c200741c0006a41086a29030022027d20082007290340220154ad7d2002200c7d2001200854ad7d20012008582002200c582002200c5122041b22051b3703002007200820017d200120087d20051b3703a801200720012008562002200c5620041b2204ad3703a001200a200c7d2009200854ad7d210a200920087d21080240024020040d002007200b3602bc01200741bc016a109d010c010b2007200b3602bc01200741bc016a109c010b20074180016a10f801200720074180016a2008200a10d001200741b0016a200a200741086a29030022097d20082007290300220c54ad7d2009200a7d200c200854ad7d200c2008582009200a582009200a5122041b22051b37030020072008200c7d200c20087d20051b3703a8012007200c2008562009200a5620041b2204ad3703a001200741a0016a41086a21050240024020040d00200720053602bc01200741bc016a109d010c010b200720053602bc01200741bc016a109c010b200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a200e427f200f501b370300200041003a00000b200741c0016a24000b820102027f027e230041106b220224002002410036020420014110200241046a100621010240024020022802042203417f460d002001450d00024020034108490d00200129000021042001102a420121050c020b41c4d1c3004133200241086a419cd9c3001038000b420021050b2000200437030820002005370300200241106a24000b1300200041033602042000419ce2c0003602000bc70104017f017e027f017e230041206b2201240042002102200141106a41086a220342003703002001420037031041ace1c0004116200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420021050c010b20044110490d01200341086a2900002105200329000021022003102a0b2000200237030020002005370308200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000b3400200041b2f3c00036020420004100360200200041146a4105360200200041106a41bcf3c000360200200041086a42083702000b3701017f02404110102822020d00411041011037000b2002420037000820024200370000200042908080808002370204200020023602000b130020004105360204200041d884c1003602000be70302067f037e230041e0006b2204240020042001109d0202400240024002402004290300200441086a29030084500d00411410282205450d02200541002900cfe140370000200541106a41002800dfe140360000200541086a41002900d7e14037000020044294808080c002370234200420053602302001200441306a108f012004280238210520042802302106200441c0006a41186a22074200370300200441c0006a41106a22084200370300200441c0006a41086a220942003703002004420037034020062005200441c0006a1000200441106a41186a2007290300370300200441106a41106a2008290300370300200441106a41086a20092903003703002004200429034037031002402004280234450d002004280230102a0b20044100360240200441106a4120200441c0006a100621050240024020042802402206417f470d004200210a4200210b0c010b20064110490d04200541086a290000210b2005290000210a2005102a0b2001200a20027c220c200b20037c200c200a54ad7c108f02200041106a2003370300200041086a2002370300410021010c010b200041b5dfc000360204200041086a4122360200410121010b20002001360200200441e0006a24000f0b411441011037000b41c4d1c3004133200441c0006a419cd9c3001038000b130020004101360204200041f88ac1003602000b3400200041b18cc10036020420004100360200200041146a4103360200200041106a41bc8cc100360200200041086a42083702000bef0a09037f017e067f037e017f027e077f017e017f230041306b2203240010980121042000280000210520003500042106200341106a2001109a02200328021021072003280214210802400240024002400240024002400240024020032802182209450d0020072009410574220a6a210b200341246a210c200721090340200941086a290300210d200941106a290300210e2009290300210f200341106a41186a200941186a290300370300200341106a41106a200e370300200341106a41086a200d3703002003200f370310200c2000460d02200c2900002000290000510d0202402003280220221020044d0d002003410e6a2003412f6a2d00003a0000200320032f002d3b010c200341186a290300210f427f210e200329031021114201210d20032d002c210c200329022421120c040b200941206a2109200a41606a220a0d000b0b41082113410021102008450d022007102a0c020b2003280220220c2002200c20024b1b211020032d002c410272210c427f21114200210e41002102200329022421124200210d41002105427f210f0b200341026a22142003410c6a41026a2d00003a0000200320032f010c3b010002400240412010282213450d00201320113703002013200c3a001c2013201237021420132010360210201320032f01003b001d2013200f3703082013411f6a20142d00003a000002400240200a4120470d0041012110200e210f410121140c010b200941206a2115200b41606a21162003412d6a2117200341246a210c200e210f4101211041012114034020152109024002400340200341106a41186a200941186a290300370300200341106a41106a200941106a290300370300200341106a41086a220a200941086a2903003703002003200929030037031002400240200c2000460d00200c2900002000290000510d002003280220221820044d0d012003410c6a41026a201741026a2d00003a0000200320172f00003b010c200a29030021112003290310211220032d002c21192003290224211a0c040b200d4201510d024200210e410021024200210f4200210d410021050b200b200941206a2209470d000c040b0b200a290300220d200f20032903102212200e56200d200f56200d200f511b220a1b21112012200e200a1b21122003280220220a2002200a20024b1b211820032d002c41027221194200210e410021022003290224211a4200210f4200210d410021050b200341046a41026a2003410c6a41026a2d0000220a3a0000200320032f010c22153b0104200341106a41026a221b200a3a0000200320153b0110024020142010470d00201041016a220a2010490d0a20104101742214200a2014200a4b1b221441ffffff3f712014470d0a2014410574220a4100480d0a0240024020100d00200a102821130c010b20132010410574200a102c21130b2013450d040b200941206a2115201320104105746a220a20193a001c200a2011370308200a2012370300200a201a370214200a2018360210200a20032f01103b001d200a411f6a201b2d00003a0000201041016a211020162009470d000b0b02402008450d002007102a0b200d4201520d0520102014470d040c030b412041081037000b200a41081037000b427f210e427f210f0b201041016a22092010490d03201041017422002009200020094b1b221441ffffff3f712014470d03201441057422094100480d030240024020100d002009102821130c010b201320104105742009102c21130b2013450d020b201320104105746a2209200f3703082009200e3703002009200536021420092002360210200941186a200642808080802084370300201041016a21100b2003201036021820032014360214200320133602102001200341106a109c02200341306a24000f0b200941081037000b1031000bef0a07037f027e047f087e017f047e027f230022062107200641c0006b41607122062400109801210820062003370310200620023703082006200436021842012109200642013703002006200028000036021c20003500042102200641206a2001109a0220022005ad42ff018342208684210a2006280220210b2006280224210c0240024002400240024020062802282205450d00200b200541057422046a210d200641346a210e2006290300220921032006290308220f2110200629031022112112200629031822132114200b21050340200541086a2903002102200541106a290300211520052903002116200641206a41186a200541186a290300370300200641206a41106a22172015370300200641206a41086a20023703002006201637032002400240200e2000460d00200e2900002000290000510d000240200628023020084b0d0020032102420021030c020b20172903002118200629032821192006290320211a2006290338211b20032102420121030c010b420021094200210f420021114200211342002102200a211b2010211a20122119201421180b20034201510d02200541206a210520022103200441606a22040d000b200620093703002006200f37030820062011370310200620133703180b41002104200c450d01200b102a0c010b200620023703002006201037030820062012370310200620143703180240412010282217450d002017201b3703182017201a37030020172019370308201741106a201837030002400240024020044120470d0041012104200221094101211c0c010b200541206a2105200641346a211d20022109410121044101211c034002400240201d2000460d00200221030340200641206a41186a200541186a290300370300200641206a41106a220e200541106a290300370300200641206a41086a200541086a2903003703002006200529030037032002400240201d2900002000290000510d000240200628023020084b0d0020032102420021030c020b200e290300211b20062903282116200629032021152006290338211a20032102420121030c010b42002109200642003703004200210220102115201221162014211b200a211a0b024020034201510d0020022103200d200541206a2205470d010c050b0b200541206a21050c010b024003402006420037030020024201510d0142002102200d200541206a2205470d000b420021090c030b200541206a2105420021094200210220102115201221162014211b200a211a0b0240201c2004470d00200441016a220e2004490d072004410174221c200e201c200e4b1b221c41ffffff3f71201c470d07201c410574220e4100480d070240024020040d00200e102821170c010b20172004410574200e102c21170b2017450d030b201720044105746a220e2016370308200e2015370300200e41106a201b370300200e41186a201a370300200441016a21042005200d470d000b0b200c450d03200b102a0c030b200e41081037000b412041081037000b4100211c410821170b0240024020094201520d00200641206a41106a22002006410872220541106a290300370300200641206a41086a220e200541086a2903003703002006200529030037032002402004201c470d00200441016a22052004490d03200441017422082005200820054b1b221c41ffffff3f71201c470d03201c41057422054100480d030240024020040d002005102821170c010b201720044105742005102c21170b2017450d020b201720044105746a22052006290320370300200541106a2000290300370300200541086a200e290300370300200541186a200a370300200441016a21040b200620043602282006201c360224200620173602202001200641206a109c02200724000f0b200541081037000b1031000bff0502067f057e230041d0006b220324000240024002400240411810282204450d00200441002900e3e140370000200441106a41002900f3e140370000200441086a41002900ebe140370000200342988080808003370224200320043602202000200341206a108f012003280228210420032802202105200341306a41186a22064200370300200341306a41106a22074200370300200341306a41086a220842003703002003420037033020052004200341306a1000200341186a2006290300370300200341106a2007290300370300200341086a20082903003703002003200329033037030002402003280224450d002003280220102a0b2003410036023020034120200341306a100621040240024020032802302205417f470d00420021094200210a0c010b20054110490d02200441086a290000210a200429000021092004102a0b411410282204450d02200441002900cfe140370000200441106a41002800dfe140360000200441086a41002900d7e14037000020034294808080c002370224200320043602202000200341206a108f012003280228210420032802202105200341306a41186a22064200370300200341306a41106a22074200370300200341306a41086a220842003703002003420037033020052004200341306a1000200341186a2006290300370300200341106a2007290300370300200341086a20082903003703002003200329033037030002402003280224450d002003280220102a0b2003410036023020034120200341306a100621040240024020032802302205417f470d004200210b4200210c0c010b20054110490d04200441086a290000210c2004290000210b2004102a0b2000200b200120092009200156200a200256200a2002511b22041b22017c220d200c2002200a20041b22027c200d200b54ad7c108f022000200920017d200a20027d2009200154ad7d109002200341d0006a24000f0b411841011037000b41c4d1c3004133200341306a419cd9c3001038000b411441011037000b41c4d1c3004133200341306a419cd9c3001038000bc70301047f230041106b2203240020034100360208200342013703002001200310b40102400240024002402001450d00200141216c210403400240024020002d00004101460d0002400240200328020420032802082201460d00200328020021050c010b200141016a22052001490d07200141017422062005200620054b1b22064100480d070240024020010d002006102821050c010b200328020020012006102c21050b2005450d052003200636020420032005360200200328020821010b2003200141016a360208200520016a41003a00000c010b02400240200328020420032802082201460d00200328020021050c010b200141016a22052001490d06200141017422062005200620054b1b22064100480d060240024020010d002006102821050c010b200328020020012006102c21050b2005450d052003200636020420032005360200200328020821010b2003200141016a360208200520016a41013a0000200041016a2003108f010b200041216a21002004415f6a22040d000b0b2003280204210020022802002002280204200328020022012003280208100702402000450d002001102a0b200341106a24000f0b200641011037000b200641011037000b1031000bdb0401057f230041106b2203240020034100360208200342013703002002200310b401024002400240024002402002450d0020024190016c2104034020032802042105200328020821020240024020012802004113470d000240024020052002460d00200328020021050c010b200241016a22052002490d08200241017422062005200620054b1b22064100480d080240024020020d002006102821050c010b200328020020022006102c21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41003a00000c010b0240024020052002460d00200328020021050c010b200241016a22052002490d07200241017422062005200620054b1b22064100480d070240024020020d002006102821050c010b200328020020022006102c21050b2005450d052003200636020420032005360200200328020821020b2003200241016a360208200520026a41013a00002001200310eb0120014188016a28020021060240024020032802042205200328020822026b4104490d00200328020021050c010b200241046a22072002490d07200541017422022007200220074b1b22024100480d070240024020050d002002102821050c010b200328020020052002102c21050b2005450d062003200236020420032005360200200328020821020b2003200241046a360208200520026a20063600000b20014190016a2101200441f07e6a22040d000b0b20002003290300370200200041086a200341086a280200360200200341106a24000f0b200641011037000b200641011037000b200241011037000b1031000b6801037f024041094101200128020022024101461b220310282204450d000240024020020d00200441003a0000410121010c010b200441013a000020042001290204370001410921010b2000200136020820002003360204200020043602000f0b200341011037000bcc0902057f027e230041c0006b22022400024002400240024002402001280200417f6a220341024b0d0020030e03010203010b41a091c1001032000b410121030240024020012d00044101460d00200241026a200141046a220341036a2d00003a0000200241206a41086a200141146a290200370300200241306a2001411c6a290200370300200241386a200141246a2d00003a0000200220032f00013b010020022001410c6a290200370320200141086a2802002104410021030c010b200141086a28020021040b200020033a0004200020022f01003b000520004101360200200041286a2001290328370300200041086a20043602002000410c6a2002290320370200200041306a200141306a290300370300200041076a200241026a2d00003a0000200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a2802003602000c020b410121030240024020012d00044101460d00200241026a200141046a220341036a2d00003a0000200241206a41086a200141146a290200370300200241306a2001411c6a290200370300200241386a200141246a2d00003a0000200220032f00013b010020022001410c6a290200370320200141086a2802002104410021030c010b200141086a28020021040b200020033a0004200020022f01003b0005200041286a2001290328370300200041386a2001290338370300200041086a20043602002000410c6a2002290320370200200041306a200141306a290300370300200041c0006a200141c0006a290300370300200041076a200241026a2d00003a0000200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a280200360200200041023602000c010b200141286a2103410121040240024020012d00044101460d002002411e6a200141046a220441036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220042f00013b011c20022001410c6a290200370300200141086a2802002105410021040c010b200141086a28020021050b410121060240024020032d00004101460d002002413e6a200341036a2d00003a0000200241286a200141386a290200370300200241306a200141c0006a290200370300200241386a200141c8006a2d00003a0000200220032f00013b013c2002200141306a2902003703202001412c6a2802002103410021060c010b2001412c6a28020021030b200020043a0004200020022f011c3b0005200020022f013c3b0029200041086a20053602002000410c6a2002290300370200200041286a20063a0000200041076a2002411c6a41026a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602002000412b6a2002413c6a41026a2d00003a0000200141d8006a2903002107200129035021082000412c6a2003360200200041d0006a2008370300200041d8006a200737030020004103360200200041306a2002290320370200200041386a200241206a41086a290300370200200041c0006a200241206a41106a290300370200200041c8006a200241206a41186a2802003602000b200241c0006a24000b960403077f017e067f02400240024002402001410c6a2802002202417f4c0d0020012802042103200128020021040240024020020d0041012105410021060c010b20022106200210282205450d020b200520032002109a052107200141186a2802002208ad420c7e2209422088a70d002009a72203417f4c0d002001280210210a0240024020030d004104210b0c010b20031028220b450d030b0240024020080d004100210c0c010b200a2008410c6c6a210d4100210c200b21050340200a41086a2802002203417f4c0d02200a280200210e0240024020030d004101210f0c010b20031028220f450d060b200f200e2003109a05210e200541086a2003360200200541046a20033602002005200e3602002005410c6a2105200c41016a210c200a410c6a220a200d470d000b0b20002007360204200020043602002000200129021c37021c200041186a200c360200200041146a2008360200200041106a200b3602002000410c6a2002360200200041086a2006360200200020012902243702242000412c6a2001412c6a290200370200200041346a200141346a2902003702002000413c6a2001413c6a290200370200200041c4006a200141c4006a290200370200200041cc006a200141cc006a290200370200200041d4006a200141d4006a290200370200200041dc006a200141dc006a2902003702000f0b1036000b200241011037000b200341041037000b200341011037000bd90303027f017e027f02402001450d00034020002802e40121002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d0020002001410c6c6a220441e4006a2902002105200441e0006a2802002104200141016a21010c010b02400240200028020022010d002003ad210541002106410021010c010b20003301044220862003ad842105410121060b2000102a2005a72103024002402005422088a7220720012f01064f0d00200121040c010b034002400240200128020022040d002003ad2105410021040c010b200641016a210620013301044220862003ad8421050b2001102a2005a72103200421012005422088a7220720042f01064f0d000b0b200741027420046a41e8016a280200210020042007410c6c6a220141e4006a2902002105200141e0006a280200210402402006417f6a2201450d00034020002802e40121002001417f6a22010d000b0b410021010b2004450d012002417f6a210202402005a7450d002004102a0b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021042001102a2004450d00024020042802002201450d0003402004102a2001210420012802002200210120000d000b0b2004102a0b0bd308030d7f017e017f230041a0016b2202240002400240024020012802202203450d0020012003417f6a36022020012802082104200128020c2205200128020422062f01064f0d01200241186a2207200620054105746a220341206a290000370300200241106a2208200341186a290000370300200241086a2209200341106a2900003703002002200341086a290000370300200241206a41286a220a2006200541306c6a22034190036a290300370300200241206a41206a220b20034188036a290300370300200241206a41186a220c20034180036a290300370300200241206a41106a220d200341f8026a290300370300200241206a41086a220e200341f0026a290300370300200341e8026a290300210f2001200541016a36020c20012004360208200120063602042002200f370320200241d0006a41186a2007290300370300200241d0006a41106a2008290300370300200241d0006a41086a200929030037030020022002290300370350200241d0006a41286a200e290300370300200241d0006a41306a200d29030037030020024188016a200c29030037030020024190016a200b29030037030020024198016a200a290300370300200220022903203703702000200241d0006a41d000109a051a0c020b200041003602400c010b2001280200210702400240200628020022030d002004ad210f410021030c010b200741016a210720063301044220862004ad84210f0b2006102a200fa7210502400240200f422088a7220420032f01064f0d00200321060c010b034002400240200328020022060d002005ad210f410021060c010b200741016a210720033301044220862005ad84210f0b2003102a200fa7210520062103200f422088a7220420062f01064f0d000b0b200241186a2208200620044105746a220341206a290000370300200241106a2209200341186a290000370300200241086a220a200341106a2900003703002002200341086a290000370300200241206a41286a220b2006200441306c6a22034190036a290300370300200241206a41206a220c20034188036a290300370300200241206a41186a220d20034180036a290300370300200241206a41106a220e200341f8026a290300370300200241206a41086a2210200341f0026a2903003703002002200341e8026a290300370320200441027420066a41fc066a280200210302402007417f6a2206450d00034020032802f80621032006417f6a22060d000b0b2001410036020c200120053602082001200336020420014100360200200241d0006a41186a2008290300370300200241d0006a41106a2009290300370300200241d0006a41086a200a290300370300200241d0006a41286a2010290300370300200241d0006a41306a200e29030037030020024188016a200d29030037030020024190016a200c29030037030020024198016a200b29030037030020022002290300370350200220022903203703702000200241d0006a41d000109a051a0b200241a0016a24000bbd0301057f230041106b2203240002400240024002400240200141046a2204417f4c0d000240024020040d00410121050c010b200410282205450d020b2003410036020820032004360204200320053602002001200310b4010240024020032802042206200328020822056b2001490d00200328020021040c010b200520016a22042005490d05200641017422072004200720044b1b22074100480d050240024020060d002007102821040c010b200328020020062007102c21040b2004450d032003200736020420032004360200200721060b200420056a20002001109a051a02400240200241046a2802002207200241086a28020022006b200520016a2201490d00200228020021050c010b200020016a22052000490d05200741017422002005200020054b1b22004100480d050240024020070d002000102821050c010b200228020020072000102c21050b2005450d0420022005360200200241046a2000360200200241086a28020021000b200241086a200020016a360200200520006a20042001109a051a02402006450d002004102a0b200341106a24000f0b1036000b200441011037000b200741011037000b200041011037000b1031000b880201057f230041d0006b220224000240411710282203450d00200341002900f1d8433700002003410f6a4100290080d943370000200341086a41002900f9d84337000020024297808080f002370224200220033602202000200241206a108f012002280228210320022802202100200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020002003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b2002200110e203200241d0006a24000f0b411741011037000b1000200028020020002802042001105f0baf0201037f23004180016b2202240002400240024002400240200128020022034110710d002000280200210420034120710d012004ad41012001103f21000c020b20002802002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a2100200441047622040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000b130020004101360204200041cc9ac1003602000b130020004102360204200041849cc1003602000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241e8073600000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241e5003600000bd20903067f017e057f230041f0016b22022400024002400240024002400240024020012802042203450d00200128020022042d0000210520012003417f6a22063602042001200441016a3602002005417f6a220541014b0d0520050e020102010b200041023a00000c050b20064104490d012004280001210720012003417b6a22053602042001200441056a36020020054108490d02200429000521082001200341736a36020420012004410d6a36020041002105200241003a00b001410d20036b2109200341726a210603400240200920056a0d000240200541ff0171450d00200241003a00b0010b200041023a00000c060b20024190016a20056a200420056a220a410d6a2d00003a0000200120063602042001200a410e6a3602002002200541016a220a3a00b0012006417f6a2106200a2105200a4120470d000b200241f0006a41186a20024190016a41186a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41086a20024190016a41086a290300370300200220022903900137037041002105200241003a00d0012004200a6a2109200a20036b410d6a210a03400240200a20056a0d000240200541ff0171450d00200241003a00d0010b200041023a00000c060b20024190016a20056a200920056a2204410d6a2d00003a00002001200636020420012004410e6a3602002002200541016a22043a00d0012006417f6a210620042105200441c000470d000b200241106a41386a220120024190016a41386a290300370300200241106a41306a220520024190016a41306a290300370300200241106a41286a220620024190016a41286a290300370300200241106a41206a220420024190016a41206a290300370300200241106a41186a220a20024190016a41186a290300370300200241106a41106a220320024190016a41106a290300370300200241106a41086a220920024190016a41086a290300370300200241d0006a41086a220b200241f0006a41086a290300370300200241d0006a41106a220c200241f0006a41106a290300370300200241d0006a41186a220d200241f0006a41186a290300370300200220022903900137031020022002290370370350200041003a000020002002290350370001200041096a200b290300370000200041116a200c290300370000200041196a200d290300370000200041216a2002290310370000200041296a2009290300370000200041316a2003290300370000200041396a200a290300370000200041c1006a2004290300370000200041c9006a2006290300370000200041d1006a2005290300370000200041d9006a2001290300370000200041e3006a2002410f6a2d00003a0000200041e1006a20022f000d3b0000200041e8006a2008370300200041e4006a20073602000c040b0240024020064104490d002004280001210620012003417b6a22053602042001200441056a360200200541084f0d010b200041023a00000c040b200041013a0000200020022f00103b0001200429000521082001200341736a36020420012004410d6a360200200041086a2008370300200041046a2006360200200041036a200241126a2d00003a0000200041106a20024190016a41e000109a051a0c030b200041023a00000c020b200041023a00000c010b200041023a00000b200241f0016a24000be71207027f017e057f027e017f017e0a7f230041b0036b2202240020002802102203200328020041016a36020020002902142104200028020c2103200028020821052000280200210620002802042100200241f0016a41086a2207200141086a280200360200200220012902003703f001024002400240024020002f01062201410b490d00200241d0026a410272410041da001099051a200241386a41004184011099051a0240024041e40110282208450d0020084100360200200841046a200241d0026a41dc00109a051a200841e0006a200241386a418401109a052107200241386a41086a2209200041b0016a280200360200200220002902a8013703382000413c6a330000210a2000413e6a310000210b20002d003f210c2000350038210d200841086a200041c0006a20002f010641796a2201410374109a05210e2007200041b4016a2001410c6c109a052107200041063b0106200820013b0106200241d0026a41086a2009280200360200200220022903383703d002200d200a200b4210868442208684210a0240024020034107490d002003410374200e6a41506a200e200341796a22094103746a220e200141ffff037120096b410374109b051a200e20043700002003410c6c20076a220341b87f6a200341ac7f6a2203200841066a22012f010020096b410c6c109b051a200341086a200241f0016a41086a280200360200200320022903f0013702000c010b200041086a20034103746a220741086a2007200041066a22012f010020036b410374109b051a20072004370000200041e0006a2003410c6c6a2207410c6a200720012f010020036b410c6c109b051a200741086a200241f0016a41086a280200360200200720022903f0013702000b200120012f010041016a3b0100200241286a41086a220f200241d0026a41086a22102802002203360200200241086a221120033602002002200c3a0017200220022903d00222043703282002200a3e02102002200a4230883c00162002200a4220883d011420022004370300200229031021042000280200220c450d0320002f01042112200241d0026a410272211303402002200641016a22063602202002200c360224200f201128020036020020022002290300370328201241ffff03712109024002400240200c2f01062200410b490d002013410041da001099051a200241f0016a200241d0026a41dc00109a051a200241386a410041b4011099051a41940210282207450d0520074100360200200741046a200241f0016a41dc00109a051a200741e0006a200241386a41b401109a052103200c41386a290000210a200241386a41086a2214200c41b0016a2802003602002002200c41a8016a290200370338200741086a200c41c0006a200c2f0106220141796a2200410374109a0521152003200c41b4016a2000410c6c109a052116200741e4016a200c4180026a2001417a6a220e410274109a052117200c41063b0106200720003b01060240200e450d00410021002017210303402003280200220120003b010420012007360200200341046a2103200e200041016a2200470d000b0b20102014280200220036020020022002290338220b3703d002201420003602002002200b370338201241ffff037122034107490d0120152009417a6a22034103746a2015200941796a22004103746a220120072f010620006b410374109b051a200120043700002009410c6c20166a220141b87f6a200141ac7f6a220120072f0106220e20006b410c6c109b051a200141086a200f280200360200200120022903283702002007200e41016a22013b01062009410274221220176a416c6a201720034102746a220e200141ffff0371220920036b410274109b051a200e200836020020092003490d02200720126a41cc016a2103034020032802002201200041016a22003b010420012007360200200341046a210320002009490d000c030b0b200c41086a2201200941016a22034103746a200120094103746a2201200020096b2207410374109b051a20012004370000200c2009410c6c6a220141ec006a200141e0006a220e2007410c6c109b051a200141e8006a200241286a41086a280200360200200e2002290328370200200c200041016a22003b01062009410274200c41e4016a22016a41086a200120034102746a2201200041ffff0371220720036b410274109b051a20012008360200201241ffff037120074f0d07200c2003417f6a22004102746a41e8016a2103034020032802002201200041016a22003b01042001200c360200200341046a210320002007490d000c080b0b200c41086a2200200941016a220e4103746a200020094103746a2200200c2f0106220120096b2212410374109b051a20002004370000200c41e0006a2009410c6c6a2200410c6a20002012410c6c109b051a200041086a200f28020036020020002002290328370200200c200141016a22003b010620094102742217200c41e4016a22016a41086a2001200e4102746a2212200041ffff03712201200e6b410274109b051a20122008360200200320014f0d00200c20176a41e8016a2100034020002802002203200941016a22093b01042003200c360200200041046a210020012009470d000b0b200241106a41086a2014280200220036020020112000360200200220022903382204370310200220043703000240200c28020022000d0020072108200a21040c050b200c2f010421122000210c200a2104200721080c000b0b41e40141041037000b41940241041037000b200020034103746a220941106a200941086a2209200120036b410374109b051a2009200437000020002003410c6c6a220141ec006a200141e0006a220920002f010620036b410c6c109b051a200141e8006a2007280200360200200920022903f001370200200020002f010641016a3b01060c010b200241d0026a410272410041da001099051a200241f0016a200241d0026a41dc00109a051a200241386a410041b4011099051a41940210282200450d0120004100360200200041046a200241f0016a41dc00109a051a200041e0006a200241386a41b401109a0521012000200528020022033602e401200520003602002005200528020441016a360204200341003b010420032000360200200120002f01062203410c6c6a22012002290300370200200020034103746a41086a2004370000200141086a200241086a280200360200200041e4016a200341016a22034102746a2008360200200020033b0106200820033b0104200820003602000b200241b0036a24000f0b41940241041037000b8b0303017f017e027f02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d00410021034100210103402002417f6a210202400240200120002f01064f0d00200141016a21010c010b02400240200028020022010d002003ad210441002105410021010c010b20003301044220862003ad842104410121050b2000102a2004a72103024002402004422088a7220620012f01064f0d00200121000c010b034002400240200128020022000d002003ad2104410021000c010b200541016a210520013301044220862003ad8421040b2001102a2004a72103200021012004422088a7220620002f01064f0d000b0b200641027420006a4198036a280200210002402005417f6a2201450d00034020002802940321002001417f6a22010d000b0b410021010b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021002001102a2000450d00024020002802002201450d0003402000102a2001210020012802002203210120030d000b0b2000102a0b0be480010d067f017e017f027e0b7f017e027f017e017f017e067f017e127f230041e0026b22012400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020004180c20370450d00200141e8006a21020c010b20014190026a41086a22034200370300200142003703900241f490c600411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a001200141e8006a4110200141a0016a100621030240024020012802a0012204417f460d0020030d010b200141e8006a21020c010b024002400240024002400240024020044104490d00200328000021042003102a200141e8006a21022004450d0720014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a001200141e8006a4110200141a0016a100621030240024020012802a0012205417f460d002003450d0020012005360294022001200336029002200141a0016a20014190026a107d20012802a0012206450d0320012902a40121072005450d012003102a0c010b41042106420021070b20014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141a0016a200141e8006a10be020240024020012802a8012208450d002007422088a720012902ac012209422088a76b20012903a001220a422088a7220b6a2105200aa721032009a7450d012008102a0c010b2007422088a721054100210b10980121030b200520044f0d020c030b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b0240200b20044f0d00200b20046b22032007422088a722056a220420034f0d032006200441246c6a28022021030c010b20014190026a41086a22044200370300200142003703900241dca2c100411420014190026a1008200141e8006a41086a2004290300370300200120012903900237036841002105200141003602a001200141e8006a4110200141a0016a10062104024020012802a001220b417f460d002004450d00200b4104490d02200428000021052004102a0b200520036a21030b200341ffc1036a220320034180c203706b210302402007a7450d002006102a0b20032000470d0320014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a001200141e8006a4110200141a0016a1006210302400240024020012802a0012204417f460d002003450d0020012004360294022001200336029002200141a0016a20014190026a107d20012802a001220c450d0220012902a401210a2004450d012003102a0c010b4104210c4200210a0b20014190026a41086a22034200370300200142003703900241f490c600411420014190026a1008200141e8006a41086a200329030037030020012001290390023703684100210d200141003602a001200141e8006a4110200141a0016a100621030240024020012802a0012204417f460d002003450d0020044104490d012003280000210d2003102a0b109801210e02400240200a422088a7220f41246c2204450d00200c41206a280200200e4d0d010b4101210b41002105410021060c050b200141a0016a41186a2203200c41186a290200370300200141a0016a41106a2205200c41106a290200370300200141a0016a41086a2206200c41086a2902003703002001200c2902003703a001024041201028220b450d00200b20012903a001370000200b41186a2003290300370000200b41106a2005290300370000200b41086a20062903003700000240200c41246a2203200c20046a470d0041012105410121060c060b200c200f41246c6a211041202108410121044101210503400240200341206a280200200e4d0d00200421060c070b200141b8026a41186a2211200341186a290200370300200141b8026a41106a2212200341106a290200370300200141b8026a41086a2213200341086a290200370300200120032902003703b8020240024020052004460d00200421060c010b200441016a22062004490d1e200441017422142006201420064b1b220641ffffff3f712006470d1e200641057422144100480d1e0240024020040d0020141028210b0c010b200b20044105742014102c210b0b200b0d00201441011037000b200b20086a220420012903b802370000200441186a2011290300370000200441106a2012290300370000200441086a2013290300370000200841206a2108200541016a2105200621042010200341246a2203460d060c000b0b412041011037000b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b41cca2c100200420051034000b024002400240024002400240024002400240200d200f20056b22044d0d0020014190026a41086a22034200370300200142003703900241f0a2c100411c20014190026a1008200141e8006a41086a2003290300370300200120012903900237036841002108200141003602a001200141e8006a4110200141a0016a10062103024020012802a0012211417f460d002003450d0020114104490d02200328000021082003102a0b20014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368410810282203450d0220014288808080c0003702a401200120033602a00120032008200e6a3600000240024020012802a401220820012802a80122036b4104490d0020012802a00121080c010b200341046a22112003490d20200841017422032011200320114b1b22034100480d200240024020080d002003102821080c010b20012802a00120082003102c21080b2008450d04200120033602a401200120083602a00120012802a80121030b2001200341046a3602a801200820036a200d20046b22133600002005200141a0016a10b40102402005450d0020054105742104200b210303402003200141a0016a108f01200341206a2103200441606a22040d000b0b20012802a4012103200141e8006a411020012802a001220420012802a801100702402003450d002004102a0b02402006450d00200b102a0b200141a8026a4200370300200141a0026a420037030020014198026a42003703002001420037039002201341066a220ead42307e2207422088a70d172007a72203417f4c0d170240024020030d0041082110410821040c010b200310282210450d05201021040b200141a0016a41186a221120014190026a41186a290300370300200141a0016a41106a221220014190026a41106a290300370300200141a0016a41086a20014190026a41086a29030037030020012001290390023703a001200e4102490d05200d20056a200f6b41056a2105200421030340200141b8026a41186a22062011290300370300200141b8026a41106a220b2012290300370300200141b8026a41086a2208200141a0016a41086a290300370300200120012903a0013703b8022003420037030820034200370300200341106a20012903b802370300200341186a2008290300370300200341206a200b290300370300200341286a2006290300370300200341306a21032005417f6a22050d000b201341056a21050c060b2006450d07200b102a0c070b41c4d1c3004133200141d8026a419cd9c3001038000b410841011037000b200341011037000b200341081037000b4100210520042103200e450d010b2003420037030820034200370300200320012903a001370310200341186a200141a8016a290300370300200341206a200141b0016a290300370300200341286a200141a0016a41186a290300370300200541016a21050b20014190026a41086a220342003703002001420037039002418ca3c100411320014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a801200142013703a0012005200141a0016a10b40102402005450d002004200541306c6a210b0340200441086a2903002107200429030021090240024020012802a401220520012802a80122036b4110490d0020012802a00121050c010b200341106a22062003490d1a200541017422032006200320064b1b22034100480d1a0240024020050d002003102821050c010b20012802a00120052003102c21050b2005450d05200120033602a401200120053602a00120012802a80121030b200520036a22052007370008200520093700002001200341106a3602a801200441106a200141a0016a108f01200441306a2204200b470d000b0b20012802a4012103200141e8006a411020012802a001220420012802a801100702402003450d002004102a0b0240200e450d002010102a0b200141083a00a001200141a0016a41086a2013360200200141023a00a40141014100200141a0016a10cc010b200aa7450d00200c102a0b20014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141a0016a200210be0220012802a8012215450d1820012902ac01211620012802a0012000470d1720014190026a41086a22034200370300200142003703900241b8a2c100411420014190026a1008200141e8006a41086a220020032903003703002001200129039002370368200141a0016a200210be02024020012802a80122170d0002402016a7450d002015102a0b41d5a3c100410f100b41e4a3c1004135100b0c190b20024110100920012802a401211820012902ac012119200342003703002001420037039002418ca3c100411320014190026a1008200020032903003703002001200129039002370368200141003602a00120024110200141a0016a100621030240024020012802a0012200417f460d002003450d0020012000360294022001200336029002200141a0016a20014190026a107820012802a001221a450d0320012902a401211b02402000450d002003102a0b2002411010090c010b4200211b4108211a0b109801211c20014190026a41086a22034200370300200142003703900241dca2c100411420014190026a1008200141e8006a41086a200329030037030020012001290390023703684100211d200141003602a00120024110200141a0016a10062103024020012802a0012200417f460d002003450d0020004104490d032003280000211d2003102a0b201a201b422088a7221e41306c6a210e0240024020180d004100211341002106410021000c010b2018417f6a2106410021000240201e450d000240201a201e41306c6a220341506a220e290300200e41086a2903008450450d00410121130c020b20014190026a41186a200341606a220341186a29000037030020014190026a41106a200341106a29000037030020014190026a41086a200341086a2900003703002001200329000037039002410121000b410021130b200141a9016a20014190026a41086a290300370000200141b1016a20014190026a41106a290300370000200141b9016a20014190026a41186a290300370000200120003a00a00120012001290390023700a101200141a0016a41017221032000450d0a20034280809aa6eaafe301420010aa02200141e8006a41086a200341086a290000370300200141e8006a41106a200341106a290000370300200141e8006a41186a200341186a2900003703002001200329000037036820012d00a0014101470d0b41201028221f450d03201f2001290368370000201f41186a200141e8006a41186a290300370000201f41106a200141e8006a41106a290300370000201f41086a200141e8006a41086a290300370000200141a0016a4101722103410221054120210441012120410121210340024002400240024020060d00410021060c010b2006417f6a2106201341ff01710d000240201a200e470d00410021130c010b200e41506a220b290300200b41086a290300844200520d0141012113200b210e0b200320012903b802370000200341086a200141b8026a41086a290300370000200341106a200141b8026a41106a290300370000200341186a200141b8026a41186a29030037000041002100200141003a00a0010c010b200141b8026a41186a200e41606a220041186a2900002207370300200141b8026a41106a200041106a2900002209370300200141b8026a41086a200041086a290000220a3703002001200029000022223703b80220032022370000200341086a200a370000200341106a2009370000200341186a2007370000200141013a00a00120034280809aa6eaafe301420010aa024100211320012d00a0012100200b210e0b20014190026a41186a220b200341186a29000037030020014190026a41106a2208200341106a29000037030020014190026a41086a2211200341086a29000037030020012003290000370390020240200041ff0171450d00200141a0016a41186a2212200b290300370300200141a0016a41106a220b2008290300370300200141a0016a41086a2208201129030037030020012001290390023703a001024020202021470d00202041016a22002020490d1820052000200520004b1b222141ffffff3f712021470d18202141057422004100480d180240024020200d0020001028211f0c010b201f20042000102c211f0b201f450d0c0b201f20046a220020012903a001370000200041186a2012290300370000200041106a200b290300370000200041086a2008290300370000200541026a2105200441206a2104202041016a21200c010b0b201f20046a21232020450d0c200141a0016a41086a2104201f210f0340200141306a200f10bf02024020012802304101470d002001280238210520014190016a10c002200128029001212402402001280298012203450d00200341216c2100202441016a21032005410876210841012005411f7174212520054105764107712211417f732126034002402003417f6a2d00004101470d00200141a0016a41186a200341186a290000370300200141a0016a41106a200341106a2900003703002004200341086a290000370300200120032900003703a001200120083602c00120014190026a200141a0016a10c1020240201120012802980222054f0d00200520266a220620054f0d0a200128029002220b20064102746a28020020257121050240200128029402450d00200b102a0b2005450d01411310282205450d0b200541002900c2a34122073700002005410f6a41002800d1a341220c360000200541086a41002900caa341220937000020014293808080b0023702a401200120053602a0012003200141a0016a108f0120012802a801211220012802a0012113200141b8026a41186a22054200370300200141b8026a41106a22064200370300200141b8026a41086a220b4200370300200142003703b80220132012200141b8026a1000200141106a41186a22102005290300370300200141106a41106a220d2006290300370300200141106a41086a2214200b290300370300200120012903b802370310024020012802a401450d0020012802a001102a0b200141003602a001200141106a4120200141a0016a1006210e024020012802a0012213417f460d00200120133602bc022001200e3602b802200141a0016a200141b8026a10c20220012903a0014201510d0d20014190026a41206a2227200441206a222828020036020020014190026a41186a2229200441186a222a29030037030020014190026a41106a222b200441106a222c29030037030020014190026a41086a2212200441086a222d290300370300200120042903003703900220012802cc01212e02402013450d00200e102a0b200141e8006a41206a20272802002213360200200141c0006a41086a220e2012290300370300200141c0006a41106a2227202b290300370300200141c0006a41186a222b2029290300370300200141c0006a41206a222920133602002001200129039002370340201242003703002001420037039002418891c600411120014190026a1008200141e8006a41086a20122903003703002001200129039002370368200141003602a00120024110200141a0016a1006211202400240024020012802a0012213417f470d00410021130c010b20134104490d01201228000021132012102a0b20042001290340370300202d200e290300370300202c2027290300370300202a202b29030037030020282029280200360200200142013703a0012001201341016a3602cc01411310282212450d10201220073700002012410f6a200c360000201241086a200937000020014293808080b002370294022001201236029002200320014190026a108f01200128029802211220012802900221132005420037030020064200370300200b4200370300200142003703b80220132012200141b8026a100020102005290300370300200d20062903003703002014200b290300370300200120012903b8023703100240200128029402450d00200128029002102a0b20014120360294022001200141106a36029002200420014190026a10c3020c030b41c4d1c3004133200141d8026a419cd9c3001038000b20042001290340370300200441086a200141c0006a41086a290300370300200441106a200141c0006a41106a290300370300200441186a200141c0006a41186a290300370300200441206a200141c0006a41206a280200360200200142003703a0012001202e3602cc01411310282212450d0d201220073700002012410f6a200c360000201241086a200937000020014293808080b002370294022001201236029002200320014190026a108f01200128029802211220012802900221132005420037030020064200370300200b4200370300200142003703b80220132012200141b8026a100020102005290300370300200d20062903003703002014200b290300370300200120012903b8023703100240200128029402450d00200128029002102a0b200141106a412010090c010b200128029402450d00200128029002102a0b200341216a21032000415f6a22000d000b0b200128029401450d002024102a0b2023200f41206a220f470d000c0d0b0b200341011037000b41c4d1c3004133200141d8026a419cd9c3001038000b41c4d1c3004133200141d8026a419cd9c3001038000b412041011037000b41cca2c100200620051034000b411341011037000b41c4d1c3004133200141d8026a419cd9c3001038000b411341011037000b411341011037000b200041011037000b200141e8006a41186a200341186a290000370300200141e8006a41106a200341106a290000370300200141e8006a41086a200341086a290000370300200120032900003703680b41002121410121234101211f410021200b20014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a00120024110200141a0016a10062103024002400240024002400240024020012802a0012200417f460d002003450d0020012000360294022001200336029002200141a0016a20014190026a107d20012802a0012225450d0220012902a40121072000450d012003102a0c010b42002107410421250b20252007422088a7220841246c6a210d02402019422088a722050d004100212f41012130410021310c050b410021314100212f4101213002402005200d20256b41246e2203200320054b1b2203450d00200341057422004100480d0e200010282230450d022003212f0b20252103200521042030210003400240200d20036b41ec004b0d00200d2003460d062025200841246c6a21114101210b0240034020002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a2900003700002004200b2206460d01200641016a210b200041206a21002011200341246a2203470d000b0b203120066a21310c060b20002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000024020044101470d00203141017221310c060b20002003290024370020200041386a2003413c6a290000370000200041306a200341346a290000370000200041286a2003412c6a29000037000020044102460d0420002003290048370040200041d8006a200341e0006a290000370000200041d0006a200341d8006a290000370000200041c8006a200341d0006a29000037000020044103460d032000200329006c370060200041f8006a20034184016a290000370000200041f0006a200341fc006a290000370000200041e8006a200341f4006a290000370000203141046a213120004180016a210020034190016a21032004417c6a22040d000c050b0b41c4d1c3004133200141d8026a419cd9c3001038000b200041011037000b203141037221310c010b203141027221310b201d201c6a21262007a721270240024002400240024002402005450d00202521032008450d03200541016a2100200841246c2104202521030340200141b8026a41186a200341186a290200370300200141b8026a41106a200341106a290200370300200141b8026a41086a200341086a290200370300200120032902003703b8022000417f6a2200450d02200341246a21032004415c6a22040d000b200d21030c030b202521032008450d02200141a0016a41186a202541186a290200370300200141a0016a41106a202541106a290200370300200141a0016a41086a202541086a290200370300200120252902003703a001202541246a2103202528022021060c010b200341206a2802002106200141a0016a41186a200141b8026a41186a290300370300200141a0016a41106a200141b8026a41106a290300370300200141a0016a41086a200141b8026a41086a290300370300200120012903b8023703a001200341246a21030b20014190026a41186a200141a0016a41186a2200290300220737030020014190026a41106a200141a0016a41106a2204290300220937030020014190026a41086a200141a0016a41086a2205290300220a370300200120012903a00122223703900220002007370300200420093703002005200a370300200120223703a001417f200d20036b41246d22002023201f6b4105766a220420042000491b21054100210b200141a0016a2100201f21040c010b0240201f2023470d0002402027450d002025102a0b4100211c410421284100212c0c020b201f41086a2900002107201f41106a2900002109201f290000210a20014190026a41186a201f41186a290000222237030020014190026a41106a200937030020014190026a41086a20073703002001200a37039002200141a0016a41186a2022370300200141a0016a41106a2009370300200141a0016a41086a20073703002001200a3703a0012023201f41206a22046b41057621054102210b200141a0016a2100202621060b417f200541016a220820082005491b221cad42247e2207422088a70d012007a72205417f4c0d010240024002400240024002400240024020050d00410421280c010b200510282228450d010b20282000290200370200202841186a200041186a290200370200202841106a200041106a290200370200202841086a200041086a290200370200202820063602200240200b450d00024020042023470d004101212c0c050b200441086a2900002107200441106a29000021092004290000210a20014190026a41186a200441186a29000037030020014190026a41106a200937030020014190026a41086a20073703002001200a37039002200441206a21040c020b0240200d2003460d00200141a0016a41186a200341186a2902002209370300200141a0016a41106a200341106a290200220a370300200141a0016a41086a200341086a29020022223703002003290200210720014190026a41086a202237030020014190026a41106a200a37030020014190026a41186a2009370300200120073703a0012001200737039002200328022021134100210b200341246a21030c030b024020042023460d00200441086a2900002107200441106a29000021092004290000210a20014190026a41186a200441186a29000037030020014190026a41106a200937030020014190026a41086a20073703002001200a37039002200441206a21040c020b4101212c0c030b200541041037000b4102210b202621130b4102210641022100412421050340200141a0016a41186a220820014190026a41186a220e290300370300200141a0016a41106a221120014190026a41106a220c290300370300200141a0016a41086a221220014190026a41086a221029030037030020012001290390023703a00102402000222c417f6a2200201c470d000240024002400240200b41ff01710e03010200010b202320046b41057621140c020b417f200d20036b41246d2214202320046b4105766a220f200f2014491b21140c010b200d20036b41246d21140b2000417f201441016a220f200f2014491b6a22142000490d0e20062014200620144b1b221cad42247e2207422088a70d0e2007a722004100480d0e02400240202c4101470d002000102821280c010b202820052000102c21280b2028450d030b202820056a220020012903a001370200200041186a2008290300370200200041106a2011290300370200200041086a2012290300370200200041206a20133602000240024002400240200b41ff01710e03010200010b20042023460d04200441086a2900002107200441106a29000021092004290000210a200e200441186a290000370300200c2009370300201020073703002001200a37039002200441206a2104410121084102210b202621130c020b0240200d2003460d002008200341186a29020022093703002011200341106a290200220a3703002012200341086a29020022223703002003290200210720102022370300200c200a370300200e2009370300200120073703a001200120073703900220032802202113410121084100210b200341246a21030c020b4102210b024020042023470d00410021080c020b200441086a2900002107200441106a29000021092004290000210a200e200441186a290000370300200c2009370300201020073703002001200a37039002200441206a210441012108202621130c010b200d2003460d02200e200341186a290200370300200c200341106a2902003703002010200341086a2902003703002001200329020037039002200328022021134101210b200341246a2103410121080b200641026a2106202c41016a2100200541246a210520080d000b0b02402027450d002025102a0b202c4115490d01202c4101762232ad42247e2207422088a70d032007a72203417f4c0d0302400240024020030d004104212e410421080c010b20031028222e450d01202e21080b2028415c6a2133202841b47f6a21344104210c410021244100212641002113202c2125034020252106410021254101210502402006417f6a221d450d000240024002400240024002402028201d41246c6a41206a280200200641246c221220286a41586a2802002203490d002006417e6a2111203420126a210441002125410021000340024020112000470d00200621050c080b200041016a21002003200428020022054f210b2004415c6a210420052103200b0d000b200041016a21052000417f7320066a21040c010b203420126a2100201d210402400340024020044101470d00410021040c020b2004417f6a210420032000280200220549210b2000415c6a210020052103200b0d000b0b20062004490d012006202c4b0d03200620046b2205410176220b450d00203320126a21032028200441246c6a21000340200141a0016a41206a2211200041206a2212280200360200200141a0016a41186a220e200041186a2210290200370300200141a0016a41106a220d200041106a2214290200370300200141a0016a41086a220f200041086a2225290200370300200120002902003703a001200341206a22272802002129200341186a222a2902002107200341106a222b2902002109200341086a222d290200210a200020032902003702002025200a37020020142009370200201020073702002012202936020020272011280200360200202a200e290300370200202b200d290300370200202d200f290300370200200320012903a0013702002003415c6a2103200041246a2100200b417f6a220b0d000b0b024020040d00200421250c050b0240200541094d0d00200421250c050b2006202c4b0d012028200441246c6a2111034020062004417f6a2225490d040240200620256b22054102490d002028200441246c6a220041206a22032802002028202541246c6a221241206a220b280200220e4f0d00200141b8026a41186a2210201241186a220d290200370300200141b8026a41106a2214201241106a220f290200370300200141b8026a41086a2227201241086a2229290200370300200120122902003703b802201220002902003702002029200041086a290200370200200f200041106a290200370200200d200041186a290200370200200b2003280200360200024020054103490d00201d210b20112103201241e8006a280200200e4f0d000340200341206a200341c4006a280200360200200341186a2003413c6a290200370200200341106a200341346a290200370200200341086a2003412c6a2902003702002003200341246a22002902003702002004200b417f6a220b460d01200341e8006a2112200021032012280200200e490d000b0b200020012903b8023702002000200e360220200041186a2010290300370200200041106a2014290300370200200041086a20272903003702000b2025450d052011415c6a2111202521042005410a4f0d050c000b0b200420061044000b20062004417f6a2225490d010b2006202c103c000b202520061044000b02400240024020132024470d00202441016a22032024490d10202441017422002003200020034b1b220341ffffffff01712003470d10200341037422004100480d100240024020240d0020001028210c0c010b200c20244103742000102c210c0b200c450d0120032124202621130b200c20134103746a2203200536020420032025360200202641016a2213212620134102490d01024003400240024002400240200c2013417f6a22264103746a2203280200450d002013410374200c6a220541746a2802002204200328020422004d0d000240201341024b0d0020132126410221130c080b200c2013417d6a22104103746a2802042203200020046a4d0d010240201341034b0d0020132126410321130c080b200541646a280200200320046a4d0d01201321260c070b20134103490d0120032802042100200c2013417d6a22104103746a28020421030b20032000490d010b2013417e6a21100b0240024002400240024002402013201041016a22274b2229450d00201320104b222a450d01200c20104103746a220d280204222b200d2802006a2203200c20274103746a2214280200220f490d022003202c4b0d032028200f41246c6a22122014280204220e41246c22006a2106200341246c21042003200f6b220b200e6b2203200e4f0d04202e2006200341246c2200109a051a200820006a210502400240200e4101480d00200341014e0d010b20062103200821000c060b203320046a210420062103034020042003415c6a220b2005415c6a22112005417c6a2802002003417c6a2802004922061b2200290200370200200441206a200041206a280200360200200441186a200041186a290200370200200441106a200041106a290200370200200441086a200041086a2902003702002005201120061b210502402012200b200320061b2203490d00200821000c070b2004415c6a21042008210020082005490d000c060b0b41b8dbc000202720131034000b41b8dbc000201020131034000b200f20031044000b2003202c103c000b202e20122000109a051a200820006a210502400240200e4101480d00200b200e4a0d010b20122103200821000c010b202820046a211120082100201221030340200320062000200641206a280200200041206a28020049220b1b2204290200370200200341206a200441206a280200360200200341186a200441186a290200370200200341106a200441106a290200370200200341086a200441086a2902003702002000200041246a200b1b2100200341246a2103200641246a2006200b1b220620114f0d01200520004b0d000b0b20032000200520006b220420044124706b109a051a0240202a450d00200d200f360200200d41046a202b200e6a3602002029450d022014201441086a20132027417f736a410374109b051a20262113202641014d0d040c010b0b41c8dbc000201020131034000b41b0b1c0001032000b200041041037000b20250d000b02402024450d00200c102a0b2032450d03202e102a0c030b200341041037000b200041041037000b202c4102490d00202c417f6a21042028202c41246c6a21064100210b0340024002400240202c20042203417f6a2204490d00202c20046b22004102490d022028200341246c6a220341206a22052802002028200441246c6a220841206a221228020022114f0d02200141b8026a41186a2213200841186a220e290200370300200141b8026a41106a220c200841106a2210290200370300200141b8026a41086a220d200841086a2214290200370300200120082902003703b802200820032902003702002014200341086a2902003702002010200341106a290200370200200e200341186a2902003702002012200528020036020020004103490d01200b210520062100200841e8006a28020020114f0d01034020002203415c6a22002003290200370200200041206a200341206a280200360200200041186a200341186a290200370200200041106a200341106a290200370200200041086a200341086a2902003702002005417f6a2205450d02200341246a2100200341c4006a28020020114f0d020c000b0b2004202c1044000b200320012903b80237020020032011360220200341186a2013290300370200200341106a200c290300370200200341086a200d2903003702000b200b41016a210b2006415c6a210620040d000b0b20014190026a41086a22034200370300200142003703900241a9a2c100410f20014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a801200142013703a001202c200141a0016a10b4010240202c450d002028202c41246c6a210b2028210003402000200141a0016a108f01200041206a28020021050240024020012802a401220420012802a80122036b4104490d0020012802a00121040c010b200341046a22062003490d0b200441017422032006200320064b1b22034100480d0b0240024020040d002003102821040c010b20012802a00120042003102c21040b2004450d04200120033602a401200120043602a00120012802a80121030b2001200341046a3602a801200420036a2005360000200b200041246a2200470d000b0b20012802a40121032002411020012802a001220020012802a801100702402003450d002000102a0b202c41246c220341246d2106410021040240024020030d004101210b410021060c010b200641ffffff3f712006470d09200641057422034100480d0920031028220b450d030b0240202c450d00202c41246c210541002104200b2103202821000340200041086a2900002107200041106a29000021092000290000210a200341186a200041186a290000370000200341106a2009370000200341086a20073700002003200a370000200441016a2104200341206a2103200041246a21002005415c6a22050d000b0b0240201c450d002028102a0b200b2004410041202004676b10c40220302031200b200410c50202402006450d00200b102a0b20014190026a41086a22034200370300200142003703900241b0a3c100411220014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a00120024110200141a0016a100621030240024020012802a0012200417f460d002003450d0020012000360294022001200336029002200141a0016a20014190026a106d20012802a0012208450d0520012902a401210a2000450d012003102a0c010b4200210a410121080b200141b8016a4200370300200141b0016a4200370300200141a8016a4200370300200142003703a001200a422088a7221041ffffff3f712010470d0020104105742203417f4c0d000240024020030d00410121060c010b200310282206450d050b200141b8026a41186a2204200141a0016a41186a290300370300200141b8026a41106a2205200141a0016a41106a290300370300200141b8026a41086a220b200141a0016a41086a290300370300200120012903a0013703b80220104102490d052010417f6a2100200621030340200320012903b802370000200341186a2004290300370000200341106a2005290300370000200341086a200b290300370000200341206a21032000417f6a22000d000b2010417f6a210c0c060b1036000b200341011037000b200341011037000b41c4d1c3004133200141d8026a419cd9c3001038000b200341011037000b4100210c200621032010450d010b200320012903b802370000200341186a200141b8026a41186a290300370000200341106a200141b8026a41106a290300370000200341086a200141b8026a41086a290300370000200c41016a210c0b201a201e41306c6a2103201ba7210e410021140c010b1031000b0240024002400240034002402018450d002003201a460d02200341506a2203290300200341086a29030084500d022018417f6a2200450d000340201a2003460d03200341506a2203290300200341086a29030084500d032000417f6a22000d000b0b2003201a460d0102400340200341506a22042903002107200441086a290300210920014190026a41186a2205200341606a220041186a29030037030020014190026a41106a220b200041106a29030037030020014190026a41086a2211200041086a29030037030020012000290300370390022007200984500d01200141a0016a41186a22002005290300370300200141a0016a41106a2205200b290300370300200141a0016a41086a220b201129030037030020012001290390023703a00120014190016a200141a0016a10bf02200141c0006a41186a22112000290300370300200141c0006a41106a22122005290300370300200141c0006a41086a2213200b290300370300200120012903a00137034002402001280290014101460d0020042103201a2004470d010c040b0b200141106a41086a220d2013290300370300200141106a41106a22132012290300370300200141106a41186a221220112903003703002001200129034022073703b8022001200737031020012802980121042000201229030037030020052013290300370300200b200d290300370300200120012903103703a001200c20044d0d03200341506a2103200620044105746a220420012903a001370000200441186a2000290300370000200441106a2005290300370000200441086a200b290300370000201441016a2114410021180c010b0b200141b8026a41086a200141e8006a41086a290300370300200141b8026a41106a200141e8006a41106a290300370300200141b8026a41186a200141e8006a41186a290300370300200120012903683703b8020b0240200e450d00201a102a0b200c201041ffffff3f7122032003200c4b1b2211450d022008210b410021050340024020082006460d002008200541057422036a2200200620036a4120109c05450d00411610282203450d0320034100290093a2413700002003410e6a41002900a1a241370000200341086a410029009ba24137000020014296808080e0023702a401200120033602a0012000200141a0016a108f0120012802a801210320012802a0012104200141b8026a41186a22124200370300200141b8026a41106a22134200370300200141b8026a41086a220e4200370300200142003703b80220042003200141b8026a1000200141106a41186a2012290300370300200141106a41106a2013290300370300200141106a41086a200e290300370300200120012903b802370310024020012802a401450d0020012802a001102a0b200141106a41201009201f210303400240202320036b41e0004b0d00024020032023460d000340200b2003460d04200320004120109c05450d042023200341206a2203470d000b0b200120004280809aa6eaafe3014200108202200129030021072001200141086a2903003703a801200120073703a0012001200141a0016a3602900220014190026a109d010c020b20002003460d01200320004120109c05450d01200341206a22042000460d01200420004120109c05450d01200341c0006a22042000460d01200420004120109c05450d01200341e0006a22042000460d0120034180016a2103200420004120109c050d000b0b200b41206a210b200541016a22052011490d000c030b0b41a0a3c1002004200c1034000b411641011037000b2006200c4105746a2103200c2111024002400240200c4104490d00200141a0016a41206a2112200141e0016a2113200141a0016a41e0006a210e200141a0026a210d200141b8016a2104200141b0016a2105200141a8016a210b20032100200c211103402004420037030020054200370300200b4200370300200142003703a001024020122000460d00200041606a200141a0016a4120109c05450d002011417f6a21000c030b2004420037030020054200370300200b4200370300200142003703a001024020132000460d00200041406a200141a0016a4120109c05450d002011417e6a21000c030b2004420037030020054200370300200b4200370300200142003703a0010240200e2000460d00200041a07f6a200141a0016a4120109c05450d002011417d6a21000c030b2004420037030020054200370300200b4200370300200142003703a001200041807f6a210302400240200d2000460d002003200141a0016a4120109c050d010b2011417c6a211120032100200320066b41e0004b0d010c020b0b2011417c6a21000c010b20032006460d012011417f6a2100200141a0016a41206a2104200141b8016a2105200141b0016a210b200141a8016a2111034020054200370300200b420037030020114200370300200142003703a001024020042003460d00200341606a200141a0016a4120109c050d020b2000417f6a21002006200341606a2203470d000c020b0b200041016a210c0b200141bc016a2031360200200141b8016a202f360200200141b4016a2030360200200141a0016a41106a2020360200200141ac016a2021360200200141083a00a001200141a0016a41086a201f360200200141033a00a40141014100200141a0016a10cc0120014190026a41086a22034200370300200142003703900241b0a3c100411220014190026a1008200141e8006a41086a20032903003703002001200129039002370368200141003602a801200142013703a001200c200141a0016a10b4010240200c450d00200c41057421002006210303402003200141a0016a108f01200341206a2103200041606a22000d000b0b20012802a40121032002411020012802a001220020012802a801100702402003450d002000102a0b02402010450d002006102a0b20014190026a41086a22034200370300200142003703900241bf91c600411620014190026a1008200141e8006a41086a220020032903003703002001200129039002370368200120143602a00120024110200141a0016a41041007200342003703002001420037039002418891c600411120014190026a1008200020032903003703002001200129039002370368200141003602a00120024110200141a0016a100621030240024020012802a0012200417f470d00410121030c010b024020030d00410121030c010b20004104490d03200328000021002003102a200041016a21030b20014190026a41086a220042003703002001420037039002418891c600411120014190026a1008200141e8006a41086a20002903003703002001200129039002370368200120033602a00120024110200141a0016a410410070240200aa7450d002008102a0b2019a7450d002017102a0b2016a7450d002015102a0b200141e0026a24000f0b41c4d1c3004133200141d8026a419cd9c3001038000bef0101047f230041206b220224002002410036021020014110200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602080c010b200220013602082002200336020c20034104490d012002200141046a36020820022003417c6a220436020c20044104490d01200128000021042002200341786a36020c2002200141086a36020820012800042103200241106a200241086a106d20022802102205450d012000200229021437020c2000200536020820002003360204200020043602002001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000bb70201057f230041d0006b220224000240411610282203450d0020034100290093a2413700002003410e6a41002900a1a241370000200341086a410029009ba24137000020024296808080e002370224200220033602202001200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b200241306a2002412010c6020240024020022802304101460d00200041003602000c010b20002002290234370204200041013602000b200241d0006a24000f0b411641011037000ba50708027f017e047f027e017f017e037f017e230041d0006b220124000240024002400240024002400240410e10282202450d00200241066a41002900b2a441370000200241002900aca4413700002002410e411c102c2202450d012002410036000e42002103200141286a41186a22044200370300200141286a41106a22054200370300200141286a41086a220642003703002001420037032820024112200141286a1000200141186a2004290300370300200141106a2005290300370300200141086a2006290300370300200120012903283703002002102a2001410036022820014120200141286a100621040240024020012802282202417f470d00410121070c010b2001200236022420012004360220200141286a200141206a107420012802282207450d03200129022c21032002450d002004102a0b02400240410e10282202450d0041002900b2a441210841002900aca4412109410121040340200241066a2008370000200220093700002002410e411c102c2202450d062002200436000e200141286a41186a22054200370300200141286a41106a22064200370300200141286a41086a220a42003703002001420037032820024112200141286a1000200141186a2005290300370300200141106a2006290300370300200141086a200a290300370300200120012903283703002002102a2001410036022820014120200141286a100621060240024020012802282202417f470d00410121054200210b0c010b2001200236022420012006360220200141286a200141206a107420012802282205450d08200129022c210b2002450d002006102a0b200b422088a72206450d0202402003a7220a2003422088a722026b200641216c220c41216d22064f0d00200220066a220d2002490d0a200a410174220e200d200e200d4b1bad220342217e220f422088a70d0a200fa7220d4100480d0a02400240200a0d00200d102821070c010b2007200a41216c200d102c21070b2007450d090b2007200241216c6a2005200c109a051a200342ffffffff0f832103200220066aad422086210f0240200ba7450d002005102a0b200441016a21042003200f842103410e102822020d000b0b410e41011037000b0240200ba7450d002005102a0b2000200337020420002007360200200141d0006a24000f0b410e41011037000b411c41011037000b41c4d1c3004133200141c8006a419cd9c3001038000b411c41011037000b41c4d1c3004133200141c8006a419cd9c3001038000b200d41011037000b1031000bcc0402057f017e230041e0006b220224000240024002400240411310282203450d0020034100290099a4413700002003410f6a41002800a8a441360000200341086a41002900a1a44137000020024293808080b00237022c200220033602282001200241286a108f012001280220210402400240200228022c2201200228023022036b4104490d00200228022821010c010b200341046a22052003490d03200141017422032005200320054b1b22034100480d030240024020010d002003102821010c010b200228022820012003102c21010b2001450d022002200336022c20022001360228200228023021030b2002200341046a360230200120036a20043600002002280230210320022802282101200241386a41186a22044200370300200241386a41106a22054200370300200241386a41086a220642003703002002420037033820012003200241386a1000200241086a41186a2004290300370300200241086a41106a2005290300370300200241086a41086a2006290300370300200220022903383703080240200228022c450d002002280228102a0b20024100360238200241086a4120200241386a100621010240024020022802382203417f460d002002200336022c20022001360228200241386a200241286a10820120022802382204450d05200229023c210702402003450d002001102a0b20002007370204200020043602000c010b20004100360208200042043702000b200241e0006a24000f0b411341011037000b200341011037000b1031000b41c4d1c3004133200241d8006a419cd9c3001038000bf70103017e057f027e420121020240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a360200200641034d0d00200428000421072001200341786a22063602042001200441086a36020020064110490d00200441106a2900002108200429000821092001200341686a22063602042001200441186a36020020064110490d0020002009370308200041186a2004290018370300200041106a20083703002000412c6a2007360200200041286a2005360200200041206a200441206a2900003703002001200341586a3602042001200441286a360200420021020b200020023703000bd30102027f027e200028022021020240024002400240410410282203450d002003200236000020002802242102200341044108102c2203450d0120032002360004200041086a290300210420002903002105200341084118102c2203450d0220032005370008200341106a2004370000200041186a290300210420002903102105200341184130102c2200450d0320002005370018200041206a2004370000200128020020012802042000412810072000102a0f0b410441011037000b410841011037000b411841011037000b413041011037000b942103157f037e077f230041c0026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110da032003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200a200a417f6a220d2000200a4105746a2000200d4105746a4120109c05220e410048220f1b2210200a41016a2211200d200a200f1b220a200020114105746a2000200a4105746a4120109c05220f4100481b220a2000200a4105746a200020104105746a4120109c0522104100481b210a200c200c417f6a220d2000200c4105746a2000200d4105746a4120109c05221141004822121b2213200c4101722214200d200c20121b220c200020144105746a2000200c4105746a4120109c0522124100481b220c2000200c4105746a200020134105746a4120109c0522134100481b210c200b200b417f6a220d2000200b4105746a2000200d4105746a4120109c05221441004822151b2216200b41016a2217200d200b20151b220b200020174105746a2000200b4105746a4120109c05220d4100481b220b2000200b4105746a200020164105746a4120109c0522154100481b210b200f411f76200e411f766a2010411f766a2011411f766a2012411f766a2013411f766a2014411f766a200d411f766a2015411f766a210d0b2000200c4105746a2000200a4105746a4120109c05220e411f76200d6a2000200b4105746a2000200a200c200e410048220e1b220f4105746a4120109c052210411f766a210d2000200b200f20104100481b220b4105746a2000200c200a200e1b22184105746a4120109c05417f4c0d01200b21180c020b2000200110db030c0f0b200d41016a220d410c490d0002402001410176220b450d00200020014105746a41606a210a2000210c0340200441206a41186a220d200c41186a220e290000370300200441206a41106a220f200c41106a2210290000370300200441206a41086a2211200c41086a22122900003703002004200c290000370320200a41086a22132900002119200a41106a2214290000211a200a41186a2215290000211b200c200a290000370000200e201b3700002010201a370000201220193700002015200d2903003700002014200f29030037000020132011290300370000200a2004290320370000200a41606a210a200c41206a210c200b417f6a220b0d000b0b20012018417f736a21184101210a0c010b200d45210a0b0240200a452009724101710d002000200110dc030d0d0b2002450d02201820014f0d0102402002200020184105746a220a4120109c0541004e0d0020002108200121070c040b200441206a41186a2212200041186a220f290000370300200441206a41106a2213200041106a2210290000370300200441206a41086a2214200041086a221129000037030020042000290000370320200a41086a220c2900002119200a41106a220b290000211a200a41186a220d290000211b2000200a290000370000200f201b3700002010201a37000020112019370000200d2012290300370000200b2013290300370000200c2014290300370000200a2004290320370000200441c0016a41186a2217200f290000370300200441c0016a41106a221c2010290000370300200441c0016a41086a22182011290000370300200420002900003703c001200041606a2115200041206a21164100210c2001210b03400240200c200b417f6a220d4f0d002016200c4105746a210a0340200441c0016a200a4120109c05417f4c0d01200a41206a210a200d200c41016a220c470d000b200d210c0b2015200b4105746a210a02400340200c200b417f6a220b4f0d01200441c0016a200a4120109c05210d200a41606a220e210a200d4100480d000b20122016200c4105746a220a41186a220d2900003703002013200a41106a221d2900003703002014200a41086a22062900003703002004200a290000370320200e41286a221e2900002119200e41306a221f290000211a200e41386a2220290000211b200a200e41206a220e290000370000200d201b370000201d201a3700002006201937000020202012290300370000201f2013290300370000201e2014290300370000200e2004290320370000200c41016a210c0c010b0b200020042903c001370000200f20172903003700002010201c2903003700002011201829030037000002402001200c41016a220a490d002000200a4105746a21002001200a6b220141154f0d010c0c0b0b200a20011044000b41a0cec300201820011034000b2007450d010b201820074f0d01200441206a41186a2216200841186a221e290000370300200441206a41106a2217200841106a221f290000370300200441206a41086a221c200841086a222029000037030020042008290000370320200820184105746a220a41086a220c2900002119200a41106a220b290000211a200a41186a220d290000211b2008200a290000370000201e201b370000201f201a37000020202019370000200d2016290300370000200b2017290300370000200c201c290300370000200a2004290320370000200441186a2205201e290000370300200441106a2209201f290000370300200441086a2221202029000037030020042008290000370300200841206a21014100211d2007417f6a220d450d022001210a0340200a20044120109c0541004e0d03200a41206a210a200d201d41016a221d470d000b200d211d0c020b4180cec300410041001034000b4190cec300201820071034000b200820074105746a210c200d210b02400340200c2100200b220a201d4d22060d01200a417f6a210b200041606a220c20044120109c05417f4a0d000b0b0240200a201d490d00200d200a490d0241800121144100210e410021124100210d4100211141800121152001201d4105746a2222210103400240200020016b220a419fc0004b22180d00200a410576220a41807f6a200a2012200e492011200d49220c72220b1b210a0240200b450d002015200a200c1b2115200a2014200c1b21140c010b200a200a41017622156b21140b02402011200d470d00024020150d00200441c0006a220d21110c010b4100210a200441c0006a2211210d2001210c0340200d200a3a0000200d200c20044120109c05417f73411f766a210d200c41206a210c2015200a41016a220a470d000b0b02402012200e470d00024020140d00200441c0016a220e21120c010b200041606a210a4100210c200441c0016a2212210e0340200e200c3a0000200e200a20044120109c05411f766a210e200a41606a210a2014200c41016a220c470d000b0b0240200e20126b220a200d20116b220c200c200a4b1b2213450d002016200120112d00004105746a220a41186a2900003703002017200a41106a290000370300201c200a41086a2900003703002004200a290000370320200120112d00004105746a220a200020122d0000417f734105746a220c290000370000200a41186a200c41186a290000370000200a41106a200c41106a290000370000200a41086a200c41086a290000370000024020134101460d004100210a034020002012200a6a220f2d0000417f734105746a220c20012011200a6a41016a22102d00004105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200120102d00004105746a220c2000200f41016a2d0000417f734105746a220b290000370000200c41186a200b41186a290000370000200c41106a200b41106a290000370000200c41086a200b41086a290000370000200a41026a210c200a41016a220b210a200c2013490d000b2012200b6a21122011200b6a21110b200020122d0000417f734105746a220a2004290320370000200a41186a2016290300370000200a41106a2017290300370000200a41086a201c290300370000201241016a2112201141016a21110b200020144105746b20002012200e461b2100200120154105746a20012011200d461b210120180d000b024002402011200d4f0d002000210a034020162001200d417f6a220d2d00004105746a220c41186a220b2900003703002017200c41106a220e290000370300201c200c41086a22002900003703002004200c290000370320200a41606a220a41086a220f2900002119200a41106a2210290000211a200a41186a2212290000211b200c200a290000370000200b201b370000200e201a370000200020193700002012201629030037000020102017290300370000200f201c290300370000200a20042903203700002011200d490d000c020b0b2001210a2012200e4f0d000340200e417f6a220e2d0000210c2016200a41186a220b2900003703002017200a41106a220d290000370300201c200a41086a22012900003703002004200a2900003703202000200c417f734105746a220c41086a220f2900002119200c41106a2210290000211a200c41186a2211290000211b200a200c290000370000200b201b370000200d201a370000200120193700002011201629030037000020102017290300370000200f201c290300370000200c2004290320370000200a41206a210a2012200e490d000b0b20082004290300370000201e2005290300370000201f2009290300370000202020212903003700002007200a20226b410576201d6a22014d0d032016201e2900003703002017201f290000370300201c202029000037030020042008290000370320200820014105746a220a41086a220c2900002119200a41106a220b290000211a200a41186a220d290000211b2008200a290000370000201e201b370000201f201a37000020202019370000200d2016290300370000200b2017290300370000200c201c290300370000200a2004290320370000200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41206a2100024002402001200c417f6a220c490d002000200c200a200310c402200821000c010b200820012002200310c402200a2102200c21010b200b200d4f2105200141154f0d010c050b0b201d200a1044000b200a200d103c000b4190cec300200120071034000b41dc83c6001032000b20014102490d00200041406a210f410021104101210d0340200d410574210a200d417f6a210b200d41016a210d02402000200a6a220e2000200b4105746a220a4120109c05417f4a0d00200441c0016a41186a2211200e41186a220c290000370300200441c0016a41106a2212200e41106a2213290000370300200441c0016a41086a2214200e41086a22152900003703002004200e2900003703c001200e200a2900003700002015200a41086a2900003700002013200a41106a290000370000200c200a41186a29000037000002400240200b0d004100210b0c010b2010210c200f210a200441c0016a200e41406a4120109c05417f4a0d0002400340200a41d8006a200a41386a290000370000200a41d0006a200a41306a290000370000200a41c8006a200a41286a290000370000200a41c0006a200a41206a290000370000200c4101460d01200441c0016a200a4120109c05210e200c417f6a220b210c200a41606a210a200e4100480d000c020b0b4100210b0b2000200b4105746a220a20042903c001370000200a41186a2011290300370000200a41106a2012290300370000200a41086a20142903003700000b201041016a2110200f41206a210f200d2001470d000b0b200441c0026a24000bd9140a057f017e067f037e037f017e017f027e077f057e23002204210520044180026b4160712204240002400240200141ffffff3f712001470d0020014105742206417f4c0d0002400240024020060d00410121070c010b200610282207450d010b410021084100210602402001450d002001410574210820072106034020062000290000370000200641186a200041186a290000370000200641106a200041106a290000370000200641086a200041086a290000370000200641206a2106200041206a2100200841606a22080d000b200141057441606a41057641016a2106200121080b20042006360218200420083602142004200736021020072006410041202006676b10c40242002109200441b0016a41086a22004200370300200442003703b001419896c300411d200441b0016a1008200441e0016a41086a2000290300370300200420042903b0013703e001200441003602b001200441e0016a4110200441b0016a1006210602400240024020042802b0012200417f460d0020042000360294012004200636029001200441b0016a20044190016a106d20042802b001220a450d0220042902b40121092000450d012006102a0c010b4101210a0b2009422088a72200450d032000410574210b200441e0016a410c6a210c200441e0016a411472210d200441e0016a410872210e200441c0006a410c72210f200a210002400340200041086a2900002110200041106a290000211120002900002112200441206a41186a2213200041186a290000370300200441206a41106a22142011370300200441206a41086a22152010370300200420123703200240024002400240411a10282206450d00200641002900b596432216370000200641186a41002f00cd964322173b0000200641106a41002900c596432218370000200641086a41002900bd964322193700002004429a808080a0033702b401200420063602b0012004200441b0016a3602e001200441206a200441e0016a10c80120042802b001210720042802b801211a200441e0016a41186a22014200370300200441e0016a41106a22064200370300200441e0016a41086a22084200370300200442003703e0012007201a200441e0016a100020044190016a41186a221b200129030037030020044190016a41106a221c200629030037030020044190016a41086a221a2008290300370300200420042903e00137039001024020042802b401450d0020042802b001102a0b200441003602e00120044190016a4120200441e0016a1006211d20042802e0012207417f460d02200420073602642004201d360260200441e0016a200441e0006a10b30320042802e801221e450d01200441b0016a41086a221f200c41086a290200370300200441b0016a41106a2220200c41106a2802003602002004200c2902003703b00120042903e001211002402007450d00201d102a0b200f20042903b00122113702002006202028020022073602002008201f2903002212370300200f41086a2012370200200f41106a2007360200200420113703e001200420103703400c030b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b2006200441b0016a41106a2802003602002008200441b0016a41086a290300370300200420042903b0013703e0014100211e0b2004201e360248200441003602e80120042903582112200420042903f801222137035820042903502122200420042903f001222337035020042903402124200420042903e001221137034020042903482110200420042903e80122253703482025a72107024002402010a7221d0d002025211020232122202121120c010b200420243703e001200420103703e801200420223703f001200420123703f8012004201d2022a74105746a3602bc012004201d3602b80120042010422088a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200e41086a201a280200360200200e20042903900137020020042022422088a7221d2012422088a74105746a3602bc012004201d3602b80120042012a73602b4012004201d3602b0012004200441106a3602c00120044190016a200441b0016a108401200d41086a201a280200360200200d20042903900137020020042903e801211020042903e001211120042903f801211220042903f001212202402007450d002021a7211d02402025422088a7450d002007102a0b201d450d002023422088a7102a0b200420113703402004201037034820042022370350200420123703582010a721070b2004201137036020042010370368200420223703702004201237037802400240024020070d00200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0220072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b20044190016a412010090c010b200441b0016a41186a2013290300370300200441b0016a41106a2014290300370300200441b0016a41086a2015290300370300200420042903203703b001411a10282207450d0320072016370000200741186a20173b0000200741106a2018370000200741086a20193700002004429a808080a0033702d401200420073602d0012004200441d0016a3602e001200441b0016a200441e0016a10c80120042802d001210720042802d801211d200142003703002006420037030020084200370300200442003703e0012007201d200441e0016a1000201b2001290300370300201c2006290300370300201a2008290300370300200420042903e00137039001024020042802d401450d0020042802d001102a0b200441203602e401200420044190016a3602e001200441e0006a200441e0016a10b4030b02402010a72206450d002012a7210802402010422088a7450d002006102a0b2008450d002022422088a7102a0b200041206a2100200b41606a220b0d010c060b0b411a41011037000b411a41011037000b41c4d1c3004133200441d0016a419cd9c3001038000b200641011037000b1036000b02402009a7450d00200a102a0b200441003602e801200442013703e0012003200441e0016a10b40102402003450d002003410574210003402002200441e0016a108f01200241206a2102200041606a22000d000b0b20042802e401210620042802e801210820042802e0012100200441b0016a41086a22014200370300200442003703b00141fbefc200411b200441b0016a1008200441e0016a41086a2001290300370300200420042903b0013703e001200441e0016a411020002008100702402006450d002000102a0b02402004280214450d002004280210102a0b200524000ba50101027f230041206b22032400410021042003410036021420012002200341146a100621010240024020032802142202417f460d002001450d002003410036020c20024104490d0120012800002104200341003602102002417c714104460d01200128000421022001102a200041086a200236020020002004360204410121040b20002004360200200341206a24000f0b41c4d1c3004133200341186a419cd9c3001038000b13002000410a36020420004188a5c1003602000b3400200041fecbc10036020420004100360200200041146a4110360200200041106a4188ccc100360200200041086a42073702000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241003600000b2201017f230041106b22022400200241003602002000200210ad02200241106a24000b13002000410b360204200041c0e5c1003602000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241c0003600000b3d01017f02404110102822020d00411041011037000b200242003700082002428080e983b1de16370000200042908080808002370204200020023602000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180c2033600000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241013600000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241063600000b3d01017f02404110102822020d00411041011037000b200242003700082002428080d287e2bc2d370000200042908080808002370204200020023602000b3e01017f02404110102822020d00411041011037000b2002420037000820024280809aa6eaafe301370000200042908080808002370204200020023602000b9f0a01047f230041206b220224000240024002400240024002400240024002400240024002400240024002402001280200417f6a220341094b0d0020030e0a0102030405060708090a010b41c4f7c1001032000b2001410c6a2802002203417f4c0d0a200128020421044101210502402003450d00200310282205450d0c0b200520042003109a0521052000410c6a2003360200200041086a20033602002000200536020420004101360200200041206a200141206a290300370300200041186a2001290318370300200041106a20012902103703000c090b2001410c6a2802002203417f4c0d09200128020421050240024020030d00410121040c010b200310282204450d0c0b200420052003109a0521052000410c6a2003360200200041086a20033602002000200536020420004102360200200041206a200141206a290300370300200041186a2001290318370300200041106a20012902103703000c080b200128020421054101210302400240200141086a22042d00004101460d002002411e6a200441036a2d00003a0000200241086a200141186a290200370300200241106a200141206a290200370300200241186a200141286a2d00003a0000200220042f00013b011c2002200141106a2902003703002001410c6a2802002104410021030c010b2001410c6a28020021040b20002005360204200020022f011c3b0009200041086a20033a00002000410c6a2004360200200041106a20022903003702002000412c6a200129022c3702002000410b6a2002411e6a2d00003a0000200041186a200241086a290300370200200041206a200241106a290300370200200041286a200241186a280200360200200041033602000c070b20004104360200200020012802043602040c060b20004105360200200020012802043602040c050b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002105410021030c010b200141086a28020021050b200020033a0004200020022f011c3b0005200041306a2001290330370300200041086a20053602002000410c6a2002290300370200200041386a200141386a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602002001280228210120004106360200200041286a20013602000c040b20004107360200200020012802043602040c030b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002101410021030c010b200141086a28020021010b200020033a0004200020022f011c3b000520004108360200200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c020b20004109360200200020012802043602040c010b2000410a360200200020012802043602040b200241206a24000f0b1036000b200341011037000b200341011037000bbf4305047f027e037f017e067f23004190026b22072400200741f0006a41086a220842003703002007420037037041b0a3c1004112200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0014100210920074100360270200741a0016a4110200741f0006a1006210802402007280270220a417f460d002008450d002007200a36027420072008360270200741306a200741f0006a106c0240024020072802300d00200728023421090c010b410021090b200a450d002008102a0b200741f0006a41086a220842003703002007420037037041b8a2c1004114200741f0006a1008200741a0016a41086a220a2008290300370300200720072903703703a001024002400240200741a0016a41104101410041001003417f460d0041effec1002108412e210a0c010b2008420037030020074200370370418891c6004111200741f0006a1008200a2008290300370300200720072903703703a00120074100360270200741a0016a4110200741f0006a1006210802400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402007280270220a417f470d004100210a0c010b024020080d004100210a0c010b200a4104490d012008280000210a2008102a0b0240200a2003460d00419dffc10021084114210a0c1e0b024020090d0041b1ffc100210841c100210a0c1e0b02402009200241086a2802004f0d0041f2ffc1002108413c210a0c1e0b02402005428080e983b1de165441002006501b450d0041ae80c20021084124210a0c1e0b200741206a2001109d02200741206a41086a290300210b2007290320210c411310282208450d01200c200554200b200654200b2006511b210a200841002900c2a3413700002008410f6a41002800d1a341360000200841086a41002900caa34137000020074293808080b002370274200720083602702001200741f0006a108f012007280278210820072802702109200741a0016a41186a220d4200370300200741a0016a41106a220e4200370300200741a0016a41086a220f4200370300200742003703a00120092008200741a0016a1000200741c0006a41186a200d290300370300200741c0006a41106a200e290300370300200741c0006a41086a200f290300370300200720072903a00137034002402007280274450d002007280270102a0b200b2006200a1b210b200c2005200a1b210620074100360270200741c0006a4120200741f0006a100621080240024002402007280270220a417f460d002008450d002007200a3602a401200720083602a001200741f0006a200741a0016a10c20220072903704201510d0520074180016a29030021052007290378210c0240200a450d002008102a0b410e10282208450d06200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d072008200441067636000e200741a0016a41186a220a4200370300200741a0016a41106a22094200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741f0006a41186a200a290300370300200741f0006a41106a2009290300370300200741f0006a41086a200d290300370300200720072903a0013703702008102a200741003602a001200741f0006a4120200741a0016a1006210820072802a001220a417f460d1b2008450d1b2007200a3602dc01200720083602d801200741a0016a200741d8016a107420072802a001220d450d082004413f71210920072902a40121100240200a450d002008102a0b4100210420092010422088a7490d010c190b200741106a20011091012007290310428080e983b1de1656200741186a29030022054200522005501b0d0141e380c20021084134210a0c1f0b200d200941216c6a22082d00004101470d17200741da016a200841036a2d00003a0000200741a0016a41086a200841146a290000370300200741ad016a200841196a290000370000200720082f00013b01d80120072008410c6a2900003703a001200841086a280000210a200841046a2800002108410121040c180b410e10282208450d06200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d0720082004410676220e36000e200741a0016a41186a220a4200370300200741a0016a41106a22094200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2009290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a20074100360270200741c0006a4120200741f0006a1006210802402007280270220a417f460d002008450d002007200a3602a401200720083602a001200741f0006a200741a0016a10742007280270220d450d092004413f712109200729027421050240200a450d002008102a0b41002108024020092005422088a74f0d0041014102200d200941216c6a2d00001b21080b02402005a7450d00200d102a0b20084102490d00410e10282208450d0a200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d0b2008200e36000e42002105200741a0016a41186a220a4200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a20074100360270200741c0006a4120200741f0006a100621080240024020072802702204417f470d004101210a0c010b024020080d004101210a0c010b200720043602a401200720083602a001200741f0006a200741a0016a10742007280270220a450d0d200729027421052004450d002008102a0b200741c0006a41186a2204200141186a290000370300200741c0006a41106a220d200141106a290000370300200741c0006a41086a220f200141086a2900003703002007200129000037034020092005422088a722114f0d0d200a200941216c6a220841013a000020082007290340370001200841096a200f290300370000200841116a200d290300370000200841196a2004290300370000410e102821080240200a0d002008450d0f200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d102008200e36000e200741a0016a41186a220a4200370300200741a0016a41106a22094200370300200741a0016a41086a22044200370300200742003703a00120084112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2009290300370300200741c0006a41086a2004290300370300200720072903a0013703402008102a200741c0006a412010090c170b2008450d10200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d112008200e36000e200741a0016a41186a22094200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a200741203602742007200741c0006a360270200a2011200741f0006a10ab022005a7450d16200a102a0c160b200741f0006a41086a2208420037030020074200370370419991c6004114200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0014100210a20074100360270200741a0016a4110200741f0006a10062108024020072802702209417f460d002008450d0020094104490d122008280000210a2008102a0b410e10282208450d12200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d132008200a36000e200741a0016a41186a22094200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a20074100360270200741c0006a4120200741f0006a1006210802400240024020072802702209417f460d002008450d002007200936027420072008360270200741086a200741f0006a106c0240024020072802080d00200728020c210d410021040c010b4101210441b8aec600210d0b02402009450d002008102a0b20040d00200d413f460d01200d0d170b200741f0006a2001428080d287e2bc2d4200410810980220072802704101470d012007280278210a200728027421080c1f0b200741f0006a41086a2208420037030020074200370370419991c6004114200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0012007200a41016a360270200741a0016a4110200741f0006a410410070c150b20072903782105200720074180016a29030037037820072005370370200b2006428080aef89dc3527c2205200654ad7c427f7c210b2007200741f0006a3602a001200741a0016a109d01200521060c140b41c4d1c3004133200741c0016a419cd9c3001038000b411341011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b41a0a3c100200920111034000b410e41011037000b411c41011037000b410e41011037000b411c41011037000b41c4d1c3004133200741c0016a419cd9c3001038000b410e41011037000b411c41011037000b200741f9006a200141086a29000037000020074181016a200141106a29000037000020074189016a200141186a290000370000200741013a00702007200129000037007102400240024002400240024002400240024002400240024002400240024002400240410e10282208450d00200841066a41002900b2a441370000200841002900aca4413700002008410e411c102c2208450d012008200a36000e200741a0016a41186a22094200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120084112200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402008102a200741003602a001200741c0006a4120200741a0016a100621080240024020072802a0012204417f460d002004210920080d010b200741003602a801200742013703a0014100200741a0016a10b40120072802a801210920072802a401210420072802a00121080b200720093602682007200436026420072008360260024002402009450d00200741a0016a20082009410110d60220072802a0014101470d012007280264450d122007280260102a0c120b4101200741e0006a10b401024020072d00704101460d0002400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d1b200841017422042009200420094b1b22044100480d1b0240024020080d002004102821090c010b200728026020082004102c21090b2009450d052007200436026420072009360260200728026821080b2007200841016a360268200920086a41003a00000c100b02400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d1a200841017422042009200420094b1b22044100480d1a0240024020080d002004102821090c010b200728026020082004102c21090b2009450d052007200436026420072009360260200728026821080b2007200841016a360268200920086a41013a0000200741f0006a410172200741e0006a108f010c0f0b20072802a401210d0240200741ac016a2802002208200741a8016a2802002209460d002007280268200820096b6a220441216a220e417f4c0d0502400240200e0d004101210f0c010b200e1028220f450d070b2007200e3602c4012007200f3602c001200720043602c8012007200741c0016a3602a001200d200741a0016a200810d70120042008490d0720072802c801220d2004490d082007280268220d2009490d0920072802c001210e2007280260210f2007200420086b22043602d0012007200d20096b220d3602d4012004200d470d0a200e20086a200f20096a2004109a051a0240024020072d00704101460d000240024020072802c40120072802c8012208460d0020072802c00121090c010b200841016a22092008490d1c200841017422042009200420094b1b22044100480d1c0240024020080d002004102821090c010b20072802c00120082004102c21090b2009450d0e200720043602c401200720093602c00120072802c80121080b2007200841016a3602c801200920086a41003a00000c010b0240024020072802c40120072802c8012208460d0020072802c00121090c010b200841016a22092008490d1b200841017422042009200420094b1b22044100480d1b0240024020080d002004102821090c010b20072802c00120082004102c21090b2009450d0e200720043602c401200720093602c00120072802c80121080b2007200841016a3602c801200920086a41013a0000200741f0006a410172200741c0016a108f010b20072802c801210920072802c401210420072802c00121082007280264450d102007280260102a0c100b2007200741e0006a3602a001200d200741a0016a200910d701024020072d00704101460d0002400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d1a200841017422042009200420094b1b22044100480d1a0240024020080d002004102821090c010b200728026020082004102c21090b2009450d0e2007200436026420072009360260200728026821080b2007200841016a360268200920086a41003a00000c0f0b02400240200728026420072802682208460d00200728026021090c010b200841016a22092008490d19200841017422042009200420094b1b22044100480d190240024020080d002004102821090c010b200728026020082004102c21090b2009450d0e2007200436026420072009360260200728026821080b2007200841016a360268200920086a41013a0000200741f0006a410172200741e0006a108f010c0e0b410e41011037000b411c41011037000b200441011037000b200441011037000b1036000b200e41011037000b200820041044000b2004200d103c000b2009200d1044000b200741f0016a41146a4108360200200741fc016a4125360200200741d8016a41146a4103360200200742033702dc01200741c8afc6003602d801200741253602f4012007200741d0016a360288022007200741d4016a36028c02200742043703b001200742013702a4012007419cb0c6003602a0012007200741f0016a3602e8012007200741a0016a3602800220072007418c026a3602f801200720074188026a3602f001200741d8016a41d8b0c600103e000b200441011037000b200441011037000b200441011037000b200441011037000b2007280268210920072802642104200728026021080b2008450d00200741c0006a41202008200910072004450d012008102a0c010b024002400240412110282208450d0041002109024020072d00704101470d00200741b8016a20074189016a290000370300200741b0016a20074181016a290000370300200741a8016a200741f9006a290000370300200720072900713703a001410121090b200820093a0000200820072903a001370001200841096a200741a8016a290300370000200841116a200741b0016a290300370000200841196a200741b8016a290300370000410e10282209450d01200941066a41002900b2a441370000200941002900aca4413700002009410e411c102c2209450d022009200a36000e200741a0016a41186a220a4200370300200741a0016a41106a22044200370300200741a0016a41086a220d4200370300200742003703a00120094112200741a0016a1000200741c0006a41186a200a290300370300200741c0006a41106a2004290300370300200741c0006a41086a200d290300370300200720072903a0013703402009102a200741203602a4012007200741c0006a3602a00120084101200741a0016a10ab022008102a0c030b412141011037000b410e41011037000b411c41011037000b20072001428080e983b1de164200108302024020072802002208450d002007280204210a0c080b200741f0006a41086a220842003703002007420037037041ad91c6004112200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0014100210a20074100360270200741a0016a4110200741f0006a100621080240024020072802702209417f460d002008450d0020094104490d012008280000210a2008102a0b4200210c200741f0006a41086a220842003703002007420037037041ad91c6004112200741f0006a1008200741a0016a41086a2008290300370300200720072903703703a0012007200a41016a360270200741a0016a4110200741f0006a41041007420021050c060b41c4d1c3004133200741c0016a419cd9c3001038000b0b02402010a7450d00200d102a2004450d010c020b20040d010b410121094113210a419781c20021080c010b200741c0016a41026a200741d8016a41026a2d00003a0000200741f0006a41086a200741a0016a41086a290300370300200741f0006a410d6a200741a0016a410d6a290000370000200720072f01d8013b01c001200720072903a001370370410021090b200741e0006a41026a2204200741c0016a41026a2d00003a0000200741f0016a41086a220d200741f0006a41086a290300370300200741f0016a41106a200741f0006a41106a290300370300200720072f01c0013b0160200720072903703703f00120090d02200741d3006a200d290300370000200741d8006a200741fd016a290000370000200720072f01603b01402007200a36004720072008360043200720072903f00137004b200720042d00003a0042200741c0006a2001460d00200741c0006a20014120109c05450d0041d280c20021084111210a0c020b200742f0f2bda9c6add9b1f400370338200741386a20012006200b417f410f10a902200741f0006a41186a200b3703002007200637038001200720053703782007200c370370200720033602940120072003360290010240024002400240411310282208450d00200841002900c2a3413700002008410f6a41002800d1a341360000200841086a41002900caa34137000020074293808080b0023702f401200720083602f0012001200741f0016a108f0120072802f801210820072802f001210a200741a0016a41186a22094200370300200741a0016a41106a22034200370300200741a0016a41086a22044200370300200742003703a001200a2008200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2003290300370300200741c0006a41086a2004290300370300200720072903a001370340024020072802f401450d0020072802f001102a0b200741203602a4012007200741c0006a3602a001200741f0006a200741a0016a10c3022002280204210f20022802002103024002400240200241086a280200220941057622120d0041042113410421140c010b2012410274220810282213450d01201321140b2009450d030240024020120d00410410282213450d0141012112201321140b201441003602002009417f6a210441012115410021084100210a024003402014200a4102746a2202200320086a2d00002008411f717420022802006a360200024002400240024020042008460d00200841016a2202411f710d0320152012470d02201541016a220d2015490d0c2015410174220e200d200e200d4b1b221241ffffffff03712012470d0c2012410274220d41004e0d010c0c0b0240200f450d002003102a0b41002116024002400240024003402015410820154108491b220a410274220f10282208450d0120082014200f109a052111200741f0006a41186a200141186a290000370300200741f0006a41106a200141106a290000370300200741f0006a41086a200141086a290000370300200720163602900120072001290000370370411310282208450d0220084100290099a4413700002008410f6a41002800a8a441360000200841086a41002900a1a44137000020074293808080b0023702f401200720083602f001200741f0006a200741f0016a108f0120072802900121090240024020072802f401220220072802f80122086b4104490d0020072802f00121020c010b200841046a22032008490d11200241017422082003200820034b1b22084100480d110240024020020d002008102821020c010b20072802f00120022008102c21020b2002450d04200720083602f401200720023602f00120072802f80121080b2007200841046a3602f801200220086a200936000020072802f801210820072802f0012102200741a0016a41186a22094200370300200741a0016a41106a22034200370300200741a0016a41086a22044200370300200742003703a00120022008200741a0016a1000200741c0006a41186a2009290300370300200741c0006a41106a2003290300370300200741c0006a41086a2004290300370300200720072903a001370340024020072802f401450d0020072802f001102a0b2015200a6b21152014200f6a2114410021082007410036027820074201370370200a200741f0006a10b4014100200728027822046b210a200728027421030340200420086a2109201120086a280200210d024002402003200a6a4104490d00200728027021020c010b200941046a22022009490d122003410174220e2002200e20024b1b220e4100480d120240024020030d00200e102821020c010b20072802702003200e102c21020b2002450d062007200e36027420072002360270200e21030b2007200941046a360278200220046a20086a200d360000200a417c6a210a200f200841046a2208470d000b200741c0006a41202002200420086a100702402003450d002002102a0b2011102a201641016a211620150d000b410021082012450d0e2013102a0c0e0b200f41041037000b411341011037000b200841011037000b200e41011037000b0240024020150d00200d102821130c010b20132015410274200d102c21130b2013450d03201321140b201420154102746a4100360200200a41016a210a201541016a21150b200920024d0d05200221082015200a4b0d000b41a0a3c100200a20151034000b200d41041037000b410441041037000b200841041037000b411341011037000b41cca2c100200841016a20091034000b0240200f450d002003102a0b410021080b0c020b1031000b200241046a280200450d002002280200102a0b2000200a3602042000200836020020074190026a24000b810f03037f017e097f23004190016b2202240002400240024002400240024002400240024002400240410e10282203450d00200341066a41002900b2a441370000200341002900aca4413700002003410e411c102c2203450d0120032001410676220436000e42002105200241f0006a41186a22064200370300200241f0006a41106a22074200370300200241f0006a41086a220842003703002002420037037020034112200241f0006a1000200241086a41186a2006290300370300200241086a41106a2007290300370300200241086a41086a2008290300370300200220022903703703082003102a20024100360238200241086a4120200241386a100621030240024020022802382207417f470d00410121060c010b024020030d00410121060c010b2002200736027420022003360270200241386a200241f0006a107420022802382206450d03200229023c21052007450d002003102a0b2001413f7122032005422088a722074f0d032006200341216c6a220341003a000020032002290038370001200341096a200241c0006a290000370000200341116a200241c8006a290000370000200341196a200241d0006a290000370000410e10282203450d04200341066a41002900b2a441370000200341002900aca4413700002003410e411c102c2203450d052003200436000e200241f0006a41186a22044200370300200241f0006a41106a22084200370300200241f0006a41086a220142003703002002420037037020034112200241f0006a1000200241086a41186a2004290300370300200241086a41106a2008290300370300200241086a41086a2001290300370300200220022903703703082003102a2002412036023c2002200241086a36023820062007200241386a10ab0202402005a7450d002006102a0b200241386a41086a220342003703002002420037033841ad91c6004112200241386a1008200120032903003703002002200229033837037020024100360238200241f0006a4110200241386a10062103417f2106024020022802382201417f460d002003450d0020014104490d07200328000021062003102a2006417f6a21060b200241386a41086a220442003703002002420037033841ad91c6004112200241386a1008200241f0006a41086a220720042903003703002002200229033837037020022006360238200241f0006a4110200241386a41041007200241386a41186a2208200041186a2209290000370300200241386a41106a220a200041106a220b2900003703002004200041086a220c2900003703002002410036025820022000290000370338200241286a200241386a10c10202402002280230450d0041012106034020082009290000370300200a200b2900003703002004200c29000037030020022006417f6a36025820022000290000370338411310282203450d0920034100290099a4413700002003410f6a41002800a8a441360000200341086a41002900a1a44137000020024293808080b00237026420022003360260200241386a200241e0006a108f012002280258210d0240024020022802642201200228026822036b4104490d00200228026021010c010b200341046a220e2003490d0c20014101742203200e2003200e4b1b22034100480d0c0240024020010d002003102821010c010b200228026020012003102c21010b2001450d0b2002200336026420022001360260200228026821030b2002200341046a360268200120036a200d3600002002280268210320022802602101200241f0006a41186a220d4200370300200241f0006a41106a220e4200370300200742003703002002420037037020012003200241f0006a1000200241086a41186a200d290300370300200241086a41106a200e290300370300200241086a41086a20072903003703002002200229037037030802402002280264450d002002280260102a0b200241086a412010090240200228022c450d002002280228102a0b20082009290000370300200a200b2900003703002004200c2900003703002002200029000037033820022006360258200641016a2106200241286a200241386a10c10220022802300d000b0b0240200228022c450d002002280228102a0b411310282203450d0a200341002900c2a3413700002003410f6a41002800d1a341360000200341086a41002900caa34137000020024293808080b00237023c200220033602382000200241386a108f012002280240210320022802382106200241f0006a41186a22014200370300200241f0006a41106a22004200370300200241f0006a41086a220442003703002002420037037020062003200241f0006a1000200241086a41186a2001290300370300200241086a41106a2000290300370300200241086a41086a2004290300370300200220022903703703080240200228023c450d002002280238102a0b200241086a4120100920024190016a24000f0b410e41011037000b411c41011037000b41c4d1c3004133200241e0006a419cd9c3001038000b41a0a3c100200320071034000b410e41011037000b411c41011037000b41c4d1c3004133200241e0006a419cd9c3001038000b411341011037000b200341011037000b1031000b411341011037000bd40201027f0240024002402002450d002002417f6a2104024020012d0000220241037122054103460d000240024020050e03040001040b2004450d0220012d0001410874200272220241ffff0371418002490d02200241fcff037141027621020c040b20044103490d0120012f0001200141036a2d000041107472410874200272220241808004490d01200241027621020c030b200241034b0d0020044104490d002001280001220241ffffffff034b0d020b200041013602000f0b200241027621020b0240200220036a220120024f0d00200041013602000f0b41012103410121050240200241c000490d0041022105200241808001490d00410441052002418080808004491b21050b0240200141c000490d0041022103200141808001490d00410441052001418080808004491b21030b20002001360204200041003602002000410c6a2003360200200041086a20053602000b130020004101360204200041f486c2003602000b3400200041f487c20036020420004100360200200041146a4107360200200041106a418488c200360200200041086a420f3702000b2201017f230041106b22022400200241003602002000200210da02200241106a24000bd60201037f0240024002400240024002400240024002400240024002400240024020012802000e0400010203000b41012102410110282201450d05200141003a0000410121030c040b410110282202450d05200241013a000020012802042103200241014105102c2202450d062002200336000120012802082104410a210320024105410a102c2201450d07200120043600050c020b41012102410110282201450d07200141023a0000410121030c020b410110282202450d07200241033a000020012802042103200241014105102c2202450d082002200336000120012802082104410a210320024105410a102c2201450d09200120043600050b410921020b2000200236020820002003360204200020013602000f0b410141011037000b410141011037000b410541011037000b410a41011037000b410141011037000b410141011037000b410541011037000b410a41011037000b130020004101360204200041cc92c2003602000b34002000419596c20036020420004100360200200041146a4107360200200041106a419c96c200360200200041086a42073702000b130020004101360204200041aca3c2003602000b890201057f230041106b22022400024002400240411110282203450d002002421137020420022003360200410d200210b4010240024020022802042204200228020822036b410d490d002003410d6a2105200228020021040c010b2003410d6a22052003490d03200441017422062005200620054b1b22064100480d030240024020040d002006102821040c010b200228020020042006102c21040b2004450d0220022006360204200220043602000b20022005360208200420036a22034100290082a542370000200341056a4100290087a54237000020002002290300370200200041086a2002280208360200200241106a24000f0b411141011037000b200641011037000b1031000bce04010b7f230041106b220324002003420037030820012002200341086a102720032003290308370300200120026a21040240024002400240200241086a220520024f0d00200341086a2106200321074100210841002105410121094100210a0340200841017421022006200741016a220b6b210c034020072d00002107024002400240024020082005470d00200c2105024002400240200a41ff01710e03010200010b200420016b21050c010b417f200c200420016b6a22052005200c491b21050b2008417f200541016a220d200d2005491b6a22052008490d0920022005200220054b1b22054100480d090240024020080d002005102821090c010b200920082005102c21090b2009450d010b200920086a20073a00000240024002400240200a41ff01710e03010300010b20042001460d010c050b0240200b2006460d004100210a0c040b20042001470d040b200841016a21080c070b4101210a200b2006470d01200841016a21080c060b200541011037000b200841016a2108200b21070c020b200841016a21084102210a200241026a21022001220741016a21010c000b0b0b4101210902402005450d0020054100480d03200510282209450d020b410021080340200920086a200320086a2d00003a0000200841016a22084108470d000b024020020d00410821080c010b200920086a210a410021080340200a20086a200120086a2d00003a00002002200841016a2208470d000b200420016b41086a21080b200020083602082000200536020420002009360200200341106a24000f0b200541011037000b1031000bc30401047f230041206b22022400024002400240024002400240410110282203450d00200320012d00003a0000200341014102102c2203450d01200320012d00013a0001200341024104102c2203450d02200320012d00023a0002200320012d00033a0003200341044108102c2203450d03200320012d00043a0004200320012d00053a0005200320012d00063a0006200320012d00073a0007200341084110102c2203450d04200320012d00083a0008200320012d00093a0009200320012d000a3a000a200320012d000b3a000b200320012d000c3a000c200320012d000d3a000d200320012d000e3a000e200320012d000f3a000f200341104120102c2203450d05200320012d00103a0010200320012d00113a0011200320012d00123a0012200320012d00133a0013200320012d00143a0014200320012d00153a0015200320012d00163a0016200320012d00173a0017200320012d00183a0018200320012d00193a0019200320012d001a3a001a200320012d001b3a001b200320012d001c3a001c200320012d001d3a001d200320012d001e3a001e200320012d001f3a001f200241186a22014200370300200241106a22044200370300200241086a22054200370300200242003703002003412020021000200041186a2001290300370000200041106a2004290300370000200041086a2005290300370000200020022903003700002003102a200241206a24000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000bd40201087f230041206b2203240020034100360208200342013703002001200310b401024002400240024020010d002003280208210420032802042105200328020021060c010b200141246c210720032802042105200328020821010340200341106a200010ec012003280210210802400240200520016b20032802182209490d00200120096a2104200328020021060c010b200120096a22042001490d04200541017422062004200620044b1b220a4100480d040240024020050d00200a102821060c010b20032802002005200a102c21060b2006450d032003200a36020420032006360200200a21050b20032004360208200620016a20082009109a051a02402003280214450d002008102a0b200041246a2100200421012007415c6a22070d000b0b2002280200200228020420062004100702402005450d002006102a0b200341206a24000f0b200a41011037000b1031000b130020004103360204200041a0a5c2003602000b340020004185acc20036020420004100360200200041146a4103360200200041106a4190acc200360200200041086a42083702000b130020004104360204200041a8b0c2003602000b0b00200041a0c21e10e6020b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200220013600000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180e1013600000b0b00200041d0860310e6020bdd0301047f230041d0026b2202240002400240024002400240411210282203450d00200341106a41002f008086423b0000200341086a41002900f88542370000200341002900f08542370000200341124124102c2203450d0120032001360012200241e8016a41186a22014200370300200241e8016a41106a22044200370300200241e8016a41086a22054200370300200242003703e80120034116200241e8016a1000200241e8006a41186a2001290300370300200241e8006a41106a2004290300370300200241e8006a41086a2005290300370300200220022903e8013703682003102a200241003602e801200241e8006a4120200241e8016a1006210120022802e8012203417f460d032002200336020c20022001360208200241e8016a200241086a10810220022903e8014201510d0220024188016a200241e8016a41086a41e000109a051a02402003450d002001102a0b200241086a20024188016a41e000109a051a200241e8016a200241086a41e000109a051a20004201370300200041086a200241e8016a41e000109a051a0c040b411241011037000b412441011037000b41c4d1c300413320024188016a419cd9c3001038000b200241e8016a200241086a41e000109a051a200042003703000b200241d0026a24000bc06709017f017e017f027e157f017e037f017e037f230041a0056b2201240010eb020240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020004101460d0042002102200141206a41086a2200420037030020014200370320418efcc5004110200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a100621000240024002400240024002400240024002400240024020012802e8032203417f460d002000450d0020034108490d01200029000021022000102a0b42002104200141206a41086a220042003703002001420037032041dffbc500410f200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034108490d02200029000021042000102a0b42002105200141206a41086a220042003703002001420037032041fefbc5004110200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034108490d03200029000021052000102a0b420020022005200442c8017e7c7d220420042002561b42c801540d0a200141206a41086a2200420037030020014200370320419499c6004114200141206a100820014188036a41086a2000290300370300200120012903203703880341002106200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034104490d04200028000021062000102a0b200141206a41086a220042003703002001420037032041a899c6004115200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a100621000240024020012802e8032203417f470d00410221070c010b024020000d00410221070c010b2003450d0520002d000021072000102a0b10fb01210820014188036a41086a22004200370300200142003703880341c2e1c000410d20014188036a1008200141e8036a41086a200029030037030020012001290388033703e80320014100360220200141e8036a4110200141206a100621000240024020012802202203417f460d002000450d00200120033602a401200120003602a001200141206a200141a0016a107c20012802202209450d07200129022421052003450d012000102a0c010b41012109420021050b200141206a41086a220042003703002001420037032041c785c2004112200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a100621000240024020012802e8032203417f460d002000450d002001200336022420012000360220200141e8036a200141206a106d20012802e803220a450d0820012902ec0321042003450d012000102a0c010b4101210a420021040b02402004422088a722000d004108210b4100210c4100210d0c0a0b2000410574210e200141e8036a41206a210f4100210c4100210d4108210b41002103200a2100034020014188026a41186a2210200041186a29000037030020014188026a41106a2211200041106a29000037030020014188026a41086a2212200041086a2900003703002001200029000037038802200141e8036a2008200310fc0120012802e803221320012802f00341014100410010032114024020012802ec03450d002013102a0b02402014417f470d00200141206a41186a22142010290300370300200141206a41106a22132011290300370300200141206a41086a221520122903003703002001200129038802370320200141e8036a200141206a10ec02200128028804450d09200141206a41286a2216200141e8036a41286a290300370300200141206a41206a2217200f2903003703002014200141e8036a41186a22182903003703002013200141e8036a41106a22192903003703002015200141e8036a41086a221a290300370300200120012903e8033703202018201029030037030020192011290300370300201a201229030037030020012001290388023703e803200f2001290320370300200f41086a2015290300370300200f41106a2013290300370300200f41186a2014290300370300200f41206a2017290300370300200f41286a20162903003703000240200c200d470d00200c41016a2214200c490d26200c41017422102014201020144b1b220dad42d0007e2202422088a70d262002a722144100480d2602400240200c0d0020141028210b0c010b200b200c41d0006c2014102c210b0b200b450d0b0b200b200c41d0006c6a200141e8036a41d000109a051a200c41016a210c0b200341016a2103200041206a2100200e41606a220e450d0a0c000b0b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b41f187c1004192021050000b201441081037000b02402004a7450d00200a102a0b02400240200c450d002001410036022820014201370320200141f8036a200c360200200141f4036a200d3602002001200b3602f003200120054220883e02ec03200120083602e803200141206a200141e8036a10c5012005a7450d012009102a0c010b02402005a7450d002009102a0b200d450d00200b102a0b200141206a41086a220042003703002001420037032041f5b6c2004112200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a1006210b024002400240024002400240024002400240024002400240024002400240024002400240024020012802e8032216417f460d00200b450d00200120163602ac022001200b3602a802200141086a200141a8026a106c20012802080d2b20012802ac02220f41807f712200417f4c0d14200128020c211202400240200f41077622140d00410121150c010b200010282215450d100b02402012450d00200141e8036a41206a2113200141a0016a41017221084100210c0340200141003a00c001200c41016a210e4100210002400240024002400340200f2000460d01200141a0016a20006a20012802a80222032d00003a00002001200341016a3602a8022001200041016a22033a00c0012003210020034120470d000b20014188026a41086a2200200141a0016a41086a29030037030020014188026a41106a2210200141a0016a41106a29030037030020014188026a41186a2211200141a0016a41186a290300370300200120012903a001370388022001200f20036b3602ac02200141a0016a200141a8026a10e80120012d00a0014101460d01200141e8036a41186a2011290300370300200141e8036a41106a2010290300370300200141e8036a41086a200029030037030020012001290388023703e8032013200841e000109a051a200141206a200141e8036a418001109a051a2014200c470d03200c4101742200200e2000200e4b1b221441ffffff0f712014470d322014410774220041004e0d020c320b200141003602ac02200041ff0171450d00200141003a00c0010b2014450d2f2015102a0c2f0b02400240200c0d002000102821150c010b2015200c4107742000102c21150b2015450d050b2015200c4107746a200141206a418001109a051a200e2012460d0120012802ac02210f200e210c0c000b0b2015450d2b2012ad42208621022014ad210402402016450d00200b102a0b2002200484211b0c010b410121154200211b0b4100210002400240201b422088a72218410774220c0d004101211c4100211d0c010b200c41027622031028221c450d0d201841ffffff0f71211d0b200741ff0171210e02402018450d002018410774210f201c210020152103034020002003290000370000200041186a200341186a290000370000200041106a200341106a290000370000200041086a200341086a290000370000200041206a210020034180016a2103200f41807f6a220f0d000b201841077441807f6a41077641016a21000b200e410247210f200141206a41086a220342003703002001420037032041c785c2004112200141206a100820014188036a41086a20032903003703002001200129032037038803200141003602f003200142013703e8032000200141e8036a10b40102402000450d0020004105742103201c210003402000200141e8036a108f01200041206a2100200341606a22030d000b0b2007200f71211a20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b0240201a450d00200141206a41086a220042003703002001420037032041bd99c600411a200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a1006210020012802e8032203417f460d002000450d002001200336022420012000360220200141e8036a200141206a10820120012802e803220f450d0c20012902ec03210202402003450d002000102a0b20014188036a411010092002a7450d00200f102a0b200141106a200641026a10ed02024002402001280210221e0d00200141206a41086a220042003703002001420037032041c785c2004112200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d002001200336022420012000360220200141e8036a200141206a106d20012802e803220d450d0d20012902ec03211f02402003450d002000102a0b410021200c020b410021204101210d4200211f0c010b410121202001290214211f201e210d0b200141206a41086a2200420037030020014200370320419499c6004114200141206a100820014188036a41086a20002903003703002001200129032037038803410121162001200641016a22063602e80320014188036a4110200141e8036a41041007200120203a001f20012015200c6a22073602ec04200120153602e8042001200141e8046a3602fc0420012001411f6a3602f8044100210e410021210240201f422088a722004105742203450d002003410575222141ffffff0f712021470d2b202141077422034100480d2b200310282216450d0a0b02402000450d002000410574210c200141206a410172210b200141e8036a41206a2108200141a8026a41c0006a2119200141a8026a41206a21174100210e20162114200d21000340200041086a2900002102200041106a29000021042000290000210520014188026a41186a2210200041186a29000037030020014188026a41106a2211200437030020014188026a41086a22122002370300200120053703880220014188056a20014188026a108b02200128029005210f2001280288052103200141003602202003200f200141206a1006210f0240024020012802202213417f460d00200f450d002001201336028c032001200f36028803200141206a20014188036a10e80120012d00204101460d0c200141a0016a200b41e000109a051a02402013450d00200f102a0b20014188036a200141a0016a41e000109a051a200141206a20014188036a41e000109a051a200141a0016a200141206a41e000109a051a4101210f0c010b200141206a20014188036a41e000109a051a4100210f0b0240200128028c05450d002003102a0b02400240200f0d00200141a8026a410041e0001099051a0c010b200141a8026a200141a0016a41e000109a051a0b024020012802f8042d00000d0020012802fc04220f2802002203200f280204460d00200f20034180016a36020002400240200141a8026a200341206a220f460d00200f200141a8026a4120109c050d010b02402017200341c0006a220f460d00200f20174120109c050d010b2019200341e0006a2203460d01200320194120109c05450d010b20012802f80441013a00000b200041206a2100200141e8036a41186a2010290300370300200141e8036a41106a2011290300370300200141e8036a41086a201229030037030020012001290388023703e8032008200141a8026a41e000109a051a200e41016a210e2014200141e8036a418001109a054180016a2114200c41606a220c0d000b0b0240201fa7450d00200d102a0b200e41ffffff0f71200e470d12200e4107742200417f4c0d1220012d001f21120240024020000d00410121110c010b200010282211450d080b410021000240200e450d002016200e4107746a2110200141e8036a41e0006a2103200141e8036a41c0006a210f200141e8036a41206a210c20112114201621000340200141e8036a41186a200041186a290000370300200141e8036a41106a200041106a290000370300200141e8036a41086a200041086a290000370300200120002900003703e803200c41186a200041386a290000370000200c41106a200041306a290000370000200c41086a200041286a290000370000200c200041206a290000370000200f41186a200041d8006a290000370000200f41106a200041d0006a290000370000200f41086a200041c8006a290000370000200f200041c0006a2900003700002003200041e0006a290000370000200341086a200041e8006a290000370000200341106a200041f0006a290000370000200341186a200041f8006a2900003700002014200141e8036a418001109a054180016a211420004180016a22002010470d000b200e41077441807f6a41077641016a21000b200141206a41086a220342003703002001420037032041f5b6c2004112200141206a100820014188036a41086a20032903003703002001200129032037038803200141003602f003200142013703e8032000200141e8036a10b40102402000450d00201120004107746a21032011210003402000200141e8036a108f01200041206a200141e8036a108f01200041c0006a200141e8036a108f01200041e0006a200141e8036a108f0120004180016a22002003470d000b0b20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b0240200e450d002011102a0b200120123a00e803200141206a41086a220042003703002001420037032041a899c6004115200141206a100820014188036a41086a2000290300370300200120012903203703880320014188036a4110200141e8036a41011007200120063602ec03200141043a00e80341014100200141e8036a10cc01410810282203450d0620032007360204200320153602000240201a0d0042002102200141206a41086a220042003703002001420037032041e194c600411c200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e803220f417f460d002000450d00200f4108490d07200029000021022000102a0b200141206a41086a2200420037030020014200370320419499c6004114200141206a100820014188036a41086a200029030037030020012001290320370388034100210f200141003602e80320014188036a4110200141e8036a10062100024020012802e803220c417f460d002000450d00200c4104490d062000280000210f2000102a0b411c10282200450d04200041186a41002800959546360000200041106a410029008d9546370000200041086a41002900859546370000200041002900fd94463700002000411c4138102c2200450d032000200237001c20014188026a41186a220c420037030020014188026a41106a2214420037030020014188026a41086a2210420037030020014200370388022000412420014188026a1000200141e8036a41186a200c290300370300200141e8036a41106a2014290300370300200141e8036a41086a201029030037030020012001290388023703e8032000102a2001200f360220200141e8036a4120200141206a410410072003102a0c110b024002402018450d00200320154180016a2210360200200120152900223701ea032001201529002a3701f20320014188026a41086a220020012903f003370300200120152900323701fa0320014188026a41106a220f20012903f8033703002001201528003a36018204200120152f003e3b01860420014188026a41186a220c200129038004370300200141003a008804200120152d00213a00e903200120152d00203a00e803200120012903e8033703880220014188036a41186a2214200c29030037030020014188036a41106a220c200f29030037030020014188036a41086a220f2000290300370300200120012903880237038803200141206a41186a22002014290300370300200141206a41106a2214200c290300370300200141206a41086a220c200f290300370300200120012903880337032020150d010b2003102a4108211241002110410021000c100b200141a0016a41186a2000290300370300200141a0016a41106a2014290300370300200141a0016a41086a200c290300370300200120012903203703a001200720106b41077641016a220041286c220f417f4c0d12200f10282212450d01201220012903a00137030020124201370320201241186a200141a0016a41186a220a290300370300201241106a200141a0016a41106a2209290300370300201241086a200141a0016a41086a222229030037030002402003280200220f2003280204220d470d00410121100c0f0b2003200f4180016a22063602002001200f2900223701ea032001200f29002a3701f20320014188026a41086a221320012903f0033703002001200f2900323701fa0320014188026a41106a220820012903f8033703002001200f28003a360182042001200f2f003e3b01860420014188026a41186a220b200129038004370300200141003a0088042001200f2d00213a00e9032001200f2d00203a00e803200120012903e8033703880220014188036a41186a220f200b29030037030020014188036a41106a220c200829030037030020014188036a41086a22142013290300370300200120012903880237038803200141206a41186a2217200f290300370300200141206a41106a2218200c290300370300200141206a41086a2219201429030037030020012001290388033703204102211041c80021110340200a2017290300220237030020092018290300220437030020222019290300220537030020012001290320221f3703a001200f2002370300200c2004370300201420053703002001201f3703880302400240024002402010417f6a2000460d002000211a0c010b200d20066b41077620006a41016a221a2000490d2e2000410174220d201a200d201a4b1b221aad42287e2202422088a70d2e2002a7220d4100480d2e0240024020000d00200d102821120c010b2012200041286c200d102c21120b2012450d010b201220116a220d41606a220020012903880337030020142903002102200c2903002104200f2903002105200d4201370300200041186a2005370300200041106a2004370300200041086a2002370300200328020022002003280204220d470d01201a21000c110b200d41081037000b200320004180016a2206360200200120002900223701ea032001200029002a3701f203201320012903f003370300200120002900323701fa03200820012903f8033703002001200028003a36018204200120002f003e3b018604200b200129038004370300200141003a008804200120002d00213a00e903200120002d00203a00e803200120012903e80337038802200f200b290300370300200c2008290300370300201420132903003703002001200129038802370388032017200f2903003703002018200c290300370300201920142903003703002001200129038803370320201141286a2111201041016a2110201a21000c000b0b200041011037000b200f41081037000b413841011037000b411c41011037000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b410841041037000b200041011037000b41c4d1c300413320014198056a419cd9c3001038000b200341011037000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b200341011037000b200041011037000b2003102a0b200141206a41086a220342003703002001420037032041d985c2004117200141206a100820014188036a41086a20032903003703002001200129032037038803200141e8036a20014188036a411010c6020240024020012802e8034101460d00200120103602f003200120003602ec03200120123602e803200141e8036a41004100200110ee020c010b20014188036a4110100920012902ec032102200120103602f003200120003602ec03200120123602e803200141e8036a2002a741012002422088a710ee020b42002102200141206a41086a220042003703002001420037032041e194c600411c200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034108490d04200029000021022000102a0b200141206a41086a220042003703002001420037032041e194c600411c200141206a100820014188036a41086a2203200029030037030020012001290320370388032001200242017c22023703e80320014188036a4110200141e8036a410810072000420037030020014200370320419499c6004114200141206a100820032000290300370300200120012903203703880341002103200141003602e80320014188036a4110200141e8036a10062100024020012802e803220f417f460d002000450d00200f4104490d05200028000021032000102a0b411c10282200450d05200041186a41002800959546360000200041106a410029008d9546370000200041086a41002900859546370000200041002900fd94463700002000411c4138102c2200450d062000200237001c20014188026a41186a220f420037030020014188026a41106a220c420037030020014188026a41086a2214420037030020014200370388022000412420014188026a1000200141e8036a41186a200f290300370300200141e8036a41106a200c290300370300200141e8036a41086a201429030037030020012001290388023703e8032000102a20012003360220200141e8036a4120200141206a410410070b410810282200450d062000200736020420002015360200410810282219450d0720192016200e4107746a221a3602042019201636020042002102200141206a41086a220342003703002001420037032041dffbc500410f200141206a100820014188036a41086a20032903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a10062103024020012802e803220f417f460d002003450d00200f4108490d09200329000021022003102a0b200242017c22042002540d09200141206a41086a220342003703002001420037032041dffbc500410f200141206a100820014188036a41086a220f20032903003703002001200129032037038803200120043703e80320014188036a4110200141e8036a41081007200141e8046a20004188b7c20010880120012802ec04211020012802e804211420012802f0042100200342003703002001420037032041eefbc5004110200141206a1008200f20032903003703002001200129032037038803200141003602f003200142013703e8032000200141e8036a10b40102402000450d002014200041286c6a210e2014210303402003200141e8036a108f01200341206a29030021020240024020012802ec03220f20012802f00322006b4108490d0020012802e803210f0c010b200041086a220c2000490d1c200f4101742200200c2000200c4b1b22004100480d1c02400240200f0d0020001028210f0c010b20012802e803200f2000102c210f0b200f450d0d200120003602ec032001200f3602e80320012802f00321000b2001200041086a3602f003200f20006a2002370000200e200341286a2203470d000b0b20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b02402010450d002014102a0b200442017c22022004540d0b200141206a41086a220042003703002001420037032041adfcc5004113200141206a100820014188036a41086a20002903003703002001200129032037038803200141e8036a20014188036a10ef0220012d00e803210020014188026a41186a220320014181046a29000037030020014188026a41106a220f200141f9036a29000037030020014188026a41086a220c200141f1036a290000370300200120012900e903370388020240024020004101460d00200141a0016a41186a4200370300200141a0016a41106a4200370300200141a0016a41086a4200370300200142003703a0010c010b200141a0016a41186a2003290300370300200141a0016a41106a200f290300370300200141a0016a41086a200c29030037030020012001290388023703a0010b200141206a41086a220042003703002001420037032041c0fcc5004111200141206a100820014188036a41086a2000290300370300200120012903203703880341002112200141003602e80320014188036a4110200141e8036a10062100024020012802e8032203417f460d002000450d0020034104490d0d200028000021122000102a0b200141206a41086a220042003703002001420037032041c0fcc5004111200141206a100820014188036a41086a20002903003703002001200129032037038803200141003602e80320014188036a4110200141e8036a41041007200141206a41186a200141a0016a41186a290300370300200141206a41106a200141a0016a41106a2903003703002000200141a0016a41086a290300370300200120012903a001370320417f201241016a220020002012491b410d74412872220b417f4c0d01200b10282208450d0d2008200129032037000020082002370020200841186a200141206a41186a290300370000200841106a200141206a41106a290300370000200841086a200141206a41086a2903003700004128211341002103410021004100211102400240024003400240024002400240024002402000450d00200f200c470d010b03402000210c200320124f0d02411610282200450d182000410e6a41002900dffc45370000200041086a41002900d9fc45370000200041002900d1fc4537000020004116412c102c2200450d192000200336001620014188026a41186a220f420037030020014188026a41106a220e420037030020014188026a41086a2214420037030020014200370388022000411a20014188026a100020014188036a41186a200f29030037030020014188036a41106a200e29030037030020014188036a41086a20142903003703002001200129038802370388032000102a200141003602a80220014188036a4120200141a8026a1006210e0240024020012802a802220f417f470d0041012100420021020c010b2001200f36028c022001200e36028802200141a8026a20014188026a107320012802a8022200450d1b20012902ac0221020240200f450d00200e102a0b20014188036a412010090b20002002422088a74105746a210f0240200c450d002010450d002011102a0b200341016a21032002a7211020002111200f2000460d000b200021112000210c0b200c41086a2900002102200c41106a2900002104200c2900002105200141e8036a41186a200c41186a290000221f370300200141e8036a41106a2004370300200141e8036a41086a2002370300200120053703e80320014188036a41186a2214201f37030020014188036a41106a2217200437030020014188036a41086a221820023703002001200537038803200b20136b411f4b0d03201341206a220e2013490d21200b410174220d200e200d200e4b1b220e4100480d21200b0d01200e102821080c020b0240200c450d002010450d002000102a0b20014188026a41186a2203420037030020014188026a41106a220f420037030020014188026a41086a220c420037030020014200370388022008201320014188026a1000200141e8036a41186a22142003290300370300200141e8036a41106a2210200f290300370300200141e8036a41086a2211200c29030037030020012001290388023703e8030240200b450d002008102a0b200141206a41086a220042003703002001420037032041adfcc5004113200141206a100820014188036a41086a220e2000290300370300200120012903203703880320014110360224200120014188036a360220200141e8036a200141206a10f002200141a8026a41186a200141a0016a41186a2903002202370300200141a8026a41106a200141a0016a41106a2903002204370300200141a8026a41086a200141a0016a41086a2903002205370300200120012903a001221f3703a8022014200237030020102004370300201120053703002001201f3703e8032000420037030020014200370320419efcc500410f200141206a1008200e2000290300370300200120012903203703880320014110360224200120014188036a360220200141e8036a200141206a10f002200141f8046a20194194b9c200108801200042003703002001420037032041adfcc5004113200141206a1008200e20002903003703002001200129032037038803200141e8036a20014188036a10ef0220012d00e8032100200320014181046a290000370300200f200141f9036a290000370300200c200141f1036a290000370300200120012900e9033703880220004101460d05200141a0036a420037030020014198036a420037030020014190036a420037030020014200370388030c060b2008200b200e102c21080b2008450d02200e210b0b200c41206a210c200820136a220e200129038803370000200e41186a2014290300370000200e41106a2017290300370000200e41086a2018290300370000201341206a21130c000b0b200e41011037000b20014188036a41186a20014188026a41186a29030037030020014188036a41106a20014188026a41106a29030037030020014188036a41086a20014188026a41086a2903003703002001200129038802370388030b200141206a41086a2200200141f8046a41086a280200360200200141206a41246a20014188036a41186a290300370200200141206a411c6a20014188036a41106a290300370200200141206a41146a20014188036a41086a290300370200200120012903f8042202370320200120012903880337022c20014194046a200141206a41286a280200360200200141e8036a41246a200141c0006a290300370200200141e8036a411c6a200141206a41186a290300370200200141e8036a41146a200141206a41106a290300370200200141f4036a220f2000290300370200200120023702ec03200141003602e803200141003602a801200142013703a001410110282200450d11200141013602a401200120012802a801220341016a3602a801200120003602a001200020036a41013a000020012802ec032103200f2802002200200141a0016a10b40102402000450d002003200041286c6a210e03402003200141a0016a108f01200341206a29030021020240024020012802a401220f20012802a80122006b4108490d0020012802a001210f0c010b200041086a220c2000490d1c200f4101742200200c2000200c4b1b22004100480d1c02400240200f0d0020001028210f0c010b20012802a001200f2000102c210f0b200f450d15200120003602a4012001200f3602a00120012802a80121000b2001200041086a3602a801200f20006a2002370000200e200341286a2203470d000b0b200141f8036a200141a0016a10f10220014193026a200141a0016a41086a280200360000200120012903a0012202370388052001200237008b02200141ac016a2001418f026a290000370000200141c28289aa043600a101200141023a00a00120012001290088023700a501200141a0016a10ce01024020012802e8030d00200141e8036a41086a280200450d0020012802ec03102a0b410810282203450d13200320073602042003201536020041081028220f450d14200f201a360204200f201636020010fb01210c411b10282200450d15200041176a41002800d89646360000200041106a41002900d19646370000200041086a41002900c99646370000200041002900c196463700002000411b4136102c2200450d162000200c36001b20014188026a41186a220c420037030020014188026a41106a220e420037030020014188026a41086a2214420037030020014200370388022000411f20014188026a100020014188036a41186a200c29030037030020014188036a41106a200e29030037030020014188036a41086a220c20142903003703002001200129038802370388032000102a20014188036a4120100e109801210e200141206a41086a2200420037030020014200370320419be1c0004111200141206a1008200c200029030037030020012001290320370388032001200e3602e80320014188036a4110200141e8036a41041007200141a0016a200341a0bbc200108301200042003703002001420037032041c2e1c000410d200141206a1008200c2000290300370300200120012903203703880320012802a001210c20012802a8012100200141003602f003200142013703e8032000200141e8036a10b40102402000450d0020004105742103200c210003402000200141e8036a108f01200041206a2100200341606a22030d000b0b20012802ec03210020014188036a411020012802e803220320012802f003100702402000450d002003102a0b024020012802a401450d00200c102a0b200f102a410810282200450d172000201a36020420002016360200200141a0016a200041acbdc200108301200141206a41086a2200420037030020014200370320419695c4004117200141206a1008200141e8036a41086a2000290300370300200120012903203703e80320012802a001210f20012802a801210020014100360228200142013703202000200141206a10b40102402000450d0020004105742103200f210003402000200141206a108f01200041206a2100200341606a22030d000b0b20012802242100200141e8036a4110200128022022032001280228100702402000450d002003102a0b024020012802a401450d00200f102a0b02402021450d002016102a0b02402020201e45720d002001280214450d00201e102a0b0240201d450d00201c102a0b201ba7450d002015102a0b200141a0056a24000f0b1036000b41c4d1c300413320014198056a419cd9c3001038000b41c4d1c300413320014198056a419cd9c3001038000b411c41011037000b413841011037000b410841041037000b410841041037000b41c4d1c300413320014198056a419cd9c3001038000b41c0c7c20041c9001050000b200041011037000b41c0c7c20041c9001050000b41c4d1c300413320014198056a419cd9c3001038000b200b41011037000b411641011037000b412c41011037000b41c4d1c300413320014198056a419cd9c3001038000b410141011037000b200041011037000b410841041037000b410841041037000b411b41011037000b413641011037000b410841041037000b41c4d1c300413320014198056a419cd9c3001038000b1031000bd11906047f017e037f027e027f037e23004190046b22002400200041e8036a41086a22014200370300200042003703e80341e7fcc5004110200041e8036a100820004188036a41086a2001290300370300200020002903e80337038803200041e0016a20004188036a109a03024002400240024002400240024020002d00e0014102470d00200041e0016a41086a22024200370300200042003703e00141b1f0c200410d200041e0016a100820012002290300370300200020002903e0013703e803200041003602e001200041e8036a4110200041e0016a1006210102400240024002400240024020002802e0012202417f460d002001450d002000200236027420002001360270200041e0016a200041f0006a107620002802e0012203450d0220002902e40121042002450d012001102a0c010b41042103420021040b20032004422088a7220541246c22066a2102200321010240200641ed00490d00200321010340024020012d00004101470d00200141016a2800002106200141086a28020021072000200141106a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b0240200141246a2d00004101470d00200141256a28000021062001412c6a28020021072000200141346a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b0240200141c8006a2d00004101470d00200141c9006a2800002106200141d0006a28020021072000200141d8006a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b0240200141ec006a2d00004101470d00200141ed006a2800002106200141f4006a28020021072000200141fc006a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c050b200220014190016a22016b41ec004b0d000b0b20012002460d012003200541246c6a21020340024020012d00004101470d00200141016a2800002106200141086a28020021072000200141106a28020036020c20002007360208200641c28289aa04470d00200041e0016a200041086a10ba0220002d00e00122074102460d00200041e0016a2101200041f0006a21020c040b2002200141246a2201460d020c000b0b41c4d1c3004133200041e8026a419cd9c3001038000b410221070c010b20002002200141016a41ef00109a0522012800003602602000200141036a28000036006320002900772108200041086a200041ff006a41d800109a051a20002900d70121090b02402005450d00200541246c21022003210103400240024020012d0000220641034b0d0002400240024020060e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012002415c6a22020d000b0b02402004a7450d002003102a0b200020002802603602682000200028006336006b200041f0006a200041086a41d800109a051a41002101024020074102460d00200020002802683602e0022000200028006b3600e302200020083703d802200041e0016a200041f0006a41d800109a051a200020093703d002200041e8036a41086a22014200370300200042003703e80341fefbc5004110200041e8036a100820004188036a41086a2001290300370300200020002903e80337038803200041003602a80320004188036a4110200041a8036a100621010240024020002802a8032202417f460d002001450d0020024108490d04200129000021042001102a200450450d010b200041d8026a200041d0026a20074101461b2903002104200041e8036a41086a22014200370300200042003703e80341fefbc5004110200041e8036a100820004188036a41086a22022001290300370300200020002903e80337038803200020043703a80320004188036a4110200041a8036a4108100720014200370300200042003703e80341eefbc5004110200041e8036a100820022001290300370300200020002903e8033703880341002101200041003602a80320004188036a4110200041a8036a100621060240024020002802a8032202417f470d000c010b200020023602ec03200020063602e803200041a8036a200041e8036a107720002802a8032201450d0520002902ac0321042002450d002006102a0b200041e8036a41086a22024200370300200042003703e803419efcc500410f200041e8036a100820004188036a41086a22062002290300370300200020002903e80337038803200041a8036a20004188036a10ef0220002d00a8032103200041e8036a41186a220a200041c1036a290000370300200041e8036a41106a220b200041b9036a2900003703002002200041b1036a290000370300200020002900a9033703e8032001410820011b21050240024020034101460d0020004188036a41186a420037030020004188036a41106a42003703002006420037030020004200370388030c010b20004188036a41186a200a29030037030020004188036a41106a200b29030037030020062002290300370300200020002903e803370388030b200041e8026a41086a20004188036a41086a2903002209370300200041e8026a41106a20004188036a41106a290300220c370300200041e8026a41186a20004188036a41186a290300220d3703002000200029038803220e3703e802200041a8036a41086a2004420020011b370300200041a8036a41106a220a200e370300200041a8036a41186a2009370300200041c8036a200c370300200041a8036a41286a200d370300200020053602ac03200041003602a803200041003602f003200042013703e803410110282201450d05200041013602ec03200020002802f003220241016a3602f003200020013602e803200120026a41013a000020002802ac032102200041a8036a410c6a2802002201200041e8036a10b40102402001450d002002200141286c6a210503402002200041e8036a108f01200241206a29030021040240024020002802ec03220620002802f00322016b4108490d0020002802e80321060c010b200141086a22032001490d0a200641017422012003200120034b1b22014100480d0a0240024020060d002001102821060c010b20002802e80320062001102c21060b2006450d09200020013602ec03200020063602e80320002802f00321010b2000200141086a3602f003200620016a20043700002005200241286a2202470d000b0b200a200041e8036a10f10220004193036a200041f0036a280200360000200020002903e80322043703d8032000200437008b03200041e8036a410c6a2000418f036a290000370000200041c28289aa043600e903200041023a00e80320002000290088033700ed03200041e8036a10ce0120002802a8030d0020002802b003450d0020002802ac03102a0b200041d8026a200041d0026a20074101461b2903002104200041e8036a41086a22014200370300200042003703e803418efcc5004110200041e8036a100820004188036a41086a2001290300370300200020002903e80337038803200020043703a80320004188036a4110200041a8036a410810074100210120070d00200041a8036a41086a200041e0016a41086a290300370300200041a8036a41106a200041e0016a41106a2d00003a0000200020002800e3023600eb02200020002802e0023602e802200020002903e0013703a803410121010b200041e0016a41086a2008370300200041e0016a41106a20002903a803370300200041f8016a200041a8036a41086a29030037030020004180026a200041a8036a41106a2d00003a0000200020013a00e001200020002802e8023600e101200020002800eb023600e401200041e8036a41086a22024200370300200042003703e80341e7fcc5004110200041e8036a100820004188036a41086a2002290300370300200020002903e80337038803410110282202450d0620004201370274200020023602700240024020010d0020004101360278200241003a00000c010b20004101360278200241013a0000200041e0016a410172200041f0006a10f1020b2000280274210120004188036a411020002802702202200028027810072001450d002002102a0b20004190046a24000f0b41c4d1c3004133200041e8026a419cd9c3001038000b41c4d1c3004133200041e8026a419cd9c3001038000b410141011037000b200141011037000b1031000b410141011037000bec0501057f23004190016b2202240002400240410f10282203450d00200341002900edae44370000200341076a41002900f4ae443700002002428f808080f001370214200220033602102001200241106a108f012002280218210320022802102101200241e0006a41186a22044200370300200241e0006a41106a22054200370300200241e0006a41086a220642003703002002420037036020012003200241e0006a1000200241306a41186a2004290300370300200241306a41106a2005290300370300200241306a41086a20062903003703002002200229036037033002402002280214450d002002280210102a0b20024100360260200241306a4120200241e0006a100621040240024020022802602201417f470d00410021030c010b2002200136025420022004360250200241e0006a200241d0006a10d4012002280280012203450d02200241106a41186a200241e0006a41186a290300370300200241106a41106a200241e0006a41106a290300370300200241106a41086a200241e0006a41086a290300370300200241086a2002418c016a2802003602002002200229036037031020022002290284013703002001450d002004102a0b200241e0006a41086a2201200241106a41086a290300370300200241e0006a41106a2204200241106a41106a290300370300200241e0006a41186a2205200241106a41186a290300370300200241d0006a41086a2206200241086a2802003602002002200229031037036020022002290300370350024002402003450d002000200229036037030020002003360220200041246a2002290350370200200041186a2005290300370300200041106a2004290300370300200041086a20012903003703002000412c6a20062802003602000c010b2000420037030020004208370320200041186a4200370300200041106a4200370300200041086a4200370300200041286a41003602000b20024190016a24000f0b410f41011037000b41c4d1c3004133200241106a419cd9c3001038000b84fc0111067f017e037f017e027f017e047f017e037f017e017f0a7e017f027e017f0a7e2a7f230041a0196b22022400200241e00e6a41086a22034200370300200242003703e00e41cd9cc6004123200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f41002104200241003602f011200241900f6a4110200241f0116a10062103024002400240024002400240024002400240024020022802f0112205417f460d002003450d0020054104490d01200328000021042003102a0b2001417f6a2106200241e00e6a41086a22034200370300200242003703e00e418e9dc6004110200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112201417f460d002003450d002001450d0220032d0000220141034f0d022003102a200141014b0d06024020010e020100010b200241e00e6a41086a22034200370300200242003703e00e418e9dc6004110200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241900f6a411010090c010b200620046b220320064b0d0520034106490d050b200241f0116a41086a22034200370300200242003703f01141c785c2004112200241f0116a1008200241e00e6a41086a2003290300370300200220022903f0113703e00e200241003602f011200241e00e6a4110200241f0116a1006210302400240024020022802f0112204417f460d002003450d00200220043602940f200220033602900f200241f0116a200241900f6a106d20022802f0112207450d0220022902f41121082004450d012003102a0c010b41012107420021080b410021090240024002402008422088a7220341057422010d004108210a4100210b0c010b2001410575220bad42d0007e220c422088a70d0c200ca722044100480d0c20041028220a450d010b2008a7210d02402003450d00200141606a210e200241f0116a41206a2103200a2105200721040340200441086a2900002108200441106a290000210c2004290000210f200241e00e6a41186a2210200441186a290000370300200241e00e6a41106a2211200c370300200241e00e6a41086a221220083703002002200f3703e00e200241900f6a200241e00e6a10ec02200241f0116a41186a2010290300370300200241f0116a41106a2011290300370300200241f0116a41086a2012290300370300200320022903900f370300200341086a200241900f6a41086a290300370300200341106a200241900f6a41106a290300370300200341186a200241900f6a41186a290300370300200341206a200241900f6a41206a290300370300200341286a200241900f6a41286a290300370300200220022903e00e3703f0112005200241f0116a41d000109a0541d0006a2105200441206a2104200141606a22010d000b200e41057641016a21090b0240200d450d002007102a0b200241e00e6a41086a22034200370300200242003703e00e41f09cc600411e200241e00e6a1008200241900f6a41086a22042003290300370300200220022903e00e3703900f200241f0116a200241900f6a10de030240024020022802f41122130d004104211342002114410021110c010b200241900f6a4110100920022802f011211120022903f81121140b10a003210820034200370300200242003703e00e41feadc4004117200241e00e6a100820042003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112204417f470d004200210c0c010b024020030d004200210c0c010b20044108490d012003290000210c2003102a0b200241e00e6a41086a22154200370300200242003703e00e41feadc4004117200241e00e6a1008200241900f6a41086a22162015290300370300200220022903e00e3703900f200220083703f011200241900f6a4110200241f0116a41081007410021172008200c7d2218500d0620154200370300200242003703e00e41a5afc4004116200241e00e6a100820162015290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112204417f460d002003450d00200220043602e40e200220033602e00e200241f0116a200241e00e6a106d20022802f0112219450d0220022902f411211a02402004450d002003102a0b201a422088a721040c010b410021044200211a410121190b4200210c200241e00e6a41086a22034200370300200242003703e00e4199fec4004111200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a1006210302400240024020022802f0112201417f470d004200210c4200211b0c010b024020030d004200211b0c010b20014110490d01200341086a290000211b2003290000210c2003102a0b200241800c6a10a102200241f00b6a20022903800c220f200241800c6a41086a2903002208428094ebdc03420010a005200241d00b6a200c201b2004ad4200109f05200241e00b6a20022903f00b221b200241f00b6a41086a290300221c4280ec94a37c427f109f052008200241d00b6a41086a290300221d20022903d00b221e200f56201d200856201d2008511b22031b2108200f201e20031b210c2018428086ebc7f5002018428086ebc7f500541b421f8042ffffffff0f83428094ebdc037e429880b5e50380211f200f20022903e00b7c210f410021034184c9c0002104024002400340024041accbc00020046b41184b0d000240200441accbc000460d000340200241c00b6a201b201c200435020022184200109f052003200c20022903c00b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241c00b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d0441accbc000200441086a2204470d000b0b200241b00b6a201b201c42e8aafa0b4200109f05200241b80b6a29030020022903b00b220c200f42e8aafa0b7e428094ebdc038042ffffffff0f837c2208200c54ad7c210c0c030b200241a00b6a201b201c200435020022184200109f052003200c20022903a00b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241a00b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d01200241900b6a201b201c200441086a35020022184200109f052003200c20022903900b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241900b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d01200241800b6a201b201c200441106a35020022184200109f052003200c20022903800b22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241800b6a41086a2903002018202054ad7c22205a200820205122011b6a2103200c201854200820205420011b0d01200241f00a6a201b201c200441186a35020022184200109f052003200c20022903f00a22202018200f7e428094ebdc038042ffffffff0f837c22185a2008200241f00a6a41086a2903002018202054ad7c22205a200820205122011b6a2103200441206a2104200c201854200820205420011b450d000b0b02402003417f6a220420034d0d00200241f0096a201b201c42c0f0f50b4200109f05200241f8096a29030020022903f009220c200f42288042ffffffff0f837c2208200c54ad7c210c0c010b02400240200441244b0d00200241e00a6a201b201c200441037422014184c9c0006a2802002205ad22184200109f05200241c00a6a200c20022903e00a22202018200f7e428094ebdc038042ffffffff0f837c2218200c2018562008200241e00a6a41086a2903002018202054ad7c22205620082020511b22041b22212018200c20041b220c7d22182008202020041b2020200820041b7d2021200c54ad7d4100200341037422104184c9c0006a280200220320056b2205200520034b1b22034101200341014b1bad2208420010a005200241b00a6a20022903c00a220c200241c00a6a41086a290300222020084200109f05200241d00a6a201b201c20014188c9c0006a2802002203ad22214200109f05200241800a6a2020420020104188c9c0006a28020022012003200120034b22051b2003200120051b6bad221b4200109f05200241a00a6a200c4200201b4200109f05200241900a6a42004200200c4200109f05427f427f200241a00a6a41086a290300220c20022903800a20022903900a7c7c221c20022903880a20022903980a84420052201c200c547222051b221c427f20022903a00a20051b220c201820022903b00a7d201b7e2008807c2208200c542205ad7c221b2005201b201c542008200c5a1b22051b211c427f200820051b211b200241d00a6a41086a29030020022903d00a22082021200f7e428094ebdc038042ffffffff0f837c220c200854ad7c21082004200120034d730d0142002008201c7d200c201b54ad7d220f200c201b7d221b200c56200f200856200f2008511b22031b210c4200201b20031b21080c020b41acd9c300200441251034000b427f2008201c7c200c201b7c220f200c542203ad7c220c2003200c200854200c2008511b22031b210c427f200f20031b21080b42002122200241e0096a2008200c428094ebdc03420010a005200241d0096a20022903e009220c200241e0096a41086a290300220f4280ec94a37c427f109f05200241c0096a200c200f201f4200109f05201f200820022903d0097c7e428094ebdc038021080240201a422088a722030d00420021230c080b20132014422088a74102746a210e201920034105746a2124200241c0096a41086a29030020022903c009220c200842ffffffff0f837c2225200c54ad7c2126200241f0116a41086a2127200241900f6a41086a21122011ad21284200212242002123201321052019211003402005200e460d08024020052802002203450d00024002400240024002402011450d00200241b0096a202520262028420010a005200241a0096a20022903b0092208200241b0096a41086a290300220c20284200109f0520024190096a2008200c20112003200320114b1bad220f4200109f05202520022903a0097d200f7e2028802108200229039009210f20024190096a41086a290300211c411210282203450d01200341002900c1ae44370000200341106a41002f00d1ae443b0000200341086a41002900c9ae4437000020024292808080a0023702f411200220033602f0112010200241f0116a108f0120022802f811210320022802f0112104200241900c6a41186a22014200370300200241900c6a41106a22074200370300200241900c6a41086a220d4200370300200242003703900c20042003200241900c6a1000200241c00d6a41186a2001290300370300200241c00d6a41106a2007290300370300200241c00d6a41086a200d290300370300200220022903900c3703c00d024020022802f411450d0020022802f011102a0b200241003602f011200241c00d6a4120200241f0116a1006210320022802f0112204417f460d032003450d03200220043602f411200220033602f011200241f8086a200241f0116a109f0120022903f808a70d02200241f8086a41106a290300210c200229038009211b2004450d042003102a0c040b41acfec4001032000b411241011037000b41c4d1c300413320024198196a419cd9c3001038000b4200211b4200210c0b0240024002400240024002400240200f200842ffffffff0f837c2208201b2008201b200854200c201c2008200f54ad7c220f54200c200f511b22031b22297d222a200f200c200f20031b222b7d2008202954ad7d222c8450450d004200211f4200211c420021084200210c0c010b200241f0116a201010ec0220272903002208420020022903f011220c42015620084200522008501b22031b2108200c420120031b210f20022802901221070240024020022802981222030d004200211f200241f0076a200f2008428094ebdc03420010a005200241f0076a41086a290300212d20022903f007212e4200211c0c010b2007200341306c6a21014200211f200241e8086a200f2008428094ebdc03420010a005200241c8086a202a202c428094ebdc03420010a005200241d8086a202a202c428094ebdc03420010a105200241e8086a41086a290300222d420020022903e808222e420156202d420052202d501b22031b2118202e420120031b2120200241c8086a41086a290300212f20022903c808213020022903d80821314200211c200721030340200241b8086a200f2003290300220c200c200f56200341086a290300220c200856200c2008511b22041b2008200c20041b2020201810a00520022903b808221b428080808010544100200241b8086a41086a290300501b450d03200241a8086a200f20082020201810a00520022903a808220c428080808010544100200241a8086a41086a290300501b450d04024002400240200ca7450d0020024180086a2030202f201b42ffffffff0f83428094ebdc037e200c42ffffffff0f838042ffffffff0f83220c4200109f0520024190086a200341106a2203200229038008221b200c20317e428094ebdc038042ffffffff0f837c220c20024180086a41086a290300200c201b54ad7c10b404200229039008210c200229039808211b200241900f6a41106a20024190086a41106a29030022213703002002201b3703980f2002200c3703900f0240200ca74101470d00427f201c20217c201f201b7c221b201f542204ad7c220c2004200c201c54200c201c511b22041b211c427f201b20041b211f0c030b200c4201510d010c020b41acaac3001032000b200220123602e00e200241e00e6a109c010b200341206a22032001470d000b0b200241e0076a200f200229038012220c200c200f56200241f0116a41186a290300220c200856200c2008511b22031b2008200c20031b202e4201202e420156202d420052202d501b22031b220c202d420020031b221b10a00520022903e0072218428080808010544100200241e0076a41086a290300501b450d01200241d0076a200f2008200c201b10a00520022903d0072208428080808010544100200241d0076a41086a290300501b450d022008a7450d03200241c0076a202a202c428094ebdc03420010a005200241b0076a20022903c007220c200241c0076a41086a290300220f4280ec94a37c427f109f05200241a0076a200c200f201842ffffffff0f83428094ebdc037e200842ffffffff0f838042ffffffff0f8322084200109f0520022903a007220c2008202a20022903b0077c7e428094ebdc038042ffffffff0f837c2208200c54ad210c200241a0076a41086a290300210f0240200228029412450d002007102a0b200f200c7c210c0b20024188076a2010200820297c220f200c202b7c200f200854ad7c10b4042002290388072108200229039007210c200241f0116a41106a20024188076a41106a290300220f3703002002200c3703f811200220083703f01102402008a74101470d00427f201c200f7c201f200c7c220c201f542203ad7c220820032008201c542008201c511b22031b211c427f200c20031b211f0c050b20084201510d030c040b10d101000b10d201000b41acaac3001032000b200220273602900f200241900f6a109c010b427f2023201c7c2022201f7c220c2022542203ad7c22082003200820235420082023511b22031b2123427f200c20031b21220b200541046a2105201041206a22102024470d000c080b0b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b200441081037000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b02402014a7450d002013102a0b20024188126a202337030020024180126a2022370300200241f8116a41003a0000200241033a00f0114101211741014100200241f0116a10cc01200220233703f811200220223703f0112002200241f0116a3602900f200241900f6a109c0102402022202384500d00201e201d84500d00200241f8066a10a10220022903f8062208201e7d220f200856200241f8066a41086a290300220c201d7d2008201e54ad7d2208200c562008200c511b0d00200241e8066a200f2008201e201d10a005200241b8066a200241e8066a41086a2903002208420020224200109f05200241c8066a2023420020022903e806220c4200109f05200241d8066a200c420020224200109f05200842005220234200527120022903c0064200527220022903d00642005272200241d8066a41086a290300220820022903b80620022903c8067c7c220f200854720d0020022903d806211b200241e00e6a41086a22034200370300200242003703e00e41ace1c0004116200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a100621030240024020022802f0112204417f460d002003450d00024020044110490d00200341086a290000210c200329000021082003102a0c020b41c4d1c300413320024198196a419cd9c3001038000b420021084200210c0b200241e00e6a41086a22034200370300200242003703e00e41ace1c0004116200241e00e6a1008200241900f6a41086a22042003290300370300200220022903e00e3703900f2002427f200c200f7c2008201b7c22182008542203ad7c221c2003201c200c54201c200c511b22031b3703f8112002427f201820031b3703f011200241900f6a4110200241f0116a41101007200241f0116a10d301200241a8066a200241f0116a2008427f85201b20031b2208200c427f85200f20031b220c10d001200241900f6a41106a200c200241a8066a41086a290300221b7d200820022903a806220f54ad7d201b200c7d200f200854ad7d200f200858201b200c58201b200c5122031b22011b37030020022008200f7d200f20087d20011b3703980f2002200f200856201b200c5620031b2203ad3703900f024020030d00200220043602e00e200241e00e6a109d010c010b200220043602e00e200241e00e6a109c010b201aa7450d002019102a0b20154200370300200242003703e00e41bb9cc6004112200241e00e6a100820162015290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022802f0112204417f470d00410021270c010b024020030d00410021270c010b20044104490d01200328000021272003102a0b200241e00e6a41086a22034200370300200242003703e00e41bb9cc6004112200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f2002202741016a22163602f011200241900f6a4110200241f0116a41041007411710282203450d012003410f6a41002900d3fe44370000200341086a41002900ccfe44370000200341002900c4fe4437000020034117412e102c2203450d0220032027360017200241900c6a41186a22044200370300200241900c6a41106a22014200370300200241900c6a41086a22054200370300200242003703900c2003411b200241900c6a1000200241c00d6a41186a2004290300370300200241c00d6a41106a2001290300370300200241c00d6a41086a2005290300370300200220022903900c3703c00d2003102a200241c00d6a41201009200241e00e6a41086a22034200370300200242003703e00e41cd9cc6004123200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024020022802f0112204417f460d002003450d00200441034d0d042003102a0b200241e00e6a41086a22154200370300200242003703e00e41cd9cc6004123200241e00e6a1008200241900f6a41086a22192015290300370300200220022903e00e3703900f200220063602f011200241900f6a4110200241f0116a41041007201641a105490d0920154200370300200242003703e00e41b99dc6004112200241e00e6a100820192015290300370300200220022903e00e3703900f41002112200241003602f011200241900f6a4110200241f0116a100621320240024020022802f0112233417f470d000c010b024020320d000c010b200220333602f411200220323602f011200241a0066a200241f0116a106c20022802a0060d2e20022802f41122104178712203417f4c0d2020022802a406210e02400240201041037622070d00410421120c010b200310282212450d060b0240200e450d004100211141002105410021010340200241003602e00e02400240024020104104490d0020022010417c6a22103602f411200220022802f011220341046a3602f0112003280000210d200241003602e00e20104104490d00200141016a210420022010417c6a22103602f4112002200341086a3602f0112003280004210320012007470d0220112004201120044b1b220741ffffffff01712007470d342007410374222441004e0d010c340b2007450d322012102a0c320b0240024020010d002024102821120c010b201220052024102c21120b2012450d090b201220056a2201200d360200200141046a2003360200201141026a2111200541086a210520042101200e2004470d000b0b2012450d2e200ead4220862007ad8421082033450d002032102a0b2012410420121b210e02402008420020121b2208422088220ca722032008a7470d00200341016a22042003490d2f200ca722054101742201200420042001491b220441ffffffff01712004470d2f200441037422014100480d2f0240024020030d0020011028210e0c010b200e20054103742001102c210e0b200e450d072008422088a721032004ad21080b202741e17a6a2104200e20034103746a2201200636020420012016360200200e200341016a22114103746a2110410021030240201141044f0d00200e21010c080b200e2105024003402005220128020020044f0d0a0240200141086a2802002004490d00200341016a21030c0b0b0240200141106a2802002004490d00200341026a21030c0b0b200141186a28020020044f0d01200341046a21032010200141206a22056b41184b0d000b200141206a21010c080b200341036a21030c080b41c4d1c300413320024198196a419cd9c3001038000b411741011037000b412e41011037000b41c4d1c300413320024198196a419cd9c3001038000b200341041037000b202441041037000b200141041037000b20012010460d00200e20114103746a21050340200128020020044f0d01200341016a21032005200141086a2201470d000b0b20112003490d01200842ffffffff0f8321080240201120036b2207450d0002402003450d00200e200e20034103746a2007410374109b051a0b200e280204210d200241e00e6a41086a22124200370300200242003703e00e418199c6004113200241e00e6a1008200241900f6a41086a22242012290300370300200220022903e00e3703900f200241f0116a200241900f6a411010c6024101210320022902f411210c0240024020022802f01122044101460d00200441014621030c010b200c422088a72206200d200d20064b1b2211200ca72204490d000240201120044d0d000340411a10282203450d06200341186a41002f00e0bb403b0000200341106a41002900d8bb40370000200341086a41002900d0bb40370000200341002900c8bb403700002003411a4134102c2203450d072003200436001a200241900c6a41186a22014200370300200241900c6a41106a22054200370300200241900c6a41086a22104200370300200242003703900c2003411e200241900c6a1000200241b00c6a41186a2001290300370300200241b00c6a41106a2005290300370300200241b00c6a41086a2010290300370300200220022903900c3703b00c2003102a200241b00c6a41201009200441016a2203210420112003470d000b0b200d2006492103200c428080808070832011ad84210c0b20124200370300200242003703e00e418199c6004113200241e00e6a100820242012290300370300200220022903e00e3703900f0240024020030d00200241900f6a411010090c010b410810282203450d062003200c422088a73600042003200ca7360000200241900f6a41102003410810072003102a0b20082007ad4220868421080b200241e00e6a41086a22034200370300200242003703e00e41b99dc6004112200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f0240200e0d00200241900f6a411010090c010b200241003602f811200242013703f0112008422088a72203200241f0116a10b4010240024020030d0020022802f811210320022802f411210120022802f01121040c010b200e20034103746a2106410020022802f81122116b210520022802f4112101410021030340201120036a2110200e20036a2212280200210702400240200120056a4104490d0020022802f01121040c010b201041046a22042010490d282001410174220d2004200d20044b1b220d4100480d280240024020010d00200d102821040c010b20022802f0112001200d102c21040b2004450d082002200d3602f411200220043602f011200d21010b2002201041046a220d3602f811200420116a20036a2007360000201241046a28020021070240200120056a417c6a41034b0d00200d41046a2224200d490d282001410174220d2024200d20244b1b220d4100480d280240024020010d00200d102821040c010b20042001200d102c21040b2004450d092002200d3602f411200220043602f011200d21010b2002201041086a3602f811200420116a20036a41046a2007360000200541786a2105200341086a2103201241086a2006470d000b201120036a21030b2008a72105200241900f6a411020042003100702402001450d002004102a0b2005450d00200e102a0b20154200370300200242003703e00e41889cc6004116200241e00e6a100820192015290300370300200220022903e00e3703900f41002134200241003602f011200241900f6a4110200241f0116a10062103024020022802f0112204417f460d002003450d0020044104490d07200328000021342003102a0b200241e00e6a41086a22034200370300200242003703e00e419e9cc600411d200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024002400240024020022802f0112204417f460d0020030d010b410421040c010b20044104490d09200328000021042003102a41012115200441014d0d010b200421150b200241900c6a41186a22034200370300200241900c6a41106a22044200370300200241900c6a41086a22014200370300200242003703900c41d3aec400411a200241900c6a1000200241f0116a41186a2003290300370300200241f0116a41106a2004290300370300200241f0116a41086a2001290300370300200220022903900c3703f011200241900e6a200241f0116a412010fd01200241e00e6a41206a200241900e6a41206a2d00003a0000200241e00e6a41186a200241900e6a41186a290300370300200241e00e6a41106a200241900e6a41106a290300370300200241e00e6a41086a200241900e6a41086a290300370300200220022903900e3703e00e200241f0116a200241e00e6a10ab010240024020022903f0114201510d004101211141002105410021060c010b200220022f01f8113b01e00c2002200229008b123703d00c2002200241fa116a2d00003a00e20c2002200241f0116a41206a2900003700d50c200241fb116a2800002103200241ff116a280000210420024183126a280000210120024187126a2800002105412010282211450d09201120022f01e00c3b00002011200536000f2011200136000b2011200436000720112003360003201120022903d00c370013201141026a20022d00e20c3a0000201141186a20022900d50c370000200241900f6a41206a200241e00e6a41206a2d00003a0000200241900f6a41186a200241e00e6a41186a290300370300200241900f6a41106a200241e00e6a41106a290300370300200241900f6a41086a200241e00e6a41086a290300370300200220022903e00e3703900f200241f0116a200241900f6a10ab0141012105024020022903f0114201510d00410121060c010b200241f0116a41086a2103410221104120210141012105410121060340200241b00c6a41186a200341186a2903002208370300200241b00c6a41106a200341106a290300220c370300200241b00c6a41086a200341086a290300220f37030020022003290300221b3703b00c200241900c6a41186a22122008370300200241900c6a41106a2207200c370300200241900c6a41086a220d200f3703002002201b3703900c024020052006470d00200541016a22042005490d2720102004201020044b1b220641ffffff3f712006470d27200641057422044100480d270240024020050d002004102821110c010b201120012004102c21110b2011450d110b201120016a220420022903900c370000200441186a2012290300370000200441106a2007290300370000200441086a200d290300370000201041026a2110200141206a2101200541016a2105200241f0116a200241900f6a10ab0120022903f0114201510d000b0b200241900c6a41186a22034200370300200241900c6a41106a22044200370300200241900c6a41086a22014200370300200242003703900c41a7aec400411a200241900c6a1000200241f0116a41186a2003290300370300200241f0116a41106a2004290300370300200241f0116a41086a2001290300370300200220022903900c3703f011200241e00d6a200241f0116a412010fd01200241900e6a41206a200241e00d6a41206a2d00003a0000200241900e6a41186a200241e00d6a41186a290300370300200241900e6a41106a200241e00d6a41106a290300370300200241900e6a41086a200241e00d6a41086a290300370300200220022903e00d3703900e200241f0116a200241900e6a10ad01024002402002280290120d004104213541002104410021360c010b412c10282235450d0a203520022903f011370200203541286a200241f0116a41286a2212280200360200203541206a200241f0116a41206a2207290300370200203541186a200241f0116a41186a220d290300370200203541106a200241f0116a41106a220e290300370200203541086a200241f0116a41086a2224290300370200200241e00e6a41206a200241900e6a41206a2d00003a0000200241e00e6a41186a200241900e6a41186a290300370300200241e00e6a41106a200241900e6a41106a290300370300200241e00e6a41086a200241900e6a41086a290300370300200220022903900e3703e00e200241900f6a200241e00e6a10ad01024020022802b00f0d0041012104410121360c010b41022110412c2101410121044101213603402012200241900f6a41286a2802003602002007200241900f6a41206a290300370300200d200241900f6a41186a290300370300200e200241900f6a41106a2903003703002024200241900f6a41086a290300370300200220022903900f3703f011024020042036470d00200441016a22032004490d2720102003201020034b1b2236ad422c7e2208422088a70d272008a722034100480d270240024020040d002003102821350c010b203520012003102c21350b2035450d0d0b203520016a220320022903f011370200200341286a2012280200360200200341206a2007290300370200200341186a200d290300370200200341106a200e290300370200200341086a2024290300370200201041026a21102001412c6a2101200441016a2104200241900f6a200241e00e6a10ad0120022802b00f0d000b0b200242003702ec0c200241f8b9c0003602e80c200420056a2201ad42d0007e2208422088a70d152008a72203417f4c0d150240024020030d00410821100c010b200310282210450d0c0b200241003602c80e200220013602c40e200220103602c00e200241900e6a41206a200241e80c6a360200200241003602a80e200241a40e6a20024198196a36020020022011200541057422016a220d36029c0e200220113602980e200220063602940e200220113602900e2002200241c00e6a3602ac0e200220024198196a3602a00e410221244101210e0240024020050d00201121030c010b4200211b2011210302400340200341086a2900002108200341106a290000210c2003290000210f200241f0116a41186a2205200341186a290000370300200241f0116a41106a2210200c370300200241f0116a41086a221220083703002002200f3703f01120024190066a200241f0116a10b004200241b00c6a41086a22072012290300370300200241b00c6a41106a22122010290300370300200241b00c6a41186a22102005290300370300200220022903f0113703b00c20024190066a41086a290300210c200229039006210f20024180066a10a102200241f0056a20022903800620024180066a41086a290300427f420010a005200241e0056a200f200c20022903f005220842012008420156200241f0056a41086a29030022084200522008501b22051b2008420020051b10a005200241900c6a41086a2007290300370300200241900c6a41106a2012290300370300200241900c6a41186a2010290300370300200220022903b00c3703900c20022903e005220850450d01200341206a2103200141606a22010d000b2002200d3602980e200d21030c010b200220022f01900c3b01e00c200220022d00920c3a00e20c200220022900a30c3703d00c200220022800f80c3602b80d2002200341206a22033602980e2002200241a80c6a2900003700d50c2002200241fb0c6a2800003600bb0d20022800930c210120022800970c2112200228009b0c2110200228009f0c2105200220022d00e20c3a00a20d200220022f01e00c3b01a00d200220022900d50c3700f511200220022903d00c3703f011200220022800bb0d3600c30d200220022802b80d3602c00d200220022d00a20d3a00aa0d200220022f01a00d3b01a80d200220022900f5113700e50e200220022903f0113703e00e200220022800c30d3600b30d200220022802c00d3602b00d4100210e410021240b200220022f01a80d3b01c00d200220022d00aa0d3a00c20d200220022903e00e3703f011200220022900e50e3700f511200220022802b00d3602a00d200220022800b30d3600a30d024002400240200e450d00200241023a00d00f0c010b200220022d00c20d3a009a0d200220022f01c00d3b01980d200220022903f0113703e00d200220022900f5113700e50d200220022802a00d3602880d200220022800a30d36008b0d200241013602a80e200220022d009a0d3a00960d200220022f01980d3b01940d200220022900e50d3700d50e200220022903e00d3703d00e20024190126a201b37030020024188126a200837030020024180126a4200370300200241a7126a2005360000200241a3126a20103600002002419f126a20123600002002419b126a2001360000200242003703f811200242003703f01120024198126a20022f01940d3b01002002419a126a20022d00960d3a0000200241f0116a41c8006a20243a0000200241ab126a20022903d00e370000200241b0126a20022900d50e370000200241bc126a200228008b0d360000200241b9126a20022802880d360000200241900f6a200241ac0e6a200241f0116a10fb0220022d00d00f4102470d010b02402003200d460d002002200d20036b41606a41607120036a41206a3602980e0b410021372006450d142011102a0c140b41c80010282238450d0c2038200241900f6a41c800109a051a200241e00e6a41086a200241900e6a41086a2903002208370300200241e00e6a41206a200241900e6a41206a280200360200200241e00e6a41186a200241900e6a41186a290300370300200241e00e6a41106a200241900e6a41106a290300370300200220022903900e3703e00e410121102008a7220320022802ec0e2201460d10200241b9126a210e200241fc0e6a21274200211b02400340200341086a2900002108200341106a290000210c2003290000210f200241f0116a41186a2205200341186a290000370300200241f0116a41106a2211200c370300200241f0116a41086a221220083703002002200f3703f011200241d0056a200241f0116a10b004200241b00c6a41086a22072012290300370300200241b00c6a41106a22122011290300370300200241b00c6a41186a22112005290300370300200220022903f0113703b00c200241d0056a41086a290300210c20022903d005210f200241c0056a10a102200241b0056a20022903c005200241c0056a41086a290300427f420010a005200241a0056a200f200c20022903b005220842012008420156200241b0056a41086a29030022084200522008501b22051b2008420020051b10a005200241900c6a41086a2007290300370300200241900c6a41106a2012290300370300200241900c6a41186a2011290300370300200220022903b00c3703900c20022903a005220850450d012001200341206a2203470d000b200220013602e80e200121030c110b200220022f01900c3b01e00c200220022d00920c3a00e20c200220022900a30c3703d00c200220022800f80c3602b80d2002200341206a22033602e80e2002200241900c6a41186a220d2900003700d50c2002200241f80c6a41036a22392800003600bb0d20022800930c211120022800970c2112200228009b0c2107200228009f0c2116200220022d00e20c3a008a0d200220022f01e00c3b01880d200220022900d50c3700e50d200220022903d00c3703e00d200220022800bb0d3600b30d200220022802b80d3602b00d20024198126a2124200241a30c6a213a20022802f80e2105200241f0116a410472220641086a2133200641106a213b200241ab126a223c41056a213d41012110410121370340200220022d008a0d22193a00aa0d200220022f01880d22323b01a80d200220022903e00d3703c00d200220022900e50d3700c50d200220022802b00d3602a00d200220022800b30d3600a30d200220193a00960d200220323b01940d2002200541016a22193602f80e200220022900c50d3700d50e200220022903c00d3703d00e200241f0116a41206a201b3703002006420037020020334200370200203b41003602002002200837038812200220053602f011202420022f01940d3b0100202441026a20022d00960d3a0000200220163600a712200220073600a3122002201236009f122002201136009b12203c20022903d00e370000203d20022900d50e370000200241003a00b812200e41036a20022800a30d360000200e20022802a00d360000200241900f6a2027200241f0116a10fb02024020022d00d00f4102470d00203821110c140b200241f0116a200241900f6a41c800109a051a024020372010470d00201041016a22052010490d26201041017422112005201120054b1b2237ad42c8007e2208422088a70d262008a722054100480d260240024020100d002005102821380c010b2038201041c8006c2005102c21380b2038450d0f0b2038201041c8006c6a200241f0116a41c800109a051a201041016a2110024020032001470d00200121030c130b02400340200241f0116a41186a2205200341186a290000370300200241f0116a41106a2211200341106a290000370300200241f0116a41086a2212200341086a290000370300200220032900003703f01120024190056a200241f0116a10b004200241b00c6a41086a22072012290300370300200241b00c6a41106a22122011290300370300200241b00c6a41186a22112005290300370300200220022903f0113703b00c20024190056a41086a290300210c200229039005210f20024180056a10a1024200211b200241f0046a20022903800520024180056a41086a290300427f420010a005200241e0046a200f200c20022903f004220842012008420156200241f0046a41086a29030022084200522008501b22051b2008420020051b10a005200241900c6a41086a2007290300370300200241900c6a41106a2012290300370300200d2011290300370300200220022903b00c3703900c20022903e004220850450d012001200341206a2203460d120c000b0b200220022f01900c3b01e00c200220022d00920c3a00e20c200220022800f80c3602b80d2002200341206a22033602e80e2002203a2900003703d00c2002203a41056a2900003700d50c200220392800003600bb0d20022800930c211120022800970c2112200228009b0c2107200228009f0c2116200220022d00e20c3a008a0d200220022f01e00c3b01880d200220022900d50c3700e50d200220022903d00c3703e00d200220022800bb0d3600b30d200220022802b80d3602b00d201921050c000b0b41e4e8c5001032000b411a41011037000b413441011037000b410841011037000b200d41011037000b200d41011037000b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b412041011037000b412c41041037000b200341041037000b200341081037000b41c80041081037000b200541081037000b200441011037000b200220013602e80e200121030c010b410121370b20382111200241023a00d00f0b024020032001460d002002200120036b41606a41607120036a41206a3602e80e0b20022802e40e450d0120022802e00e102a0c010b4108213841082111410021100b0240024002400240024002400240024020102015490d000240024020022802c40e220320022802c80e223d6b2004412c6c2201412c6d2205490d0020022802c00e21030c010b203d20056a2205203d490d18200341017422122005201220054b1b2205ad42d0007e2208422088a70d182008a722124100480d180240024020030d002012102821030c010b20022802c00e200341d0006c2012102c21030b2003450d02200220053602c40e200220033602c00e20022802c80e213d0b203520016a213e024020040d002035213b0c070b2003203d41d0006c6a2133203521030340200241c00d6a41186a2204200341186a290200370300200241c00d6a41106a2201200341106a290200370300200241c00d6a41086a2205200341086a290200370300200220032902003703c00d2003412c6a213b2003280220223c450d07200341286a2802002124200341246a280200213a200241900f6a41186a22392004290300370300200241900f6a41106a223f2001290300370300200241900f6a41086a22402005290300370300200220022903c00d3703900f200241d0046a200241900f6a10b0042024ad42387e2208422088a70d092008a72203417f4c0d09200241d0046a41086a290300211c20022903d00421180240024020030d00410821150c010b200310282215450d040b0240024020240d0041002124410021060c010b203c20244105746a213241002106203c21070340200741086a2900002108200741106a290000210c2007290000210f200241f0116a41186a2227200741186a290000370300200241f0116a41106a2216200c370300200241f0116a41086a221920083703002002200f3703f011200741206a2107200241e80c6a210320022802ec0c210d024003402003280200221241086a210420122f0106220e4105742103410021010240024003402003450d01200241f0116a20044120109c052205450d02200341606a2103200141016a2101200441206a21042005417f4a0d000b2001417f6a210e0b200d450d02200d417f6a210d2012200e4102746a4194036a21030c010b0b2010201220014102746a41e8026a220328020022044d0d072011200441c8006c6a22042903102108200441186a290300210c200241c0046a10a102200241b0046a20022903c004200241c0046a41086a290300427f420010a0052010200328020022044d0d08200241a0046a2018201c20022903b004220f4201200f420156200241b0046a41086a290300220f420052200f501b22011b200f420020011b10a0052011200441c8006c6a220441186a427f200c200820022903a0047c220f2008542201ad7c221b2001201b200c54200f20085a1b22011b3703002004427f200f20011b370310200241900c6a41186a22042027290300370300200241900c6a41106a22012016290300370300200241900c6a41086a22052019290300370300200220022903f0113703900c200328020021120240024020062024460d00200621030c010b202441016a22032024490d1c2024410174220d2003200d20034b1b220dad42387e2208422088a70d1c2008a722034100480d1c0240024020240d002003102821150c010b2015202441386c2003102c21150b2015450d0a20242103200d21240b2015200341386c6a220342003703082003420037030020032012360210200320022903900c3702142003411c6a2005290300370200200341246a20012903003702002003412c6a2004290300370200200641016a21060b20072032470d000b0b0240203a450d00203c102a0b200241b00c6a41186a22032039290300370300200241b00c6a41106a2204203f290300370300200241b00c6a41086a22012040290300370300200220022903900f3703b00c20024190046a10a10220024180046a20022903900420024190046a41086a290300427f420010a005200241f0036a2018201c20022903800422084201200842015620024180046a41086a29030022084200522008501b22051b2008420020051b10a00520334200370308203320022903f00337030020334200370310203341186a4200370300203320063602282033202436022420332015360220203320022903b00c37022c203341346a20012903003702002033413c6a2004290300370200203341c4006a2003290300370200203d41016a213d203341d0006a2133203b2103203b203e470d000b2002203d3602c80e0c070b02402037450d002038102a0b024020022802c80e2203450d00200341d0006c210120022802c00e41206a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200141b07f6a22010d000b0b024020022802c40e450d0020022802c00e102a0b20022802e80c20022802ec0c20022802f00c10bc0202402004450d002004412c6c2104203541206a210303400240200341046a280200450d002003280200102a0b2003412c6a2103200441546a22040d000b0b2036450d0f2035102a0c0f0b201241081037000b200341081037000b41a09ec400200420101034000b41b09ec400200420101034000b200341081037000b2002203d3602c80e203b203e460d000340203b41206a2802002204450d01203b412c6a21030240203b41246a280200450d002004102a0b2003213b203e2003470d000b0b02402036450d002035102a0b2034ad42307e2208422088a70d002008a72203417f4c0d00024002400240024020030d00410821060c010b200310282206450d010b2034412c6c2203417f4c0d0202400240024020030d004104213f0c010b20031028223f450d010b4100213602402010203420102034491b223b0d0020342141410021390c030b2011201041c8006c22356a2127200241f0116a41106a2132200241f0116a41086a213320112103203421164100213941002119034002402010450d002035210403400240200341c0006a2d00000d00200241e0036a427f427f200341106a290300220842012008420156200341186a29030022084200522008501b22011b2008420020011b10a0052003200241e0036a41086a290300370308200320022903e0033703000b200341c8006a2103200441b87f6a22040d000b0b20022802c00e220520022802c80e220e41d0006c6a211502400240024002400240200e450d00200521120340024020122802282203450d00200341386c2101201228022041106a210303402010200328020022044d0d0402402011200441c8006c6a22042d00400d002004290310220c200441186a290300220f84500d00200241d0036a2012290300220842004280808080104200109f05200241a0036a4200420020084200109f05200241c0036a427f20022903d003201241086a290300220842ffffffff0f8320085220022903a80342005272200241d0036a41086a290300221b200842208620022903a0037c7c2208201b547222071b427f200820071b200c200f10a005200241b0036a201241146a350200201241186a290300220842208684200842208820022903c003200241c0036a41086a290300109f052004427f2004290300220820022903b0037c220c200c2008542207200441086a220d2903002208200241b0036a41086a2903007c2007ad7c220c200854200c2008511b22071b370300200d427f200c20071b3703000b200341386a2103200141486a22010d000b0b201241d0006a22122015470d000b0b201941016a21192011201041c8006c6a21122035210420112103024003402003210102400240201220036b41d8014d0d00200141c0006a2d00000d01200141c8006a21030c070b0340024020040d00201621410c0c0b200441b87f6a2104200141c0006a2107200141c8006a2203210120072d00000d000b200341b87f6a21010c060b20014188016a2d0000450d01200141d0016a2d0000450d03200441e07d6a2104200141a0026a210320014198026a2d00000d000b410321040c030b20014190016a2103410121040c020b41bcc0c200200420101034000b200141d8016a2103410221040b2001200441c8006c6a21010b024020032012460d00200141086a29030021082001290300210c0340200341c8006a21040240200341c0006a2d00000d00200341086a290300220f2008200c2003290300221b562008200f562008200f511b22121b2108201b200c20121b210c2003200120121b21010b2004210320272004470d000b0b200141013a00400240200e450d002001410c6a210d200141206a210e0340200541d0006a2124024020052802282204450d0020052802202103200441386c2104034002400240200d2003460d00200341146a200e4120109c050d010b200541186a22122903002108200141086a2207290300210c20032001290300220f2005290310221b7d3703002003200c20087d200f201b54ad7d3703082001290300210820122007290300370300200520083703100b200341386a2103200441486a22040d000b0b2024210520242015470d000b0b200129031021082032200141306a2900003703002033200141286a290000370300200141186a290300210c200241f0116a41186a2203200141386a290000370300200220012900203703f01102400240024020392016460d00201621410c010b201641016a22042016490d15201641017422012004200120044b1b2241ad42307e220f422088a70d15200fa722044100480d150240024020160d002004102821060c010b2006201641306c2004102c21060b2006450d0120162139204121160b2033290300210f2032290300211b2003290300211c20022903f01121182006203941306c6a2203200837032020032018370300200341286a200c370300200341186a201c370300200341106a201b370300200341086a200f370300203941016a2139201121032019203b4f0d040c010b0b200441081037000b200341041037000b200341081037000b024020022802c80e2203450d0020022802c00e2235200341d0006c6a2140200641e0006a213b2006203941306c22036a210d200241900e6a41186a213c200241900e6a41106a213d200241900e6a41086a213a20034191014921334100213602400340203c203541c4006a290000370300203d2035413c6a290000370300203a203541346a2900003703002002203529002c3703900e024020352802282203450d0020352802202204200341386c6a21322035412c6a211641002127410821194100211503402006210302400240024020330d00203b2103024002400240200441146a2201200241f0116a46220e450d0020062903202108200641086a290300210c200641106a290300210f200641186a290300211b2006290300211c200241f0116a41286a200641286a290300370300200241f0116a41186a201b370300200241f0116a41106a200f370300200241f0116a41086a200c37030020022008370390122002201c3703f0110c010b024002400340200341406a22102903002108200341a07f6a2205290300210c200541086a290300210f200541106a290300211b200541186a290300211c200241f0116a41286a2205201041086a290300370300200241f0116a41186a2210201c370300200241f0116a41106a2211201b370300200241f0116a41086a2212200f37030020022008370390122002200c3703f011200241f0116a20014120109c05450d03200341706a22242903002108200341506a2207290300210c200741086a290300210f200741106a290300211b200741186a290300211c2005202441086a2903003703002010201c3703002011201b3703002012200f37030020022008370390122002200c3703f0110240200e0d00200241f0116a20014120109c05450d00200341206a2903002108200341086a290300210c200341106a290300210f200341186a290300211b2003290300211c2005200341286a2903003703002010201b3703002011200f3703002012200c37030020022008370390122002201c3703f011200e0d03200241f0116a20014120109c05450d03200341d0006a2903002108200341306a290300210c200341386a290300210f200341c0006a290300211b200341c8006a290300211c2005200341d8006a2903003703002010201c3703002011201b3703002012200f37030020022008370390122002200c3703f011200e0d02200241f0116a20014120109c05450d02200341e0006a2105200341c0016a2103200d20056b4190014d0d050c010b0b200241900f6a41286a2005290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a2010290300370300200241900f6a41106a2011290300370300200241900f6a41086a2012290300370300200220022903f0113703900f0c050b200241900f6a41286a2005290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a2010290300370300200241900f6a41106a2011290300370300200241900f6a41086a2012290300370300200220022903f0113703900f0c040b200241900f6a41286a2005290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a2010290300370300200241900f6a41106a2011290300370300200241900f6a41086a2012290300370300200220022903f0113703900f0c030b200241900f6a41286a200241f0116a41286a290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a200241f0116a41186a290300370300200241900f6a41106a200241f0116a41106a290300370300200241900f6a41086a200241f0116a41086a290300370300200220022903f0113703900f0c020b200341a07f6a21030b2003200d460d0102400240200441146a2201200241f0116a470d0020032903202108200341086a290300210c200341106a290300210f200341186a290300211b2003290300211c200241f0116a41286a200341286a290300370300200241f0116a41186a201b370300200241f0116a41106a200f370300200241f0116a41086a200c37030020022008370390122002201c3703f0110c010b0340200341206a2903002108200341086a290300210c200341106a290300210f200341186a290300211b2003290300211c200241f0116a41286a200341286a290300370300200241f0116a41186a201b370300200241f0116a41106a200f370300200241f0116a41086a200c37030020022008370390122002201c3703f011200241f0116a20014120109c05450d01200d200341306a2203470d000c030b0b200241900f6a41286a200241f0116a41286a290300370300200241900f6a41206a200241f0116a41206a290300370300200241900f6a41186a200241f0116a41186a290300370300200241900f6a41106a200241f0116a41106a290300370300200241900f6a41086a200241f0116a41086a290300370300200220022903f0113703900f0b200241e00e6a41286a200241900f6a41286a2903002208370300200241e00e6a41206a200241900f6a41206a290300220c370300200241e00e6a41186a200241900f6a41186a290300220f370300200241e00e6a41106a200241900f6a41106a290300221b370300200241e00e6a41086a200241900f6a41086a290300221c370300200220022903900f22183703e00e200241f0116a41286a2008370300200241f0116a41206a200c370300200241f0116a41186a200f370300200241f0116a41106a201b370300200241f0116a41086a201c370300200220183703f011200241f0116a2016460d00200241f0116a20164120109c05450d00024002402035290310221b2004290300220c85203541186a290300220f200441086a2903002208858450450d0042002108428080808010210c0c010b20024190036a200c42004280808080104200109f0520024180036a42004200200c4200109f050240200842ffffffff0f832008522002290388034200527220024190036a41086a290300221c20084220862002290380037c7c2218201c54724101470d000240201b422088200f42208684221b200f422088220f84500d00200241e0026a200c2008201b200f10a005200241e0026a41086a290300210820022903e002210c0c020b41dcc0c2001032000b200241f0026a2002290390032018201b4201201b420156200f420052200f501b22031b200f420020031b10a005200241f0026a41086a290300210820022903f002210c0b200220042f00143b01a00d2002200441166a2d00003a00a20d2002200441276a2900003703f80c20022004412c6a2900003700fd0c200441236a28000021012004411f6a28000021052004411b6a2800002110200441176a280000211102400240024020152027460d00201521030c010b202741016a22032027490d17202741017422122003201220034b1b2212ad42307e220f422088a70d17200fa722034100480d170240024020270d002003102821190c010b2019202741306c2003102c21190b2019450d0120272103201221270b20022d00a20d211220022f01a00d21072019200341306c6a2203200136000f2003200536000b2003201036000720032011360003200320073b0100200341026a20123a00002003200c370320200341286a2008370300200320022903f80c370013200341186a20022900fd0c370000201541016a21150c010b200341081037000b200441386a22042032470d000b024020150d002027450d012019102a0c010b02400240201541306c22040d00420021084200210c0c010b201941206a2103420021084200210c0340200341086a290300200c7c2003290300220c20087c2208200c54ad7c210c200341306a2103200441506a22040d000b0b200241d0026a420042808080801020087d220f200f428080808010564200200c200842808080801056ad7c7d22084200522008501b22031b221c4200200820031b22082015ad2218420010a00520022903d002210f0240201c20185441002008501b0d00200241d0026a41086a290300211b2015417f6a2110201941206a21034100210403402003427f20032903002208200f7c220c200c2008542201200341086a22052903002208201b7c2001ad7c220c200854200c2008511b22011b3703002005427f200c20011b37030020102004460d01200341306a21032015200441016a22044b0d000b41ccc0c200200420151034000b200241c0026a200f200820182008109f050240201c20022903c0027da72205450d004100210303402019200320157041306c6a2204427f2004290320220842017c220c200c2008542201200441286a2204290300220f2001ad7c221b200f54200c20085a1b22011b3703202004427f201b20011b370300200341016a22032005490d000b0b200241f0116a41186a2204203c290300370300200241f0116a41106a2201203d290300370300200241f0116a41086a2205203a290300370300200220022903900e3703f011024020362034470d00203441016a22032034490d14203441017422102003201020034b1b2210ad422c7e2208422088a70d142008a722034100480d140240024020340d0020031028213f0c010b203f2034412c6c2003102c213f0b203f450d0320342136201021340b203f2036412c6c6a220320022903f011370200200529030021082001290300210c2004290300210f200320153602282003202736022420032019360220200341186a200f370200200341106a200c370200200341086a2008370200203641016a21360b203541d0006a22352040470d000c020b0b200341041037000b02402037450d002038102a0b024020022802c80e2203450d00200341d0006c210420022802c00e41206a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200441b07f6a22040d000b0b024020022802c40e450d0020022802c00e102a0b20022802e80c20022802ec0c20022802f00c10bc022006450d08203941306c220341306e21040240024020030d0041012142420021300c010b200441057422014100480d10200110282242450d072004ad21300b024002402006200620036a470d00410021190c010b203941306c2101410021192042210320062104034020032004290000370000200341186a200441186a290000370000200341106a200441106a290000370000200341086a200441086a290000370000201941016a2119200341206a2103200441306a2104200141506a22010d000b0b200242003702ec0c200241f8b9c0003602e80c024020194105742203450d00204220036a213b200241f0116a4102722143200241900c6a41136a213c200241b00c6a41136a2144204221070340200241b0026a200710b004200241b0026a41086a290300210c20022903b002210f200241a0026a10a10220024190026a20022903a002200241a0026a41086a290300427f420010a00520024180026a200f200c20022903900222084201200842015620024190026a41086a29030022084200522008501b22031b2008420020031b10a005200741086a2900002108200741106a290000210c2007290000210f200241e00e6a41186a220e200741186a290000370300200241e00e6a41106a2224200c370300200241e00e6a41086a221520083703002002200f3703e00e20022903800221080240024002400240024002400240024020022802e80c221041f8b9c000460d0020022802ec0c21110c010b200241900f6a410041e0021099051a200241f0116a41004190041099051a41f80610282210450d0141002111201041003b010620104100360200201041086a200241900f6a41e002109a051a201041e8026a200241f0116a419004109a051a200241003602ec0c200220103602e80c0b200741206a210702400340201041086a2104201041066a210d20102f01062212410574210341002101024003402003450d01200241e00e6a20044120109c052205450d03200341606a2103200141016a2101200441206a21042005417f4a0d000b2001417f6a21120b02402011450d002011417f6a2111201020124102746a41f8066a28020021100c010b0b200241c00d6a41186a2203200e290300370300200241c00d6a41106a2024290300220c370300200241c00d6a41086a2015290300220f370300200220022903e00e221b3703c00d200220022802f00c41016a3602f00c200241900e6a41106a2239200c370300200241900e6a41086a2240200f370300200241900e6a41186a223e20032903003703002002201b3703900e200d2f01002204410b490d04200241900f6a410041e0021099051a200241f0116a41004190041099051a41f80610282203450d02200341003b010620034100360200200341086a200241900f6a41e002109a052101200341e8026a200241f0116a419004109a052105200241b00c6a41086a2245201041d0016a290000370300200241b00c6a41106a2246201041d8016a290000370300200241b00c6a41186a2247201041e0016a290000370300200241f0116a41086a222720104190056a290300370300200241f0116a41106a221620104198056a290300370300200241f0116a41186a2232201041a0056a290300370300200241f0116a41206a2233201041a8056a290300370300200241f0116a41286a2235201041b0056a290300370300200220102900c8013703b00c20022010290388053703f0112001201041e8016a20102f010641796a2204410574109a0521012005201041b8056a200441306c109a052105201041063b0106200320043b0106200220022f01b00c3b01e00c200220022d00b20c3a00e20c200220442900003703d00c2002204441056a22482900003700d50c20022800b30c214920022800b70c214a20022800bb0c214b20022800bf0c214c200241900f6a41286a224d2035290300370300200241900f6a41206a224e2033290300370300200241900f6a41186a224f2032290300370300200241900f6a41106a22502016290300370300200241900f6a41086a22512027290300370300200220022903f0113703900f0240024020124107490d00201241057420016a41c07e6a2001201241796a22114105746a2201200441ffff037120116b410574109b051a200141186a203e290300370000200141106a2039290300370000200141086a2040290300370000200120022903900e370000201241306c20056a220441e07d6a200441b07d6a2204200341066a220d2f010020116b41306c109b051a200441186a4200370300200420083703102004420037030820042008370300200441286a4100360200200442083703200c010b201041086a20124105746a220441206a2004200d2f010020126b410574109b051a200441186a203e290300370000200441106a2039290300370000200441086a2040290300370000200420022903900e370000201041e8026a201241306c6a220441306a2004200d2f010020126b41306c109b051a200441186a4200370300200420083703102004420037030820042008370300200441286a4100360200200442083703200b200d200d2f010041016a3b0100200241d00e6a41026a220420022d00e20c3a00002015205129030037030020242050290300370300200e204f290300370300200241e00e6a41206a2238204e290300370300200241e00e6a41286a2237204d290300370300200220022f01e00c3b01d00e200220022903d00c3703900c200220022900d50c3700950c200220022903900f3703e00e200241e00d6a41286a22522037290300370300200241e00d6a41206a22532038290300370300200241e00d6a41186a2254200e290300370300200241e00d6a41106a22552024290300370300200241e00d6a41086a22562015290300370300200220022903e00e3703e00d200220022f01d00e3b01a00d200220042d00003a00a20d200220022903900c3703f80c200220022900950c3700fd0c0240201028020022110d00200241e80c6a2104200321010c060b20102f0104213d41002157200321580340200241b80d6a41026a225920022d00a20d3a0000200220022f01a00d3b01b80d200220022903f80c3703d00e200220022900fd0c3700d50e2037205229030037030020382053290300370300200e20542903003703002024205529030037030020152056290300370300200220022903e00d3703e00e203d41ffff0371211202400240024020112f01062203410b490d002043410041a2071099051a41a80710282205450d0720054100360200200541046a200241f0116a41a407109a051a2047201141e0016a2900003703002046201141d8016a2900003703002045201141d0016a290000370300200220112900c8013703b00c2035201141b0056a2903003703002033201141a8056a2903003703002032201141a0056a290300370300201620114198056a290300370300202720114190056a29030037030020022011290388053703f011200541086a201141e8016a20112f0106220441796a2203410574109a05215a200541e8026a201141b8056a200341306c109a05215b200541f8066a20114194076a2004417a6a220d410274109a05213a201141063b0106200520033b01060240200d450d0041002103203a210403402004280200220120033b010420012005360200200441046a2104200d200341016a2203470d000b0b204d2035290300370300204e2033290300370300204f20322903003703002050201629030037030020512027290300370300200220022903f0113703900f200220022f01b00c3b01e00c200220022d00b20c3a00e20c20022900b30c210820022900bb0c210c200220482900003700d50c200220442900003703d00c203c20022903d00c370000203c41056a220d20022900d50c370000200220022d00e20c3a00920c200220022f01e00c3b01900c2002200c37009b0c200220083700930c2035204d2903003703002033204e2903003703002032204f2903003703002016205029030037030020272051290300370300200220022903900f3703f011203d41ffff037122044107490d01205a2012417a6a22014105746a205a201241796a22034105746a220420052f010620036b410574109b051a200441186a20022900d50e3700002004204c36000f2004204b36000b2004204a36000720042049360003200441026a20592d00003a0000200420022f01b80d3b0000200420022903d00e370013201241306c205b6a220441e07d6a200441b07d6a220420052f0106223d20036b41306c109b051a200441286a2037290300370300200441206a2038290300370300200441186a200e290300370300200441106a2024290300370300200441086a2015290300370300200420022903e00e3703002005203d41016a22043b01062012410274223d203a6a416c6a203a20014102746a2212200441ffff037120016b410274109b051a20122058360200200120052f010622124b0d022005203d6a41e0066a2104034020042802002201200341016a22033b010420012005360200200441046a210420032012490d000c030b0b201141086a2204201241016a22014105746a200420124105746a2204200320126b2205410574109b051a2004204c36000f2004204b36000b2004204a36000720042049360003200441026a20592d00003a0000200420022f01b80d3b0000200420022903d00e370013200441186a20022900d50e3700002011201241306c6a22044198036a200441e8026a220d200541306c109b051a20044190036a203729030037030020044188036a203829030037030020044180036a200e290300370300200441f8026a2024290300370300200441f0026a2015290300370300200d20022903e00e3703002011200341016a22033b01062012410274201141f8066a22046a41086a200420014102746a2204200341ffff037120016b410274109b051a200420583602000240201220112f010622034f0d00205820013b010420582011360200200120034f0d002003417f6a210520112001417f6a22034102746a4180076a2104034020042802002201200341026a3b010420012011360200200441046a21042005200341016a2203470d000b0b41001a200241e80c6a1a20101a0c090b201141086a2203201241016a22014105746a200320124105746a220320112f0106223d20126b223a410574109b051a2003204c36000f2003204b36000b2003204a36000720032049360003200341026a20592d00003a0000200320022f01b80d3b0000200320022903d00e370013200341186a20022900d50e370000201141e8026a201241306c6a220341306a2003203a41306c109b051a200341286a2037290300370300200341206a2038290300370300200341186a200e290300370300200341106a2024290300370300200341086a2015290300370300200320022903e00e3703002011203d41016a22033b01062012410274223a201141f8066a223d6a41086a203d20014102746a223d200341ffff037120016b410274109b051a203d2058360200200420112f010622014f0d002011203a6a41fc066a2103034020032802002204201241016a22123b010420042011360200200341046a210320012012470d000b0b205741016a2112200241b00d6a41026a220320022d00920c3a00002040202729030037030020392016290300370300203e2032290300370300200241900e6a41206a22042033290300370300200241900e6a41286a22012035290300370300200220022f01900c3b01b00d200220022903f0113703900e2002203c2900003703c00e2002200d2900003700c50e20022800930c214920022800970c214a200228009b0c214b200228009f0c214c20522001290300370300205320042903003703002054203e2903003703002055203929030037030020562040290300370300200220022903900e3703e00d200220022f01b00d3b01a00d200220032d00003a00a20d200220022903c00e3703f80c200220022900c50e3700fd0c0240201128020022030d0020111a200241e80c6a22041a200521010c070b20112f0104213d200241e80c6a1a20111a2003211120052158201221570c000b0b2010200141306c6a22034180036a4200370300200341f8026a2008370300200341f0026a4200370300200341e8026a200837030020034190036a410036020020034188036a220128020021042003418c036a2802002103200142083703002004450d052003450d052004102a0c050b41f80641081037000b41f80641081037000b41a80741081037000b201020124105746a220341286a200341086a2201200420126b410574109b051a200341206a203e290300370000200341186a2039290300370000200341106a2040290300370000200120022903900e3700002010201241306c6a22034198036a200341e8026a220420102f010620126b41306c109b051a20034190036a410036020020034188036a420837030020034180036a4200370300200341f8026a2008370300200341f0026a420037030020042008370300201020102f010641016a3b01060c010b2043410041a2071099051a41a80710282203450d0820034100360200200341046a200241f0116a41a407109a051a2003200428020022053602f806200420033602002004200428020441016a360204200541003b010420052003360200200320032f010622054105746a220441086a20022f01a00d3b00002004410a6a20022d00a20d3a0000200441176a204c360000200441136a204b3600002004410f6a204a3600002004410b6a20493600002004411b6a20022903f80c370000200441206a20022900fd0c3700002003200541306c6a220441e8026a20022903e00d370300200441f0026a2056290300370300200441f8026a205529030037030020044180036a205429030037030020044188036a205329030037030020044190036a2052290300370300200341f8066a200541016a22044102746a2001360200200320043b0106200120043b01042001200336020020101a0b2007203b470d000b0b02402036412c6c2203450d00203f20036a2132203f210d03400240200d28022841306c2203450d00200d280220220e20036a21150340200241f0016a200d10b004200e221041286a2224290300210f20102903202108200241f0016a41086a290300211b20022903f001211c200241e0016a10a102200241d0016a20022903e001200241e0016a41086a290300427f420010a005200241c0016a201c201b20022903d001220c4201200c420156200241d0016a41086a290300220c420052200c501b22031b200c420020031b10a005200241a0016a200f420020022903c001220c4200109f05200241b0016a20084200200c4200109f0520024190016a4200420020084200109f0542ffffffff0f200241b0016a41086a290300220820022903a0012002290390017c7c220c42208820022903a80120022903980184420052200c2008547222031b2108427f20023502b401200c4220868420031b210c201041306a210e200241e80c6a210320022802ec0c21120240024003402003280200221141086a210420112f010622074105742103410021010240024003402003450d01201020044120109c052205450d02200341606a2103200141016a2101200441206a21042005417f4a0d000b2001417f6a21070b2012450d022012417f6a2112201120074102746a41f8066a21030c010b0b2011200141306c6a220341f8026a2204427f2004290300220f200c7c221b201b200f54220420034180036a2201290300220f20087c2004ad7c221b200f54201b200f511b22041b3703002001427f201b20041b370300200241f0116a41186a2211200d41186a290000370300200241f0116a41106a2212200d41106a290000370300200241f0116a41086a2207200d41086a2900003703002002200d2900003703f01120034188036a2105024020034190036a220128020022042003418c036a280200470d00200441016a22032004490d16200441017422272003202720034b1b2227ad42307e220f422088a70d16200fa722164100480d160240024020040d002016102821030c010b2005280200200441306c2016102c21030b2003450d0220052003360200200541046a2027360200200128020021040b2005280200200441306c6a220320022903f0113703002003200c370320200341186a2011290300370300200341106a2012290300370300200341086a2007290300370300200341286a20083703002001200128020041016a3602000b2010200c37032020242008370300200e2015460d020c010b0b201641081037000b200d412c6a220d2032470d000b0b200241e00e6a41086a22034200370300200242003703e00e41a5afc4004116200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a100621030240024020022802f0112204417f460d002003450d00200220043602e40e200220033602e00e200241f0116a200241e00e6a106d20022802f0112207450d0320022902f41121082004450d012003102a0c010b42002108410121070b02402007450d002008422088a72203450d0020034105742101200721040340410f10282203450d04200341002900edae44370000200341076a41002900f4ae443700002002428f808080f0013702f411200220033602f0112004200241f0116a108f0120022802f811210320022802f0112105200241900c6a41186a22104200370300200241900c6a41106a22114200370300200241900c6a41086a22124200370300200242003703900c20052003200241900c6a1000200241c00d6a41186a2010290300370300200241c00d6a41106a2011290300370300200241c00d6a41086a2012290300370300200220022903900c3703c00d024020022802f411450d0020022802f011102a0b200441206a2104200241c00d6a41201009200141606a22010d000b0b02402008a7450d002007102a0b20022802f00c211020022802e80c21030240024020022802ec0c22010d00200321040c010b2001210520032104034020042802f80621042005417f6a22050d000b0340200320032f01064102746a41f8066a28020021032001417f6a22010d000b0b200241ac0f6a20032f0106360200200241900f6a41186a4100360200200241a40f6a2003360200200220103602b00f200241003602a00f200242003703980f200220043602940f200241003602900f200241f0116a200241900f6a10b1020240200241b0126a223b280200220d0d00427f2120427f211c0c080b200241f0116a41106a2101200241a8126a2133200241f0116a41286a2135427f2120427f211c0340200241e00d6a41086a200241f0116a41086a22112903002208370300200241e00d6a41106a2001290300220c370300200241e00d6a41186a200241f0116a41186a2205290300220f370300200220022903f011221b3703e00d203329030021182035290300211f20022802b412212420022802b812210320022903a0122121200229039012212f200241900e6a41186a2215200f370300200241900e6a41106a2227200c370300200241900e6a41086a221620083703002002201b3703900e20024180016a10a102200241e0006a20022903800120024180016a41086a290300427f420010a005200241f0006a10a102200241c0006a2002290370200241f0006a41086a290300427f420010a005200241d0006a2002290360220842012008420156200241e0006a41086a29030022084200522008501b22041b2008420020041b202f201f109f05200241306a2002290340220842012008420156200241c0006a41086a29030022084200522008501b22041b2008420020041b20212018109f05200241d0006a41086a290300211f200241306a41086a290300211b4100211220022903502121200229033021184100210e410821070240200341306c2210450d00201041306d220ead42307e2208422088a70d112008a722044100480d11200410282207450d050b02402003450d00200341047441706a213220072103200d21040340200441286a290300210c200441206a290300210f2005200441186a2903003703002001200441106a2903003703002011200441086a290300370300200220042903003703f011200241206a10a102200241106a2002290320200241206a41086a290300427f420010a00520022002290310220842012008420156200241106a41086a29030022084200522008501b22121b2008420020121b200f200c109f052003200241086a29030037030820032002290300370300200341106a20022903f011370300200341186a2011290300370300200341206a2001290300370300200341286a2005290300370300200341306a2103200441306a2104201041506a22100d000b203241047641016a21120b02402024450d00200d102a0b2012ad42307e2208422088a70d012008a72203417f4c0d010240024020030d004108210d0c010b20031028220d450d060b0240024020120d00410021100c010b2007201241306c6a211141002110200d2103200721040340200320042903003703002003200441086a290300370308200341106a200441106a290300370300200341186a200441186a290300370300200341206a200441206a290300370300200341286a200441286a290300370300200341306a2103201041016a2110200441306a22042011470d000b0b2005201f3703002002202137038012200220183703f011200220103602981220022012360294122002200d360290122002201b3703f811200241e00e6a41186a2015290300370300200241e00e6a41106a2027290300370300200241e00e6a41086a2016290300370300200220022903900e3703e00e0240410f10282203450d00200341002900edae44370000200341076a41002900f4ae443700002002428f808080f0013702b40c200220033602b00c200241e00e6a200241b00c6a108f0120022802b80c210320022802b00c2104200241900c6a41186a22054200370300200241900c6a41106a22104200370300200241900c6a41086a22114200370300200242003703900c20042003200241900c6a1000200241c00d6a41186a2005290300370300200241c00d6a41106a2010290300370300200241c00d6a41086a2011290300370300200220022903900c3703c00d024020022802b40c450d0020022802b00c102a0b200241003602e80e200242013703e00e2002200241f0116a3602b00c200241b00c6a200241e00e6a10a301200220013602b00c200241b00c6a200241e00e6a10a30120022802901221032002280298122204200241e00e6a10b40102402004450d00200441306c21040340200341106a200241e00e6a108f01200220033602b00c200341306a2103200241b00c6a200241e00e6a10a301200441506a22040d000b0b20022802e40e2103200241c00d6a412020022802e00e220420022802e80e100702402003450d002004102a0b20182020542103201b201c512104201b201c5421050240200228029412450d00200228029012102a0b2003200520041b21030240200e450d002007102a0b201b201c20031b211c2018202020031b2120200241f0116a200241900f6a10b10220022802b012220d450d090c010b0b410f41011037000b1036000b41c4d1c300413320024198196a419cd9c3001038000b410f41011037000b200441081037000b200341081037000b41a80741081037000b200141011037000b200241f0116a200241900f6a10b1020240203b2802002203450d000340024020022802b412450d002003102a0b200241f0116a200241900f6a10b10220022802b01222030d000b0b024020022802940f220341f8b9c000460d00200328020021012003102a2001450d00200128020021042001102a2004450d00024020042802002203450d0003402004102a2003210420032802002201210320010d000b0b2004102a0b200241e00e6a41086a22034200370300200242003703e00e4199fec4004111200241e00e6a1008200241900f6a41086a22042003290300370300200220022903e00e3703900f2002201c3703f811200220203703f011200241900f6a4110200241f0116a4110100720034200370300200242003703e00e41a5afc4004116200241e00e6a100820042003290300370300200220022903e00e3703900f200241003602f811200242013703f0112019200241f0116a10b40102402019450d00201941057421042042210303402003200241f0116a108f01200341206a2103200441606a22040d000b0b20022802f4112103200241900f6a411020022802f011220420022802f811100702402003450d002004102a0b2019ad210802402036450d002036412c6c2104203f41206a210303400240200341046a280200450d002003280200102a0b2003412c6a2103200441546a22040d000b0b2008422086210802402034450d00203f102a0b203020088421082041450d012006102a0c010b200241e00e6a41086a22034200370300200242003703e00e4199fec4004111200241e00e6a1008200241900f6a41086a2003290300370300200220022903e00e3703900f200241003602f011200241900f6a4110200241f0116a10062103024020022802f0112204417f460d002004410f4d0d052003102a0b410021420b024020172014a745720d002013102a0b20420d0102402009450d00200941d0006c2104200a41c0006a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200441b07f6a22040d000b0b200b450d00200a102a0b200041003602000c010b200020083702042000204236020002402009450d00200941d0006c2104200a41c0006a210303400240200341046a280200450d002003280200102a0b200341d0006a2103200441b07f6a22040d000b0b200b450d00200a102a0b200241a0196a24000f0b41c4d1c300413320024198196a419cd9c3001038000b41c4d1c300413320024198196a419cd9c3001038000b1031000baa0b02067f017e230041206b22042400200441106a41086a220542003703002004420037031041f9b5c200411d200441106a1008200441086a2005290300370300200420042903103703000240024002400240024002400240024002400240200441104101410041001003417f470d001098012106024002400240024020024101470d00200441106a41086a220542003703002004420037031041b8bfc200411a200441106a1008200441086a2005290300370300200420042903103703002004410036021020044110200441106a10062105024020042802102207417f460d002005450d0020074104490d06200528000021072005102a200720064b0d020b200441106a41086a220542003703002004420037031041b8bfc200411a200441106a1008200441086a2005290300370300200420042903103703002004200620014101746a36021020044110200441106a410410070b200028020821052000280204210820002802002109200441106a41086a220042003703002004420037031041f9b5c200411d200441106a1008200441086a2000290300370300200420042903103703002004410036021820044201370310410410282200450d052004410436021420042004280218220741046a36021820042000360210200020076a200636000020042802142206200428021822006b4104490d01200428021021060c020b200041046a280200450d0b2000280200102a0c0b0b200041046a22072000490d09200641017422002007200020074b1b22004100480d090240024020060d002000102821060c010b200428021020062000102c21060b2006450d042004200036021420042006360210200428021821000b2004200041046a360218200620006a20013600002005200441106a10b40102402005450d002009200541286c6a21072009210503402005200441106a108f01200541206a290300210a0240024020042802142201200428021822006b4108490d00200428021021010c010b200041086a22062000490d0b200141017422002006200020064b1b22004100480d0b0240024020010d002000102821010c010b200428021020012000102c21010b2001450d072004200036021420042001360210200428021821000b2004200041086a360218200120006a200a3700002007200541286a2205470d000b0b20042802142105200428021821000240024020024101460d000240024020052000460d00200428021021050c010b200041016a22052000490d0b200041017422012005200120054b1b22014100480d0b0240024020000d002001102821050c010b200428021020002001102c21050b2005450d082004200136021420042005360210200428021821000b2004200041016a360218200520006a41003a00000c010b0240024020052000460d00200428021021050c010b200041016a22052000490d0a200041017422012005200120054b1b22014100480d0a0240024020000d002001102821050c010b200428021020002001102c21050b2005450d082004200136021420042005360210200428021821000b2004200041016a360218200520006a41013a00000240024020042802142205200428021822006b4104490d00200428021021050c010b200041046a22012000490d0a200541017422002001200020014b1b22004100480d0a0240024020050d002000102821050c010b200428021020052000102c21050b2005450d092004200036021420042005360210200428021821000b2004200041046a360218200520006a20033600000b2004280214210020044110200428021022052004280218100702402000450d002005102a0b2008450d092009102a0c090b200041046a280200450d082000280200102a0c080b41c4d1c3004133200441106a419cd9c3001038000b410441011037000b200041011037000b200041011037000b200141011037000b200141011037000b200041011037000b1031000b200441206a24000bcb0201057f230041d0006b220224002002410036022820014110200241286a1006210302400240024020022802282204417f460d0020030d010b200041003a00000c010b41002101200241003a00480340024020042001470d000240200141ff0171450d00200241003a00480b41c4d1c3004133200241286a419cd9c3001038000b200241286a20016a200320016a2d00003a00002002200141016a22053a00482005210120054120470d000b200241086a41186a2201200241286a41186a290300370300200241086a41106a2205200241286a41106a290300370300200241086a41086a2206200241286a41086a2903003703002002200229032837030802402004450d002003102a0b20002002290308370001200041013a0000200041196a2001290300370000200041116a2005290300370000200041096a20062903003700000b200241d0006a24000bdf0301017f024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f200128020020012802042002412010072002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b952801057f02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200141046a2202280200200141086a22032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00003a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00013a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00023a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00033a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00043a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00053a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00063a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00073a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00083a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00093a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d0f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000e3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1020012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d000f3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1120012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00103a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1220012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00113a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1320012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00123a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1420012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00133a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1520012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00143a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1620012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00153a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1720012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00163a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1820012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00173a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1920012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00183a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1a20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d00193a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1b20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001a3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1c20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001b3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1d20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001c3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1e20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001d3a000002400240200228020020032802002204460d00200128020021050c010b200441016a22052004490d21200441017422062005200620054b1b22064100480d210240024020040d002006102821050c010b200128020020042006102c21050b2005450d1f20012005360200200141046a2006360200200141086a28020021040b2003200441016a360200200520046a20002d001e3a000002400240200228020020032802002202460d00200128020021040c010b200241016a22042002490d21200241017422052004200520044b1b22054100480d210240024020020d002005102821040c010b200128020020022005102c21040b2004450d2020012004360200200141046a2005360200200141086a28020021020b2003200241016a360200200420026a20002d001f3a00000f0b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200541011037000b1031000b02000ba50201057f230041d0006b21020240200128020022032001280204470d00200041003602000f0b200120034180016a3602002002200329006237012a2002200329006a370132200241086a41086a220120022903303703002002200329007237013a200241086a41106a220420022903383703002002200328007a360142200220032f007e3b0146200241086a41186a22052002290340370300200220032f00603b012820022002290328370308200241286a41186a22062005290300370300200241286a41106a22052004290300370300200241286a41086a220420012903003703002002200229030837032820002003360200200020022903283702042000410c6a2004290300370200200041146a20052903003702002000411c6a20062903003702000b280020004101360204200041086a200128020420012802006b4107762201360200200020013602000bb905020b7f047e23004190016b22032400024002402001280200220420012802042205460d00200120044180016a22063602002003200441e2006a29000037016a2003200441ea006a290000370172200341c8006a41086a220720032903703703002003200441f2006a29000037017a200341c8006a41106a220820032903783703002003200441fa006a280000360182012003200441fe006a2f00003b018601200341c8006a41186a22092003290380013703002003200441e0006a2f00003b016820032003290368370348200341286a41186a220a2009290300370300200341286a41106a220b2008290300370300200341286a41086a220c200729030037030020032003290348370328200541807f6a210d02400340200341086a41186a200a290300220e370300200341086a41106a200b290300220f370300200341086a41086a200c2903002210370300200320032903282211370308200341e8006a41186a200e370300200341e8006a41106a200f370300200341e8006a41086a2010370300200320113703682002450d01200d2004460d02200120064180016a22053602002003200641e2006a29000037016a2003200641ea006a290000370172200720032903703703002003200641f2006a29000037017a200820032903783703002003200641fa006a280000360182012003200641fe006a2f00003b01860120092003290380013703002003200641e0006a2f00003b016820032003290368370348200a2009290300370300200b2008290300370300200c20072903003703002003200329034837032820044180016a21042002417f6a2102200521060c000b0b20002004360200200020032903683702042000410c6a200341f0006a290300370200200041146a200341f8006a2903003702002000411c6a20034180016a2903003702000c010b200041003602000b20034190016a24000ba50201057f230041d0006b21020240200128020022032001280204470d00200041003602000f0b200120034180016a3602002002200329004237012a2002200329004a370132200241086a41086a220120022903303703002002200329005237013a200241086a41106a220420022903383703002002200328005a360142200220032f005e3b0146200241086a41186a22052002290340370300200220032f00403b012820022002290328370308200241286a41186a22062005290300370300200241286a41106a22052004290300370300200241286a41086a220420012903003703002002200229030837032820002003360200200020022903283702042000410c6a2004290300370200200041146a20052903003702002000411c6a20062903003702000bb905020b7f047e23004190016b22032400024002402001280200220420012802042205460d00200120044180016a22063602002003200441c2006a29000037016a2003200441ca006a290000370172200341c8006a41086a220720032903703703002003200441d2006a29000037017a200341c8006a41106a220820032903783703002003200441da006a280000360182012003200441de006a2f00003b018601200341c8006a41186a22092003290380013703002003200441c0006a2f00003b016820032003290368370348200341286a41186a220a2009290300370300200341286a41106a220b2008290300370300200341286a41086a220c200729030037030020032003290348370328200541807f6a210d02400340200341086a41186a200a290300220e370300200341086a41106a200b290300220f370300200341086a41086a200c2903002210370300200320032903282211370308200341e8006a41186a200e370300200341e8006a41106a200f370300200341e8006a41086a2010370300200320113703682002450d01200d2004460d02200120064180016a22053602002003200641c2006a29000037016a2003200641ca006a290000370172200720032903703703002003200641d2006a29000037017a200820032903783703002003200641da006a280000360182012003200641de006a2f00003b01860120092003290380013703002003200641c0006a2f00003b016820032003290368370348200a2009290300370300200b2008290300370300200c20072903003703002003200329034837032820044180016a21042002417f6a2102200521060c000b0b20002004360200200020032903683702042000410c6a200341f0006a290300370200200041146a200341f8006a2903003702002000411c6a20034180016a2903003702000c010b200041003602000b20034190016a24000be6880106147f027e077f017e027f017e230041d0046b22042400200441c0036a20012002200310f903200441c0036a41086a280200210520042802c40321060240024020042802c0034101470d002000200636020420004101360200200041086a20053602000c010b200441d4036a280200220741306c2108200441d8036a2802002109200441d0036a280200210a200441cc036a280200210b4100210c4100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004102470d000b200441d0006a200b200d6a41546a10fa032004280250210c200428025421010b4100210e20014100200c1b210f200741306c2108200c4104200c1b21104100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004108470d000b200441c8006a200b200d6a41546a10fa032004280248210e200428024c21010b4100211120014100200e1b2112200741306c2108200e4104200e1b210d4100210102400340024020082001470d000c020b200b20016a2102200141306a220c210120022d00004104470d000b200441c0006a200b200c6a41546a10fa0320042802402111200428024421010b4100210e2001410020111b2113200741306c21082011410420111b21114100210102400340024020082001470d000c020b200b20016a2102200141306a220c210120022d00004103470d000b200441386a200b200c6a41546a10fa032004280238210e200428023c21010b41002102024020014100200e1b2201450d00200141286c2108200e4104200e1b41186a2101410021020340200220012d0000456a2102200141286a2101200841586a22080d000b0b0240024020120d00411e2101200041b98dc6003602040c010b200d201241146c6a211241002114410021150240024002400340200d450d0141d78dc600210841382101200d41086a280200417c6a220e41024b0d02200d280200210c024002400240200e0e03000501000b41012115200c41af8dc600460d01200c28000041e3c2b1e306460d010c040b41012114200c41b38dc600460d00200c41b38dc6004106109c050d030b0240200d410c6a280200450d0041132101200041d58ec6003602040c050b0240200d41106a280200220120026b220c20014d0d00412a2101200041e88ec6003602040c050b41af8ec6002108412621012013200c4d0d022011200c4102746a220c450d02418f8ec600210841202101200f200c280200220c4d0d022010200c4104746a220c450d0241928fc6002108411f2101200c2802080d02200c2d000d220c41077141044b0d020240200c0e050003030300000b200d41146a220d2012470d000b0b41b18fc60041b98dc600201441017122021b2108411c411e20021b21012002450d002015410171450d00200741306c2108410021010c010b200020083602040c010b0240034020082001460d01200b20016a2102200141306a220d210120022d00004106470d000b200441306a200b200d6a41546a10fa032004280234450d00200041fd8ac600360204411f21010c010b200741306c21082003280268210c410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004105470d000b200441286a200b200d6a41546a220110fa030240200428022c41014d0d00411821012000419c8bc6003602040c020b200441206a200110fa032004280224450d0020042802202201450d002001280200200c4d0d0041222101200041b48bc6003602040c010b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004107470d000b200441186a200b200d6a41546a10fa0320042802182201200428021c4104746a2108034020012008460d012001450d012001410c6a2102200141106a210120022d0000410271450d000b41322101200041c08cc6003602040c010b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d0000410c470d000b200b200d6a2201415c6a2802002202450d00200141546a280200220d200241186c6a210c0340200d220241186a210d2002280208410374210120022802002102024003402001450d01200141786a210120022d00042108200241086a21022008410271450d000b413121012000418f8cc6003602040c030b200d200c470d000b0b200741306c2108410021010240034020082001460d01200b20016a2102200141306a220d210120022d00004102470d000b200441106a200b200d6a41546a10fa0320042802142201450d002004280210220220014104746a211103402002450d01200241106a210e200420022d000d22083a00c0032002280200220120022802086a210c410021024100200441c0036a20084104461b210d024003400240024002400240200241ff01710e03000102000b2001200c460d014100210220012108200141016a21010c020b2001200c460d034101210220012108200141016a21010c010b200d450d0241022102200d21084100210d0b20082d0000410271450d000b41392101200041d68bc6003602040c030b200e2102200e2011470d000b0b200741306c21084100210c4100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004102470d000b200441086a200b200d6a41546a10fa032004280208210c200428020c21010b4100210e20014100200c1b2110200741306c2108200c4104200c1b21124100210102400340024020082001470d000c020b200b20016a2102200141306a220d210120022d00004103470d000b2004200b200d6a41546a10fa032004280200210e200428020421010b200e4104200e1b220220014100200e1b41286c6a210d41002113024002400340024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402002200d460d00412d2101418e91c400210820022802084103470d2102402002280200220c41f8e2c500460d00200c41f8e2c5004103109c050d220b200241286a21114115210c418790c400210e4114210141fa90c400210802400240024020022d00180e0400240123000b4136210c41d18fc400210e2010200228021c22014d0d22201220014104746a220f450d222002280214210c200228020c210220092d00700d01200c410b470d014138210141c290c4002108200241ac81c600460d23200241ac81c600410b109c05450d230c210b412f210141bb91c400210820022802144106470d220240200228020c220c41cb8fc400460d00200c41cb8fc4004106109c050d230b02402013450d00411f2101200041ea91c4003602040c280b2002411c6a2113201121020c240b41262101419c90c4002108200c417d6a220c41134b0d2102400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200c0e14003e3e3e0e043e073c0b0a120114111b103e0c19000b200241effec500460d3d200241effec5004103109c05450d3d41effec50020024103109c050d3d41011028220e450d1d200e41003a0000200f2d000c41e000460d010c3a0b200241f2fec500460d0141f2fec5002002410f109c05450d0120024181ffc500460d034181ffc5002002410f109c05450d03024020024198ffc500460d004198ffc5002002410f109c050d3d0b41071028220e450d20200e4100360003200e41013a0002200e41003b0000200f2d000c41e000460d060c380b200f2802084101470d380240200f2802002214200e460d0041002102034020024101460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d3a0c000b0b200f2d000d4104470d38200e102a201121020c3d0b41041028220e450d1b200e4100360000200f2d000c41e000470d35200f2802084104470d350240200f2802002214200e460d0041002102034020024104460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d370c000b0b200f2d000d4104470d35200e102a201121020c3c0b024020024190ffc500460d00200229000042e5f0d1fbb5ac98b6ec00520d3a0b41071028220e450d1c200e4100360003200e41013a0002200e41003b0000200f2d000c41e000460d010c330b41011028220e450d1a200e41003a0000200f2d000c41e000470d31200f2802084101470d31200f2802002214200e460d3041002102034020024101460d31200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d320c000b0b200f2802084107470d31200f2802002214200e460d2e41002102034020024107460d2f200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d320c000b0b200241a7ffc500460d0141a7ffc5002002410a109c05450d010240200241b1ffc500460d0041b1ffc5002002410a109c050d060b4126210c419c90c400210e200f2d000c41e000470d35200f2802080d3520112102200f2d000d4104460d380c350b200f2802084107470d31200f2802002214200e460d2b41002102034020024107460d2c200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d320c000b0b41021028220e450d19200e41003b0000200f2d000c41e000470d29200f2802084102470d290240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d2b0c000b0b200f2d000d4104470d29200e102a201121020c360b0240200241c6ffc500460d0041c6ffc5002002410d109c050d340b4126210c419c90c400210e200f2d000c41e000470d32200f2802080d3220112102200f2d000d4104460d350c320b0240200241d3ffc500460d0041d3ffc5002002410c109c050d330b4126210c419c90c400210e200f2d000c41e000470d31200f2802080d3120112102200f2d000d4104460d340c310b0240200241eaffc500460d0041eaffc50020024115109c050d320b4126210c419c90c400210e200f2d000c41e000470d30200f2802080d3020112102200f2d000d4104460d330c300b0240200241ffffc500460d0041ffffc5002002410a109c050d310b41021028220e450d16200e41003b0000200f2d000c41e000460d010c240b02402002418980c600460d00418980c60020024107109c050d300b4126210c419c90c400210e200f2d000c41e000470d2e200f2802080d2e20112102200f2d000d4104460d310c2e0b200f2802084102470d220240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d240c000b0b200f2d000d4104470d22200e102a201121020c300b02402002419080c600460d00419080c60020024113109c050d2e0b4126210c419c90c400210e200f2d000c41e000470d2c200f2802080d2c20112102200f2d000d4104460d2f0c2c0b200241a380c600460d0141a380c60020024111109c05450d01200241e280c600460d0641e280c60020024111109c05450d060240200241f380c600460d0041f380c60020024111109c050d2d0b41041028220e450d17200e4100360000200f2d000c41e000460d080c1f0b0240200241b480c600460d0041b480c6002002410e109c050d2c0b41081028220e450d13200e4200370000200f2d000c41e000460d020c1d0b41021028220e450d11200e41003b0000200f2d000c41e000470d1b200f2802084102470d1b0240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d1d0c000b0b200f2d000d4104470d1b200e102a201121020c2c0b200241c280c600460d0141c280c60020024110109c05450d01200241d280c600460d0241d280c60020024110109c05450d020240200241b781c600460d0041b781c60020024110109c050d2a0b4126210c419c90c400210e200f2d000c41e000470d28200f2802080d2820112102200f2d000d4104460d2b0c280b200f2802084108470d1a0240200f2802002214200e460d0041002102034020024108460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d1c0c000b0b200f2d000d4104470d1a200e102a201121020c2a0b4126210c419c90c400210e200f2d000c41e000470d26200f2802080d26200f2d000d22014104460d2620112102200141fb0171450d290c260b41031028220e450d0f200e41003a0002200e41003b0000200f2d000c41e000470d16200f2802084103470d160240200f2802002214200e460d0041002102034020024103460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d180c000b0b200f2d000d4104470d16200e102a201121020c280b41021028220e450d0f200e41003b0000200f2d000c41e000470d14200f2802084102470d140240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d160c000b0b200f2d000d4104470d14200e102a201121020c270b02402002418481c600460d00418481c60020024116109c050d250b41021028220e450d10200e41003b0000200f2d000c41e000460d020c120b200f2802084104470d160240200f2802002214200e460d0041002102034020024104460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d180c000b0b200f2d000d4104470d16200e102a201121020c250b02402002419a81c600460d00419a81c60020024112109c050d230b4126210c419c90c400210e200f2d000c41e000470d21200f2802080d2120112102200f2d000d4104460d240c210b200f2802084102470d0f0240200f2802002214200e460d0041002102034020024102460d01200e20026a2108201420026a210c200241016a2102200c2d000020082d0000470d110c000b0b200f2d000d4104470d0f200e102a201121020c230b024020130d0041002116410021170c0e0b024020132802040d002000418992c400360204413221010c260b024020132802002216201341086a28020022174d0d00200041bb92c40036020441c90021010c260b201720032802644d0d0d2000418493c40036020441c10021010c250b410141011037000b410441011037000b410141011037000b410741011037000b410741011037000b410241011037000b410241011037000b410241011037000b410841011037000b410341011037000b410241011037000b410441011037000b410241011037000b20092903082118200441c0036a41086a22024200370300200441f8b9c0003602c4032009290310211920042018a7417f2018428080808010541b3602d00320042019a7417f2019428080808010541b3602c003200441c0036a4104722201410d10fb032001410c10fb032001410710fb032001410f10fb03200441d8006a41106a20042802d003360200200441d8006a41086a2002290300370300200420042903c003370358200441c0036a41106a22082007360200200441c0036a410c6a200a3602002004200b3602c803200420053602c403200420063602c003200441f0006a200441c0036a10fc03024002400240410110282201450d00200141003a0000200420042f01c003220d3b01b002200841e0083b01002002428180808010370300200420013602c403200441013602c0032004200d3b01d203200441f0006a200441c0036a10fd03210c0240410310282202450d00200241026a41002d00fae2453a0000200241002f00f8e2453b00000240410310282208450d00200841026a41002d00f1fe453a0000200841002f00effe453b0000200441b0026a41026a200441c0036a41026a220b2d000022073a0000200420042f00c003220e3b01b00220044184016a280200210d200441f0006a41106a2802002101200b20073a00002004200e3b01c00302400240024002400240024002400240200d2001470d00200141016a220d2001490d012001410174220b200d200b200d4b1b220dad42287e2218422088a70d012018a7220b4100480d010240024020010d00200b102821010c010b200428027c200141286c200b102c21010b2001450d072004200d360280012004200136027c200428028401210d0b200428027c200d41286c6a220141003a00182001200836020c200142838080803037020420012002360200200141106a428380808030370200200141196a20042f01c0033b00002001411b6a200441c2036a2d00003a00002001411c6a200c360200200420042802840141016a36028401200441c0036a200441f0006a418c01109a051a20044180026a200441c0036a10fe0320044180026a41106a280200220e41306c2101200428028802220741546a210202400340410021082001450d01200141506a21012002412c6a210d200241306a220c2102200d2d00004103470d000b200c41086a2802002201450d00200141286c2102200c28020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200e41306c2101200741546a21022008417f6a210d02400340410021082001450d01200141506a21012002412c6a210c200241306a220b2102200c2d00004103470d000b200b41086a2802002201450d00200141286c2102200b28020041186a2101410021080340200820012d0000456a2108200141286a2101200241586a22020d000b0b200e41306c21012007415c6a21020240034041002111024020010d00410021010c020b200141506a2101200241246a210c200241306a220b2102200c2d00004104470d000b200b28020021010b0240024002400240200e450d00200120086a211a2007200e41306c6a2112200441d8006a410472211b4100211c4100211d0340024020072d000041786a220141044b0d00024002400240024020010e050301020400030b200728020c2201450d032007280204220c200141186c6a211e201d210103402001211d0240200c22082802144104742202450d00200828020c21010340024020012d0000410b470d00200141046a220c280200220b200d490d00200c200b41016a3602000b200141106a2101200241706a22020d000b0b200442003703d00320044280808080c0003703c803200442043703c003024002400240411010282201450d0020042802c8032102200420013602c003200441013602c403200120024104746a22014200370200200141056a4200370000200420042802c80341016a3602c80302402008280214221f450d0041002106201f210103400240024002400240024002400240024002400240024002400240200620014f0d004110210c0240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200828020c222020064104746a2d000022140eac010001020202020202020202020202020303030404050506060707080809090a0a0b0b0c0d0d0e0e0f0f1010111213131414151516161717181819191a1a1b1b1c1c1d1d1e1e1f1f2020212122222323242425252627272828292a2a2b2b2c2d2d2e2e2f2f303031313232333434353536363737383839393a3a3b3b3c3c3d3d3e3e3f3f40404141424243434444454546464747484a4a4a4a49494a4a4a4a4a4a4a4a4a4a4a4a4a4a4b4b4b4b000b4111210c0c4a0b4112210c0c490b410a210c0c480b4108210c0c470b4108210c0c460b4104210c0c450b4104210c0c440b4104210c0c430b4104210c0c420b4104210c0c410b4104210c0c400b4104210c0c3f0b4105210c0c3e0b4105210c0c3d0b4105210c0c3c0b4105210c0c3b0b4105210c0c3a0b4113210c0c390b4114210c0c380b4106210c0c370b4107210c0c360b410b210c0c350b410b210c0c340b410b210c0c330b410b210c0c320b410b210c0c310b410b210c0c300b410b210c0c2f0b410b210c0c2e0b410b210c0c2d0b410b210c0c2c0b410b210c0c2b0b410c210c0c2a0b410c210c0c290b410c210c0c280b410c210c0c270b410c210c0c260b410c210c0c250b4100210c0c240b4100210c0c230b4101210c0c220b4102210c0c210b4103210c0c200b4103210c0c1f0b4100210c0c1e0b4100210c0c1d0b4100210c0c1c0b4100210c0c1b0b4100210c0c1a0b4100210c0c190b4101210c0c180b4102210c0c170b4103210c0c160b4103210c0c150b4100210c0c140b4100210c0c130b4100210c0c120b4100210c0c110b410d210c0c100b410d210c0c0f0b410d210c0c0e0b410d210c0c0d0b410d210c0c0c0b410d210c0c0b0b410d210c0c0a0b410d210c0c090b410d210c0c080b410d210c0c070b410d210c0c060b410d210c0c050b410d210c0c040b410d210c0c030b410e210c0c020b410e210c0c010b410f210c0b200641016a210a2004280260210f201b2101024003402001280200221141086a210520112f0106210b41002102024002400340200b20022201460d01200141016a210202404100417f4101200520016a2d00002213200c4b1b2013200c461b41016a0e03000301000b0b2002417f6a210b0b0240200f0d00200441d8006a21020c030b200f417f6a210f2011200b4102746a41ec006a21010c010b0b200441d8006a21020240201120014103746a41146a22012802000e04010d0001010b200141046a21020b20022802002102024002400240024002400240024002402014417e6a220141084b0d0020010e09010302120405050607010b20042802c8032201417f6a220c20014f0d12200c20014b0d1220042802c003200c4104746a220c280208220120026a22022001490d12200c41086a20023602000c130b20042802c8032201417f6a220c20014f0d11200c20014b0d1120042802c003200c4104746a220c280208220120026a22022001490d11200c41086a200236020020042802c8032201417f6a220c20014f0d11200c20014b0d1120042802c0032202200c4104746a280204210c02400240200120042802c403460d002001210b0c010b200141016a220b2001490d2320014101742211200b2011200b4b1b220b41ffffffff0071200b470d23200b41047422114100480d23200220014104742011102c2202450d082004200b3602c403200420023602c00320042802c803210b0b2002200b4104746a2202200e3b000d200241003a000c2002200c360204200220013602002002410f6a200e4110763a0000200241086a4100360200200420042802c80341016a3602c8030c120b20042802c8032201417f6a220c20014f0d10200c20014b0d1020042802c003200c4104746a220c280208220120026a22022001490d10200c41086a200236020020042802c803220221010240200220042802c403470d00200241016a22012002490d222002410174220c2001200c20014b1b220141ffffffff00712001470d222001410474220b4100480d220240024020020d00200b1028210c0c010b20042802c0032002410474200b102c210c0b200c450d08200420013602c4032004200c3602c00320042802c80321010b20042802c00320014104746a2201200e3b000d200141003a000c2001200a360204200120023602002001410f6a200e4110763a0000200141086a4100360200200420042802c80341016a3602c8030c110b20042802c8032201417f6a220c20014f0d0f200c20014b0d0f20042802c003200c4104746a220c280208220120026a22022001490d0f200c41086a200236020020042802c803220221010240200220042802c403470d00200241016a22012002490d212002410174220c2001200c20014b1b220141ffffffff00712001470d212001410474220b4100480d210240024020020d00200b1028210c0c010b20042802c0032002410474200b102c210c0b200c450d08200420013602c4032004200c3602c00320042802c80321010b20042802c00320014104746a2201200e3b000d200141013a000c2001200a360204200120023602002001410f6a200e4110763a0000200141086a4100360200200420042802c80341016a3602c8030c100b200441c0036a200610ff030d0e20042802c8032202450d0e20042002417f6a22013602c80320042802c003220c20014104746a220b2d000c4102460d0e2001450d0f2002417e6a220220014f0d0e200c20024104746a220c200b2802002202200c280200220c200c20024b1b360200200220014f0d0f200441c0036a200610ff030d0e0c0f0b20042802c8032201417f6a220c20014f0d0d200c20014b0d0d20042802c003200c4104746a220c280208220120026a22022001490d0d202020064104746a41046a280200210b200c41086a200236020020042802c8032201417f6a220220014b0d0d2002200b6b220120024b0d0d200441c0036a200610ff030d0d20042802c803220220014d0d0d20042802c003220c20014104746a2d000c0d0e2002410474200c6a41706a2202200120022802002202200220014b1b3602000c0e0b20042802c8032201417f6a220c20014f0d0c200c20014b0d0c20042802c003200c4104746a220c280208220120026a22022001490d0c200c41086a200236020020042802c8032201417f6a220520014b0d0c202020064104746a41046a280200220128020021022001280204210c2004200520012802086b220b20054b22013a00b00220010d0c410410282213450d052013200b36020002400240200c4104490d00200520022802006b220f20054b0d08200241046a21010c010b0240200c0d0041012102410121110c0b0b200520022802006b220f20054b0d07200241046a21010b2002200c4102746a2120410121114104210c4102210b41022102034002402002417f6a22142011470d00201441016a22112014490d1f200b2011200b20114b1b221141ffffffff03712011470d1f201141027422144100480d1f0240024020024101470d002014102821130c010b2013200c2014102c21130b2013450d090b2013200c6a200f36020002400240202020016b410d490d000240200520012802006b220f20054b0d00200141046a21010c020b200441013a00b0020c0d0b20202001460d0b200520012802006b220f20054b0d0a200141046a21010b200b41026a210b200241016a2102200c41046a210c0c000b0b20042802c8032201417f6a220c20014f0d0b200c20014b0d0b20042802c003200c4104746a220c280208220120026a22022001490d0b200c41086a2002360200200441c0036a200610ff030d0b20042802c8032201450d0b20042802c00322022d000c0d0c200141047420026a41706a41003602000c0c0b41fce2c500200620011034000b201141041037000b200b41041037000b200b41041037000b410441041037000b41012111200441013a00b0020c030b201441041037000b200441013a00b0020c010b20042d00b0020d002013450d022002ad4220862011ad842118410121050240200441c0036a200610ff030d0002402018422088a72201450d002001410274210c20132101034020042802c803220b200128020022024d0d02024020042802c003221120024104746a2d000c0d00200b41047420116a41706a220b2002200b280200220b200b20024b1b3602000b200141046a2101200c417c6a220c0d000b0b410021050b02402018a7450d002013102a0b20050d020c030b2011450d012013102a0c010b200441c0036a200610ff03450d010b024020042802c403450d0020042802c003102a0b024020042802d003450d0020042802cc03102a0b4101211c0c0a0b200a201f460d0120082802142101200a21060c000b0b20042802cc0320042802d4032201410041202001676b10800420042903d003212120042802cc03211f024020042802c403450d0020042802c003102a0b0240201f0d004101211c0c080b0240200828021422022021422088a722114101746a220141ffffffff00712001470d002001410474220c417f4c0d00024002400240200c0d004108210b0c010b200c1028220b450d01200828021421020b20084100360214200828020c21222008200b36020c200841106a220b2802002123200b2001360200202220024104746a210f201f20114103746a212041022111024020020d00201f210a202221010c040b41002101201f210a4100210c20222102024002400340200241016a2f0000200241036a2d000041107472210e024020022d0000221341ac01470d00200241106a21010c070b200241086a2900002118200241046a280000210502400240024020114102470d000240200a2020470d00410021112020210a0c020b200a2902002219422088a721152019a7211041012111200a41086a210a0b20114101470d00200c2010470d0002402001200b280200470d00200141016a22112001490d15200141017422062011200620114b1b221141ffffffff00712011470d15201141047422064100480d150240024020010d002006102821010c010b200828020c20014104742006102c21010b2001450d022008200136020c200b2011360200200828021421010b200828020c20014104746a220120042f00c0033b00012001412d3a000020012015360204200141036a200441c0036a41026a2d00003a00002008200828021441016a220136021402402001200b280200470d00200141016a22112001490d15200141017422062011200620114b1b221141ffffffff00712011470d15201141047422064100480d150240024020010d002006102821010c010b200828020c20014104742006102c21010b2001450d042008200136020c200b2011360200200828021421010b200828020c20014104746a220120042f00c0033b00012001410b3a00002001200d36020441022111200141036a200441c0036a41026a2d00003a00002008200828021441016a2201360214200c21100b02402001200b280200470d00200141016a22062001490d14200141017422142006201420064b1b220641ffffffff00712006470d14200641047422144100480d140240024020010d002014102821010c010b200828020c20014104742014102c21010b2001450d042008200136020c200b2006360200200828021421010b200c41016a210c200828020c20014104746a22012018370308200120053602042001200e3b0001200120133a0000200141036a200e4110763a00002008200828021441016a2201360214200241106a2202200f470d010c080b0b200641081037000b200641081037000b201441081037000b200c41081037000b1036000b411041041037000b2001200f460d0003400240024020012d000022024109460d00200241ac01470d010c030b0240200141046a280200220228020441ffffffff0371450d002002280200102a0b2002102a0b200141106a2201200f470d000b0b2021a7210102402023450d002022102a0b200a202047201120114102461b210202402001450d00201f102a0b024020024101470d004101211c0c050b200841186a210c024002402004280268450d0020082802142202450d00200828020c210120024104742102410021080340024020012d0000412c470d002001410b3a0000200141046a201a360200200841016a21080b200141106a2101200241706a22020d000b4101210120080d010b201d21010b200c201e470d000b2001211d0c030b20072802042201200d490d022007200141016a3602040c020b200728020c2201450d012007280204220c2001411c6c6a210b0340200c2201411c6a210c024020012802182202450d0020012802102101200241027421020340024020012802002208200d490d002001200841016a3602000b200141046a21012002417c6a22020d000b0b200c200b460d020c000b0b200728020c2201450d00200141146c2102200728020441106a2101034002402001417c6a2802000d0020012802002208200d490d002001200841016a3602000b200141146a21012002416c6a22020d000b0b200741306a22072012470d000b201c4101710d02201d4101710d01200428029002211120042802880221070b2004418c026a280200210f20042802840221132004280280022105410021060c020b200441c0036a41106a20044180026a41106a280200360200200441c0036a41086a20044180026a41086a29030037030020042004290380023703c003200441b0026a200441c0036a10fc03411010282202450d07200241063a0000410110282201450d06200141003a000041011028220c450d05200c20012d00003a00002001102a411010282208450d04200841063a000041f00010282201450d03200141063a00602001412c3b01502001200d3602442001410b3a0040200141d8003a0030200120042802683602242001412d3a0020200141003602142001410f3a0010200141003602042001410f3a0000024020082d00004109470d0002402008280204220d28020441ffffffff0371450d00200d280200102a2008280204210d0b200d102a0b2008102a024020022d00004109470d0002402002280204220828020441ffffffff0371450d002008280200102a200228020421080b2008102a0b2002102a200441e4036a4287808080f000370200200441e0036a2001360200200441dc036a4100360200200441c0036a410c6a4281808080800c370200200441c8036a4101360200200441003602ec03200442043702d4032004200c3602c403200441013602c003200441b0026a200441c0036a108104200441c0036a200441b0026a418c01109a051a20044198026a200441c0036a10fe0320044198026a410c6a280200210f200441a8026a28020021112004280298022105200428029c02211320042802a0022107410021060c010b2004418c026a280200210f200428028802210702402004280290022211450d00201141306c21022007210103402001108204200141306a2101200241506a22020d000b0b41012106411a211341f28cc60021050240200f450d002007102a0b0b200441e4006a280200210e200428025c21080240200441e0006a2802002201450d000340200828026c21082001417f6a22010d000b0b4100210d4100210102400340200e450d0102400240200120082f01064f0d00200820014103746a41146a2902002118200141016a21010c010b02400240200828020022010d00200dad21184100210c410021010c010b2008330104422086200dad8421184101210c0b2008102a2018a7210d024002402018422088a7220b20012f01064f0d00200121020c010b034002400240200128020022020d00200dad2118410021020c010b200c41016a210c2001330104422086200dad8421180b2001102a2018a7210d200221012018422088a7220b20022f01064f0d000b0b200b41027420026a41f0006a28020021082002200b4103746a41146a29020021180240200c417f6a2201450d000340200828026c21082001417f6a22010d000b0b410021010b200e417f6a210e2018a74103470d000b0b0240200841f8b9c000460d00200828020021012008102a2001450d00200128020021022001102a2002450d00024020022802002201450d0003402002102a2001210220012802002208210120080d000b0b2002102a0b02402006450d002000200536020420004101360200200041086a20133602000c250b200441b0026a41106a2011360200200441b0026a410c6a200f360200200420073602b802200420133602b402200420053602b002200441c0036a200441b0026a2009280260108304024020042802c0034101470d000240200441c0036a41086a280200450d0020042802c403102a0b2000418c8dc60036020420004101360200200041086a41233602000c250b200441d4036a2802002102200441c0036a41106a280200210f200441c0036a410c6a2802002106200441c8036a280200210d20042802c403210820032802582110200441003602a002200442013703980202400240410410282201450d002004410436029c02200420042802a002220c41046a3602a00220042001360298022001200c6a200836000002400240200428029c02220820042802a00222016b4104490d0020042802980221080c010b200141046a220c2001490d0320084101742201200c2001200c4b1b22014100480d030240024020080d002001102821080c010b20042802980220082001102c21080b2008450d022004200136029c02200420083602980220042802a00221010b2004200141046a3602a002200820016a200d3600002006200241306c22016a210d024020020d00200621010c0e0b200141506a2111200441c0036a4101722102200441c0036a41276a210c200441c0036a41206a210b200441c0036a41186a2107200441c0036a41086a210e20062101034020012d00002108200c200141286a290000370000200b200141216a2900003703002007200141196a290000370300200441c0036a41106a2203200141116a290000370300200e200141096a2900003703002004200141016a2900003703c003024020084110470d00200141306a21010c0f0b200441b0026a41276a2213200c290000370000200441b0026a41206a2205200b290300370300200441b0026a41186a20072903002218370300200441b0026a41106a20032903002219370300200441b0026a41086a200e2903002221370300200420042903c00322243703b00220022024370000200241086a2021370000200241106a2019370000200241186a2018370000200241206a2005290300370000200241276a2013290000370000200420083a00c003200441f0006a200441c0036a20044198026a10840420042d00702208411f470d0d201141506a2111200141306a2201200d470d000b200d21010c0d0b410441011037000b200141011037000b1031000b41f00041081037000b411041081037000b410141011037000b410141011037000b411041081037000b200b41041037000b410341011037000b410341011037000b410141011037000b200428027421122004280278211002402011450d00200141306a2101200441c0036a4101722102200441c0036a41276a210b200441c0036a41206a2107200441c0036a41186a210e200441c0036a41086a2111034020012d0000210c200b200141286a2900003700002007200141216a290000370300200e200141196a290000370300200441c0036a41106a2203200141116a2900003703002011200141096a2900003703002004200141016a2900003703c003200c4110460d01200441b0026a41276a2213200b290000370000200441b0026a41206a22052007290300370300200441b0026a41186a200e2903002218370300200441b0026a41106a20032903002219370300200441b0026a41086a20112903002221370300200420042903c00322243703b00220022024370000200241086a2021370000200241106a2019370000200241186a2018370000200241206a2005290300370000200241276a20132900003700002004200c3a00c003200441c0036a108204200141306a2201200d470d000b0b0240200f450d002006102a0b0240200428029c02450d00200428029802102a0b024020084105470d002010450d002012102a0b200041cd8fc60036020420004101360200200041086a41253602000c190b02402001200d460d00200441c0036a4101722102200441c0036a41276a210c200441c0036a41206a210b200441c0036a41186a2107200441c0036a41086a210e034020012d00002108200c200141286a290000370000200b200141216a2900003703002007200141196a290000370300200441c0036a41106a2211200141116a290000370300200e200141096a2900003703002004200141016a2900003703c00320084110460d01200441b0026a41276a2203200c290000370000200441b0026a41206a2213200b290300370300200441b0026a41186a20072903002218370300200441b0026a41106a20112903002219370300200441b0026a41086a200e2903002221370300200420042903c00322243703b00220022024370000200241086a2021370000200241106a2019370000200241186a2018370000200241206a2013290300370000200241276a2003290000370000200420083a00c003200441c0036a108204200141306a2201200d470d000b0b0240200f450d002006102a0b2004280298022101200429029c0221182000411c6a41003a0000200041146a2018370200200041106a20013602002000410c6a2017360200200041086a2016360200200020103602042000411d6a20042f0080023b0000200041003602002000411f6a20044182026a2d00003a00000c180b200e102a2000419c90c4003602040c160b200e102a2000419c90c4003602040c150b200e102a2000419c90c4003602040c140b200e102a2000419c90c4003602040c130b200e102a2000419c90c4003602040c120b200e102a2000419c90c4003602040c110b200e102a2000419c90c4003602040c100b200e102a2000419c90c4003602040c0f0b200f2d000d22024104460d05200241fb01710d05200e102a201121020c0b0b200f2d000d22024104460d02200241fb01710d02200e102a201121020c0a0b200f2d000d22024104460d00200241fb01710d00200e102a201121020c090b200e102a2000419c90c4003602040c0b0b200e102a2000419c90c4003602040c0a0b200e102a2000419c90c4003602040c090b200e102a2000419c90c4003602040c080b200e102a2000419c90c4003602040c070b02400240200241bbffc500460d0041bbffc5002002410b109c050d010b4126210c419c90c400210e200f2d000c41e000470d01200f2802080d0120112102200f2d000d4104460d040c010b0240200241dfffc500460d0041dfffc5002002410b109c050d030b4126210c419c90c400210e200f2d000c41e000470d00200f2802080d0020112102200f2d000d4104460d030b200e2108200c21010b200020083602040c040b0240200241ac81c600460d0041ac81c6002002410b109c050d030b024041021028220c450d00200c41003b0000200f2d000c41e000470d02200f2802084102470d020240200f280200220e200c460d0041002101034020014102460d01200c20016a2102200e20016a2108200141016a210120082d000020022d0000470d040c000b0b200f2d000d4104470d02200c102a201121020c010b0b410241011037000b200c102a0b412621012000419c90c4003602040b20004101360200200041086a200136020002402007450d00200b200741306c6a2111200b210703402007220041306a21070240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102a0c0d0b0240200041086a280200450d00200041046a280200102a0b200041146a280200450d0c200041106a280200102a0c0c0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102a0c0b0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102a0c0a0b200041086a280200450d09200041046a280200102a0c090b200041086a280200450d08200041046a280200102a0c080b200041086a280200450d07200041046a280200102a0c070b02402000410c6a2802002201450d00200041046a280200220c20014104746a210e03400240200c2802082202450d00200c2802002101200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41106a21010240200c41046a280200450d00200c280200102a0b2001210c2001200e470d000b0b200041086a280200450d062000280204102a0c060b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102a0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102a0c050b02402000410c6a2802002201450d00200041046a280200220c2001411c6c6a210e03400240200c2802042201450d000240200c410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41086a280200450d00200c280204102a0b200c411c6a21010240200c41146a280200450d00200c280210102a0b2001210c2001200e470d000b0b200041086a280200450d042000280204102a0c040b02402000410c6a2802002201450d00200041046a280200220c200141186c6a210e03400240200c41046a280200450d00200c280200102a0b0240200c41146a2802002202450d00200c28020c2101200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41186a21010240200c41106a280200450d00200c28020c102a0b2001210c2001200e470d000b0b200041086a280200450d032000280204102a0c030b02402000410c6a2802002201450d00200041046a280200220c2001411c6c6a210e03400240200c2802042201450d000240200c410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a220d280200220828020441ffffffff0371450d002008280200102a200d28020021080b2008102a0b200141106a2101200241706a22020d000b0b200c41086a280200450d00200c280204102a0b200c411c6a21010240200c41146a280200450d00200c280210102a0b2001210c2001200e470d000b0b200041086a280200450d022000280204102a0c020b0240200041046a2802002201450d00200041086a280200450d002001102a0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002208450d00200141046a280200450d002008102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0b200041246a280200220c450d0102402000412c6a2802002201450d00200c20014104746a210e0340200c220d41106a210c0240200d2802042201450d000240200d410c6a2802002202450d002002410c6c21020340024020012802002208450d00200141046a280200450d002008102a0b2001410c6a2101200241746a22020d000b0b200d41086a280200450d00200d280204102a0b200c200e470d000b0b200041286a280200450d012000280224102a0c010b0240200041086a280200450d00200041046a280200102a0b0240200041146a2802002201450d00200041186a280200450d002001102a0b200041246a280200450d00200041206a280200102a0b20072011470d000b0b200a450d00200b102a0b200441d0046a24000ba20301067f230041106b2202240020024100360208200242013703002000200210a001200041046a200210a001200041086a200210a00120002d0018210302400240024002400240200228020420022802082204460d00200228020021050c010b200441016a22052004490d03200441017422062005200620054b1b22064100480d030240024020040d002006102821050c010b200228020020042006102c21050b2005450d0120022006360204200220053602000b2002200441016a360208200520046a20033a0000200028020c2106200041146a2802002204200210b4010240024020022802042203200228020822056b2004490d00200228020021000c010b200520046a22002005490d03200341017422072000200720004b1b22074100480d030240024020030d002007102821000c010b200228020020032007102c21000b2000450d022002200736020420022000360200200721030b200020056a20062004109a051a200128020020012802042000200520046a100702402003450d002000102a0b200241106a24000f0b200641011037000b200741011037000b1031000bd60801037f024002400240024002400240024002400240410110282202450d00200220002d00003a0000200241014102102c2202450d01200220002d00013a0001200241024104102c2202450d02200220002d00023a0002200220002d00033a0003200241044108102c2202450d03200220002d00043a0004200220002d00053a0005200220002d00063a0006200220002d00073a0007200241084110102c2202450d04200220002d00083a0008200220002d00093a0009200220002d000a3a000a200220002d000b3a000b200220002d000c3a000c200220002d000d3a000d200220002d000e3a000e200220002d000f3a000f200241104120102c2202450d05200220002d00103a0010200220002d00113a0011200220002d00123a0012200220002d00133a0013200220002d00143a0014200220002d00153a0015200220002d00163a0016200220002d00173a0017200220002d00183a0018200220002d00193a0019200220002d001a3a001a200220002d001b3a001b200220002d001c3a001c200220002d001d3a001d200220002d001e3a001e200220002d001f3a001f2002412041c000102c2202450d06200220002d00203a0020200220002d00213a0021200220002d00223a0022200220002d00233a0023200220002d00243a0024200220002d00253a0025200220002d00263a0026200220002d00273a0027200220002d00283a0028200220002d00293a0029200220002d002a3a002a200220002d002b3a002b200220002d002c3a002c200220002d002d3a002d200220002d002e3a002e200220002d002f3a002f200220002d00303a0030200220002d00313a0031200220002d00323a0032200220002d00333a0033200220002d00343a0034200220002d00353a0035200220002d00363a0036200220002d00373a0037200220002d00383a0038200220002d00393a0039200220002d003a3a003a200220002d003b3a003b200220002d003c3a003c200220002d003d3a003d200220002d003e3a003e200220002d003f3a003f024002402001280200220041046a2802002203200041086a28020022016b41c000490d00200028020021030c010b200141c0006a22042001490d09200341017422012004200120044b1b22014100480d090240024020030d002001102821030c010b200028020020032001102c21030b2003450d0820002003360200200041046a2001360200200041086a28020021010b200041086a200141c0006a360200200320016a220041386a200241386a290000370000200041306a200241306a290000370000200041286a200241286a290000370000200041206a200241206a290000370000200041186a200241186a290000370000200041106a200241106a290000370000200041086a200241086a290000370000200020022900003700002002102a0f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b41c00041011037000b200141011037000b1031000bc32205017f057e097f047e0f7f230041c0056b22032400200241206a2903002104200241186a2903002105200241106a2903002106200241c8006a29030021072002290308210820022802002109200341086a41186a220a200241c0006a220b290300370300200341086a41106a220c200241386a220d290300370300200341086a41086a220e200241306a220f2903003703002003200241286a2202290300370308200341286a41186a2210200b290300370300200341286a41106a2211200d290300370300200341286a41086a220d200f290300370300200320022903003703282001280200210b20034180026a41186a2202200a29030037030020034180026a41106a220f200c29030037030020034180026a41086a220c200e2903003703002003200329030837038002024002400240024041381028220a450d00200a4200370308200a4200370300200a2009360210200a2003290328370214200a411c6a200d290300370200200a41246a2011290300370200200a412c6a2010290300370200200341d0016a41086a200c290300370300200341d0016a41106a200f290300370300200341d0016a41186a200229030037030020032003290380023703d001024002400240200b2802082202200b41046a280200470d00200241016a220c2002490d012002410174220d200c200d200c4b1b220cad42d0007e2212422088a70d012012a7220d4100480d010240024020020d00200d102821020c010b200b280200200241d0006c200d102c21020b2002450d02200b2002360200200b41046a200c360200200b28020821020b200b280200200241d0006c6a2202420037031020022004370308200220053703002002200a360220200220032903d00137022c200241186a4200370300200241246a428180808010370200200241346a200341d0016a41086a220a2903003702002002413c6a200341d0016a41106a220e290300370200200241c4006a200341d0016a41186a2202290300370200200b200b28020841016a3602082001280204210f20034190016a41186a200341286a41186a29030037030020034190016a41106a200341286a41106a29030037030020034190016a41086a200341286a41086a2903003703002003200329032837039001024002400240200f280200220c41f8b9c000460d00200f280204210d0c010b4100210d20034180026a410041e0021099051a200341f8016a220b4100360200200341f0016a2201420037030020024200370300200e4200370300200a4200370300200342003703d0014194031028220c450d01200c41003b0106200c4100360200200c41086a20034180026a41e002109a051a200c4190036a200b280200360200200c4188036a2001290300370200200c4180036a200341e8016a290300370200200c41f8026a200341e0016a290300370200200c41f0026a200341d0016a41086a290300370200200c20032903d0013702e802200f4100360204200f200c3602000b02400340200c41086a210a200c41066a2110200c2f0106220e41057421024100210b0240024003402002450d0120034190016a200a4120109c052201450d02200241606a2102200b41016a210b200a41206a210a2001417f4a0d000b200b417f6a210e0b200d450d02200d417f6a210d200c200e4102746a4194036a280200210c0c010b0b200c200b4102746a41e8026a20093602000c060b200341c8006a41186a20034190016a41186a22022903002212370300200341c8006a41106a20034190016a41106a220a2903002213370300200341c8006a41086a20034190016a41086a220b290300221437030020032003290390012215370348200f200f28020841016a36020820022012370300200a2013370300200b20143703002003201537039001024002400240024020102f0100220d410b490d0020034180026a410041e0021099051a200341f8016a22024100360200200341f0016a220a4200370300200341d0016a41186a4200370300200341d0016a41106a4200370300200341d0016a41086a4200370300200342003703d00141940310282211450d03201141003b010620114100360200201141086a20034180026a41e002109a05210b20114190036a200228020036020020114188036a200a29030037020020114180036a200341d0016a41186a290300370200201141f8026a200341d0016a41106a290300370200201141f0026a200341d0016a41086a290300370200201120032903d0013702e8022003200c2f00c8013b01cc012003200c41ca016a2d00003a00ce01200c41cb016a2800002116200c41cf016a2800002117200c41d3016a2800002118200c41d7016a28000021192003200c41e0016a2900003700bd012003200c2900db013703b801200c28028003211a200b200c41e8016a200c2f010641796a2202410574109a05210b201141e8026a200c4184036a2002410274109a052101200c41063b0106201120023b0106200320032f01cc013b01b401200320032d00ce013a00b601200320032903b8013703d001200320032900bd013700d501200e4107490d01201141066a2110200b200e417a6a220d4105746a200b200e41796a220a4105746a220b200241ffff0371200a6b410574109b051a200b41186a20034190016a41186a290300370000200b41106a20034190016a41106a290300370000200b41086a20034190016a41086a290300370000200b2003290390013700002001200d4102746a210b2001200a4102746a21020c020b200c41086a2201200e41016a220f4105746a2001200e4105746a2201200d200e6b410574109b051a200141186a2002290300370000200141106a200a290300370000200141086a200b2903003700002001200329039001370000200c41e8026a2202200f4102746a2002200e4102746a2202200c2f0106200e6b410274109b051a20022009360200200c200c2f010641016a3b01060c080b200c41086a2202200e41016a220a4105746a2002200e4105746a220220102f0100200e6b410574109b051a200241186a20034190016a41186a290300370000200241106a20034190016a41106a290300370000200241086a20034190016a41086a2903003700002002200329039001370000200c41e8026a220b200e4102746a2102200b200a4102746a210b200e210a0b200b200220102f0100200a6b410274109b051a20022009360200201020102f010041016a3b0100200341b0016a41026a221b20032d00b60122023a0000200341fc006a41026a221c20023a0000200320032900d50137008501200320032903d00137038001200320032f01b40122023b01b001200320032900850137006d2003200329038001370368200320023b017c200c280200220d450d05200c2f0104211020034180026a410272211d0340201b201c2d00003a0000200320032f017c3b01b00120032003290368370390012003200329006d37009501201041ffff0371210c02400240024002400240200d2f01062202410b490d00201d410041be031099051a41c40310282201450d0320014100360200200141046a20034180026a41c003109a051a2003200d2f00c8013b01cc012003200d41ca016a2d00003a00ce012003200d41db016a2900003703b8012003200d41e0016a2900003700bd01200d41cb016a280000211e200d41cf016a280000211f200d41d3016a2800002120200d41d7016a2800002121200d4180036a2802002122200141086a200d41e8016a200d2f0106220a41796a2202410574109a052123200141e8026a200d4184036a2002410274109a05212420014194036a200d41b0036a200a417a6a220e410274109a052109200d41063b0106200120023b01060240200e450d00410021022009210a0340200a280200220b20023b0104200b2001360200200a41046a210a200e200241016a2202470d000b0b200320032d00ce0122023a00b601200320032f01cc01220a3b01b401200320032903b8013703d001200320032900bd013700d50120034180016a41026a220e20023a00002003200a3b018001200320032903d00137038002200320032900d50137008502201041ffff0371220a4107490d012023200c417a6a220b4105746a2023200c41796a22024105746a220a20012f010620026b410574109b051a200a41186a200329009501370000200a201936000f200a201836000b200a2017360007200a2016360003200a41026a201b2d00003a0000200a20032f01b0013b0000200a2003290390013700132024200b410274220a6a202420024102746a221020012f0106221620026b410274109b051a2010201a3602002001201641016a22103b0106200c410274221620096a416c6a2009200a6a220a201041ffff0371220c200b6b410274109b051a200a2011360200200c200b490d02200120166a41fc026a210a0340200a280200220b200241016a22023b0104200b2001360200200a41046a210a2002200c490d000c030b0b200d41086a220a200c41016a220b4105746a200a200c4105746a220a2002200c6b410574109b051a200a41186a200329009501370000200a201936000f200a201836000b200a2017360007200a2016360003200a41026a200341b0016a41026a2d00003a0000200a20032f01b0013b0000200a200329039001370013200d41e8026a2202200b410274220a6a2002200c41027422016a2202200d2f0106220e200c6b410274109b051a2002201a360200200d200e41016a22023b01062001200d4194036a220c6a41086a200c200a6a220a200241ffff03712201200b6b410274109b051a200a2011360200201041ffff037120014f0d0b200d200b417f6a22024102746a4198036a210a0340200a280200220b200241016a22023b0104200b200d360200200a41046a210a20022001490d000c0c0b0b200d41086a2202200c41016a22104105746a2002200c4105746a2202200d2f0106200c6b410574109b051a200241186a2003290095013700002002201936000f2002201836000b2002201736000720022016360003200241026a201b2d00003a0000200220032f01b0013b00002002200329039001370013200d41e8026a220b201041027422096a200b200c41027422026a220b200d2f01062216200c6b410274109b051a200b201a360200200d201641016a220b3b01062002200d4194036a22166a41086a201620096a2209200b41ffff0371220b20106b410274109b051a20092011360200200a200b4f0d00200d20026a4198036a210203402002280200220a200c41016a220c3b0104200a200d360200200241046a2102200b200c470d000b0b201c200e2d00003a0000200320032f0180013b017c2003200329038002370368200320032900850237006d200d28020022020d01201e21162021211920202118201f2117200121112022211a0c080b41c40341041037000b200d2f01042110201e21162021211920202118201f21172002210d2022211a200121110c000b0b41940341041037000b41940341041037000b1031000b200d41081037000b413841081037000b20034180026a410272410041be031099051a41c40310282202450d0120024100360200200241046a20034180026a41c003109a051a2002200f280200220a36029403200f2002360200200f200f28020441016a360204200a41003b0104200a2002360200200220022f0106220b4105746a220a41086a20032f017c3b0000200a410a6a200341fc006a41026a2d00003a0000200a41176a2019360000200a41136a2018360000200a410f6a2017360000200a410b6a2016360000200a411b6a2003290368370000200a41206a200329006d37000020024194036a200b41016a220a4102746a20113602002002200b4102746a41e8026a201a3602002002200a3b01062011200a3b0104201120023602000b20002005370310200020083703002000200329032837032020002007370340200041186a200437030020002006370308200041286a200341306a290300370300200041306a200341386a290300370300200041386a200341286a41186a290300370300200341c0056a24000f0b41c40341041037000b0a0041c8c2c2001032000b5101027e024002402003450d002002280200450d010b41b698c40041f4031050000b2001280218220342002003290308220420023502047d2205200520045622021b37030820004105410420021b3602000bee0201047f024002400240024002402002417f4c0d000240024020020d00410121060c010b200210282206450d020b200620012002109a0521062004417f4c0d000240024020040d0041012101410021070c010b20042107200410282201450d030b200120032004109a052103024020002802082201200041046a280200470d00200141016a22082001490d05200141017422092008200920084b1b220841ffffff3f712008470d05200841057422094100480d050240024020010d002009102821010c010b200028020020014105742009102c21010b2001450d0420002001360200200041046a2008360200200028020821010b200028020020014105746a220141003602182001200336020c2001200236020820012002360204200120063602002001411c6a2005360200200141146a2004360200200141106a20073602002000200028020841016a3602080f0b1036000b200241011037000b200441011037000b200941041037000b1031000bf90e05047f027e027f017e027f230041c00c6b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320022802042105200241246a2802002106200241346a280200210302400240200241146a2802002207450d004105210220012802002802182802402802bc012003490d010b200441286a4200370300200441206a4200370300200441186a420037030020012802182202420020022903082208427f20012802102903482209420586200942ffffffffffffffff07832009521b7d22092009200856220a1b3703082004420037031041052102200a0d000240024020012802142802082005200441106a4120101741026a220a41024b0d00200a0e03020001020b41a0fac5001032000b0240024020070d00410121034100210b0c010b2004200128021029034842002003ad220c4200109f052001280218220a4200200a2903082209427f200429030020042903084200521b7d22082008200956220a1b370308200a0d012003417f4c0d060240024020030d004101210b02402001280214280208200641014100101741026a220341024b0d0020030e03040002040b41a0fac5001032000b024002402003102e220b450d00024020012802142802082006200b2003101741026a220341024b0d0020030e03020003020b41a0fac5001032000b200341011037000b200b102a0c020b200c422086200c842109200b4521030b20012802002101200441306a41186a220a200441106a41186a290300370300200441306a41106a2205200441106a41106a290300370300200441306a41086a2206200441106a41086a2903003703002004200429031037033020012802182107024020030d0020072802402802bc012009422088a74f0d002009a7450d01200b102a0c010b200441d0006a41186a200a290300370300200441d0006a41106a2005290300370300200441d0006a41086a20062903003703002004200429033037035020072802180d062007417f360218200441a8016a200741e8006a290000370300200441a0016a200741e0006a29000037030020044198016a200741d8006a2900003703002004200729005037039001024002402007411c6a220d280200220a41f8b9c000460d00200741206a28020021060c010b41002106200441e0096a410041e0021099051a200441c0016a410041a0081099051a41880b1028220a450d08200a41003b0106200a4100360200200a41086a200441e0096a41e002109a051a200a41e8026a200441c0016a41a008109a051a200741206a41003602002007200a36021c0b024002400340200a2f0106220e4105742105410021024100210302400240034020052002460d0120044190016a200a20026a41086a4120109c052201450d02200241206a2102200341016a21032001417f4a0d000b2003417f6a210e0b2006450d022006417f6a2106200a200e4102746a41880b6a280200210a0c010b0b200741246a2101410121020c010b200441f0006a41186a20044190016a41186a290300370300200441f0006a41106a20044190016a41106a290300370300200441f0006a41086a20044190016a41086a2903003703002004200429039001370370200741246a210141002106200e2103410021020b0240024020020d00200441fc096a200441f0006a41086a290300370200200441840a6a200441f0006a41106a2903003702002004418c0a6a200441f0006a41186a290300370200200420013602f009200420033602ec092004200d3602e8092004200a3602e409200420063602e009200420042903703702f409200441e0016a20042903b001370300200441e8016a200441b0016a41086a290300370300200441f4016a4200370200200442003703d801200442003703c001200441f8b9c0003602f001200441003a00fc01200441fd016a20042900900137000020044185026a20044190016a41086a2900003700002004418d026a20044190016a41106a29000037000020044195026a20044190016a41186a290000370000200441003a009d02200441e0096a200441c0016a10b70121020c010b200441d8016a4200370300200441d4016a41f8b9c000360200200441003602e001200441003602d001200442003703c801200441f8b9c0003602c401200441003602c001200a200341e0006c6a41e8026a2102200441c0016a1095010b200441c0016a41186a200441d0006a41186a290300370300200441c0016a41106a200441d0006a41106a290300370300200441c0016a41086a200441d0006a41086a290300370300200420042903503703c00120042009370294012004200b36029001200441e0096a200241306a200441c0016a20044190016a10bd01024020042802e009450d0020042802e4092202450d00200441e8096a280200450d002002102a0b2007200728021841016a360218410421020b20002002360200200441c00c6a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b41a8b8c0004110200441c0016a41d0b8c0001038000b41880b41081037000b900302017f027e230041c0006b22042400024002402003450d0020022802000d0020022802042103200441186a4200370300200441106a4200370300200441086a420037030020012802182202420020022903082205427f20012802102903482206420586200642ffffffffffffffff07832006521b7d2206200620055622021b3703082004420037030002400240024020020d00024002402001280214280208200320044120101741026a220241024b0d0020020e03020001020b41a0fac5001032000b200441206a2001280200280218220241186a200241d0006a2002410c6a4100200228020c1b200410a7012004280220450d01200441306a41086a2203200441206a41086a28020036020020042004290320370330200141046a21020240200141086a280200450d002002280200102a0b20022004290330370200200241086a2003280200360200410021010c020b200041053602000c030b2001410c6a4100360200410121010b20004100360200200020013602040c010b41b698c40041f4031050000b200441c0006a24000bae0f06017f017e057f027e037f027e230041d0016b220424000240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042103200241286a2903002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a2802002109200441286a20012802102903484200200241146a280200220aad4200109f052001280218220242002002290308220b427f200429032820042903304200521b7d220c200c200b5622021b370308024020020d00200a417f4c0d0802400240024002400240200a0d004101210d02402001280214280208200341014100101741026a220241024b0d00200141146a210e20020e03060002060b41a0fac5001032000b0240200a102e220d450d00024020012802142802082003200d200a101741026a220241024b0d00200141146a210e20020e03030002030b41a0fac5001032000b200a41011037000b41002102200441003a00980102400340200a2002460d01200441f8006a20026a200d20026a2d00003a00002004200241016a22033a0098012003210220034120470d000b200441a0016a41186a2202200441f8006a41186a290300370300200441a0016a41106a2203200441f8006a41106a290300370300200441a0016a41086a220f200441f8006a41086a290300370300200420042903783703a0010240200a450d00200d102a0b200441386a41086a200f290300370300200441386a41106a2003290300370300200441386a41186a2002290300370300200420042903a001370338200441186a200128021029034842002007ad4200109f052001280218220242002002290308220b427f200429031820042903204200521b7d220c200c200b5622021b37030820020d042007417f4c0d0c20070d03200e280200280208200641014100101741026a220241024b0d0220020e03040204040b0240200241ff0171450d00200441003a0098010b200a450d030b200d102a0c020b41a0fac5001032000b0240024002402007102e2202450d000240200e280200280208200620022007101741026a220341024b0d0020030e03030002030b41a0fac5001032000b200741011037000b2007410f4d0d00200241086a2900002110200229000021112002102a200441086a200128021029034842002009ad4200109f052001280218220242002002290308220b427f200429030820042903104200521b7d220c200c200b5622021b37030820020d01200141046a210a0240024020092001410c6a220d28020022034b0d00200921020c010b02400240200141086a280200220220036b200920036b2206490d00200a2802002107200321020c010b200320066a22072003490d0d2002410174220e2007200e20074b1b220e4100480d0d0240024020020d00200e102821070c010b200a2802002002200e102c21070b2007450d0c20012007360204200141086a200e3602002001410c6a28020021020b200720026a210e0240024020064102490d00200e410020092003417f7322036a22061099051a2007200920026a20036a6a210e200620026a21020c010b2006450d010b200e41003a0000200241016a21020b200d2002360200024002402001280214280208200820012802042002101741026a220241024b0d0020020e03030001030b41a0fac5001032000b2001410c6a2202280200210720024100360200200141086a28020021032001280204210d2001420137020420012802182202290308220c210b024002402005500d002005210b200c2005540d010b2002200c200b7d3703082002290310210c200441a0016a41186a200241186a2903003703002004200b3703a8012004200b3703a0012004200c3703b001200128020041186a2802002106200441f8006a41186a200441386a41186a290300370300200441f8006a41106a200441386a41106a290300370300200441f8006a41086a200441386a41086a29030037030020042004290338370378200420073602c801200420033602c4012004200d3602c001200441d8006a2006200441f8006a20112010200441a0016a200441c0016a10c101410121090240024020042802584101460d00200441d8006a410472210d200441d8006a41106a2d00002107200441e4006a2802002106200441e0006a2802002103410021090c010b200441e4006a210d200441ec006a2802002106200441d8006a41106a2802002103410021070b200d280200210d200220042903a80120022903087c370308200141086a2802002102024020090d0002402002450d00200a280200102a0b200a200d3602000c0e0b2002450d00200a280200102a0b200a200d3602004180022107410021060c0c0b2002102a0b200041053602000c0b0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200e41011037000b1031000b2001410c6a2006360200200141086a200336020020004100360200200020073602040b200441d0016a24000bc71006017f017e057f027e037f027e230041e0016b2204240002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802204101470d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620022802042103200241286a2903002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a2802002109200441206a20012802102903484200200241146a280200220aad4200109f052001280218220242002002290308220b427f200429032020042903284200521b7d220c200c200b5622021b3703080240024020020d00200a417f4c0d0902400240024002400240200a0d004101210d02402001280214280208200341014100101741026a220241024b0d00200141146a210e20020e03060002060b41a0fac5001032000b0240200a102e220d450d00024020012802142802082003200d200a101741026a220241024b0d00200141146a210e20020e03030002030b41a0fac5001032000b200a41011037000b41002102200441003a00c80102400340200a2002460d01200441a8016a20026a200d20026a2d00003a00002004200241016a22033a00c8012003210220034120470d000b20044188016a41186a2202200441a8016a41186a29030037030020044188016a41106a2203200441a8016a41106a29030037030020044188016a41086a220f200441a8016a41086a290300370300200420042903a801370388010240200a450d00200d102a0b200441306a41086a200f290300370300200441306a41106a2003290300370300200441306a41186a20022903003703002004200429038801370330200441106a200128021029034842002007ad4200109f052001280218220242002002290308220b427f200429031020042903184200521b7d220c200c200b5622021b37030820020d042007417f4c0d0d20070d03200e280200280208200641014100101741026a220241024b0d0220020e03040204040b0240200241ff0171450d00200441003a00c8010b200a450d030b200d102a0c020b41a0fac5001032000b0240024002402007102e2202450d000240200e280200280208200620022007101741026a220341024b0d0020030e03030002030b41a0fac5001032000b200741011037000b2007410f4d0d00200241086a2900002110200229000021112002102a2004200128021029034842002009ad4200109f052001280218220242002002290308220b427f200429030020042903084200521b7d220c200c200b5622021b37030820020d01200141046a21070240024020092001410c6a220a28020022034b0d00200921020c010b02400240200141086a280200220220036b200920036b2206490d002007280200210d200321020c010b200320066a220d2003490d0e2002410174220e200d200e200d4b1b220e4100480d0e0240024020020d00200e1028210d0c010b20072802002002200e102c210d0b200d450d0d2001200d360204200141086a200e3602002001410c6a28020021020b200d20026a210e0240024020064102490d00200e410020092003417f7322036a22061099051a200d200920026a20036a6a210e200620026a21020c010b2006450d010b200e41003a0000200241016a21020b200a2002360200024002402001280214280208200820012802042002101741026a220241024b0d0020020e03030001030b41a0fac5001032000b2001410c6a2202280200210d20024100360200200141086a28020021032001280204210a2001420137020420012802182202290308220c210b0240024002402005500d002005210b200c2005540d010b2002200c200b7d3703082002290310210c20044188016a41186a200241186a2903003703002004200b370390012004200b370388012004200c37039801200128020041186a28020021062004200d360258200420033602542004200a360250200441a8016a20062011201020044188016a200441306a200441d0006a10b5014101210d0240024020042802a8014101460d00200441d0006a41086a200441a8016a41186a290300370300200441d0006a41106a200441c8016a2802003602002004200441a8016a41106a290300370350200441d8016a2d00002106200441d0016a2802002109200441cc016a2802002108200441b4016a280200210e200441a8016a41086a28020021034100210d20042802ac01210a0c010b200441bc016a280200210e200441b8016a2802002103200441b4016a280200210a410021060b200220042903900120022903087c370308200441f0006a41086a2202200441d0006a41086a290300370300200441f0006a41106a220f200441d0006a41106a280200360200200420042903503703700240200d0d00200441bc016a2002290300370200200441c4016a200f2802003602002004200e3602b001200420033602ac012004200a3602a801200420042903703702b4010240200141086a280200450d002007280200102a0b200120083602042001410c6a4100360200200141086a2009360200200641ff017122020d02200441a8016a2007108f010c020b200141086a280200450d002007280200102a0b2001200a3602042001410c6a4100360200200141086a200336020041800221020b20004100360200200020023602040c020b2002102a0b200041053602000b200441e0016a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200e41011037000b1031000b9d0503027f037e057f230041206b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441106a20012802102903184200200241146a2802002203ad22064200109f0520012802182202420020022903082207427f200429031020042903184200521b7d2208200820075622021b370308024020020d0020042001280210290348420020064200109f0520012802182202420020022903082207427f200429030020042903084200521b7d2208200820075622021b37030820020d000240024020032001410c6a2209280200220a4b0d00200321020c010b02400240200141086a2802002202200a6b2003200a6b220b490d002001280204210c200a21020c010b200a200b6a220c200a490d062002410174220d200c200d200c4b1b220d4100480d060240024020020d00200d1028210c0c010b20012802042002200d102c210c0b200c450d052001200c360204200141086a200d3602002001410c6a28020021020b200c20026a210d02400240200b4102490d00200d41002003200a417f73220a6a220b1099051a200c200320026a200a6a6a210d200b20026a21020c010b200b450d010b200d41003a0000200241016a21020b20092002360200024002402001280214280208200520012802042002101741026a220241024b0d0020020e03020001020b41a0fac5001032000b2001410c6a2202280200210320024100360200200141086a280200210220012802042105200142013702040240200128021c220a450d00200141206a280200450d00200a102a0b2001200536021c200141246a2003360200200141206a20023602000b20004105360200200441206a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b200d41011037000b1031000b23002001410c6a4100360200200128020041206a200141046a108f01200041043602000b27002001410c6a4100360200200128020028021841d0006a200141046a108f01200041043602000bd50102027f027e410021042001410c6a41003602002001280218220541186a2903002106200529031021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102821050c010b200128020420052004102c21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b200441011037000b1031000bc20103017f017e017f410021042001410c6a4100360200200128021829030821050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102821060c010b200128020420062004102c21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b200441011037000b1031000bb804020b7f027e230041206b220424002001410c6a41003602000240024002402001280200280218220528021841016a220641004c0d00200541d0006a2107200520063602182005411c6a2108200541206a28020021090240024003402008280200220a41086a210b200a2f0106220c41057421084100210d0240024003402008450d012007200b4120109c05220e450d02200841606a2108200d41016a210d200b41206a210b200e417f4a0d000b200d417f6a210c0b2009450d022009417f6a2109200a200c4102746a41880b6a21080c010b0b200a200d41e0006c6a220841c5036a310000200841e8026a290300220f200f50220b1ba7450d004200200841f8026a290300200b1b210f4200200841f0026a290300200b1b21100c010b200441086a200541286a28020020072005412c6a28020028021c110500200441106a290300210f20052802182106200429030821100b20052006417f6a36021802400240200141086a280200220b2001410c6a28020022086b4110490d002001280204210b0c010b200841106a220d2008490d03200b4101742208200d2008200d4b1b22084100480d0302400240200b0d0020081028210b0c010b2001280204200b2008102c210b0b200b450d022001200b360204200141086a20083602002001410c6a28020021080b2001410c6a200841106a360200200b20086a2208200f3700082008201037000020004104360200200441206a24000f0b41b8b8c0004118200441186a41e0b8c0001038000b200841011037000b1031000bd50102027f027e410021042001410c6a41003602002001280200220541086a2903002106200529030021070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102821050c010b200128020420052004102c21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b200441011037000b1031000b860302047f027e230041c0006b220424000240024002402003450d0020022802000d0020034101460d0120022802100d01410521050240200241146a28020022032001280210220628026c4b0d0020022802042107200441086a200629034842002003ad4200109f0520012802182202420020022903082208427f200429030820042903104200521b7d2209200920085622021b37030820020d002003417f4c0d0302400240024020030d004101210202402001280214280208200741014100101741026a220641024b0d0020060e03040002040b41a0fac5001032000b02402003102e2202450d0002402001280214280208200720022003101741026a220641024b0d0020060e03030002030b41a0fac5001032000b200341011037000b2001410c6a4100360200200441186a2002200310a803410421052004200141046a36023c200441186a2004413c6a10c8012003450d010b2002102a0b20002005360200200441c0006a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b1036000bc20103017f017e017f410021042001410c6a4100360200200128020029031021050240024002400240200141086a28020022064108490d00200128020421060c010b200641017422044108200441084b1b22044100480d020240024020060d002004102821060c010b200128020420062004102c21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441086a360200200620046a2005370000200041043602000f0b200441011037000b1031000bdc0102027f027e410021042001410c6a4100360200200128020028021828024022054180016a2903002106200529037821070240024002400240200141086a28020022054110490d00200128020421050c010b200541017422044110200441104b1b22044100480d020240024020050d002004102821050c010b200128020420052004102c21050b2005450d0120012005360204200141086a20043602002001410c6a28020021040b2001410c6a200441106a360200200520046a2201200637000820012007370000200041043602000f0b200441011037000b1031000bb20803027f047e027f230041e0046b2204240002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200441286a20012802102903484200200241146a2802002202ad4200109f0520012802182203420020032903082206427f200429032820042903304200521b7d2207200720065622031b3703080240024020030d002002417f4c0d0402400240024020020d004101210302402001280214280208200541014100101741026a220541024b0d0020050e03040002040b41a0fac5001032000b02402002102e2203450d0002402001280214280208200520032002101741026a220541024b0d0020050e03030002030b41a0fac5001032000b200241011037000b2004200236023c20042003360238200441d0036a200441386a108101024020042802d00322054113460d00200441c8026a200441d0036a410472418401109a051a02402002450d002003102a0b200441c0016a200441c8026a418401109a051a20042005360238200441386a410472200441c0016a418401109a051a200441003602d803200442013703d003200441386a200441d0036a10eb0120042802d8032103024020042802d403450d0020042802d003102a0b200128021822022903102206200241186a2903002207844200510d07200441186a2003ad42004280c8afa0254200109f05200441086a200429031822084280a094a58d1d7c2209200441186a41086a2903002009200854ad7c2006200710a00520024200200229030822062004290308427f200441086a41086a290300501b7d220720072006561b37030820072006580d03200441386a106a0c020b2002450d010b2003102a0b410521020c070b20012802002102200441c8026a200441386a418801109a051a200441c0016a41086a2002280218220241d8006a290000370300200441d0016a2203200241e0006a290000370300200441d8016a2205200241e8006a290000370300200420022900503703c001200441d7036a200441c8026a418801109a051a02402002413c6a2802002201200241386a280200470d00200141016a220a2001490d062001410174220b200a200b200a4b1b220aad42b0017e2206422088a70d062006a7220b4100480d060240024020010d00200b102821010c010b2002280234200141b0016c200b102c21010b2001450d0520022001360234200241386a200a360200200228023c21010b2002280234200141b0016c6a220141013a0000200120042903c001370001200141096a200441c8016a290300370000200141116a2003290300370000200141196a2005290300370000200141216a200441d0036a418f01109a051a2002200228023c41016a36023c410421020c060b41b698c40041f4031050000b41b698c40041f4031050000b1036000b419cb7c0001032000b200b41081037000b1031000b20002002360200200441e0046a24000b8c1705087f027e037f027e047f230041a0026b22042400024002400240024002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d0320034104460d0420022802400d0420034105460d0520022802500d0520034106460d0620022802600d0620034107460d0720022802700d0720022802042103200241246a2802002105200241346a2802002106200241c4006a2802002107200241d4006a2802002108200241e4006a2802002109200241f4006a280200210a200441206a20012802102903484200200241146a280200220bad4200109f052001280218220242002002290308220c427f200429032020042903284200521b7d220d200d200c5622021b3703080240024020020d00200b417f4c0d0a024002400240200b0d004101210e02402001280214280208200341014100101741026a220241024b0d00200141146a210f20020e03040002040b41a0fac5001032000b0240200b102e220e450d00024020012802142802082003200e200b101741026a220241024b0d00200141146a210f20020e03030002030b41a0fac5001032000b200b41011037000b41002102200441003a00f00102400340200b2002460d01200441d0016a20026a200e20026a2d00003a00002004200241016a22033a00f0012003210220034120470d000b20044180026a41086a2202200441d0016a41086a29030037030020044180026a41106a2203200441d0016a41106a29030037030020044180026a41186a2210200441d0016a41186a290300370300200420042903d001370380020240200b450d00200e102a0b200441306a41086a2002290300370300200441306a41106a2003290300370300200441306a41186a20102903003703002004200429038002370330200441106a200128021029034842002006ad4200109f052001280218220242002002290308220c427f200429031020042903184200521b7d220d200d200c5622021b3703082002450d030c100b0240200241ff0171450d00200441003a00f0010b200b450d010b200e102a0b200441f0006a41186a20044180026a41186a290300370300200441f0006a41106a20044180026a41106a290300370300200441f0006a41086a20044180026a41086a2903003703002004200429038002370370410521020c0e0b2006417f4c0d080240024002400240024020060d004101210b0240200f280200280208200541014100101741026a220241024b0d0020020e03120002120b41a0fac5001032000b02402006102e220b450d000240200f2802002802082005200b2006101741026a220241024b0d0020020e03030002030b41a0fac5001032000b200641011037000b41002102200441003a00f0010240034020062002460d01200441d0016a20026a200b20026a2d00003a00002004200241016a22033a00f0012003210220034120470d000b20044180026a41086a2202200441d0016a41086a29030037030020044180026a41106a2203200441d0016a41106a29030037030020044180026a41186a220e200441d0016a41186a290300370300200420042903d0013703800202402006450d00200b102a0b200441d0006a41086a2002290300370300200441d0006a41106a2003290300370300200441d0006a41186a200e29030037030020042004290380023703502004200128021029034842002008ad4200109f052001280218220242002002290308220c427f200429030020042903084200521b7d220d200d200c5622031b3703084105210220030d112008417f4c0d0c20080d03200f280200280208200741014100101741026a220341024b0d0220030e03110211110b0240200241ff0171450d00200441003a00f0010b2006450d0f0b200b102a410521020c0f0b41a0fac5001032000b024002400240024002402008102e2203450d000240200f280200280208200720032008101741026a220b41024b0d00200b0e03030002030b41a0fac5001032000b200841011037000b2008410f4d0d00200341086a2900002111200329000021122003102a024002400240200a0d00410121064100210b4100210e0c010b20044180026a41186a210320044180026a41106a210520044180026a41086a210841002110410021024100210b4100210e4101210603402003420037030020054200370300200842003703002001280218220742002007290308220d427f2001280210290348220c420586200c42ffffffffffffffff0783200c521b7d220c200c200d5622071b370308200442003703800220070d1102400240200f280200280208200920026a221320044180026a4120101741026a220741024b0d0020070e03130001130b41a0fac5001032000b200441d0016a41186a22142003290300370300200441d0016a41106a22152005290300370300200441d0016a41086a2216200829030037030020042004290380023703d0010240200b200e470d002010200b41016a220e2010200e4b1b220e41ffffff3f71200e470d03200e41057422074100480d0302400240200b0d002007102821060c010b200620022007102c21060b2006450d100b200620026a220720042903d001370000200741186a2014290300370000200741106a2015290300370000200741086a2016290300370000201341206a2013490d11201041026a2110200241206a2102200a200b41016a220b470d000b0b2001280200280218210320044190016a41086a200441306a41086a29030037030020044190016a41106a2201200441306a41106a29030037030020044190016a41186a2205200441306a41186a290300370300200441b0016a41086a200341d8006a290000370300200441b0016a41106a2208200341e0006a290000370300200441b0016a41186a2207200341e8006a2900003703002004200429033037039001200420032900503703b00120044180026a41186a220a200441d0006a41186a29030037030020044180026a41106a2209200441d0006a41106a29030037030020044180026a41086a200441d0006a41086a29030037030020042004290350370380022003413c6a2802002202200341386a280200470d03200241016a220f2002490d0020024101742210200f2010200f4b1b220fad42b0017e220c422088a70d00200ca7221041004e0d020b1031000b2003102a0c0f0b0240024020020d002010102821020c010b2003280234200241b0016c2010102c21020b2002450d0b20032002360234200341386a200f360200200328023c21020b2003280234200241b0016c6a220241023a0000200220042903b0013700012002200429039001370021200241096a200441b0016a41086a290300370000200241116a2008290300370000200241196a2007290300370000200241296a20044190016a41086a290300370000200241316a2001290300370000200241396a2005290300370000200220063600642002200e3600682002200b36006c20022012370370200241f8006a20113703002002200429038002370041200241c9006a20044180026a41086a290300370000200241d1006a2009290300370000200241d9006a200a290300370000200220042f00703b0061200241e3006a200441f0006a41026a2d00003a0000200220042903d0013703800120024188016a200441d0016a41086a29030037030020024190016a200441d0016a41106a29030037030020024198016a200441d0016a41186a290300370300200241a0016a200441f0016a290300370300200241a8016a200441f8016a2903003703002003200328023c41016a36023c410421020c0d0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200741011037000b201041081037000b41052102200e450d012006102a0c010b410521020b20002002360200200441a0026a24000b16002000410036020020002001410c6a2802003602040bab0202057f027e230041106b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d024105210302402001410c6a2802002205200241146a2802002206490d00200520066b200241246a2802002205470d0020022802042107200128020421082004200128021029035042002005ad4200109f0520012802182202420020022903082209427f200429030020042903084200521b7d220a200a20095622021b37030820020d000240024020012802142802082007200820066a2005101841026a220241024b0d0020020e03020001020b41b0fbc5001032000b410421030b20002003360200200441106a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000bf90303027f027e067f230041106b2204240002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002203ad4200109f0520012802182202420020022903082206427f200429030020042903084200521b7d2207200720065622021b37030841052108024020020d000240024020032001410c6a2209280200220a4b0d00200321020c010b02400240200141086a2802002202200a6b2003200a6b220b490d002001280204210c200a21020c010b200a200b6a220c200a490d062002410174220d200c200d200c4b1b220d4100480d060240024020020d00200d1028210c0c010b20012802042002200d102c210c0b200c450d052001200c360204200141086a200d3602002001410c6a28020021020b200c20026a210d02400240200b4102490d00200d41002003200a417f73220a6a220b1099051a200c200320026a200a6a6a210d200b20026a21020c010b200b450d010b200d41003a0000200241016a21020b20092002360200024002402001280214280208200520012802042002101741026a220141024b0d0020010e03020001020b41a0fac5001032000b410421080b20002008360200200441106a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b200d41011037000b1031000bbb0b05047f027e037f017e037f230041e0016b2204240002400240024002400240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120034102460d0220022802200d0220034103460d0320022802300d03200241246a2802002105200241346a280200210602400240024002400240200241146a2802002203450d0020022802042107200441306a200128021029034842002003ad4200109f0520012802182202420020022903082208427f200429033020042903384200521b7d22092009200856220a1b37030841052102200a0d0e2003417f4c0d092003102e220a450d0a024020012802142802082007200a2003101741026a220741024b0d0020070e03040002040b41a0fac5001032000b4101210b410021074100210c0c010b2004200336028c012004200a36028801200441c0006a20044188016a106d200429024421082004280240210b200a102a200b450d0c2008a7210c200128021028025c2008422088a72207490d0b0b200b2007410041202007676b10c402024020074102490d00200b21022007210303402002200241206a220a4120109c05450d0c200a21022003417f6a220341024f0d000b0b200441206a200128021029034842002006ad220d4200109f0520012802182202420020022903082208427f200429032020042903284200521b7d2209200920085622021b37030820020d0a2006417f4c0d060240024020060d004101210a02402001280214280208200541014100101741026a220241024b0d0020020e030d00020d0b41a0fac5001032000b024002402006102e220a450d00024020012802142802082005200a2006101741026a220241024b0d0020020e03020003020b41a0fac5001032000b200641011037000b200a102a0c0b0b20042001280210220329032842002007ad4200109f05200441106a20032903204200200d4200109f0520012802182102427f2109024020042903184200520d0020042903084200520d002004290310220820042903007c220d2008540d00427f200d20032903307c22082008200d541b21090b200242002002290308220820097d220920092008561b37030820092008580d012006450d0a200a102a0c0a0b200a102a0c0a0b200441b8016a41086a22052001280200280218220341d8006a290000370300200441b8016a41106a2201200341e0006a290000370300200441b8016a41186a220e200341e8006a290000370300200420032900503703b80102402003413c6a2802002202200341386a280200470d00200241016a220f2002490d0820024101742210200f2010200f4b1b2210ad42b0017e2208422088a70d082008a7220f4100480d080240024020020d00200f102821020c010b2003280234200241b0016c200f102c21020b2002450d0720032002360234200341386a2010360200200328023c21020b2003280234200241b0016c6a220241003a0000200220042f00dd013b0001200241053a00102002200736000c2002200c3600082002200b360004200220042903b801370011200241036a200441dd016a41026a2d00003a0000200241196a2005290300370000200241216a2001290300370000200241296a200e2903003700002002200a360034200220063600382002200636003c200220042f00b5013b0031200241336a200441b5016a41026a2d00003a00002002200429038801370340200241c8006a20044188016a41086a290300370300200241d0006a20044188016a41106a290300370300200241d8006a20044188016a41186a290300370300200241e0006a200441a8016a290300370300200241e8006a200441c0006a41c800109a051a2003200328023c41016a36023c410421020c090b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b41b698c40041f4031050000b1036000b200341011037000b200f41081037000b1031000b41052102200c450d00200b102a0b20002002360200200441e0016a24000b8e0a03027f027e057f230041e00b6b220424000240024002400240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002202ad4200109f0520012802182203420020032903082206427f200429030020042903084200521b7d2207200720065622081b3703084105210320080d052002417f4c0d02024020020d0002402001280214280208200541014100101741026a220241024b0d0020020e03070007070b41a0fac5001032000b02400240024002402002102e2208450d0002402001280214280208200520082002101741026a220541024b0d0020050e03030002030b41a0fac5001032000b200241011037000b2002410f4b0d010b2008102a0c060b200841086a2900002106200829000021072008102a200128020028021822092802180d032009417f360218200441c8006a200941e8006a290000370300200441c0006a200941e0006a290000370300200441306a41086a200941d8006a29000037030020042009290050370330024002402009411c6a220a280200220841f8b9c000460d00200941206a280200210b0c010b4100210b20044180096a410041e0021099051a200441e0006a410041a0081099051a41880b10282208450d05200841003b010620084100360200200841086a20044180096a41e002109a051a200841e8026a200441e0006a41a008109a051a200941206a41003602002009200836021c0b02400240034020082f0106220c4105742105410021024100210102400240034020052002460d01200441306a200820026a41086a4120109c052203450d02200241206a2102200141016a21012003417f4a0d000b2001417f6a210c0b200b450d02200b417f6a210b2008200c4102746a41880b6a28020021080c010b0b200941246a2103410121020c010b200441106a41186a200441306a41186a290300370300200441106a41106a200441306a41106a290300370300200441106a41086a200441306a41086a29030037030020042004290330370310200941246a21034100210b200c2101410021020b0240024020020d002004419c096a200441106a41086a290300370200200441a4096a200441106a41106a290300370200200441ac096a200441106a41186a29030037020020042003360290092004200136028c092004200a3602880920042008360284092004200b36028009200420042903103702940920044180016a200429035037030020044188016a200441d0006a41086a29030037030020044194016a42003702002004420037037820044200370360200441f8b9c00036029001200441003a009c012004419d016a2004290030370000200441a5016a200441306a41086a290000370000200441ad016a200441306a41106a290000370000200441b5016a200441306a41186a290000370000200441003a00bd0120044180096a200441e0006a10b70121020c010b200441f8006a4200370300200441f4006a41f8b9c00036020020044100360280012004410036027020044200370368200441f8b9c000360264200441003602602008200141e0006c6a41e8026a2102200441e0006a1095010b200241286a2006370300200241206a2007370300200242013703182009200928021841016a360218410421030c050b41b698c40041f4031050000b41b698c40041f4031050000b1036000b41a8b8c0004110200441e0006a41d0b8c0001038000b41880b41081037000b20002003360200200441e00b6a24000ba30203037f027e027f230041206b220424002001410c6a22054100360200200441086a2001280200280218220641186a200641d0006a10a801200441086a41106a290300210720042802082106200429031021080240024002400240200141086a2802002209200528020022056b4110490d00200128020421090c010b200541106a220a2005490d0220094101742205200a2005200a4b1b22054100480d020240024020090d002005102821090c010b200128020420092005102c21090b2009450d0120012009360204200141086a20053602002001410c6a28020021050b2001410c6a200541106a360200200920056a22012007427f20061b37000820012008427f20061b37000020004104360200200441206a24000f0b200541011037000b1031000bee0203027f027e017f230041206b220424000240024002402003450d0020022802000d0020034101460d0120022802100d0120022802042105200420012802102903484200200241146a2802002202ad4200109f0520012802182203420020032903082206427f200429030020042903084200521b7d2207200720065622081b37030841052103024020080d002002417f4c0d0302400240024020020d004101210802402001280214280208200541014100101741026a220141024b0d0020010e03040002040b41a0fac5001032000b02402002102e2208450d0002402001280214280208200520082002101741026a220141024b0d0020010e03030002030b41a0fac5001032000b200241011037000b200441106a200820021054024020042802100d002004280214200441186a280200100b0b410421032002450d010b2008102a0b20002003360200200441206a24000f0b41b698c40041f4031050000b41b698c40041f4031050000b1036000bbe0101037f410021042001410c6a4100360200200128020028021c21050240024002400240200141086a28020022064104490d00200128020421060c010b200641017422044104200441044b1b22044100480d020240024020060d002004102821060c010b200128020420062004102c21060b2006450d0120012006360204200141086a20043602002001410c6a28020021040b2001410c6a200441046a360200200620046a2005360000200041043602000f0b200441011037000b1031000bc205020a7f017e230041c0006b220424002004200136020c20042000410120011b3602082004200441086a106c024020042802000d000240024002400240024002400240200428020c22014170712200417f4c0d002004280204210502400240200141047622060d00410821070c010b200010282207450d020b02402005450d00200441206a4104722108410021094100210a410021000340200441206a200441086a109803200441306a41086a220b200841086a2802003602002004200829020037033002402004280220220c4104470d002006450d0a2007102a0c0a0b200041016a2101200441106a41086a220d200b28020036020020042004290330370310024020002006470d0020092001200920014b1b220641ffffffff00712006470d062006410474220b4100480d060240024020000d00200b102821070c010b2007200a200b102c21070b2007450d050b2007200a6a2200200c360200200041046a20042903103702002000410c6a200d280200360200200941026a2109200a41106a210a2001210020052001470d000b0b2007450d07200441206a200220072005200311060020042802202100410110282201450d042004428180808010370234200420013602300240024020004105460d00200141003a0000200141014102102c2101024020004104470d002001450d08200141003a00012004428280808020370234200420013602304202210e0c020b2001450d08200141013a0001200442828080802037023420042001360230200441206a200441306a1099032004350238210e200428023021010c010b200141013a00004201210e0b2001ad422086200e84210e02402006450d002007102a0b200441c0006a2400200e0f0b1036000b200041081037000b200b41081037000b1031000b410141011037000b410241011037000b410241011037000b41b8c6c20041f000200441206a41c0c5c2001038000bde0202047f017e02400240024002400240024020012802042202450d00200128020022032d0000210420012002417f6a22053602042001200341016a3602002004417f6a220441034b0d0520040e0401020304010b200041043602000f0b0240200541034b0d00200041043602000f0b200041003602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b024020054108490d0020004101360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b0240200541034b0d00200041043602000f0b200041023602002003280001210420012002417b6a3602042001200341056a360200200020043602040f0b024020054108490d0020004103360200200329000121062001200241776a3602042001200341096a360200200041086a20063703000f0b200041043602000f0b200041043602000b840b02037f017e024002400240024002400240024002400240024002400240024020002802000e0400010203000b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0c200241017422042003200420034b1b22044100480d0c0240024020020d002004102821030c010b200128020020022004102c21030b2003450d0420012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41013a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d0c200241017422002004200020044b1b22004100480d0c0240024020020d002000102821020c010b200128020020022000102c21020b2002450d0520012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0b200241017422042003200420034b1b22044100480d0b0240024020020d002004102821030c010b200128020020022004102c21030b2003450d0520012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41023a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d0b200241017422002003200020034b1b22004100480d0b0240024020020d002000102821020c010b200128020020022000102c21020b2002450d0620012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d0a200241017422042003200420034b1b22044100480d0a0240024020020d002004102821030c010b200128020020022004102c21030b2003450d0620012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41033a00002000280204210302400240200141046a2802002202200428020022006b4104490d00200128020021020c010b200041046a22042000490d0a200241017422002004200020044b1b22004100480d0a0240024020020d002000102821020c010b200128020020022000102c21020b2002450d0720012002360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200220006a20033600000f0b02400240200141046a280200200141086a2802002202460d00200128020021030c010b200241016a22032002490d09200241017422042003200420034b1b22044100480d090240024020020d002004102821030c010b200128020020022004102c21030b2003450d0720012003360200200141046a2004360200200141086a28020021020b200141086a2204200241016a360200200320026a41043a00002000290308210502400240200141046a2802002202200428020022006b4108490d00200128020021020c010b200041086a22032000490d09200241017422002003200020034b1b22004100480d090240024020020d002000102821020c010b200128020020022000102c21020b2002450d0820012002360200200141046a2000360200200141086a28020021000b200141086a200041086a360200200220006a20053700000f0b200441011037000b200041011037000b200441011037000b200041011037000b200441011037000b200041011037000b200441011037000b200041011037000b1031000bfd0201057f230041d0006b220224002002410036022820014110200241286a10062103024002400240024020022802282204417f460d0020030d010b200041023a00000c010b2004450d0120032d0000220541014b0d01410021010240024020050e020100010b41002101200241003a00482004417f6a2105200341016a21060340024020052001470d00200141ff0171450d04200241003a00480c040b200241286a20016a200620016a2d00003a00002002200141016a22043a00482004210120044120470d000b200241086a41186a200241286a41186a290300370300200241086a41106a200241286a41106a290300370300200241086a41086a200241286a41086a29030037030020022002290328370308410121010b200020013a000020002002290308370001200041096a200241106a290300370000200041116a200241186a290300370000200041196a200241206a2903003700002003102a0b200241d0006a24000f0b41c4d1c3004133200241286a419cd9c3001038000b1300200041013602042000418cc8c2003602000b340020004195c9c20036020420004100360200200041146a4103360200200041106a41a0c9c200360200200041086a420a3702000b2f01017f02404101102822020d00410141011037000b200042818080801037020420002002360200200241003a00000b8b5606077f017e067f027e037f037e230041e0036b22012400200141d8006a41086a220242003703002001420037035841e7fcc5004110200141d8006a100820014190016a41086a20022903003703002001200129035837039001200141e8026a20014190016a109a0302400240024002400240024002400240024002400240024020012d00e80222024102470d00200141d8006a21030c010b20014190016a4110100920014188026a41086a200141f1026a29000037030020014188026a41106a200141e8026a41116a29000037030020014188026a41186a220420014181036a290000370300200120012900e90237038802200141d8006a21030240200241037122024103460d0020020e03010001010b200141a0016a41186a2004290300370300200141a0016a41106a20014188026a41106a290300370300200141a0016a41086a20014188026a41086a29030037030020012001290388023703a001200141d8006a41086a220242003703002001420037035841c0fcc5004111200141d8006a100820014190016a41086a2002290300370300200120012903583703900141002105200141003602e80220014190016a4110200141e8026a10062102024020012802e8022204417f460d002002450d0020044104490d02200228000021052002102a0b411610282202450d022002410e6a41002900dffc45370000200241086a41002900d9fc45370000200241002900d1fc4537000020024116412c102c2202450d0320022005360016200141d8006a41186a22044200370300200141d8006a41106a22064200370300200141d8006a41086a22074200370300200142003703582002411a200141d8006a1000200141e8026a41186a2004290300370300200141e8026a41106a2006290300370300200141e8026a41086a2007290300370300200120012903583703e8022002102a20014100360258200141e8026a4120200141d8006a1006210202400240024020012802582206417f460d002002450d0020012006360294012001200236029001200141d8006a20014190016a107320012802582204450d07200129025c210802402006450d002002102a0b200120043602782001200837027c2008a721022008422088a72206418002490d01412010282206450d08200620012903a001370000200641186a200141a0016a41186a290300370000200641106a200141a0016a41106a290300370000200641086a200141a0016a41086a29030037000020014281808080103702ec02200120063602e802200541016a2205200141e8026a109f032006102a200141d8006a41086a220642003703002001420037035841c0fcc5004111200141d8006a100820014190016a41086a20062903003703002001200129035837039001200120053602e80220014190016a4110200141e8026a410410070c020b4100210620014100360280012001420137037841012104410021020b200141e8026a41186a2209200141a0016a41186a290300370300200141e8026a41106a220a200141a0016a41106a290300370300200141e8026a41086a220b200141a0016a41086a290300370300200120012903a0013703e802024020062002470d00200241016a22072002490d0c2002410174220c2007200c20074b1b220741ffffff3f712007470d0c2007410574220c4100480d0c0240024020020d00200c102821040c010b20042002410574200c102c21040b2004450d082001200736027c20012004360278200721020b200420064105746a220720012903e802370000200741186a2009290300370000200741106a200a290300370000200741086a200b2903003700002001200641016a360280012005200141f8006a109f030b2002450d002004102a0b200141d8006a41086a220242003703002001420037035841d8a1c6004113200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a001200141e8026a4110200141a0016a1006210202400240024020012802a0012204417f460d002002450d002004450d0120022d000021042002102a200141e8026a4110100920044102460d0020044101710d020b41c0acc3001032000b41c4d1c3004133200141d8036a419cd9c3001038000b200141d8006a41086a220242003703002001420037035841afc5c2004111200141d8006a100820014190016a41086a22042002290300370300200120012903583703900120014190016a41101009200242003703002001420037035841c8fbc5004117200141d8006a100820042002290300370300200120012903583703900120014190016a41101009200242003703002001420037035841feadc4004117200141d8006a1008200141e8026a41086a22042002290300370300200120012903583703e8020240200141e8026a41104101410041001003417f470d0010a0032108200242003703002001420037035841feadc4004117200141d8006a100820042002290300370300200120012903583703e802200120083703a001200141e8026a4110200141a0016a410810070b2002420037030020014200370358418194c1004110200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a1006210220012802e8022204417f460d072002450d0720044104490d062002280000210d2002102a200141a0016a41101009410121090c080b41c4d1c3004133200141d8036a419cd9c3001038000b411641011037000b412c41011037000b41c4d1c3004133200141d8036a419cd9c3001038000b412041011037000b200c41011037000b41c4d1c3004133200141d8036a419cd9c3001038000b410021090b200141d8006a41086a220242003703002001420037035841d591c6004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a10062102024002400240024002400240024002400240024002400240024020012802e8022204417f460d002002450d002004450d0b20022d000021042002102a20044102460d0020044101710d010b410410282204450d0120044100360200200141d8006a41086a2202420037030020014200370358419194c1004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602f002200142013703e8024101200141e8026a10b401200428020021070240024020012802ec02220520012802f00222066b4104490d0020012802e80221020c010b200641046a22022006490d0d2005410174220a2002200a20024b1b220a4100480d0d0240024020050d00200a102821020c010b20012802e8022005200a102c21020b2002450d032001200a3602ec02200120023602e802200a21050b2001200641046a220a3602f002200220066a2007360000200141a0016a41102002200a100702402005450d002002102a0b2004102a410410282204450d0320044100360200200141d8006a41086a2202420037030020014200370358418898c1004116200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602f002200142013703e8024101200141e8026a10b401200428020021070240024020012802ec02220520012802f00222066b4104490d0020012802e80221020c010b200641046a22022006490d0d2005410174220a2002200a20024b1b220a4100480d0d0240024020050d00200a102821020c010b20012802e8022005200a102c21020b2002450d052001200a3602ec02200120023602e802200a21050b2001200641046a220a3602f002200220066a2007360000200141a0016a41102002200a100702402005450d002002102a0b2004102a200141d8006a41086a2202420037030020014200370358419e98c1004110200141d8006a1008200141a0016a41086a22042002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a41041007200141013a00e802200242003703002001420037035841d591c6004115200141d8006a100820042002290300370300200120012903583703a001200141a0016a4110200141e8026a410110070b200141d8006a41086a2202420037030020014200370358419194c1004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a100621020240024020012802e8022204417f460d002002450d002001200436028c022001200236028802200141e8026a20014188026a10820120012802e802220e450d0620012902ec02210f2004450d012002102a0c010b4104210e4200210f0b200141d8006a41086a2202420037030020014200370358418898c1004116200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602e802200141a0016a4110200141e8026a100621020240024020012802e8022204417f460d002002450d002001200436028c022001200236028802200141e8026a20014188026a10820120012802e8022207450d0720012902ec02211002402004450d002002102a0b20012007360288022010422088a7210c0c010b4104210720014104360288024100210c420021100b200f422088a72111024020090d002011417f6a220220114f0d07200220114b0d07200e20024102746a280200210d0b41002011419c7f6a22022002201141016a4b1b221220114b0d07200e20124102746a21132012450d0a200cad2108200e210b0340200b2802002109024002400240024002402008a7220a41014b0d0041002102200a0e020201020b41002102200a2104034020022004410176220620026a22052009200720054102746a280200491b2102200420066b220441014b0d000b0b20092007200241027422046a2802002206460d022002200920064b6a21020c010b410021020b200120023602e80241d498c100412e200141e8026a418499c1001038000b20082002ad580d09200720046a2204200441046a2002417f73200a6a410274109b051a201042ffffffff0f83200a417f6a220cad422086842110200b41046a220b2013460d0b2008427f7c210820012802880221070c000b0b410441041037000b200a41011037000b410441041037000b200a41011037000b41c4d1c3004133200141d8036a419cd9c3001038000b41c4d1c3004133200141d8036a419cd9c3001038000b41ae98c10041261050000b41e4e8c5001032000b41b0b1c0001032000b41c4d1c3004133200141d8036a419cd9c3001038000b200f42ffffffff0f8321080240201120126b2202450d0002402012450d00200e20132002410274109b051a2010422088a7210c0b20082002ad4220868421080b2001280288022107410021020240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200c41014b0d00200c0e020201020b200c2104034020022004410176220620026a2205200d200720054102746a280200491b2102200420066b220441014b0d000b0b0240200d200720024102746a2802002204460d002002200d20044b6a21020b200c2002490d010b200c2010a7470d02200c41016a2204200c490d13200c41017422062004200620044b1b220441ffffffff03712004470d132004410274220641004e0d010c130b41f8b0c0001032000b02400240200c0d002006102821070c010b2007200c4102742006102c21070b2007450d0120012007360288022004ad21100b200720024102746a220441046a2004200c20026b410274109b051a2004200d36020002402008422088220fa722042008a7470d00200441016a22022004490d11200fa722054101742206200220022006491b220241ffffffff03712002470d11200241027422064100480d110240024020040d0020061028210e0c010b200e20054102742006102c210e0b200e450d022008422088a721042002ad21080b200e20044102746a200d3602000240200c41016a22130d00419499c1001032000b2013201341017622024d0d02200128028802220620024102746a280200210d024020134101710d0020132002417f6a22024d0d04200620024102746a280200200d6a410176210d0b200141d8006a41086a2202420037030020014200370358419194c1004115200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200141003602f002200142013703e802200441016a2211200141e8026a10b4010240024020110d0020012802f002210920012802ec02210720012802e80221040c010b410020012802f00222026b2106200441027441046a210a20012802ec022107200e210503402005280200210b02400240200720066a4104490d0020012802e80221040c010b200241046a22042002490d13200741017422092004200920044b1b22094100480d130240024020070d002009102821040c010b20012802e80220072009102c21040b2004450d07200120093602ec02200120043602e802200921070b200541046a21052001200241046a22093602f002200420026a200b3600002006417c6a210620092102200a417c6a220a0d000b0b2008a72102200141a0016a411020042009100702402007450d002004102a0b02402002450d00200e102a0b200128028802210e200141d8006a41086a2202420037030020014200370358418898c1004116200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a001200142013703e802200141003602f0022013200141e8026a10b401200c41027441046a2109410020012802f00222026b21062010a7210c20012802ec022107200e210503402005280200210b02400240200720066a4104490d0020012802e80221040c010b200241046a22042002490d122007410174220a2004200a20044b1b220a4100480d120240024020070d00200a102821040c010b20012802e8022007200a102c21040b2004450d072001200a3602ec02200120043602e802200a21070b200541046a21052001200241046a220a3602f002200420026a200b3600002006417c6a2106200a21022009417c6a22090d000b200141a0016a41102004200a100702402007450d002004102a0b0240200c450d00200e102a0b200141d8006a41086a2202420037030020014200370358419e98c1004110200141d8006a1008200141a0016a41086a2002290300370300200120012903583703a0012001200d3602e802200141a0016a4110200141e8026a410410070240201141e500470d00200d419a086a1098014b0d00200141d8006a41086a220442003703002001420037035841d985c2004117200141d8006a1008200141e8026a41086a2004290300370300200120012903583703e802410810282204450d072004200d360004200441e400360000200141e8026a41102004410810072004102a0b200242003703002001420037035841f9b5c200411d200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a001200141e8026a4110200141a0016a10062102024020012802a0012204417f460d002002450d0020012002360288022001200436028c0220044104490d0c2001200241046a3602880220012004417c6a220636028c0220064104490d0c200228000021072001200441786a36028c022001200241086a360288022002280004210b200141a0016a20014188026a107720012802a001220a450d0c20012902a40121144100210502400240200128028c0222040d000c010b20012004417f6a220936028c022001200128028802220641016a36028802024020062d00004101460d000c010b20094104490d0020012004417b6a36028c022001200641056a360288022006280001210c410121050b2002102a2014422088a72109024020072000470d00024020050d002009ad42287e2208422088a70d0a2008a72202417f4c0d0a0240024020020d004108210c0c010b20021028220c450d0c0b4100210602402009450d00200941286c210541002106200c2102200a21040340200441086a2903002108200441106a2903002110200441186a290300210f20042903002115200241206a200441206a290300370300200241186a200f370300200241106a2010370300200241086a200837030020022015370300200241286a2102200641016a2106200441286a2104200541586a22050d000b0b200141b0016a200b360200200141a0016a410c6a2006360200200141a0016a41086a20093602002001200c3602a401200141003602a001200141e8026a200141a0016a10c30120014193026a200141e8026a41086a280200360000200120012903e80237008b02200141e8026a410c6a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce012009450d01200c102a0c010b2009ad42287e2208422088a70d092008a72202417f4c0d090240024020020d00410821130c010b200210282213450d0c0b0240024020090d00410021060c010b200941286c21054100210620132102200a21040340200441086a2903002108200441106a2903002110200441186a290300210f20042903002115200241206a200441206a290300370300200241186a200f370300200241106a2010370300200241086a200837030020022015370300200241286a2102200641016a2106200441286a2104200541586a22050d000b0b200141b4016a200b360200200141b0016a2006360200200141a0016a410c6a2009360200200141a0016a41086a20133602002001200c3602a401200141013602a001200141e8026a200141a0016a10c30120014193026a200141e8026a41086a280200360000200120012903e80237008b02200141e8026a410c6a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce012009450d002013102a0b2014a7210c0240200b20076a2000470d00200141d8006a41086a220242003703002001420037035841c694c600411b200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a801200142013703a0012009200141a0016a10b40102402009450d00200a200941286c6a2107200a210403402004200141a0016a108f01200441206a29030021080240024020012802a401220620012802a80122026b4108490d0020012802a00121060c010b200241086a22052002490d15200641017422022005200220054b1b22024100480d150240024020060d002002102821060c010b20012802a00120062002102c21060b2006450d0f200120023602a401200120063602a00120012802a80121020b2001200241086a3602a801200620026a20083700002007200441286a2204470d000b0b20012802a4012102200141e8026a411020012802a001220420012802a801100702402002450d002004102a0b200141e8026a41106a2009360200200141f4026a200c360200200141e8026a41086a2202200a360200200141003602ec022001410a3a00e80241014100200141e8026a10cc01200141d8006a41086a220442003703002001420037035841f9b5c200411d200141d8006a100820022004290300370300200120012903583703e802200141e8026a411010090c010b200c450d00200a102a0b200141d8006a41086a22024200370300200142003703584196b6c2004115200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141003602a001200141e8026a4110200141a0016a1006210220012802a0012204417f460d0f2002450d0f2004450d0e20022d0000220641034b0d0e0240024020060e04010f0100010b2004417f6a41074b0d0d0c0f0b2002102a0c0f0b200641041037000b200641041037000b41ac99c100200220131034000b41ac99c100200220131034000b200941011037000b200a41011037000b410841011037000b1036000b200241081037000b200241081037000b200241011037000b41c4d1c3004133200141d8036a419cd9c3001038000b20022800052106200228000121042002102a024020042000470d00200141043602a001200120063602a401200141e8026a200141a0016a10c30120014193026a200141f0026a280200360000200120012903e80237008b02200141f4026a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce010b200620046a2000470d022001410036028802200141d8006a41086a22024200370300200142003703584196b6c2004115200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141a0016a20014188026a10da02200141e8026a411020012802a001220220012802a8011007024020012802a401450d002002102a0b200141023602ec022001410a3a00e80241014100200141e8026a10cc010c020b2004417f6a4108490d0020022800052106200228000121042002102a024020042000470d00200141033602a001200120063602a401200141e8026a200141a0016a10c30120014193026a200141f0026a280200360000200120012903e80237008b02200141f4026a2001418f026a290000370000200141c6a4b9da043600e902200141023a00e80220012001290088023700ed02200141e8026a10ce010b200620046a2000470d012001410236028802200141d8006a41086a22024200370300200142003703584196b6c2004115200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141a0016a20014188026a10da02200141e8026a411020012802a001220220012802a8011007024020012802a401450d002002102a0b200141013602ec022001410a3a00e80241014100200141e8026a10cc010c010b41c4d1c3004133200141d8036a419cd9c3001038000b02400240024002400240024020004180e101700d00200141e8026a10d301200141c8006a200141e8026a1091012001200141c8006a41086a29030022083703800120012001290348221037037820014180036a2008370300200141e8026a41106a2010370300200141e8026a41086a220441013a00002001410b3a00e8024100210241014100200141e8026a10cc01200141003a008f012001420037039801200142003703900120044200370300200142003703e8024181a2c6004112200141e8026a1008200141a0016a41086a2004290300370300200120012903e8023703a001200141003602e802200141a0016a4110200141e8026a100621040240024020012802e8022206417f470d000c010b024020040d000c010b2001200636028c022001200436028802200141e8026a20014188026a10820120012802e8022202450d0620012902ec0221082006450d002004102a0b2002410420021b210c024002402008420020021b2214422088a722040d004100210b0c010b200141f1026a210d200141c8026a211320014188026a41206a210e200141a0016a41086a2109200141a0036a21114100210a4100210b41002102024003400240024002400240200b450d00200c20024102746a2106200c2002200a6a4102746a21050340200220044f0d02200141a0016a2006280200220710e90220012903a0014201520d0420014188026a200941e000109a051a2001290378220f200129038802221554200141f8006a41086a290300220820014188026a41086a29030022105420082010511b450d03200141013a008f010240200a20026a220720044f0d0020052006280200360200200641046a2106200541046a2105200241016a22022004490d010c070b0b41c4b2c000200720041034000b200c20024102746a21060340200220044f0d01200141a0016a2006280200220710e90220012903a0014201520d0320014188026a200941e000109a051a2001290378220f20012903880222155a200141f8006a41086a290300220820014188026a41086a29030022105a20082010511b0d02200641046a2106200141013a008f01200241016a22022004490d000b4100210b0c050b41e8b1c000200220041034000b2001200f20157d3703782001200820107d200f201554ad7d37038001411210282206450d05200641106a41002f008086423b0000200641086a41002900f88542370000200641002900f08542370000200641124124102c2206450d0620062007360012200341186a22054200370000200341106a22124200370000200341086a22004200370000200342003700002006411620031000200141e8026a41186a2005290000370300200141e8026a41106a2012290000370300200141e8026a41086a2000290000370300200120032900003703e8022006102a200141e8026a41201009200e20012903980220014188026a41186a29030010aa02200141386a201320012903880220014188026a41086a220629030010d00120014190016a41086a2205427f20052903002208200141386a41086a2903007c200129039001221020012903387c220f2010542205ad7c22102005201020085420102008511b22051b3703002001427f200f20051b37039001200129038802210820112006290300370300200d2013290000370000200d41086a201341086a290000370000200d41106a201341106a290000370000200d41186a201341186a2900003700002001200837039803200141023a00f0022001410b3a00e802200120073602940341014100200141e8026a10cc010b200a417f6a210a200b41016a210b200241016a22022004490d000b0b200b450d00200220044f0d00200c20024102746a2206200b4102746b2006200420026b410274109b051a0b200141e8026a41086a22024200370300200142003703e8024181a2c6004112200141e8026a1008200141a0016a41086a2002290300370300200120012903e8023703a00102400240200c0d00200141a0016a411010090c010b200141003602f002200142013703e8022004200b6b2204200141e8026a10b4010240024020040d0020012802f002210920012802ec02210720012802e80221040c010b410020012802f00222026b2106200c20044102746a210b20012802ec022107200c210503402005280200210a02400240200720066a4104490d0020012802e80221040c010b200241046a22042002490d0a200741017422092004200920044b1b22094100480d0a0240024020070d002009102821040c010b20012802e80220072009102c21040b2004450d07200120093602ec02200120043602e802200921070b2001200241046a22093602f002200420026a200a3600002006417c6a210620092102200b200541046a2205470d000b0b2014a72102200141a0016a411020042009100702402007450d002004102a0b2002450d00200c102a0b024020012d008f010d004200210f200141286a20012903782208200141f8006a41086a2202290300221042c0843d420010a005200141186a20012903282215200141286a41086a290300221442c0fb42427f109f05200141086a2015201442a0c21e4200109f05200220102010200141086a41086a29030020012903082215200820012903187c42018842ffffffff0f837c2214201554ad7c22152014200856201520105620152010511b22041b22157d20082008201420041b221054ad7d3703002001200820107d370378200141e8026a41086a22024200370300200142003703e80241ace1c0004116200141e8026a1008200141d8006a41086a2002290300370300200120012903e802370358200141003602e802200141d8006a4110200141e8026a100621020240024020012802e8022204417f470d00420021080c010b20044110490d06200241086a29000021082002290000210f2002102a0b200141e8026a41086a22044200370300200142003703e80241ace1c0004116200141e8026a1008200141d8006a41086a2004290300370300200120012903e80237035820014200200820157d200f201054ad7d2214200f20107d2216200f56201420085620142008511b22021b3703f00220014200201620021b3703e802200141d8006a4110200141e8026a4110100720014190016a41086a2206427f200629030022142008201520021b7c2001290390012208200f201020021b7c220f2008542202ad7c22082002200820145420082014511b22021b3703002001427f200f20021b3703900120014180036a2015370300200141e8026a41106a2010370300200441033a00002001410b3a00e80241014100200141e8026a10cc010b200141e8026a10d30120014188026a200141e8026a200129039001220820014190016a41086a29030022104102109802024002402001280288020d00200141a0016a41106a201020014188026a41106a29030022157d2008200129039002220f54ad7d201520107d200f200854ad7d200f2008582015201058201520105122021b22041b37030020012008200f7d200f20087d20041b3703a8012001200f200856201520105620021b2202ad3703a001200141a0016a41086a2104024020020d0020012004360258200141d8006a109c010c020b20012004360258200141d8006a109d010c010b41abb6c20041ca00100b200120103703a801200120083703a0012001200141a0016a3602880220014188026a109c010b2001290378210820014180036a200141f8006a41086a290300370300200141f8026a2008370300200141e8026a41086a41043a00002001410b3a00e80241014100200141e8026a10cc010b200141d8006a41086a220242003703002001420037035841affec5004111200141d8006a1008200141e8026a41086a2002290300370300200120012903583703e802200141e8026a41101009200141e0036a24000f0b411241011037000b412441011037000b200941011037000b41c4d1c3004133200141d8036a419cd9c3001038000b41c4d1c3004133200141d8036a419cd9c3001038000b1031000bf52901047f230041c0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240411610282203450d002003410e6a41002900dffc45370000200341086a41002900d9fc45370000200341002900d1fc4537000020034116412c102c2203450d0120032000360016200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a22054200370300200242003703202003411a200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002003102a200128020021032001280208210120024100360228200242013703202001200241206a10b40102402001450d00200320014105746a2105034002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d052002200436022420022000360220200228022821010b2002200141016a360228200020016a20032d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d062002200436022420022000360220200228022821010b2002200141016a360228200020016a200341016a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d072002200436022420022000360220200228022821010b2002200141016a360228200020016a200341026a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d082002200436022420022000360220200228022821010b2002200141016a360228200020016a200341036a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d092002200436022420022000360220200228022821010b2002200141016a360228200020016a200341046a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0a2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341056a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0b2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341066a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0c2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341076a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0d2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341086a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0e2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341096a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d0f2002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410a6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d102002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410b6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d112002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410c6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d122002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410d6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d132002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410e6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d142002200436022420022000360220200228022821010b2002200141016a360228200020016a2003410f6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d152002200436022420022000360220200228022821010b2002200141016a360228200020016a200341106a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d162002200436022420022000360220200228022821010b2002200141016a360228200020016a200341116a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d172002200436022420022000360220200228022821010b2002200141016a360228200020016a200341126a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d182002200436022420022000360220200228022821010b2002200141016a360228200020016a200341136a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d192002200436022420022000360220200228022821010b2002200141016a360228200020016a200341146a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1a2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341156a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1b2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341166a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1c2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341176a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1d2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341186a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1e2002200436022420022000360220200228022821010b2002200141016a360228200020016a200341196a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d1f2002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411a6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d202002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411b6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d212002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411c6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d222002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411d6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d232002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411e6a2d00003a000002400240200228022420022802282201460d00200228022021000c010b200141016a22002001490d25200141017422042000200420004b1b22044100480d250240024020010d002004102821000c010b200228022020012004102c21000b2000450d242002200436022420022000360220200228022821010b2002200141016a360228200020016a2003411f6a2d00003a0000200341206a22032005470d000b0b2002280224210320024120200228022022012002280228100702402003450d002001102a0b200241c0006a24000f0b411641011037000b412c41011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b200441011037000b1031000bab0103017f017e027f230041206b2200240042002101200041106a41086a220242003703002000420037031041feb3c300410d200041106a1008200041086a2002290300370300200020002903103703002000410036021020004110200041106a100621020240024020002802102203417f460d002002450d0020034108490d01200229000021012002102a0b200041206a240020010f0b41c4d1c3004133200041106a419cd9c3001038000b0a0041d0c5c2001032000b3400200041bfcec20036020420004100360200200041146a4109360200200041106a41c4cec200360200200041086a42043702000bcf0101017f024002400240024002400240410110282202450d00200241003a0000200241014102102c2202450d01200241003a0001200241024104102c2202450d02200241003b0002200241044108102c2202450d0320024100360004200241084110102c2202450d0420024200370008200241104120102c2202450d052002420037001820024200370010200042a08080808004370204200020023602000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b130020004102360204200041a0e1c2003602000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242b8173700000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242c8013700000bcb0201047f230041d0006b220324002003410036022820012002200341286a1006210402400240024020032802282205417f460d0020040d010b200041003a00000c010b41002101200341003a00480340024020052001470d000240200141ff0171450d00200341003a00480b41c4d1c3004133200341286a419cd9c3001038000b200341286a20016a200420016a2d00003a00002003200141016a22023a00482002210120024120470d000b200341086a41186a2201200341286a41186a290300370300200341086a41106a2202200341286a41106a290300370300200341086a41086a2206200341286a41086a2903003703002003200329032837030802402005450d002004102a0b20002003290308370001200041013a0000200041196a2001290300370000200041116a2002290300370000200041096a20062903003700000b200341d0006a24000bd31803017f017e2b7f230041b00d6b22032400200320023602042003200136020042002104200341086a41086a220142003703002003420037030841aef2c2004115200341086a1008200341900d6a41086a2001290300370300200320032903083703900d200341e80c6a200341900d6a10a903024002400240024020032802ec0c22050d00410121050c010b20032903f00c220442ffffffff0f560d010b20004200370000200041186a4200370000200041106a4200370000200041086a42003700000c010b20032802e80c2101200341086a410041e00c1099051a200541206a21062001411874411875210120052004422088a74105746a210741002108410021094100210a4100210b4100210c4100210d4100210e4100210f410021104100211141002112410021134100211441002115410021164100211741002118410021194100211a4100211b4100211c4100211d4100211e4100211f4100212041002121410021224100212341002124410021254100212641002127200521024100212841d1002129024003402028212a02400240024002402001450d0020072005460d01200141016a210103400240024020022007470d002006212b200621022005212c0c010b2002212c200241206a222b21020b2001417f6a22010d000c030b0b024020022007460d00200241206a212b2002212c0c030b2006212b2005212c20072005460d040c010b200141016a2101034020072002460d04200241206a21022001417f6a22010d000b200241606a212c2002212b0b202c450d020b202b21020240024002400240024002402003280204220141056a222b417f4c0d002003280200212d02400240202b450d00202b10282228450d034100212e200341003602980d2003202b3602940d200320283602900d0c010b200341003602980d2003202b3602940d200341013602900d410110282228450d03200341013602940d200320283602900d20032802980d212e0b2003202e41016a3602980d2028202e6a202a3a00002001200341900d6a10b4010240024020032802940d222e20032802980d222b6b2001490d0020032802900d212e0c010b202b20016a2228202b490d05202e410174222b2028202b20284b1b222b4100480d0502400240202e0d00202b1028212e0c010b20032802900d202e202b102c212e0b202e450d042003202b3602940d2003202e3602900d20032802980d212b0b2003202b20016a3602980d202e202b6a202d2001109a051a2003200341900d6a36028c0d202c2003418c0d6a10c80120032802940d212c20032802900d210120032802980d212b200341900d6a41186a222e4200370300200341900d6a41106a22284200370300200341900d6a41086a222d4200370300200342003703900d2001202b200341900d6a1000200341e80c6a41186a222b202e290300370300200341e80c6a41106a222e2028290300370300200341e80c6a41086a222f202d290300370300200320032903900d3703e80c0240202c450d002001102a0b2029417f6a2129202a41016a2128200341086a202a4103704105746a220120032903e80c370000200141186a202b290300370000200141106a202e290300370000200141086a202f2903003700004100212c0340202a202a41036e222b417d6c6a4102470d06200341086a202c6a220141df006a2d000022082001411f6a2d000022097120082009722001413f6a2d00007172211f200141de006a2d000022082001411e6a2d000022097120082009722001413e6a2d00007172211e200141dd006a2d000022082001411d6a2d000022097120082009722001413d6a2d00007172211d200141dc006a2d000022082001411c6a2d000022097120082009722001413c6a2d00007172211c200141db006a2d000022082001411b6a2d000022097120082009722001413b6a2d00007172211b200141da006a2d000022082001411a6a2d000022097120082009722001413a6a2d00007172211a200141d9006a2d00002208200141196a2d00002209712008200972200141396a2d000071722119200141d8006a2d00002208200141186a2d00002209712008200972200141386a2d000071722118200141d7006a2d00002208200141176a2d00002209712008200972200141376a2d000071722117200141d6006a2d00002208200141166a2d00002209712008200972200141366a2d000071722116200141d5006a2d00002208200141156a2d00002209712008200972200141356a2d000071722115200141d4006a2d00002208200141146a2d00002209712008200972200141346a2d000071722114200141d3006a2d00002208200141136a2d00002209712008200972200141336a2d000071722113200141d2006a2d00002208200141126a2d00002209712008200972200141326a2d000071722112200141d1006a2d00002208200141116a2d00002209712008200972200141316a2d000071722111200141d0006a2d00002208200141106a2d00002209712008200972200141306a2d000071722110200141cf006a2d000022082001410f6a2d000022097120082009722001412f6a2d00007172210f200141ce006a2d000022082001410e6a2d000022097120082009722001412e6a2d00007172210e200141cd006a2d000022082001410d6a2d000022097120082009722001412d6a2d00007172210d200141cc006a2d000022082001410c6a2d000022097120082009722001412c6a2d00007172210c200141cb006a2d000022082001410b6a2d000022097120082009722001412b6a2d00007172210b200141ca006a2d000022082001410a6a2d000022097120082009722001412a6a2d00007172210a200141c9006a2d00002208200141096a2d00002209712008200972200141296a2d000071722109200141c8006a2d00002208200141086a2d00002220712008202072200141286a2d000071722108200141c7006a2d00002220200141076a2d00002221712020202172200141276a2d000071722120200141c6006a2d00002221200141066a2d00002222712021202272200141266a2d000071722121200141c5006a2d00002222200141056a2d00002223712022202372200141256a2d000071722122200141c4006a2d00002223200141046a2d00002224712023202472200141246a2d000071722123200141c3006a2d00002224200141036a2d00002225712024202572200141236a2d000071722124200141c2006a2d00002225200141026a2d00002226712025202672200141226a2d000071722125200141c1006a2d00002226200141016a2d00002227712026202772200141216a2d000071722126200141c0006a2d0000222720012d0000222e712027202e72200141206a2d000071722127202c41800c460d06200341086a202c202b410574202a41096e41e0006c6b6a6a220141ff006a201f3a0000200141fe006a201e3a0000200141fd006a201d3a0000200141fc006a201c3a0000200141fb006a201b3a0000200141fa006a201a3a0000200141f9006a20193a0000200141f8006a20183a0000200141f7006a20173a0000200141f6006a20163a0000200141f5006a20153a0000200141f4006a20143a0000200141f3006a20133a0000200141f2006a20123a0000200141f1006a20113a0000200141f0006a20103a0000200141ef006a200f3a0000200141ee006a200e3a0000200141ed006a200d3a0000200141ec006a200c3a0000200141eb006a200b3a0000200141ea006a200a3a0000200141e9006a20093a0000200141e8006a20083a0000200141e7006a20203a0000200141e6006a20213a0000200141e5006a20223a0000200141e4006a20233a0000200141e3006a20243a0000200141e2006a20253a0000200141e1006a20263a0000200141e0006a20273a0000202b212a202c41e0006a222c41e00c470d000c060b0b1036000b202b41011037000b410141011037000b202b41011037000b1031000b4100210120290d000b0b2000201f3a001f2000201e3a001e2000201d3a001d2000201c3a001c2000201b3a001b2000201a3a001a200020193a0019200020183a0018200020173a0017200020163a0016200020153a0015200020143a0014200020133a0013200020123a0012200020113a0011200020103a00102000200f3a000f2000200e3a000e2000200d3a000d2000200c3a000c2000200b3a000b2000200a3a000a200020093a0009200020083a0008200020203a0007200020213a0006200020223a0005200020233a0004200020243a0003200020253a0002200020263a0001200020273a00000b02402004a7450d002005102a0b200341b00d6a24000bfd0102057f017e230041306b220224002002410036022020014110200241206a10062101024002400240024020022802202203417f460d0020010d010b200041003602040c010b20022003360214200220013602102003450d0120022003417f6a3602142002200141016a36021020012d00002103200241206a200241106a106d20022802202204450d012002410c6a41026a2002411d6a41026a2d000022053a0000200220022f001d22063b010c20022902242107200020033a0000200020063b0001200041036a20053a000020002007370208200020043602042001102a0b200241306a24000f0b41c4d1c3004133200241206a419cd9c3001038000bfb0401057f230041106b2202240002400240024002400240024020002802704101460d0002400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d06200341017422052004200520044b1b22054100480d060240024020030d002005102821040c010b200128020020032005102c21040b2004450d0320012004360200200141046a2005360200200141086a28020021030b200141086a2205200341016a360200200420036a41003a00002000280274210602400240200141046a2802002204200528020022036b4104490d00200128020021040c010b200341046a22052003490d06200441017422032005200320054b1b22034100480d060240024020040d002003102821040c010b200128020020042003102c21040b2004450d0420012004360200200141046a2003360200200141086a28020021030b200141086a200341046a360200200420036a20063600000c010b02400240200141046a280200200141086a2802002203460d00200128020021040c010b200341016a22042003490d05200341017422052004200520044b1b22054100480d050240024020030d002005102821040c010b200128020020032005102c21040b2004450d0420012004360200200141046a2005360200200141086a28020021030b200141086a200341016a360200200420036a41013a00000b2000200110f1012000280278210320004180016a2802002200200110b40102402000450d002000410574210003402002200136020c20032002410c6a10c801200341206a2103200041606a22000d000b0b200241106a24000f0b200541011037000b200341011037000b200541011037000b1031000b860201017f0240024020002d00002201410e4b0d00024002400240024020010e0f050505050500050501050205030505050b200041086a2d00004101470d04200041146a280200450d04200041106a280200102a0c040b200041046a2d00004103470d0302402000410c6a280200450d00200041086a280200102a0b200041186a280200450d03200041146a280200102a0c030b200041046a2802000d022000410c6a280200450d02200041086a280200102a0c020b200041086a2d00004105490d01200041306a280200450d012000412c6a280200102a0c010b200041086a280200450d00200041046a280200102a0b0240200041fc006a280200450d002000280278102a0b0b130020004106360204200041c8f3c2003602000b3400200041d3f9c20036020420004100360200200041146a410f360200200041106a41dcf9c200360200200041086a42063702000b5501017f230041206b22022400200241003602082002420837030020024100360218200242013703104100200241106a10b401200041086a20022802183602002000200229031037020020021072200241206a24000b7201017f230041306b22022400200241186a4200370300200241106a4200370300200241086a42003703002002420037030020024100360228200242013703202002200241206a36022c20022002412c6a10c801200041086a200228022836020020002002290320370200200241306a24000b5d01027f230041106b2202240002404101102822030d00410141011037000b200341003a00002002428180808010370204200220033602004100200210b401200041086a200228020836020020002002290300370200200241106a24000b0900200042043702000b851805047f017e027f047e017f23004190026b22012400200141a8016a41086a22024200370300200142003703a80141f99fc6004115200141a8016a1008200141d0016a41086a22032002290300370300200120012903a8013703d001200141d0016a4110100920024200370300200142003703a801418ea0c600411a200141a8016a100820032002290300370300200120012903a8013703d00141002102200141003602a801200141d0016a4110200141a8016a100621030240024002400240024002400240024020012802a8012204417f460d002003450d0020044104490d01200328000021022003102a0b200141a8016a41086a22034200370300200142003703a80141bfa0c600411b200141a8016a1008200141d0016a41086a22042003290300370300200120012903a8013703d001200141186a200141d0016a109f02200129032021052001280218210620034200370300200142003703a80141bfa0c600411b200141a8016a1008200141086a4180e59af700200220024180e59af7004922071b20024180e59af70020071b6b2207ad2208420020084200109f0520042003290300370300200120012903a8013703d0012005420020061b2105200842a8c30180210842ffffffffffffffffff00428080808080808080807f20071b2001290308220920012903102009423f87521b42808090bbbad6adf00d7f210902400240200241ffe49af7004b0d0042ffffffffffffffffff00428080808080808080807f2005200820097d22097d22084200531b20082005427f5522022009427f554720022008427f5547711b22084280ec94a37c20084280ec94a37c551b21080c010b42ffffffffffffffffff00428080808080808080807f2005200820097c22097c22084200531b20082005427f5522022009427f554620022008427f5547711b21080b200120083703a801200141d0016a4110200141a8016a41081007200141a8016a41086a22024200370300200142003703a801418ea0c600411a200141a8016a1008200141d0016a41086a22032002290300370300200120012903a8013703d001200141d0016a4110100920024200370300200142003703a80141a8a0c6004117200141a8016a100820032002290300370300200120012903a8013703d001200141d0016a4110100920024200370300200142003703a80141d9efc200410d200141a8016a100820032002290300370300200120012903a8013703d00141002106200141003602a801200141d0016a4110200141a8016a10062102024020012802a8012203417f460d002002450d0020034104490d02200228000021062002102a200141d0016a411010090b200141a8016a41086a22024200370300200142003703a801419df2c2004111200141a8016a1008200141d0016a41086a2002290300370300200120012903a8013703d001200141a8016a200141d0016a411010a7030240024020012d00a8014101460d00200141286a41086a4200370300200141286a41106a4200370300200141286a41186a4200370300200141f0016a41186a200141c1016a290000370300200141f0016a41106a200141a8016a41116a290000370300200141f0016a41086a200141b1016a290000370300200120012900a9013703f00120014200370328200141f0016a21020c010b200141d0016a41101009200141f0016a41186a200141c1016a2900002208370300200141f0016a41106a200141a8016a41116a2900002205370300200141f0016a41086a200141b1016a2900002209370300200141286a41086a2009370300200141286a41106a2005370300200141286a41186a2008370300200120012900a90122083703f00120012008370328200141f0016a21020b42002108200141a8016a41086a22034200370300200142003703a80141b1f0c200410d200141a8016a1008200141d0016a41086a2003290300370300200120012903a8013703d001200141003602a801200141d0016a4110200141a8016a100621040240024020012802a8012203417f470d00410421070c010b200120033602f401200120043602f001200141a8016a200141f0016a107620012802a8012207450d0320012902ac01210802402003450d002004102a0b200141d0016a411010090b200141a8016a41086a22034200370300200142003703a80141e6efc2004115200141a8016a1008200141d0016a41086a2003290300370300200120012903a8013703d001200141a8016a200141d0016a411010a7030240024020012d00a8014101460d00200220012900a901370000200141c8006a41086a4200370300200141c8006a41106a4200370300200141c8006a41186a4200370300200241186a200141c1016a290000370000200241106a200141b9016a290000370000200241086a200141b1016a290000370000200142003703480c010b200141d0016a41101009200241186a200141c1016a2900002205370000200241106a200141b9016a2900002209370000200241086a200141b1016a290000220a370000200220012900a901220b370000200141c8006a41086a200a370300200141c8006a41106a2009370300200141c8006a41186a20053703002001200b3703480b0240200641fb01490d00200641857e6a2203450d00411010282202450d04200241086a41002900c6f042370000200241002900bef042370000200241104120102c2202450d0520022003360010200141a8016a41186a22034200370300200141a8016a41106a22044200370300200141a8016a41086a220c4200370300200142003703a80120024114200141a8016a1000200141f0016a41186a2003290300370300200141f0016a41106a2004290300370300200141f0016a41086a200c290300370300200120012903a8013703f0012002102a200141f0016a412010090b200141a8016a41186a22024200370300200141a8016a41106a22034200370300200141a8016a41086a22044200370300200142003703a801200141a8016a1014200141e8006a41186a2002290300370300200141e8006a41106a2003290300370300200141e8006a41086a2004290300370300200120012903a801370368200141f0016a41186a200141286a41186a290300370300200141f0016a41106a200141286a41106a290300370300200141f0016a41086a200141286a41086a290300370300200120012903283703f001200242003703002003420037030020044200370300200142003703a8010240200141f0016a4120200141a8016a1015450d0020014188016a41086a2004290300220537030020014188016a41106a2003290300220937030020014188016a41186a2002290300220a370300200120012903a801220b3703880120042005370300200320093703002002200a3703002001200b3703a8010240024020084220882205a722022008a7460d00200821090c010b200241016a22032002490d082005a74101742204200320032004491bad220942247e2205422088a70d082005a722034100480d080240024020020d002003102821070c010b2007200241246c2003102c21070b2007450d0720084220882205a721020b2007200241246c6a220241003a0000200220012903a801370001200241096a200141b0016a290300370000200241116a200141b8016a290300370000200241196a200141c0016a290300370000200220012f00f0013b0021200241236a200141f2016a2d00003a00002005422086200942ffffffff0f83844280808080107c21080b200020012903283700102000200636020020002001290368370030200041286a200141286a41186a290300370000200041206a200141286a41106a290300370000200041186a200141286a41086a290300370000200041386a200141e8006a41086a290300370000200041c0006a200141e8006a41106a290300370000200041c8006a200141e8006a41186a290300370000200041086a200837020020002007360204200041e8006a200141c8006a41186a290300370000200041e0006a200141c8006a41106a290300370000200041d8006a200141c8006a41086a2903003700002000200129034837005020014190026a24000f0b41c4d1c3004133200141a8016a419cd9c3001038000b41c4d1c3004133200141a8016a419cd9c3001038000b41c4d1c3004133200141a8016a419cd9c3001038000b411041011037000b412041011037000b200341041037000b1031000bb40202067f017e230041206b220224000240024002400240200128020422034104490d0020012802002204280000210520012003417c6a22063602042001200441046a36020020064104490d01200428000421062001200341786a3602042001200441086a360200200241106a2001106d200228021022030d02200041003602080c030b200041003602080c020b200041003602080c010b200241106a41086a280200210720022802142104200241106a2001106d02402002280210450d00200241086a200241106a41086a2802002201360200200220022903102208370300200041106a20073602002000200436020c200020033602082000200636020420002005360200200041146a20083702002000411c6a20013602000c010b200041003602082004450d002003102a0b200241206a24000ba60301067f230041106b22022400200241003602082002420137030020002802002103024002400240410410282204450d0020024284808080c0003702042002200436020020042003360000200028020421050240024020022802042206200228020822046b4104490d00200441046a2103200228020021060c010b200441046a22032004490d03200641017422072003200720034b1b22074100480d030240024020060d002007102821060c010b200228020020062007102c21060b2006450d0220022007360204200220063602000b20022003360208200620046a200536000020002802082104200041106a2802002203200210b40102402003450d0020034105742103034020042002108f01200441206a2104200341606a22030d000b0b200028021421042000411c6a2802002203200210b40102402003450d0020034105742103034020042002108f01200441206a2104200341606a22030d000b0b2002280204210420012802002001280204200228020022032002280208100702402004450d002003102a0b200241106a24000f0b410441011037000b200741011037000b1031000b1300200041043602042000418897c3003602000b3400200041879fc30036020420004100360200200041146a4105360200200041106a41a0a2c300360200200041086a42133702000b34002000418ca2c30036020420004100360200200041146a4105360200200041106a41a0a2c300360200200041086a42133702000bf90101047f230041206b22032400200341106a41086a220442003703002003420037031041a8a0c6004117200341106a1008200341086a200429030037030020032003290310370300410021042003410036021020034110200341106a100621050240024020032802102206417f460d002005450d0020064104490d01200528000021042005102a0b02400240417f200420026a220520052004491b2204418080c002418080f00120011b4b0d00200041046a2004360200410021040c010b200041800c3b0001200041036a41003a0000410121040b200020043a0000200341206a24000f0b41c4d1c3004133200341106a419cd9c3001038000b850201047f230041206b22032400200341106a41086a2204420037030020034200370310418ea0c600411a200341106a1008200341086a200429030037030020032003290310370300410021042003410036021020034110200341106a100621050240024020032802102206417f460d002005450d0020064104490d01200528000021042005102a0b02400240417f2004418094ebdc034180afd0e50220021b2205200120052001491b6a220120012004491b220420054b0d00200041046a2004360200410021040c010b200041800c3b0001200041036a41003a0000410121040b200020043a0000200341206a24000f0b41c4d1c3004133200341106a419cd9c3001038000bef1a04057f017e037f017e230041e0016b220124000240024002400240024002400240024041880110282202450d000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200028020022002802000e1500011402030405060708090a0b0c0d0e0f10111213000b0240024002400240024002400240200041086a280200417f6a220341054b0d004101210420030e06060102030405060b41e4f0c2001032000b200041146a2802002204417f4c0d1b2000410c6a28020021000240024020040d0020014200370360410121050c010b200410282205450d1d20014100360264200120043602600b20012004360264200520002004109a051a20012903602106410221040c040b200041106a2903002106410321040c030b200041146a2802002204417f4c0d192000410c6a28020021000240024020040d0020014200370360410121050c010b200410282205450d1c20014100360264200120043602600b20012004360264200520002004109a051a20012903602106410421040c020b200141e0006a2000410c6a106f2001290264210620012802602105410521040c010b200141e0006a2000410c6a10712001290264210620012802602105410621040b200220063703102002200536020c20022004360208200241003602000c140b10a103000b200141e0006a200041046a1070200241033602002002410c6a200141e8006a280200360200200220012903603702040c120b10bb03000b200141e0006a200041086a10ae02200241086a200141e0006a41e000109a051a200241053602000c100b200141e0006a200041086a10bc0320024106360200200241386a200141e0006a41306a290300370300200241306a200141e0006a41286a290300370300200241286a200141e0006a41206a290300370300200241206a200141e0006a41186a290300370300200241186a200141e0006a41106a290300370300200241106a200141e0006a41086a290300370300200220012903603703080c0f0b200141e0006a41186a200041286a290000370300200141e0006a41106a200041206a290000370300200141e8006a200041186a290000370300200141e0006a41286a200041386a290000370300200141e0006a41306a200041c0006a290000370300200141e0006a41386a200041c8006a290000370300200141e0006a41c8006a200041d8006a290000370300200141e0006a41d0006a200041e0006a290000370300200141e0006a41d8006a200041e8006a2900003703002001200041106a2900003703602001200041306a290000370380012001200041d0006a2900003703a0012000410c6a2802002205417f4c0d10200028020421030240024020050d0041012100410021040c010b20052104200510282200450d140b200020032005109a0521002001200141e0006a41e000109a0521032002200536020c2002200436020820022000360204200241106a200341e000109a051a200241073602000c0e0b200141e0006a200041086a10bd0320024108360200200241306a200141e0006a41286a290300370300200241286a200141e0006a41206a290300370300200241206a200141e0006a41186a290300370300200241186a200141e0006a41106a290300370300200241106a200141e0006a41086a290300370300200220012903603703080c0d0b02400240024002400240024020002d0004417f6a220541034b0d0020050e0401020304010b41c0f1c2001032000b200041106a280200220341ffffff3f712003470d1220034105742204417f4c0d12200041086a2802002100410121054101210702402004450d00200410282207450d170b024020030d0041002104410021030c040b2003410574210420072105034020052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a290000370000200541206a2105200041206a2100200441606a22040d000b41012105200341057441606a41057641016a21040c030b200041086a10ba032107410221050c020b200041086a28020021072000410c6a10ba032103410321050c010b200141026a200041046a220541036a2d00003a0000200141e0006a41086a2000411c6a290000370300200141e0006a41106a200041246a2d00003a0000200120052f00013b01002001200041146a29000037036020002d00254100472108200041286a2802002109200041106a28000021042000410c6a2800002103200041086a2800002107410421050b200220053a0004200220012f01003b0005200220043602102002200336020c200220073602082002200129036037021420022009360228200220083a002520024109360200200241076a200141026a2d00003a00002002411c6a200141e8006a290300370200200241246a200141f0006a2d00003a00000c0c0b02400240024002400240024020002d0004417f6a220541034b0d0020050e0401020304010b41c0f1c2001032000b200041106a280200220341ffffff3f712003470d1120034105742204417f4c0d11200041086a2802002100410121054101210702402004450d00200410282207450d170b024020030d0041002104410021030c040b2003410574210420072105034020052000290000370000200541186a200041186a290000370000200541106a200041106a290000370000200541086a200041086a290000370000200541206a2105200041206a2100200441606a22040d000b41012105200341057441606a41057641016a21040c030b200041086a10ba032107410221050c020b200041086a28020021072000410c6a10ba032103410321050c010b200141026a200041046a220541036a2d00003a0000200141e0006a41086a2000411c6a290000370300200141e0006a41106a200041246a2d00003a0000200120052f00013b01002001200041146a29000037036020002d00254100472108200041286a2802002109200041106a28000021042000410c6a2800002103200041086a2800002107410421050b200220053a0004200220012f01003b0005200220043602102002200336020c200220073602082002200129036037021420022009360228200220083a00252002410a360200200241076a200141026a2d00003a00002002411c6a200141e8006a290300370200200241246a200141f0006a2d00003a00000c0b0b200141e0006a200041086a10d3022002410b360200200241c0006a200141e0006a41386a290300370300200241386a200141e0006a41306a290300370300200241306a200141e0006a41286a290300370300200241286a200141e0006a41206a290300370300200241206a200141e0006a41186a290300370300200241186a200141e0006a41106a290300370300200241106a200141e0006a41086a290300370300200220012903603703080c0a0b200141e0006a200041046a10be03200241046a200141e0006a41c400109a051a2002410c3602000c090b200028020421002002410d360200200220003602040c080b2000410c6a2802002205417f4c0d09200028020421030240024020050d0041012100410021040c010b20052104200510282200450d100b200020032005109a0521002002200536020c20022004360208200220003602042002410e3602000c070b024002400240024002400240200041086a280200417f6a220541024b0d0020050e03010203010b418486c2001032000b200041386a2903002106200041306a290300210a41012105024002402000410c6a2d00004101460d00200141e8006a2000411c6a290200370300200141e0006a41106a200041246a290200370300200141f8006a2000412c6a2d00003a00002001200041146a29020037036020002f000d2000410f6a2d0000411074722104200041106a2802002103410021050c010b200041106a28020021030b200141186a200141e0006a41186a280200360200200141106a200141e0006a41106a290300370300200141086a200141e0006a41086a29030037030020012001290360370300410121000c030b2000410c6a28020022054108762104410221000c010b2000410c6a28020022054108762104410321000b0b2002200a3703302002200336021020022000360208200220012903003702142002410f360200200241386a200637030020022004410874200541ff01717236020c2002411c6a200141086a290300370200200241246a200141106a2903003702002002412c6a200141186a2802003602000c060b200141e0006a200041086a10bf03200241086a200141e0006a418001109a051a200241103602000c050b200141e0006a200041046a10c003200241113602002002412c6a20014188016a280200360200200241246a20014180016a2903003702002002411c6a200141f8006a290300370200200241146a200141f0006a2903003702002002410c6a200141e8006a290300370200200220012903603702040c040b200141e0006a200041046a10af02200241046a200141e0006a41e400109a051a200241123602000c030b10c103000b10d501000b200041086a290300210620024102360200200220063703080b200141e0016a240020020f0b41880141081037000b1036000b200441011037000b200441011037000b200541011037000b200441011037000b200441011037000b200541011037000b0a0041acb4c3001032000b910c03047f017e057f230041206b2202240002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a2203410c4b0d0020030e0d0102030405060708090a0b0c0d010b41e0ffc4001032000b4101210302400240200141046a2d00004101460d002002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002104410021030c010b200141086a28020021040b200041286a2001290328370300200041046a20033a0000200041056a20022f011c3b0000200041086a20043602002000410c6a2002290300370200200041306a200141306a290300370300200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a28020036020020012d00012101200041013a0000200020013a00010c0c0b200041023a0000200041106a200141106a290300370300200041086a200141086a2903003703000c0b0b200041033a0000200041106a200141106a290300370300200041086a200141086a2903003703000c0a0b200041043a00000c090b200041053a0000200041106a200141106a290300370300200041086a200141086a2903003703000c080b2001410c6a2802002205ad42247e2206422088a70d082006a72204417f4c0d08200141046a28020021030240024020040d00410421070c010b200410282207450d0a0b0240024020050d00410021040c010b200541246c2108410021042002411e6a21092007210103400240024020032d00004101460d002009200341036a2d00003a0000200341046a280000210a200341016a2f0000210b200241086a200341106a290000370300200241106a200341186a290000370300200241186a200341206a2d00003a00002002200b3b011c2002200341086a2900003703004100210b0c010b200341046a280200210a4101210b0b200341246a21032001200b3a0000200141046a200a360200200141016a20022f011c3b0000200141036a20092d00003a0000200141086a2002290300370200200141106a200241086a290300370200200141186a200241106a290300370200200141206a200241186a280200360200200141246a2101200441016a21042008415c6a22080d000b0b200041063a00002000410c6a2004360200200041086a2005360200200041046a20073602000c070b200041073a00000c060b200041083a0000200020012d00013a00010c050b4101210302400240200141046a2d00004101460d002002411e6a200141076a2d00003a0000200241086a200141146a290000370300200241106a2001411c6a290000370300200241186a200141246a2d00003a00002002200141056a2f00003b011c20022001410c6a290000370300200141086a2800002101410021030c010b200141086a28020021010b200041093a0000200041046a20033a0000200041056a20022f011c3b0000200041086a20013602002000410c6a2002290300370200200041076a2002411e6a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c040b2000410a3a0000200041046a200141046a2802003602000c030b2000410b3a00000c020b2000410c3a00000c010b2001410c6a280200220841ffffff3f712008470d0120084105742203417f4c0d01200141046a28020021010240024020030d004101210a0c010b20031028220a450d040b0240024020080d0041002108410021010c010b20084105742104200a2103034020032001290000370000200341186a200141186a290000370000200341106a200141106a290000370000200341086a200141086a290000370000200341206a2103200141206a2101200441606a22040d000b200841057441606a41057641016a21010b2000410d3a00002000410c6a2001360200200041086a2008360200200041046a200a3602000b200241206a24000f0b1036000b200441041037000b200341011037000bab0701017f024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d0000417f6a220241104b0d0020020e110102030405060708090a0b0c0d0e0f1011010b41e8d0c5001032000b41880110282202450d102002200141046a28020010cf03200041046a2002360200200041013a0000200041106a200141106a290300370300200041086a200141086a2903003703000f0b200041023a0000200041046a200141046a2802003602000f0b200041033a0000200041046a200141046a280200360200200041026a200141026a2d00003a0000200020012d00014101713a00010f0b200041043a0000200041046a200141046a280200360200200041026a200141026a2d00003a0000200020012d00014101713a00010f0b200041053a0000200041046a200141046a2802003602000f0b41880110282202450d0c2002200141046a28020010cf03200041063a0000200041046a20023602000f0b41880110282202450d0c2002200141046a28020010cf03200041073a0000200041046a20023602000f0b41880110282202450d0c2002200141046a28020010cf03200041083a0000200041046a20023602000f0b200041093a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a2902003702000f0b2000410a3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b2000410b3a0000200041046a200141046a2802003602000f0b2000410c3a00002000410c6a2001410c6a280200360200200041046a200141046a2902003702000f0b2000410d3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b2000410e3a00000f0b2000410f3a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b200041103a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041216a200141216a2d00003a00000f0b200041113a00000f0b41880141081037000b41880141081037000b41880141081037000b41880141081037000bb60401047f0240024002400240024020012d0000417f6a220241034b0d0020020e0401020304010b4188b5c3001032000b200041013a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b200041023a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a2900003700000f0b200041033a000020002001290001370001200041196a200141196a290000370000200041116a200141116a290000370000200041096a200141096a290000370000200041216a200141216a290000370000200041296a200141296a290000370000200041316a200141316a290000370000200041396a200141396a2900003700000f0b024002402001410c6a280200220341ffffff3f712003470d0020034105742202417f4c0d00200141046a28020021010240024020020d00410121040c010b200210282204450d020b0240024020030d0041002103410021010c010b2003410574210520042102034020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a290000370000200241206a2102200141206a2101200541606a22050d000b200341057441606a41057641016a21010b200041043a00002000410c6a2001360200200041086a2003360200200041046a20043602000f0b1036000b200241011037000b8d0c07037f017e017f017e017f017e017f230041c0006b220224000240024002400240024002400240024002400240024020012d0000417f6a220341044b0d0020030e050102030405010b41d093c4001032000b200041f9006a2002280020360000200041086a200141086a290300370300200041fc006a200241236a280000360000200041106a200141106a290300370300200041186a200141186a290300370300200041206a200141206a290300370300200041286a200141286a290300370300200041306a200141306a290300370300200041386a200141386a290300370300200041c0006a200141c0006a290300370300200041c8006a200141c8006a290300370300200041d0006a200141d0006a290300370300200041d8006a200141d8006a290300370300200041e0006a200141e0006a290300370300200041e8006a200141e8006a290300370300200041f0006a200141f0006a290300370300200041f8006a200141f8006a2d00004100473a0000200041013a00000c040b2001410c6a2802002203417f4c0d04200141046a2802002104200141106a29030021050240024020030d0041002101410121060c010b20032101200310282206450d060b200620042003109a0521042000410c6a2003360200200041086a2001360200200041046a2004360200200041106a2005370300200041023a00000c030b4101210402400240200141046a2d00004101460d00200241026a200141076a2d00003a0000200241206a41086a200141146a290000370300200241306a2001411c6a290000370300200241386a200141246a2d00003a00002002200141056a2f00003b010020022001410c6a290000370320200141086a2800002106410021040c010b200141086a28020021060b200141306a2802002203417f4c0d03200141c0006a29030021052001290338210720012802282108200129034821090240024020030d00410021014101210a0c010b2003210120031028220a450d060b200a20082003109a052108200041c0006a2005370300200041386a2007370300200041046a20043a0000200041086a2006360200200041c8006a2009370300200041306a20033602002000412c6a2001360200200041286a2008360200200041056a20022f01003b0000200041076a200241026a2d00003a00002000410c6a2002290320370200200041146a200241206a41086a2903003702002000411c6a200241306a290300370200200041246a200241386a280200360200200041033a00000c020b200141386a2903002105200141306a2903002107200141c0006a2903002109200241386a200141196a290000370300200241306a200141116a290000370300200241286a200141096a290000370300200220012900013703202001412c6a2802002203417f4c0d02200141246a28020021010240024020030d0041012104410021060c010b20032106200310282204450d060b200420012003109a052101200041386a2005370300200041306a2007370300200041c0006a20093703002000412c6a2003360200200041286a2006360200200041246a2001360200200041043a000020002002290320370001200041096a200241286a290300370000200041116a200241306a290300370000200041196a200241386a2903003700000c010b200241186a2204200141196a290000370300200241106a2206200141116a290000370300200241086a2208200141096a29000037030020022001290001370300410021030240200141216a2d00004101470d00200241206a41186a2001413a6a290000370300200241206a41106a200141326a290000370300200241206a41086a2001412a6a2900003703002002200141226a290000370320410121030b20002002290300370001200041216a20033a0000200041226a2002290320370000200041196a2004290300370000200041116a2006290300370000200041096a20082903003700002000412a6a200241206a41086a290300370000200041326a200241206a41106a2903003700002000413a6a200241206a41186a290300370000200041053a00000b200241c0006a24000f0b1036000b200341011037000b200341011037000b200341011037000b920501047f230041206b2202240002400240024002400240024002402001280200417f6a220341024b0d0020030e03010203010b41dc9cc4001032000b41880110282203450d032003200128020410cf0320004101360200200020033602040c020b410121030240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002101410021030c010b200141086a28020021010b200020033a0004200020022f011c3b000520004102360200200041086a20013602002000410c6a2002290300370200200041076a2002411c6a41026a2d00003a0000200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000c010b410121040240024020012d00044101460d002002411e6a200141046a220341036a2d00003a0000200241086a200141146a290200370300200241106a2001411c6a290200370300200241186a200141246a2d00003a0000200220032f00013b011c20022001410c6a290200370300200141086a2802002105410021040c010b200141086a28020021050b41880110282203450d022003200128022810cf03200020043a0004200041086a2005360200200041286a200336020020004103360200200020022f011c3b0005200041076a2002411e6a2d00003a00002000410c6a2002290300370200200041146a200241086a2903003702002000411c6a200241106a290300370200200041246a200241186a2802003602000b200241206a24000f0b41880141081037000b41880141081037000b0a0041b095c4001032000bad0301047f230041106b22022400024002400240024002400240024002400240024002402001280200417f6a220341054b0d0020030e06010203040506010b41e4f0c2001032000b200041013602000c050b2001410c6a2802002203417f4c0d05200128020421010240024020030d0041002104410121050c010b20032104200310282205450d070b200520012003109a0521012000410c6a2003360200200041086a200436020020002001360204200041023602000c040b20004103360200200041086a200141086a2903003703000c030b2001410c6a2802002203417f4c0d03200128020421010240024020030d0041012104410021050c010b20032105200310282204450d060b200420012003109a0521012000410c6a2003360200200041086a200536020020002001360204200041043602000c020b2002200141046a106f200041053602002000410c6a200241086a280200360200200020022903003702040c010b2002200141046a1071200041063602002000410c6a200241086a280200360200200020022903003702040b200241106a24000f0b1036000b200341011037000b200341011037000bdd0301047f024002400240024002400240024020012d0000417f6a220241034b0d0020020e0401020304010b41c0f1c2001032000b2001410c6a280200220341ffffff3f712003470d0320034105742202417f4c0d03200141046a28020021010240024020020d00410121040c010b200210282204450d050b0240024020030d0041002103410021010c010b2003410574210520042102034020022001290000370000200241186a200141186a290000370000200241106a200141106a290000370000200241086a200141086a290000370000200241206a2102200141206a2101200541606a22050d000b200341057441606a41057641016a21010b200041013a00002000410c6a2001360200200041086a2003360200200041046a20043602000f0b200141046a10ba032101200041023a0000200041046a20013602000f0b200141046a2802002102200041086a200141086a10ba03360200200041046a2002360200200041033a00000f0b200041043a000020002001290001370001200041096a200141096a290000370000200041116a200141116a290000370000200041196a200141196a290000370000200041246a200141246a280200360200200041216a200141216a2d00004100473a00000f0b1036000b200241011037000b3400200041c5b6c30036020420004100360200200041146a4102360200200041106a41ccb6c300360200200041086a42073702000be40201047f230041c0006b2202240002400240410f10282203450d00200341076a4100290092b4433700002003410029008bb4433700002003410f411e102c2203450d012003200036000f200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034113200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002003102a200128020021042001280208210320024100360228200242013703202003200241206a10b40102402003450d00200341057421002004210303402003200241206a108f01200341206a2103200041606a22000d000b0b2002280224210320024120200228022022002002280228100702402003450d002000102a0b0240200141046a280200450d002004102a0b200241c0006a24000f0b410f41011037000b411e41011037000b8a1401037f200141046a2802002102200141086a28020021030240024002400240024002400240024002400240024002400240024002400240024020002d00004101460d000240024020022003460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0220012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41003a00000240024002400240024002400240024020002d00010e080001020304050607000b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d18200341017422022000200220004b1b22024100480d180240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d17200341017422022000200220004b1b22024100480d170240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d16200341017422022000200220004b1b22024100480d160240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41023a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d15200341017422022000200220004b1b22024100480d150240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41033a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d14200341017422022000200220004b1b22024100480d140240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41043a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d13200341017422022000200220004b1b22024100480d130240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41053a00000f0b02400240200141046a28020020042802002203460d00200128020021000c010b200341016a22002003490d12200341017422022000200220004b1b22024100480d120240024020030d002002102821000c010b200128020020032002102c21000b2000450d0a20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41063a00000f0b02400240200141046a28020020042802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0a20012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41073a000002400240200141046a28020020042802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0b20012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a20002d00023a00000f0b0240024020022003460d00200128020021020c010b200341016a22022003490d10200341017422042002200420024b1b22044100480d100240024020030d002004102821020c010b200128020020032004102c21020b2002450d0b20012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a41013a0000024020002d0001220341024b0d0002400240024020030e03000102000b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d13200341017422022000200220004b1b22024100480d130240024020030d002002102821000c010b200128020020032002102c21000b2000450d0f20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41003a00000f0b02400240200141046a280200200141086a2802002203460d00200128020021000c010b200341016a22002003490d12200341017422022000200220004b1b22024100480d120240024020030d002002102821000c010b200128020020032002102c21000b2000450d0f20012000360200200141046a2002360200200141086a28020021030b200141086a200341016a360200200020036a41013a00000f0b02400240200141046a280200200141086a2802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d0f20012002360200200141046a2004360200200141086a28020021030b200141086a2204200341016a360200200220036a41023a000002400240200141046a28020020042802002203460d00200128020021020c010b200341016a22022003490d11200341017422042002200420024b1b22044100480d110240024020030d002004102821020c010b200128020020032004102c21020b2002450d1020012002360200200141046a2004360200200141086a28020021030b200141086a200341016a360200200220036a20002d00023a00000b0f0b200441011037000b200241011037000b200241011037000b200241011037000b200241011037000b200241011037000b200241011037000b200241011037000b200441011037000b200441011037000b200441011037000b200241011037000b200241011037000b200441011037000b200441011037000b1031000bac64070e7f017e047f017e047f0f7e087f230041900b6b220124004100210241002103410421040240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402000410c6a28020041246c2205450d00200028020421064104210441002102410021030340024020062d00004101470d00200641106a2802002207417f4c0d1a200641086a2802002108200641016a28000021090240024020070d004101210a4100210b0c010b2007210b20071028220a450d040b200a20082007109a05210a20014188076a41026a220c200141f0056a41026a2d00003a0000200141a0086a41086a220d200141c0096a41086a290200370300200120012f00f0053b018807200120012902c0093703a008024020022003470d00200241016a22082002490d1d2002410174220e2008200e20084b1b2203ad42247e220f422088a70d1d200fa722084100480d1d0240024020020d002008102821040c010b2004200241246c2008102c21040b2004450d050b2004200241246c6a220841013a000020082009360001200820073600102008200b36000c2008200a360008200820012f0188073b0005200841076a200c2d00003a0000200820012903a0083702142008411c6a200d290300370200200241016a21020b200641246a21062005415c6a22050d000b0b200141003602a0084188e8c2004110200141a0086a4104100720014188076a41086a22064200370300200142003703880741d9efc200410d20014188076a1008200141f0056a41086a2208200629030037030020012001290388073703f0052001200028020022073602a008200141f0056a4110200141a0086a4104100720064200370300200142003703880741b1f0c200410d20014188076a10082008200629030037030020012001290388073703f005200141103602a4082001200141f0056a3602a00820042002200141a0086a10e102200642003703002001420037038807419df2c200411120014188076a10082008200629030037030020012001290388073703f005200141103602a4082001200141f0056a3602a008200041106a2205200141a0086a10f002411010282206450d02200641086a41002900c6f042370000200641002900bef042370000200641104120102c2208450d0320082007417f6a360010200141d8046a41186a22064200370300200141d8046a41106a22074200370300200141d8046a41086a22094200370300200142003703d80420084114200141d8046a100020014188076a41186a200629030037030020014188076a41106a200729030037030020014188076a41086a22062009290300370300200120012903d804370388072008102a200141203602a408200120014188076a3602a0082005200141a0086a10f00220064200370300200142003703880741e6efc200411520014188076a1008200141f0056a41086a2208200629030037030020012001290388073703f005200141103602a4082001200141f0056a3602a008200041d0006a200141a0086a10f00220064200370300200142003703880741aef2c200411520014188076a10082008200629030037030020012001290388073703f005200141a0086a200141f0056a10a903024020012802a40822070d00200141013602d804410021094100210641002105410021080c060b200120073602d804200141ac086a280200210620012802a008210920012802a8082105024020012903a808220f422088a741d1004f0d00200fa721080c060b200141a0086a41186a220a200041286a290000370300200141a0086a41106a220b200041206a290000370300200141a0086a41086a220c200041186a290000370300200120002900103703a00820062009411874220941187522084d0d04200720084105746a220820012903a008370000200841186a200a290300370000200841106a200b290300370000200841086a200c290300370000200941808080086a41187541d1006f21090c060b200741011037000b200841041037000b411041011037000b412041011037000b41c4f2c200200820061034000b200141a0086a41186a220a200041286a290000370300200141a0086a41106a220b200041206a290000370300200141a0086a41086a220c200041186a290000370300200120002900103703a008024020062008470d0020052006470d00200641016a22082006490d14200641017422072008200720084b1b220541ffffff3f712005470d14200541057422074100480d140240024020060d002007102821080c010b20012802d80420064105742007102c21080b2008450d02200120083602d8040b20012802d804220720064105746a220820012903a008370000200841086a200c290300370000200841106a200b290300370000200841186a200a290300370000200641016a21060b20014188076a41086a22084200370300200142003703880741aef2c200411520014188076a1008200141f0056a41086a200829030037030020012001290388073703f0050240024020070d00200141f0056a411010090c010b410110282208450d0220014281808080103702a408200120083602a008200820093a00002006200141a0086a10b40102402006450d00200641057421082007210603402001200141a0086a3602c0092006200141c0096a10c801200641206a2106200841606a22080d000b0b20012802a4082106200141f0056a411020012802a008220820012802a808100702402006450d002008102a0b2007450d002005450d002007102a0b20014188076a41086a22084200370300200142003703880741d4f2c200410d20014188076a1008200141f0056a41086a2206200829030037030020012001290388073703f005200141f0056a4110100920084200370300200142003703880741eea0c600411120014188076a10082006200829030037030020012001290388073703f005200141f0056a41101009411210282206450d02200641106a41002f00f1f2423b0000200641086a41002900e9f242370000200641002900e1f242370000200141d8046a41186a22074200370300200141d8046a41106a22054200370300200141d8046a41086a22094200370300200142003703d80420064112200141d8046a100020014188076a41186a200729030037030020014188076a41106a200529030037030020082009290300370300200120012903d804370388072006102a20014188076a4120100e2000280200211010eb0220104105490d07200141f0056a41086a22064200370300200142003703f0054193cdc2004111200141f0056a1008200141a0086a41086a2006290300370300200120012903f0053703a008200141003602c009200141a0086a4110200141c0096a100621060240024020012802c0092208417f460d002006450d002001200836028c072001200636028807200141c0096a20014188076a107b20012802c009220a450d0520012902c409210f2008450d012006102a0c010b4104210a4200210f0b2010417b6a2105200a200f422088a7220b41c4006c22066a21090240200641cd014f0d0041002106200a21080c060b200a41d0016a21084100210603400240200841b07e6a22072d00004101460d00200841b47e6a28020020054f0d080b0240200741c4006a2d00004101460d00200841f87e6a2802002005490d00200641016a21060c080b024020074188016a2d00004101460d00200841bc7f6a2802002005490d00200641026a21060c080b02400240200741cc016a2d00004101460d00200828020020054f0d010b20084190026a2108200641046a2106200920074190026a6b41cc014d0d060c010b0b200641036a21060c060b200741011037000b410141011037000b411241011037000b41c4d1c3004133200141f0056a419cd9c3001038000b200841b07e6a21080b20082009460d00200a200b41c4006c6a21070340024020082d00004101460d00200841046a28020020054f0d020b200641016a21062007200841c4006a2208470d000b0b2006200b4b0d01200f42ffffffff0f83210f0240200b20066b2208450d0002402006450d00200a200a200641c4006c6a200841c4006c109b051a0b2008ad422086200f84210f0b200141f0056a41086a22064200370300200142003703f0054193cdc2004111200141f0056a1008200141a0086a41086a2006290300370300200120012903f0053703a008200141c0096a200a200f422088a7109202200141a0086a411020012802c009220820012802c8091007200fa72106024020012802c409450d002008102a0b2006450d00200a102a0b200141003a00c009200141f0056a41086a22064200370300200142003703f00541c8fbc5004117200141f0056a1008200141a0086a41086a22082006290300370300200120012903f0053703a008200141a0086a4110200141c0096a41011007200141a0086a10f801412410282206450d01200620012903a00837000020064114360220200641186a200141a0086a41186a290300370000200641106a200141a0086a41106a290300370000200641086a200829030037000020014281808080103702c409200120063602c009200141c0096a10f901201010ea0202400240201041809c3170450d0020014188076a21110c010b200141f0056a41086a22064200370300200142003703f00541d590c600411f200141f0056a100820014188076a41086a2006290300370300200120012903f00537038807200141003602a00820014188076a4110200141a0086a1006210602400240024020012802a0082208417f460d002006450d002008450d0120062d000021082006102a20014188076a4110100920084102460d0020084101710d020b20014188076a2111201010c803450d02201010c9031a0c020b41c4d1c3004133200141f0056a419cd9c3001038000b20014188076a2111201010c903450d00201010c8031a0b200141f0056a41086a22064200370300200142003703f00541c290c6004113200141f0056a100820014188076a41086a2006290300370300200120012903f0053703880741002106200141003602a00820114110200141a0086a10062108024020012802a0082207417f460d002008450d0020074104490d03200828000021062008102a0b200141f0056a41086a22084200370300200142003703f00541a990c6004119200141f0056a100820014188076a41086a2008290300370300200120012903f0053703880741002108200141003602a00820114110200141a0086a10062107024020012802a0082205417f460d002007450d0020054104490d04200728000021082007102a0b02400240200620084f0d0002400340200141c0096a200610ca0320012802c00922074113470d012008200641016a2206470d000c020b0b20014188076a200141c0096a410472419401109a051a200141f0056a20014188076a419401109a051a200141d8046a200141f0056a419401109a051a200120073602a80820012006ad220f3703a008200141ac086a200141d8046a419401109a052105200141b0096a2802002010460d01200141a8086a106a0b4108211241002106410021130c080b200141c0036a2005419401109a051a200141a0086a200141c0036a419401109a051a41a00110282212450d04201220073602082012200f3703002012410c6a200141a0086a419401109a051a02400240200641016a220720084f0d000340200141c0096a200710ca0320012802c00922054113470d022008200741016a2207470d000b0b41012106410121130c080b20014188076a200141c0096a410472220c419401109a051a200141f0056a20014188076a419401109a051a200141d8046a200141f0056a419401109a051a200120053602a80820012007ad220f3703a008200141a0086a410c6a200141d8046a419401109a05210a41012106200141a8086a210b200141b0096a2802002010470d06200741016a2107200141c0036a200a419401109a051a41012106410121130340200141a0086a200141c0036a419401109a051a024020132006470d00200641016a22092006490d0c2006410174220d2009200d20094b1b2213ad42a0017e2214422088a70d0c2014a722094100480d0c024002402006450d002012200641a0016c2009102c21120c010b2009102821120b2012450d070b2012200641a0016c6a220920053602082009200f3703002009410c6a200141a0086a419401109a051a200641016a2106200720084f0d0802400340200141c0096a200710ca03024020012802c00922054113460d0020014188076a200c419401109a051a200141f0056a20014188076a419401109a051a200141d8046a200141f0056a419401109a051a200120053602a80820012007ad220f3703a008200a200141d8046a419401109a05210920012802b0092010470d02200741016a2107200141c0036a2009419401109a051a0c030b2008200741016a2207470d000c0a0b0b0b200b106a0c070b41e4e8c5001032000b412441041037000b41c4d1c3004133200141f0056a419cd9c3001038000b41c4d1c3004133200141f0056a419cd9c3001038000b41a00141081037000b200941081037000b200b106a410121130b2012200641a0016c6a2115024020060d00201221160c020b20014188076a4104722106200141a0086a410472211720014198026a41086a21182012211603402016280200210520162802082108200141a0086a2016410c6a419401109a051a201641a0016a211620084113460d02200141c0096a200141a0086a419401109a051a200120083602a0082017200141c0096a419401109a051a200141f0056a200510cb0320012802f005210b0240024020012802f80522080d00420021194200211a4200211b4200211c4200211d4200211e0c010b200841057421094200211d200b21084200211e4200211b4200211c420021194200211a034020014198036a2008109d0220014198036a41086a2903002114200129039803210f20062008290000370000200641086a200841086a290000370000200641106a200841106a290000370000200641186a200841186a290000370000200120053602880720014190036a20014188076a10cc0320012d00900341017121070240024020012d009103220a0d00200141d0026a200f2014420a420010a00520012903d002221f210f200141d0026a41086a290300222021140c010b200141f0026a20144200200aad221f4200109f0520014180036a200f4200201f4200109f05200141e0026a42004200200f4200109f05427f20014180036a41086a290300221f20012903f00220012903e0027c7c222020012903f80220012903e802844200522020201f5472220a1b2120427f200129038003200a1b211f0b200841206a21084200202020071b201c7c4200201f20071b2221201b7c221b202154ad7c211c2020420020071b201a7c201f420020071b221f20197c2219201f54ad7c211a2014201e7c200f201d7c221d200f54ad7c211e200941606a22090d000b0b024020012802f405450d00200b102a0b200141f0056a200510cb0320012802f00521000240024020012802f80522080d004200212142002122420021234200212442002120420021250c010b2008410574210942002120200021084200212542002123420021244200212142002122034020062008290000370000200641086a200841086a2207290000370000200641106a200841106a220a290000370000200641186a200841186a220b2900003700002001200536028807200141c8026a20014188076a10cc0320012d00c802210c20012d00c902210d20014188076a41186a200b29000037030020014188076a41106a200a29000037030020014188076a41086a20072900003703002001200829000037038807200141a8026a200520014188076a200d411010cd03200141a8026a41186a29030020257c20012903b802220f20207c2220200f54ad7c21254200200141a8026a41086a290300220f200c41017122071b20247c420020012903a802221420071b221f20237c2223201f54ad7c2124200f420020071b20227c2014420020071b220f20217c2221200f54ad7c2122200841206a2108200941606a22090d000b0b024020012802f405450d002000102a0b20014198026a10a1022018290300210f2001290398022114024002402020201d7c221f4202882025201e7c201f202054ad7c2220423e8684221d2020420288221e84500d00201d201f85201e20208584500d00410021080240034020014188026a201f2020200841046a41fe0071109e05200841026a2108200129038802221d20014188026a41086a290300221e84500d01201d201f85201e2020858450450d000b0b200141f8016a201f2020200841fe0071109e0520012903f801200141f8016a41086a29030084211d4200211e024020080d00201d420052ad211d0c020b201d420052ad211d0340200141d8016a201f202041002008417e6a2207200720084b1b220841ff0071109e05200141e8016a201d42018622264201842225201e420186201d423f8884221e2025201e109f052026202520012903e80120012903d80156200141e8016a41086a290300221d200141d8016a41086a290300222756201d2027511b1b211d20080d000c020b0b4200211e201f202084420052ad211d0b024002402014420288200f423e8684221f200f420288222084500d00201f2014852020200f8584500d004100210802400340200141c8016a2014200f200841046a41fe0071109e05200841026a210820012903c801221f200141c8016a41086a290300222084500d01201f2014852020200f858450450d000b0b200141b8016a2014200f200841fe0071109e0520012903b801200141b8016a41086a29030084211f42002120024020080d00201f420052ad211f0c020b201f420052ad211f034020014198016a2014200f41002008417e6a2207200720084b1b220841ff0071109e05200141a8016a201f420186222642018422252020420186201f423f8884222020252020109f052026202520012903a80120012903980156200141a8016a41086a290300221f20014198016a41086a290300222756201f2027511b1b211f20080d000c020b0b420021202014200f84420052ad211f0b02400240024002400240201d201e8450450d004100210b0c010b2024201c7c2023201b7c2214202354ad7c21232022201a7c202120197c220f202154ad7c212102400240024020012d00b0090e03010200010b200f201456202120235620212023511b210b0c020b0340200141c8006a20142023201d201e10a005201f22192020221a844200510d04200141c8006a41086a290300211f20012903482120200141386a200f20212019201a10a0054101210b20202001290338221b54201f200141386a41086a290300222554201f20255122081b0d020240201b2020542025201f5420081b450d004100210b0c030b200141286a2020201f201d201e109f05200141186a201b20252019201a109f050240200f2001290318221f7d22202021200141186a41086a2903007d200f201f54ad7d222584500d002023200141286a41086a2903007d211b20142001290328220f5421082014200f7d211f201d210f201e21212020211d2025211e20192114201a2123201f201b2008ad7d222084500d030c010b0b4100210b0c010b0340201e2125201d2119201f2020844200510d02200141f8006a200f20212019202510a00520014188016a20142023201f202010a0054101210b200129038801221a2001290378221b5420014188016a41086a290300221d200141f8006a41086a290300221e54201d201e5122081b0d010240201b201a54201e201d5420081b450d004100210b0c020b200141e8006a201a201d201f2020109f05200141d8006a201b201e20192025109f050240200f2001290358221d7d221e2021200141d8006a41086a2903007d200f201d54ad7d221a8450450d004100210b0c020b2023200141e8006a41086a2903007d211b20142001290368220f5421082014200f7d211d201f210f20202121201e211f201a21202019211420252123201d201b2008ad7d221e844200520d000b0b20014188076a200510cb032001280288072128200128028c0721292001280290072208450d0220282008410574222a6a212b2028210802400340200141f0056a41186a2207200841186a220c290000370300200141f0056a41106a2209200841106a220d290000370300200141f0056a41086a220a200841086a2200290000370300200120082900003703f0052008290000210f200641186a222c200c2900003700002006200f370000200641086a222d2000290000370000200641106a222e200d2900003700002001200536028807200141106a20014188076a10cc0320012d0011210e20012d0010212f20014188076a41186a220c200729030037030020014188076a41106a220d200929030037030020014188076a41086a2200200a290300370300200120012903f005370388070240200b202f41017145734101470d00200841206a21080c020b200841206a2108202a41606a222a0d000c040b0b0340200141d8046a41186a200c290300220f370300200141d8046a41106a200d2903002214370300200141d8046a41086a2000290300221f370300200120012903880722203703d804200c200f370300200d20143703002000201f370300200142e4cab5fbb6ccdcb0e3003703a8032001202037038807200141a8036a20014188076a200e41187441187541027441f48fc6006a2802004180de346c20106a10a8022008202b460d03024003402007200841186a220e2900003703002009200841106a222f290000370300200a200841086a222a290000370300200120082900003703f0052001200536028807202a290000210f202f29000021142008290000211f202c200e290000370000202e2014370000202d200f3700002006201f370000200141086a20014188076a10cc0320012d0009210e20012d0008212f200c2007290300370300200d20092903003703002000200a290300370300200120012903f00537038807200b202f41017145730d01202b200841206a2208470d000c050b0b200841206a21080c000b0b41f895c1001032000b41f895c1001032000b02402029450d002028102a0b200510ce0302400240200b0d00200141053a009007200141053a00880720012005360294074101410020014188076a10cc01200141f0056a41086a22084200370300200142003703f00541c290c6004113200141f0056a100820014188076a41086a2008290300370300200120012903f005370388072001200541016a3602f00520114110200141f0056a41041007200141a0086a106a0c010b2001200536029407200141043a009007200141053a0088074101410020014188076a10cc01024020012802ac092207450d00200141f0056a200141a0086a418801109a051a200120053602f80602400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240411710282208450d002008410f6a41002900918945220f370000200841086a410029008a89452214370000200841002900828945221f37000020084117412e102c2208450d012008200720106a2200360017200141d8046a41186a22074200370300200141d8046a41106a22094200370300200141d8046a41086a220a4200370300200142003703d8042008411b200141d8046a100020014188076a41186a220e200729030037030020014188076a41106a222f200929030037030020014188076a41086a220c200a290300370300200120012903d804370388072008102a200141003602d80420014188076a4120200141d8046a1006210b0240024020012802d8042208417f470d00200141003602e004200142013703d8044100200141d8046a10b40120012802e004210820012802dc04210d20012802d804210b0c010b2008210d0b200120083602b8032001200d3602b4032001200b3602b003024002400240024002402008450d00200141d8046a200b2008410110d60220012802d8044101460d0420012802dc04212a20012802e404220820012802e004220b460d0320012802b8032008200b6b6a220d4190016a222c417f4c0d1f202c0d014101212d0c020b4101200141b0036a10b40120012802b403210b20012802b8032108024020012802f0054113470d0002400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d222008410174220d200b200d200b4b1b220d4100480d220240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d082001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41003a00000c150b02400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d212008410174220d200b200d200b4b1b220d4100480d210240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d082001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41013a0000200141f0056a200141b0036a10eb01200141f0056a4188016a280200210d0240024020012802b403220b20012802b80322086b4104490d0020012802b003210b0c010b200841046a222a2008490d21200b4101742208202a2008202a4b1b22084100480d2102400240200b0d0020081028210b0c010b20012802b003200b2008102c210b0b200b450d09200120083602b4032001200b3602b00320012802b80321080b2001200841046a3602b803200b20086a200d3600000c140b202c1028222d450d080b2001202c3602dc0a2001202d3602d80a2001200d3602e00a2001200141d80a6a3602d804202a200141d8046a200810d701200d2008490d0820012802e00a222a200d490d0920012802b803222a200b490d0a20012802d80a212c20012802b003212d2001200d20086b220d3602e80a2001202a200b6b222a3602ec0a200d202a470d0b202c20086a202d200b6a200d109a051a20012802dc0a210b20012802e00a21080240024020012802f0054113470d0002400240200b2008460d0020012802d80a210b0c010b200841016a220b2008490d212008410174220d200b200d200b4b1b220d4100480d210240024020080d00200d1028210b0c010b20012802d80a2008200d102c210b0b200b450d0f2001200d3602dc0a2001200b3602d80a20012802e00a21080b2001200841016a3602e00a200b20086a41003a00000c010b02400240200b2008460d0020012802d80a210b0c010b200841016a220b2008490d202008410174220d200b200d200b4b1b220d4100480d200240024020080d00200d1028210b0c010b20012802d80a2008200d102c210b0b200b450d0f2001200d3602dc0a2001200b3602d80a20012802e00a21080b2001200841016a3602e00a200b20086a41013a0000200141f0056a200141d80a6a10eb01200141f0056a4188016a280200210d0240024020012802dc0a220b20012802e00a22086b4104490d0020012802d80a210b0c010b200841046a222a2008490d20200b4101742208202a2008202a4b1b22084100480d2002400240200b0d0020081028210b0c010b20012802d80a200b2008102c210b0b200b450d10200120083602dc0a2001200b3602d80a20012802e00a21080b2001200841046a3602e00a200b20086a200d3600000b20012802e00a210b20012802dc0a210d20012802d80a210820012802b403450d1320012802b003102a0c130b2001200141b0036a3602d804202a200141d8046a200b10d70120012802b403210b20012802b8032108024020012802f0054113470d0002400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d1f2008410174220d200b200d200b4b1b220d4100480d1f0240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d102001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41003a00000c120b02400240200b2008460d0020012802b003210b0c010b200841016a220b2008490d1e2008410174220d200b200d200b4b1b220d4100480d1e0240024020080d00200d1028210b0c010b20012802b0032008200d102c210b0b200b450d102001200d3602b4032001200b3602b00320012802b80321080b2001200841016a3602b803200b20086a41013a0000200141f0056a200141b0036a10eb01200141f0056a4188016a280200210d0240024020012802b403220b20012802b80322086b4104490d0020012802b003210b0c010b200841046a222a2008490d1e200b4101742208202a2008202a4b1b22084100480d1e02400240200b0d0020081028210b0c010b20012802b003200b2008102c210b0b200b450d11200120083602b4032001200b3602b00320012802b80321080b2001200841046a3602b803200b20086a200d3600000c110b20012802b403450d1220012802b003102a0c120b411741011037000b412e41011037000b200d41011037000b200d41011037000b200841011037000b202c41011037000b2008200d1044000b200d202a103c000b200b202a1044000b200141c0036a41146a4108360200200141cc036a4125360200200141f00a6a41146a4103360200200142033702f40a200141c8afc6003602f00a200141253602c4032001200141e80a6a3602880b2001200141ec0a6a36028c0b200142043703e804200142013702dc042001419cb0c6003602d8042001200141c0036a3602800b2001200141d8046a3602d00320012001418c0b6a3602c8032001200141880b6a3602c003200141f00a6a41d8b0c600103e000b200d41011037000b200d41011037000b200841011037000b200d41011037000b200d41011037000b200841011037000b20012802b803210b20012802b403210d20012802b00321080b2008450d0020014188076a41202008200b1007200d450d012008102a0c010b41900110282208450d014113210b024020012802f0054113460d0020014188076a200141f0056a10cf032001200141f0056a4188016a28020036029008200128028807210b200141d8046a2006418c01109a051a0b2008200b360200200841046a200141d8046a418c01109a051a41171028220b450d02200b410f6a200f370000200b41086a2014370000200b201f370000200b4117412e102c220b450d03200b20003600172007420037030020094200370300200a4200370300200142003703d804200b411b200141d8046a1000200e2007290300370300202f2009290300370300200c200a290300370300200120012903d80437038807200b102a200141d8046a2008410110ac0220014188076a412020012802d804220720012802e0041007024020012802dc04450d002007102a0b024020082802004113460d002008106a0b2008102a0b024020012802f0054113460d00200141f0056a106a0b200141f0056a41086a22084200370300200142003703f00541c290c6004113200141f0056a1008200c2008290300370300200120012903f005370388072001200541016a3602f00520114110200141f0056a410410070c040b41900141081037000b411741011037000b412e41011037000b20014188076a200141a0086a418801109a051a200141003b01f005200141d8046a20014188076a200141f0056a10f401200120012d00e0044102463a009107200141073a009007200141053a00880720012005360294074101410020014188076a10cc01200141f0056a41086a22084200370300200142003703f00541c290c6004113200141f0056a100820014188076a41086a2008290300370300200120012903f005370388072001200541016a3602f00520114110200141f0056a410410070b20162015470d000b201521160c010b1036000b024020162015460d00200141a0086a41086a2108200141a0086a410c6a21070340201641086a28020021062016290300210f200141a0086a2016410c6a419401109a051a20064113460d01200141c0096a200141a0086a419401109a051a200120063602a8082001200f3703a0082007200141c0096a419401109a051a2008106a201641a0016a22162015470d000b0b02402013450d002012102a0b0240024002400240411710282206450d002006410f6a41002900918945370000200641086a410029008a894537000020064100290082894537000020064117412e102c2206450d01200620103600174200210f200141d8046a41186a22084200370300200141d8046a41106a22074200370300200141d8046a41086a22054200370300200142003703d8042006411b200141d8046a100020014188076a41186a200829030037030020014188076a41106a200729030037030020014188076a41086a2005290300370300200120012903d804370388072006102a200141003602a00820014188076a4120200141a0086a100621080240024020012802a0082206417f470d004108210b0c010b200120063602c409200120083602c009200141a0086a200141c0096a10800120012802a008220b450d0320012902a408210f02402006450d002008102a0b20014188076a412010090b200b200f422088a722084190016c22076a2105200b210602402008450d00200741f07e6a2107200141a0086a410472210a200b21060240034020062802002108200141c0096a200641046a418401109a051a20084114460d01200141a0086a200141c0096a418401109a051a02400240024020084113470d0020070d01200521060c050b20064188016a280200210920014188076a200141a0086a418401109a051a200120083602a008200a20014188076a418401109a051a200141003b01c009200141f0056a200141a0086a200141c0096a10f40120012d00f8052108200120093602ac08200120084102463a00a908200141073a00a808200141053a00a00841014100200141a0086a10cc012007450d010b20064190016a2106200741f07e6a21070c010b0b200521060c010b20064190016a21060b200fa7210920062005460d03200141a0086a4104722107034020062802002108200141a0086a200641046a418c01109a051a20084114460d04200141c0096a200141a0086a418c01109a051a200120083602a0082007200141c0096a418c01109a051a024020084113460d00200141a0086a106a0b20064190016a22062005470d000c040b0b411741011037000b412e41011037000b41c4d1c3004133200141f0056a419cd9c3001038000b02402009450d00200b102a0b201010bd0202402002450d00200241246c21082004210603400240024020062d0000220741034b0d0002400240024020070e0404000102040b2006410c6a280200450d03200641086a280200102a0c030b2006410c6a280200450d02200641086a280200102a0c020b2006410c6a280200450d01200641086a280200102a0c010b200641086a280200450d00200641046a280200102a0b200641246a21062008415c6a22080d000b0b02402003450d002004102a0b200141900b6a24000f0b1031000be80201067f230041b0026b2201240020014198016a41086a22024200370300200142003703980141988bc500411620014198016a100820014188016a41086a2203200229030037030020012001290398013703880120014198016a20014188016a10df030240024020012802980122044113470d0041ae8bc50021020c010b20014188016a41101009200141046a20014198016a4104722205418401109a051a200141a0026a2d00002106200141013a00af0220024200370300200142003703980141d590c600411f20014198016a10082003200229030037030020012001290398013703880120014188016a4110200141af026a41011007200241023a0000200141053a009801410021024101410020014198016a10cc0120012004360298012005200141046a418401109a051a20014188016a200041809c316a20014198016a20064180de3410b7042001280288014101470d00200128028c0121020b200141b0026a240020020bc01802117f187e230041f0056b22012400200141a0046a41086a22024200370300200142003703a00441ac89c5004115200141a0046a1008200141306a41086a2002290300370300200120012903a004370330200141003602a004200141306a4110200141a0046a10062103024002400240024002400240024002400240024020012802a0042204417f460d002003450d002001200436024420012003360240200141286a200141c0006a106c20012802280d09200128024441b0016e220541b0016c2202417f4c0d02200128022c21060240024020020d00410821070c010b200210282207450d040b02402006450d0020014198036a4104722108410021094100210a0340024002400240200128024422024104490d002001280240220b280000210c20012002417c6a3602442001200b41046a360240200141a0046a200141c0006a10810120012802a0044113460d00200a41016a210d20014198036a200141a0046a418801109a051a4100210b200141003a00e8052001280244417f6a2102024003402002417f460d01200141c8056a200b6a2001280240220e2d00003a00002001200e41016a3602402001200b41016a220e3a00e805200120023602442002417f6a2102200e210b200e4120470d000b200141a8056a41186a2202200141c8056a41186a290300370300200141a8056a41106a220e200141c8056a41106a290300370300200141a8056a41086a220f200141c8056a41086a290300370300200120012903c8053703a805200128029803210b20014190026a2008418401109a051a200141f0016a41086a2210200f290300370300200141f0016a41106a220f200e290300370300200141f0016a41186a220e2002290300370300200120012903a8053703f001200b4113460d01200141ec006a20014190026a418401109a051a200141c8006a41186a2211200e290300370300200141c8006a41106a220e200f290300370300200141c8006a41086a220f2010290300370300200120012903f0013703482005200a470d030240200a4101742202200d2002200d4b1b2205ad42b0017e2212422088a70d002012a7220241004e0d030b1031000b0240200b41ff0171450d00200141003a00e8050b20014198036a106a0b0240200a450d002007210203402002106a200241b0016a2102200941d07e6a22090d000b0b2005450d0d2007102a0c0d0b02400240200a0d002002102821070c010b2007200a41b0016c2002102c21070b2007450d070b2007200a41b0016c6a2202200b360200200241046a200141ec006a418401109a051a2002200c360288012002200129034837028c0120024194016a200f2903003702002002419c016a200e290300370200200241a4016a2011290300370200200941b0016a2109200d210a200d2006470d000b0b2007450d092006ad42208621122005ad211302402004450d002003102a0b201220138421140c010b41082107420021140b024002402014422088a72204450d00200141a0046a20072802880110b8040240024020012802b00422020d0042002115420021120c010b200141186a20012903a004200141a0046a41086a290300200141b8046a3502004200109f05200141186a41086a29030021122001290318211520012802b404450d002002102a0b4100210e20044101460d012007200441b0016c6a210a200741b0016a21024100210e200721034101210b0340200141a0046a20024188016a28020010b8040240024020012802b00422090d0042002116420021130c010b200141086a20012903a004200141a0046a41086a29030020013502b8044200109f05200141086a41086a29030021132001290308211620012802b404450d002009102a0b201220132015201656201220135620122013511b22091b21122015201620091b21152003200220091b2103200e200b20091b210e200b41016a210b200241b0016a2202200a470d000b20030d01200441b0016c21092007210203402002106a200241b0016a2102200941d07e6a22090d000b0b41e789c50021022014a7450d072007102a0c070b200e20044f0d0320072004417f6a220941b0016c6a22024180016a290300211320024188016a290300211520024190016a290300211620024198016a2903002117200241e0006a2903002118200241e8006a2903002119200241f0006a290300211a200241f8006a290300211b200241c0006a290300211c200241c8006a290300211d200241d0006a290300211e200241d8006a290300211f200241206a2903002120200241286a2903002121200241306a2903002122200241386a2903002123200229030021242002290308212520022903102126200241186a2903002127200241a0016a2903002112200141306a41086a220b200241a8016a29030022283703002007200e41b0016c6a220241186a220e2903002129200e2027370300200229031021272002202637031020022903082126200220253703082002290300212520022024370300200241386a220e2902002124200e2023370200200241306a220e2902002123200e2022370200200241286a220e2902002122200e2021370200200241206a220e2902002121200e2020370200200241d8006a220e2902002120200e201f370200200241d0006a220e290200211f200e201e370200200241c8006a220e290200211e200e201d370200200241c0006a220e290200211d200e201c370200200241f8006a220e290200211c200e201b370200200241f0006a220e290200211b200e201a370200200241e8006a220e290200211a200e2019370200200241e0006a220e2902002119200e201837020020024198016a201737020020024190016a201637020020024188016a2203280200210e2003201537020020024180016a220329020021152003201337020020012012370330200241a0016a2012370200200241a8016a202837020020014198036a41f8006a201c37030020014198036a41f0006a201b37030020014198036a41e8006a201a37030020014198036a41e0006a201937030020014198036a41d8006a202037030020014198036a41d0006a201f37030020014198036a41c8006a201e37030020014198036a41c0006a201d37030020014198036a41386a202437030020014198036a41306a202337030020014198036a41286a202237030020014198036a41206a202137030020014198036a41186a202937030020014198036a4180016a2015370300200120273703a803200120263703a0032001202537039803200141a0046a41086a22024200370300200142003703a00441ac89c5004115200141a0046a1008200b2002290300370300200120012903a004370330200141103602a4042001200141306a3602a00420072009200141a0046a10ef0102402009450d00200441b0016c41d07e6a21092007210203402002106a200241b0016a2102200941d07e6a22090d000b0b02402014a7450d002007102a0b411310282202450d042002410f6a41002800e38945360000200241086a41002900dc8945370000200241002900d48945370000200241134126102c2202450d052002200e360013200141a8056a41186a22094200370300200141a8056a41106a220b4200370300200141a8056a41086a22034200370300200142003703a80520024117200141a8056a100020014190026a41186a200929030037030020014190026a41106a200b29030037030020014190026a41086a2003290300370300200120012903a805370390022002102a200141a0046a20014190026a10e003024020012802b004220b450d0020014190026a412010090b02400240200b450d00200141a8046a290300211220012903a004211320012802b40421030240200141a0046a41186a280200220a4105742209450d00200b2102034020022013201210aa02200241206a2102200941606a22090d000b0b200141c8046a2012370300200141c0046a2013370300200141b8046a200a360200200141b4046a2003360200200141b0046a200b360200200141ac046a200e360200200141a8046a41013a0000200141053a00a00441014100200141a0046a10cc01200141a0046a20014198036a418801109a051a20014190026a200041809c316a200141a0046a41004180de3410b7042001280290024101470d0120012802940221020c080b20014198036a106a0b410021020c060b1036000b200241081037000b200241081037000b41c489c500200e20041034000b411341011037000b412641011037000b200141f0056a240020020f0b41c4d1c3004133200141a0046a419cd9c3001038000b810601067f230041d0026b2202240002400240024002400240411a10282203450d00200341186a41002f00ce88453b0000200341106a41002900c68845370000200341086a41002900be8845370000200341002900b688453700002003411a4134102c2203450d012003200136001a200241c0016a41186a22014200370300200241c0016a41106a22044200370300200241c0016a41086a22054200370300200242003703c0012003411e200241c0016a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903c0013703002003102a200241003602c00120024120200241c0016a1006210320022802c0012201417f460d032003450d03200220033602282002200136022c20014104490d022003280000210620022001417c6a36022c2002200341046a360228200241c0016a200241286a10810120022802c0014113460d02200241386a200241c0016a418801109a051a02400240200228022c2207450d00200228022822012d0000210420022007417f6a220536022c2002200141016a360228200441034f0d00200541034b0d01200241386a106a0c040b200241386a106a0c030b2001280001210520022007417b6a36022c2002200141056a36022820022802382101200241c0016a200241386a410472418401109a051a200220022800303602202002200241336a28000036002320014113460d02200241386a200241c0016a418401109a051a20022002280023360033200220022802203602302003102a0c040b411a41011037000b413441011037000b41c4d1c3004133200241c8026a419cd9c3001038000b411321010b200241c0016a200241386a418401109a051a2002200228003336002b200220022802303602280240024020014113470d00200041133602000c010b20002001360200200041046a200241c0016a418401109a051a20004190016a20043a00002000418c016a200536020020004188016a2006360200200020022802283600910120004194016a200228002b3600000b200241d0026a24000bfb0202047f017e230041d0006b22022400024002400240411310282203450d002003410f6a41002800a88945360000200341086a41002900a18945370000200341002900998945370000200341134126102c2203450d0120032001360013200241286a41186a22014200370300200241286a41106a22044200370300200241286a41086a220542003703002002420037032820034117200241286a1000200241186a2001290300370300200241106a2004290300370300200241086a2005290300370300200220022903283703002003102a2002410036022820024120200241286a100621010240024020022802282203417f460d002002200336022420022001360220200241286a200241206a106d20022802282204450d04200229022c210602402003450d002001102a0b20002006370204200020043602000c010b20004100360208200042013702000b200241d0006a24000f0b411341011037000b412641011037000b41c4d1c3004133200241c8006a419cd9c3001038000ba40301057f230041d0006b22022400024002400240411010282203450d00200341002900a68845370000200341086a41002900ae88453700002002429080808080023702242002200336022020012802002104200341104120102c2203450d0120032004360010200242a0808080c00237022420022003360220200141046a200241206a108f012002280228210320022802202101200241306a41186a22044200370300200241306a41106a22054200370300200241306a41086a220642003703002002420037033020012003200241306a1000200241186a2004290300370300200241106a2005290300370300200241086a20062903003703002002200229033037030002402002280224450d002002280220102a0b410021032002410036023020024120200241306a100621010240024020022802302204417f470d00410021010c010b2004450d0320012d0000220441ff0071220341074f0d032001102a200441077621010b200020033a0001200020013a0000200241d0006a24000f0b411041011037000b412041011037000b41c4d1c3004133200241306a419cd9c3001038000bf00b04017f047e117f087e23004190046b22052400024002400240024020040d00420021064200210742002108420021090c010b42002108200541f0036a41186a220a4200370300200541f0036a41106a220b4200370300200541f0036a41086a220c4200370300200542003703f00341e588c500411d200541f0036a100020054198036a41186a220d200a29030037030020054198036a41106a220e200b29030037030020054198036a41086a220f200c290300370300200520052903f0033703980320054198016a20054198036a412010fd01200541c0016a41206a20054198016a41206a2d00003a0000200541c0016a41186a20054198016a41186a290300370300200541c0016a41106a20054198016a41106a290300370300200541c0016a41086a20054198016a41086a29030037030020052005290398013703c001200541e8016a200541c0016a10af0142002109420021064200210720052d00a8024107460d002004417f6a2110200541b8036a4104722111200541f0026a2112200541b0026a41206a2113200541b0026a41186a211442002106420021074200210842002109034020142007370300200520063703c002200520083703b002200520093703b8022013200541e8016a41c100109a0521040240024020122002460d00201220024120109c050d010b20112004290200370200201141086a200441086a2215290200370200201141106a200441106a2216290200370200201141186a200441186a2217290200370200200520013602b803411010282218450d03201841002900a68845370000201841086a41002900ae88453700002005429080808080023702e403200520183602e00320052802b8032119201841104120102c2218450d04200541203602e403200520052802e803221a41046a3602e803200520183602e0032018201a6a20193600002011200541e0036a108f0120052802e803211820052802e0032119200a4200370300200b4200370300200c4200370300200542003703f00320192018200541f0036a1000200d200a290300370300200e200b290300370300200f200c290300370300200520052903f00337039803024020052802e403450d0020052802e003102a0b20054198036a41204101410041001003417f470d0020052d0090032118200a2017290000370300200b2016290000370300200c2015290000370300200520042900003703f00320054188016a200541f0036a109d0220054188016a41086a290300211b200529038801211c02400240201820032018200341ff0171491b220441ff01710d00200541086a201c201b420a420010a005200541b8036a41186a200a290300370300200541b8036a41106a200b290300370300200541b8036a41086a200c290300370300200520052903f0033703b803200541186a2001200541b8036a4100201010cd03200541186a41186a290300211d200541186a41086a290300211e2005290328211f2005290318212020052903082221211c200541086a41086a2903002222211b0c010b200541c8006a201b42002004ad42ff018322214200109f05200541d8006a201c420020214200109f05200541b8036a41186a200a290300370300200541b8036a41106a200b290300370300200541b8036a41086a200c290300370300200520052903f0033703b803200541e8006a2001200541b8036a2004201010cd03200541386a42004200201c4200109f05427f200541d8006a41086a2903002221200529034820052903387c7c221d2005290350200529034084420052201d2021547222041b2122427f200529035820041b2121200541e8006a41186a290300211d200541e8006a41086a290300211e2005290378211f200529036821200b201b20077c201c20067c2207201c54ad7c201d7c2007201f7c2206200754ad7c2107202220097c202120087c2209202154ad7c201e7c200920207c2208200954ad7c21090b200541e8016a200541c0016a10af0120052d00a8024107470d000b0b2000200637031020002008370300200041186a20073703002000200937030820054190046a24000f0b411041011037000b412041011037000be907030b7f047e027f230041a0016b22012400024002400240024002400240411a10282202450d00200241186a41002f00ce88453b0000200241106a41002900c68845370000200241086a41002900be8845370000200241002900b688453700002002411a4134102c2202450d012002200036001a20014180016a41186a2203420037030020014180016a41106a2204420037030020014180016a41086a2205420037030020014200370380012002411e20014180016a1000200141286a41186a2003290300370300200141286a41106a2004290300370300200141286a41086a200529030037030020012001290380013703282002102a200141286a41201009411310282202450d022002410f6a41002800a88945360000200241086a41002900a18945370000200241002900998945370000200241134126102c2202450d032002200036001320014180016a41186a2205420037030020014180016a41106a2206420037030020014180016a41086a2203420037030020014200370380012002411720014180016a1000200141286a41186a22072005290300370300200141286a41106a22082006290300370300200141286a41086a200329030037030020012001290380013703282002102a200141286a41201009200141c8006a200010cb03200128024c21092001280248210a024020012802502202450d002002410574210b200141c8006a4104722103200a21020340200141086a41186a200241186a290000220c370300200141086a41106a200241106a290000220d370300200141086a41086a200241086a290000220e37030020012002290000220f3703082003200f370200200341086a200e370200200341106a200d370200200341186a200c37020020012000360248411010282204450d06200441002900a68845370000200441086a41002900ae88453700002001429080808080023702742001200436027020012802482110200441104120102c2204450d072001412036027420012001280278221141046a36027820012004360270200420116a20103600002003200141f0006a108f012001280278210420012802702110200542003703002006420037030020014180016a41086a2211420037030020014200370380012010200420014180016a10002007200529030037030020082006290300370300200141286a41086a2011290300370300200120012903800137032802402001280274450d002001280270102a0b200241206a2102200141286a41201009200b41606a220b0d000b0b02402009450d00200a102a0b200141a0016a24000f0b411a41011037000b413441011037000b411341011037000b412641011037000b411041011037000b412041011037000b801102047f027e230041e0016b22022400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802000e1514000102030405060708090a0b0c0d0e0f10111213140b10a103000b20004102360200200041086a200141086a2903003703000c130b200241e0006a200141046a1070200041033602002000410c6a200241e8006a280200360200200020022903603702040c120b10bb03000b200241e0006a200141086a10ae02200041086a200241e0006a41e000109a051a200041053602000c100b200241e0006a200141086a10bc0320004106360200200041386a200241e0006a41306a290300370300200041306a200241e0006a41286a290300370300200041286a200241e0006a41206a290300370300200041206a200241e0006a41186a290300370300200041186a200241e0006a41106a290300370300200041106a200241e0006a41086a290300370300200041086a20022903603703000c0f0b200241e0006a41186a200141286a290000370300200241e0006a41106a200141206a290000370300200241e8006a200141186a290000370300200241e0006a41286a200141386a290000370300200241e0006a41306a200141c0006a290000370300200241e0006a41386a200141c8006a290000370300200241e0006a41c8006a200141d8006a290000370300200241e0006a41d0006a200141e0006a290000370300200241e0006a41d8006a200141e8006a2900003703002002200141106a2900003703602002200141306a290000370380012002200141d0006a2900003703a0012001410c6a2802002203417f4c0d0f200128020421010240024020030d0041012104410021050c010b20032105200310282204450d110b200420012003109a0521012002200241e0006a41e000109a0521042000410c6a2003360200200041086a200536020020002001360204200041106a200441e000109a051a200041073602000c0e0b200241e0006a200141086a10bd0320004108360200200041306a200241e0006a41286a290300370300200041286a200241e0006a41206a290300370300200041206a200241e0006a41186a290300370300200041186a200241e0006a41106a290300370300200041106a200241e0006a41086a290300370300200041086a20022903603703000c0d0b200241e0006a200141046a10c30320004109360200200041246a20024180016a2903003702002000411c6a200241f8006a290300370200200041146a200241f0006a2903003702002000410c6a200241e8006a290300370200200020022903603702040c0c0b200241e0006a200141046a10c3032000410a360200200041246a20024180016a2903003702002000411c6a200241f8006a290300370200200041146a200241f0006a2903003702002000410c6a200241e8006a290300370200200020022903603702040c0b0b200241e0006a200141086a10d3022000410b360200200041c0006a200241e0006a41386a290300370300200041386a200241e0006a41306a290300370300200041306a200241e0006a41286a290300370300200041286a200241e0006a41206a290300370300200041206a200241e0006a41186a290300370300200041186a200241e0006a41106a290300370300200041106a200241e0006a41086a290300370300200041086a20022903603703000c0a0b200241e0006a200141046a10be03200041046a200241e0006a41c400109a051a2000410c3602000c090b2000410d360200200020012802043602040c080b2001410c6a2802002203417f4c0d08200128020421010240024020030d0041002104410121050c010b20032104200310282205450d0b0b200520012003109a0521012000410c6a2003360200200041086a2004360200200020013602042000410e3602000c070b024002400240024002400240200141086a280200417f6a220341024b0d0020030e03010203010b418486c2001032000b200141386a2903002106200141306a290300210741012103024002402001410c6a2d00004101460d00200241e8006a2001411c6a290200370300200241e0006a41106a200141246a290200370300200241f8006a2001412c6a2d00003a00002002200141146a29020037036020012f000d2001410f6a2d0000411074722104200141106a2802002105410021030c010b200141106a28020021050b200241186a200241e0006a41186a280200360200200241106a200241e0006a41106a290300370300200241086a200241e0006a41086a29030037030020022002290360370300410121010c030b2001410c6a28020022034108762104410221010c010b2001410c6a28020022034108762104410321010b0b2000410f360200200041386a2006370300200041306a2007370300200041106a2005360200200041086a2001360200200041146a20022903003702002000410c6a2004410874200341ff0171723602002000411c6a200241086a290300370200200041246a200241106a2903003702002000412c6a200241186a2802003602000c060b200241e0006a200141086a10bf03200041086a200241e0006a418001109a051a200041103602000c050b200241e0006a200141046a10c003200041113602002000412c6a20024188016a280200360200200041246a20024180016a2903003702002000411c6a200241f8006a290300370200200041146a200241f0006a2903003702002000410c6a200241e8006a290300370200200020022903603702040c040b200241e0006a200141046a10af02200041046a200241e0006a41e400109a051a200041123602000c030b10c103000b10d501000b200241e0006a200141086a10c20320004100360200200041106a200241e0006a41086a290300370300200041086a20022903603703000b200241e0016a24000f0b1036000b200341011037000b200341011037000bfe1a03087f047e037f23004180076b22042400200441c8036a200141a002109a051a200441e8016a200441c8036a10d10341012105024002400240024002400240024020042d00e8014101470d00200020042f00e9013b0001200041013a0000200041036a20042d00eb013a000020032802002106410021000c010b200441106a200441e8016a41086a41d801109a051a0240024002400240024002400240024002400240024020032802002206450d00200341086a28020021072003280204210841002109200441003602c8034188e8c2004110200441c8036a10062101024020042802c8032205417f460d002001450d0020054104490d02200128000021092001102a0b411410282201450d0241002105200141106a41002800eaa046360000200141086a41002900e2a046370000200141002900daa046370000200141144128102c2201450d0320012009360014200441e8016a41186a22094200370300200441e8016a41106a220a4200370300200441e8016a41086a220b4200370300200442003703e80120014118200441e8016a1000200441c0066a41186a2009290300370300200441c0066a41106a200a290300370300200441c0066a41086a200b290300370300200420042903e8013703c0062001102a200441203602cc032004200441c0066a3602c80320062007200441c8036a10cb012008450d002006102a0b200441086a200441106a41d0006a10f3012004280208210720042d000c2108200441c8036a200441106a41d801109a051a4100210120042903e803220c4202510d0c20044198066a41186a200441c8036a41186a29030037030020044198066a41106a200441c8036a41106a29030037030020044198066a41086a200441c8036a41086a290300370300200420042903c8033703980620044188046a290300210d20044180046a290300210e20044190046a280200210920042903f003210f200441e8016a41086a22014200370300200442003703e80141d9efc200410d200441e8016a1008200441c0066a41086a2001290300370300200420042903e8013703c006200441003602e801200441c0066a4110200441e8016a10062101024020042802e801220a417f460d002001450d00200a41034d0d042001102a0b0240200c4201520d00200f4200510d050b411310282201450d05200141002900cef0423700002001410f6a41002800ddf042360000200141086a41002900d6f04237000020044293808080b0023702fc05200420013602f80520044198066a200441f8056a108f01200428028006210120042802f805210a200441e8016a41186a220b4200370300200441e8016a41106a22104200370300200441e8016a41086a22114200370300200442003703e801200a2001200441e8016a1000200441c0066a41186a200b290300370300200441c0066a41106a2010290300370300200441c0066a41086a2011290300370300200420042903e8013703c006024020042802fc05450d0020042802f805102a0b200441003602e801200441c0066a4120200441e8016a1006210a0240024020042802e8012201417f470d00410021010c010b0240200a0d00410021010c010b20014104490d07200a2800002101200a102a0b200441c8036a41d0006a210a024020012009470d00411310282201450d0820084101712108200941016a2109200141002900cef0423700002001410f6a41002800ddf042360000200141086a41002900d6f04237000020044293808080b0023702fc05200420013602f80520044198066a200441f8056a108f01200428028006210120042802f805210b200441e8016a41186a22104200370300200441e8016a41106a22114200370300200441e8016a41086a22124200370300200442003703e801200b2001200441e8016a1000200441c0066a41186a2010290300370300200441c0066a41106a2011290300370300200441c0066a41086a2012290300370300200420042903e8013703c006024020042802fc05450d0020042802f805102a0b200420093602e801200441c0066a4120200441e8016a41041007200441e8016a2008200210b803024020042903e801220ca741ff01714101460d00200441e8016a41086a22014200370300200442003703e80141a8a0c6004117200441e8016a1008200441c0066a41086a22092001290300370300200420042903e8013703c0062004200c4220883e02e801200441c0066a4110200441e8016a41041007200441e8016a2007200810b90320042903e801220ca741ff01714101460d0020014200370300200442003703e801418ea0c600411a200441e8016a100820092001290300370300200420042903e8013703c0062004200c4220883e02e801200441c0066a4110200441e8016a410410070c0a0b200c420888a7220941ff01714104460d09200c421088a721010c0a0b41034102200120094b1b2101410021090c090b41c4d1c3004133200441e8016a419cd9c3001038000b411441011037000b412841011037000b41c4d1c3004133200441e8016a419cd9c3001038000b41fcf8c5001032000b411341011037000b41c4d1c3004133200441e8016a419cd9c3001038000b411341011037000b200441e8016a200e200d20044198066a200720082002109e020240024020042d00e8014101460d0020044194026a280200210920044190026a280200210b2004418c026a280200210720044184026a280200211020044180026a2802002108024020044188026a2802002201450d002001410c6c21022008210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b02402010450d002008102a0b02402009450d002009410c6c21022007210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200b450d012007102a0c010b20042f01ea01210120042d00e9012209417e6a220241024b0d0120020e03000100000b200441e8016a200a10d203024020042d00e8014101460d0020044194026a280200210920044190026a280200210a2004418c026a280200210720044184026a280200210b20044180026a2802002108024020044188026a2802002201450d002001410c6c21022008210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b0240200b450d002008102a0b02402009450d002009410c6c21022007210103400240200141046a280200450d002001280200102a0b2001410c6a2101200241746a22020d000b0b200a450d032007102a0c030b20042f01ea01210120042d00e9012209417e6a220241024b0d0020020e03020002020b200a106a200441f0056a41026a200441f4056a41026a2d00003a0000200420042f00f4053b01f005200041036a20014108763a000020002001410874200941ff0171723b0001200041013a000020054521000b20000d032006450d03200341046a2802000d020c030b200441e0066a41186a20044198066a41186a290300370300200441e0066a41106a20044198066a41106a290300370300200441e0066a41086a20044198066a41086a29030037030020042004290398063703e006410121010b200441f8056a41186a2208200441e0066a41186a2202290300370300200441f8056a41106a220a200441e0066a41106a2209290300370300200441f8056a41086a220b200441e0066a41086a2207290300370300200420042903e0063703f805200441e8016a200441c8036a41d0006a418801109a051a200220082903003703002009200a2903003703002007200b290300370300200420042903f8053703e0064102210802402001450d00200441c0066a41186a2002290300370300200441c0066a41106a2009290300370300200441c0066a41086a2007290300370300200420042903e0063703c006410121080b200441a2066a200441c0066a41086a290300370100200441aa066a200441c0066a41106a290300370100200441b2066a200441c0066a41186a290300370100200420083a009906200420042903c00637019a06200441003a009806200441e0066a200441e8016a20044198066a10f401200441e8016a41026a200441eb066a2d00003a0000200420042f00e9063b01e80120042903e006210c024020042d00e80622014102460d0020044198066a41026a200441e8016a41026a2d00003a0000200420042f01e8013b0198060b200441ec056a41026a220220044198066a41026a2d00003a0000200420042f0198063b01ec05024020014102460d00200441e8016a41026a20022d00003a0000200420042f01ec053b01e8010b200441d4036a20013a0000200441d5036a20042f01e8013b0000200441d7036a200441e8016a41026a2d00003a00002004200c3702cc03200441003a00c8034101210941014100200441c8036a10cc01200441003602c8034188e8c2004110200441c8036a10062102024020042802c8032207417f460d002002450d0020074104490d03200228000021092002102a200941016a21090b200420093602c8034188e8c2004110200441c8036a410410072000410c6a20013a0000200041046a200c3702002000410d6a20042f01ec053b00002000410f6a200441ee056a2d00003a0000200041003a00002006450d012005450d01200341046a280200450d010b2006102a0b20044180076a24000f0b41c4d1c3004133200441e8016a419cd9c3001038000bf41f05017f037e077f017e037f230041a00a6b22022400420221030240024002400240024002400240024002400240024002400240200129036822044202520d00200220014198016a418801109a051a0c010b20024188026a200141dc006a29000037030020024180026a200141d4006a290000370300200241f8016a200141cc006a290000370300200241d0016a41206a200141c4006a290000370300200241d0016a41186a2001413c6a290000370300200241d0016a41106a200141346a290000370300200241d0016a41086a2001412c6a290000370300200220012900243703d00120024190026a41086a20014188016a29030037030020024190026a41106a20014190016a290300370300200220014180016a29030037039002200141f8006a2903002103200129037021052001280204210620012d00002107200241800a6a41026a2208200141036a2d00003a0000200241c8026a41086a2209200141106a290200370300200241c8026a41106a220a200141186a290200370300200241c8026a41186a220b200141206a280200360200200220012f00013b01800a200220012902083703c80202400240024020074101460d00200241e0096a41026a20082d00003a0000200241b0066a41086a2009290300370300200241b0066a41106a200a290300370300200241b0066a41186a200b2d00003a0000200220022f01800a3b01e009200220022903c8023703b0060c010b200241c0076a200641067610fe0120022802c00721070240024020022802c8072006413f7122064b0d00410021080c010b200241e0096a41026a200720064105746a220641026a2d00003a0000200241b8066a2006410f6a290000370300200241c0066a200641176a290000370300200241c8066a2006411f6a2d00003a0000200220062f00003b01e009200220062900073703b00620062800032106410121080b024020022802c407450d002007102a0b20080d00410121070c010b200241c0076a41026a200241e0096a41026a2d00003a0000200241c8026a41086a200241b0066a41086a290300370300200241c8026a41106a200241b0066a41106a290300370300200241c8026a41186a200241b0066a41186a2d00003a0000200220022f01e0093b01c007200220022903b0063703c802410021070b200241c0096a41026a2208200241c0076a41026a2d00003a0000200241a0056a41086a2209200241c8026a41086a290300370300200241a0056a41106a220a200241c8026a41106a290300370300200241a0056a41186a220b200241c8026a41186a2d00003a0000200220022f01c0073b01c009200220022903c8023703a00502402007450d00200041013b0001200041013a0000200041036a41003a000020014198016a106a0c0c0b200241b7026a2009290300370000200241bf026a200a290300370000200241c7026a200b2d00003a0000200220022f01c0093b01a802200220063600ab02200220022903a0053700af02200220082d00003a00aa02200241c0076a20014198016a418801109a051a200241c8086a41106a20024190026a41106a290300370300200241c8086a41086a20024190026a41086a29030037030020022002290390023703c80841002107200241800a6a410010f701200241c0096a41086a2002418b0a6a290000370300200241c0096a41106a200241930a6a290000370300200241d5096a200241800a6a41186a290000370000200220022900830a3703c00920022f01800a210b20022d00820a210c200241800a6a41086a22014200370300200242003703800a41d9efc200410d200241800a6a1008200241e0096a41086a2001290300370300200220022903800a3703e009200241003602800a200241e0096a4110200241800a6a10062101024020022802800a2206417f460d002001450d0020064104490d02200128000021072001102a0b41002106024020044201520d0020054200510d03417f21062007ad220d20032003200d541b220d200d20037d2005827d220d42ffffffff0f560d00200da721060b411010282201450d03200141086a41002900c6f042370000200141002900bef042370000200141104120102c2201450d0420012006360010200241800a6a41186a22074200370300200241800a6a41106a22084200370300200241800a6a41086a22094200370300200242003703800a20014114200241800a6a1000200241e0096a41186a2007290300370300200241e0096a41106a220a2008290300370300200241e0096a41086a2009290300370300200220022903800a3703e0092001102a4101210102400240200241e0096a41204101410041001003417f470d000c010b200241800a6a200610f701200241a0096a41086a2002418b0a6a290000370300200241a0096a41106a200241930a6a290000370300200241a0096a41156a2007290000370000200241e0096a41086a200241c0096a41086a290300370300200a200241c0096a41106a290300370300200241e0096a41156a200241c0096a41156a290000370000200220022900830a3703a009200220022903c0093703e00920022f01800a20022d00820a411074722106410021010b20024180096a41156a2207200241e0096a41156a29000037000020024180096a41106a2208200241e0096a41106a29030037030020024180096a41086a2209200241e0096a41086a290300370300200241e0086a41086a220a200241a0096a41086a290300370300200241e0086a41106a220e200241a0096a41106a290300370300200241e0086a41156a220f200241a0096a41156a290000370000200220022903e00937038009200220022903a0093703e00802402001450d00200241c0076a106a200041036a41003a0000200041800a3b0001200041013a00000c0c0b200241e8046a41156a22012007290000370000200241e8046a41106a22072008290300370300200241e8046a41086a22082009290300370300200241c8046a41086a2209200a290300370300200241c8046a41106a220a200e290300370300200241c8046a41156a220e200f29000037000020022002290380093703e804200220022903e0083703c80420024188056a41106a220f200241c8086a41106a29030037030020024188056a41086a2210200241c8086a41086a290300370300200220022903c80837038805200241b0066a41046a200241c0076a418801109a051a200241a0056a200241b0066a418c01109a051a200241c8026a200241a0056a41046a418801109a051a20024186046a200b200c41107472220b4110763a000020024184046a220c200b3b0100200241e0036a2003370300200241d8036a2005370300200241e8036a220b200229038805370300200241f0036a2010290300370300200241f8036a2210200f29030037030020024187046a20022903e8043700002002418f046a200829030037000020024197046a20072903003700002002419c046a2001290000370000200220043703d003200241a30136028004200241a6046a20064110763a0000200241a4046a220720063b0100200241a7046a20022903c804370000200241af046a2009290300370000200241b7046a200a290300370000200241bc046a200e290000370000410410282201450d05200242043702b406200220013602b006200241c8026a200241b0066a10eb010240024020022903d0034201510d000240024020022802b40620022802b8062201460d0020022802b00621060c010b200141016a22062001490d0c200141017422082006200820064b1b22084100480d0c0240024020010d002008102821060c010b20022802b00620012008102c21060b2006450d09200220083602b406200220063602b00620022802b80621010b2002200141016a3602b806200620016a41003a00000c010b20022903e00320022903d8032203420c882204420120044201561b8021040240024020022802b406220620022802b80622016b4102490d0020022802b00621060c010b200141026a22082001490d0b200641017422012008200120084b1b22014100480d0b0240024020060d002001102821060c010b20022802b00620062001102c21060b2006450d09200220013602b406200220063602b00620022802b80621010b2002200141026a3602b806200620016a2004a741047420037aa7417f6a22014101200141014b1b2201410f2001410f491b723b00000b2010200241b0066a10a0012002200b3602a005200241a0056a200241b0066a10a30120022802800421080240024020022802b406220620022802b80622016b4104490d0020022802b00621060c010b200141046a22092001490d0a200641017422012009200120094b1b22014100480d0a0240024020060d002001102821060c010b20022802b00620062001102c21060b2006450d09200220013602b406200220063602b00620022802b80621010b2002200141046a3602b806200620016a20083600002002200241b0066a3602a005200c200241a0056a10c8012002200241b0066a3602a0052007200241a0056a10c80120022802b006210120022802b40621060240024020022802b80622074180024b0d00200241d0016a20012007200241a8026a10dd0321070c010b200241800a6a41186a22084200370300200241800a6a41106a22094200370300200241800a6a41086a220a4200370300200242003703800a20012007200241800a6a1000200241e0096a41186a2008290300370300200241e0096a41106a2009290300370300200241e0096a41086a200a290300370300200220022903800a3703e009200241d0016a200241e0096a4120200241a8026a10dd0321070b02402006450d002001102a0b2007450d0a200241b0016a41086a200241a8026a41086a290300370300200241b0016a41106a200241a8026a41106a290300370300200241b0016a41186a200241a8026a41186a29030037030020024188016a41086a200241e0036a29030037030020024188016a41106a200241e8036a29030037030020024188016a41186a200241f0036a290300370300200241a8016a200241f8036a290300370300200220022903a8023703b0012002200241d8036a2903003703880120022903d00321032002200241c8026a418801109a051a0b200041086a20022903b001370300200041286a2003370300200041306a200229038801370300200041206a200241b0016a41186a290300370300200041186a200241b0016a41106a290300370300200041106a200241b0016a41086a290300370300200041386a20024188016a41086a290300370300200041c0006a20024188016a41106a290300370300200041c8006a20024188016a41186a290300370300200041d0006a20024188016a41206a290300370300200041d8006a2002418801109a051a200041003a0000200241a00a6a24000f0b41c4d1c3004133200241800a6a419cd9c3001038000b41fcf8c5001032000b411041011037000b412041011037000b410441011037000b200841011037000b200141011037000b200141011037000b1031000b20004180083b0001200041013a0000200041036a41003a0000200241c8026a106a0b200241a00a6a24000be00402037f017e230041306b220224000240024020012802004110460d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b024002400240024002400240200141086a2d00000e06050402010004050b200141c8006a21030c020b200141d0006a21030c010b200141186a21030b200241086a41086a220142003703002002420037030841affec5004111200241086a1008200241206a41086a20012903003703002002200229030837032020024100360208200241206a4110200241086a1006210102400240024020022802082204417f470d004280ade20421050c010b024020010d004280ade20421050c010b20044108490d01200129000021052001102a4280ade20420057d21050b024020032903002005560d00200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c040b200041800c3b0001200041013a0000200041036a41003a00000c030b41c4d1c3004133200241086a419cd9c3001038000b200041003a0000200041306a41013a0000200041286a4200370300200041206a4280808080c000370300200041186a4204370300200041106a427f370300200041086a42003703000c010b2002411c6a41013602002002420137020c200241ccd1c50036020820024104360224200241ccd0c3003602202002200241206a360218200241086a41f0d0c300103e000b200241306a24000ba60201037f412e210241f8f4c50021030240024002402001417e6a22044102200441ff01714102491b41ff01710e03020001020b4130210241c8f4c50021030c010b20014180feff07714108762104024020014101710d00411f210241b4f5c50021030240024002400240024002400240200441ff01710e080006010203040508000b4120210241baf7c50021030c070b4127210241daf6c50021030c060b4117210241c3f6c50021030c050b41a4f6c50021030c040b4126210241fef5c50021030c030b412b210241d3f5c50021030c020b413921024181f7c50021030c010b411f210241daf7c500210302400240200441ff01710e03000102000b41c100210241baf8c50021030c010b41c100210241f9f7c50021030b20002002360204200020033602000b13002000410136020420004188bcc3003602000b3400200041e7bfc30036020420004100360200200041146a4102360200200041106a41f0bfc300360200200041086a42093702000b130020004101360204200041bcc2c3003602000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242dc0b3700000b130020004104360204200041e0c5c3003602000b3400200041beccc30036020420004100360200200041146a4101360200200041106a41d4ccc300360200200041086a42133702000beb050a067f017e017f017e017f017e017f017e017f017e230041206b2202240002400240024020014108490d00200141017641feffffff07712203417f6a220420014f0d022001410d74200173220541117620057322054105742005732206417f2001417f6a677622077122054100200120052001491b6b220520014f0d01200020044105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c37000020052008370000024020032001490d00200321040c030b2006410d7420067322054111762005732205410574200573220620077122054100200120052001491b6b220520014f0d01200020034105746a22042900002108200020054105746a220541086a2209290000210a200541106a220b290000210c200541186a220d290000210e20042005290000370000200441186a220f2900002110200f200e370000200441106a220f290000210e200f200c370000200441086a2204290000210c2004200a370000200d2010370000200b200e3700002009200c370000200520083700002003410172220420014f0d022006410d742006732205411176200573220541057420057320077122054100200120052001491b6b220520014f0d01200020044105746a22012900002108200020054105746a220041086a2205290000210a200041106a2204290000210c200041186a2203290000210e20012000290000370000200141186a220629000021102006200e370000200141106a2206290000210e2006200c370000200141086a2201290000210c2001200a370000200320103700002004200e3700002005200c370000200020083700000b200241206a24000f0b4190cec300200520011034000b4180cec300200420011034000be90609067f017e017f017e017f027e017f017e027f230041206b22022400024020014101762203450d0003402003417f6a2203210402400240024003402004410174220541017221060240200541026a220520014f0d00200620014f0d0220052006200020064105746a200020054105746a4120109c054100481b21060b200620014f0d03200420014f0d02200020044105746a2204200020064105746a22054120109c0541004e0d03200541086a22072900002108200541106a2209290000210a200541186a220b290000210c2004290000210d20042005290000370000200441186a220e290000210f200e200c370000200441106a220e290000210c200e200a370000200441086a2204290000210a20042008370000200b200f3700002009200c3700002007200a3700002005200d370000200621040c000b0b41c8cfc300200620011034000b41d8cfc300200420011034000b20030d000b0b0240024020014102490d002001210703402007417f6a220720014f0d02200241186a2209200041186a2204290000370300200241106a220b200041106a2205290000370300200241086a220e200041086a2203290000370300200020074105746a220641086a2900002108200641106a290000210a200641186a290000210c2000290000210d200020062900003700002004200c3700002005200a370000200320083700002002200d37030041002105024002400240034020062002290300370000200641186a2009290300370000200641106a200b290300370000200641086a200e2903003700002005410174220641017221040240200641026a220620074f0d00200420074f0d0220062004200020044105746a200020064105746a4120109c054100481b21040b200420074f0d03200520074f0d02200020054105746a2205200020044105746a22064120109c0541004e0d032009200541186a2203290000370300200b200541106a2210290000370300200e200541086a2211290000370300200641086a2900002108200641106a290000210a200641186a290000210c2005290000210d200520062900003700002003200c3700002010200a370000201120083700002002200d370300200421050c000b0b41c8cfc300200420071034000b41d8cfc300200520071034000b200741014b0d000b0b200241206a24000f0b4190cec300200720011034000b9009030a7f017e0a7f230041c0006b22022400200041807f6a21032001417f6a2104200141324921054101210641002107024003400240024020062001490d00410021080c010b41012108200020064105746a2209200941606a4120109c054100480d0003404101210a20042006460d03200641016a2106200941206a220a20094120109c052108200a21092008417f4a0d000b200620014921080b2006200146210a20050d0120062001460d01024002400240024002402006417f6a220920014f0d002008450d0120002006410574220b6a220a290000210c200a200020094105746a22092900003700002009200c370000200a41086a220d290000210c200d200941086a22082900003700002008200c370000200a41106a220e290000210c200e200941106a220f290000370000200f200c370000200a41186a2210290000210c2010200941186a22112900003700002011200c37000020064102490d04200920002006417e6a22124105746a22134120109c05417f4a0d042009290000210c20092013290000370000200241206a41186a22142011290000370300200241206a41106a2215200f290000370300200241206a41086a221620082900003703002008201341086a290000370000200f201341106a2900003700002011201341186a2900003700002002200c370320024020120d00410021120c040b200241206a20002006417d6a22084105746a4120109c05417f4a0d032003200b6a21090340200941d8006a200941386a290000370000200941d0006a200941306a290000370000200941c8006a200941286a290000370000200941c0006a200941206a2900003700002008450d032008417f6a2108200241206a20094120109c05210f200941606a2109200f4100480d000b200841016a21120c030b4180cec300200920011034000b4190cec300200620011034000b410021120b200020124105746a22092002290320370000200941186a2014290300370000200941106a2015290300370000200941086a20162903003700000b200741016a21070240200120066b220f4102490d00200a41206a2209200a4120109c05417f4a0d00200a290000210c200a2009290000370000200241206a41186a22112010290000370300200241206a41106a2213200e290000370300200241206a41086a2212200d290000370300200d200941086a290000370000200e200941106a2900003700002010200941186a2900003700002002200c3703204101210d0240200f4103490d00200a41c0006a2209200241206a4120109c05417f4a0d00410321084102210e02400340200e410574200a6a41606a220d2009290000370000200d41186a200941186a290000370000200d41106a200941106a290000370000200d41086a200941086a2900003700002008200f4f0d0120084105742109200e210d2008210e200841016a2108200a20096a2209200241206a4120109c054100480d000c020b0b200e210d0b200a200d4105746a22092002290320370000200941186a2011290300370000200941106a2013290300370000200941086a20122903003700000b20074105470d000b4100210a0b200241c0006a2400200a0b8305010f7f230041a0026b22042400200441c0016a41386a2205200041386a2206290000370300200441c0016a41306a2207200041306a2208290000370300200441c0016a41286a2209200041286a220a290000370300200441c0016a41206a220b200041206a220c290000370300200441c0016a41186a220d200041186a220e290000370300200441c0016a41106a220f200041106a2210290000370300200441c0016a41086a2211200041086a2212290000370300200420002900003703c0010240024020012002200441c0016a2003100a0d00410121000c010b20052006290000370300200720082900003703002009200a290000370300200b200c290000370300200d200e290000370300200f20102900003703002011201229000037030020044188026a2205200341086a29000037030020044190026a2206200341106a29000037030020044198026a2207200341186a290000370300200420002900003703c00120042003290000370380022004200441c0016a41e000109a05220041c0016a200041e000109a051a200041e0006a41386a200041386a290000370300200041e0006a41306a200041306a290000370300200041e0006a41286a200041286a290000370300200041e0006a41206a200041206a290000370300200041e0006a41186a200041186a290000370300200041e0006a41106a200041106a290000370300200041e0006a41086a200041086a29000037030020002000290000370360200041a0016a41186a2007290300370300200041a0016a41106a2006290300370300200041a0016a41086a200529030037030020002000290380023703a00120012002200041e0006a200041a0016a10164521000b200441a0026a240020000bc50101037f230041206b220224002002410036021020014110200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602040c010b200220013602082002200336020c20034104490d0120022003417c6a36020c2002200141046a36020820012800002103200241106a200241086a10820120022802102204450d012000200229021437020820002004360204200020033602002001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000be80201057f230041b0036b22022400200241003602a80220014110200241a8026a1006210302400240024020022802a8022201417f470d00200041133602000c010b20022001360294012002200336029001200241a8026a20024190016a10810120022802a8024113460d01200241a0016a200241a8026a418801109a051a024002402002280294012204450d0020022802900122052d0000210620022004417f6a360294012002200541016a3602900120064103490d010b200241a0016a106a0c020b20022802a00121042002410c6a200241a0016a410472418401109a051a2002200228009901360204200220024199016a41036a28000036000720044113460d0120002004360200200041046a2002410c6a418401109a051a20004188016a20063a000020002002280204360089012000418c016a20022800073600002001450d002003102a0b200241b0036a24000f0b41c4d1c3004133200241a8026a419cd9c3001038000bdb0102027f037e230041206b220224002002410036021020014120200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602100c010b200220013602082002200336020c20034110490d012002200341706a36020c2002200141106a360208200141086a290000210420012900002105200241106a200241086a106d20022802102203450d0120022902142106200020043703082000200537030020002006370214200020033602102001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000bc40101037f230041206b220224002002410036021020014120200241106a10062101024002400240024020022802102203417f460d0020010d010b200041003602040c010b200220013602082002200336020c20034104490d0120022003417c6a36020c2002200141046a36020820012800002103200241106a200241086a106d20022802102204450d012000200229021437020820002004360204200020033602002001102a0b200241206a24000f0b41c4d1c3004133200241106a419cd9c3001038000bd20101037f230041106b22022400200241003602082002420137030020012d00002103410110282104024002400240024020034101460d002004450d02200242818080801037020420022004360200200441003a0000200141086a200210e3030c010b2004450d02200242818080801037020420022004360200200441013a00002002200236020c200141016a2002410c6a10c8010b2002280204210420004120200228020022012002280208100702402004450d002001102a0b200241106a24000f0b410141011037000b410141011037000ba60a02067f027e230041106b2202240020002802102103200041186a2802002204200110b4010240024002400240024002400240024002400240200141046a2802002205200141086a28020022066b2004490d00200128020021050c010b200620046a22072006490d08200541017422062007200620074b1b22064100480d080240024020050d002006102821050c010b200128020020052006102c21050b2005450d0120012005360200200141046a2006360200200141086a28020021060b200141086a2207200620046a360200200520066a20032004109a051a200028021c210502400240200141046a2802002206200728020022046b4104490d00200128020021060c010b200441046a22032004490d08200641017422042003200420034b1b22044100480d080240024020060d002004102821060c010b200128020020062004102c21060b2006450d0220012006360200200141046a2004360200200141086a28020021040b200141086a2203200441046a360200200620046a20053600002002200136020c2000412c6a2002410c6a10c801200041086a29030021082000290300210902400240200141046a2802002206200328020022046b4110490d00200128020021060c010b200441106a22052004490d08200641017422042005200420054b1b22044100480d080240024020060d002004102821060c010b200128020020062004102c21060b2006450d0320012006360200200141046a2004360200200141086a28020021040b200141086a2205200441106a360200200620046a22042008370008200420093700002000280220210302400240200141046a2802002206200528020022046b4104490d00200128020021060c010b200441046a22052004490d08200641017422042005200420054b1b22044100480d080240024020060d002004102821060c010b200128020020062004102c21060b2006450d0420012006360200200141046a2004360200200141086a28020021040b200141086a2205200441046a360200200620046a20033600000240024020002802244101460d0002400240200141046a28020020052802002200460d00200128020021040c010b200041016a22042000490d0a200041017422062004200620044b1b22064100480d0a0240024020000d002006102821040c010b200128020020002006102c21040b2004450d0720012004360200200141046a2006360200200141086a28020021000b200141086a200041016a360200200420006a41003a00000c010b02400240200141046a28020020052802002204460d00200128020021060c010b200441016a22062004490d09200441017422052006200520064b1b22054100480d090240024020040d002005102821060c010b200128020020042005102c21060b2006450d0720012006360200200141046a2005360200200141086a28020021040b200141086a2205200441016a360200200620046a41013a00002000280228210602400240200141046a2802002204200528020022006b4104490d00200128020021040c010b200041046a22052000490d09200441017422002005200020054b1b22004100480d090240024020040d002000102821040c010b200128020020042000102c21040b2004450d0820012004360200200141046a2000360200200141086a28020021000b200141086a200041046a360200200420006a20063600000b200241106a24000f0b200641011037000b200441011037000b200441011037000b200441011037000b200641011037000b200541011037000b200041011037000b1031000b910101047f230041106b2201240041002102200141003602044188e8c2004110200141046a1006210302400240024020012802042204417f470d000c010b024020030d000c010b20044104490d01200328000021042003102a4188e8c20041101009410121020b2000200236020020002004360204200141106a24000f0b41c4d1c3004133200141086a419cd9c3001038000bfb0103017f017e027f230041206b2201240042002102200141106a41086a220342003703002001420037031041affec5004111200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a100621030240024020012802102204417f460d002003450d0020044108490d01200329000021022003102a0b200141106a41086a220342003703002001420037031041affec5004111200141106a1008200141086a2003290300370300200120012903103703002001200220007c37031020014110200141106a41081007200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000b1300200041053602042000418cdac3003602000b3400200041a4d5c30036020420004100360200200041146a4107360200200041106a41e4ecc300360200200041086a42083702000b3701017f02404110102822020d00411041011037000b2002420037000820024201370000200042908080808002370204200020023602000bc70101017f23004190016b22022400200241003a00782002428080848080023703682002420137035820024201370350200242af0137034820024287013703402002420137033820024201370330200242013703282002420137032020024201370318200242013703102002420137030820024280808080c00037036020024280808180800437037020024100360288012002420137038001200241086a20024180016a10ee01200041086a200228028801360200200020022903800137020020024190016a24000b130020004110360204200041c0f6c3003602000b3301017f02404108102822020d00410841011037000b2000428880808080013702042000200236020020024280ade2043700000b3201017f02404104102822020d00410441011037000b20004284808080c000370204200020023602002002418080013600000b3101017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180083600000b3101017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242e8073700000b3c01017f02404110102822020d00411041011037000b2002420037000820024280a094a58d1d370000200042908080808002370204200020023602000b3b01017f02404110102822020d00411041011037000b2002420037000820024280c8afa025370000200042908080808002370204200020023602000b3e01017f02404110102822020d00411041011037000b20024200370008200242808086bdbacdd21a370000200042908080808002370204200020023602000b3f01017f02404110102822020d00411041011037000b200242003700082002428080a8ec85afd1b101370000200042908080808002370204200020023602000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241083600000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241023600000bc81603027f047e117f230041a0096b22072400200741e0006a41186a200141186a290000370300200741e0006a41106a200141106a290000370300200741e0006a41086a200141086a2900003703002007200129000037036020074180016a41186a200241186a29000037030020074180016a41106a200241106a29000037030020074180016a41086a200241086a2900003703002007200229000037038001200628020021012006280204210220062802082108200741d0006a10f6030240024002400240024020072903502209200741d0006a41086a290300220a8450450d004200210b4200210c0c010b200741306a200a420020054200109f05200741c0006a2009420020054200109f05200741206a4200420020094200109f0502402007290338200729032884420052200741c0006a41086a290300220b200729033020072903207c7c220c200b5472450d004127210641a6b5c00021080c020b2007290340210b0b200741c0016a200741e0006a200b200c41081098024101210d20072802c0014101470d0120072802c801210620072802c40121080b2000200836020420004101360200200041146a41003602002000410c6a4201370200200041086a20063602002002450d012001102a0c010b200741c0016a41106a290300210b20072903c801210c200741a0016a41186a220e200a370300200720093703b001200720053703a801200720053703a001200741c0016a10f703200741c0026a4200370300200741f0026a4200370300200741e0026a4200370300200741d0026a42003703002007428080e983b1de163703b80220074280a094a58d1d3703e80220074280a094a58d1d3703d80220074280a094a58d1d3703c802200742808880808080103703f8022007200741c0016a360280032007200741c0016a36028403200741d0056a41186a220f200741e0006a41186a290300370300200741d0056a41106a2206200741e0006a41106a290300370300200741d0056a41086a2210200741e0006a41086a290300370300200720072903603703d00510a00321051098012111200741c0036a4200370300200741b4036a41d0b5c000360200200741b0036a4101360200200741a8036a4200370300200741a4036a41f8b9c000360200200741e0036a2010290300370300200741e8036a2006290300370300200741f0036a200f29030037030020074200370390032007428080808080013703b803200741003602a003200720072903d0053703d803200720074184036a3602d003200720074180036a3602cc032007200741c0016a3602c803200720113602d4032007200537038803200f20074180016a41186a290300370300200620074180016a41106a290300370300201020074180016a41086a29030037030020072007290380013703d005200720083602a804200720023602a404200720013602a004200741f8036a20074188036a200741d0056a20032004200741a0016a200741a0046a10c101024020072802f8030d00200741f8036a41106a2d00000d00200741d0056a41086a200741a8036a290300370300200741a0046a41086a200741dc056a280200360200200720072903a0033703d005200720072902d4053703a00420074198096a200741a0046a1092014100210d0b200720072903b001200e29030020072903a80122054200109f0520072903a00120057d10e503200741106a200741e0006a2007290300200741086a29030010d0012006200b200741106a41086a29030022097d200c2007290310220554ad7d2009200b7d2005200c54ad7d2005200c582009200b582009200b5122021b22011b220a3703002007200c20057d2005200c7d20011b22033703d80520072005200c562009200b5620021b2202ad22053703d00541012101024020020d00200720033703a0042007200a3703a8042007200741a0046a3602e007200741e0076a109d014100210120072903d00521050b0240024020054200520d002001450d01200720103602a004200741a0046a109d010c010b200720103602a004200741a0046a109c010b20072802c403210120072802c0032106200720072802bc032202360298042007200636029404200720023602900420072002200141b0016c6a221236029c0402402001450d00200741e0076a410172211320074187076a2114200741e9076a210820074180076a4102722110200741d0056a41106a2115200741f8056a2116200741b4066a211720074191066a210f200741f1056a210e200741d0056a4101722118200741c8066a2119034020022d00002101200741a0046a200241016a41af01109a051a0240024020014103460d00200720013a00d0052018200741a0046a41af01109a052106024002400240024020010e03000102000b20072802d805211a20072802dc05210620072802d40521012014201541d800109a051a2007410c3a00e007201320074180076a41df00109a051a20012006200741e0076a10cc0141012106410021110240201a450d002001102a0b4100211a0c020b200741e8086a41186a2201200641186a2211290000370300200741e8086a41106a221a200641106a221b290000370300200741e8086a41086a221c200641086a221d290000370300200720062900003703e808200741e0076a2016418801109a051a20102006290000370000201041086a201d290000370000201041106a201b290000370000201041186a201129000037000020074180023b01800720074188096a200741e0076a20074180076a10f40120072d0090092106200820072903e808370000200841086a201c290300370000200841106a201a290300370000200841186a2001290300370000200741043a00e8072007410c3a00e007200720064102463a008908410021064101211141014100200741e0076a10cc014100211a0c010b2019290300210520072903c0062109200741e8086a41186a200641186a290000370300200741e8086a41106a200641106a290000370300200741e8086a41086a200641086a290000370300200720062900003703e80820074180076a41186a200e41186a29000037030020074180076a41106a200e41106a29000037030020074180076a41086a200e41086a2900003703002007200e29000037038007200741e0076a41186a200f41186a290000370300200741e0076a41106a200f41106a290000370300200741e0076a41086a200f41086a2900003703002007200f2900003703e00720074188096a41086a201741086a2802003602002007201729020037038809200741e8086a20074180076a200741e0076a2009200520074188096a10f80341012111410121064101211a0b024020072d00d005220141014b0d000240024020010e020001000b2011450d03024020072802d805450d0020072802d405102a0b20072d00e0054105490d03200728028806450d03200728028406102a0c030b2006450d022016106a0c020b201a20072802b80645720d0120072802b406102a0c010b2007200241b0016a360298040c020b200241b0016a22022012470d000b20072012360298040b20074190046a1069200041106a200741f8036a41106a290300370200200041086a200741f8036a41086a290300370200200020072903f80337020002402007280294032202450d0020074188036a41106a280200450d002002102a0b200d450d0020074188036a411c6a280200210220072802ac0321080240024020072802a80322060d00200221010c010b2006210020022101034020012802880b21012000417f6a22000d000b0340200220022f01064102746a41880b6a28020021022006417f6a22060d000b0b200741d0056a411c6a20022f0106360200200741e8056a4100360200200741e4056a2002360200200720083602f005200741003602e005200742003703d805200720013602d405200741003602d005200741d0056a109b010b200741a0096a24000bc70104017f017e027f017e230041206b2201240042002102200141106a41086a22034200370300200142003703104188d9c3004111200141106a1008200141086a2003290300370300200120012903103703002001410036021020014110200141106a1006210302400240024020012802102204417f470d00420121050c010b20044110490d01200341086a2900002102200329000021052003102a0b2000200537030020002002370308200141206a24000f0b41c4d1c3004133200141106a419cd9c3001038000be20301047f23004190026b2201240020014190016a41086a22024200370300200142003703900141c0fec500411820014190016a100820014180016a41086a2002290300370300200120012903900137038001200141003602900120014180016a411020014190016a100621030240024002402001280290012204417f470d00410221020c010b2001200436028c02200120033602880220014190016a20014188026a10ea0120012d00800222024102460d01200141106a20014190016a41f000109a051a200120014184026a28000036000b20012001280081023602082004450d002003102a0b20014190016a200141106a41f000109a051a2001200128000b3600830120012001280208360280010240024020024102470d002000428080818080043703682000428080848080023703602000420137035020004201370348200042af0137034020004287013703382000420137033020004201370328200042013703202000420137031820004201370310200042013703082000420137030020004280808080c000370358410021020c010b200020014190016a41f000109a05220441f4006a20012800830136000020042001280280013600710b200020023a007020014190026a24000f0b41c4d1c3004133200141106a419cd9c3001038000b891d01117f230041b0036b2206240020064190026a2000108c01410221070240024020062d00900222084102470d00410121094134210a410221080c010b20064190036a41086a2209200641a4026a29020037030020064190036a41106a220b200641ac026a29020037030020064190036a41186a220c200641b4026a290200370300200641e8026a41086a220d200641c8026a290300370300200641e8026a41106a220e200641d0026a290300370300200641e8026a41186a220f200641d8026a290300370300200641e8026a41206a2210200641e0026a29030037030020062006419c026a290200370390032006200641c0026a2903003703e80220064190026a41086a280200210a024020080d00200641bc026a2802002107200641e8016a41186a200c290300370300200641e8016a41106a200b290300370300200641e8016a41086a2009290300370300200641c0016a41086a200d290300370300200641c0016a41106a200e290300370300200641c0016a41186a200f290300370300200641c0016a41206a201029030037030020062006290390033703e801200620062903e8023703c0010b41022108024020074102470d00410121094134210a0c010b200641e8026a41186a200641e8016a41186a290300370300200641e8026a41106a200641e8016a41106a290300370300200641e8026a41086a200641e8016a41086a29030037030020064190026a41086a200641c0016a41086a29030037030020064190026a41106a200641c0016a41106a29030037030020064190026a41186a200641c0016a41186a29030037030020064190026a41206a200641c0016a41206a290300370300200620062903e8013703e802200620062903c0013703900241002109200721080b200641a0016a41086a2207200641e8026a41086a290300370300200641a0016a41106a220b200641e8026a41106a290300370300200641a0016a41186a220c200641e8026a41186a290300370300200641f8006a41086a220d20064190026a41086a290300370300200641f8006a41106a220e20064190026a41106a290300370300200641f8006a41186a220f20064190026a41186a290300370300200641f8006a41206a221020064190026a41206a290300370300200620062903e8023703a00120062006290390023703780240024020090d00200641d0006a22112006290378370300200641346a20072903003702002006413c6a200b290300370200200641c4006a200c290300370200200641d8006a200d290300370300200641e0006a200e290300370300200641e8006a200f290300370300200641f0006a20102903003703002006200a360228200620062903a00137022c2006200836024c41012109109801210d0240024020084101470d002011280200200d460d010b20064190026a2001108c010240024020062d009002220a4102470d00412e210a419d8fc400210b0c010b200641e8016a41026a20062d0093023a0000200641e8026a41086a2209200641a4026a280200360200200620062f0091023b01e80120062006419c026a2902003703e802200641ac026a2802002108200641a8026a28020021070240200a0d0041012109412e210a419d8fc400210b024020080d000c020b2007102a0c010b20064190026a41086a280200210a200628029402210b200641a0016a41026a200641e8016a41026a2d00003a0000200641c0016a41086a2009280200360200200620062f01e8013b01a001200620062903e8023703c001200641b0026a2d0000210c410021090b2006418c026a41026a200641a0016a41026a2d00003a000020064190036a41086a220e200641c0016a41086a280200360200200620062f01a0013b018c02200620062903c0013703900320090d002006418b016a200e280200360000200620062f018c023b01782006200a36007f2006200b36007b2006200629039003370083012006200c3a00970120062008360093012006200736008f0120062006418e026a2d00003a007a200628024c211220062802502113200620052802002211200541086a28020022144105746a3602940320062011360290032006200641286a3602980320064190026a20064190036a106802400240024002400240024002400240024002402006280290020d0041002109200641003602f001200642043703e801410421074100210a0c010b411010282207450d012007200629039002370200200741086a20064190026a41086a220b290300370200200641c0016a41086a20064190036a41086a28020036020020062006290390033703c001200641e8026a200641c0016a10680240024020062802e8020d00410121094101210a0c010b410121084101210a0340200b200641e8026a41086a290300370300200620062903e8023703900202400240200a2008460d00200841016a21090c010b200841016a22092008490d082008410174220a2009200a20094b1b220a41ffffffff0071200a470d08200a410474220c4100480d080240024020080d00200c102821070c010b20072008410474200c102c21070b2007450d050b200720084104746a2208200629039002370200200841086a200b290300370200200641e8026a200641c0016a10682009210820062802e8020d000b0b200620093602f0012006200a3602ec01200620073602e8010b200641286a41186a28020021082006280238210b2006410036029002200b200820064190026a100d2110200628029002220f417f460d02200641e8026a41186a200241186a290000370300200641e8026a41106a200241106a290000370300200641e8026a41086a200241086a290000370300200620022900003703e802200641003602980320064201370390032010200f20064190036a10b20202400240200628029403220e200628029803220c6b4120490d00200c41206a210b20062802900321080c010b200c41206a220b200c490d05200e4101742208200b2008200b4b1b22154100480d0502400240200e0d002015102821080c010b200628029003200e2015102c21080b2008450d04200620153602940320062008360290032015210e0b2006200b360298032008200c6a220c20062903e802370000200c41086a200641e8026a41086a290300370000200c41106a200641e8026a41106a290300370000200c41186a200641e8026a41186a29030037000020064190026a41186a220c420037030020064190026a41106a2215420037030020064190026a41086a2216420037030020064200370390022008200b20064190026a1000200641c0016a41186a200c290300370300200641c0016a41106a2015290300370300200641c0016a41086a201629030037030020062006290390023703c0010240200e450d002008102a0b0240200f450d002010102a0b0240200641c0016a200641f8006a4120109c050d000240024020090d004100210b0c010b2009410474210c2007410c6a21084100210b03402008280200200b6a210b200841106a2108200c41706a220c0d000b0b20062006280244200b6b360244411710282208450d06200d201320141b210f4101201220141b2110200641286a41106a210b200841002900f1d8433700002008410f6a4100290080d943370000200841086a41002900f9d84337000020064297808080f002370294032006200836029003200020064190036a108f012006280298032115200628029003211620064190026a41186a2208420037030020064190026a41106a220c420037030020064190026a41086a220e420037030020064200370390022016201520064190026a1000200641e8026a41186a2008290300370300200641e8026a41106a200c290300370300200641e8026a41086a200e29030037030020062006290390023703e8020240200628029403450d00200628029003102a0b200641e8026a41201009200c2004370300200641c0026a200f360200200641bc026a2010360200200641b8026a200d360200200641b4026a20062802443602002008200b29030037030020064190026a41206a200b41086a280200360200200641c4026a2002290000370200200641cc026a200241086a290000370200200641d4026a200241106a290000370200200641dc026a200241186a2900003702002006200337039802200641003a009002200120064190026a109a01200641186a2000109101200641186a41086a29030021032006290318210420064190026a200042004200109401024002402006290390024200520d002006200e3602e802200641e8026a109c010c010b2006200e3602e802200641e8026a109d010b200641086a20012004200310d0012006200641106a290300370398022006200629030837039002200620064190026a3602e802200641e8026a109c0102402009450d0020094104742109200741046a210803400240200841046a280200450d002008280200102a0b200841106a2108200941706a22090d000b0b0240200a450d002007102a0b200541046a280200450d0b2011102a0c0b0b200720094104746a2101200721082009450d0620072108034002402008280200220b0d00200841106a21080c080b200841046a2802002109200841086a28020021002008410c6a280200210c200628024021022006280238210d20064190026a41186a220e420037030020064190026a41106a220f420037030020064190026a41086a221042003703002006420037039002200b412020064190026a1000200641e8026a41186a200e290300370300200641e8026a41106a200f290300370300200641e8026a41086a201029030037030020062006290390023703e802200d2002200641e8026a41202009200c100502402000450d002009102a0b200841106a22082001470d000c080b0b411041041037000b200c41041037000b41eef3c50041381050000b201541011037000b1031000b411741011037000b20082001460d0003402008280200450d010240200841086a280200450d00200841046a280200102a0b200841106a22082001470d000b0b200a450d002007102a0b2006413c6a280200450d002006280238102a0b200541046a280200450d002005280200102a0b200641b0036a24000bf46504177f017e077f017e23004180036b2204240041002105200441003602f002200420023602ec02200420013602e8020240024002400240024002400240200241034b0d0041012106200441013a00d002200441ec016a4101360200200442013702dc01200441a4e2c5003602d801200441263602c4022004200441c0026a3602e8012004200441d0026a3602c00220044180016a200441d8016a10332004280280012107200428028401210820042802880121094105210a4100210b0c010b200441043602f002024020012800004180c2cdeb06460d004101210a410121060c010b024002402002417c714104460d00200241074b0d0141082002103c000b41012106200441013a00d002200441ec016a4101360200200442013702dc01200441a4e2c5003602d801200441263602c4022004200441c0026a3602e8012004200441d0026a3602c00220044180016a200441d8016a10332004280280012107200428028401210820042802880121094105210a410021054100210b0c010b200441083602f002410121060240200128000422074101460d004102210a0c010b200441d8016a200441e8026a10fa0402400240024020042802d8014101470d00410421084100210c410021090c010b200441d8016a410572210d41042108412c210a410021054100210c410021094100210b02400340200441d0026a41026a2201200d41026a2d00003a00002004200d2f00003b01d002200428028802210e200428028402210f200428028002211020042802fc01211120042802f801211220042802f401211320042802f001211420042802ec01211520042802e801211620042802e401211720042802e0012118024020042d00dc012206417e6a41ff0171410b4b0d0041002119024002400240024002400240024002400240024002400240024020060e100c0c000102030405060708090a0b0c0c0c0b410121190c0b0b410221190c0a0b410321190c090b410421190c080b410521190c070b410621190c060b410721190c050b410821190c040b410921190c030b410a21190c020b410b21190c010b410c21190b0240200b41ff0171221a20194d0d004113210a0c030b41002119024002400240024002400240024002400240024002400240024020060e100c0c000102030405060708090a0b0c0c0c0b410121190c0b0b410221190c0a0b410321190c090b410421190c080b410521190c070b410621190c060b410721190c050b410821190c040b410921190c030b410a21190c020b410b21190c010b410c21190b0240201a2019470d004114210a0c030b4100210b02400240024002400240024002400240024002400240024020060e100c0c000102030405060708090a0b0c0c0c0b4101210b0c0b0b4102210b0c0a0b4103210b0c090b4104210b0c080b4105210b0c070b4106210b0c060b4107210b0c050b4108210b0c040b4109210b0c030b410a210b0c020b410b210b0c010b410c210b0b20044180016a41026a221920012d00003a0000200420042f01d0023b01800102400240200c2009470d00200c41016a2201200c490d0720052001200520014b1b2209ad42307e221b422088a70d07201ba722014100480d0702400240200c0d002001102821080c010b2008200a41546a2001102c21080b2008450d010b2008200a6a220141546a20063a00002001200e3602002001417c6a200f360200200141786a2010360200200141746a2011360200200141706a20123602002001416c6a2013360200200141686a2014360200200141646a2015360200200141606a20163602002001415c6a2017360200200141586a2018360200200141556a220120042f0180013b0000200141026a20192d00003a0000200541026a2105200a41306a210a200c41016a210c200441d8016a200441e8026a10fa0420042802d8014101460d030c010b0b200141041037000b024002402006410e4b0d00024002400240024002400240024002400240024002400240024020060e0f0001020304050607080e090e0a0b0c000b2017450d0d2018102a0c0d0b02402017450d002018102a0b2014450d0c2015102a0c0c0b02402016450d00201641047421062018210103400240200141046a280200450d002001280200102a0b200141106a2101200641706a22060d000b0b2017450d0b2018102a0c0b0b02402016450d00201641286c21062018210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200641586a22060d000b0b2017450d0a2018102a0c0a0b2017450d092018102a0c090b2017450d082018102a0c080b2017450d072018102a0c070b02402016450d00201820164104746a2114201821160340024020162802082206450d0020162802002101200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641106a21010240201641046a280200450d002016280200102a0b2001211620012014470d000b0b2017450d062018102a0c060b02402016450d00201641146c21062018210103400240200141046a280200450d002001280200102a0b200141146a21012006416c6a22060d000b0b2017450d052018102a0c050b02402016450d0020182016411c6c6a2114201821160340024020162802042201450d0002402016410c6a2802002206450d00200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641086a280200450d002016280204102a0b2016411c6a21010240201641146a280200450d002016280210102a0b2001211620012014470d000b0b2017450d042018102a0c040b02402016450d002018201641186c6a21142018211603400240201641046a280200450d002016280200102a0b0240201641146a2802002206450d00201628020c2101200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641186a21010240201641106a280200450d00201628020c102a0b2001211620012014470d000b0b2017450d032018102a0c030b02402016450d0020182016411c6c6a2114201821160340024020162802042201450d0002402016410c6a2802002206450d00200641047421060340024020012d00004109470d000240200141046a220d280200220528020441ffffffff0371450d002005280200102a200d28020021050b2005102a0b200141106a2101200641706a22060d000b0b201641086a280200450d002016280204102a0b2016411c6a21010240201641146a280200450d002016280210102a0b2001211620012014470d000b0b2017450d022018102a0c020b02402018450d002017450d002018102a0b02402014450d0002402012450d002012410c6c2106201421010340024020012802002205450d00200141046a280200450d002005102a0b2001410c6a2101200641746a22060d000b0b2013450d002014102a0b2010450d010240200e450d002010200e4104746a21172010211803402018220d41106a21180240200d2802042201450d000240200d410c6a2802002206450d002006410c6c21060340024020012802002205450d00200141046a280200450d002005102a0b2001410c6a2101200641746a22060d000b0b200d41086a280200450d00200d280204102a0b20182017470d000b0b200f450d012010102a0c010b02402017450d002018102a0b02402014450d002013450d002014102a0b2010450d002011102a0b0c010b024020042d00dc010d002008200c41306c6a21062008210102400340024020062001470d004100210d0c020b20012d0000210a200141306a220b2101200a410c470d000b200b415c6a280200210d0b2008200c41306c6a210b20082101024003404100210a0240200b2001470d00410021010c020b20012d00002106200141306a2205210120064104470d000b200441f8006a200541546a10fa03200428027c21010b0240200d2001470d004101210741e100210b41f3da012105410021060c030b0240200c450d00200c41306c210a2008210103402001108204200141306a2101200a41506a220a0d000b0b41012106411a210a024020090d000c030b2008102a0c020b20042802dc01220a4110762105200a410876210b200441d8016a41106a280200210d200441e4016a2802002118200441d8016a41086a28020021070b0240200c450d00200c41306c21062008210103402001108204200141306a2101200641506a22060d000b0b4101210602402009450d002008102a0b200d2109201821080b02402006450d00200821060c040b20042802f0022002470d022005411074200b41ff017141087472200a41ff017172211c2008200c41306c6a210a200821010240024002400240024002400240024002400240024002400340200a2001460d0120012d00002102200141306a2206210120024102470d000b200441f0006a200641546a10fa034104211d02402004280274221e0d004100211e0c020b201e41047422014100480d0c2004280270210220011028221d450d0a201e410474210641002115201d21010340200241086a280200220a417f4c0d042002410c6a2d0000210b2002280200210502400240200a0d004101210d0c010b200a1028220d450d060b200d2005200a109a0521052001410d6a2002410d6a2d00003a00002001410c6a200b3a0000200141086a200a360200200141046a200a36020020012005360200200141106a2101201541016a2115200241106a2102200641706a22060d000b201d0d020b4100211e4104211d0b410021150b2008200c41306c6a210a2008210102400340410021174104210b0240200a2001470d0041042102410021010c020b20012d00002102200141306a2206210120024103470d000b200441e8006a200641546a10fa0341042102410021012004280268220a450d00200428026c2101200a21020b024020010d004101211a41002102410021184100210541002110410121124100210a4100211141042116410021064100211f410421134100210e0c090b200141286c210d2002411c6a21014104210b410021174101211a41002102410021184100210541002110410121124100210a4100211141042116410021064100211f410421134100210e0340024002400240024002402001417c6a2d00000e0400010203000b20012802002114024020022018470d00200241016a22182002490d0f2002410174220f2018200f20184b1b221841ffffffff03712018470d0f2018410274220f4100480d0f0240024020020d00200f1028210b0c010b200b2002410274200f102c210b0b200b450d080b200b20024102746a2014360200200241016a21020c030b200441d8016a41086a2214200141086a280200360200200420012902003703d8010240200a2011470d00200a41016a2211200a490d0e200a410174220f2011200f20114b1b2211ad420c7e221b422088a70d0e201ba7220f4100480d0e02400240200a0d00200f102821160c010b2016200a410c6c200f102c21160b2016450d080b2016200a410c6c6a220f20042903d801370200200f41086a2014280200360200200a41016a210a0c020b200441d8016a41086a2214200141086a280200360200200420012902003703d80102402006201f470d00200641016a220f2006490d0d20064101742219200f2019200f4b1b221fad420c7e221b422088a70d0d201ba7220f4100480d0d0240024020060d00200f102821130c010b20132006410c6c200f102c21130b2013450d080b20132006410c6c6a220f20042903d801370200200f41086a2014280200360200200641016a21060c010b2001417e6a22142d0000210f2001417d6a22192d00002120024020052010470d00200541016a22102005490d0c200541017422212010202120104b1b221020106a22222010490d0c20224100480d0c0240024020050d002022102821120c010b201220212022102c21120b2012450d080b201220054101746a2222200f4101713a0001202220203a000020142d0000211420192d0000210f02400240200e2017460d00200e21190c010b201741016a22192017490d0c201741017422222019202220194b1b222020206a22192020490d0c20194100480d0c0240024020170d0020191028211a0c010b201a20222019102c211a0b201a450d0920172119202021170b200541016a2105201a20194101746a221920144101713a00012019200f3a0000200e41016a210e0b200141286a2101200d41586a220d450d090c000b0b1036000b200a41011037000b200f41041037000b200f41041037000b200f41041037000b202241011037000b201941011037000b200141041037000b2008200c41306c6a21142008210102400240024002400240024002400240024002400240024002400240034020142001460d0120012d0000210d200141306a220f2101200d4104470d000b200441e0006a200f41546a10fa0320042802642201450d002004280260210d2001410274210f20024101742114200241027421010340200d2802002119024020022018470d00200241016a22182002490d1020142018201420184b1b221841ffffffff03712018470d10201841027422204100480d100240024020020d0020201028210b0c010b200b20012020102c210b0b200b450d030b200d41046a210d200b20016a2019360200201441026a2114200141046a2101200241016a2102200f417c6a220f0d000b0b2008200c41306c6a21142008210102400240034020142001460d0120012d0000210d200141306a220f2101200d4105470d000b200441d8006a200f41546a10fa03200428025c410c6c2219450d0020042802582101200a4101742114200a410c6c210d0340200141086a210f024002400240200141046a2802004101470d002004200f28020022203602c0022001280200222220204b0d010b20044100360280010c010b200441023602ec01200442023702dc01200441e8a7c6003602d801200441013602f402200441013602ec02200420223602d0022004200441e8026a3602e8012004200441d0026a3602f0022004200441c0026a3602e80220044180016a200441d8016a1033200428028001450d0020044180016a21010c0e0b2001290200211b200441d8016a41086a2220200f2802003602002004201b3703d8010240200a2011470d00200a41016a2211200a490d1120142011201420114b1b2211ad420c7e221b422088a70d11201ba7220f4100480d1102400240200a0d00200f102821160c010b2016200d200f102c21160b2016450d030b2001410c6a21012016200d6a220f20042903d801370200200f41086a2020280200360200201441026a2114200d410c6a210d200a41016a210a201941746a22190d000b0b2008200c41306c6a21142008210102400240034020142001460d0120012d0000210d200141306a220f2101200d4106470d000b200441d0006a200f41546a10fa032004280254220d450d0020042802502101200d410c6c210f200641017421142006410c6c210d0340200441d8016a2001108305024020042802d801450d00200441d8016a21010c0f0b2001290200211b200441d8016a41086a2219200141086a2802003602002004201b3703d80102402006201f470d00200641016a221f2006490d122014201f2014201f4b1b221fad420c7e221b422088a70d12201ba722204100480d120240024020060d002020102821130c010b2013200d2020102c21130b2013450d030b2001410c6a21012013200d6a222020042903d801370200202041086a2019280200360200201441026a2114200d410c6a210d200641016a2106200f41746a220f0d000b0b2008200c41306c6a21142008210102400240034020142001460d0120012d0000210d200141306a220f2101200d4107470d000b200441c8006a200f41546a10fa03200428024c220d450d0020042802482201200d4104746a21222005410174210d200441d8016a41047221200340200441d8016a2001201a200e10840502400240024020042d00d8014101460d00200420042d00d90122143a00c002024020142001410c6a2d0000220f470d0020044100360280010c030b200441023602ec01200442023702dc01200441fca8c6003602d801200441273602f402200441273602ec022004200f3a00d0022004200441e8026a3602e8012004200441c0026a3602f0022004200441d0026a3602e80220044180016a200441d8016a10330c010b20044180016a41086a202041086a28020036020020042020290200370380010b0240200428028001450d0020044180016a21010c110b2001410c6a2d000021140b2001410d6a2d0000210f024020052010470d00200541016a22102005490d13200d2010200d20104b1b221020106a22192010490d1320194100480d130240024020050d002019102821120c010b2012200d2019102c21120b2012450d030b2012200d6a221920143a0000201941016a200f4101713a0000200d41026a210d200541016a2105200141106a22012022470d000b0b200441b8016a2002360200200441b4016a2018360200200441ac016a2015360200200441a8016a201e360200200441a0016a20053602002004419c016a201036020020044194016a200a36020020044190016a20113602002004200b3602b0012004201d3602a40120042012360298012004201636028c0120042006360288012004201f3602840120042013360280012008200c41306c6a210a20082101024003400240200a2001470d004100210b0c020b20012d00002102200141306a2206210120024104470d000b200441c0006a200641546a10fa032004280244210b0b2004200b3602bc012008200c41306c6a210a20082101024003400240200a2001470d00410021010c020b20012d00002102200141306a220621012002410c470d000b2006415c6a28020021010b200420013602c001200b2001470d0a024002400240200b450d002008200c41306c6a210a200821010340200a2001460d0320012d00002102200141306a2206210120024104470d000b2008200c41306c6a210b200821010340200b2001460d0220012d00002102200141306a220a21012002410c470d000b200441386a200641546a10fa03200428023c2201450d002004280238220d20014102746a2114200a415c6a2118200a41546a211620044191026a210f410021050340200420053602c4012018280200210120162802002102200442013702dc012004418487c6003602d801200441013602d402200441013602ec012004200441d0026a3602e8012004200441c4016a3602d002200441e8026a200441d8016a103320042802e802210a20042902ec02211b200120054d0d100240201ba7450d00200a102a0b2004200d28020022013602c002024002400240024020042802ac0120014b0d00200441013602ec01200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a103320042902ec02221b422088a7210120042802e8022106201ba721020c010b0240024002402002200541186c6a22022802142215450d0020042802a40120014104746a220a2d000d2110200a2802002111200228020c210120022802002113200a2802082212210602402002280208220e450d00200e410374210b201221022013210a034002402002200a2802006a220620024f0d0002404120102822060d00412041011037000b200641186a41002900e8ae46370000200641106a41002900e0ae46370000200641086a41002900d8ae46370000200641002900d0ae463700000c040b200a41086a210a20062102200b41786a220b0d000b0b0240410810282202450d0020022010ad42ff0183422886370200200441d0026a41026a220a200441e8026a41026a2d00003a0000200420042f00e8023b01d002200420103a00900220044180800136028c022004428180808010370284022004200236028002200442808080808080103703f801200442013703f001200420063602ec012004200e3602e801200420133602e401200420123602e001200420113602dc01200420044180016a3602d801200f20042f01d0023b0000200f41026a200a2d00003a00002015410474210a41002102034020042002360298022004200136029c02200441b0026a200441d8016a2001108505024020042802b002450d00200441c0026a41086a200441b0026a41086a280200360200200420042903b0023703c002200441033602e402200442033702d402200441e881c6003602d002200441283602fc02200441013602f402200441293602ec022004200441e8026a3602e0022004200441c0026a3602f802200420044198026a3602f00220042004419c026a3602e802200441a0026a200441d0026a1033024020042802c402450d0020042802c002102a0b20042802a0022206450d0020042902a402211b024020042802f401450d0020042802f001102a0b201b42208821230240200428028402450d00200428028002102a0b2023a72101201ba721020c070b200141106a2101200241016a2102200a41706a220a0d000b02402004280288020d00024020042802f401450d0020042802f001102a0b200428028402450d07200428028002102a0c070b418082c6001032000b410841041037000b412010282206450d01200641186a41002900df8146370000200641106a41002900d78146370000200641086a41002900cf8146370000200641002900c781463700000b41202102412021010c010b412041011037000b2006450d010b200420063602d00220042001ad4220862002ad843702d4022004200441d0026a3602c002200441023602ec01200442023702dc012004418c87c6003602d8012004412a3602f402200441013602ec022004200441e8026a3602e8012004200441c0026a3602f0022004200441c4016a3602e802200441c8016a200441d8016a1033024020042802d402450d0020042802d002102a0b20042802c801220a450d0020042902cc01211b0c110b200541016a2105200d41046a220d2014470d000b0b2008200c41306c6a210a200821010240024002400340200a2001460d0120012d00002102200141306a2206210120024109470d000b2004200641546a28020022013602b002024020042802b80120014b0d00200441ec016a4101360200200442023702dc01200441e4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c0c0b200420042802b00120014102746a28020022013602c002024020042802ac0120014b0d00200441ec016a4101360200200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0c0b20042802a40120014104746a220131000d4220862001350208844280808080c000510d00412d1028220a450d01200a41256a41002900c18746370000200a41206a41002900bc8746370000200a41186a41002900b48746370000200a41106a41002900ac8746370000200a41086a41002900a48746370000200a410029009c874637000042ad808080d005211b0c110b2008200c41306c6a210a200821010340200a2001460d0a20012d00002102200141306a2206210120024108470d000b200441306a200641546a221610fa03200428023021014100210a02400240200428023422020d004104210b410021180c010b200241ffffffff01712002470d15200241037422064100480d1520061028220b450d02200221180b02402002450d002001200241146c6a21062002410274417c6a2105200b210203402001280200210a200241046a200141086a2802003602002002200a360200200241086a2102200141146a22012006470d000b200541027641016a210a0b200b200a200441d8016a41004120200a676b10fd04200b200a4103746a2206200b460d084101210a200b2101200b2102034002400240200a450d00200620016b410376200a4d0d0b2001200a4103746a22010d010c0b0b20062001460d0a0b200420023602c00202400240200241046a280200220a200141046a280200470d00200228020022052001280200220d460d012005200d200a109c05450d010b200141086a21014100210a200241086a22022006470d010c0a0b0b200441ec016a4101360200200442013702dc01200441cc87c6003602d8012004412b3602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0c0b412d41011037000b200641041037000b41ba86c60041c8001050000b419c86c600411e1050000b201941011037000b202041041037000b200f41041037000b202041041037000b200441286a201610fa030240200428022c2201450d00200141146c2102200428022841106a210102400340024002400240024002402001417c6a2802000e0400030201000b20042001280200220a3602b002024020042802b801200a4b0d00200441ec016a4101360200200442023702dc01200441e4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c0b0b200420042802b001200a4102746a280200220a3602c00220042802ac01200a4b0d03200441013602ec01200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0a0b20042001280200220a3602b002024020042802a001200a4b0d00200441ec016a4101360200200442023702dc01200441a8acc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c0a0b200428029801200a4101746a2d0001450d02200441ec016a4101360200200442023702dc01200441c8acc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c090b20042001280200220a3602c002200428028801200a4b0d01200441013602ec01200442023702dc0120044194abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a103320042802e802220a0d090c010b20042001280200220a3602c002200428029401200a4d0d020b200141146a21012002416c6a22020d000c020b0b200441ec016a4101360200200442023702dc01200441c4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c040b2018450d00200b102a0b2008200c41306c6a210a2008210102400340200a2001460d0120012d00002102200141306a2206210120024103470d000b200441206a200641546a10fa0320042802242201450d0020042802202106200141286c210b41002101034002400240024002400240200620016a220241186a2d00000e0400030201000b20042002411c6a28020022023602c00220042802ac0120024b0d03200441ec016a4101360200200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c060b2002411a6a2d0000450d022002410c6a2802002101200241146a2802002102200441d8016a41146a4101360200200420023602d402200420013602d002200441043602c402200442013702dc01200441d487c6003602d8012004200441d0026a3602c0022004200441c0026a3602e801200441e8026a200441d8016a10330c050b200441d8016a2002411c6a10830520042802d801220a450d0120042902dc01211b0c0a0b200241206a2802004101470d002002411c6a280200210a2004200241246a28020022023602b002200a20024d0d00200441023602ec01200442023702dc01200441e8a7c6003602d801200441013602f402200441013602ec022004200a3602c0022004200441e8026a3602e8012004200441c0026a3602f0022004200441b0026a3602e802200441d0026a200441d8016a103320042802d002220a0d080b200b200141286a2201470d000b0b02400240024002400240200428029401220141014b0d00200428028801220141014b0d012008200c41306c6a210a200821010240024002400240024002400340200a2001460d0120012d00002102200141306a220621012002410d470d000b200441186a200641546a10fa0320042802182201200428021c411c6c6a2106034020012006460d012004200128020022023602c002024020042802880120024b0d00200441013602ec01200442023702dc0120044194abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a103320042802e802220a450d0020042902ec02211b0c130b200141046a2201280200450d02200441d8016a200120042802980120042802a00110840520042d00d8014101460d03200141186a210120042d00d901450d000b41201028220a450d08200a41186a41002900848846370000200a41106a41002900fc8746370000200a41086a41002900f48746370000200a41002900ec874637000042a08080808004211b0c110b2008200c41306c6a210a2008210102400340200a2001460d0120012d00002102200141306a220621012002410a470d000b200441106a200641546a10fa0320042802142201450d002004280210220b2001411c6c6a21050340200b450d012004200b28020022013602c00220042802940120014d0d04200b280204450d05200441d8016a200b41046a20042802980120042802a00110840520042d00d8014101460d0620042d00d9010d0d200441086a200b10cd0402400240200428020c2201450d00200428020821022001410274210a20042802b801210603402004200228020022013602b0020240200620014b0d00200441ec016a4101360200200442023702dc01200441e4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441b0026a3602d002200441e8026a200441d8016a10330c100b200420042802b00120014102746a28020022013602c00220042802ac0120014d0d02200241046a2102200a417c6a220a0d000b0b200b411c6a220b2005460d020c010b0b200441013602ec01200442023702dc0120044188acc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c0b0b0240200428028401450d00200428028001102a0b0240200428029001450d00200428028c01102a0b0240200428029c01450d00200428029801102a0b024020042802ac012202450d0020042802a40121012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b024020042802a801450d0020042802a401102a0b024020042802b401450d0020042802b001102a0b2017450d13201a102a0c130b41291028220a450d07200a41286a41002d00b488463a0000200a41206a41002900ac8846370000200a41186a41002900a48846370000200a41106a410029009c8846370000200a41086a41002900948846370000200a410029008c884637000042a98080809005211b0c0f0b200441e0016a290300211b20042802dc01210a0c0e0b200441ec016a4101360200200442023702dc01200441c4abc6003602d801200441013602d4022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c070b412a1028220a450d05200a41286a41002f00dd88463b0000200a41206a41002900d58846370000200a41186a41002900cd8846370000200a41106a41002900c58846370000200a41086a41002900bd8846370000200a41002900b5884637000042aa808080a005211b0c0c0b200441e0016a290300211b20042802dc01210a0c0b0b200441ec016a4101360200200442013702dc01200441dc87c6003602d801200441013602d402200420013602c0022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c040b200441ec016a4101360200200442013702dc01200441e487c6003602d801200441013602d402200420013602c0022004200441d0026a3602e8012004200441c0026a3602d002200441e8026a200441d8016a10330c030b412041011037000b412941011037000b412a41011037000b20042802e802210a20042902ec02211b0c050b024041201028220a450d00200a41186a41002900848846370000200a41106a41002900fc8746370000200a41086a41002900f48746370000200a41002900ec874637000042a08080808004211b0c050b412041011037000b20042802e802210a0b20042902ec02211b2018450d02200b102a0c020b200441ec016a4102360200200441f4026a4101360200200442023702dc012004418c86c6003602d801200441013602ec022004200441e8026a3602e8012004200441c0016a3602f0022004200441bc016a3602e802200441d0026a200441d8016a103320042802d002210a0b20042902d402211b0b0240200428028401450d00200428028001102a0b0240200428029001450d00200428028c01102a0b0240200428029c01450d00200428029801102a0b024020042802ac012202450d0020042802a40121012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b024020042802a801450d0020042802a401102a0b024020042802b401450d0020042802b001102a0b2017450d01201a102a200a0d040c020b2001290204211b2001280200210a02402017450d00201a102a0b0240201f450d002013102a0b02402011450d002016102a0b02402010450d002012102a0b02402015450d0020154104742102201d210103400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b0240201e450d00201d102a0b2018450d00200b102a0b200a0d020b2000201c36020420004100360200200041186a2003360200200041146a200c360200200041106a20093602002000410c6a2008360200200041086a20073602000c040b1031000b0240201ba7450d00200a102a0b200041ea8ac60036020420004101360200200041086a41133602000240200c450d00200c41306c21022008210103402001108204200141306a2101200241506a22020d000b0b2009450d022008102a0c020b200441003a00d002200441ec016a4101360200200442013702dc01200441a4e2c5003602d801200441263602c4022004200441c0026a3602e8012004200441d0026a3602c00220044180016a200441d8016a1033200428028001210720042802840121060240200c450d00200c41306c21022008210103402001108204200141306a2101200241506a22020d000b0b4105210a2009450d002008102a0b02402006450d00200a41ff01714105470d002007102a0b200041d48ac60036020420004101360200200041086a41163602000b20044180036a24000b160020002001280208360204200020012802003602000bd21301177f23004190026b220224000240024002400240024002402000280200220341f8b9c000460d00200028020421040c010b41002104200241b8016a410041d8001099051a2002411f6a220542003700002002420037011a41ec0010282203450d0120034100360200200320022902183702042003410b6a2005290000370000200341136a200241b7016a41d900109a051a20004100360204200020033602000b200141ff0171210602400340200341066a210720032f01062108410c21094100210502400240034020082005460d01200320056a210a200941086a2109200541016a210502404100417f4101200a41086a2d0000220a20064b1b200a2006461b41016a0e03000301000b0b2005417f6a21080b2004450d022004417f6a2104200320084102746a41ec006a28020021030c010b0b200320096a42013702000c030b2000200028020841016a360208024002400240024020072f01002205410b490d00200241276a41016a410041d8001099051a200241003a001941ec001028220b450d03200b4100360200200b410036000f200b4200370007200b20022f01183b0005200b41136a200241276a41d900109a051a2003410e6a2d0000210c2003280248210d2003280244210e200b41086a2003410f6a20032f010641796a2205109a052109200b41146a200341cc006a2005410374109a052106200341063b0106200b20053b010620084107490d0120092008417a6a220a6a2009200841796a22086a2209200541ffff037120086b109b051a200920013a00002006200a4103746a200620084103746a2205200b41066a22072f010020086b410374109b051a2005410136020020072f010021050c020b200341086a2209200841016a22066a200920086a2209200520086b220a109b051a200920013a0000200341146a220920064103746a200920084103746a2209200a410374109b051a200941013602002003200541016a3b01060c050b200341086a2205200841016a22096a200520086a220620072f0100220520086b220a109b051a200620013a0000200341146a220620094103746a200620084103746a2209200a410374109b051a200941013602000b2007200541016a3b01002003280200220a450d02200341046a2105200241276a41016a210f200241a8016a2101200241a0016a211020024198016a211120024190016a211220024180016a41086a2113034020052f0100210602400240024002400240200a2f01062205410b490d00200f410041d8001099051a200241003a0019200220022f01183b0108200241b7016a200241276a41d900109a051a20014200370300201042003703002011420037030020124200370300201342003703002002420037038001419c0110282209450d03200941003602002009410036000f20094200370007200920022f01083b0005200941136a200241b7016a41d900109a051a20094194016a20012903003702002009418c016a201029030037020020094184016a2011290300370200200941fc006a2012290300370200200941f4006a2013290300370200200920022903800137026c200a41c8006a2802002114200a41c4006a2802002115200a410e6a2d00002116200941086a200a410f6a200a2f0106220341796a2205109a052117200941146a200a41cc006a2005410374109a052118200941ec006a200a4188016a2003417a6a2204410274109a052107200a41063b0106200920053b010602402004450d00410021052007210303402003280200220820053b010420082009360200200341046a21032004200541016a2205470d000b0b20064107490d0120172006417a6a22036a2017200641796a22056a220820092f010620056b109b051a2008200c3a0000201820034103746a201820054103746a220820092f010620056b410374109b051a2008200e3602002008200d360204200920092f010641016a22083b01062006410274220c20076a416c6a200720034102746a2204200841ffff0371220620036b410274109b051a2004200b36020020062003490d022009200c6a41d4006a2103034020032802002208200541016a22053b010420082009360200200341046a210320052006490d000c030b0b200a41086a2209200641016a22036a200920066a2209200520066b2208109b051a2009200c3a0000200a41146a220920034103746a200920064103746a22092008410374109b051a2009200e3602002009200d360204200a200541016a22053b01062006410274200a41ec006a22096a41086a200920034102746a2209200541ffff0371220820036b410274109b051a2009200b360200200620084f0d08200a2003417f6a22054102746a41f0006a2103034020032802002209200541016a22053b01042009200a360200200341046a210320052008490d000c090b0b200a41086a2203200641016a22056a200320066a2203200a2f0106220820066b2204109b051a2003200c3a0000200a41146a220320054103746a200320064103746a22032004410374109b051a2003200e3602002003200d360204200a200841016a22033b010620064102742207200a41ec006a22086a41086a200820054102746a2204200341ffff0371220820056b410274109b051a2004200b360200200620084f0d00200a20076a41f0006a2105034020052802002203200641016a22063b01042003200a360200200541046a210520082006470d000b0b200a28020022030d012009210b2014210d2015210e2016210c0c050b419c0141041037000b200a41046a21052003210a2016210c2015210e2014210d2009210b0c000b0b41ec0041041037000b41ec0041041037000b200241b7016a41016a410041d8001099051a2002411f6a220542003700002002420037011a200220022902183703082002200529000037000f200241276a200241b7016a41d900109a051a200241a8016a22034200370300200241a0016a2209420037030020024180016a41186a2208420037030020024190016a2206420037030020024180016a41086a220a42003703002002420037038001419c0110282205450d0120054100360200200520022903083702042005410b6a200229000f370000200541136a200241276a41d900109a051a20054194016a20032903003702002005418c016a200929030037020020054184016a2008290300370200200541fc006a2006290300370200200541f4006a200a290300370200200520022903800137026c20052000280200220336026c200020053602002000200028020441016a360204200341003b010420032005360200200520052f010622034103746a220941186a200d360200200941146a200e360200200520036a41086a200c3a0000200541ec006a200341016a22034102746a200b360200200520033b0106200b20033b0104200b20053602000b20024190026a24000f0b419c0141041037000b822701377f2001410c6a28020021022001280208210341002104024002400240200141106a28020022050d00410021064100210741002108410021094100210a4100210b4100210c4100210d4100210e410021050c010b410021044100210e4100210d4100210c4100210b4100210a4100210941002108410021074100210f4100211002400340200121112010210620032005417f6a220541306c6a220128002c2112200128002821132001280024211420012800202115200128001c2116200128001821172001280014211820012800102119200128000c211a2001280008211b2001280004211c41012110024002400240024002400240024020012d0000221d417e6a221e410e4d0d004101211f0c010b4101211f4101212041012121410121224101212341012124201c21010240024002400240024002400240024002400240024002400240024002400240024002400240201e0e0f00010203040506180717080917171a000b0240200f0d002006211020112101201c210f201b2125201a21260c180b02402026450d0020264104742110200f210103400240200141046a280200450d002001280200102a0b200141106a2101201041706a22100d000b0b4101211f410021102025450d11200f102a0c110b024020070d002006211020112101201c2107201b2127201a21280c170b02402028450d00202841286c21102007210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101201041586a22100d000b0b4100211f410121102027450d0f2007102a0c0f0b2029450d0d2008450d0d2008102a0c0d0b202a450d0b2009450d0b2009102a0c0b0b202b450d09200a450d09200a102a0c090b0240200b0d002006211020112101201c210b201b212c201a212d0c130b0240202d450d00200b202d4104746a2121200b21200340024020202802082210450d0020202802002101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041106a21010240202041046a280200450d002020280200102a0b2001212020012021470d000b0b4100212041012110202c450d07200b102a0c070b0240200c0d002006211020112101201c210c201b212e201a212f0c120b0240202f450d00202f41146c2110200c210103400240200141046a280200450d002001280200102a0b200141146a21012010416c6a22100d000b0b4100212141012110202e450d05200c102a0c050b0240200d0d002006211020112101201c210d201b2130201a21310c110b02402031450d00200d2031411c6c6a2121200d21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b2001212020012021470d000b0b41002122410121102030450d03200d102a0c030b0240200e0d002006211020112101201c210e201b2132201a21330c100b02402033450d00200e203341186c6a2121200e212003400240202041046a280200450d002020280200102a0b0240202041146a2802002210450d00202028020c2101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041186a21010240202041106a280200450d00202028020c102a0b2001212020012021470d000b0b41002123410121102032450d01200e102a0c010b024020040d002006211020112101201a2134201b2135201c21040c0f0b02402034450d0020042034411c6c6a2121200421200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b2001212020012021470d000b0b410021244101211002402035450d002004102a0b201c2104201b2135201a21344101211f410121204101212141012122410121230c0d0b201a2133201b2132201c210e4101211f4101212041012121410121220c0b0b201a2131201b2130201c210d4101211f4101212041012121410121230c0a0b201a212f201b212e201c210c4101211f410121200c080b201a212d201b212c201c210b4101211f0c060b2006211020112101201c210a201b212b201a21360c090b2006211020112101201c2109201b212a201a21370c080b2006211020112101201c2108201b2129201a21380c070b201a2128201b2127201c21070c010b201a2126201b2125201c210f0b410121200b410121210b41012122410121230b410121240b024002400240201e410b4b0d000240024002400240024002400240024002400240201e0e0c000102030405060a070a0809000b2010450d0b0240201a450d00201a4104742110201c210103400240200141046a280200450d002001280200102a0b200141106a2101201041706a22100d000b0b201b450d0b0c0a0b201f450d0a0240201a450d00201a41286c2110201c210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101201041586a22100d000b0b201b0d090c0a0b41000d09201b0d080c090b41000d08201b0d070c080b41000d07201b0d060c070b2020450d060240201a450d00201c201a4104746a211e201c21200340024020202802082210450d0020202802002101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041106a21010240202041046a280200450d002020280200102a0b200121202001201e470d000b0b201b0d050c060b2021450d050240201a450d00201a41146c2110201c210103400240200141046a280200450d002001280200102a0b200141146a21012010416c6a22100d000b0b201b0d040c050b2022450d040240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d030c040b2023450d030240201a450d00201c201a41186c6a211e201c212003400240202041046a280200450d002020280200102a0b0240202041146a2802002210450d00202028020c2101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041186a21010240202041106a280200450d00202028020c102a0b200121202001201e470d000b0b201b0d020c030b2024450d020240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d010c020b0240201d410e4b0d00200621102011210102400240024002400240024002400240024002400240201d0e0f0001020304040405060e070e08090a000b201b0d0b0c0c0b0240201b450d00201c102a0b2018450d0b2019102a0c0b0b0240201a450d00201a4104742110201c210103400240200141046a280200450d002001280200102a0b200141106a2101201041706a22100d000b0b201b0d090c0a0b201a450d00201a41286c2110201c210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101201041586a22100d000b0b201b0d070c080b0240201a450d00201c201a4104746a211e201c21200340024020202802082210450d0020202802002101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041106a21010240202041046a280200450d002020280200102a0b200121202001201e470d000b0b201b0d060c070b0240201a450d00201a41146c2110201c210103400240200141046a280200450d002001280200102a0b200141146a21012010416c6a22100d000b0b201b0d050c060b0240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d040c050b0240201a450d00201c201a41186c6a211e201c212003400240202041046a280200450d002020280200102a0b0240202041146a2802002210450d00202028020c2101201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041186a21010240202041106a280200450d00202028020c102a0b200121202001201e470d000b0b201b0d030c040b0240201a450d00201c201a411c6c6a211e201c21200340024020202802042201450d0002402020410c6a2802002210450d00201041047421100340024020012d00004109470d000240200141046a221f280200222428020441ffffffff0371450d002024280200102a201f28020021240b2024102a0b200141106a2101201041706a22100d000b0b202041086a280200450d002020280204102a0b2020411c6a21010240202041146a280200450d002020280210102a0b200121202001201e470d000b0b201b0d020c030b0240201c450d00201b450d00201c102a0b02402018450d0002402016450d002016410c6c2110201821010340024020012802002224450d00200141046a280200450d002024102a0b2001410c6a2101201041746a22100d000b0b2017450d002018102a0b2014450d0202402012450d00201420124104746a211c2014212003402020221f41106a21200240201f2802042201450d000240201f410c6a2802002210450d002010410c6c21100340024020012802002224450d00200141046a280200450d002024102a0b2001410c6a2101201041746a22100d000b0b201f41086a280200450d00201f280204102a0b2020201c470d000b0b2013450d022014102a0c020b0240201b450d00201c102a0b02402018450d002017450d002018102a0b2014450d012015102a0c010b201c102a0b20062110201121010b20050d000b4100210520012111201021060b200f0d010b4104210f41002125410021260b20002003360280012000200636025420002026360208200020253602042000200f36020020004188016a200536020020004184016a2002360200200041fc006a2034410020041b360200200041f8006a2035410020041b36020020002004410420041b360274200041f0006a20334100200e1b360200200041ec006a20324100200e1b3602002000200e4104200e1b360268200041e4006a20314100200d1b360200200041e0006a20304100200d1b3602002000200d4104200d1b36025c200041d8006a2011360200200041d0006a202f4100200c1b360200200041cc006a202e4100200c1b3602002000200c4104200c1b360248200041c4006a202d4100200b1b360200200041c0006a202c4100200b1b3602002000200b4104200b1b36023c200041386a20364100200a1b360200200041346a202b4100200a1b3602002000200a4104200a1b3602302000412c6a2037410020091b360200200041286a202a410020091b36020020002009410420091b360224200041206a2038410020081b3602002000411c6a2029410020081b36020020002008410420081b360218200041146a2028410020071b360200200041106a2027410020071b36020020002007410420071b36020c0bb10a010e7f230041106b2202240002400240024002400240024020012802004101470d00200141106a2d000021032001410c6a2802002104200141086a280200210520012f0112210620012d0011210720012802042108200241086a200010fa0320022802082201200228020c22094104746a210a4100210b20094104490d01200341ff0171210c02400340024020012d000c200c470d0020012802082004470d000240200128020022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b200741ff0171220941044720012d000d220e410446220d460d00200e2009460d0520094104460d05200d0d050b02400240024002402001411c6a2d0000200c470d00200141186a2802002004470d000240200128021022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b200741ff0171220941044720012d001d220e410446220d460d00200e2009460d0120094104460d01200d0d010b2001412c6a2d0000200c470d02200141286a2802002004470d02200128022022092008460d012004450d012004210d2008210e034020092d0000200e2d0000470d03200941016a2109200e41016a210e200d417f6a220d450d020c000b0b200b410172210b0c060b200741ff0171220941044720012d002d220e410446220d460d00200e2009460d0220094104460d02200d0d020b024002402001413c6a2d0000200c470d00200141386a2802002004470d000240200128023022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b200741ff0171220941044720012d003d220e410446220d460d00200e2009460d0120094104460d01200d0d010b200b41046a210b200a200141c0006a22016b41304d0d040c010b0b200b410372210b0c030b200b410272210b0c020b2001280204210b0c030b2001200a460d0102400240200741ff0171220f4104460d00200341ff0171210c0c010b200341ff0171210c0340024020012d000c200c470d0020012802082004470d000240200128020022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b20012d000d4104460d030b200b41016a210b200141106a2201200a470d000c030b0b0340024020012d000c200c470d0020012802082004470d000240200128020022092008460d002004450d002004210d2008210e034020092d0000200e2d0000470d02200941016a2109200e41016a210e200d417f6a220d0d000b0b20012d000d2209200f470d0020094104470d020b200b41016a210b200141106a2201200a460d020c000b0b2005450d012008102a0c010b024020002802082201200041046a280200470d0002400240200141016a22092001490d002001410174220e2009200e20094b1b220941ffffffff00712009470d002009410474220e41004e0d010b1031000b0240024020010d00200e102821010c010b20002802002001410474200e102c21010b2001450d0220002001360200200041046a2009360200200028020821010b200028020020014104746a220120063b010e200120073a000d200120033a000c2001200436020820012005360204200120083602002000200028020841016a3602082002200010fa032002280204417f6a210b0b200241106a2400200b0f0b200e41041037000bf722032d7f017e017f230041306b22022400200241043602002001280204210320012802002104410121050240024002400240024002400240024002400240024002400240024002400240200128020822060d0041002107410121080c010b413010282207450d012007200636000c200720033600082007200436000420022007360200200741023a000041002108410121070b200141106a2802002109200128020c210a02400240200141146a280200220b0d002007210c0c010b2007410174220d200741016a220c200d200c4b1b220c41306c210e0240024020070d00200e1028210d0c010b2002280200200741306c200e102c210d0b200d450d022002200d360200200d200741306c6a220d41033a0000200d20022f002d3b0001200d200b36000c200d2009360008200d200a360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021050b2001411c6a280200210f200128021821104100211102400240200141206a28020022120d00200c210e410021130c010b024002402007200c460d00200c210e0c010b41000d0e41000d0e200c410174220d200c41016a220e200d200e4b1b220ead42307ea722144100480d0e02400240200c0d0020141028210d0c010b2002280200200c41306c2014102c210d0b200d450d042002200d3602000b2002280200200741306c6a220d41043a0000200d20022f002d3b0001200d201236000c200d200f360008200d2010360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012113200741016a21070b200141286a280200211420012802242115024002402001412c6a28020022120d00200e210c0c010b024002402007200e460d00200e210c0c010b41000d0e41000d0e200e410174220d200e41016a220c200d200c4b1b220cad42307ea722114100480d0e02400240200e0d0020111028210d0c010b2002280200200e41306c2011102c210d0b200d450d052002200d3602000b2002280200200741306c6a220d41053a0000200d20022f002d3b0001200d201236000c200d2014360008200d2015360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012111200741016a21070b200141346a28020021162001280230211702400240200141386a280200220e0d00410021180c010b02402007200c470d0041000d0e41000d0e200c410174220d200c41016a2212200d20124b1b2212ad42307ea722194100480d0e02400240200c0d0020191028210d0c010b2002280200200c41306c2019102c210d0b200d450d062002200d3602002012210c0b2002280200200741306c6a220d41063a0000200d20022f002d3b0001200d200e36000c200d2016360008200d2017360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a29020037020041012118200741016a21070b200141c0006a280200211a200128023c211b4101211902400240200141c4006a280200221c0d00200c210e4101211d0c010b024002402007200c460d00200c210e0c010b41000d0e41000d0e200c410174220d200c41016a220e200d200e4b1b220ead42307ea722124100480d0e02400240200c0d0020121028210d0c010b2002280200200c41306c2012102c210d0b200d450d072002200d3602000b2002280200200741306c6a220d41073a0000200d20022f002d3b0001200d201c36000c200d201a360008200d201b360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a21074100211d0b200141cc006a280200211e2001280248211f02400240200141d0006a28020022200d00200e21120c010b024002402007200e460d00200e21120c010b41000d0e41000d0e200e410174220d200e41016a220c200d200c4b1b2212ad42307ea7220c4100480d0e02400240200e0d00200c1028210d0c010b2002280200200e41306c200c102c210d0b200d450d082002200d3602000b2002280200200741306c6a220d41083a0000200d20022f002d3b0001200d202036000c200d201e360008200d201f360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a200241046a41086a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021190b410121210240024020012802544101460d002012210c0c010b200141d8006a280200210e0240024020072012460d002012210c0c010b41000d0e41000d0e2012410174220d201241016a220c200d200c4b1b220cad42307ea722224100480d0e0240024020120d0020221028210d0c010b2002280200201241306c2022102c210d0b200d450d092002200d3602000b2002280200200741306c6a220d41093a0000200d20022f002d3b0001200d200e360204200d2002290204370208200d41036a2002412f6a2d00003a0000200d41106a2002410c6a290200370200200d41186a200241046a41106a290200370200200d41206a200241046a41186a290200370200200d41286a200241046a41206a290200370200200741016a21070b200141e0006a2802002123200128025c212402400240200141e4006a28020022250d00200c210e0c010b024002402007200c460d00200c210e0c010b41000d0e41000d0e200c410174220d200c41016a220e200d200e4b1b220ead42307ea722124100480d0e02400240200c0d0020121028210d0c010b2002280200200c41306c2012102c210d0b200d450d0a2002200d3602000b2002280200200741306c6a220d410a3a0000200d20022f002d3b0001200d202536000c200d2023360008200d2024360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021210b200141ec006a2802002126200128026821274101212202400240200141f0006a28020022280d00200e2112410121290c010b024002402007200e460d00200e21120c010b41000d0e41000d0e200e410174220d200e41016a220c200d200c4b1b2212ad42307ea7220c4100480d0e02400240200e0d00200c1028210d0c010b2002280200200e41306c200c102c210d0b200d450d0b2002200d3602000b2002280200200741306c6a220d410c3a0000200d20022f002d3b0001200d202836000c200d2026360008200d2027360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021290b200141f8006a280200212a2001280274212b02400240200141fc006a280200222c0d002012210c0c010b0240024020072012460d002012210c0c010b41000d0e41000d0e2012410174220d201241016a220c200d200c4b1b220cad42307ea7220e4100480d0e0240024020120d00200e1028210d0c010b2002280200201241306c200e102c210d0b200d450d0c2002200d3602000b2002280200200741306c6a220d410d3a0000200d20022f002d3b0001200d202c36000c200d202a360008200d202b360004200d2002290204370210200d41036a2002412f6a2d00003a0000200d41186a2002410c6a290200370200200d41206a200241146a290200370200200d41286a200241046a41186a290200370200200741016a2107410021220b20014184016a2802002112200128028001210d02400240200c20076b20014188016a28020041306c222d41306d220e490d00200228020021010c010b2007200e6a22012007490d0d200c410174222e2001202e20014b1b222ead42307e222f422088a70d0d202fa722304100480d0d02400240200c0d002030102821010c010b2002280200200c41306c2030102c21010b2001450d0c20022001360200202e210c0b2001200741306c6a200d202d109a051a2007200e6a210702402012450d00200d102a0b2000200136020820004280c2cdeb16370200200041106a20073602002000410c6a200c3602002022450d0d0240202c450d00202b202c411c6c6a210e202b21000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102a0b2000411c6a21010240200041146a280200450d002000280210102a0b200121002001200e470d000b0b202a450d0d202b102a0c0d0b413041041037000b200e41041037000b201441041037000b201141041037000b201941041037000b201241041037000b200c41041037000b202241041037000b201241041037000b200c41041037000b200e41041037000b203041041037000b1031000b02402029450d0002402028450d002027202841186c6a210e2027210003400240200041046a280200450d002000280200102a0b0240200041146a2802002207450d00200028020c2101200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041186a21010240200041106a280200450d00200028020c102a0b200121002001200e470d000b0b2026450d002027102a0b02402021450d0002402025450d0020242025411c6c6a210e202421000340024020002802042201450d0002402000410c6a2802002207450d00200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041086a280200450d002000280204102a0b2000411c6a21010240200041146a280200450d002000280210102a0b200121002001200e470d000b0b2023450d002024102a0b02402019450d0002402020450d00202041146c2107201f210103400240200141046a280200450d002001280200102a0b200141146a21012007416c6a22070d000b0b201e450d00201f102a0b0240201d450d000240201c450d00201b201c4104746a210e201b21000340024020002802082207450d0020002802002101200741047421070340024020012d00004109470d000240200141046a220c280200220d28020441ffffffff0371450d00200d280200102a200c280200210d0b200d102a0b200141106a2101200741706a22070d000b0b200041106a21010240200041046a280200450d002000280200102a0b200121002001200e470d000b0b201a450d00201b102a0b02402016410047201841017371450d002017102a0b02402014410047201141017371450d002015102a0b0240200f410047201341017371450d002010102a0b02402005450d000240200b450d00200b41286c2107200a210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200741586a22070d000b0b2009450d00200a102a0b02402008450d0002402006450d00200641047421072004210103400240200141046a280200450d002001280200102a0b200141106a2101200741706a22070d000b0b2003450d002004102a0b200241306a24000bee0203037f017e027f410121020240024002400240200041086a2802002203417f6a220420034f0d00200420034b0d00200028020020044104746a220329020421052003200141016aad3702042005a721012005422088a721030240200041086a28020022024101460d002002450d0220002802002002417e6a4104746a22022802042001470d002002200228020820036a36020841000f0b410021022003450d000240200041146a2802002204200041106a280200470d00200441016a22062004490d04200441017422072006200720064b1b220641ffffffff01712006470d04200641037422074100480d040240024020040d002007102821040c010b200028020c20044103742007102c21040b2004450d032000200436020c200041106a2006360200200028021421040b200028020c20044103746a22042003360204200420013602002000200028021441016a3602140b20020f0b41ede3c500413f1050000b200741041037000b1031000b8a1302147f027e23004180026b220424000240024020014115490d0041012105410121060240024002400340200121072000210820052006714101732109024002400240024002400240034002400240024002402003450d00024020054101710d002000200110de042003417f6a21030b2001410276220a41036c210b200a410174210c4100210d024020014132490d00200b200b417f6a220d2000200b4103746a280200220e2000200d4103746a280200220f4922101b2211200b41016a2212200d200b20101b200020124103746a280200220b200f200e20101b220d49220f1b200b200d200f1b200020114103746a2802004922131b210b200c200c417f6a220d2000200c4103746a28020022112000200d4103746a280200221249220e1b2214200c4101722206200d200c200e1b200020064103746a280200220c20122011200e1b220d4922111b200c200d20111b200020144103746a2802004922141b210c200a200a417f6a22122000200a4103746a2802002206200020124103746a280200221549220d1b2216200a41016a22172012200a200d1b200020174103746a280200220a20152006200d1b22064922121b200a200620121b200020164103746a2802004922061b210a41024101200d1b200d20121b20066a200e6a20116a20146a20106a200f6a20136a210d0b200d2000200c4103746a280200220e2000200a4103746a280200220f4922106a2000200b4103746a280200220d200f200e20101b221149220f6a210e200d2011200f1b2000200c200a20101b220d4103746a280200490d01200b200a200c20101b200f1b210d0c020b2000200110df040c0f0b200e41016a220e410c490d0002402001410176220b450d00200020014103746a41786a210a2000210c0340200c2902002118200c200a290200370200200a2018370200200c41086a210c200a41786a210a200b417f6a220b0d000b0b2001200d417f736a210d4101210a0c010b200e45210a0b0240200a452009724101710d002000200110e0040d0d0b2002450d02200d20014f0d01024020022802002000200d4103746a220a2802004f0d0020002108200121070c040b200029020021182000200a290200370200200a2018370200200041786a210f200041086a211120002902002218a721104100210c2001210b03400240200c200b417f6a220d4f0d002011200c4103746a210a0340200a28020020104b0d01200a41086a210a200d200c41016a220c470d000b200d210c0b200f200b4103746a210a02400340200c200b417f6a220b4f0d01200a280200210d200a41786a220e210a200d20104b0d000b2011200c4103746a220a2902002119200a200e41086a220d290200370200200d2019370200200c41016a210c0c010b0b2000201837020002402001200c41016a220a490d002000200a4103746a21002001200a6b220141154f0d010c0c0b0b200a20011044000b41b8e9c500200d20011034000b2007450d010b200d20074f0d012008290200211820082008200d4103746a220a290200370200200a2018370200200841086a210e20082902002219a72111410021142007417f6a2210450d02200e210a0340200a28020020114f0d03200a41086a210a2010201441016a2214470d000b201021140c020b4198e9c500410041001034000b41a8e9c500200d20071034000b200820074103746a210c2010210b02400340200c210d200b220a20144d22060d01200a417f6a210b200d41786a220c28020020114f0d000b0b0240200a2014490d002010200a490d0241800121054100210b410021014100210c4100210f4180012109200e20144103746a2215211003400240200d20106b220a4187104b22130d00200a410376220a41807f6a200a2001200b49200f200c49220e7222001b210a02402000450d002009200a200e1b2109200a2005200e1b21050c010b200a200a41017622096b21050b0240200f200c470d00024020090d002004220c210f0c010b4100210a2004220f210c2010210e0340200c200a3a0000200c200e28020020114f6a210c200e41086a210e2009200a41016a220a470d000b0b02402001200b470d00024020050d0020044180016a220b21010c010b200d41786a210a4100210e20044180016a2201210b0340200b200e3a0000200b200a2802002011496a210b200a41786a210a2005200e41016a220e470d000b0b0240200b20016b220a200c200f6b220e200e200a4b1b2212450d002010200f2d00004103746a220a2902002118200a200d20012d0000417f734103746a290200370200024020124101460d004100210a0340200d2001200a6a220e2d0000417f734103746a2010200f200a6a41016a22002d00004103746a290200370200201020002d00004103746a200d200e41016a2d0000417f734103746a290200370200200a41026a210e200a41016a2200210a200e2012490d000b200120006a2101200f20006a210f0b200d20012d0000417f734103746a2018370200200141016a2101200f41016a210f0b200d20054103746b200d2001200b461b210d201020094103746a2010200f200c461b211020130d000b02400240200f200c4f0d00200d210a03402010200c417f6a220c2d00004103746a220b2902002118200b200a41786a220a290200370200200a2018370200200f200c490d000c020b0b2010210a2001200b4f0d000340200a2902002118200a200d200b417f6a220b2d0000417f734103746a220c290200370200200c2018370200200a41086a210a2001200b490d000b0b200820193702002007200a20156b41037620146a22014d0d032008200820014103746a220a290200370200200a2019370200200720016b220c450d04200c20012001200c4b1b210b2007410376210d200a41086a2100024002402001200c417f6a220c490d002000200c200a2003108004200821000c010b2008200120022003108004200a2102200c21010b200b200d4f2105200141154f0d010c050b0b2014200a1044000b200a2010103c000b41a8e9c500200120071034000b41dc83c6001032000b20014102490d00200041786a21104100210e4101210b0340200b410374210c200b417f6a210a200b41016a210b02402000200c6a220d2802002000200a4103746a220f2802004f0d00200d2902002118200d200f2902003702000240200a450d00200e210c2010210a200d41706a2802002018a7220d4d0d00024002400340200a41086a200a290200370200200c4101460d01200c417f6a210c200a41786a220a280200200d4b0d000c020b0b4100210c0b2000200c4103746a210f0b200f20183702000b200e41016a210e201041086a2110200b2001470d000b0b20044180026a24000be00402097f017e230041306b22022400200241106a2203200141246a290200370300200241086a22042001411c6a29020037030020022001290214370300200241186a41106a2205200141106a280200360200200241186a41086a2206200141086a290200370300200220012902003703182000200241186a10fd0321070240024002400240200041206a28020022082000411c6a280200470d00200841016a22092008490d032008410174220a2009200a20094b1b220941ffffffff03712009470d032009410274220a4100480d030240024020080d00200a102821080c010b20002802182008410274200a102c21080b2008450d01200020083602182000411c6a2009360200200028022021080b200028021820084102746a20073602002000200028022041016a3602202005200329030037030020062004290300370300200220022903003703180240200041f0006a22032802002208200041ec006a280200470d00200841016a22042008490d03200841017422052004200520044b1b2204ad42187e220b422088a70d03200ba722054100480d030240024020080d002005102821080c010b2000280268200841186c2005102c21080b2008450d0220002008360268200041ec006a2004360200200041f0006a28020021080b2000280268200841186c6a22082002290318370200200841106a200241186a41106a290300370200200841086a200241186a41086a29030037020020032003280200220841016a360200024020012d002c450d0020004101360254200041d8006a20083602000b200241306a24000f0b200a41041037000b200541041037000b1031000bb20c01067f0240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102a0f0b0240200041086a280200450d00200041046a280200102a0b200041146a280200450d0c200041106a280200102a0f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102a0f0b200041086a280200450d09200041046a280200102a0f0b200041086a280200450d08200041046a280200102a0f0b200041086a280200450d07200041046a280200102a0f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d002003280200102a0b2001210320012004470d000b0b200041086a280200450d062000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102a0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102a0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102a0b2003411c6a21010240200341146a280200450d002003280210102a0b2001210320012004470d000b0b200041086a280200450d042000280204102a0f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d002003280200102a0b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d00200328020c102a0b2001210320012004470d000b0b200041086a280200450d032000280204102a0f0b200041046a220110f904200041086a280200450d022001280200102a0f0b0240200041046a2802002201450d00200041086a280200450d002001102a0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0b200041246a2802002203450d0102402000412c6a2802002201450d00200320014104746a210403402003220541106a2103024020052802042201450d0002402005410c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200541086a280200450d002005280204102a0b20032004470d000b0b200041286a280200450d012000280224102a0c010b0240200041086a280200450d00200041046a280200102a0b0240200041146a2802002201450d00200041186a280200450d002001102a0b200041246a280200450d00200041206a280200102a0f0b0bff7f05077f017e277f037e0f7f23002203210420034180096b4160712203240002400240024002400240024002400240024002400240411010282205450d00200541063a0000412010282206450d01200641063a001020064100360204200620032f00f0053b00012006412d3a0000200641036a200341f2056a2d00003a0000024020052d00004109470d0002402005280204220728020441ffffffff0371450d002007280200102a200528020421070b2007102a0b2005102a200141106a28020041306c2105200128020841546a210702400340024020050d00411010282207450d0520074180023b010c200742828080802037020420072006360200200720032f01d0033b010e0240200128021022052001410c6a280200470d00200541016a22082005490d0e200541017422092008200920084b1b2208ad42307e220a422088a70d0e200aa722094100480d0e0240024020050d002009102821050c010b2001280208200541306c2009102c21050b2005450d07200120053602082001410c6a2008360200200128021021050b2001280208200541306c6a220520032f00e0043b0001200541073a0000200542818080801037000820052007360004200520032902f005370210200541036a200341e2046a2d00003a0000200541186a200341f8056a290200370200200541206a20034180066a290200370200200541286a200341f0056a41186a2902003702002001200128021041016a220b3602104100210c0c020b200541506a21052007412c6a2108200741306a2209210720082d00004107470d000b200320032f01d0033b01f0050240200941086a22072802002205200941046a280200470d00200541016a22082005490d0c2005410174220d2008200d20084b1b220841ffffffff00712008470d0c2008410474220d4100480d0c0240024020050d00200d102821050c010b20092802002005410474200d102c21050b2005450d0620092005360200200941046a2008360200200941086a28020021050b200928020020054104746a22054180023b010c200542828080802037020420052006360200200520032f01f0053b010e2007200728020041016a360200200341c0006a200910fa032003280244417f6a210c2001280210210b0b200b41306c21052001280208220e41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200b41306c2105200e41546a210702400340410021092005450d01200541506a21052007412c6a2106200741306a220d210720062d00004103470d000b200d41086a2802002205450d00200541286c2107200d28020041186a2105410021090340200920052d0000456a2109200541286a2105200741586a22070d000b0b200b41306c2105200e415c6a2107024003404100210f024020050d00410021050c020b200541506a2105200741246a2106200741306a220d210720062d00004104470d000b200d28020021050b200341003602e0040240200520096a220b0d0041042110410021110c080b02402008450d00200342003703f005410021050c060b200341f0056a4100200110d60420032802f405210520032802f0054101470d05200341f8056a290300210a024020032802e0042207450d0020032802e404450d002007102a0b2003200a3702e404200320053602e00441002111410421104100210f0c060b411041081037000b412041081037000b411041041037000b200941041037000b200d41041037000b0240024002400240410410282210450d0020102005360200200b4102490d02024020084102490d00200342003703f0054100210d0c020b200341f0056a4101200110d60420032802f405210d20032802f0054101470d01200341f8056a290300210a024020032802e004450d0020032802e404450d0020032802e004102a0b2003200a3702e4042003200d3602e0040c020b410441041037000b410221064104210741012109410121110340200941016a210502400240024020092011470d0020062005200620054b1b221141ffffffff03712011470d0a2011410274220e4100480d0a20102007200e102c2210450d010b201020076a200d36020002402005200b4f0d000240200820054d0d00200342003703f0054100210d0c030b200341f0056a2005200110d60420032802f405210d20032802f0054101470d0220032903f805210a024020032802e004450d0020032802e404450d0020032802e004102a0b200941016a210f2003200a3702e4042003200d3602e0040c050b200941016a210f0c040b200e41041037000b200641026a2106200741046a2107200521090c000b0b4101210f410121110b20032802e00421050b2005450d0020032902e404210a02402011450d002010102a0b2000200536020420004101360200200041086a200a3702000c010b024020012802102205450d0020012802082212200541306c6a2113200341e0046a41146a2114200341e0076a211520034194066a2116200341a4066a2117200341b4066a2118200341c4066a2119200341d4066a211a200341e4066a211b200341f4066a211c20034184076a211d20034194076a211e200341a4076a211f200341b4076a2120200341c4076a2121200341d4076a212202400240024002400340024020122d0000410c470d00201228020c2205450d0020122802042206200541186c6a212303400240200641146a220e2802002205450d002006410c6a212441002109024002400340200920054f0d014101210502402024280200200941047422256a22072d0000410b470d002003200741046a22073602c00220072802002207200f4f0d03201020074102746a2802002208450d002003200c3602d407200341133a00d007200341d7003a00c007200320083602b4072003412d3a00b0072003200c3602a407200341123a00a00720032007360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200c3602b406200341123a00b0062003200c3602a406200341133a00a006200341d6003a00900620032008360284062003412d3a0080062003200c3602f405200341123a00f005200e280200222620094d0d09200e2009360200200628020c2105200320153602f804200320243602f0042003200520256a220b41106a220d3602e8042003200941016a22273602e0042003202620276b22283602e40420032005202741047422296a222a3602ec042003200341f0056a3602f404200d21050240200b2d0000220841ac01460d004100210502400340200b20056a21070240200841ff01714109470d000240200741046a280200220828020441ffffffff0371450d002008280200102a0b2008102a0b2005450d012003200741206a3602e804200541106a2105200741106a2d0000220841ac01470d000b200b20056a41106a21050c010b200741106a21050b02402005202a460d0003402003200541106a22073602e80420052d0000220841ac01460d01024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b20072105200d2007470d000b0b02400240024002402028450d000240202720062802142205470d00200341f0056a21052015210b0c030b2025200541047422056b2108200628020c20056a2107200341f0056a21052015210d0340024002402005200d470d00410021050c010b2003200541106a3602f4040b200341d0036a200510d30420032d00d00341ac01460d04200720032903d003370300200741086a200341d0036a41086a2903003703002006200628021441016a3602142008450d02200741106a2107200841706a210820032802f804210d20032802f40421050c000b0b2024201410d7040c020b20032802f804210b20032802f40421050b0240200b20056b2207450d000240024020032802f004220d41046a222a280200222520266b20074104762208490d00200d28020021070c010b202620086a22072026490d12202541017422262007202620074b1b222641ffffffff00712026470d122026410474222b4100480d120240024020250d00202b102821070c010b200d2802002025410474202b102c21070b2007450d0d200d2007360200202a20263602000b2007202720086a22254104746a200720296a2028410474109b051a200320253602e0042025200d2802082207460d00200920086a410474200741047422076b2108200d28020020076a21070340024002402005200b470d00410021050c010b2003200541106a3602f4040b200341d0036a200510d30420032d00d00341ac01460d02200720032903d003370300200741086a200341d0036a41086a290300370300200d200d28020841016a3602082008450d01200741106a2107200841706a210820032802f804210b20032802f40421050c000b0b200341003602d803200342083703d003200341d0036a201410d70420032802d003222820032802d8032207410474220b6a210d20032802d40321292028210502402007450d000240024020032802f004222541046a222a280200220520032802e404222720032802e00422076a22266b200b4104752208490d00202528020021050c010b202620086a222b2026490d1220054101742226202b2026202b4b1b222641ffffffff00712026470d122026410474222b4100480d120240024020050d00202b102821050c010b20252802002005410474202b102c21050b2005450d0e20252005360200202a20263602000b2005200720086a220841047422266a200520074104746a2027410474109b051a200320083602e00420282105200820252802082207460d002025280200220520266a212a200520074104746a21082028210703400240200b0d00200d21050c020b200341d0036a41026a2205200741036a2d00003a0000200320072f00013b01d003024020072d0000222741ac01470d00200741106a21050c020b200741046a2802002126200741086a290300210a200820273a0000200841086a200a370300200841046a202636020020032f01d0032127200841036a20052d00003a0000200841016a20273b00002025202528020841016a360208200b41706a210b200741106a22052107200841106a2208202a470d000b0b02402005200d460d0003400240024020052d000022074109460d00200741ac01470d010c030b0240200541046a280200220728020441ffffffff0371450d002007280200102a0b2007102a0b200541106a2205200d470d000b0b2029450d002028102a0b024020032802e804220520032802ec04220d460d0003402003200541106a22073602e80420052d0000220841ac01460d01024020084109470d000240200541046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b20072105200d2007470d000b0b024020032802e4042205450d00024020032802e004220d20032802f004220b41086a22082802002207460d00200b280200220b20074104746a200b200d4104746a2005410474109b051a0b2008200520076a3602000b024020032d00f0054109470d00024020032802f405220528020441ffffffff0371450d002005280200102a20032802f40521050b2005102a0b024020032d0080064109470d000240200341f0056a41146a280200220528020441ffffffff0371450d002005280200102a20032802840621050b2005102a0b024020032d0090064109470d0002402016280200220528020441ffffffff0371450d002005280200102a20032802940621050b2005102a0b024020032d00a0064109470d0002402017280200220528020441ffffffff0371450d002005280200102a20032802a40621050b2005102a0b024020032d00b0064109470d0002402018280200220528020441ffffffff0371450d002005280200102a20032802b40621050b2005102a0b024020032d00c0064109470d0002402019280200220528020441ffffffff0371450d002005280200102a20032802c40621050b2005102a0b024020032d00d0064109470d000240201a280200220528020441ffffffff0371450d002005280200102a20032802d40621050b2005102a0b024020032d00e0064109470d000240201b280200220528020441ffffffff0371450d002005280200102a20032802e40621050b2005102a0b024020032d00f0064109470d000240201c280200220528020441ffffffff0371450d002005280200102a20032802f40621050b2005102a0b024020032d0080074109470d000240201d280200220528020441ffffffff0371450d002005280200102a20032802840721050b2005102a0b024020032d0090074109470d000240201e280200220528020441ffffffff0371450d002005280200102a20032802940721050b2005102a0b024020032d00a0074109470d000240201f280200220528020441ffffffff0371450d002005280200102a20032802a40721050b2005102a0b024020032d00b0074109470d0002402020280200220528020441ffffffff0371450d002005280200102a20032802b40721050b2005102a0b024020032d00c0074109470d0002402021280200220528020441ffffffff0371450d002005280200102a20032802c40721050b2005102a0b024020032d00d0074109470d0002402022280200220528020441ffffffff0371450d002005280200102a20032802d40721050b2005102a0b410f21050b200520096a2209200e2802002205490d000c030b0b41ace4c500200920051034000b2003410136028406200342013702f405200341bce4c5003602f0052003412c3602d4032003200341d0036a360280062003200341c0026a3602d003200341e0046a200341f0056a103320032802e00422050d040b200641186a22062023470d000b0b201241306a22122013470d000c050b0b20032902e404210a2000200536020420004101360200200041086a200a3702002011450d042010102a0c040b41e4e8c5001032000b202b41081037000b202b41081037000b200341c8006a41106a200141106a2802002220360200200341c8006a41086a200141086a290200220a37030020032001290200370348202041306c2105200aa7221241546a210702400340024020050d00410021080c020b200541506a21052007412c6a2108200741306a2209210720082d00004108470d000b200341386a200910fa0320032802382108200328023c21050b2005410020081b210d202041306c2105201241546a21072008410420081b210802400340024020050d00410021090c020b200541506a21052007412c6a2109200741306a2206210720092d0000410a470d000b200341306a200610fa0320032802302109200328023421050b2005410020091b210b202041306c2105201241546a21072009410420091b211702400340024020050d004100211c0c020b200541506a21052007412c6a2109200741306a2206210720092d00004109470d000b200628020021074101211c0b20034200370274200341f8b9c0003602702017200b411c6c6a211f2008200d41146c6a210d200341e0046a410272221b41266a2121201b41186a2122201b41086a212b4104211641002124410021264100211e4100211d410021140240024002400240410041ff01710e03000102000b410021050c020b410221050c010b410121050b03400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020050e03000104040b0240201441ff01710e03020300020b201e4101470d04410021050c0b0b201c450d0f4100211c410221284100212a200721050c1d0b034002400240024002400240200d200822056b413c4b0d002005200d470d01200521080c020b200528020c0d03200541146a2108200541106a28020021050c1f0b200541106a21090340200528020c450d02200941146a2109200541146a2205200d470d000b200d21080b201e4101470d07410021050c0a0b200941046a2108200928020021050c1c0b200541206a280200450d1a200541346a280200450d19200541d0006a2108200541c8006a280200450d180c000b0b0340024002400240200d200822056b413c4b0d00410121142005200d470d01200521080c2b0b200528020c0d01200541146a2108200541106a28020021050c180b200541106a210902400340200528020c450d01200941146a2109200541146a2205200d470d000b200d21080c2a0b200941046a2108200928020021050c170b200541206a280200450d15200541346a280200450d14200541d0006a2108200541c8006a280200450d130c000b0b024002400240201441ff01710e03010200010b201e4101470d03410021050c080b034002400240024002400240200d200822056b413c4b0d002005200d470d01200521080c020b200528020c0d03200541146a2108200541106a28020021050c160b200541106a21090340200528020c450d02200941146a2109200541146a2205200d470d000b200d21080b201e4101470d07410021050c080b200941046a2108200928020021050c130b200541206a280200450d11200541346a280200450d10200541d0006a2108200541c8006a280200450d0f0c000b0b0340024002400240200d200822056b413c4b0d002005200d460d10200541106a21090340200528020c450d02200941146a2109200541146a2205200d470d000c110b0b200528020c0d01200541146a2108200541106a28020021050c0e0b200941046a2108200928020021050c0d0b200541206a280200450d0b200541346a280200450d0a200541d0006a2108200541c8006a280200450d090c000b0b410121050c060b410121050c040b410121050c020b410121050b0340024002400240024020050e020001010b2029201d470d01410121050c030b2017201f460d0a200341206a201710cd0420032802202229450d0a2017411c6a2117202920032802244102746a211d0c010b2029450d09202928020021054101211e41022114202941046a2129410121280c160b410021050c000b0b0340024002400240024020050e020001010b2029201d470d014101211e2029211d410121050c030b410221142017201f460d22200341106a201710cd042017411c6a211720032802102205450d23200520032802144102746a211d200521290c010b202941046a2109024020290d00410221144101211e200921290c230b2029280200210541002128410221144101211e200921290c150b410021050c000b0b0340024002400240024020050e020001010b2029201d470d01410121050c030b2017201f460d08200341286a201710cd0420032802282229450d082017411c6a21172029200328022c4102746a211d0c010b2029450d07202928020021054101211e41022114202941046a2129410121280c140b410021050c000b0b0340024002400240024020050e020001010b2029201d470d014101211e2029211d410121050c030b410221142017201f460d20200341186a201710cd042017411c6a211720032802182205450d212005200328021c4102746a211d200521290c010b202941046a2109024020290d00410221144101211e200921290c210b2029280200210541002128410221144101211e200921290c130b410021050c000b0b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41012114410121280c0d0b200341e0006a41086a200341f0006a41086a280200360200200320032903703703602003280258220d41306c21052003280250220b41546a210702400340410021082005450d01200541506a21052007412c6a2109200741306a2206210720092d00004103470d000b200641086a2802002205450d00200541286c2107200628020041186a2105410021080340200820052d0000456a2108200541286a2105200741586a22070d000b0b200d41306c2105200b415c6a210702400340024020050d00410021050c020b200541506a2105200741246a2109200741306a2206210720092d00004104470d000b200628020021050b200341f0056a41106a2228200341c8006a41106a280200360200200341f0056a41086a200341c8006a41086a290300370300200320032903483703f005200341b0016a200341f0056a10fc0302402026450d00201620264102746a212a200520086a2125200341f0056a41e0016a210f200341f0056a41d0016a2115200341f0056a41c0016a2129200341f0056a41b0016a2114200341f0056a41a0016a2117200341f0056a4190016a2118200341f0056a4180016a2119200341f0056a41f0006a211a200341f0056a41e0006a211b200341f0056a41d0006a211c200341f0056a41c0006a211d200341f0056a41306a211e200341f0056a41206a211f200341e7046a212020034184066a212120034194066a2122200341b4066a212b200341c4066a2123200341d4066a2112200341e4066a2101200341f4066a211320034184076a212c20034194076a212d200341a4076a212e200341b4076a212f200341c4076a2130200341d4076a21312016212703402027220541046a212720052802002106200341e0006a21052003280264210b03402005280200220d41086a2107200d2f0106220e4102742105417f210802400340024020050d00200e21080c020b20072802002109200841016a21082005417c6a2105200741046a21070240417f2009200647200920064b1b41016a0e03020001020b0b200d41346a20084105746a220e2802182107200e28021c21052003200c3602d407200341133a00d007200341d7003a00c007200320053602b4072003412d3a00b0072003200c3602a407200341123a00a00720032007360294072003410b3a009007200341063a008007200341003a00f00620034184083b01e006200341373a00d006200320023602c4062003412d3a00c0062003200c3602b406200341123a00b0062003200c3602a406200341133a00a006200341d6003a00900620032005360284062003412d3a0080062003200c3602f405200341123a00f005200e280208220d41106a220541ffffffff00712005470d1220054104742207417f4c0d12200e41086a21260240024002400240024020070d00410821060c010b200710282206450d012026280200210d0b0240200d0d00410021080c030b41002109410021070340024020072005470d00200541016a22082005490d262005410174220b2008200b20084b1b220841ffffffff00712008470d262008410474220b4100480d260240024020050d00200b102821060c010b20062005410474200b102c21060b2006450d03200821050b200620096a2208410f3a0000200841046a2007360200200841016a20032f01d0033b0000200841036a200341d0036a41026a2d00003a0000200941106a2109200741016a22082107200d2008460d030c000b0b200741081037000b200b41081037000b02400240024002400240024002400240200520086b410e4d0d00200521090c010b2008410f6a22072008490d28200541017422092007200920074b1b220941ffffffff00712009470d28200941047422074100480d280240024020050d002007102821060c010b200620054104742007102c21060b2006450d010b200341e0046a200341f0056a10d904200620084104746a220520032903e004370300200541086a200341e0046a41086a2207290300370300200341e0046a202810d904200541186a2007290300370300200520032903e004370310200341e0046a201f10d904200541286a2007290300370300200541206a20032903e004370300200341e0046a201e10d904200541386a2007290300370300200541306a20032903e004370300200341e0046a201d10d904200541c8006a2007290300370300200541c0006a20032903e004370300200341e0046a201c10d904200541d8006a2007290300370300200541d0006a20032903e004370300200341e0046a201b10d904200541e8006a2007290300370300200541e0006a20032903e004370300200341e0046a201a10d904200541f8006a2007290300370300200541f0006a20032903e004370300200341e0046a201910d90420054188016a200729030037030020054180016a20032903e004370300200341e0046a201810d90420054198016a200729030037030020054190016a20032903e004370300200341e0046a201710d904200541a8016a2007290300370300200541a0016a20032903e004370300200341e0046a201410d904200541b8016a2007290300370300200541b0016a20032903e004370300200341e0046a202910d904200541c8016a2007290300370300200541c0016a20032903e004370300200341e0046a201510d904200541d8016a2007290300370300200541d0016a20032903e004370300200341e0046a200f10d904200541e8016a2007290300370300200541e0016a20032903e004370300024002402008410f6a22052009460d002009210d200521090c010b200941016a22052009490d28200941017422072005200720054b1b220d41ffffffff0071200d470d28200d41047422054100480d280240024020090d002005102821060c010b200620094104742005102c21060b2006450d020b200620094104746a220541063a0000200520032900e004370001200541086a2020290000370000200341e0046a200341b0016a418c01109a051a411010282207450d02200741063a0000200341d0036a200341e0046a418c01109a051a20262802002205417f4c0d18200e28020021090240024020050d004101210b410120092005109a05220920092005109a051a2005ad2132410021050c010b20051028220b450d04200b20092005109a05210920051028220b450d05200b20092005109a051a2009102a2005ad21320b200341e0046a200341d0036a418c01109a051a200e31000d2133200341d0036a200341e0046a418c01109a051a200341e0046a200341d0036a418c01109a051a200341c0026a200341e0046a418c01109a051a411010282209450d05200841106a2108200a428080808080804083220a2032842033422886844280808080800c842132200941063a00002009102a200341d0036a200341c0026a418c01109a051a200341e0046a200341d0036a418c01109a051a024020072d00004109470d0002402007280204220928020441ffffffff0371450d002009280200102a200728020421090b2009102a0b2007102a200341c0026a200341e0046a418c01109a051a200341e0046a200341c0026a418c01109a051a200341003602fc03200320083602f8032003200d3602f403200320063602f003200341003602ec03200342043702e403200320323702dc03200320053602d8032003200b3602d403200341013602d003200341e0046a200341d0036a108104200341b0016a200341e0046a418c01109a051a200e4101360210200e2025360214024020032d00f0054109470d00024020032802f405220528020441ffffffff0371450d002005280200102a20032802f40521050b2005102a0b024020032d0080064109470d0002402021280200220528020441ffffffff0371450d002005280200102a20032802840621050b2005102a0b024020032d0090064109470d0002402022280200220528020441ffffffff0371450d002005280200102a20032802940621050b2005102a0b024020032d00a0064109470d000240200341f0056a41346a280200220528020441ffffffff0371450d002005280200102a20032802a40621050b2005102a0b024020032d00b0064109470d000240202b280200220528020441ffffffff0371450d002005280200102a20032802b40621050b2005102a0b024020032d00c0064109470d0002402023280200220528020441ffffffff0371450d002005280200102a20032802c40621050b2005102a0b024020032d00d0064109470d0002402012280200220528020441ffffffff0371450d002005280200102a20032802d40621050b2005102a0b024020032d00e0064109470d0002402001280200220528020441ffffffff0371450d002005280200102a20032802e40621050b2005102a0b024020032d00f0064109470d0002402013280200220528020441ffffffff0371450d002005280200102a20032802f40621050b2005102a0b024020032d0080074109470d000240202c280200220528020441ffffffff0371450d002005280200102a20032802840721050b2005102a0b024020032d0090074109470d000240202d280200220528020441ffffffff0371450d002005280200102a20032802940721050b2005102a0b024020032d00a0074109470d000240202e280200220528020441ffffffff0371450d002005280200102a20032802a40721050b2005102a0b024020032d00b0074109470d000240202f280200220528020441ffffffff0371450d002005280200102a20032802b40721050b2005102a0b024020032d00c0074109470d0002402030280200220528020441ffffffff0371450d002005280200102a20032802c40721050b2005102a0b024020032d00d0074109470d0002402031280200220528020441ffffffff0371450d002005280200102a20032802d40721050b2005102a0b200a4280808080808c0184210a202541016a21252027202a470d080c090b200741081037000b200541081037000b411041081037000b200541011037000b200541011037000b411041081037000b0240200b450d00200b417f6a210b200d20084102746a4194036a21050c010b0b0b4198ebc5004180011050000b02402024450d002016102a0b200341f0056a200341b0016a418c01109a051a200341e0046a200341f0056a10fe030240200341e0046a41106a2802002205450d0020032802e8042228200541306c6a212a0340024020282d000041786a220541024b0d0002400240024020050e03000102000b202828020c2205450d0220282802042208200541146c6a210c03400240200828020c0d002008280210210d200341e0006a21052003280264210e03402005280200220b41086a2107200b2f010622244102742105417f210902400340024020050d00202421090c020b20072802002106200941016a21092005417c6a2105200741046a21070240417f2006200d472006200d4b1b41016a0e03020001020b0b0240200b41346a20094105746a2205280210450d00200820052802143602100c030b4198ecc50041351050000b200e450d01200e417f6a210e200b20094102746a4194036a21050c000b0b200841146a2208200c470d000c030b0b20282802042106200341e0006a21052003280264210b03402005280200220d41086a2107200d2f0106220e4102742105417f210802400340024020050d00200e21080c020b20072802002109200841016a21082005417c6a2105200741046a21070240417f2009200647200920064b1b41016a0e03020001020b0b0240200d41346a20084105746a2205280210450d00202820052802143602040c040b4198ecc50041351050000b200b450d02200b417f6a210b200d20084102746a4194036a21050c000b0b202828020c2205450d00202828020422272005411c6c6a21260340024020272802182205450d002027280210220e20054102746a21250340200e220c41046a210e200c2802002106200341e0006a21052003280264210b03402005280200220d41086a2107200d2f010622244102742105417f2108024002400340024020050d00202421080c020b20072802002109200841016a21082005417c6a2105200741046a21070240417f2009200647200920064b1b41016a0e03020001020b0b0240200d41346a20084105746a2205280210450d00200c20052802143602000c020b4198ecc50041351050000b200b450d00200b417f6a210b200d20084102746a4194036a21050c010b0b200e2025470d000b0b2027411c6a22272026470d000b0b202841306a2228202a470d000b0b200341ec046a290200210a20032802e004210520032902e404213220032802602003280264200328026810da04200041106a200a370200200041086a203237020020002005360204200041003602002011450d1c2010102a200424000f0b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41012128410021140c080b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41002128410121140c040b200541cc006a28020021050c020b2005413c6a2108200541386a28020021050c010b200541286a2108200541246a28020021050b41002114410021280b2007212a0b2003200536027c02402005200f490d002003410136028406200342023702f40520034188ebc5003602f005200341013602d4032003200341d0036a360280062003200341fc006a3602d003200341e0046a200341f0056a103320032902e404220a422088a7210820032802e0042125200aa7211a0c0a0b201020054102746a2802002207450d050240024020262024460d0020242115202621240c010b202441016a22092024490d10202441017422062009200620094b1b221541ffffffff03712015470d10201541027422094100480d100240024020240d002009102821160c010b201620244102742009102c21160b2016450d020b201620244102746a2005360200200341f0056a200328027c220b200341c8006a10db0420032802f805211a20032802f4052125024020032802f00522194101470d0020032802fc052108201521240c0a0b20252802082205417f4c0d002025280200210920252d000c210602400240024020050d004100210e410121240c010b2005210e200510282224450d010b202420092005109a05210920032005360288012003200e360284012003200936028001200320063a008c01200320252d000d3a008d0120034100360290012003200328027c360298012003200736029c010240024002402003280270220741f8b9c000460d00200328027421270c010b20214200370100201b41206a420037010020224200370100201b41106a4200370100202b4200370100201b4200370100200341f0056a410041e0021099051a41940310282207450d014100212720074100360200200720032903e0043702042007410c6a200341e0046a41086a290300370200200741146a200341e0046a41106a2903003702002007411c6a200341e0046a41186a290300370200200741246a200341e0046a41206a2903003702002007412c6a200341e0046a41286a290300370200200741346a200341f0056a41e002109a051a20034100360274200320073602700b202641016a2126034020072f0106221841027421244100210541142106417f210902400340024020242005470d00201821090c020b200720056a210e200941016a2109200641206a2106200541046a21050240417f200e41086a280200220e200b47200e200b4b1b41016a0e03020001020b0b200720066a2205290200210a2005200329038001370200200541186a200329039801370200200541106a220729020021322007200329039001370200200541086a200329038801370200203242ffffffff0f83420285500d08200a42808080807083500d08200aa7102a0c080b02402027450d002027417f6a2127200720094102746a4194036a28020021070c010b0b2003200328027841016a360278200329039801210a20032903900121322003290388012133200329038001213420072f01062206410b490d0420214200370100201b41206a2235420037010020224200370100201b41106a22364200370100202b4200370100201b4200370100200341f0056a410041e0021099051a024041940310282205450d0020054100360200200520032903e0043702042005410c6a200341e0046a41086a222c290300370200200541146a200341e0046a41106a222d2903003702002005411c6a200341e0046a41186a222e290300370200200541246a200341e0046a41206a22372903003702002005412c6a200341e0046a41286a2238290300370200200541346a200341f0056a41e002109a05210e200341f0056a41086a2227200741fc016a290200370300200341f0056a41106a221820074184026a290200370300200341f0056a41186a22232007418c026a290200370300200320072902f4013703f00520072802202139200541086a200741246a20072f010641796a2206410274109a052124200e20074194026a2006410574109a05210e200741063b0106200520063b0106202e2023290300370300202d2018290300370300202c2027290300370300200320032903f0053703e0040240024020094107490d0020242009417a6a22134102746a2024200941796a22014102746a2209200641ffff037120016b410274109b051a2009200b360200200e20134105746a200e20014105746a2209200541066a22062f010020016b410574109b051a200941186a200a37020020092032370210200920333702082009203437020020062f0100210e0c010b200741086a2206200941016a22244102746a200620094102746a2201200741066a22062f0100220e20096b2213410274109b051a2001200b360200200741346a220b20244105746a200b20094105746a22092013410574109b051a200941186a200a3702002009203237021020092033370208200920343702000b2006200e41016a3b0100200341d0036a41186a222f202e290300220a370300200341d0036a41106a2230202d2903002232370300200341d0036a41086a2231202c2903002233370300200341b0016a41186a223a200a370300200341b0016a41106a223b2032370300200341b0016a41086a223c2033370300200320032903e004220a3703d0032003200a3703b00102402007280200220e0d00200521090c070b20072f010421012005213d0340200341c0026a41186a223e203a290300370300200341c0026a41106a223f203b290300370300200341c0026a41086a2240203c290300370300200320032903b0013703c002200141ffff0371210b02400240024002400240200e2f01062205410b490d0020214200370100203542003701002022420037010020364200370100202b4200370100201b42003701002031202c2903003703002030202d290300370300202f202e290300370300200341d0036a41206a22052037290300370300200341d0036a41286a22072038290300370300200320032903e0043703d003200341f0056a41004190031099051a41c40310282209450d0320094100360200200920032903d0033702042009410c6a2031290300370200200941146a20302903003702002009411c6a202f290300370200200941246a20052903003702002009412c6a2007290300370200200941346a200341f0056a419003109a052107200e41206a28020021412023200e418c026a2902003703002018200e4184026a2902003703002027200e41fc016a2902003703002003200e41f4016a2902003703f005200941086a200e41246a200e2f0106220641796a2205410274109a0521422007200e4194026a2005410574109a05214320094194036a200e41b0036a2006417a6a2224410274109a052113200e41063b0106200920053b010602402024450d00410021052013210703402007280200220620053b010420062009360200200741046a21072024200541016a2205470d000b0b202e2023290300220a370300202d20182903002232370300202c20272903002233370300200320032903f00522343703e0042023200a3703002018203237030020272033370300200320343703f005200141ffff037122074107490d012042200b417a6a220641027422246a2042200b41796a22054102746a220720092f010620056b410274109b051a20072039360200204320064105746a204320054105746a220720092f010620056b410574109b051a200741186a203e290300370200200741106a203f290300370200200741086a2040290300370200200720032903c002370200200920092f010641016a22073b0106200b410274220120136a416c6a201320246a2224200741ffff0371220b20066b410274109b051a2024203d360200200b2006490d02200920016a41fc026a2107034020072802002206200541016a22053b010420062009360200200741046a21072005200b490d000c030b0b200e41086a2207200b41016a220941027422066a2007200b41027422246a22072005200b6b2227410274109b051a20072039360200200e41346a220720094105746a2007200b4105746a22072027410574109b051a200741186a203e290300370200200741106a203f290300370200200741086a2040290300370200200720032903c002370200200e200541016a22053b01062024200e4194036a22076a41086a200720066a2207200541ffff0371220620096b410274109b051a2007203d360200200b20064f0d0c200e2009417f6a22054102746a4198036a2107034020072802002209200541016a22053b01042009200e360200200741046a210720052006490d000c0d0b0b200e41086a2205200b41016a222441027422066a2005200b41027422016a2205200e2f01062213200b6b2242410274109b051a20052039360200200e41346a220520244105746a2005200b4105746a22052042410574109b051a200541186a203e290300370200200541106a203f290300370200200541086a2040290300370200200520032903c002370200200e201341016a22053b01062001200e4194036a22136a41086a201320066a2213200541ffff0371220620246b410274109b051a2013203d360200200720064f0d00200e20016a4198036a2105034020052802002207200b41016a220b3b01042007200e360200200541046a21052006200b470d000b0b203a2023290300370300203b2018290300370300203c2027290300370300200320032903f0053703b001200e28020022050d01204121390c090b41c40341041037000b200e2f010421012005210e204121392009213d0c000b0b41940341041037000b41940341041037000b200541011037000b1036000b200941041037000b200741086a2205200941016a220e4102746a200520094102746a2205200620096b2224410274109b051a2005200b360200200741346a2205200e4105746a200520094105746a22052024410574109b051a200541186a200a3702002005203237021020052033370208200520343702002007200641016a3b01060c010b20214200370100203542003701002022420037010020364200370100202b4200370100201b42003701002031202c2903003703002030202d290300370300202f202e290300370300200341d0036a41206a22072037290300370300200341d0036a41286a22062038290300370300200320032903e0043703d003200341f0056a41004190031099051a41c40310282205450d0220054100360200200520032903d0033702042005410c6a2031290300370200200541146a20302903003702002005411c6a202f290300370200200541246a20072903003702002005412c6a2006290300370200200541346a200341f0056a419003109a05210b20052003280270220736029403200320053602702003200328027441016a36027420072005360200200741003b0104200b20052f010622064105746a220720032903b001370200200741186a203a290300370200200741106a203b290300370200200741086a203c290300370200200520064102746a41086a203936020020054194036a200641016a22074102746a2009360200200520073b0106200920073b0104200920053602000b02402019450d00201a450d002025102a0b201521240b202a2107202841ff01710e03010205010b41c40341041037000b410021050c040b410221050c030b20032802702003280274200328027810da0402402024450d002016102a0b02402020450d00202041306c2107201221050340200510dc04200541306a2105200741506a22070d000b0b0240200341d4006a280200450d002012102a0b2000202536020420004101360200200041086a2008ad422086201aad843702002011450d042010102a200424000f0b201f21170b410121050c000b0b024020012802102205450d0020012802082103200541306c21050340200310dc04200341306a2103200541506a22050d000b0b2001410c6a280200450d002001280208102a0b200424000f0b1031000bfc8c0204117f017e0b7f017e230041e0006b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000e100100021817161514130d0b0c09080706010b200141186a2802002104200141146a2802002105200141106a28020021062001410c6a2802002107200141086a2802002108200141046a28020021090240200241046a280200200241086a280200220a460d002002280200210b0c1e0b200a41016a220b200a490d1a200a410174220c200b200c200b4b1b220c4100480d1a02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d042002200b360200200241046a200c360200200241086a280200210a0c1d0b2001410c6a280200210b200141086a2802002105200141046a280200210420012d0001210d02400240200241046a280200200241086a280200220a460d002002280200210c0c010b200a41016a220c200a490d1a200a4101742206200c2006200c4b1b22064100480d1a02400240200a0d0020061028210c0c010b2002280200200a2006102c210c0b200c450d032002200c360200200241046a2006360200200241086a280200210a0b200241086a2206200a41016a360200200c200a6a200d3a000002400240200241046a280200220c2006280200220a6b200b490d002002280200210c0c010b200a200b6a220d200a490d1a200c410174220a200d200a200d4b1b220a4100480d1a02400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d022002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2004200b109a051a4100210b4101210d024020050d004101210c0c270b2004102a4101210c0c260b2001410c6a2802002106200141086a280200210e200141046a280200210f024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d1a200a410174220c200b200c200b4b1b220c4100480d1a02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41013a0000200f20064104746a21104100210c4100210b41002105410121042006210a024003400240200b2005470d00200c200b41016a220d200c200d4b1b22054100480d1c02400240200c0d002005102821040c010b2004200b2005102c21040b2004450d020b2004200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b024020060d00200f21080c190b200f210a02400340200a41106a2108200a2d000d22114105460d1a200a2d000c210c200a2802082109200a2802042112200a28020021130240024002400240024002402005200b470d00200b41016a220a200b490d22200b410174220d200a200d200a4b1b22054100480d2202400240200b0d002005102821040c010b2004200b2005102c21040b2004450d010b2004200b6a200c3a0000200b41016a210a200b410174220b41046a2107200b41026a210c2009210b0340200721060240200a2005470d00200a41016a220d200a490d23200c200d200c200d4b1b22054100480d2302400240200a0d002005102821040c010b2004200a2005102c21040b2004450d030b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200641026a2107200c41026a210c200a41016a210a200d210b200d0d000b0240024020090d00200a210b0c010b4100210c0340200a200c6a210b41fc00210d02400240024002402013200c6a2d00000e050200010305020b41fe00210d0c020b41fd00210d0c010b41ff00210d0b0240200b2005470d00200b41016a2205200b490d2420062005200620054b1b22054100480d2402400240200b0d002005102821040c010b2004200b2005102c21040b2004450d050b2004200a6a200c6a200d3a0000200641026a21062009200c41016a220c470d000b200a200c6a210b0b20120d030c040b200541011037000b200541011037000b200541011037000b2013102a0b4100210a0240024020114104460d0002402005200b470d00200b41016a220a200b490d1f200b410174220c200a200c200a4b1b22054100480d1f02400240200b0d002005102821040c010b2004200b2005102c21040b2004450d020b2004200b6a41013a0000200b41016a210b201141077141ff0073210a0b02402005200b470d00200b41016a220c200b490d1e200b410174220d200c200d200c4b1b22054100480d1e02400240200b0d002005102821040c010b2004200b2005102c21040b2004450d030b2004200b6a200a3a0000200b41016a210b2008210a20082010470d010c1c0b0b200541011037000b200541011037000b200541011037000b200c41011037000b200a41011037000b200641011037000b200c41011037000b200141286a2802002113200141246a280200210f200141206a28020021082001411c6a2802002107200141186a2802002112200141146a28020021092001410c6a2902002114200141086a2802002110200141046a28020021110240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d27200a410174220c200b200c200b4b1b220c4100480d2702400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41003a0000200341dc006a410036020020034201370254200320023602502014422088a7210d4100210a4100210b2014a72206210c034002400240200a200b460d002003280254210a0c010b200a41016a2204200a490d28200a41017422052004200520044b1b22044100480d2802400240200a0d0020041028210a0c010b2003280254200a2004102c210a0b200a450d03200320043602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c41077622041b3a00002003280258210a200328025c210b2004210c20040d000b02400240200a200b6b2006490d00200328025421040c010b200b20066a220c200b490d27200a4101742204200c2004200c4b1b220c4100480d2702400240200a0d00200c102821040c010b2003280254200a200c102c21040b2004450d032003200c36025820032004360254200c210a0b2003200b20066a220c36025c2004200b6a20112006109a051a02402010450d002011102a0b034002400240200a200c460d002003280254210a0c010b200a41016a220b200a490d28200a4101742204200b2004200b4b1b220b4100480d2802400240200a0d00200b1028210a0c010b2003280254200a200b102c210a0b200a450d052003200b3602582003200a3602540b2003200c41016a36025c200a200c6a200d41807f72200d41ff0071200d410776220b1b3a00000240200b450d002003280258210a200328025c210c200b210d0c010b0b4101211102402009450d002007210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d29200a410174220d200c200d200c4b1b220d4100480d2902400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d072003200d3602582003200c3602540b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2007490d002003280254210b0c010b200a20076a220c200a490d28200b410174220d200c200d200c4b1b220c4100480d2802400240200b0d00200c1028210b0c010b2003280254200b200c102c210b0b200b450d072003200c3602582003200b3602540b2003200a20076a36025c200b200a6a20092007109a051a410021112012450d002009102a0b200820134104746a21062013210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d28200a410174220d200c200d200c4b1b220d4100480d2802400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d082003200d3602582003200c3602540b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b2008210402402013450d00411021072008210403402004220b41106a2104200b280200220c4108460d01200b410c6a2802002102200b41086a280200210a200b280204210b024002400240024002400240024002400240200c0e080001020304050607000b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d31200c4101742205200d2005200d4b1b22054100480d3102400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d12200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41003a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d32200c4101742205200d2005200d4b1b22054100480d3202400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d14200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d32200b410174220d200c200d200c4b1b220d4100480d3202400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d152003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c080b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d30200c4101742205200d2005200d4b1b22054100480d3002400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d14200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41013a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d31200c4101742205200d2005200d4b1b22054100480d3102400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d16200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d31200b410174220d200c200d200c4b1b220d4100480d3102400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d172003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c070b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2f200c4101742205200d2005200d4b1b22054100480d2f02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d16200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41023a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d30200c4101742205200d2005200d4b1b22054100480d3002400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d18200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d30200b410174220d200c200d200c4b1b220d4100480d3002400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d192003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c060b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2e200c4101742205200d2005200d4b1b22054100480d2e02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d18200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41033a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2f200c4101742205200d2005200d4b1b22054100480d2f02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1a200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2f200b410174220d200c200d200c4b1b220d4100480d2f02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d1b2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10eb0420032d0000220a411f460d0420032f000120032d000341107472210d0c280b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2d200c4101742205200d2005200d4b1b22054100480d2d02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1a200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41043a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2e200c4101742205200d2005200d4b1b22054100480d2e02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1c200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2e200b410174220d200c200d200c4b1b220d4100480d2e02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d1d2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10eb0420032d0000220a411f460d0320032f000120032d000341107472210d0c270b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2c200c4101742205200d2005200d4b1b22054100480d2c02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1c200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41053a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2d200c4101742205200d2005200d4b1b22054100480d2d02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1e200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2d200b410174220d200c200d200c4b1b220d4100480d2d02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d1f2003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b20032002200341d0006a10eb0420032d0000220a411f460d0220032f000120032d000341107472210d0c260b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2b200c4101742205200d2005200d4b1b22054100480d2b02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d1e200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41063a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2c200c4101742205200d2005200d4b1b22054100480d2c02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d20200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2c200b410174220d200c200d200c4b1b220d4100480d2c02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d212003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000c020b0b024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2a200c4101742205200d2005200d4b1b22054100480d2a02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d20200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a41073a00000340024002402003280258200328025c220c460d002003280254210d0c010b200c41016a220d200c490d2b200c4101742205200d2005200d4b1b22054100480d2b02400240200c0d0020051028210d0c010b2003280254200c2005102c210d0b200d450d22200320053602582003200d360254200328025c210c0b2003200c41016a36025c200d200c6a200b41807f72200b41ff0071200b410776220c1b3a0000200c210b200c0d000b0340024002402003280258200328025c220b460d002003280254210c0c010b200b41016a220c200b490d2b200b410174220d200c200d200c4b1b220d4100480d2b02400240200b0d00200d1028210c0c010b2003280254200b200d102c210c0b200c450d232003200d3602582003200c360254200328025c210b0b2003200b41016a36025c200c200b6a200a41807f72200a41ff0071200a410776220b1b3a0000200b210a200b0d000b0b200741106a210720042006470d000b200621040b0240034020062004460d012004280200210a200441106a2104200a4108470d000b0b0240200f450d002008102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b0340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d28200a4101742206200c2006200c4b1b22064100480d2802400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d212004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d27200b410174220a200c200a200c4b1b220a4100480d2702400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d212004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021104101210d2009450d222011450d222012450d222009102a0c220b200c41011037000b200441011037000b200c41011037000b200b41011037000b200d41011037000b200c41011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200541011037000b200541011037000b200d41011037000b200641011037000b200a41011037000b20032903082114200328020421042013410474210c02400340200c2007460d01200820076a210b200741106a2107200b2802004108470d000b0b0240200f450d002008102a0b02402003280258450d002003280254102a0b02402009450d002011450d002012450d002009102a0b200a411f470d17410021104101210d0b4101210b4101210c410121044101210641012105410121074101210241012112410121084101210941012113410121110c3a0b2001412c6a280200210e200141286a2802002115200141246a2802002111200141206a28020021162001411c6a2802002117200141186a2802002118200141146a28020021102001410c6a2902002114200141086a2802002119200141046a28020021120240024002400240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d14200a410174220c200b200c200b4b1b220c4100480d1402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b4101210d200241086a200a41016a36020041002109200b200a6a41003a0000024041041028220f450d00200f41eec2b5ab063600000240024002400240024020120d00410021044100211a0c010b410121074100210a410021062014a72209210b034002400240200a2006460d00200a21082006210c0c010b200a41016a220c200a490d1a200a410174220d200c200d200c4b1b22084100480d1a02400240200a0d002008102821070c010b2007200a2008102c21070b02402007450d00200a210c2008210a0c010b200841011037000b2007200c6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41016a2106200d210b200d0d000b02400240024002400240200820066b20094f0d00200620096a220a2006490d1d2008410174220b200a200b200a4b1b220a4100480d1d0240024020080d00200a102821070c010b20072008200a102c21070b2007450d01200a21080b200720066a20122009109a051a02402019450d002012102a0b41011028220d450d07200d41003a0000410221054101210a41012104200620096a2213210b03400240200a2004470d002005200a41016a2204200520044b1b22044100480d1e200d200a2004102c220d450d080b200d200a6a200b41807f72200b41ff0071200b41077622061b3a0000200541026a2105200a41016a210a2006210b20060d000b2004200a6b20134f0d03200a20136a220b200a490d1c20044101742205200b2005200b4b1b220b4100480d1c20040d01200b1028210d0c020b200a41011037000b200d2004200b102c210d0b200d450d02200b21040b200d200a6a20072013109a051a4101211a2009200c6a200a6a41016a21092008450d002007102a0b0240024002400240024020100d004101211b0c010b4100211b20034100360240200342013703382003410c6a2017360200200341086a201836020020032010360204200320144220883e0200200341d0006a2003200341386a10f104024020032d00502213411f460d0020032f005120032d0053411074722108200341d0006a41086a290300211420032802542116200328023c0d140c150b024020042009470d00200941016a220a2009490d1c2009410174220b200a200b200a4b1b22044100480d1c0240024020090d0020041028210d0c010b200d20092004102c210d0b200d450d040b200d20096a41013a0000200941016a210a200941017441026a210c20032802402206210b03400240200a2004470d00200a41016a2204200a490d1d200c2004200c20044b1b22044100480d1d02400240200a0d0020041028210d0c010b200d200a2004102c210d0b200d450d040b200d200a6a200b41807f72200b41ff0071200b41077622051b3a0000200c41026a210c200a41016a210a2005210b20050d000b2003280238210b02402004200a6b20064f0d00200a20066a220c200a490d1c20044101742205200c2005200c4b1b220c4100480d1c0240024020040d00200c1028210d0c010b200d2004200c102c210d0b200d450d02200c21040b200d200a6a200b2006109a051a0240200328023c450d00200b102a0b2006200a6a21094100211b0b024020110d00410021050c0e0b2003410036024020034201370338410121064100210c4100210a2016210b024003400240200a200c470d00200c41016a2205200c490d1d200c41017422072005200720054b1b22054100480d1d02400240200c0d002005102821060c010b2006200c2005102c21060b2006450d022003200536023c200320063602382005210c0b2003200a41016a22073602402006200a6a200b41807f72200b41ff0071200b41077622051b3a00002007210a2005210b20050d000b2011200e4104746a21080240200e0d00201121050c0c0b201121052016450d0b200841706a211c4100210a2011211d0340201d210502400340200541046a28020022130d01200a41016a210a2008200541106a2205470d000c0f0b0b200541106a211d200a41016a211e2016417f6a2116200541086a29020021142005280200211f200328023c210c2003280240210b02400240034002400240200b200c460d00200328023821060c010b200c41016a2206200c490d20200c41017422072006200720064b1b22074100480d2002400240200c0d002007102821060c010b2003280238200c2007102c21060b2006450d022003200736023c200320063602382007210c0b2003200b41016a22073602402006200b6a200a41807f72200a41ff0071200a41077622061b3a00002007210b2006210a20060d000b20032014370308200320133602042003201f360200200341d0006a2003200341386a10f10420032d00502213411f460d010c0c0b200741011037000b201c2005460d0b201e210a20160d000c0b0b0b200541011037000b200c41011037000b200441011037000b200441011037000b200b41011037000b200441011037000b410141011037000b410441011037000b200c41011037000b20032d0053211d20032f0051211f20032802542116200329035821140240200841706a2005460d00200541106a210503402005220a41106a21050240200a2802042206450d00200a28020821070240200a410c6a280200220a450d00200a410c6c210b2006210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2007450d002006102a0b20052008470d000b0b02402015450d002011102a0b2013411f460d03201f201d41107472210841012105200328023c450d0b2003280238102a0c0b0b200541106a21050b20052008460d0003402005220a41106a21050240200a2802042206450d00200a28020821070240200a410c6a280200220a450d00200a410c6c210b2006210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2007450d002006102a0b20052008470d000b0b2015450d002011102a0b024020042009470d00200941016a220a2009490d0e2009410174220b200a200b200a4b1b22044100480d0e0240024020090d0020041028210d0c010b200d20092004102c210d0b200d450d020b200d20096a41023a0000200941016a210a200941017441026a210c20032802402206210b03400240200a2004470d00200a41016a2204200a490d0f200c2004200c20044b1b22044100480d0f02400240200a0d0020041028210d0c010b200d200a2004102c210d0b200d450d040b200d200a6a200b41807f72200b41ff0071200b41077622051b3a0000200c41026a210c200a41016a210a2005210b20050d000b2003280238210b02402004200a6b20064f0d00200a20066a220c200a490d0e20044101742205200c2005200c4b1b220c4100480d0e0240024020040d00200c1028210d0c010b200d2004200c102c210d0b200d450d04200c21040b200d200a6a200b2006109a051a0240200328023c450d00200b102a0b2006200a6a2109410121050b201a201245720d032019450d032012102a0c030b200441011037000b200441011037000b200c41011037000b02402010450d00201b4101730d0002402017450d002017410c6c210b2010210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2018450d002010102a0b2011452005720d030240200e450d002011200e4104746a21072011210603402006220541106a210602402005280204220a450d0002402005410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200541086a280200450d002005280204102a0b20062007470d000b0b2015450d032011102a0c030b2003280238102a0b410021050b0240201a201245720d002019450d002012102a0b02402010450d00201b4101730d0002402017450d002017410c6c210b2010210a03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b2018450d002010102a0b02402005201145720d000240200e450d002011200e4104746a21072011210603402006220541106a210602402005280204220a450d0002402005410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200541086a280200450d002005280204102a0b20062007470d000b0b2015450d002011102a0b2013411f460d002008410874201372210a02402004450d00200d102a0b2000200a360200200041086a2014370200200041046a2016360200200f102a0c010b200341146a2009360200200341106a20043602002003200d36020c20034284808080c0003702042003200f360200200341d0006a2003200210f504200320032900513703382003200341d0006a41086a29000037003f20032d0050220a411f460d012000200a3a000020002003290338370001200041086a200329003f3700000b410021084101210d4101210c4101210b4101210441012105410121064101210741012102410121090c1f0b410021114101210d4101210b4101210c4101210441012106410121054101210741012102410121124101210841012109410121130c380b2001410c6a2802002105200141086a2802002107200141046a28020021060240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d04200a410174220c200b200c200b4b1b220c4100480d0402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a410b3a0000200341c4006a41003602002003420137023c2003200236023820062005411c6c6a21114100210a4100210b2005210c0240034002400240200a200b460d00200328023c210a0c010b200a41016a220d200a490d06200a4101742204200d2004200d4b1b220d4100480d0602400240200a0d00200d1028210a0c010b200328023c200a200d102c210a0b200a450d022003200d3602402003200a36023c0b2003200b41016a360244200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210a2003280244210b200c210c0c010b0b2003201136025c2003200636025820032007360254200320063602502005450d02034020032006220a411c6a2206360258200a2802102207450d03200a410c6a2802002102200a41086a2802002108200a2802042105200a41146a2902002114200a280200210b024002400240024003400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d0b200a410174220d200c200d200c4b1b220d4100480d0b02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d022003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002400240024020050d00410121130c010b200320023602302003200836022c200320053602282003200341286a200341386a10e80420032d0000220a411f470d01410021130b2014a721092014422088a72204210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d0d200a410174220d200c200d200c4b1b220d4100480d0d02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d052003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280240220b2003280244220a6b2004490d00200328023c210b0c010b200a20046a220c200a490d0c200b410174220a200c200a200c4b1b220a4100480d0c02400240200b0d00200a1028210b0c010b200328023c200b200a102c210b0b200b450d052003200a3602402003200b36023c2003280244210a0b2003200a20046a360244200b200a6a20072004109a051a02402009450d002007102a0b2005450d0520130d010c050b20032d0003411074210b20032f0001210c200329030821202003280204210d02402014a7450d002007102a0b200c200b72210b200341d0006a10f60402402003280240450d00200328023c102a0b2000200b3b00012000200a3a0000200041036a200b4110763a0000200041086a2020370000200041046a200d360000410021024101210d4101210c4101210b410121044101210541012106410121070c250b02402002450d002002410474210b2005210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b2008450d032005102a0c030b200d41011037000b200d41011037000b200a41011037000b20062011470d000c030b0b200d41011037000b200c41011037000b200341d0006a10f60420032802402108200328023c21022003280238220441086a210d200441046a210520032802442207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d05200a4101742206200c2006200c4b1b22064100480d0502400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d04200b410174220a200c200a200c4b1b220a4100480d0402400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021134101210d4101210b4101210c4101210441012106410121054101210741012102410121124101210841012109410121110c390b200641011037000b200a41011037000b2001410c6a2802002106200141086a2802002107200141046a280200210d0240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d14200a410174220c200b200c200b4b1b220c4100480d1402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a410a3a0000200341246a41003602002003420137021c20032002360218200d200641186c6a210f4100210a4100210b2006210c0240034002400240200a200b460d00200328021c210a0c010b200a41016a2204200a490d16200a41017422052004200520044b1b22044100480d1602400240200a0d0020041028210a0c010b200328021c200a2004102c210a0b200a450d02200320043602202003200a36021c0b2003200b41016a360224200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280220210a2003280224210b200c210c0c010b0b2003200f3602342003200d3602302003200736022c2003200d3602282006450d0220034101722102200341026a2107024003402003200d41186a2213360230200d2802002208450d04200d41146a2802002111200d41106a2802002110200d28020c2109200d280208210c200d28020421124100210b200341003602442003420137023c2008200c4103746a21062003200341186a3602384100210a02400240034002400240200b200a460d00200328023c210b0c010b200b41016a220a200b490d1a200b410174220d200a200d200a4b1b220a4100480d1a02400240200b0d00200a1028210b0c010b200328023c200b200a102c210b0b200b450d022003200a3602402003200b36023c2003280244210a0b2003200a41016a360244200b200a6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210b2003280244210a200c210c0c010b0b024020062008470d00200821040c020b2008210a0340200a41086a2104200a2902002214422088a7220a41ff01714104460d02200a41187441187521052014a7210b02400240024003400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d0d200a410174220d200c200d200c4b1b220d4100480d0d02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d022003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024020032802402003280244220a460d00200328023c210b0c030b200a41016a220b200a490d0b200a410174220c200b200c200b4b1b220c4100480d0b02400240200a0d00200c1028210b0c010b200328023c200a200c102c210b0b200b450d012003200c3602402003200b36023c2003280244210a0c020b200d41011037000b200c41011037000b2003200a41016a360244200b200a6a2005417f73220a413f7141c00072200a2005417f4a1b3a00002004210a20042006470d000b200621040c010b200a41011037000b0240034020062004460d0120042d0004210a200441086a2104200a4104470d000b0b02402012450d002008102a0b20092011410474220a6a210c0240024002400240024020110d002009210a0c010b200a41706a210d2009210a0340200a2d0000210b2007200a41036a2d00003a00002003200a41016a2f00003b01000240200b41ac01470d00200a41106a210a0c020b200341cc006a41026a20072d000022043a0000200320032f010022053b014c200a41046a2802002106200a41086a2903002114200220053b0000200241026a20043a00002003200b3a00002003201437030820032006360204200341d0006a2003200341386a10f004024020032d00502204411f46220b450d00200d41706a210d200a41106a220a200c470d010c030b0b20032d0053210520032f0051210620032802542108200329035821140240200d450d00200a41106a210a034002400240200a2d0000220d4109460d00200d41ac01470d010c030b0240200a41046a280200220d28020441ffffffff0371450d00200d280200102a0b200d102a0b200a41106a220a200c470d000b0b02402010450d002009102a0b02402003280240450d00200328023c102a0b200b0d022006200541107472210a200341286a10f70402402003280220450d00200328021c102a0b2000200a3b0001200020043a0000200041036a200a4110763a0000200041086a2014370000200041046a2008360000410021074101210d4101210c4101210b4101210441012105410121060c230b200a200c460d00034002400240200a2d0000220b4109460d00200b41ac01470d010c030b0240200a41046a280200220b28020441ffffffff0371450d00200b280200102a0b200b102a0b200a41106a220a200c470d000b0b02402010450d002009102a0b20032802402111200328023c21092003280238210c20032802442208210b034002400240200c41086a2205280200200c410c6a2204280200220a460d00200c280204210d0c010b200a41016a220d200a490d09200a4101742206200d2006200d4b1b22064100480d0902400240200a0d0020061028210d0c010b200c280204200a2006102c210d0b200d450d03200c200d360204200520063602002004280200210a0b2004200a41016a360200200d200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402005280200220b2004280200220a6b2008490d00200c280204210b0c010b200a20086a220d200a490d08200b410174220a200d200a200d4b1b220a4100480d0802400240200b0d00200a1028210b0c010b200c280204200b200a102c210b0b200b450d04200c200b3602042005200a3602002004280200210a0b2004200a20086a360200200b200a6a20092008109a051a2011450d002009102a0b2013210d2013200f470d010c050b0b200641011037000b200a41011037000b200441011037000b200c41011037000b200341286a10f70420032802202108200328021c21022003280218220441086a210d200441046a210520032802242207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d04200a4101742206200c2006200c4b1b22064100480d0402400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d03200b410174220a200c200a200c4b1b220a4100480d0302400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021094101210d4101210b4101210c410121044101210641012105410121074101210241012112410121080c280b200641011037000b200a41011037000b1031000b2001410c6a2802002105200141086a2802002106200141046a28020021080240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d12200a410174220c200b200c200b4b1b220c4100480d1202400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41093a0000200341c4006a41003602002003420137023c2003200236023820082005411c6c6a21124100210a4100210b2005210c0240034002400240200a200b460d00200328023c210a0c010b200a41016a220d200a490d14200a4101742204200d2004200d4b1b220d4100480d1402400240200a0d00200d1028210a0c010b200328023c200a200d102c210a0b200a450d022003200d3602402003200a36023c0b2003200b41016a360244200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280240210a2003280244210b200c210c0c010b0b2003201236025c2003200836025820032006360254200320083602502005450d02034020032008220a411c6a2208360258200a2802102206450d03200a410c6a2802002102200a41086a2802002109200a2802042107200a41146a2902002114200a280200210b024002400240024003400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d19200a410174220d200c200d200c4b1b220d4100480d1902400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d022003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002400240024020070d00410121110c010b200320023602302003200936022c200320073602282003200341286a200341386a10e80420032d0000220a411f470d01410021110b20062014422088a7220b4102746a21052014a7211303400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d1b200a410174220d200c200d200c4b1b220d4100480d1b02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d052003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024020052006460d002006210403402004280200210b03400240024020032802402003280244220a460d00200328023c210c0c010b200a41016a220c200a490d1d200a410174220d200c200d200c4b1b220d4100480d1d02400240200a0d00200d1028210c0c010b200328023c200a200d102c210c0b200c450d082003200d3602402003200c36023c2003280244210a0b2003200a41016a360244200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b200441046a22042005470d000b0b02402013450d002006102a0b2007450d0520110d010c050b20032d0003411074210b20032f0001210c200329030821202003280204210d02402014a7450d002006102a0b200c200b72210b200341d0006a10f80402402003280240450d00200328023c102a0b2000200b3b00012000200a3a0000200041036a200b4110763a0000200041086a2020370000200041046a200d360000410021064101210d4101210c4101210b41012104410121050c200b02402002450d002002410474210b2007210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b2009450d032007102a0c030b200d41011037000b200d41011037000b200d41011037000b20082012470d000c030b0b200d41011037000b200c41011037000b200341d0006a10f80420032802402108200328023c21022003280238220441086a210d200441046a210520032802442207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d13200a4101742206200c2006200c4b1b22064100480d1302400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d12200b410174220a200c200a200c4b1b220a4100480d1202400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021084101210d4101210b4101210c4101210441012106410121054101210741012102410121120c250b200641011037000b200a41011037000b200141046a280200210a024002400240024002400240200241046a280200200241086a280200220b460d002002280200210c0c010b200b41016a220c200b490d13200b410174220d200c200d200c4b1b220d4100480d1302400240200b0d00200d1028210c0c010b2002280200200b200d102c210c0b200c450d012002200c360200200241046a200d360200200241086a280200210b0b200241086a200b41016a360200200c200b6a410c3a00004100210c4100210b410021064101210503400240200b2006470d00200c200b41016a220d200c200d4b1b22064100480d1402400240200c0d002006102821050c010b2005200b2006102c21050b2005450d030b2005200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b200b417f6a2109200241086a2104200241046a2107200b210c03400240024020072802002004280200220a460d002002280200210d0c010b200a41016a220d200a490d14200a4101742208200d2008200d4b1b22084100480d1402400240200a0d0020081028210d0c010b2002280200200a2008102c210d0b200d450d042002200d360200200720083602002004280200210a0b2004200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b20094d0d002002280200210c0c010b200a200b6a220d200a490d13200c410174220a200d200a200d4b1b220a4100480d1302400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d042002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2005200b109a051a4101210d2006450d052005102a0c050b200d41011037000b200641011037000b200841011037000b200a41011037000b200141046a280200210a02400240200241046a280200200241086a280200220b460d002002280200210c0c010b200b41016a220c200b490d0e200b410174220d200c200d200c4b1b220d4100480d0e02400240200b0d00200d1028210c0c010b2002280200200b200d102c210c0b200c450d022002200c360200200241046a200d360200200241086a280200210b0b200241086a200b41016a360200200c200b6a41083a00004100210c4100210b410021064101210503400240200b2006470d00200c200b41016a220d200c200d4b1b22064100480d0f02400240200c0d002006102821050c010b2005200b2006102c21050b2005450d040b2005200b6a200a41807f72200a41ff0071200a410776220d1b3a0000200c41026a210c200b41016a210b200d210a200d0d000b200b417f6a2109200241086a2104200241046a2107200b210c03400240024020072802002004280200220a460d002002280200210d0c010b200a41016a220d200a490d0f200a4101742208200d2008200d4b1b22084100480d0f02400240200a0d0020081028210d0c010b2002280200200a2008102c210d0b200d450d052002200d360200200720083602002004280200210a0b2004200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b20094d0d002002280200210c0c010b200a200b6a220d200a490d0e200c410174220a200d200a200d4b1b220a4100480d0e02400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d052002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2005200b109a051a4101210d2006450d002005102a0b4101210b4101210c0c190b200d41011037000b200641011037000b200841011037000b200a41011037000b2001410c6a2802002106200141086a280200210f200141046a28020021100240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d10200a410174220c200b200c200b4b1b220c4100480d1002400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41073a00002010200641146c6a2112410021044100210a4100210c4101210b2006210d03400240200a200c470d002004200a41016a220c2004200c4b1b220c4100480d110240024020040d00200c1028210b0c010b200b200a200c102c210b0b200b450d030b200b200a6a200d41807f72200d41ff0071200d41077622051b3a0000200441026a2104200a41016a210a2005210d20050d000b024020060d00201021080c070b201021040340200441146a2108200428020c22134104460d072004280204211120042802002109200a4101742105200441106a280200210d20042802082207210403400240200a200c470d00200a41016a220c200a490d122005200c2005200c4b1b220c4100480d1202400240200a0d00200c1028210b0c010b200b200a200c102c210b0b200b450d050b200b200a6a200441807f72200441ff0071200441077622061b3a0000200541026a2105200a41016a210a2006210420060d000b02400240200c200a6b2007490d00200c21040c010b200a20076a2204200a490d11200c41017422052004200520044b1b22044100480d1102400240200c0d0020041028210b0c010b200b200c2004102c210b0b200b450d050b200b200a6a20092007109a051a200720046b200a6a210c02402011450d002009102a0b02400240200c450d002004210c0c010b200441016a220c2004490d1120044101742205200c2005200c4b1b220c4100480d110240024020040d00200c1028210b0c010b200b2004200c102c210b0b200b450d060b200b20076a200a6a20133a00002007200a6a41016a210a03400240200a200c470d00200a41016a220c200a490d12200a4101742204200c2004200c4b1b220c4100480d1202400240200a0d00200c1028210b0c010b200b200a200c102c210b0b200b450d080b200b200a6a200d41807f72200d41ff0071200d41077622041b3a0000200a41016a210a2004210d20040d000b2008210420082012470d000c080b0b200c41011037000b200c41011037000b200c41011037000b200441011037000b200c41011037000b200c41011037000b20082012460d0003402008410c6a2802004104460d010240200841046a280200450d002008280200102a0b200841146a22082012470d000b0b0240200f450d002010102a0b200241086a2106200241046a2107200a210402400240024003400240024020072802002006280200220d460d00200228020021050c010b200d41016a2205200d490d0c200d41017422082005200820054b1b22084100480d0c02400240200d0d002008102821050c010b2002280200200d2008102c21050b2005450d0220022005360200200720083602002006280200210d0b2006200d41016a3602002005200d6a200441807f72200441ff00712004410776220d1b3a0000200d2104200d0d000b02400240200241046a2802002204200241086a280200220d6b200a490d00200228020021040c010b200d200a6a2205200d490d0b2004410174220d2005200d20054b1b220d4100480d0b0240024020040d00200d102821040c010b20022802002004200d102c21040b2004450d0220022004360200200241046a200d360200200241086a280200210d0b200241086a200d200a6a3602002004200d6a200b200a109a051a410021124101210d200c450d02200b102a0c020b200841011037000b200d41011037000b4101210b4101210c41012104410121064101210541012107410121020c1a0b2001410c6a2802002105200141086a2802002112200141046a2802002108024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d0e200a410174220c200b200c200b4b1b220c4100480d0e02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41063a0000200341dc006a41003602002003420137025420032002360250200820054104746a21134100210a4100210b2005210c034002400240200a200b460d002003280254210a0c010b200a41016a220d200a490d0f200a4101742204200d2004200d4b1b220d4100480d0f02400240200a0d00200d1028210a0c010b2003280254200a200d102c210a0b200a450d032003200d3602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280258210a200328025c210b200c210c0c010b0b200821042005450d05200541047421114100210c034002402008200c6a220b410d6a2d000022044102470d00200b41106a21040c070b200b2802002105200b41086a2802002106200b41046a2802002107200b410c6a2d00002102024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d0f200a4101742209200d2009200d4b1b22094100480d0f02400240200a0d0020091028210d0c010b2003280254200a2009102c210d0b200d450d04200320093602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a200241ff00733a0000024002402003280258200328025c220a460d002003280254210d0c010b200a41016a220d200a490d0f200a4101742202200d2002200d4b1b22024100480d0f02400240200a0d0020021028210d0c010b2003280254200a2002102c210d0b200d450d05200320023602582003200d360254200328025c210a0b2003200a41016a36025c200d200a6a20043a0000200320063602402003200736023c200320053602382003200341386a200341d0006a10e80420032d00002205411f470d052011200c41106a220c470d000c070b0b200c41011037000b200d41011037000b200941011037000b200241011037000b20032d0003210220032f0001210920032802042111200329030821140240200b41106a2013460d00200b41106a210403402004410d6a2d00004102460d01200428020421072004280200210602402004280208220a450d00200a410474210b2006210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210402402007450d002006102a0b20042013470d000b0b2002411074210a02402012450d002008102a0b2009200a72210a02402003280258450d002003280254102a0b2000200a3b0001200020053a0000200041036a200a4110763a0000200041086a2014370000200041046a2011360000410021054101210d4101210c4101210b410121040c0f0b20042013460d0003402004410d6a2d00004102460d01200428020421062004280200210502402004280208220a450d00200a410474210b2005210a03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210402402006450d002005102a0b20042013470d000b0b02402012450d002008102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d0a200a4101742206200c2006200c4b1b22064100480d0a02400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d09200b410174220a200c200a200c4b1b220a4100480d0902400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021024101210d4101210b4101210c410121044101210641012105410121070c1a0b200641011037000b200a41011037000b2001410c6a2802002107200141086a2802002108200141046a280200210602400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41053a0000200341d0006a410c6a4100360200200342013702542003200236025020062007410c6c6a2102410121044100210c4100210a2007210b03400240200a200c470d00200c41016a220d200c490d0a200c4101742205200d2005200d4b1b220d4100480d0a02400240200c0d00200d102821040c010b2004200c200d102c21040b2004450d04200d210c0b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200a41016a210a200d210b200d0d000b2003200c3602582003200a36025c200320043602542006210a2007450d012007410c6c210d4100210b0340024002402006200b6a220a41046a280200220c4102460d002003200a280200200c200a41086a280200200341d0006a10f20420032d00002204411f460d0120032f000120032d00034110747221052003290308211420032802042107200a410c6a210c200d200b6b41746a210a02400340200a450d01200a41746a210a200c280204210b200c410c6a210c200b4102470d000b0b02402008450d002006102a0b02402003280258450d002003280254102a0b200020053b0001200020043a0000200041036a20054110763a0000200041086a2014370000200041046a2007360000410021044101210d4101210c4101210b0c110b200a410c6a210a0c030b200d200b410c6a220b470d000b2002210a0c010b200c41011037000b200a410020076b410c6c6a210b024003402006200b460d01200b410c6a210b200a280204210c200a410c6a210a200c4102470d000b0b02402008450d002006102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d0a200a4101742206200c2006200c4b1b22064100480d0a02400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d09200b410174220a200c200a200c4b1b220a4100480d0902400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021074101210d4101210b4101210c4101210441012106410121050c190b200641011037000b200a41011037000b200d41011037000b2001410c6a2802002109200141086a2802002113200141046a2802002106024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d09200a410174220c200b200c200b4b1b220c4100480d0902400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41043a0000200341d0006a410c6a4100360200200342013702542003200236025020062009410c6c6a2111410121044100210c4100210a2009210b03400240200a200c470d00200c41016a220d200c490d0a200c4101742205200d2005200d4b1b220d4100480d0a02400240200c0d00200d102821040c010b2004200c200d102c21040b2004450d05200d210c0b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200a41016a210a200d210b200d0d000b2003200c3602582003200a36025c200320043602542006210a2009450d022009410c6c21084100210c03400240024002402006200c6a220b41046a28020022044102460d00200b2802002105200b41086a28020021072003280258200328025c220a460d012003280254210d0c020b200b410c6a210a0c050b200a41016a220d200a490d0a200a4101742202200d2002200d4b1b22024100480d0a02400240200a0d0020021028210d0c010b2003280254200a2002102c210d0b200d450d03200320023602582003200d3602540b2003200a41016a36025c200d200a6a41f0003a00002003200520042007200341d0006a10f204024020032d0000220d411f460d0020032f000120032d00034110747221042003290308211420032802042105200b410c6a210b2008200c6b41746a210a02400340200a450d01200a41746a210a200b280204210c200b410c6a210b200c4102470d000b0b02402013450d002006102a0b02402003280258450d002003280254102a0b200020043b00012000200d3a0000200041036a20044110763a0000200041086a2014370000200041046a20053600004100210b4101210d4101210c0c0f0b2008200c410c6a220c470d000b2011210a0c020b200c41011037000b200241011037000b200a410020096b410c6c6a210b024003402006200b460d01200b410c6a210b200a280204210c200a410c6a210a200c4102470d000b0b02402013450d002006102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d09200a4101742206200c2006200c4b1b22064100480d0902400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d08200b410174220a200c200a200c4b1b220a4100480d0802400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021054101210d4101210b4101210c41012104410121060c170b200641011037000b200a41011037000b200d41011037000b2001410c6a2802002106200141086a2802002109200141046a280200210802400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d0a200a410174220c200b200c200b4b1b220c4100480d0a02400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41033a0000200820064102746a21074100210c4100210a41002105410121042006210b03400240200a2005470d00200c200a41016a220d200c200d4b1b22054100480d0b02400240200c0d002005102821040c010b2004200a2005102c21040b2004450d030b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41026a210c200a41016a210a200d210b200d0d000b02402006450d00200821060340200a410174210c2006280200210b03400240200a2005470d00200a41016a220d200a490d0d200c200d200c200d4b1b22054100480d0d02400240200a0d002005102821040c010b2004200a2005102c21040b2004450d060b2004200a6a200b41807f72200b41ff0071200b410776220d1b3a0000200c41026a210c200a41016a210a200d210b200d0d000b200641046a22062007470d000b0b02402009450d002008102a0b200241086a2106200241046a2107200a210c03400240024020072802002006280200220b460d002002280200210d0c010b200b41016a220d200b490d0b200b4101742208200d2008200d4b1b22084100480d0b02400240200b0d0020081028210d0c010b2002280200200b2008102c210d0b200d450d052002200d360200200720083602002006280200210b0b2006200b41016a360200200d200b6a200c41807f72200c41ff0071200c410776220b1b3a0000200b210c200b0d000b02400240200241046a280200220c200241086a280200220b6b200a490d002002280200210c0c010b200b200a6a220d200b490d0a200c410174220b200d200b200d4b1b220b4100480d0a02400240200c0d00200b1028210c0c010b2002280200200c200b102c210c0b200c450d052002200c360200200241046a200b360200200241086a280200210b0b200241086a200b200a6a360200200c200b6a2004200a109a051a410021064101210d2005450d052004102a0c050b200c41011037000b200541011037000b200541011037000b200841011037000b200b41011037000b4101210b4101210c410121040c120b2001410c6a2802002106200141086a2802002117200141046a280200210e0240024002400240024002400240024002400240024002400240024002400240024002400240200241046a280200200241086a280200220a460d002002280200210b0c010b200a41016a220b200a490d14200a410174220c200b200c200b4b1b220c4100480d1402400240200a0d00200c1028210b0c010b2002280200200a200c102c210b0b200b450d012002200b360200200241046a200c360200200241086a280200210a0b200241086a200a41016a360200200b200a6a41023a0000200341dc006a41003602002003420137025420032002360250200e200641286c6a21094100210a4100210b2006210c034002400240200a200b460d002003280254210a0c010b200a41016a220d200a490d15200a4101742204200d2004200d4b1b220d4100480d1502400240200a0d00200d1028210a0c010b2003280254200a200d102c210a0b200a450d032003200d3602582003200a3602540b2003200b41016a36025c200a200b6a200c41807f72200c41ff0071200c410776220c1b3a00000240200c450d002003280258210a200328025c210b200c210c0c010b0b200e21052006450d0f200e210503402005220a41286a2105200a2d001822134104460d10200a41206a2900002114200a411c6a2800002104200a411a6a2d0000210f200a41196a2c00002110200a41146a2802002106200a41106a2802002111200a28020c2102200a2802042112200a2802002108200a2802082207210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d16200a410174220d200c200d200c4b1b220d4100480d1602400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d052003200d3602582003200c360254200328025c210a0b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2007490d002003280254210b0c010b200a20076a220c200a490d15200b410174220a200c200a200c4b1b220a4100480d1502400240200b0d00200a1028210b0c010b2003280254200b200a102c210b0b200b450d052003200a3602582003200b360254200328025c210a0b2003200a20076a36025c200b200a6a20082007109a051a02402012450d002008102a0b2006210b0340024002402003280258200328025c220a460d002003280254210c0c010b200a41016a220c200a490d16200a410174220d200c200d200c4b1b220d4100480d1602400240200a0d00200d1028210c0c010b2003280254200a200d102c210c0b200c450d072003200d3602582003200c360254200328025c210a0b2003200a41016a36025c200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b024002402003280258220b200328025c220a6b2006490d002003280254210b0c010b200a20066a220c200a490d15200b410174220a200c200a200c4b1b220a4100480d1502400240200b0d00200a1028210b0c010b2003280254200b200a102c210b0b200b450d072003200a3602582003200b360254200328025c210a0b2003200a20066a36025c200b200a6a20022006109a051a02402011450d002002102a0b0240024002400240024020130e0400010203000b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d19200a410174220c200b200c200b4b1b220c4100480d1902400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0c2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41003a00000340024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d1a200a410174220c200b200c200b4b1b220c4100480d1a02400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a200441807f72200441ff00712004410776220a1b3a0000200a2104200a0d000c040b0b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d18200a410174220c200b200c200b4b1b220c4100480d1802400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0d2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41013a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d18200a410174220c200b200c200b4b1b220c4100480d1802400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41f0003a0000200320042014a72014422088a7200341d0006a10f20420032d0000220a411f460d0220032f000120032d000341107472210d0c120b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d17200a410174220c200b200c200b4b1b220c4100480d1702400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41023a0000200320042014a72014422088a7200341d0006a10f20420032d0000220a411f460d0120032f000120032d000341107472210d0c110b024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d16200a410174220c200b200c200b4b1b220c4100480d1602400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0e2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a41033a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d16200a410174220c200b200c200b4b1b220c4100480d1602400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d0f2003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a2010417f73220a413f7141c00072200a2010417f4a1b3a0000024002402003280258200328025c220a460d002003280254210b0c010b200a41016a220b200a490d16200a410174220c200b200c200b4b1b220c4100480d1602400240200a0d00200c1028210b0c010b2003280254200a200c102c210b0b200b450d102003200c3602582003200b360254200328025c210a0b2003200a41016a36025c200b200a6a200f41ff01714100473a00000b20052009470d000c110b0b200c41011037000b200d41011037000b200d41011037000b200a41011037000b200d41011037000b200a41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b200c41011037000b2003290308211420032802042104024020052009460d000340200541186a2d00004104460d01200541106a280200210b2005410c6a280200210c0240200541046a280200450d002005280200102a0b0240200b450d00200c102a0b200541286a22052009470d000b0b02402017450d00200e102a0b02402003280258450d002003280254102a0b2000200d3b00012000200a3a0000200041036a200d4110763a0000200041086a2014370000200041046a20043600004100210c4101210d0c080b20052009460d000340200541186a2d00004104460d01200541106a280200210a2005410c6a280200210b0240200541046a280200450d002005280200102a0b0240200a450d00200b102a0b200541286a22052009470d000b0b02402017450d00200e102a0b20032802582108200328025421022003280250220441086a210d200441046a2105200328025c2207210b024002400340024002402005280200200d280200220a460d002004280200210c0c010b200a41016a220c200a490d06200a4101742206200c2006200c4b1b22064100480d0602400240200a0d0020061028210c0c010b2004280200200a2006102c210c0b200c450d022004200c36020020052006360200200d280200210a0b200d200a41016a360200200c200a6a200b41807f72200b41ff0071200b410776220a1b3a0000200a210b200a0d000b02400240200441046a280200220b200441086a280200220a6b2007490d002004280200210b0c010b200a20076a220c200a490d05200b410174220a200c200a200c4b1b220a4100480d0502400240200b0d00200a1028210b0c010b2004280200200b200a102c210b0b200b450d022004200b360200200441046a200a360200200441086a280200210a0b200441086a200a20076a360200200b200a6a20022007109a051a02402008450d002002102a0b410021044101210d4101210b4101210c0c120b200641011037000b200a41011037000b20082010460d0003402008410d6a2d00004105460d010240200841046a280200450d002008280200102a0b200841106a22082010470d000b0b0240200e450d00200f102a0b200241086a2106200241046a2107200b210c0240024003400240024020072802002006280200220a460d002002280200210d0c010b200a41016a220d200a490d04200a4101742208200d2008200d4b1b22084100480d0402400240200a0d0020081028210d0c010b2002280200200a2008102c210d0b200d450d022002200d360200200720083602002006280200210a0b2006200a41016a360200200d200a6a200c41807f72200c41ff0071200c410776220a1b3a0000200a210c200a0d000b02400240200241046a280200220c200241086a280200220a6b200b490d002002280200210c0c010b200a200b6a220d200a490d03200c410174220a200d200a200d4b1b220a4100480d0302400240200c0d00200a1028210c0c010b2002280200200c200a102c210c0b200c450d022002200c360200200241046a200a360200200241086a280200210a0b200241086a200a200b6a360200200c200a6a2004200b109a051a4100210c4101210d2005450d032004102a0c030b200841011037000b200a41011037000b1031000b4101210b0c0b0b2000200d3b00012000200a3a0000200041036a200d4110763a0000200041086a2014370000200041046a2004360000410021094101210d4101210c4101210b4101210441012105410121064101210741012102410121080c080b4101210c200241086a200a41016a3602004100210d200b200a6a41003a0000200341146a2004360200200341106a20053602002003200636020c200320073602082003200836020420032009360200200341d0006a2003200210f504200320032900513703382003200341d0006a41086a29000037003f20032d0050220a411f460d082000200a3a000020002003290338370001200041086a200329003f3700000b4101210b0b410121040b410121050b410121060b410121070b410121020b41012108410121090b20012d0000220a410f4b0d18200a0e100a0b0c0d0e0f101112181318141516170a0b4101210b4100210d4101210c0b410121040b410121060b410121050b410121070b410121020b410121120b410121080b410121090b41012113410121110c0f0b200141086a280200450d10200141046a280200102a0c100b200d450d0f0240200141086a280200450d00200141046a280200102a0b200141146a280200450d0f200141106a280200102a0c0f0b02402001410c6a280200220b450d00200141046a280200210a200b410474210b03400240200a41046a280200450d00200a280200102a0b200a41106a210a200b41706a220b0d000b0b200141086a280200450d0e2001280204102a0c0e0b200c450d0d02402001410c6a280200220b450d00200141046a280200210a200b41286c210b03400240200a41046a280200450d00200a280200102a0b0240200a41106a280200450d00200a410c6a280200102a0b200a41286a210a200b41586a220b0d000b0b200141086a280200450d0d2001280204102a0c0d0b200141086a280200450d0c200141046a280200102a0c0c0b200b450d0b200141086a280200450d0b200141046a280200102a0c0b0b2004450d0a200141086a280200450d0a200141046a280200102a0c0a0b2005450d0902402001410c6a280200220a450d00200141046a2802002204200a4104746a2105034002402004280208220b450d002004280200210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210a0240200441046a280200450d002004280200102a0b200a2104200a2005470d000b0b200141086a280200450d092001280204102a0c090b02402001410c6a280200220b450d00200141046a280200210a200b41146c210b03400240200a41046a280200450d00200a280200102a0b200a41146a210a200b416c6a220b0d000b0b200141086a280200450d082001280204102a0c080b2006450d0702402001410c6a280200220a450d00200141046a2802002204200a411c6c6a2105034002402004280204220a450d0002402004410c6a280200220b450d00200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441086a280200450d002004280204102a0b2004411c6a210a0240200441146a280200450d002004280210102a0b200a2104200a2005470d000b0b200141086a280200450d072001280204102a0c070b2007450d0602402001410c6a280200220a450d00200141046a2802002204200a41186c6a210503400240200441046a280200450d002004280200102a0b0240200441146a280200220b450d00200428020c210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441186a210a0240200441106a280200450d00200428020c102a0b200a2104200a2005470d000b0b200141086a280200450d062001280204102a0c060b2002450d05200141046a220a10f904200141086a280200450d05200a280200102a0c050b2008450d040240200141046a280200220a450d00200141086a280200450d00200a102a0b0240200141146a280200220a450d0002402001411c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200141186a280200450d002001280214102a0b200141246a2802002204450d0402402001412c6a280200220a450d002004200a4104746a210503402004220d41106a21040240200d280204220a450d000240200d410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200d41086a280200450d00200d280204102a0b20042005470d000b0b200141286a280200450d042001280224102a0c040b2009450d030240200141086a280200450d00200141046a280200102a0b0240200141146a280200220a450d00200141186a280200450d00200a102a0b200141246a280200450d03200141206a280200102a0c030b20011082040c020b410121100b2000411f3a0000024020012d0000220a410f4b0d0002400240024002400240024002400240024002400240024002400240200a0e100001020304050607080e090e0a0b0c0d000b200b450d0e200141086a280200450d0e200141046a280200102a0c0e0b200d450d0d0240200141086a280200450d00200141046a280200102a0b200141146a280200450d0d200141106a280200102a0c0d0b200c450d0c02402001410c6a280200220b450d00200141046a280200210a200b410474210b03400240200a41046a280200450d00200a280200102a0b200a41106a210a200b41706a220b0d000b0b200141086a280200450d0c2001280204102a0c0c0b2004450d0b02402001410c6a280200220b450d00200141046a280200210a200b41286c210b03400240200a41046a280200450d00200a280200102a0b0240200a41106a280200450d00200a410c6a280200102a0b200a41286a210a200b41586a220b0d000b0b200141086a280200450d0b2001280204102a0c0b0b2006450d0a200141086a280200450d0a200141046a280200102a0c0a0b2005450d09200141086a280200450d09200141046a280200102a0c090b2007450d08200141086a280200450d08200141046a280200102a0c080b2002450d0702402001410c6a280200220a450d00200141046a2802002204200a4104746a2105034002402004280208220b450d002004280200210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441106a210a0240200441046a280200450d002004280200102a0b200a2104200a2005470d000b0b200141086a280200450d072001280204102a0c070b2012450d0602402001410c6a280200220b450d00200141046a280200210a200b41146c210b03400240200a41046a280200450d00200a280200102a0b200a41146a210a200b416c6a220b0d000b0b200141086a280200450d062001280204102a0c060b2008450d0502402001410c6a280200220a450d00200141046a2802002204200a411c6c6a2105034002402004280204220a450d0002402004410c6a280200220b450d00200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441086a280200450d002004280204102a0b2004411c6a210a0240200441146a280200450d002004280210102a0b200a2104200a2005470d000b0b200141086a280200450d052001280204102a0c050b2009450d0402402001410c6a280200220a450d00200141046a2802002204200a41186c6a210503400240200441046a280200450d002004280200102a0b0240200441146a280200220b450d00200428020c210a200b410474210b03400240200a2d00004109470d000240200a41046a220d280200220c28020441ffffffff0371450d00200c280200102a200d280200210c0b200c102a0b200a41106a210a200b41706a220b0d000b0b200441186a210a0240200441106a280200450d00200428020c102a0b200a2104200a2005470d000b0b200141086a280200450d042001280204102a0c040b2013450d03200141046a220a10f904200141086a280200450d03200a280200102a0c030b2011450d020240200141046a280200220a450d00200141086a280200450d00200a102a0b0240200141146a280200220a450d0002402001411c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200141186a280200450d002001280214102a0b200141246a2802002204450d0202402001412c6a280200220a450d002004200a4104746a210503402004220d41106a21040240200d280204220a450d000240200d410c6a280200220b450d00200b410c6c210b03400240200a280200220c450d00200a41046a280200450d00200c102a0b200a410c6a210a200b41746a220b0d000b0b200d41086a280200450d00200d280204102a0b20042005470d000b0b200141286a280200450d022001280224102a0c020b2010450d010240200141086a280200450d00200141046a280200102a0b0240200141146a280200220a450d00200141186a280200450d00200a102a0b200141246a280200450d01200141206a280200102a0c010b20011082040b200341e0006a24000bb309010a7f230041b0016b2202240041002103024020012802102204450d0020012802082205200128020c460d00200128021421062001200541246a360208200241c4006a41026a2207200541036a2d00003a0000200241286a41086a2208200541106a290000370300200241286a41106a2209200541186a290000370300200241286a41186a220a200541206a280000360200200220052f00013b01442002200541086a29000037032820052d0000220b4102460d00200541046a280000210520012004417f6a360210200241086a41026a20072d00003a000020024190016a41086a200829030037030020024190016a41106a200929030037030020024190016a41186a200a280200360200200220022f01443b01082002200229032837039001024002400240200b4101460d002002418c016a41026a200241086a41026a2d00003a0000200241f0006a41086a20024190016a41086a290300370300200241f0006a41106a20024190016a41106a290300370300200241f0006a41186a20024190016a41186a2d00003a0000200220022f01083b018c0120022002290390013703700c010b200241c8006a200541067610fe01200228024821040240024020022802502005413f7122014b0d00410021010c010b2002418c016a41026a200420014105746a220141026a2d00003a0000200241f8006a2001410f6a29000037030020024180016a200141176a29000037030020024188016a2001411f6a2d00003a0000200220012f00003b018c012002200129000737037020012800032105410121010b0240200228024c450d002004102a0b20010d00410121010c010b200241ec006a41026a2002418c016a41026a2d00003a000020024190016a41086a200241f0006a41086a29030037030020024190016a41106a200241f0006a41106a29030037030020024190016a41186a200241f0006a41186a2d00003a0000200220022f018c013b016c2002200229037037039001410021010b200241e8006a41026a2204200241ec006a41026a2d00003a0000200241c8006a41086a220720024190016a41086a290300370300200241c8006a41106a220820024190016a41106a290300370300200241c8006a41186a220920024190016a41186a2d00003a0000200220022f016c3b016820022002290390013703480240024020010d002002418c016a41026a20042d00003a0000200241f0006a41086a2007290300370300200241f0006a41106a2008290300370300200241f0006a41186a20092d00003a0000200220022f01683b018c0120022002290348370370410121010c010b200641013a0000410021010b200241246a41026a22042002418c016a41026a2d00003a0000200241086a41086a2207200241f0006a41086a290300370300200241086a41106a2208200241f0006a41106a290300370300200241086a41186a2209200241f0006a41186a2d00003a0000200220022f018c013b0124200220022903703703082001450d00200020022f01243b0001200041046a2005360000200041086a2002290308370000200041036a20042d00003a0000200041106a2007290300370000200041186a2008290300370000200041206a20092d00003a0000410121030b200020033a0000200241b0016a24000bd50505067f017e047f017e027f23004180026b22022400024002400240024002402000280200220320002802044f0d00200028020c2104200141086a2105200241a0016a4102722106024003402000200341016a360200200241186a20002802082802002207109b0220022d00184101460d0120022900192108200241086a2007106c20022802080d012007280204200228020c2203490d012003417f4c0d0302400240024020030d00410121090c010b2003102e2209450d0820072802042003490d01200920072802002003109a051a2007280204220a2003490d062007200a20036b3602042007200728020020036a3602000b20022008370310024002402001280200220b41f8b9c000460d002001280204210c0c010b2006410041da001099051a200241186a41004184011099051a41e4011028220b450d074100210c200b4100360200200b41046a200241a0016a41dc00109a051a200b41e0006a200241186a418401109a051a200141003602042001200b3602000b2003ad220d422086200d84210d024002400340200b41086a2107200b2f0106220e41037421034100210a024003402003450d01200241106a20074108109c05220f450d03200341786a2103200a41016a210a200741086a2107200f417f4a0d000b200a417f6a210e0b0240200c450d00200c417f6a210c200b200e4102746a41e4016a280200210b0c010b0b2002200837022c200220053602282002200e360224200220013602202002200b36021c200241003602182002200d3702a401200220093602a001200241186a200241a0016a10bb020c010b200b200a410c6c6a220341e4006a2207280200210a2007200d370200200341e0006a22072802002103200720093602002003450d00200a450d002003102a0b200028020022032000280204490d010c030b0b2009102a0b200441013a00000b20024180026a24000f0b1036000b2003200a1044000b41e40141041037000b200341011037000bfd0e03047f027e087f230041206b2202240002400240024002400240024002400240024002400240024002400240024041a20210282203450d00200241a20236020420022003360200200341003b0000200241023602080240024020012903684202520d00024020022802044102470d00200228020041024104102c2203450d0420024104360204200220033602000b200228020041033a00022002200228020841016a3602080c010b024020022802044102470d00200228020041024104102c2203450d0420024104360204200220033602000b20022802004183013a00022002200228020841016a3602082001200210a60120022002360210200141246a200241106a10fa020240024020012903684201510d0002400240200228020420022802082203460d00200228020021040c010b200341016a22042003490d12200341017422052004200520044b1b22054100480d120240024020030d002005102821040c010b200228020020032005102c21040b2004450d072002200536020420022004360200200228020821030b2002200341016a360208200420036a41003a00000c010b200141f8006a29030020012903702206420c882207420120074201561b8021070240024020022802042204200228020822036b4102490d00200228020021040c010b200341026a22052003490d11200441017422032005200320054b1b22034100480d110240024020040d002003102821040c010b200228020020042003102c21040b2004450d072002200336020420022004360200200228020821030b2002200341026a360208200420036a2007a741047420067aa7417f6a22034101200341014b1b2203410f2003410f491b723b00000b20014190016a200210a001200220014180016a360210200241106a200210a3010b20014198016a200210eb012002280208210120024100360218200242013703102001417e6a200241106a10b4012002280208220341014d0d052002280218210520022802142108200228021021092002410036020820022802002101024002402003417e6a220a450d004102210b2005450d0d200120092d00003a00004101210c2002200228020841016a36020820054101460d0d200920056a210d200120092d00013a00012002200228020841016a3602084102210b200941026a21042005417e6a220e0d014100210e0c0b0b0240024002402002280204220320054f0d00200341017422042005200420054b1b22044100480d120240024020030d002004102821010c010b200120032004102c21010b2001450d0a20022004360204200220013602002002280208210b0c010b4100210b2005450d010b2001200b6a220320092d00003a0000024020054101470d00200b41016a210b0c010b2005417f6a2104200941016a2101200341016a21030340200320012d00003a0000200341016a2103200141016a21012004417f6a22040d000b200b20056a210b0b2002200b3602084102210b0c0b0b024002402002280204220120036b200e490d00200228020021010c010b2003200e6a220b2003490d0f20014101742203200b2003200b4b1b22034100480d0f0240024020010d002003102821010c010b200228020020012003102c21010b2001450d0820022003360204200220013602000b200120056a200141026a200a109b051a0240200520022802082201460d00200520016b210b2005417e6a2103200228020020016a210c410021010340024020032001470d002005210b0c0d0b200c20016a20042d00003a00002002200228020841016a360208200441016a2104200b200141016a2201470d000b200d20046b220e0d004100210e4101210c0c090b200e4100480d0e200e1028220c0d08200e41011037000b41a20241011037000b410441011037000b410441011037000b200541011037000b200341011037000b41e4e8c5001032000b200441011037000b200341011037000b2005210b0b0240200d2004460d00200c20042d00003a00004101210f02400240200441016a2201200d470d00200c41016a21050c010b200c41016a21032009200520046b6a21040340200320012d00003a0000200341016a2103200d200141016a2201470d000b2004450d01200c20046a21052004210f0b0240024020022802042201200a200b6a22036b200f490d00200228020021010c010b2003200f6a22042003490d06200141017422032004200320044b1b22034100480d060240024020010d002003102821010c010b200228020020012003102c21010b2001450d0520022003360204200220013602000b2001200b200f6a220d6a2001200b6a200a109b051a0240200d20022802082201460d00200228020020016a2103200b200f6a20016b2104200c2101034020052001460d01200320012d00003a00002002200228020841016a360208200141016a2101200341016a21032004417f6a22040d000b0b200d210b0b200e450d00200c102a0b200a450d010b0240200b20022802082201460d002002280200220320016a2003200b6a200a109b051a0b2002200a20016a3602080b02402008450d002009102a0b20002002290300370200200041086a200241086a280200360200200241206a24000f0b200341011037000b1031000b130020004103360204200041889fc4003602000b340020004196a6c40036020420004100360200200041146a4101360200200041106a419ca6c400360200200041086a42043702000b4001017f230041206b22022400200241186a4200370300200241106a4200370300200241086a42003703002002420037030020002002108b04200241206a24000bde0301017f024002400240024002400240410110282202450d00200220012d00003a0000200241014102102c2202450d01200220012d00013a0001200241024104102c2202450d02200220012d00023a0002200220012d00033a0003200241044108102c2202450d03200220012d00043a0004200220012d00053a0005200220012d00063a0006200220012d00073a0007200241084110102c2202450d04200220012d00083a0008200220012d00093a0009200220012d000a3a000a200220012d000b3a000b200220012d000c3a000c200220012d000d3a000d200220012d000e3a000e200220012d000f3a000f200241104120102c2202450d05200220012d00103a0010200220012d00113a0011200220012d00123a0012200220012d00133a0013200220012d00143a0014200220012d00153a0015200220012d00163a0016200220012d00173a0017200220012d00183a0018200220012d00193a0019200220012d001a3a001a200220012d001b3a001b200220012d001c3a001c200220012d001d3a001d200220012d001e3a001e200220012d001f3a001f200042a08080808004370204200020023602000f0b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000bb31102077f027e230041106b2202240020024100360208200242013703004104200210b4010240024002400240024002400240024002400240024002400240024002400240024020022802042203200228020822046b4104490d00200441046a2105200228020021030c010b200441046a22052004490d0f200341017422062005200620054b1b22064100480d0f0240024020030d002006102821030c010b200228020020032006102c21030b2003450d0120022006360204200220033602000b20022005360208200320046a41eede91ab06360000410e200210b4010240024020022802042203200228020822066b410e490d002006410e6a2104200228020021050c010b2006410e6a22042006490d0f200341017422052004200520044b1b22074100480d0f0240024020030d002007102821050c010b200228020020032007102c21050b2005450d022002200736020420022005360200200721030b20022004360208200520066a220641002900e4c740370000200641066a41002900eac7403700000240200320046b41034b0d00200441046a22062004490d0f200341017422072006200720064b1b22064100480d0f0240024020030d002006102821050c010b200520032006102c21050b2005450d0320022006360204200220053602000b2002200441046a360208200520046a410a3600000240024020022802042205200228020822046b4104490d00200228020021050c010b200441046a22032004490d0f200541017422062003200620034b1b22034100480d0f0240024020050d002003102821050c010b200228020020052003102c21050b2005450d0420022003360204200220053602000b2002200441046a360208200520046a41a3013600000240024020022802042205200228020822046b4104490d00200228020021050c010b200441046a22032004490d0f200541017422062003200620034b1b22034100480d0f0240024020050d002003102821050c010b200228020020052003102c21050b2005450d0520022003360204200220053602000b2002200441046a360208200520046a41a301360000410b200210b40141f4c7c0002104034002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0720022006360204200220033602000b2002200541016a360208200320056a20042d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0820022006360204200220033602000b2002200541016a360208200320056a200441016a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0920022006360204200220033602000b2002200541016a360208200320056a200441026a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0a20022006360204200220033602000b2002200541016a360208200320056a200441036a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0b20022006360204200220033602000b2002200541016a360208200320056a200441046a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0c20022006360204200220033602000b2002200541016a360208200320056a200441056a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0d20022006360204200220033602000b2002200541016a360208200320056a200441066a2d00003a000002400240200228020420022802082205460d00200228020021030c010b200541016a22032005490d10200541017422062003200620034b1b22064100480d100240024020050d002006102821030c010b200228020020052006102c21030b2003450d0e20022006360204200220033602000b2002200541016a360208200320056a200441076a2d00003a0000200441086a28020021060240024020022802042203200228020822056b4104490d00200228020021030c010b200541046a22072005490d10200341017422082007200820074b1b22074100480d100240024020030d002007102821030c010b200228020020032007102c21030b2003450d0f20022007360204200220033602000b2002200541046a360208200320056a20063600002004410c6a220441f8c8c000470d000b200235020821092002350200210a200241106a2400200a2009422086840f0b200641011037000b200741011037000b200641011037000b200341011037000b200341011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200741011037000b1031000b961b04057f017e037f017e230041800a6b22022400024002402001450d00200220003602180c010b200241013602180b2002200136021c200241e0076a200241186a107f024020022802e4072203450d00200241e0076a410c6a280200210120022802e807210420022802e0072100200241b0046a200241e0076a41106a41e000109a051a200241e0076a200241186a1079024020022802e007450d0020024180036a41086a2205200241e0076a41086a280200360200200220022903e00737038003200241e0076a200241b0046a41e000109a051a200241306a200241e0076a41e000109a051a200241206a41086a22062005280200360200200220022903800337032020024190016a410c6a200136020020024190016a41086a20043602002002200336029401200220003602900120024190016a41106a200241306a41e000109a05210120024188026a2006280200360200200220022903203703800220024190016a10c703024002402002280290012200450d00200241e0076a2000417f6a10f701200241e0076a20014120109c050d000240024020024188026a28020022030d004100210341042104410021010c010b024002402003ad420c7e2207422088a70d002007a722014100480d0020022802800221002001102822040d01200141041037000b1031000b200341a0026c210520034105742106200421010340200241e0076a2000108704200141086a200241e0076a41086a280200360200200120022903e0073702002001410c6a2101200041a0026a2100200541e07d6a22050d000b200641606a41057641016a21010b200220013602b804200220033602b404200220043602b004200241e0076a200241b0046a108e040240200241e0016a2201200241e0076a4120109c05450d004190fac500410e100b200141201019200241e0076a412010190b02402001200241e0076a4120109c050d0020024184026a28020021082002280280022109200228028802210520024190026a20024190016a41f000109a051a2009200541a0026c6a2100200228029002210a20092101024002402005450d00200241b0046a41f0006a21042009210102400340200241f8066a200141e800109a051a200141e8006a290300210720024180036a200141f0006a41b001109a051a20074203510d01200241b0046a200241f8066a41e800109a051a2002200737039805200420024180036a41b001109a051a200241e0076a200241b0046a10870420022802e8072105024020022802e407450d0020022802e007102a0b200241e0076a200241b0046a41a002109a051a200241003602e006200241d0066a200241e0076a2005200241e0066a10d00320022d00d0064101460d03024020022d00dc0622054102460d0020023100de06210720023100dd06210b20022802d806210620022802d406210341f19ec600410d100b02402005450d00200b100c0b2007100c2003450d0020032006100b0b200141a0026a22012000470d000b200021010c010b200141a0026a21010b20012000460d03200241f8086a2105200241e0076a41f0006a2103034020024180036a200141e800109a051a200141e8006a2903002107200241e0076a200141f0006a41b001109a051a20074203510d04200241f8066a20024180036a41e800109a051a200241b0046a200241e0076a41b001109a051a200241e0076a200241f8066a41e800109a051a200220073703c8082003200241b0046a41b001109a051a2005106a200141a0026a22012000470d000c040b0b200241106a20022f00d10620022d00d3064110747210d30320022903102107200241ec076a42c4808080d01b370200200241323602f407200241b8b9c3003602e807200220073703e007200241e0076a1032000b41a0b9c3001032000b4188b9c3001032000b02402008450d002009102a0b200241086a10e403200228020c210120022802082100200241e0076a41086a22054200370300200242003703e00741f99fc6004115200241e0076a1008200241b0046a41086a2005290300370300200220022903e0073703b00420022001410020001b3602e007200241b0046a4110200241e0076a41041007200a109e03200241e0076a10b203200220024190026a410c6a28020022033602f00620022802940221062002200241e0076a410c6a28020022013602f406024020032001470d0002402003450d0020022802e407210941002105034002400240024002400240024002400240200620056a22012d00002204200920056a22002d0000470d000240024002400240024020040e050001020304000b20012000460d09200141016a200041016a4120109c050d040c090b024020012000460d00200141016a280000200041016a280000470d040b200141106a2802002204200041106a280200470d03200141086a2802002208200041086a280200220a460d072008200a2004109c050d030c070b024020012000460d00200141016a280000200041016a280000470d030b200141106a2802002204200041106a280200470d02200141086a2802002208200041086a280200220a460d052008200a2004109c050d020c050b024020012000460d00200141016a280000200041016a280000470d020b200141106a2802002204200041106a280200470d01200141086a2802002208200041086a280200220a460d032008200a2004109c050d010c030b2001410c6a28020022042000410c6a280200470d00200141046a2802002208200041046a280200220a460d012008200a2004109c05450d010b41df86c2004114100b200241b0046a200110ec0120022802b004220420022802b8041019024020022802b404450d002004102a0b200241b0046a200010ec0120022802b004220420022802b8041019024020022802b404450d002004102a0b20012d000020002d00002204470d0520040e050403020100040b2001410c6a28020022042000410c6a280200470d04200141046a2802002201200041046a2802002200460d05200120002004109c050d040c050b024020012000460d00200141016a280000200041016a280000470d040b200141106a2802002204200041106a280200470d03200141086a2802002201200041086a2802002200460d04200120002004109c05450d040c030b024020012000460d00200141016a280000200041016a280000470d030b200141106a2802002204200041106a280200470d02200141086a2802002201200041086a2802002200460d03200120002004109c050d020c030b024020012000460d00200141016a280000200041016a280000470d020b200141106a2802002204200041106a280200470d01200141086a2802002201200041086a2802002200460d02200120002004109c050d010c020b20012000460d01200141016a200041016a4120109c05450d010b4194bac3001032000b200541246a21052003417f6a22030d000b0b024020024190026a41306a2201200241e0076a41306a22004120109c05450d004190fac500410e100b2001412010192000412010190b0240200120004120109c05450d0041acbac3001032000b024020022802ec072200450d0020022802e4072101200041246c210003400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b0240200241e8076a280200450d0020022802e407102a0b0240200228029c022200450d002002280294022101200041246c210003400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b024020024198026a280200450d00200228029402102a0b200241800a6a240042010f0b20024180036a41146a410836020020024180036a410c6a4125360200200241f8066a41146a4103360200200242033702fc06200241c8afc6003602f80620024125360284032002200241f0066a3602e0062002200241f4066a3602d006200242043703c004200242013702b404200241fcb9c3003602b004200220024180036a360288072002200241b0046a360290032002200241d0066a360288032002200241e0066a36028003200241f8066a4184bac300103e000b02402001450d00200141246c21002003210103400240024020012d0000220541034b0d0002400240024020050e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b2004450d002003102a0b200241f4076a4102360200200241bc046a4104360200200242023702e407200241bca7c4003602e007200241043602b404200241b4a7c4003602b0042002410036028403200241b8aec600360280032002200241b0046a3602f007200220024180036a3602b804200241e0076a41cca7c400103e000b8d05030b7f017e037f230041206b220224002001280200220320012802082204410c6c6a21052001280204210602400240024020040d00410421074100210841012109410021014100210a200321040c010b41012109410021084100210441042107410021014100210a2003210b0240024003400240200b280200220c0d00200b410c6a21040c040b024002400240200820046b200b41046a290200220d422088a7220e490d002004200e6a210f0c010b2004200e6a220f2004490d0420084101742210200f2010200f4b1b22104100480d040240024020080d002010102821090c010b200920082010102c21090b2009450d01201021080b200920046a200c200e109a051a02400240200a2001460d0020012110200a21010c010b200141016a22042001490d04200141017422102004201020044b1b221041ffffffff03712010470d04201041027422044100480d040240024020010d002004102821070c010b200720014102742004102c21070b2007450d030b200720014102746a200e3602000240200da7450d00200c102a0b200a41016a210a200f210420102101200b410c6a220b2005470d010c050b0b201041011037000b200441041037000b1031000b024020042005460d0003402004280200220b450d010240200441046a280200450d00200b102a0b2004410c6a22042005470d000b0b200121100b02402006450d002003102a0b200241186a22014200370300200241106a22044200370300200241086a220b42003703002002420037030020092007200a20021023200041186a2001290300370000200041106a2004290300370000200041086a200b2903003700002000200229030037000002402010450d002007102a0b02402008450d002009102a0b200241206a24000ba10301027f23004180026b22022400024002402001450d00200220003602000c010b200241013602000b20022001360204200241f8006a2002107f0240200228027c450d00200241086a200241f8006a41f000109a051a200241086a10c7030240200241086a410c6a2802002200450d00200228020c2101200041246c210003400240024020012d0000220341034b0d0002400240024020030e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b0240200241106a280200450d00200228020c102a0b20024180026a240042010f0b200241f4016a41043602002002411c6a41023602002002420237020c200241bca7c400360208200241043602ec01200241c8a8c4003602e801200241003602fc01200241b8aec6003602f8012002200241e8016a3602182002200241f8016a3602f001200241086a41cca7c400103e000be328010b7f230041d0006b220224002002410036022820024201370320024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240410410282203450d0020024284808080c00037022420022003360220200341edcad18b0636000002400240200228022420022802282203460d00200228022021040c010b200341016a22042003490d1b200341017422052004200520044b1b22054100480d1b0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0220022005360224200220043602200b2002200341016a360228200420036a41073a00004115200241206a10b40141accbc000210603402006280204210720062802082203200241206a10b4010240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d1c200541017422042008200420084b1b22044100480d1c0240024020050d002004102821050c010b200228022020052004102c21050b2005450d042002200436022420022005360220200228022821040b2002200420036a360228200520046a20072003109a051a200228022421042002280228210302400240200628020c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102821040c010b200228022020032005102c21040b2004450d072002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102821040c010b200228022020032005102c21040b2004450d072002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628020c4101460d00200241306a20062802101103002002280234210720022802382203200241206a10b4010240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d1e200541017422042008200420084b1b22044100480d1e0240024020050d002004102821050c010b200228022020052004102c21050b2005450d092002200436022420022005360220200228022821040b2002200420036a360228200520046a20072003109a051a200228024021050240200228023c4101460d0020052002280244200241206a1091040c020b200520022802482203200241206a10910402402003450d00200341d8006c21074100210403400240200520046a220341346a280200450d002003413c6a280200450d00200341386a280200102a0b0240200341c4006a280200450d00200341cc006a280200450d00200341c8006a280200102a0b2007200441d8006a2204470d000b0b2002280244450d012005102a0c010b2006280214210720062802182203200241206a10b4010240024020022802242205200228022822046b2003490d00200228022021050c010b200420036a22082004490d1d200541017422042008200420084b1b22044100480d1d0240024020050d002004102821050c010b200228022020052004102c21050b2005450d092002200436022420022005360220200228022821040b2002200420036a360228200520046a20072003109a051a200628022021030240200628021c4101460d002003200641246a280200200241206a1091040c010b20032006280228200241206a1091040b200228022421042002280228210302400240200628022c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0b2002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0b2002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628022c4101460d00200241186a200628023011030020022802182104200228021c2203200241206a10b4012003450d012003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1f20074101742205200a2005200a4b1b22054100480d1f0240024020070d002005102821070c010b200228022020072005102c21070b2007450d0e2002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1092042003200241206a1093042003412c6a2103200841546a22080d000c020b0b2006280230210420062802382203200241206a10b4012003450d002003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1e20074101742205200a2005200a4b1b22054100480d1e0240024020070d002005102821070c010b200228022020072005102c21070b2007450d0e2002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1092042003200241206a1093042003412c6a2103200841546a22080d000b0b200228022421042002280228210302400240200628023c4102470d000240024020042003460d00200228022021040c010b200341016a22042003490d1e200341017422052004200520044b1b22054100480d1e0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0f2002200536022420022004360220200228022821030b2002200341016a360228200420036a41003a00000c010b0240024020042003460d00200228022021040c010b200341016a22042003490d1d200341017422052004200520044b1b22054100480d1d0240024020030d002005102821040c010b200228022020032005102c21040b2004450d0f2002200536022420022004360220200228022821030b2002200341016a360228200420036a41013a00000240200628023c4101460d00200241106a20062802401103002002280210210420022802142203200241206a10b4012003450d012003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1f20074101742205200a2005200a4b1b22054100480d1f0240024020070d002005102821070c010b200228022020072005102c21070b2007450d122002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1093042003200241206a1093042003412c6a2103200841546a22080d000c020b0b2006280240210420062802482203200241206a10b4012003450d002003412c6c21082004411c6a21030340200341686a28020021092003416c6a2802002204200241206a10b4010240024020022802242207200228022822056b2004490d00200228022021070c010b200520046a220a2005490d1e20074101742205200a2005200a4b1b22054100480d1e0240024020070d002005102821070c010b200228022020072005102c21070b2007450d122002200536022420022007360220200228022821050b2002200520046a360228200720056a20092004109a051a200341706a200241206a1093042003200241206a1093042003412c6a2103200841546a22080d000b0b02400240200628024c4101460d00200241086a20062802501103002002280208210b200228020c2203200241206a10b4012003450d01200341386c210c410021070340200b20076a220341046a2802002109200341086a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1f20084101742205200a2005200a4b1b22054100480d1f0240024020080d002005102821080c010b200228022020082005102c21080b2008450d142002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a200341106a2802002109200341146a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1f20084101742205200a2005200a4b1b22054100480d1f0240024020080d002005102821080c010b200228022020082005102c21080b2008450d152002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a02400240200341186a2802004101460d00200241306a2003411c6a280200200341206a28020028020c1102002002280230210920022802382204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d2120084101742205200a2005200a4b1b22054100480d210240024020080d002005102821080c010b200228022020082005102c21080b2008450d182002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a2002280234450d012009102a0c010b2003411c6a2802002109200341246a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d2020084101742205200a2005200a4b1b22054100480d200240024020080d002005102821080c010b200228022020082005102c21080b2008450d182002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a0b200341286a200241206a109304200c200741386a2207470d000c020b0b2006280250210b20062802582203200241206a10b4012003450d00200341386c210c410021070340200b20076a220341046a2802002109200341086a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1e20084101742205200a2005200a4b1b22054100480d1e0240024020080d002005102821080c010b200228022020082005102c21080b2008450d172002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a200341106a2802002109200341146a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1e20084101742205200a2005200a4b1b22054100480d1e0240024020080d002005102821080c010b200228022020082005102c21080b2008450d182002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a02400240200341186a2802004101460d00200241306a2003411c6a280200200341206a28020028020c1102002002280230210920022802382204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d2020084101742205200a2005200a4b1b22054100480d200240024020080d002005102821080c010b200228022020082005102c21080b2008450d1b2002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a2002280234450d012009102a0c010b2003411c6a2802002109200341246a2802002204200241206a10b4010240024020022802242208200228022822056b2004490d00200228022021080c010b200520046a220a2005490d1f20084101742205200a2005200a4b1b22054100480d1f0240024020080d002005102821080c010b200228022020082005102c21080b2008450d1b2002200536022420022008360220200228022821050b2002200520046a360228200820056a20092004109a051a0b200341286a200241206a109304200c200741386a2207470d000b0b200641dc006a220641b8dac000470d000b2002280228220341046a2204417f4c0d1720022802242108200228022021070240024020040d00410121050c010b200410282205450d190b2002410036023820022004360234200220053602302003200241306a10b4010240024020022802342205200228023822046b2003490d00200228023021050c010b200420036a22092004490d1b2005410174220a2009200a20094b1b22094100480d1b0240024020050d002009102821050c010b200228023020052009102c21050b2005450d1a20022009360234200220053602300b200520046a20072003109a051a200420036a210302402008450d002007102a0b200241d0006a24002003ad4220862005ad840f0b410441011037000b200541011037000b200441011037000b200541011037000b200541011037000b200441011037000b200441011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b200541011037000b1036000b200441011037000b200941011037000b1031000b9c1d010a7f230041106b220324002001200210b401024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001450d00200141d8006c2104410021050340200020056a220641046a2802002107200641086a2802002208200210b40102400240200241046a2209280200220a200241086a2201280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d18200a410174220b200c200b200c4b1b220b4100480d1802400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d032002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a200641d4006a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1820084101742207200b2007200b4b1b22074100480d180240024020080d0020071028210b0c010b200228020020082007102c210b0b200b450d042002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a000002402006410c6a2d0000220841024b0d0002400240024020080e03000102000b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1b2008410174220a200b200a200b4b1b220a4100480d1b0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d082002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41003a0000200641146a2802002107200641186a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1b200a410174220b200c200b200c4b1b220b4100480d1b02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d092002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a0c020b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a2008410174220a200b200a200b4b1b220a4100480d1a0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d092002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41013a00002006410d6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a20084101742207200b2007200b4b1b22074100480d1a0240024020080d0020071028210b0c010b200228020020082007102c210b0b200b450d0a2002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a0000200641146a2802002107200641186a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1a200a410174220b200c200b200c4b1b220b4100480d1a02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d0b2002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a200641206a2802002107200641246a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1a200a410174220b200c200b200c4b1b220b4100480d1a02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d0c2002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a2008410174220a200b200a200b4b1b220a4100480d1a0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d0d2002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a2006410e6a2d00003a00000c010b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d192008410174220a200b200a200b4b1b220a4100480d190240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d0d2002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41023a00002006410d6a2d0000210a02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1920084101742207200b2007200b4b1b22074100480d190240024020080d0020071028210b0c010b200228020020082007102c210b0b200b450d0e2002200b36020020092007360200200128020021080b2001200841016a360200200b20086a200a3a0000200641146a2802002107200641186a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d0f2002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a200641206a2802002107200641246a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d102002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a2006412c6a2802002107200641306a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d112002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a2006410e6a2d0000220841044b0d000240024002400240024020080e050001020304000b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1d2008410174220a200b200a200b4b1b220a4100480d1d0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41003a00000c040b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1c2008410174220a200b200a200b4b1b220a4100480d1c0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41013a00000c030b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1b2008410174220a200b200a200b4b1b220a4100480d1b0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41023a00000c020b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d1a2008410174220a200b200a200b4b1b220a4100480d1a0240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41033a00000c010b02400240200928020020012802002208460d002002280200210b0c010b200841016a220b2008490d192008410174220a200b200a200b4b1b220a4100480d190240024020080d00200a1028210b0c010b20022802002008200a102c210b0b200b450d162002200b3602002009200a360200200128020021080b2001200841016a360200200b20086a41043a00000b02400240200641346a2802004101460d002003200641386a2802002006413c6a28020028020c1102002003280200210720032802082208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d1a200a410174220b200c200b200c4b1b220b4100480d1a02400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d182002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a2003280204450d012007102a0c010b200641386a2802002107200641c0006a2802002208200210b401024002402009280200220a2001280200220b6b2008490d002002280200210a0c010b200b20086a220c200b490d19200a410174220b200c200b200c4b1b220b4100480d1902400240200a0d00200b1028210a0c010b2002280200200a200b102c210a0b200a450d182002200a3602002009200b3602002001280200210b0b2001200b20086a360200200a200b6a20072008109a051a0b200641c4006a20021093042004200541d8006a2205470d000b0b200341106a24000f0b200b41011037000b200741011037000b200a41011037000b200b41011037000b200a41011037000b200741011037000b200b41011037000b200b41011037000b200a41011037000b200a41011037000b200741011037000b200b41011037000b200b41011037000b200b41011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200a41011037000b200b41011037000b200b41011037000b1031000b840701087f20002802042102024002400240024002400240024020002802004101460d00200041086a2802002200200110b4012000450d01200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d08200741017422082009200820094b1b22084100480d080240024020070d002008102821070c010b200128020020072008102c21070b2007450d042001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a2000417c6a280200210520002802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d08200741017422082009200820094b1b22084100480d080240024020070d002008102821070c010b200128020020072008102c21070b2007450d052001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a200041186a2100200341686a22030d000c020b0b2000410c6a2802002200200110b4012000450d00200041186c2103200241146a2100200141086a2102200141046a21040340200041706a2802002105200041746a2802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d07200741017422082009200820094b1b22084100480d070240024020070d002008102821070c010b200128020020072008102c21070b2007450d052001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a2000417c6a280200210520002802002206200110b4010240024020042802002207200228020022086b2006490d00200128020021070c010b200820066a22092008490d07200741017422082009200820094b1b22084100480d070240024020070d002008102821070c010b200128020020072008102c21070b2007450d062001200736020020042008360200200228020021080b2002200820066a360200200720086a20052006109a051a200041186a2100200341686a22030d000b0b0f0b200841011037000b200841011037000b200841011037000b200841011037000b1031000b840401087f200028020421020240024002400240024020002802004101460d00200041086a2802002200200110b40120004103742200450d01200220006a2103200141086a2104034020022802002105200241046a2802002200200110b40102400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d06200741017422082009200820094b1b22084100480d060240024020070d002008102821070c010b200128020020072008102c21070b2007450d042001200736020020062008360200200428020021080b2004200820006a360200200720086a20052000109a051a200241086a22022003470d000c020b0b2000410c6a2802002200200110b40120004103742200450d00200220006a2103200141086a2104034020022802002105200241046a2802002200200110b40102400240200141046a22062802002207200428020022086b2000490d00200128020021070c010b200820006a22092008490d05200741017422082009200820094b1b22084100480d050240024020070d002008102821070c010b200128020020072008102c21070b2007450d042001200736020020062008360200200428020021080b2004200820006a360200200720086a20052000109a051a200241086a22022003470d000b0b0f0b200841011037000b200841011037000b1031000bd10f02037f027e230041a0076b22022400024002402001450d00200220003602080c010b200241013602080b2002200136020c200241f0046a200241086a107a02400240024002400240024002400240024002400240024020022903d8054203510d00200241106a200241f0046a41a002109a051a200241c0026a200241106a41a002109a051a200241e0046a200241c0026a10870420022802e8042101200241f0046a200241c0026a41a002109a051a20024198076a20022802e804360200200220022903e00437039007200241b0026a200241f0046a200120024190076a10d0034101410220022d00b00241014622001b220310282201450d01200241003602f804200220033602f404200220013602f0040240024020000d00200241013602f804200141003a000020022802f404210020022802f80421010240200241bc026a2d000022034102470d000240024020002001460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d06200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41003a00000c020b0240024020002001460d0020022802f00421000c010b200141016a22002001490d0e200141017422042000200420004b1b22044100480d0e0240024020010d002004102821000c010b20022802f00420012004102c21000b2000450d06200220043602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41013a00000240024020034101460d000240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d10200141017422032000200320004b1b22034100480d100240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d09200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41003a00000c010b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d09200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41013a00000240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0a200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a20022d00bd023a00000b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0e200141017422032000200320004b1b22034100480d0e0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0a200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a20022d00be023a00000c010b200241013602f804200141013a000020022d00b102417e6a22014102200141ff01714102491b41ff0171220141024b0d0002400240024020010e03000102000b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0f200141017422032000200320004b1b22034100480d0f0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0c200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41003a00000c020b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0e200141017422032000200320004b1b22034100480d0e0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0c200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41013a00000c010b0240024020022802f40420022802f8042201460d0020022802f00421000c010b200141016a22002001490d0d200141017422032000200320004b1b22034100480d0d0240024020010d002003102821000c010b20022802f00420012003102c21000b2000450d0c200220033602f404200220003602f00420022802f80421010b2002200141016a3602f804200020016a41023a0000200241b0026a410172200241f0046a10c6030b20023502f804210520023502f0042106200241a0076a240020062005422086840f0b2002411c6a4104360200200241d4026a4102360200200242023702c402200241bca7c4003602c00220024104360214200241e0a8c400360210200241003602b402200241b8aec6003602b0022002200241106a3602d0022002200241b0026a360218200241c0026a41cca7c400103e000b200341011037000b200341011037000b200441011037000b200341011037000b200341011037000b200341011037000b200341011037000b200341011037000b200341011037000b200341011037000b1031000baf0d04067f017e057f017e230041c0016b22022400200241086a10e403200228020c21032002280208210420024180016a41086a22054200370300200242003703800141f99fc600411520024180016a1008200241106a41086a2005290300370300200220022903800137031020022003410020041b3602a001200241106a4110200241a0016a41041007109801109e0320054200370300200242003703800141f99fc600411520024180016a100820024190016a41086a20052903003703002002200229038001370390012002410036021020024190016a4110200241106a1006210502400240024002400240024020022802102203417f460d002005450d00200341034d0d05200528000021062005102a20060d010b41042107410021060c010b2006ad420c7e2208422088a70d012008a722054100480d01200510282207450d022007210341002104034002400240024002400240411410282205450d00200541106a41002800eaa046360000200541086a41002900e2a046370000200541002900daa046370000200541144128102c2205450d0120052004360014200241106a41186a22094200370300200241106a41106a220a4200370300200241106a41086a220b42003703002002420037031020054118200241106a1000200241a0016a41186a2009290300370300200241a0016a41106a200a290300370300200241a0016a41086a200b290300370300200220022903103703a0012005102a20024100360210200241a0016a4120200241106a1006210a2002280210220b417f460d03200a450d032002200b3602142002200a3602102002200241106a106c02400240024020022802000d002002280214220c20022802042209490d002009417f4c0d050240024020090d00410121050c010b2009102e2205450d0220052002280210220d2009109a051a2002200c20096b3602142002200d20096a3602100b20050d020b41c4d1c300413320024180016a419cd9c3001038000b200941011037000b2009ad2208422086210e0240200b450d00200a102a0b200e2008842108200241a0016a412010090c040b411441011037000b412841011037000b1036000b41012105420021080b20032005360200200341046a20083702002003410c6a21032006200441016a2204470d000b0b200220063602182002200636021420022007360210200241a0016a200241106a108e04200241106a41186a200241a0016a41186a290300370300200241106a41106a2205200241a0016a41106a290300370300200241106a41086a200241a0016a41086a290300370300200220022903a00137031020024180016a41086a22034200370300200242003703800141e6efc200411520024180016a100820024190016a41086a20032903003703002002200229038001370390012002411036028401200220024190016a36028001200241106a20024180016a10f002200241106a10b20320024100360298012002420137039001200220024190016a3602a0012005200241a0016a10c801200241106a20024190016a10a001200220024190016a3602a001200241c0006a200241a0016a10c801200220024190016a3602a001200241e0006a200241a0016a10c801200228021421042002411c6a280200220520024190016a10b401024002402005450d00200541246c210b0340200241a0016a200410ec0120022802a001210a02400240200228029401220920022802980122056b20022802a8012203490d0020022802900121090c010b200520036a22062005490d04200941017422052006200520064b1b22054100480d040240024020090d002005102821090c010b20022802900120092005102c21090b2009450d032002200536029401200220093602900120022802980121050b2002200520036a36029801200920056a200a2003109a051a024020022802a401450d00200a102a0b200441246a2104200b415c6a220b0d000b0b200235029801210820022802900121090240200228021c2203450d0020022802142105200341246c210303400240024020052d0000220441034b0d0002400240024020040e0404000102040b2005410c6a280200450d03200541086a280200102a0c030b2005410c6a280200450d02200541086a280200102a0c020b2005410c6a280200450d01200541086a280200102a0c010b200541086a280200450d00200541046a280200102a0b200541246a21052003415c6a22030d000b0b0240200241186a280200450d002002280214102a0b200241c0016a240020084220862009ad840f0b200541011037000b1031000b200541041037000b41c4d1c300413320024180016a419cd9c3001038000bee2605017f027e0d7f027e067f230041b0036b22022400024002402001450d00200220003602080c010b200241013602080b2002200136020c2002200241086a106c024020022802000d00200228020421012002200241086a36029801200241003a0090032002420037028402200241f8b9c000360280022002200136022420024100360220200220024190036a36022c200220024198016a360228200241206a20024180026a10860420022802800221012002290284022103024020022d009003450d0020012003a72003422088a710b0020c010b2001450d002002200337021420022001360210200241206a200241106a1097040240024002400240024002400240024002400240024020022802204101460d00200241206a41086a2201290300210342002104200142003703002002420037032041feb3c300410d200241206a100820024180026a41086a200129030037030020022002290320370380022002410036022020024180026a4110200241206a100621010240024020022802202200417f460d002001450d0020004108490d01200129000021042001102a0b024041a00210282205450d0020054102360298012005420237036820052003200442dc0b7c220420032004561b3703a001200241106a21012002280214210603402001280200220741086a210020072f010622084103742101410021090240024003402001450d0141bee6c20020004108109c05220a450d02200141786a2101200941016a2109200041086a2100200a417f4a0d000b2009417f6a21080b024020060d004101210b0c080b2006417f6a2106200720084102746a41e4016a21010c010b0b200220072009410c6c6a220141e8006a280200360284022002200141e0006a28020036028002200241206a20024180026a107e02402002280220220c0d004101210b0c060b2002280224210d200241206a41086a22012802002208450d0320014200370300200242003703204193cdc2004111200241206a100820024180026a41086a200129030037030020022002290320370380022002410036022020024180026a4110200241206a1006210102400240024020022802202200417f460d002001450d002002200036029c012002200136029801200241206a20024198016a107b20022802202206450d02200229022421032000450d012001102a0c010b42002103410421060b2003a7210b2006210020062101024002400240024002402003422088a7220e450d002006200e41c4006c6a21004100210902400340200620096a22012d0000210a200241206a200141016a41c300109a051a200a4102460d0120024180026a41186a200241206a41186a29000037030020024180026a41106a200241206a41106a29000037030020024180026a41086a200241206a41086a2900003703002002200229002037038002200a4101460d03200941c4006a2109200141c4006a2000470d000b200021010c010b200141c4006a21010b0240034020002001460d0120012d00002109200141c4006a210120094102470d000b0b410121074100210f0240200b0d00410021100c020b2006102a410021100c010b20024198016a41086a220a20024180026a41086a29030037030020024198016a41106a220f20024180026a41106a29030037030020024198016a41186a221120024180026a41186a290300370300200220022903800222033703f0022002200337039801412010282207450d022007200229039801370000200741186a2011290300370000200741106a200f290300370000200741086a200a2903003700004101210f024002400240200e41c4006c41bc7f6a2009470d00410121100c010b200141c4006a2d00002109200241206a200141c5006a41c300109a051a20014188016a210a024020094102470d0041012110200a21010c020b4101210f410121100340200a21010240034020024180026a41186a220a200241206a41186a29000037030020024180026a41106a220e200241206a41106a29000037030020024180026a41086a2211200241206a41086a2900003703002002200229002037038002200941ff01714101460d0120002001460d0320012d00002109200241206a200141016a41c300109a051a200141c4006a210120094102460d040c000b0b20024198016a41086a2011290300220337030020024198016a41106a200e290300220437030020024198016a41186a200a29030022123703002002200229038002221337039801200241f0026a41186a220a2012370300200241f0026a41106a220e2004370300200241f0026a41086a22112003370300200220133703f00202402010200f470d00200f41016a2209200f490d14200f41017422142009201420094b1b221041ffffff3f712010470d14201041057422094100480d1402400240200f0d002009102821070c010b2007200f4105742009102c21070b2007450d050b2007200f4105746a220920022903f002370000200941186a200a290300370000200941106a200e290300370000200941086a2011290300370000200f41016a210f20002001460d0120012d00002109200241206a200141016a41c300109a051a200141c4006a210a20094102470d000b200141c4006a21010c010b200021010b0240034020002001460d0120012d00002109200141c4006a210120094102470d000b0b200b450d002006102a0b200c200841f0006c6a210820024180026a41106a211520024180026a41086a21144200210341042116200c210a02400340200a2802042101200a2802002100200241206a200a41086a41e800109a051a200a41f0006a210a024020010d00200a2008460d0a0340200a2802042206450d0b200a41086a280200210b0240200a410c6a2802002201450d00200141246c21002006210103400240024020012d0000220941034b0d0002400240024020090e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b200a41f0006a210a0240200b450d002006102a0b200a2008470d000c0b0b0b20024198016a200241206a41e800109a051a20022001360284022002200036028002201420024198016a41e800109a051a109801210120024190036a20024180026a10f6010240024002400240200228028002417f6a220020014f0d00200241206a200010f701200241206a20154120109c050d00200228028002221741002001417b6a2200200020014b1b490d0020024190036a20076b220641606a210e200641406a2111200641a07f6a21182007200f41057422096a210b410021010240024002400340024002400240200b200720016a22006b41e0004b0d00200f4105742001470d01410021000c060b024020062001470d0020024190036a21000c060b200020024190036a4120109c05450d05200e2001470d0120024190036a21000c050b0340024020024190036a2000470d0020024190036a21000c060b200020024190036a4120109c05450d05200041206a2100200941606a22090d000b410021000c040b200041206a221920024190036a4120109c05450d02024020112001470d0020024190036a21000c040b200041c0006a221920024190036a4120109c05450d01024020182001470d0020024190036a21000c040b200941807f6a210920014180016a2101200041e0006a20024190036a4120109c050d000b200720016a41606a21000c020b201921000c010b201921000b200241206a201710f701200241206a20024190036a4120109c05210120000d0020010d010b0240200228028c022200450d002002280284022101200041246c210003400240024020012d0000220941034b0d0002400240024020090e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b200228028802450d01200228028402102a0c010b20024190036a20024180026a10f601200241206a20024180026a41f000109a051a0240024020034220882204a722012003a7460d00200121000c010b200141016a22092001490d142004a722004101742206200920092006491bad220342f0007e2204422088a70d142004a722094100480d140240024020010d002009102821160c010b2016200141f0006c2009102c21160b2016450d020b2016200041f0006c6a200241206a41f000109a051a200241206a41186a220920024190036a41186a290300370300200241206a41106a220620024190036a41106a290300370300200241206a41086a220b20024190036a41086a29030037030020022002290390033703200240200f2010470d00200f41016a2201200f490d14200f410174220e2001200e20014b1b221041ffffff3f712010470d14201041057422014100480d1402400240200f0d002001102821070c010b2007200f4105742001102c21070b2007450d040b200342ffffffff0f83200041016aad4220868421032007200f4105746a22012002290320370000200141186a2009290300370000200141106a2006290300370000200141086a200b290300370000200f41016a210f0b200a2008470d010c0a0b0b200941041037000b200141011037000b200941011037000b412041011037000b41c4d1c300413320024190036a419cd9c3001038000b41a00241081037000b41c4d1c300413320024190036a419cd9c3001038000b2002200229022437038002419db6c300412820024180026a419cb4c3001038000b4101210b200d450d01200c102a0c010b0240200d450d00200c102a0b02402010450d002007102a0b0240200342ffffffff0f560d004101210b2003a7450d012016102a0c010b024020160d004101210b0c010b200541a00241c004102c2205450d01200541a0026a20024180026a41e800109a051a2005420237038803200520033703c003200520163602bc03200541033602b80320052002290398013703900320054198036a200241a0016a290300370300200541a0036a200241a8016a290300370300200541a8036a200241b0016a290300370300200541b0036a200241b8016a290300370300200541c8036a200241206a41f800109a051a4102210b0b200241106a210120022802142106024003402001280200220741086a210020072f010622084103742101410021090240024003402001450d0141a7c5c20020004108109c05220a450d02200141786a2101200941016a2109200041086a2100200a417f4a0d000b2009417f6a21080b2006450d022006417f6a2106200720084102746a41e4016a21010c010b0b200741e0006a2009410c6c6a22012802084104490d002001280200280000210742002103200241206a41086a2201420037030020024200370320419194c1004115200241206a100820024180026a41086a200129030037030020022002290320370380022002410036022020024180026a4110200241206a100621000240024020022802202201417f460d002002200136029c012002200036029801200241206a20024198016a10820120022802202209450d04200229022421032001450d012000102a0c010b410421090b4100210002402003422088a72201417f6a220a20014b0d00200a20014f0d002009200a4102746a2201450d00200128020020074721000b02402003a7450d002009102a0b20000d030b200b210f0c030b41c00441081037000b41c4d1c300413320024190036a419cd9c3001038000b2005200b41a0026c2201200b4101742200200b41016a220f2000200f4b1b41a0026c2200102c2205450d01200520016a20024180026a41e800109a05220142023703682001200229039801370370200141f8006a200241a0016a29030037030020014180016a200241a8016a29030037030020014188016a200241b0016a29030037030020014190016a200241b8016a2903003703002001419c016a20073602002001410d36029801200141a8016a200241206a41f800109a051a0b20022802102002280214200228021810b00220024100360288022002420137038002200f20024180026a10b401200f41a0026c210b20022802840221062002280288022101200521090340200241206a20091087042002280220210802400240200620016b20022802282207490d00200120076a2100200228028002210a0c010b200120076a22002001490d042006410174220a2000200a20004b1b220e4100480d040240024020060d00200e1028210a0c010b2002280280022006200e102c210a0b200a450d032002200e360284022002200a36028002200e21060b2002200036028802200a20016a20082007109a051a02402002280224450d002008102a0b200941a0026a210920002101200b41e07d6a220b0d000b200f41a0026c210920054198016a210103402001106a200141a0026a2101200941e07d6a22090d000b2005102a200241b0036a24002000ad422086200aad840f0b200041081037000b200e41011037000b1031000b2002418c026a4104360200200241346a410236020020024202370224200241bca7c4003602202002410436028402200241f8a8c400360280022002410036029c01200241b8aec60036029801200220024180026a360230200220024198016a36028802200241206a41cca7c400103e000bf00101067f2001280204210202400240024003402001280200220341086a210420032f01062205410374210141002106024003402001450d0141ffa0c60020044108109c052207450d03200141786a2101200641016a2106200441086a21042007417f4a0d000b2006417f6a21050b02402002450d002002417f6a2102200320054102746a41e4016a21010c010b0b20004187a1c600360204200041086a41283602000c010b200341e0006a2006410c6c6a220128020841074b0d01200041afa1c600360204200041086a41293602000b200041013602000f0b200041086a2001280200290000370300200041003602000be92c06087f017e097f027e017f027e230041b0026b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241c8006a200241106a107f02400240200228024c2203450d00200241d4006a280200210420022802502105200241c8006a200241106a1079200228024822060d0102402004450d00200441246c21002003210103400240024020012d0000220741034b0d0002400240024020070e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b2005450d002003102a0b200241dc016a4104360200200241dc006a41023602002002420237024c200241bca7c400360248200241043602d40120024194a9c4003602d0012002410036022c200241b8aec6003602282002200241d0016a3602582002200241286a3602d801200241c8006a41cca7c400103e000b200241d0006a2802002108200228024c2109200241086a200241106a106c0240024020022802080d00200228020c21012002200241106a360228200241003a0038200242003702d401200241f8b9c0003602d0012002200136024c200241003602482002200241386a3602542002200241286a360250200241c8006a200241d0016a10860420022802d001210120022902d401210a024020022d0038450d002001200aa7200a422088a710b0020c010b20010d010b200241dc016a4104360200200241dc006a41023602002002420237024c200241bca7c400360248200241043602d40120024194a9c4003602d0012002410036022c200241b8aec6003602282002200241d0016a3602582002200241286a3602d801200241c8006a41cca7c400103e000b2002200a37021c20022001360218200241013b01342002420037022c200241f8b9c000360228200241286a41086a210b024002400240024002402008450d002006200841a0026c6a210c200241d0016a410272210d2006210e024002400240024002400240024002400340200e41e8006a2903004202520d0902400240200e28029801410247220f0d00200e2903a001210a200241186a2101200228021c211002400240024002400240024002400240024002400240024002400240024002400240024003402001280200221141086a210020112f010622124103742101410021070240024003402001450d0141f7fcc50020004108109c052213450d02200141786a2101200741016a2107200041086a21002013417f4a0d000b2007417f6a21120b2010450d022010417f6a2110201120124102746a41e4016a21010c010b0b0240201141e0006a2007410c6c6a220128020841074b0d00201442808080807083422984210a41fffcc50021120c020b200a42b8178020012802002900002214510d0341c6e6c2002112413121100c020b201442808080807083421c84210a41a8fdc50021120b200aa721100b024002400240024020022d0035450d004131210141f7e6c20021000c010b2002280228200228022c200228023010b0022002420037022c200241f8b9c000360228200242e2c289abb68edbb7f400370338200241d0016a410272410041da001099051a200241c8006a41004184011099051a41e40110282213450d0420134100360200201341046a200241d0016a41dc00109a051a201341e0006a200241c8006a418401109a051a2002410036022c2002201336022820132f0106220e4103742111417f210041002101024002400340024020112001470d00200e21000c020b200241386a201320016a41086a4108109c052207450d02200141086a2101200041016a2100200741004e0d000b0b200242e2c289abb68edbb7f40037025c2002200b360258200220003602542002201336024c200241003602482002200241286a360250201041046a2200417f4c0d062000450d02200010282201450d07200241003602ac02200220013602d0012010413f4b0d03200120104102743a0000410121070c1b0b412d210141a8e7c20021000b2002200136024c2002200036024841d5e7c2004122200241c8006a41f8e7c2001038000b200241003602ac0241012100200241013602d001410110282201450d05200141033a0000200241013602ac02200220013602d001410521070c130b201041808001490d162010418080808004490d150c100b200f0d0e200e2903a0012115200241c8006a200241186a10970402400240024020022802484101470d002002350250210a200228024c21160c010b2002290350210a200241c8006a41086a220142003703002002420037034841feb3c300410d200241c8006a1008200241d0016a41086a2001290300370300200220022903483703d00120024100360248200241d0016a4110200241c8006a100621010240024020022802482200417f470d00420021170c010b024020010d00420021170c010b200041074d0d07200129000021172001102a0b02402015200a423c7c560d004100210f2015201742dc0b7c220a540d020c110b201842808080807083422584210a41f8b5c30021160b4101210f0b024020022d0035450d004131210141f7e6c20021000c080b0240200f450d002002280228200228022c200228023010b0022002420037022c200241f8b9c000360228200242f4d2b59bc7ae98b8303703380c060b20022802282111200242f4d2b59bc7ae98b830370338201141f8b9c000460d05200228022c21100c060b41e40141041037000b1036000b200041011037000b410141011037000b41c4d1c3004133200241c8006a419cd9c3001038000b200d410041da001099051a200241c8006a41004184011099051a41e40110282211450d034100211020114100360200201141046a200241d0016a41dc00109a051a201141e0006a200241c8006a418401109a051a2002410036022c200220113602280b0340201141086a210020112f010622124103742101410021070240024003402001450d01200241386a20004108109c052213450d02200141786a2101200741016a2107200041086a21002013417f4a0d000b2007417f6a21120b2010450d032010417f6a2110201120124102746a41e4016a28020021110c010b0b412d210141a8e7c20021000b2002200136024c2002200036024841d5e7c2004122200241c8006a41f8e7c2001038000b200242f4d2b59bc7ae98b83037025c2002200b360258200220123602542002201136024c200241003602482002200241286a360250200241003602d801200242013703d00141011028210102400240200f0d002001450d03200141003a000020024281808080103702d401200220013602d001200141014109102c2201450d042001200a3700012002428980808090013702d401200220013602d0010c010b2001450d04200141013a000020024281808080103702d401200220013602d001200aa72201200241d0016a10b4010240024020022802d401220720022802d80122006b2001490d0020022802d00121070c010b200020016a22132000490d14200741017422112013201120134b1b22134100480d140240024020070d002013102821070c010b20022802d00120072013102c21070b2007450d06200220133602d401200220073602d0010b2002200020016a3602d801200720006a20162001109a051a0b200241386a41086a200241d0016a41086a280200360200200220022903d001370338200241c8006a200241386a10bb022002200f3a0035200241003a0034200a2118200f450d05200241d0016a41086a200241286a41086a290300370300200220022903283703d0010c110b41e40141041037000b410141011037000b410941011037000b410141011037000b201341011037000b200e41a0026a220e200c470d010c0a0b0b200141033a0000200241013602ac022000417f6a41034b0d01200041017422074105200741054b1b22074100480d0a0b200120002007102c2201450d01200220013602d001200721000b20012010360001410521070c030b200741011037000b02400240200041034b0d00200041017422074104200741044b1b22074100480d08200120002007102c2201450d01200220013602d001200721000b20012010410274410272360000410421070c020b200741011037000b0240200041014b0d0020012000200041017422074102200741024b1b2207102c2201450d02200220013602d001200721000b41022107200120104102744101723b00000b200220073602ac0202400240200020076b2010490d00200021130c010b200720106a22132007490d05200041017422112013201120134b1b22134100480d05200120002013102c2201450d02200220013602d0010b2002200720106a3602ac02200120076a20122010109a051a2002201336023c200220022802d001360238200220022802ac02360240200241c8006a200241386a10bb0220024180023b0134200241d0016a41086a200241286a41086a290300370300200220022903283703d0010c030b200741011037000b201341011037000b200241d0016a41086a200b290300370300200220022903283703d0010b2002280218200228021c200228022010b00202402004450d00200441246c21002003210103400240024020012d0000220741034b0d0002400240024020070e0404000102040b2001410c6a280200450d03200141086a280200102a0c030b2001410c6a280200450d02200141086a280200102a0c020b2001410c6a280200450d01200141086a280200102a0c010b200141086a280200450d00200141046a280200102a0b200141246a21012000415c6a22000d000b0b02402005450d002003102a0b02402008450d00200841a0026c210020064198016a210103402001106a200141a0026a2101200041e07d6a22000d000b0b02402009450d002006102a0b2002410036025020024201370348410110282201450d022002410136024c20022002280250220041016a36025020022001360248200120006a20022d00dc013a000002400240200228024c20022802502201460d00200228024821000c010b200141016a22002001490d01200141017422072000200720004b1b22074100480d010240024020010d002007102821000c010b200228024820012007102c21000b2000450d022002200736024c20022000360248200228025021010b2002200141016a360250200020016a20022d00dd013a000020022802d801200241c8006a10b40120022802d00122072100024020022802d4012213450d002013210120072100034020002802e40121002001417f6a22010d000b0b0240024002400240024002400240024002400240024020022802d80122120d00410021010c010b200241d0016a210f41002113034002400240201320002f01064f0d0020002013410c6c6a41e0006a2111200020134103746a41086a2101201341016a21130c010b02400240200028020022010d00201542808080807083200fad84211541002107410021010c010b2000330104422086200fad842115410121070b201521142015210a02402015422088a7220020012f0106490d000340200a221442ffffffff0f83210a200741016a210720012f01042200200128020022012f01064f0d000b0b20012000410c6c6a2113200120004103746a2110200041027420016a41e8016a28020021002014a7210f02402007417f6a2201450d00034020002802e40121002001417f6a22010d000b0b201341e0006a2111201041086a2101410021130b02400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d032002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00003a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d042002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00013a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d052002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00023a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d062002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00033a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d072002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00043a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d082002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00053a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d092002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00063a000002400240200228024c20022802502207460d00200228024821100c010b200741016a22102007490d0c2007410174220e2010200e20104b1b220e4100480d0c0240024020070d00200e102821100c010b20022802482007200e102c21100b2010450d0a2002200e36024c20022010360248200228025021070b2002200741016a360250201020076a20012d00073a00002011280200211020112802082201200241c8006a10b40102400240200228024c2211200228025022076b2001490d00200228024821110c010b200720016a220e2007490d0c20114101742207200e2007200e4b1b22074100480d0c0240024020110d002007102821110c010b200228024820112007102c21110b2011450d0b2002200736024c20022011360248200228025021070b2002200720016a360250201120076a20102001109a051a2012417f6a22120d000b20022802d801210120022802d401211320022802d00121070b2002350248210a2002350250211420072013200110b002200241b0026a2400200a2014422086840f0b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200e41011037000b200741011037000b1031000b200741011037000b410141011037000b5702017f027e230041306b2202240020024101410010a80320024100360228200242013703202002200241206a36022c20022002412c6a10c8012002350228210320023502202104200241306a240020042003422086840bba48030b7f047e017f230041d00c6b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241f0066a200241106a107a024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022903d8074203510d00200241186a200241f0066a41a002109a051a200241f0026a200241186a41a002109a051a200241f0066a200241f0026a10870420022802f8062103024020022802f406450d0020022802f006102a0b200241f0066a200241f0026a41a002109a051a20024190056a200241f0066a10d10341012100024020022d0090054101470d00200220022d0093053a00bb02200220022f0091053b00b902200241013a00b8020c180b200241f0066a20024190056a41086a41d801109a051a200241086a200241c0076a220410f301024002402002290390074202520d00200241b8026a41206a22014200370300200241b8026a41186a22004280808080c000370300200241013a00e002200242043703c8022002427f3703c002200242003703b80220024190056a41206a2203420037030020024190056a41186a22054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241c8096a200241b8026a20024190056a109b04200241b8026a41286a2206200241c8096a41286a2903003703002001200241c8096a41206a2903003703002000200241c8096a41186a290300370300200241b8026a41106a2207200241c8096a41106a290300370300200241b8026a41086a2208200241c8096a41086a290300370300200220022903c8093703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241f8096a200241b8026a20024190056a109b042006200241f8096a41286a2903003703002001200241f8096a41206a2903003703002000200241f8096a41186a2903003703002007200241f8096a41106a2903003703002008200241f8096a41086a290300370300200220022903f8093703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241a80a6a200241b8026a20024190056a109b042006200241a80a6a41286a2903003703002001200241a80a6a41206a2903003703002000200241a80a6a41186a2903003703002007200241a80a6a41106a2903003703002008200241a80a6a41086a290300370300200220022903a80a3703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241d80a6a200241b8026a20024190056a109b042006200241d80a6a41286a2903003703002001200241d80a6a41206a2903003703002000200241d80a6a41186a2903003703002007200241d80a6a41106a2903003703002008200241d80a6a41086a290300370300200220022903d80a3703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241880b6a200241b8026a20024190056a109b042006200241880b6a41286a2903003703002001200241880b6a41206a2903003703002000200241880b6a41186a2903003703002007200241880b6a41106a2903003703002008200241880b6a41086a290300370300200220022903880b3703b8022003420037030020054280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241b80b6a200241b8026a20024190056a109b04200241980c6a41286a2203200241b80b6a41286a290300370300200241980c6a41206a2206200241b80b6a41206a290300370300200241980c6a41186a2205200241b80b6a41186a290300370300200241980c6a41106a2207200241b80b6a41106a290300370300200241980c6a41086a2208200241b80b6a41086a290300370300200220022903b80b3703980c2001420037030020004280808080c000370300200241013a00e002200242043703c8022002427f3703c002200242003703b802200241e80b6a200241980c6a200241b8026a109b042002419c056a2201200241e80b6a41086a290300370200200241a4056a2200200241e80b6a41106a290300370200200241ac056a2209200241e80b6a41186a290300370200200241b4056a220a200241e80b6a41206a290300370200200241bc056a220b200241e80b6a41286a290300370200200220022903e80b3702940520024198096a41286a220c200b29020037030020024198096a41206a220b200a29020037030020024198096a41186a220a200929020037030020024198096a41106a2209200029020037030020024198096a41086a220020012902003703002002200229029405370398092003200c2903003703002006200b2903003703002005200a290300370300200720092903003703002008200029030037030020022002290398093703980c418102210120022802c0074112460d010c170b20022d000c210b20022802082108200241b8026a41206a22014200370300200241b8026a41186a22004280808080c000370300200241013a00e002200242043703c8022002427f3703c002200242003703b80220024190056a41206a2205420037030020024190056a41186a22064280808080c000370300200241013a00b805200242043703a0052002427f37039805200242003703900520024198096a200241b8026a20024190056a109b04200241b8026a41286a220720024198096a41286a290300370300200120024198096a41206a290300370300200020024198096a41186a290300370300200241b8026a41106a220920024198096a41106a290300370300200241b8026a41086a220a20024198096a41086a29030037030020022002290398093703b8022005420037030020064280808080c000370300200241013a00b805200242043703a0052002427f370398052002420037039005200241c8096a200241b8026a20024190056a109b042007200241c8096a41286a2903003703002001200241c8096a41206a2903003703002000200241c8096a41186a2903003703002009200241c8096a41106a290300370300200a200241c8096a41086a290300370300200220022903c8093703b802200241b80b6a41086a22014200370300200242003703b80b41d9efc200410d200241b80b6a1008200241880b6a41086a2001290300370300200220022903b80b3703880b410021002002410036029005200241880b6a411020024190056a1006210102402002280290052205417f460d002001450d0020054104490d03200128000021002001102a0b2000ad210d427f210e02402002290390074201520d00200229039807220e4200510d04200d200241a0076a290300220f200f200d541b2210200e7c2010200f7d200e827d210e0b20024190056a41206a420037030020024190056a41186a4280808080c000370300200241bc056a2002419b0c6a280000360000200241013a00b805200242043703a0052002420037039005200220022800980c3600b90520024200200e200d7d220d200d200e561b37039805200241f8096a200241b8026a20024190056a109b04200241980c6a41286a200241f8096a41286a290300370300200241980c6a41206a200241f8096a41206a290300370300200241980c6a41186a200241f8096a41186a290300370300200241980c6a41106a200241f8096a41106a290300370300200241980c6a41086a200241f8096a41086a290300370300200220022903f8093703980c20022802b8072100411310282201450d04200141002900cef0423700002001410f6a41002800ddf042360000200141086a41002900d6f04237000020024293808080b0023702bc0b200220013602b80b200241f0066a200241b80b6a108f0120022802c00b210120022802b80b2105200241b8026a41186a22064200370300200241b8026a41106a22074200370300200241b8026a41086a22094200370300200242003703b80220052001200241b8026a1000200241e80b6a41186a2006290300370300200241e80b6a41106a2007290300370300200241e80b6a41086a2009290300370300200220022903b8023703e80b024020022802bc0b450d0020022802b80b102a0b200241003602b802200241e80b6a4120200241b8026a100621010240024020022802b8022205417f460d002001450d00024020054104490d00200128000021092001102a200920004d0d02200220022800880b3602900920022002418b0b6a28000036009309200241003a00bb0220024180063b00b902200241013a00b80220022802a80c21030240200241b00c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241ac0c6a280200450d002003102a0b20022802b40c21030240200241bc0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241b80c6a280200450d1a2003102a0c1a0b41c4d1c3004133200241c80c6a419cd9c3001038000b410021090b410c10282205450d05410410282201450d06200242043702bc02200220013602b802200241f0066a200241b8026a108f010240024020022802bc02220620022802c00222016b4104490d0020022802b80221070c010b200141046a22072001490d1a200641017422012007200120074b1b22014100480d1a0240024020060d002001102821070c010b20022802b80220062001102c21070b2007450d08200220013602bc02200220073602b80220022802c00221010b410421062002200141046a3602c002200720016a2000360000200241e80b6a41086a20022802c0022201360200200220022903b802220e3703e80b200541086a20013602002005200e370200410021010240200920004f0d00410c10282206450d09410410282201450d0a200242043702bc02200220013602b802200241f0066a200241b8026a108f010240024020022802bc02220720022802c00222016b4104490d0020022802b80221070c010b200141046a22092001490d1b200741017422012009200120094b1b22014100480d1b0240024020070d002001102821070c010b20022802b80220072001102c21070b2007450d0c200220013602bc02200220073602b80220022802c00221010b2002200141046a3602c002200720016a2000417f6a360000200241e80b6a41086a20022802c0022201360200200220022903b802220e3703e80b200641086a20013602002006200e370200410121010b20024190056a41206a42818080801037030020024190056a41186a2001360200200241a4056a2001360200200220022800880b3602900920022002418b0b6a28000036009309200241bc056a200228009309360000200241013a00b805200220053602ac05200220063602a0052002427f3703980520022008ad220e3703900520022002280290093600b905200241a80a6a200241980c6a20024190056a109b04200241980c6a41286a200241a80a6a41286a290300370300200241980c6a41206a200241a80a6a41206a290300370300200241980c6a41186a200241a80a6a41186a290300370300200241980c6a41106a200241a80a6a41106a290300370300200241980c6a41086a200241a80a6a41086a290300370300200220022903a80a3703980c200241b8026a200b4101712201200310b80320022d00b8020d14200241b8026a2008200110b90320022d00b802450d1320022f00b90220022d00bb024110747221010c150b200241e4076a2802002100200241b8026a10fb01200010fc0120022802b802220120022802c00241014100410010032103024020022802bc02450d002001102a0b41800621012003417f470d1510fb01220c200241e0076a280200470d15200241b80b6a41086a22014200370300200242003703b80b41c2e1c000410d200241b80b6a1008200241880b6a41086a2001290300370300200220022903b80b3703880b200241003602b802200241880b6a4110200241b8026a100621010240024020022802b8022203417f460d002001450d00200220033602bc0b200220013602b80b200241b8026a200241b80b6a107c20022802b802220b450d0c20022902bc02210e2003450d012001102a0c010b4101210b4200210e20022802e40721000b024002402000200e422088a74f0d00200b20004105746a2211450d00200241003602c002200242013703b802200241c4076a2802002100410410282201450d0d20024284808080c0003702bc02200220013602b80220012000360000200241c8076a2802002106200241d0076a2802002201200241b8026a10b4010240024020022802bc02220320022802c00222006b2001490d0020022802b80221030c010b200020016a22072000490d1b200341017422082007200820074b1b22074100480d1b0240024020030d002007102821030c010b20022802b80220032007102c21030b2003450d0f200220073602bc02200220033602b8020b2002200020016a3602c002200320006a20062001109a051a200241d4076a2802002100200241dc076a2802002201200241b8026a10b4010240024020010d0020022802bc02210620022802c00221090c010b20002001410c6c6a210a034020002802002108200041086a2802002201200241b8026a10b4010240024020022802bc02220620022802c00222036b2001490d0020022802b80221070c010b200320016a22072003490d1d200641017422092007200920074b1b22094100480d1d0240024020060d002009102821070c010b20022802b80220062009102c21070b2007450d12200220093602bc02200220073602b802200921060b2002200320016a22093602c002200720036a20082001109a051a2000410c6a2200200a470d000b0b20022802e007210302400240200620096b4104490d0020022802b80221010c010b200941046a22012009490d1b200641017422002001200020014b1b22004100480d1b0240024020060d002000102821010c010b20022802b80220062000102c21010b2001450d11200220003602bc02200220013602b802200021060b2002200941046a22003602c002200120096a200336000020022802e407210702400240200620006b41034d0d00200621030c010b200041046a22032000490d1b200641017422082003200820034b1b22034100480d1b0240024020060d002003102821010c010b200120062003102c21010b2001450d12200220033602bc02200220013602b8020b200120006a20073600002001200941086a200241e8076a2011100a210002402003450d002001102a0b2000450d010b4180082101200ea7450d16200b102a0c160b410c10282201450d10410410282200450d1120024284808080c0003702bc02200220003602b8022000200c3600002011200241b8026a108f01200241b80b6a41086a20022802c0022200360200200220022903b802220d3703b80b200141086a20003602002001200d370200200220022800880b3602d80a20022002418b0b6a2800003600db0a0240200ea7450d00200b102a0b20024190056a41206a42818080801037030020024190056a41186a4100360200200241bc056a20022800db0a360000200241013a00b805200220013602ac05200242043703a0052002427f370398052002420037039005200220022802d80a3600b905200241e80b6a200241980c6a20024190056a109b04200241b8026a41086a20022903e80b370300200241b8026a41106a200241e80b6a41086a290300370300200241b8026a41186a200241e80b6a41106a290300370300200241b8026a41206a200241e80b6a41186a290300370300200241b8026a41286a200241e80b6a41206a290300370300200241e8026a200241e80b6a41286a290300370300200241003a00b8020c160b200241246a410436020020024184036a4102360200200242023702f402200241bca7c4003602f0022002410436021c200241aca9c4003602182002410036029405200241b8aec600360290052002200241186a36028003200220024190056a360220200241f0026a41cca7c400103e000b41c4d1c3004133200241c80c6a419cd9c3001038000b41fcf8c5001032000b411341011037000b410c41041037000b410441011037000b200141011037000b410c41041037000b410441011037000b200141011037000b41c4d1c3004133200241c80c6a419cd9c3001038000b410441011037000b200741011037000b200941011037000b200041011037000b200341011037000b410c41041037000b410441011037000b20024190056a41206a2205420037030020024190056a41186a22064280808080c000370300200220022800880b3602e80b20022002418b0b6a2800003600eb0b200241bc056a20022800eb0b360000200242043703a0052002427f370398052002427f200e20011b37039005200220022802e80b3600b905200241013a00b805200241d80a6a200241980c6a20024190056a109b04200241e80b6a41286a2207200241d80a6a41286a290300370300200241e80b6a41206a2209200241d80a6a41206a290300370300200241e80b6a41186a2200200241d80a6a41186a290300370300200241e80b6a41106a220a200241d80a6a41106a290300370300200241e80b6a41086a220b200241d80a6a41086a290300370300200220022903d80a3703e80b20024190056a20022903a807200241b0076a290300200241f0066a200820012003109e02024020022d0090054101470d00200220022d0093053a00bb02200220022f0091053b00b902200241013a00b80220022802f80b2103024020002802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241fc0b6a280200450d002003102a0b20022802840c210302402002418c0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241880c6a280200450d042003102a0c040b200241980c6a41286a20024190056a41306a2201290300370300200241980c6a41206a20024190056a41286a290300370300200241980c6a41186a2005290300370300200241980c6a41106a2006290300370300200241980c6a41086a20024190056a41106a29030037030020022002290398053703980c200241880b6a200241e80b6a200241980c6a109b042007200241880b6a41286a2903003703002009200241880b6a41206a2903003703002000200241880b6a41186a290300370300200a200241880b6a41106a290300370300200b200241880b6a41086a290300370300200220022903880b3703e80b20024190056a200410d203024020022d0090054101470d00200220022d0093053a00bb02200220022f0091053b00b902200241013a00b80220022802f80b21030240200241800c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241fc0b6a280200450d002003102a0b20022802840c210302402002418c0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241880c6a280200450d042003102a0c040b200241980c6a41286a2001290300370300200241980c6a41206a20024190056a41286a290300370300200241980c6a41186a20024190056a41206a290300370300200241980c6a41106a20024190056a41186a290300370300200241980c6a41086a20024190056a41106a29030037030020022002290398053703980c200241b80b6a200241e80b6a200241980c6a109b04200241b8026a41086a20022903b80b370300200241b8026a41106a200241b80b6a41086a290300370300200241b8026a41186a200241b80b6a41106a290300370300200241b8026a41206a200241b80b6a41186a290300370300200241b8026a41286a200241b80b6a41206a290300370300200241b8026a41306a200241b80b6a41286a290300370300200241003a00b8020c030b20022f00b90220022d00bb024110747221010b200220022800880b3602e80b20022002418b0b6a2800003600eb0b200241013a00b802200220013b00b902200220014110763a00bb0220022802a80c21030240200241b00c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241ac0c6a280200450d002003102a0b20022802b40c21030240200241bc0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241b80c6a280200450d012003102a0c010b200241003a00bb02200220013b00b902200241013a00b80220022802a80c2103024020052802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241ac0c6a280200450d002003102a0b20022802b40c21030240200241bc0c6a2802002201450d002001410c6c21002003210103400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241b80c6a280200450d002003102a0b2004106a20022d00b80221000b024002400240024002400240410110282201450d00200242013702f406200220013602f00602400240200041ff01714101460d00200241013602f806200141003a0000200241c0026a290300210e024020022802f4062200417f6a41074b0d00200041017422034109200341094b1b22034100480d09200120002003102c2201450d04200220033602f406200220013602f0060b200241093602f8062001200e370001200241d0026a2802002100200241d8026a2802002201200241f0066a10b40102402001450d0020002001410c6c6a2108034020002802002106200041086a2802002201200241f0066a10b4010240024020022802f406220520022802f80622036b2001490d0020022802f00621050c010b200320016a22072003490d0b200541017422042007200420074b1b22074100480d0b0240024020050d002007102821050c010b20022802f00620052007102c21050b2005450d07200220073602f406200220053602f0060b2002200320016a3602f806200520036a20062001109a051a2000410c6a22002008470d000b0b200241dc026a2802002100200241e4026a2802002201200241f0066a10b4010240024020010d0020022802f406210620022802f80621080c010b20002001410c6c6a2104034020002802002107200041086a2802002201200241f0066a10b4010240024020022802f406220620022802f80622036b2001490d0020022802f00621050c010b200320016a22052003490d0b200641017422082005200820054b1b22084100480d0b0240024020060d002008102821050c010b20022802f00620062008102c21050b2005450d08200220083602f406200220053602f006200821060b2002200320016a22083602f806200520036a20072001109a051a2000410c6a22002004470d000b0b200241c8026a290300210e02400240200620086b4108490d0020022802f00621030c010b200841086a22012008490d09200641017422002001200020014b1b22014100480d090240024020060d002001102821030c010b20022802f00620062001102c21030b2003450d07200220013602f406200220033602f0060b2002200841086a3602f806200320086a200e370000024020022802f40620022802f8062201470d00200141016a22002001490d09200141017422052000200520004b1b22004100480d090240024020010d002000102821030c010b200320012000102c21030b2003450d08200220003602f406200220033602f0060b2002200141016a22053602f806200320016a20022d00e8023a00000c010b200241013602f806200141013a0000200241b8026a410172200241f0066a10c60320022802f806210520022802f00621030b024020022d00b8020d000240200241d8026a2802002200450d00200241d0026a28020021012000410c6c210003400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b0240200241d4026a280200450d0020022802d002102a0b0240200241e4026a2802002200450d00200241dc026a28020021012000410c6c210003400240200141046a280200450d002001280200102a0b2001410c6a2101200041746a22000d000b0b200241e0026a280200450d0020022802dc02102a0b200241d00c6a24002005ad4220862003ad840f0b410141011037000b200341011037000b200741011037000b200841011037000b200141011037000b200041011037000b1031000bd40505017f027e077f017e017f230041206b220324002002290300210420012903002105200141106a2106200228021021070240024002400240024002400240200141146a2802002208200141186a28020022096b200241186a280200220a490d00200628020021080c010b2009200a6a220b2009490d032008410174220c200b200c200b4b1b220bad420c7e220d422088a70d03200da7220c4100480d030240024020080d00200c102821080c010b20062802002008410c6c200c102c21080b2008450d0120012008360210200141146a200b3602000b20082009410c6c6a2007200a410c6c109a051a200141186a2009200a6a36020020024100360218200341086a200641086a280200360200200320062902003703002001411c6a2106200228021c210b02400240200141206a2802002208200141246a28020022096b200241246a280200220a490d00200628020021080c010b2009200a6a220c2009490d032008410174220e200c200e200c4b1b220cad420c7e220d422088a70d03200da7220e4100480d030240024020080d00200e102821080c010b20062802002008410c6c200e102c21080b2008450d022001200836021c200141206a200c3602000b427f200520047c220420042005541b210520082009410c6c6a200b200a410c6c109a051a200141246a2009200a6a36020020024100360224200341106a41086a200641086a28020036020020032006290200370310200229030822042001290308220d200d2004561b210420012d0028450d034101210120022d0028450d030c040b200c41041037000b200e41041037000b1031000b410021010b20002005370300200020032903003702102000200329031037021c200020013a002820002004370308200041186a200341086a280200360200200041246a200341106a41086a2802003602000240200241146a280200450d002007102a0b0240200241206a280200450d00200b102a0b200341206a24000ba13507037f017e037f017e147f027e107f230041d0036b2202240002400240024002400240024002400240024020014104490d0020002800002103101a4101470d07200241a8016a41086a22004200370300200242003703a801419be1c0004111200241a8016a1008200241e8006a41086a2000290300370300200220022903a80137036841002101200241003602a801200241e8006a4110200241a8016a100621000240024020022802a8012204417f460d002000450d0020044104490d01200028000021012000102a0b200241003602a801410141838ac100411c200241a8016a101b2100024002400240024020022802a8012204417f470d00410121040c010b2004ad22054220862005842105200045210420000d010b41002100410121060c010b2005422088a74105490d04200028000121070240024020002d00000d0020072003460d0141002106200720034f0d02410121060c020b4101210620072001490d010b410021060b200120034f0d022006450d020240410110282201450d00200141003a00000240200141014105102c2201450d0020012003360001410141838ac100411c4100200020041b22062005422088a7417f20061b20014105101c21062001102a024020042005a745720d002000102a0b20060d0a200241a8016a41086a22004200370300200242003703a80141c2e1c000410d200241a8016a1008200241e8006a41086a2000290300370300200220022903a801370368200241003602a801200241e8006a4110200241a8016a1006210002400240024020022802a8012201417f460d002000450d002002200136022c20022000360228200241a8016a200241286a107c20022802a8012208450d0220022902ac0121092001450d012000102a0c010b42002109410121080b200241186a109d042002280218210a2002280220220b4115490d07200b410176220c41ffffff3f71200c470d09200c4105742200417f4c0d094101210d024002402000450d0020001028220d450d010b200a41606a210e200a41a07f6a210f41002110410021114104211241002113200b211403400240024020142215417f6a22040d0041012107410021140c010b024002400240024002400240200a20044105746a20154105742216200a6a41406a4120109c054100480d002015417e6a2106200f20166a210041002114410021010340024020062001470d00201521070c080b200141016a2101200041206a20004120109c052104200041606a21002004417f4a0d000b200141016a21072001417f7320156a21040c010b200f20166a210002400340024020044101470d00410021040c020b2004417f6a2104200041206a20004120109c052101200041606a210020014100480d000b0b20152004490d012015200b4b0d03201520046b22074101762206450d00200e20166a2100200a20044105746a21010340200241a8016a41186a2216200141186a2217290000370300200241a8016a41106a2218200141106a2219290000370300200241a8016a41086a221a200141086a221b290000370300200220012900003703a801200041086a221c2900002105200041106a221d290000211e200041186a2214290000211f200120002900003700002017201f3700002019201e370000201b200537000020142016290300370000201d2018290300370000201c201a290300370000200020022903a801370000200041606a2100200141206a21012006417f6a22060d000b0b024020040d00200421140c050b0240200741094d0d00200421140c050b2015200b4b0d01201520046b2106200a20044105746a2116034020152004417f6a2214490d040240201520146b22074102490d00200a20044105746a2200200a20144105746a22044120109c05417f4a0d002004290000210520042000290000370000200241a8016a41186a221a200441186a2201290000370300200241a8016a41106a221b200441106a2217290000370300200241a8016a41086a221c200441086a22182900003703002018200041086a2900003700002017200041106a2900003700002001200041186a290000370000200220053703a80141012119024020074103490d00200441c0006a200241a8016a4120109c05417f4a0d00410221012016210002400340200041186a200041386a290000370000200041106a200041306a290000370000200041086a200041286a2900003700002000200041206a221729000037000020062001460d01200041c0006a21182001211920172100200141016a21012018200241a8016a4120109c05417f4a0d020c000b0b200121190b200420194105746a220020022903a801370000200041186a201a290300370000200041106a201b290300370000200041086a201c2903003700000b2014450d05201641606a2116200641016a2106201421042007410a4f0d050c000b0b200420151044000b20152004417f6a2214490d010b2015200b103c000b201420151044000b02400240024020132011470d00201141016a22002011490d11201141017422012000200120004b1b220041ffffffff01712000470d11200041037422014100480d110240024020110d002001102821120c010b201220114103742001102c21120b2012450d0120002111201021130b201220134103746a2200200736020420002014360200201041016a2213211020134102490d0102400340024002400240024020122013417f6a22104103746a2200280200450d00201341037420126a220641746a2802002204200028020422014d0d000240201341024b0d0020132110410221130c080b20122013417d6a221a4103746a2802042200200120046a4d0d010240201341034b0d0020132110410321130c080b200641646a280200200020046a4d0d01201321100c070b20134103490d012000280204210120122013417d6a221a4103746a28020421000b20002001490d010b2013417e6a211a0b0240024002400240024002402013201a41016a22204b2221450d002013201a4b2222450d012012201a4103746a221b2802042223201b2802006a2200201220204103746a221c280200221d490d022000200b4b0d03200a201d4105746a2218201c280204221941057422016a2106200041057421042000201d6b221520196b220020194f0d04200d200620004105742201109a05221720016a21070240024020194101480d00200041014e0d010b20062100201721010c060b200e20046a21042006210003402004200041606a2206200741606a2215201520064120109c0541004822161b2201290000370000200441186a200141186a290000370000200441106a200141106a290000370000200441086a200141086a2900003700002007201520161b2107024020182006200020161b2200490d00201721010c070b200441606a21042017210120172007490d000c060b0b41b8dbc000202020131034000b41b8dbc000201a20131034000b201d20001044000b2000200b103c000b200d20182001109a05221720016a21070240024020194101480d00201520194a0d010b20182100201721010c010b200a20046a211620172101201821000340200020062001200620014120109c0541004822151b2204290000370000200041186a200441186a290000370000200041106a200441106a290000370000200041086a200441086a2900003700002001200141206a20151b2101200041206a2100200641206a200620151b220620164f0d01200720014b0d000b0b20002001200720016b416071109a051a02402022450d00201b201d360200201b41046a202320196a3602002021450d02201c201c41086a20132020417f736a410374109b051a20102113201041014d0d040c010b0b41c8dbc000201a20131034000b41b0b1c0001032000b200141041037000b20140d000b02402011450d002012102a0b200c450d09200d102a0c090b200041011037000b41c4d1c3004133200241186a419cd9c3001038000b410541011037000b410141011037000b41c4d1c3004133200241186a419cd9c3001038000b200241f4006a4104360200200241bc016a4102360200200242023702ac01200241bca7c4003602a8012002410436026c200241c8a9c4003602682002410036022c200241b8aec6003602282002200241e8006a3602b8012002200241286a360270200241a8016a41cca7c400103e000b20042005a745720d052000102a0c050b02402005a7450d002000102a0b41e695c600412d100b0c040b200b4102490d00200a200b417f6a22014105746a21074101210403400240024002400240200b20012200417f6a2201490d00200b20016b22154102490d03200a20004105746a2200200a20014105746a22064120109c05417f4a0d032006290000210520062000290000370000200241a8016a41186a2213200641186a2216290000370300200241a8016a41106a2219200641106a2217290000370300200241a8016a41086a2212200641086a22182900003703002018200041086a2900003700002017200041106a2900003700002016200041186a290000370000200220053703a8014101210020154103490d02200641c0006a200241a8016a4120109c05417f4a0d0241002115200721000340200041186a200041386a290000370000200041106a200041306a290000370000200041086a200041286a2900003700002000200041206a2217290000370000200420152216460d022016417f6a2115200041c0006a2118201721002018200241a8016a4120109c05417f4a0d020c000b0b2001200b1044000b410220166b21000b200620004105746a220020022903a801370000200041186a2013290300370000200041106a2019290300370000200041086a20122903003700000b200741606a21072004417f6a210420010d000b0b2009a721102009422088a72200450d01200820004105746a2118200241a8016a41016a211a200241c0026a2124200241e9026a211b200241e0016a2125200241a8016a41306a2126200241a8016a41286a212741002115200821070240024002400240024002400340024002400240200b41014b0d000240200b0e020c000c0b0340200241a8016a41186a200741186a290000370300200241a8016a41106a200741106a290000370300200241a8016a41086a200741086a290000370300200220072900003703a801200a200241a8016a4120109c05450d02201541016a21152018200741206a2207470d000c0c0b0b0340200241a8016a41186a200741186a290000370300200241a8016a41106a200741106a290000370300200241a8016a41086a200741086a290000370300200220072900003703a801200741206a21070240200b450d0041002100200b210103402001410176220420006a22062000200a20064105746a200241a8016a4120109c054101481b2100200120046b220141014b0d000b200a20004105746a200241a8016a4120109c05450d030b201541016a211520072018460d0b0c000b0b200741206a2107410021000b0240024002400240024002400240200b20004d0d0020024100360268200241e8006a101d2104024020022802682201417f470d00410221060c0a0b200220013602ac01200220043602a8012001450d0320042d0000210620022001417f6a3602ac012002200441016a3602a801200641014b0d030240024020060e020100010b410021202021210c2012211c2019211420132128201721292016211d2021212a2012212b2019212c2013212d2017212e2016212f0c060b200241106a200241a8016a106c20022802100d0320022802ac0122062002280214222b490d03202b417f4c0d0e02400240202b0d004101212041010d010c050b202b102e2220450d02202020022802a801221c202b109a05211d20022006202b6b3602ac012002201c202b6a3602a801201d450d040b200241086a200241a8016a106c20022802080d0220022802ac01410c6e222e410c6c2206417f4c0d0e200228020c212f0240024002400240024020060d004104212d0c010b20061028222d450d010b024002400240202f0d00202d212c0c010b4100210c4100211c41002114202d212c03402002200241a8016a106c20022802000d0220022802ac01221d20022802042206490d022006417f4c0d140240024020060d00410121290c010b2006102e2229450d05202920022802a80122282006109a051a2002201d20066b3602ac012002202820066a3602a8010b201441016a211d02402014202e470d00200c201d200c201d4b1b222ead420c7e2205422088a70d182005a722284100480d180240024020140d0020281028212d0c010b202d201c2028102c212d0b202d450d06202d212c0b202c201c6a22142029360200201441046a2006ad2205422086200584370200200c41026a210c201c410c6a211c201d2114202f201d470d000b0b202c450d06202b212a202f211d202e2129202d2128202c2114202b211c202b210c20200d080c070b02402014450d004100210603400240202c20066a221d41046a280200450d00201d280200102a0b201c2006410c6a2206470d000b0b202e450d05202d102a0c050b200641041037000b200641011037000b202841041037000b41a08ac1002000200b1034000b202b41011037000b202b450d002020102a0b410021202016212f2017212e2013212d2019212c2012212b2021212a2022211d20232129200d212820112114200e211c200f210c0b2001450d010b2004102a0b024020200d00410221060c030b10fb012121200241003602b001200242013703a80102400240024002400240410410282201450d0020024284808080c0003702ac01200220013602a80120012003360000201c200241a8016a10b4010240024020022802ac01220420022802b00122016b201c490d0020022802a80121040c010b2001201c6a22062001490d10200441017422162006201620064b1b22064100480d100240024020040d002006102821040c010b20022802a80120042006102c21040b2004450d02200220063602ac01200220043602a8010b20022001201c6a3602b001200420016a2020201c109a051a201d200241a8016a10b401201d450d022014201d410c6c6a211220142104034020042802002113200441086a2802002201200241a8016a10b4010240024020022802ac01221620022802b00122066b2001490d0020022802a80121170c010b200620016a22172006490d11201641017422192017201920174b1b22194100480d110240024020160d002019102821170c010b20022802a80120162019102c21170b2017450d05200220193602ac01200220173602a801201921160b2002200620016a22193602b001201720066a20132001109a051a2004410c6a22042012470d000c050b0b410441011037000b200641011037000b20022802ac01211620022802b00121190c010b201941011037000b02400240201620196b4104490d0020022802a80121010c010b201941046a22012019490d0b201641017422042001200420014b1b22044100480d0b0240024020160d002004102821010c010b20022802a80120162004102c21010b2001450d04200220043602ac01200220013602a801200421160b2002201941046a22043602b001200120196a202136000002400240201620046b41034d0d00201621060c010b200441046a22062004490d0b201641017422172006201720064b1b22064100480d0b0240024020160d002006102821010c010b200120162006102c21010b2001450d05200220063602ac01200220013602a8010b200120046a2015360000200241e9dabdf3063602cc03202542003703002026420037030020274200370300200241a8016a41206a4200370300200241a8016a41186a4200370300200241a8016a41106a4200370300200241a8016a41086a4200370300200242003703a8010240200241cc036a200a20004105746a2001201941086a200241a8016a101e0d00200241e8006a41086a2200201a41086a290000370300200241e8006a41106a2204201a41106a290000370300200241e8006a41186a2216201a41186a290000370300200241e8006a41206a2217201a41206a290000370300200241e8006a41286a2213201a41286a290000370300200241e8006a41306a2219201a41306a290000370300200241e8006a41376a2212201a41376a2900003700002002201a29000037036820022d00a8012122200241286a41086a22232000290300370300200241286a41106a22002004290300370300200241286a41186a22042016290300370300200241286a41206a22162017290300370300200241286a41286a22172013290300370300200241286a41306a22132019290300370300200241286a41376a221920122900003700002002200229036837032802402006450d002001102a0b201b2002290328370000201b41086a2023290300370000201b41106a2000290300370000201b41186a2004290300370000201b41206a2016290300370000201b41286a2017290300370000201b41306a2013290300370000201b41376a2019290000370000200220223a00e802200220153602e402200220213602e0022002201d3602dc02200220293602d802200220283602d4022002201c3602d0022002200c3602cc02200220203602c802200220033602c402200241123602c0022002420237039002200241e8006a200241a8016a108704200228026c2100200228026822042002280270101f210102402000450d002004102a0b2024106a20010d02410110282200450d06200041013a0000200041014105102c2200450d07201541016a211520002003360001410141838ac100411c2000410510202000102a202f2116202e2117202d2113202c2119202b2112202a2121201d2122202921232028210d20142111201c210e200c210f20072018470d010c090b0b02402006450d002001102a0b0240200c450d002020102a0b0240201d450d00201d410c6c210003400240201441046a280200450d002014280200102a0b2014410c6a2114200041746a22000d000b0b410121062029450d012028102a0c010b410321060b02402010450d002008102a0b0240200228021c450d00200a102a0b412e2104419396c6002100200241186a2101024002400240024020060e0400010203000b412d210441e695c6002100200241286a21010c020b411f210441c795c6002100200241e8006a21010c010b419995c6002100200241a8016a21010b200120043602042001200036020020002004100b0c060b200441011037000b200641011037000b410141011037000b410541011037000b1036000b02402010450d002008102a0b200228021c450d00200a102a0b200241d0036a240042010f0b1031000bcb06020d7f037e230041e0006b22012400200141e9dabdf306360208410021022001410036020c200141086a2001410c6a102621032001200128020c360214200120033602102001200141106a106c2001280204210441002105024002400240024020012802000d00200128021422034160712206417f4c0d0202400240200341057622070d00410121050c010b200610282205450d020b2004450d0041002108034020032109200141003a00582008220a41016a2108410021030240024002400240034020092003460d01200141386a20036a200128021022062d00003a00002001200641016a3602102001200341016a22063a00582006210320064120470d000b200141186a41186a220b200141386a41186a290300370300200141186a41106a220c200141386a41106a290300370300200141186a41086a220d200141386a41086a290300370300200120012903383703182007200a470d03200a41017422032008200320084b1b220741ffffff3f712007470d082007410574220341004e0d010c080b200141003602140240200341ff0171450d00200141003a00580b2007450d012005102a0c010b02400240200a0d002003102821050c010b2005200a4105742003102c21050b20050d01200341011037000b410021050c020b200920066b21032005200a4105746a220a2001290318370000200a41186a200b290300370000200a41106a200c290300370000200a41086a200d29030037000020082004470d000b2001200920066b3602140b4101210a2005410120051b21084100210302402004410020051b2206450d0020064105742203410575220241ffffff3f712002470d03200241057422094100480d03024020091028220a0d00200941011037000b200820036a210420064105742109200a2103200821060340200641086a290000210e200641106a290000210f20062900002110200341186a200641186a290000370000200341106a200f370000200341086a200e37000020032010370000200341206a2103200641206a2106200941606a22090d000b200420086b41606a41057641016a21030b02402005450d002007450d002008102a0b20002003360208200020023602042000200a360200200141e0006a24000f0b200641011037000b1036000b1031000bf80303047f027e037f230041306b22022400200241106a41086a220342003703002002420037031041c694c600411b200241106a1008200241086a200329030037030020022002290310370300410021032002410036021020024110200241106a100621040240024002400240024020022802102205417f470d000c010b2002200536022420022004360220200241106a200241206a107720022802102203450d01200229021421062005450d002004102a0b20024100360218200242013703102006420020031b2207422088a72205200241106a10b4012003410820031b210802402005450d002008200541286c6a21092008210503402005200241106a108f01200541206a29030021060240024020022802142204200228021822036b4108490d00200228021021040c010b200341086a220a2003490d0520044101742203200a2003200a4b1b22034100480d050240024020040d002003102821040c010b200228021020042003102c21040b2004450d042002200336021420022004360210200228021821030b2002200341086a360218200420036a20063700002009200541286a2205470d000b0b200235021821062002280210210302402007a7450d002008102a0b200241306a240020064220862003ad840f0b41c4d1c3004133200241286a419cd9c3001038000b200341011037000b1031000b9d0d04047f017e027f017e230041c0016b22022400200241086a41086a220342003703002002420037030841eefbc5004110200241086a1008200241a0016a41086a2003290300370300200220022903083703a0014100210320024100360208200241a0016a4110200241086a10062104024002400240024002400240024002400240024020022802082205417f470d000c010b024020040d000c010b2002200536027c20022004360278200241086a200241f8006a107720022802082203450d01200229020c21062005450d002004102a0b200241086a41086a2205420037030020024200370308419efcc500410f200241086a1008200241a0016a41086a22042005290300370300200220022903083703a001200241f8006a200241a0016a10ef0220022d00782105200241a0016a41186a220720024191016a290000370300200241a0016a41106a220820024189016a290000370300200420024181016a290000370300200220022900793703a0012006420020031b21062003410820031b21030240024020054101460d00200241d8006a41186a4200370300200241d8006a41106a4200370300200241d8006a41086a4200370300200242003703580c010b200241d8006a41186a2007290300370300200241d8006a41106a2008290300370300200241d8006a41086a2004290300370300200220022903a0013703580b2002412c6a2006370200200241086a41186a42043703002002413c6a200241d8006a41086a290300370200200241c4006a200241e8006a290300370200200241cc006a200241d8006a41186a2903003702002002200336022820024201370318200242c801370310200242b81737030820022002290358370234200241013a0054200241003602800120024201370378410810282203450d012002410836027c2002200228028001220441086a3602800120022003360278200320046a42b8173700002002290310210602400240200228027c220420022802800122036b4108490d00200228027821040c010b200341086a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102821040c010b200228027820042003102c21040b2004450d032002200336027c2002200436027820022802800121030b2002200341086a36028001200420036a20063700002002290318210602400240200228027c220420022802800122036b4108490d00200228027821040c010b200341086a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102821040c010b200228027820042003102c21040b2004450d042002200336027c2002200436027820022802800121030b2002200341086a36028001200420036a20063700002002290320210602400240200228027c220420022802800122036b4108490d00200228027821040c010b200341086a22052003490d08200441017422032005200320054b1b22034100480d080240024020040d002003102821040c010b200228027820042003102c21040b2004450d052002200336027c2002200436027820022802800121030b2002200341086a36028001200420036a200637000020022802282104200241086a41286a2802002203200241f8006a10b40102402003450d002004200341286c6a210803402004200241f8006a108f01200441206a290300210602400240200228027c220520022802800122036b4108490d00200228027821050c010b200341086a22072003490d0a200541017422032007200320074b1b22034100480d0a0240024020050d002003102821050c010b200228027820052003102c21050b2005450d082002200336027c2002200536027820022802800121030b2002200341086a36028001200520036a20063700002008200441286a2204470d000b0b200241346a200241f8006a10f10202400240200228027c2002280280012203460d00200228027821040c010b200341016a22042003490d08200341017422052004200520044b1b22054100480d080240024020030d002005102821040c010b200228027820032005102c21040b2004450d072002200536027c2002200436027820022802800121030b2002200341016a36028001200420036a20022d00543a00002002350280012106200235027821090240200228022c450d002002280228102a0b200241c0016a240020064220862009840f0b41c4d1c3004133200241d8006a419cd9c3001038000b410841011037000b200341011037000b200341011037000b200341011037000b200341011037000b200541011037000b1031000baa0607017f017e077f017e027f017e027f230041c0006b2202240042002103200241086a2204420037030020024200370300419695c400411720021008200241206a41086a20042903003703002002200229030037032020024100360200200241206a411020021006210502400240024002400240024020022802002204417f460d0020022004360234200220053602302002200241306a107c20022802002206450d02200229020421032004450d012005102a0c010b410121060b41002107024002402003422088a7220441057422080d00410421094100210a0c010b2008410575220aad420c7e220b422088a70d04200ba722054100480d04200510282209450d020b2003a7210c02402004450d00200841606a210d20092105200621040340200441086a2900002103200441106a290000210b2004290000210e200241186a200441186a290000370300200241106a200b370300200241086a20033703002002200e370300200241206a2002108b04200541086a200241206a41086a280200360200200520022903203702002005410c6a2105200441206a2104200841606a22080d000b200d41057641016a21070b0240200c450d002006102a0b20024100360208200242013703002007200210b4010240024020070d002002280208210d200228020021060c010b20092007410c6c6a210f2009210503402005280200210c200541086a2802002204200210b4010240024020022802042206200228020822086b2004490d00200228020021060c010b200820046a220d2008490d0620064101742210200d2010200d4b1b220d4100480d060240024020060d00200d102821060c010b20022802002006200d102c21060b2006450d052002200d360204200220063602000b2002200820046a220d360208200620086a200c2004109a051a2005410c6a2205200f470d000b2007410c6c21052009210403400240200441046a280200450d002004280200102a0b2004410c6a2104200541746a22050d000b0b0240200a450d002009102a0b200241c0006a2400200dad4220862006ad840f0b41c4d1c3004133200241386a419cd9c3001038000b200541041037000b200d41011037000b1031000baf1905047f017e057f037e3c7f230041d0016b22022400024002402001450d00200220003602100c010b200241013602100b20022001360214200241086a200241106a106c024002400240024002400240024002400240024002400240024020022802080d0020022802142201200228020c2200490d002000417f4c0d010240024020000d00410121030c010b2000102e2203450d032003200228021022042000109a051a2002200120006b3602142002200420006a3602100b2003450d0020024188016a41086a220142003703002002420037038801419695c400411720024188016a1008200241e8006a41086a200129030037030020022002290388013703682002410036028801200241e8006a411020024188016a10062101024002402002280288012204417f460d002001450d002002200436025c2002200136025820024188016a200241d8006a107c2002280288012205450d05200229028c0121062004450d012001102a0c010b41012105420021060b200241d8006a109d044100210702402006422088a72201450d00200520014105746a21082002280258220920022802604105746a210a2005210b0340200b41086a290000210c200b41106a290000210d200b290000210e20024188016a41186a200b41186a29000037030020024188016a41106a200d37030020024188016a41086a200c3703002002200e37038801200b41206a210b20092101024003400240200a20016b41e0004b0d0002402001200a460d00034020024188016a2001460d04200120024188016a4120109c05450d04200a200141206a2201470d000b0b200b2008470d030c040b200120024188016a460d01200120024188016a4120109c05450d01200141206a220420024188016a460d01200420024188016a4120109c05450d01200141c0006a220420024188016a460d01200420024188016a4120109c05450d01200141e0006a220420024188016a460d0120014180016a2101200420024188016a4120109c050d000b0b0b200241e8006a41186a20024188016a41186a290300220c370300200241386a41086a20024188016a41086a290300370300200241386a41106a20024188016a41106a290300370300200241386a41186a200c3703002002200229038801370338410121070b2006a721010240200228025c450d002002280258102a0b02402001450d002005102a0b200241e8006a41186a2201200241386a41186a290300370300200241e8006a41106a2204200241386a41106a290300370300200241e8006a41086a220b200241386a41086a290300370300200220022903383703682007450d0b200241186a41186a2001290300370300200241186a41106a2004290300370300200241186a41086a200b29030037030020022002290368370318200241e9dabdf306360268200241c0016a4200370300200241b8016a4200370300200241b0016a4200370300200241a8016a420037030020024188016a41186a420037030020024188016a41106a420037030020024188016a41086a4200370300200242003703880102400240200241e8006a200241186a2003200020024188016a101e450d00410021010c010b4101210120022d00c701210f20022d00c601211020022d00c501211120022d00c401211220022d00c301211320022d00c201211420022d00c101211520022d00c001211620022d00bf01211720022d00be01211820022d00bd01211920022d00bc01211a20022d00bb01211b20022d00ba01211c20022d00b901211d20022d00b801211e20022d00b701211f20022d00b601212020022d00b501212120022d00b401212220022d00b301212320022d00b201212420022d00b101212520022d00b001212620022d00af01212720022d00ae01212820022d00ad01212920022d00ac01212a20022d00ab01212b20022d00aa01212c20022d00a901212d20022d00a801212e20022d00a701212f20022d00a601213020022d00a501213120022d00a401213220022d00a301213320022d00a201213420022d00a101213520022d00a001213620022d009f01213720022d009e01213820022d009d01213920022d009c01213a20022d009b01213b20022d009a01213c20022d009901213d20022d009801213e20022d009701213f20022d009601214020022d009501214120022d009401214220022d009301214320022d009201214420022d009101214520022d009001214620022d008f01214720022d008e01214820022d008d01214920022d008c01214a20022d008b01210820022d008a01210920022d008901210720022d00880121050b20024188016a41186a2204200241186a41186a29030037030020024188016a41106a220b200241186a41106a29030037030020024188016a41086a220a200241186a41086a29030037030020022002290318370388012001450d0b200241e8006a41186a20042903002206370300200241e8006a41106a200b290300220c370300200241e8006a41086a200a290300220d3703002002200229038801220e37036820042006370300200b200c370300200a200d3703002002200e37038801410110282201450d04200120053a0000200141014102102c2201450d05200120073a0001200141024104102c2201450d06200120083a0003200120093a0002200141044108102c2201450d07200120473a0007200120483a0006200120493a00052001204a3a0004200141084110102c2201450d082001203f3a000f200120403a000e200120413a000d200120423a000c200120433a000b200120443a000a200120453a0009200120463a0008200141104120102c2201450d092001202f3a001f200120303a001e200120313a001d200120323a001c200120333a001b200120343a001a200120353a0019200120363a0018200120373a0017200120383a0016200120393a00152001203a3a00142001203b3a00132001203c3a00122001203d3a00112001203e3a00102001412041c000102c2201450d0a2001200f3a003f200120103a003e200120113a003d200120123a003c200120133a003b200120143a003a200120153a0039200120163a0038200120173a0037200120183a0036200120193a00352001201a3a00342001201b3a00332001201c3a00322001201d3a00312001201e3a00302001201f3a002f200120203a002e200120213a002d200120223a002c200120233a002b200120243a002a200120253a0029200120263a0028200120273a0027200120283a0026200120293a00252001202a3a00242001202b3a00232001202c3a00222001202d3a00212001202e3a0020200241386a20024188016a108b042002280240210b200228023c2109200228023821050c0c0b200241f4006a41043602002002419c016a41023602002002420237028c01200241bca7c400360288012002410436026c200241e0a9c4003602682002410036023c200241b8aec6003602382002200241e8006a360298012002200241386a36027020024188016a41cca7c400103e000b1036000b200041011037000b41c4d1c3004133200241c8016a419cd9c3001038000b410141011037000b410241011037000b410441011037000b410841011037000b411041011037000b412041011037000b41c00041011037000b410021010b0240024002400240410110282204450d00200242818080801037028c0120022004360288010240024020010d00200441003a000042808080801021060c010b200441013a000041c00020024188016a10b40102400240200228028c01220720022802900122046b41c000490d00200441c0006a210a20022802880121070c010b200441c0006a220a2004490d0520074101742208200a2008200a4b1b22084100480d050240024020070d002008102821070c010b20022802880120072008102c21070b2007450d032002200836028c0120022007360288010b200720046a220441086a200141086a290000370000200441106a200141106a290000370000200441186a200141186a290000370000200441206a200141206a290000370000200441286a200141286a290000370000200441306a200141306a290000370000200441386a200141386a2900003700002002200a3602900120042001290000370000200b20024188016a10b40102400240200228028c012204200228029001220a6b200b490d0020022802880121040c010b200a200b6a2207200a490d05200441017422082007200820074b1b22074100480d050240024020040d002007102821040c010b20022802880120042007102c21040b2004450d042002200736028c0120022004360288010b2002200a200b6a2207360290012004200a6a2005200b109a051a2001102a2007ad42208621062009450d002005102a0b02402000450d002003102a0b200241d0016a240020062004ad840f0b410141011037000b200841011037000b200741011037000b1031000baf0e04077f027e047f077e23004190026b22022400024002402001450d00200220003602200c010b200241013602200b20022001360224200241186a200241206a106c024002400240024020022802180d0020022802242201200228021c2203490d000240024002402003417f4c0d000240024020030d00410121040c010b2003102e2204450d022004200228022022002003109a051a2002200120036b3602242002200020036a3602200b2004450d03200241106a200241206a106c20022802100d052002280224220120022802142200490d052000417f4c0d000240024020000d00410121050c010b2000102e2205450d032005200228022022062000109a051a2002200120006b3602242002200620006a3602200b2005450d05200241086a200241206a106c024020022802080d0020022802242206200228020c2201490d002001417f4c0d010240024020010d00410121070c010b2001102e2207450d062007200228022022082001109a051a2002200620016b3602242002200820016a3602200b2007450d002001ad2209422086200984210941002101200241003a00c8012000ad220a422086200a84220a422088a72108200521000240024002400240034020082001460d0120024188016a20016a20002d00003a00002002200141016a22063a00c801200041016a210020062101200641c000470d000b200241d0016a41386a220120024188016a41386a290300370300200241d0016a41306a220020024188016a41306a290300370300200241d0016a41286a220820024188016a41286a290300370300200241d0016a41206a220b20024188016a41206a290300370300200241d0016a41186a220c20024188016a41186a290300370300200241d0016a41106a220d20024188016a41106a290300370300200241d0016a41086a220e20024188016a41086a29030037030020022002290388013703d001200641ff017141c000490d02200241c8006a41386a22062001290300370300200241c8006a41306a2000290300220f370300200241c8006a41286a20082903002210370300200241c8006a41206a200b2903002211370300200241c8006a41186a200c2903002212370300200241c8006a41106a200d2903002213370300200241c8006a41086a200e2903002214370300200220022903d00122153703482000200f37030020082010370300200b2011370300200c2012370300200d2013370300200e201437030020012006290300370300200220153703d00141002101200241003a00a8012009422088a7210820072100034020082001460d0220024188016a20016a20002d00003a00002002200141016a22063a00a801200041016a21002006210120064120470d000b200241286a41186a220120024188016a41186a2200290300370300200241286a41106a220620024188016a41106a2208290300370300200241286a41086a220b20024188016a41086a220c290300370300200220022903880137032820024188016a41386a200241d0016a41386a29030037030020024188016a41306a200241d0016a41306a29030037030020024188016a41286a200241d0016a41286a29030037030020024188016a41206a200241d0016a41206a2903003703002000200241d0016a41186a2903003703002008200241d0016a41106a290300370300200c200241d0016a41086a290300370300200220022903d00137038801200241c8006a41186a2001290300370300200241c8006a41106a2006290300370300200241c8006a41086a200b290300370300200220022903283703482004200320024188016a200241c8006a100a4521000c030b200141ff0171450d01200241003a00c8010c010b200141ff0171450d00200241003a00a8010b410021000b410110282201450d07200120003a000002402009a7450d002007102a0b0240200aa7450d002005102a0b02402003450d002004102a0b20024190026a24002001ad428080808010840f0b200241dc016a41043602002002419c016a41023602002002420237028c01200241bca7c40036028801200241043602d401200241eca9c4003602d0012002410036024c200241b8aec6003602482002200241d0016a360298012002200241c8006a3602d80120024188016a41cca7c400103e000b1036000b200341011037000b200041011037000b200241dc016a41043602002002419c016a41023602002002420237028c01200241bca7c40036028801200241043602d401200241eca9c4003602d0012002410036024c200241b8aec6003602482002200241d0016a360298012002200241c8006a3602d80120024188016a41cca7c400103e000b200141011037000b200241dc016a41043602002002419c016a41023602002002420237028c01200241bca7c40036028801200241043602d401200241eca9c4003602d0012002410036024c200241b8aec6003602482002200241d0016a360298012002200241c8006a3602d80120024188016a41cca7c400103e000b410141011037000be30503037f047e017f230041a0016b2202240041002103200241003a00482000410120011b2104024002400240024002400240034020012003460d01200241286a20036a200420036a2d00003a00002002200341016a22003a00482000210320004120470d000b200241086a41186a200241286a41186a22002903002205370300200241086a41106a200241286a41106a22012903002206370300200241086a41086a200241286a41086a22042903002207370300200220022903282208370308200241d0006a41186a2005370300200241d0006a41106a2006370300200241d0006a41086a200737030020022008370350411310282203450d03200341002900cef0423700002003410f6a41002800ddf042360000200341086a41002900d6f04237000020024293808080b002370294012002200336029001200241d0006a20024190016a108f01200228029801210320022802900121092000420037030020014200370300200442003703002002420037032820092003200241286a1000200241f0006a41186a2000290300370300200241f0006a41106a2001290300370300200241f0006a41086a2004290300370300200220022903283703700240200228029401450d00200228029001102a0b20024100360228200241f0006a4120200241286a1006210320022802282200417f470d01410021000c020b0240200341ff0171450d00200241003a00480b2002413c6a4102360200200241fc006a41043602002002420237022c200241bca7c40036022820024104360274200241fca9c40036027020024100360254200241b8aec6003602502002200241f0006a3602382002200241d0006a360278200241286a41cca7c400103e000b024020030d00410021000c010b20004104490d02200328000021002003102a0b410410282203450d0220032000360000200241a0016a24002003ad4280808080c000840f0b411341011037000b41c4d1c3004133200241286a419cd9c3001038000b410441011037000b880f03057f037e017f230041c0016b22022400024020010d00410121000b200220003602082002200136020c41002103200241003a00702001417f6a21040340024020012003470d000240200341ff0171450d00200241003a00700b200241e4006a41023602002002419c016a410436020020024202370254200241bca7c400360250200241043602940120024194aac4003602900120024100360234200241b8aec600360230200220024190016a3602602002200241306a36029801200241d0006a41cca7c400103e000b200241d0006a20036a200020036a22052d00003a00002002200541016a3602082002200341016a22053a00702002200436020c2004417f6a21042005210320054120470d000b200241106a41086a200241d0006a41086a290300370300200241106a41106a200241d0006a41106a290300370300200241106a41186a200241d0006a41186a2903003703002002200229035037031041002103200241003a0070200120056b2106200020056a2100417f21010340024020062003470d000240200341ff0171450d00200241003a00700b200241e4006a41023602002002419c016a410436020020024202370254200241bca7c400360250200241043602940120024194aac4003602900120024100360234200241b8aec600360230200220024190016a3602602002200241306a36029801200241d0006a41cca7c400103e000b200241d0006a20036a200020036a22052d00003a00002002200420036b36020c2002200541016a3602082002200341016a22053a00702001417f6a21012005210320054120470d000b200241306a41086a200241d0006a41086a290300370300200241306a41106a200241d0006a41106a290300370300200241306a41186a200241d0006a41186a290300370300200220022903503703300240024002400240024002400240024002400240024002400240200420056b220441016a4110490d002002200020056a220341106a3602082002200441716a220536020c20054108490d0220032900002107200341086a29000021082002200441696a36020c2002200341186a360208200341106a29000021092002200241086a106c20022802000d0c200228020c2205200228020422034f0d010c0c0b2002419c016a4104360200200241e4006a410236020020024202370254200241bca7c400360250200241043602940120024194aac400360290012002410036027c200241b8aec600360278200220024190016a3602602002200241f8006a36029801200241d0006a41cca7c400103e000b2003417f4c0d0302400240024020030d00410121044101450d0d0c010b2003102e2204450d012004200228020822012003109a0521002002200520036b36020c2002200120036a3602082000450d0c0b20024190016a41186a200241106a41186a29030037030020024190016a41106a200241106a41106a29030037030020024190016a41086a200241106a41086a2903003703002002200229031037039001200241d0006a41186a200241306a41186a290300370300200241d0006a41106a200241306a41106a290300370300200241d0006a41086a200241306a41086a29030037030020022002290330370350200220033602b801200220033602b401200220043602b001200241f8006a20024190016a200241d0006a200720082009200241b0016a10f50320022802784101460d0220024184016a2802002104200241f8006a41086a2802002100200228027c210520022d00880121010c030b200341011037000b2002419c016a4104360200200241e4006a410236020020024202370254200241bca7c400360250200241043602940120024194aac400360290012002410036027c200241b8aec600360278200220024190016a3602602002200241f8006a36029801200241d0006a41cca7c400103e000b0240200228028801450d0020024184016a280200102a0b410021050b200241003602582002420137035041011028210302402005450d002003450d02200242818080801037025420022003360250200341003a0000200341014102102c2203450d03200242828080802037025420022003360250200320013a00012004200241d0006a10b401024020022802542203200228025822016b2004490d00200228025021030c070b0240200120046a22062001490d002003410174220a2006200a20064b1b22064100480d000240024020030d002006102821030c010b200228025020032006102c21030b2003450d0520022006360254200220033602500c070b1031000b2003450d04200242818080801037025420022003360250200341013a000042808080801021070c060b1036000b410141011037000b410241011037000b200641011037000b410141011037000b2002200120046a2206360258200320016a20052004109a051a2006ad42208621072005450d002000450d002005102a0b200241c0016a240020072003ad840f0b2002419c016a4104360200200241e4006a410236020020024202370254200241bca7c400360250200241043602940120024194aac400360290012002410036027c200241b8aec600360278200220024190016a3602602002200241f8006a36029801200241d0006a41cca7c400103e000bc00c03047f017e067f23004180026b220224000240024020010d002002200136020c200241013602080c010b20022001417f6a36020c410121032002200041016a36020820002d0000220141014b0d0041002104410021000240024002400240024002400240024020010e020100010b2002200241086a106c20022802000d07200228020c220120022802042200490d072000417f4c0d010240024020000d00410121040c010b2000102e2204450d032004200228020822052000109a051a2002200120006b36020c2002200520006a3602080b2004450d07200241106a20042000ad22064220862006842206422088a7105420022802104101460d03200241186a280200210520022802142100410021030b2002200536021420022000360210200241e7e485f3063602b001200241d0016a41186a22074200370300200241d0016a41106a22084200370300200241d0016a41086a22094200370300200242003703d00141002101200241106a410020001b210a0240024020000d004100210b0c010b200a41046a280200210c200a280200210b0b200241b0016a200b4101200b1b200c4100200b1b200241d0016a1021200241f0006a41186a2007290300370300200241f0006a41106a2008290300370300200241f0006a41086a2009290300370300200220022903d0013703702002200536021420022000360210200241e2c289ab063602b001200742003703002008420037030020094200370300200242003703d0010240024020000d000c010b200a41046a280200210b200a28020021010b200241b0016a2001410120011b200b410020011b200241d0016a102220024190016a41186a2207200241d0016a41186a220129030037030020024190016a41106a2208200241d0016a41106a220b29030037030020024190016a41086a2209200241d0016a41086a220a290300370300200220022903d00137039001200220053602fc01200220003602f801200241e9dabdf3063602f40120014200370300200b4200370300200a4200370300200242003703d0010240024020000d00410021000c010b200241f8016a410020001b220041046a2802002105200028020021000b200241f4016a2000410120001b2005410020001b200241d0016a1022200241b0016a41186a22002001290300370300200241b0016a41106a2201200b290300370300200241b0016a41086a2205200a290300370300200241106a41086a200241f0006a41086a290300370300200241106a41106a200241f0006a41106a290300370300200241106a41186a200241f0006a41186a290300370300200220022903d0013703b00120022002290370370310200241c8006a2007290300370300200241c0006a2008290300370300200241386a20092903003703002002200229039001370330200241e8006a2000290300370300200241e0006a2001290300370300200241d8006a2005290300370300200220022903b001370350200241003602d801200242013703d001200241106a200241d0016a108f01200241306a200241d0016a108f01200241d0006a200241d0016a108f0120022802d801210020022802d401210a20022802d001210b024020032006a745720d002004102a0b200041046a2201417f4c0d000240024020010d00410121050c010b200110282205450d040b2002410036021820022001360214200220053602102000200241106a10b4010240024020022802142205200228021822016b2000490d00200228021021050c010b200120006a22042001490d06200541017422072004200720044b1b22044100480d060240024020050d002004102821050c010b200228021020052004102c21050b2005450d0520022004360214200220053602100b200520016a200b2000109a051a200120006a21000240200a450d00200b102a0b20024180026a24002000ad4220862005ad840f0b1036000b200041011037000b200220022902143703d001419fdbc0004116200241d0016a41d4c7c0001038000b200141011037000b200441011037000b1031000b200241dc016a4104360200200241246a410236020020024202370214200241bca7c400360210200241043602d4012002419caac4003602d001200241003602b401200241b8aec6003602b0012002200241d0016a3602202002200241b0016a3602d801200241106a41cca7c400103e000b823305087f017e067f037e037f23004180066b220124000240024002400240411210282202450d00200241002900c1ae44370000200241106a41002f00d1ae443b0000200241086a41002900c9ae4437000020014292808080a0023702e404200120023602e0042000200141e0046a108f0120012802e804210220012802e0042100200141a0046a41186a22034200370300200141a0046a41106a22044200370300200141a0046a41086a22054200370300200142003703a00420002002200141a0046a1000200141c8006a41186a2003290300370300200141c8006a41106a2004290300370300200141c8006a41086a2005290300370300200120012903a004370348024020012802e404450d0020012802e004102a0b200141003602e004200141c8006a4120200141e0046a1006210620012802e0042207417f460d022006450d02200120073602e405200120063602e005200141306a200141e0056a109f0120012802300d0120012802e4052202450d0120012002417f6a22033602e405200120012802e005220541016a22043602e00520052d0000220241014b0d01410021080240024020020e020100010b41002102200141003a0080050340024020032002470d00200141003602e405200241ff0171450d04200141003a0080050c040b200141e0046a20026a200520026a220041016a2d00003a00002001200041026a3602e0052001200241016a22003a0080052000210220004120470d000b200141a0046a41086a200141e0046a41086a2903002209370300200141e8016a41186a200141e0046a41186a290300370300200141e8016a41106a200141e0046a41106a290300370300200141e8016a41086a20093703002001200320006b22033602e405200120012903e00422093703a004200120093703e80141012108200520006a41016a21040b20014180046a41186a200141e8016a41186a29030037030020014180046a41106a200141e8016a41106a29030037030020014180046a41086a200141e8016a41086a290300370300200120012903e801370380042003450d0120012003417f6a22033602e4052001200441016a3602e00520042d0000220041014b0d01410021020240024020000e020100010b41002102200141003a0080050340024020032002470d00200141003602e405200241ff0171450d04200141003a0080050c040b200141e0046a20026a200420026a220041016a2d00003a00002001200041026a3602e0052001200241016a22003a0080052000210220004120470d000b200141c0046a41086a200141e0046a41086a2903002209370300200141e8016a41186a200141e0046a41186a290300370300200141e8016a41106a200141e0046a41106a290300370300200141e8016a41086a20093703002001200320006b3602e405200120012903e00422093703c004200120093703e801410121020b200141c0036a41186a2205200141e8016a41186a2200290300370300200141c0036a41106a220a200141e8016a41106a2203290300370300200141c0036a41086a220b200141e8016a41086a2204290300370300200141e0036a41086a220c20014180046a41086a290300370300200141e0036a41106a220d20014180046a41106a290300370300200141e0036a41186a220e20014180046a41186a290300370300200120012903e8013703c00320012001290380043703e003200141a0036a41186a220f200e290300370300200141a0036a41106a220e200d290300370300200141a0036a41086a220d200c290300370300200120012903e0033703a00320014180036a41186a220c200529030037030020014180036a41106a2205200a29030037030020014180036a41086a220a200b290300370300200120012903c00337038003200141e0046a41186a220b200f290300370300200141e0046a41106a220f200e290300370300200141e0046a41086a220e200d290300370300200120012903a0033703e0042000200c290300370300200320052903003703002004200a29030037030020012001290380033703e801200141c0056a41046a2205200141fa026a41046a2f01003b0100200120012801fa023602c00520084102460d01200141d8026a41186a200b290300370300200141d8026a41106a200f290300370300200141d8026a41086a200e290300370300200141b8026a41086a2004290300370300200141b8026a41106a2003290300370300200141b8026a41186a2000290300370300200141b0026a41046a20052f01003b0100200120012903e0043703d802200120012903e8013703b802200120012802c0053602b00202402007450d002006102a0b200141c8006a412010090c030b411241011037000b41c4d1c3004133200141a0046a419cd9c3001038000b410221080b20014188016a41186a2200200141d8026a41186a29030037030020014188016a41106a2203200141d8026a41106a29030037030020014188016a41086a2204200141d8026a41086a290300370300200141e8006a41086a2205200141b8026a41086a290300370300200141e8006a41106a2206200141b8026a41106a290300370300200141e8006a41186a2207200141b8026a41186a290300370300200120012903d80237038801200120012903b802370368200141c8016a41086a220a2004290300370300200141c8016a41106a22042003290300370300200141c8016a41186a2203200029030037030020012001290388013703c801200141a8016a41086a22002005290300370300200141a8016a41106a22052006290300370300200141a8016a41186a22062007290300370300200120012903683703a8010240024020084102460d002001418a026a220720012903a801370100200141f1016a200a290300370000200141f9016a200429030037000020014181026a200329030037000020014192026a20002903003701002001419a026a2005290300370100200141a2026a2006290300370100200120083a00e801200120012903c8013700e901200120023a0089024100210602400240024002400240024002400240200241ff01714101470d00200141e0046a200710ac01200141e0056a41186a200141e0046a41186a22022900002209370300200141e0056a41106a200141e0046a41106a22002900002210370300200141e0056a41086a200141e0046a41086a22032900002211370300200120012900e00422123703e005200220093703002000201037030020032011370300200120123703e004412010282206450d01200620012903e004370000200641186a2002290300370000200641106a2000290300370000200641086a200329030037000020012d00e80121080b0240200841ff01714101460d0020012d0089024101460d03200141c0056a41186a22024200370300200141c0056a41106a22004200370300200141c0056a41086a22034200370300200142003703c00541d3aec400411a200141c0056a1000200141e0046a41186a2002290300370300200141e0046a41106a2000290300370300200141e0046a41086a2003290300370300200120012903c0053703e004200141e0046a412010090c060b200141e0046a200141e8016a41017210ac01200141e0056a41186a200141e0046a41186a22022903002209370300200141e0056a41106a200141e0046a41106a22002903002210370300200141e0056a41086a200141e0046a41086a22032903002211370300200120012903e00422123703e005200220093703002000201037030020032011370300200120123703e004412010282208450d01200820012903e004370000200841186a2002290300370000200841106a2000290300370000200841086a2003290300370000200141003602e00420084120200141e0046a1006210720012802e004220b417f460d032007450d032001200b360284042001200736028004200141186a20014180046a109f012001290318a70d042001280284042202450d04200141286a29030021092001290320211020012002417f6a2203360284042001200128028004220541016a22043602800420052d0000220241014b0d044100210a0240024020020e020100010b41002102200141003a0080050340024020032002470d002001410036028404200241ff0171450d07200141003a0080050c070b200141e0046a20026a200520026a220041016a2d00003a00002001200041026a360280042001200241016a22003a0080052000210220004120470d000b200141e0056a41086a200141e0046a41086a290300370300200141e0056a41106a200141e0046a41106a290300370300200141e0056a41186a200141e0046a41186a290300370300200120012903e0043703e0052001200320006b2203360284044101210a200520006a41016a21040b200141c0056a41186a200141e0056a41186a290300370300200141c0056a41106a200141e0056a41106a290300370300200141c0056a41086a200141e0056a41086a290300370300200120012903e0053703c0052003450d0420012003417f6a2203360284042001200441016a3602800420042d0000220241014b0d040240024020020e020100010b41002102200141003a0080050340024020032002470d002001410036028404200241ff0171450d07200141003a0080050c070b200141e0046a20026a200420026a220041016a2d00003a00002001200041026a360280042001200241016a22003a0080052000210220004120470d000b200141a0046a41086a200141e0046a41086a2903002211370300200141e0056a41186a200141e0046a41186a290300370300200141e0056a41106a200141e0046a41106a290300370300200141e0056a41086a20113703002001200320006b36028404200120012903e00422113703a004200120113703e0050b200141c0036a41186a2202200141e0056a41186a2200290300370300200141c0036a41106a2203200141e0056a41106a2204290300370300200141c0036a41086a2205200141e0056a41086a220c290300370300200141e0036a41086a220d200141c0056a41086a290300370300200141e0036a41106a220e200141c0056a41106a290300370300200141e0036a41186a220f200141c0056a41186a290300370300200120012903e0053703c003200120012903c0053703e003200141a0036a41186a2213200f290300370300200141a0036a41106a220f200e290300370300200141a0036a41086a220e200d290300370300200120012903e0033703a00320014180036a41186a200229030037030020014180036a41106a200329030037030020014180036a41086a2005290300370300200120012903c00337038003200141e0046a41186a22032013290300370300200141e0046a41106a2205200f290300370300200141e0046a41086a220d200e290300370300200120012903a0033703e004200141c0056a41046a220e200141fa026a41046a2f01003b0100200120012801fa023602c005200a4102460d0420014189026a21022000200329030037030020042005290300370300200c200d290300370300200141c0046a41046a200e2f01003b0100200120012903e0043703e005200120012802c0053602c0040240200b450d002007102a0b200141f1046a20012903e005370000200141f9046a200141e0056a41086a29030037000020014181056a200141e0056a41106a29030037000020014189056a200141e0056a41186a290300370000200141b6056a200141c4046a2f01003b0100200120103703e0042001200a3a00f004200120012802c0043601b205200120093703e80420014191056a200229000037000020014199056a200241086a290000370000200141a1056a200241106a290000370000200141a9056a200241186a290000370000200141b1056a200241206a2d00003a0000200141003602e805200142013703e0052001200141e0046a3602c005200141c0056a200141e0056a10a301200141e0046a41106a200141e0056a10a90120012802e40521022008412020012802e005220020012802e805100702402002450d002000102a0b2008102a4101210a0c060b412041011037000b412041011037000b200141c0056a41186a22024200370300200141c0056a41106a22004200370300200141c0056a41086a22034200370300200142003703c00541d3aec400411a200141c0056a1000200141e0046a41186a2002290300370300200141e0046a41106a2000290300370300200141e0046a41086a2003290300370300200120012903c0053703e004200141203602e4052001200141e0046a3602e0052007200141e0056a10ff010c020b41e2bbc00041d8001050000b41c4d1c3004133200141a0046a419cd9c3001038000b410021084100210a0b0240024002400240024020060d00410021020c010b200141003602e00420064120200141e0046a1006210720012802e004220b417f460d012007450d012001200b3602bc05200120073602b8052001200141b8056a109f012001290300a70d0520012802bc052202450d05200141106a29030021092001290308211020012002417f6a22033602bc05200120012802b805220541016a22043602b80520052d0000220241014b0d054100210c0240024020020e020100010b41002102200141003a0080050340024020032002470d00200141003602bc05200241ff0171450d08200141003a0080050c080b200141e0046a20026a200520026a220041016a2d00003a00002001200041026a3602b8052001200241016a22003a0080052000210220004120470d000b20014180046a41106a200141e0046a41106a2903002211370300200141e0056a41086a200141e0046a41086a290300370300200141e0056a41106a2011370300200141e0056a41186a200141e0046a41186a2903003703002001200320006b22033602bc05200120012903e0043703e0054101210c200520006a41016a21040b200141c0056a41186a200141e0056a41186a290300370300200141c0056a41106a200141e0056a41106a290300370300200141c0056a41086a200141e0056a41086a290300370300200120012903e0053703c0052003450d0520012003417f6a22033602bc052001200441016a3602b80520042d0000220241014b0d05410021050240024020020e020100010b41002102200141003a0080050340024020032002470d00200141003602bc05200241ff0171450d08200141003a0080050c080b200141e0046a20026a200420026a220041016a2d00003a00002001200041026a3602b8052001200241016a22003a0080052000210220004120470d000b200141c0046a41086a200141e0046a41086a2903002211370300200141e0056a41186a200141e0046a41186a290300370300200141e0056a41106a200141e0046a41106a290300370300200141e0056a41086a20113703002001200320006b3602bc05200120012903e00422113703c004200120113703e005410121050b200141c0036a41186a2204200141e0056a41186a2202290300370300200141c0036a41106a220d200141e0056a41106a2200290300370300200141c0036a41086a220e200141e0056a41086a2203290300370300200141e0036a41086a220f200141c0056a41086a290300370300200141e0036a41106a2213200141c0056a41106a290300370300200141e0036a41186a2214200141c0056a41186a290300370300200120012903e0053703c003200120012903c0053703e003200141a0036a41186a22152014290300370300200141a0036a41106a22142013290300370300200141a0036a41086a2213200f290300370300200120012903e0033703a00320014180036a41186a220f200429030037030020014180036a41106a2204200d29030037030020014180036a41086a220d200e290300370300200120012903c00337038003200141e0046a41186a220e2015290300370300200141e0046a41106a22152014290300370300200141e0046a41086a22142013290300370300200120012903a0033703e0042002200f290300370300200020042903003703002003200d29030037030020012001290380033703e005200141c0056a41046a2204200141fa026a41046a2f01003b0100200120012801fa023602c005200c4102460d05200141d8026a41186a200e290300370300200141d8026a41106a2015290300370300200141d8026a41086a2014290300370300200141b8026a41086a2003290300370300200141b8026a41106a2000290300370300200141b8026a41186a2002290300370300200141b0026a41046a20042f01003b0100200120012903e0043703d802200120012903e0053703b802200120012802c0053602b0020240200b450d002007102a0b20014191056a20053a000020014192056a20012903b8023701002001419a056a200141b8026a41086a290300370100200141a2056a200141b8026a41106a290300370100200141aa056a200141b8026a41186a290300370100200141b6056a200141b4026a2f01003b0100200120103703e004200120012802b0023601b205200120093703e80420014190056a200141e8016a41206a2d00003a000020014188056a200141e8016a41186a290300370300200141e0046a41206a200141e8016a41106a290300370300200141e0046a41186a200141e8016a41086a290300370300200120012903e8013703f004200141003602e805200142013703e0052001200141e0046a3602c005200141c0056a200141e0056a10a301200141e0046a41106a200141e0056a10a90120012802e40521022006412020012802e005220020012802e805100702402002450d002000102a0b2006102a410121020b200a20084572450d010c020b41e2bbc00041d8001050000b2008102a0b2006452002720d002006102a0b20014180066a24000f0b41c4d1c3004133200141a0046a419cd9c3001038000bde3305097f017e077f037e057f230041a0056b22012400024002400240024002400240411210282202450d0020024100290095ae44370000200241106a41002f00a5ae443b0000200241086a410029009dae4437000020014292808080a00237028c042001200236028804200020014188046a108f0120012802900421022001280288042100200141c8036a41186a22034200370300200141c8036a41106a22044200370300200141c8036a41086a22054200370300200142003703c80320002002200141c8036a1000200141186a2003290300370300200141106a2004290300370300200141086a2005290300370300200120012903c8033703000240200128028c04450d00200128028804102a0b20014100360288042001412020014188046a100621032001280288042204417f460d042003450d04200120043602e404200120033602e00420014180056a200141e0046a106d2001280280052206450d02200128028405210720012802e4042202450d0120012002417f6a22053602e404200120012802e004220841016a22093602e00420082d0000220041014b0d01410021020240024020000e020100010b41002102200141003a00a8040340024020052002470d00200141003602e404200241ff0171450d04200141003a00a8040c040b20014188046a20026a200820026a220041016a2d00003a00002001200041026a3602e0042001200241016a22003a00a8042000210220004120470d000b200141c8036a41086a20014188046a41086a290300220a370300200141a0016a41186a20014188046a41186a290300370300200141a0016a41106a20014188046a41106a290300370300200141a0016a41086a200a3703002001200520006b22053602e4042001200129038804220a3703c8032001200a3703a00141012102200820006a41016a21090b200141a8036a41186a200141a0016a41186a290300370300200141a8036a41106a200141a0016a41106a290300370300200141a8036a41086a200141a0016a41086a290300370300200120012903a0013703a8032005450d0120012005417f6a22083602e4042001200941016a3602e00420092d0000220541014b0d01410021000240024020050e020100010b41002100200141003a00a8040340024020082000470d00200141003602e404200041ff0171450d04200141003a00a8040c040b20014188046a20006a200920006a220541016a2d00003a00002001200541026a3602e0042001200041016a22053a00a8042005210020054120470d000b200141e8036a41086a20014188046a41086a290300220a370300200141a0016a41186a20014188046a41186a290300370300200141a0016a41106a20014188046a41106a290300370300200141a0016a41086a200a3703002001200820056b3602e4042001200129038804220a3703e8032001200a3703a001410121000b200141e8026a41186a2205200141a0016a41186a2208290300370300200141e8026a41106a2209200141a0016a41106a220b290300370300200141e8026a41086a220c200141a0016a41086a220d29030037030020014188036a41086a220e200141a8036a41086a29030037030020014188036a41106a220f200141a8036a41106a29030037030020014188036a41186a2210200141a8036a41186a290300370300200120012903a0013703e802200120012903a80337038803200141c8026a41186a22112010290300370300200141c8026a41106a2210200f290300370300200141c8026a41086a220f200e29030037030020012001290388033703c802200141a8026a41186a220e2005290300370300200141a8026a41106a22052009290300370300200141a8026a41086a2209200c290300370300200120012903e8023703a80220014188046a41186a201129030037030020014188046a41106a201029030037030020014188046a41086a200f290300370300200120012903c802370388042008200e290300370300200b2005290300370300200d2009290300370300200120012903a8023703a0010c030b411241011037000b2007450d002006102a0b410221020b024020024102460d0020014188026a41186a20014188046a41186a29030037030020014188026a41106a20014188046a41106a29030037030020014188026a41086a20014188046a41086a290300370300200141e8016a41086a200141a0016a41086a290300370300200141e8016a41106a200141a0016a41106a290300370300200141e8016a41186a200141a0016a41186a290300370300200120012903880437038802200120012903a0013703e801200120012f0180053b01e60102402004450d002003102a0b2001412010090c020b41c4d1c3004133200141a8036a419cd9c3001038000b410221020b200141c0006a41186a220320014188026a41186a290300370300200141c0006a41106a220420014188026a41106a290300370300200141c0006a41086a220520014188026a41086a290300370300200141206a41086a2208200141e8016a41086a290300370300200141206a41106a2209200141e8016a41106a290300370300200141206a41186a220b200141e8016a41186a2903003703002001200129038802370340200120012903e80137032020014180016a41086a220c200529030037030020014180016a41106a2205200429030037030020014180016a41186a220420032903003703002001200129034037038001200141e0006a41086a22032008290300370300200141e0006a41106a22082009290300370300200141e0006a41186a2209200b29030037030020012001290320370360024020024102460d00200141c2016a220b2001290360370100200141a9016a200c290300370000200141b1016a2005290300370000200141b9016a2004290300370000200141ca016a2003290300370100200141d2016a2008290300370100200141da016a2009290300370100200120023a00a00120012001290380013700a101200120003a00c101410021030240024002400240024002400240024002400240200041ff01714101470d0020014188046a200b10ae0120014180056a41186a20014188046a41186a2202290000220a37030020014180056a41106a20014188046a41106a2200290000221237030020014180056a41086a20014188046a41086a2204290000221337030020012001290088042214370380052002200a37030020002012370300200420133703002001201437038804412010282203450d012003200129038804370000200341186a2002290300370000200341106a2000290300370000200341086a200429030037000020012d00a00121020b0240200241ff01714101460d0020012d00c1014101460d03200141e0046a41186a22024200370300200141e0046a41106a22004200370300200141e0046a41086a22044200370300200142003703e00441a7aec400411a200141e0046a100020014188046a41186a200229030037030020014188046a41106a200029030037030020014188046a41086a2004290300370300200120012903e0043703880420014188046a412010090c080b20014188046a200141a0016a41017210ae0120014180056a41186a20014188046a41186a2202290300220a37030020014180056a41106a20014188046a41106a2200290300221237030020014180056a41086a20014188046a41086a2205290300221337030020012001290388042214370380052002200a37030020002012370300200520133703002001201437038804412010282204450d012004200129038804370000200441186a2002290300370000200441106a2000290300370000200441086a200529030037000020014100360288042004412020014188046a10062109200128028804220d417f460d032009450d032001200d3602cc03200120093602c803200141e8036a200141c8036a106d20012802e8032202450d0520012802ec03210c20012802cc032200450d04200141f0036a280200210820012000417f6a220e3602cc03200120012802c803220f41016a22103602c803200f2d0000220041014b0d044100210b0240024020000e020100010b41002100200141003a00a80403400240200e2000470d00200141003602cc03200041ff0171450d07200141003a00a8040c070b20014188046a20006a200f20006a220541016a2d00003a00002001200541026a3602c8032001200041016a22053a00a8042005210020054120470d000b20014180056a41086a20014188046a41086a29030037030020014180056a41106a20014188046a41106a29030037030020014180056a41186a20014188046a41186a2903003703002001200129038804370380052001200e20056b220e3602cc034101210b200f20056a41016a21100b200141e0046a41186a20014180056a41186a290300370300200141e0046a41106a20014180056a41106a290300370300200141e0046a41086a20014180056a41086a29030037030020012001290380053703e004200e450d042001200e417f6a220e3602cc032001201041016a3602c80320102d0000220041014b0d040240024020000e020100010b41002100200141003a00a80403400240200e2000470d00200141003602cc03200041ff0171450d07200141003a00a8040c070b20014188046a20006a201020006a220541016a2d00003a00002001200541026a3602c8032001200041016a22053a00a8042005210020054120470d000b200141a8036a41106a20014188046a41106a290300220a37030020014180056a41086a20014188046a41086a29030037030020014180056a41106a200a37030020014180056a41186a20014188046a41186a2903003703002001200e20056b3602cc032001200129038804370380050b200141e8026a41186a220020014180056a41186a290300370300200141e8026a41106a220520014180056a41106a290300370300200141e8026a41086a220e20014180056a41086a29030037030020014188036a41086a220f200141e0046a41086a29030037030020014188036a41106a2210200141e0046a41106a29030037030020014188036a41186a2211200141e0046a41186a29030037030020012001290380053703e802200120012903e00437038803200141c8026a41186a22152011290300370300200141c8026a41106a22112010290300370300200141c8026a41086a2210200f29030037030020012001290388033703c802200141a8026a41186a2000290300370300200141a8026a41106a2005290300370300200141a8026a41086a200e290300370300200120012903e8023703a80220014188046a41186a201529030037030020014188046a41106a201129030037030020014188046a41086a2010290300370300200120012903c802370388040c060b412041011037000b412041011037000b200141e0046a41186a22024200370300200141e0046a41106a22004200370300200141e0046a41086a22044200370300200142003703e00441a7aec400411a200141e0046a100020014188046a41186a200229030037030020014188046a41106a200029030037030020014188046a41086a2004290300370300200120012903e004370388042001412036028405200120014188046a36028005200b20014180056a10ff010c040b41e2bbc00041d8001050000b200c450d002002102a0b4102210b0b0240200b4102460d00200141c1016a210020014180056a41186a220520014188046a41186a29030037030020014180056a41106a220e20014188046a41106a29030037030020014180056a41086a220f20014188046a41086a290300370300200120012903880437038005200120012f01e0043b01e8030240200d450d002009102a0b20014195046a2001290380053700002001419d046a200f290300370000200141a5046a200e290300370000200141ad046a20052903003700002001200b3a00940420012008360290042001200c36028c042001200236028804200120012f01e8033b01d604200141b5046a2000290000370000200141bd046a200041086a290000370000200141c5046a200041106a290000370000200141cd046a200041186a290000370000200141d5046a200041206a2d00003a000020014100360288052001420137038005200820014180056a10b40120014194046a210502402008450d00200841057421000340200220014180056a108f01200241206a2102200041606a22000d000b0b200520014180056a10a9012001280284052102200441202001280280052200200128028805100702402002450d002000102a0b0240200128028c04450d00200128028804102a0b2004102a410121090c020b41c4d1c3004133200141a8036a419cd9c3001038000b41002104410021090b0240024002400240024020030d00410021020c010b20014100360288042003412020014188046a100621080240024002400240200128028804220b417f460d002008450d002001200b3602dc04200120083602d804200141a8036a200141d8046a106d4200211220012802a8032202450d0220012802ac03211020012802dc042200450d01200141b0036a350200210a20012000417f6a220c3602dc04200120012802d804220d41016a220f3602d804200d2d0000220041014b0d014100210e0240024020000e020100010b41002100200141003a00a80403400240200c2000470d00200141003602dc04200041ff0171450d04200141003a00a8040c040b20014188046a20006a200d20006a220541016a2d00003a00002001200541026a3602d8042001200041016a22053a00a8042005210020054120470d000b200141c8036a41086a20014188046a41086a290300221337030020014180056a41186a20014188046a41186a29030037030020014180056a41106a20014188046a41106a29030037030020014180056a41086a20133703002001200c20056b220c3602dc04200120012903880422133703c80320012013370380054101210e200d20056a41016a210f0b200141e0046a41186a20014180056a41186a290300370300200141e0046a41106a20014180056a41106a290300370300200141e0046a41086a20014180056a41086a29030037030020012001290380053703e004200c450d012001200c417f6a220c3602dc042001200f41016a3602d804200f2d0000220541014b0d01410021000240024020050e020100010b41002100200141003a00a80403400240200c2000470d00200141003602dc04200041ff0171450d04200141003a00a8040c040b20014188046a20006a200f20006a220541016a2d00003a00002001200541026a3602d8042001200041016a22053a00a8042005210020054120470d000b200141e8036a41086a20014188046a41086a290300221237030020014180056a41186a20014188046a41186a29030037030020014180056a41106a20014188046a41106a29030037030020014180056a41086a20123703002001200c20056b3602dc04200120012903880422123703e8032001201237038005410121000b200141e8026a41186a220520014180056a41186a220c290300370300200141e8026a41106a220d20014180056a41106a220f290300370300200141e8026a41086a221120014180056a41086a221529030037030020014188036a41086a2216200141e0046a41086a29030037030020014188036a41106a2217200141e0046a41106a29030037030020014188036a41186a2218200141e0046a41186a29030037030020012001290380053703e802200120012903e00437038803200141c8026a41186a22192018290300370300200141c8026a41106a22182017290300370300200141c8026a41086a2217201629030037030020012001290388033703c802200141a8026a41186a22162005290300370300200141a8026a41106a2205200d290300370300200141a8026a41086a220d2011290300370300200120012903e8023703a80220014188046a41186a201929030037030020014188046a41106a201829030037030020014188046a41086a2017290300370300200120012903c80237038804200c2016290300370300200f20052903003703002015200d290300370300200120012903a80237038005200a422086210a2010ad21120c030b41e2bbc00041d8001050000b2010450d002002102a0b4102210e4200210a0b200e4102460d0120014188026a41186a20014188046a41186a29030037030020014188026a41106a20014188046a41106a29030037030020014188026a41086a20014188046a41086a290300370300200141e8016a41086a220520014180056a41086a290300370300200141e8016a41106a220c20014180056a41106a290300370300200141e8016a41186a220d20014180056a41186a29030037030020012001290388043703880220012001290380053703e801200120012f01e0043b01e601200a20128421120240200b450d002008102a0b200141b5046a20003a0000200141b6046a20012903e801370100200141be046a2005290300370100200141c6046a200c290300370100200141ce046a200d2903003701002001419c046a200141a0016a41086a290300370200200141a4046a200141a0016a41106a290300370200200141ac046a200141a0016a41186a290300370200200141b4046a200141a0016a41206a2d00003a00002001201237028c042001200236028804200120012f01e6013b01d604200120012903a0013702940420014100360288052001420137038005200a422088a7220020014180056a10b40120014194046a210502402000450d00200041057421000340200220014180056a108f01200241206a2102200041606a22000d000b0b200520014180056a10a9012001280284052102200341202001280280052200200128028805100702402002450d002000102a0b0240200128028c04450d00200128028804102a0b2003102a410121020b200920044572450d010c020b41c4d1c3004133200141a8036a419cd9c3001038000b2004102a0b02402003452002720d002003102a0b2006450d002007450d002006102a0b200141a0056a24000b13002000410d360204200041bcafc4003602000b3400200041d9dbc40036020420004100360200200041146a4113360200200041106a41e0dbc400360200200041086a42073702000b09002000410010e6020b6c01027f230041106b22022400200241003602082002420137030002404104102822030d00410441011037000b2003410036000020024284808080c000370204200220033602004100200210b401200041086a200228020836020020002002290300370200200241106a24000b3001017f02404108102822020d00410841011037000b20004288808080800137020420002002360200200242003700000b8e0201037f230041c0006b22022400200241186a4200370300200241106a22034200370300200241086a4200370300200241286a22044100360200200242003703002002420837032020024100360238200242013703302002200236023c2002413c6a200241306a10a3012002200336023c2002413c6a200241306a10a3012002280220210320042802002204200241306a10b40102402004450d00200441306c21040340200341106a200241306a108f012002200336023c200341306a21032002413c6a200241306a10a301200441506a22040d000b0b20002002290330370200200041086a200241306a41086a28020036020002402002280224450d002002280220102a0b200241c0006a24000b7001027f230041306b2202240020024200370310200242003703082002200241086a36021c02404101102822030d00410141011037000b20024201370224200220033602202002411c6a200241206a10a301200041086a200228022836020020002002290320370200200241306a24000b3001017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241043600000b9c0402057f027e230041d0016b220224002002200110b1040240024020022d00004101470d00200241286a41186a200241196a290000370300200241286a41106a200241116a290000370300200241286a41086a200241096a2900003703002002200229000137032802400240410e10282201450d002001410029008aaf44370000200141066a4100290090af443700002002428e808080e00137026c20022001360268200241286a200241e8006a108f012002280270210120022802682103200241f8006a41186a22044200370300200241f8006a41106a22054200370300200241f8006a41086a220642003703002002420037037820032001200241f8006a1000200241c8006a41186a2004290300370300200241c8006a41106a2005290300370300200241c8006a41086a2006290300370300200220022903783703480240200228026c450d002002280268102a0b20024100360278200241c8006a4120200241f8006a100621040240024020022802782203417f470d00410021010c010b2002200336026c20022004360268200241f8006a200241e8006a108a022002280298012201450d0220024190016a29030021072002290388012108200228029c0121052003450d002004102a0b2001450d022005450d032001102a0c030b410e41011037000b41c4d1c3004133200241c8016a419cd9c3001038000b42002108420021070b2000200837030020002007370308200241d0016a24000bb70301057f230041f0006b220224000240410e10282203450d00200341002900fcae44370000200341066a4100290082af443700002002428e808080e001370254200220033602502001200241d0006a108f012002280258210320022802502101200241086a41186a22044200370300200241086a41106a22054200370300200241086a41086a220642003703002002420037030820012003200241086a1000200241306a41186a2004290300370300200241306a41106a2005290300370300200241306a41086a20062903003703002002200229030837033002402002280254450d002002280250102a0b200241086a200241306a412010fd01200241d0006a41086a200241086a41096a290000370300200241d0006a41106a200241086a41116a290000370300200241d0006a41186a200241086a41196a290000370300200220022900093703500240024020022d00084101460d00200041003a00000c010b200041013a000020002002290350370001200041096a200241d8006a290300370000200041116a200241e0006a290300370000200041196a200241e8006a2903003700000b200241f0006a24000f0b410e41011037000b13002000410236020420004184fcc4003602000b3101017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241a0053600000bdf14030d7f077e0b7f23004180046b22042400024002400240024002400240410d10282205450d0020054100290098af44370000200541056a410029009daf443700002004428d808080d0013702ec02200420053602e8022001200441e8026a108f0120042802f002210520042802e8022106200441a8036a41186a22074200370300200441a8036a41106a22084200370300200441a8036a41086a22094200370300200442003703a80320062005200441a8036a100020044198016a41186a200729030037030020044198016a41106a200829030037030020044198016a41086a2009290300370300200420042903a80337039801024020042802ec02450d0020042802e802102a0b200441003602a80320044198016a4120200441a8036a1006210502400240024020042802a8032206417f460d002005450d002006450d0420052d0000220641034f0d042005102a20060e03000201000b200441f0006a200110b10420042d00704101470d06200441b8016a41186a20044189016a290000370300200441b8016a41106a20044181016a290000370300200441b8016a41086a200441f9006a290000370300200420042900713703b801410e10282205450d042005410029008aaf44370000200541066a4100290090af443700002004428e808080e0013702ec02200420053602e802200441b8016a200441e8026a108f0120042802f002210520042802e8022106200441a8036a41186a22074200370300200441a8036a41106a22084200370300200441a8036a41086a22094200370300200442003703a80320062005200441a8036a100020044198016a41186a200729030037030020044198016a41106a200829030037030020044198016a41086a2009290300370300200420042903a80337039801024020042802ec02450d0020042802e802102a0b200441003602a80320044198016a4120200441a8036a100621070240024020042802a8032206417f470d00410021050c010b200420063602cc02200420073602c802200441a8036a200441c8026a108a0220042802c8032205450d06200441a8026a41186a200441a8036a41186a290300370300200441a8026a41106a200441a8036a41106a290300370300200441a8026a41086a200441a8036a41086a290300370300200441e8026a41086a200441d4036a290200370300200441e8026a41106a200441dc036a290200370300200441e8026a41186a200441e4036a29020037030020044188036a200441ec036a29020037030020044190036a200441f4036a280200360200200420042903a8033703a802200420042902cc033703e8022006450d002007102a0b200441c8026a41086a2209200441a8026a41086a290300370300200441c8026a41106a220a200441a8026a41106a290300370300200441c8026a41186a220b200441a8026a41186a290300370300200441a8036a41086a220c200441e8026a41086a2206290300370300200441a8036a41106a220d200441e8026a41106a2207290300370300200441a8036a41186a220e200441e8026a41186a2208290300370300200441a8036a41206a220f200441e8026a41206a290300370300200441a8036a41286a2210200441e8026a41286a280200360200200420042903a8023703c802200420042903e8023703a80302402005450d0020044188026a41186a200b29030037030020044188026a41106a200a29030037030020044188026a41086a2009290300370300200441d8016a41086a200c290300370300200441d8016a41106a200d290300370300200441d8016a41186a200e290300370300200441d8016a41206a200f290300370300200441d8016a41286a2010280200360200200420042903c80237038802200420042903a8033703d8010b2008200441b8016a41186a2903003703002007200441b8016a41106a2903003703002006200441b8016a41086a290300370300200420042903b8013703e8022005450d06200441306a41206a220c2004290388022211370300200441a8036a41186a2206200441e8026a41186a220d2903002212370300200441a8036a41106a2207200441e8026a41106a220e2903002213370300200441a8036a41086a2208200441e8026a41086a220f2903002214370300200441a8036a41286a20044188026a41086a2903002215370300200441a8036a41306a20044188026a41106a2903002216370300200441a8036a41386a20044188026a41186a2903002217370300200441306a41386a22102017370300200441306a41306a22182016370300200441306a41286a22192015370300200441306a41186a22092012370300200441306a41106a220a2013370300200441306a41086a220b2014370300200420042903e80222123703a803200420113703c80320042012370330200441286a221a200441d8016a41286a280200360200200441206a221b200441d8016a41206a290300370300200441186a221c200441d8016a41186a221d290300370300200441106a221e200441d8016a41106a221f290300370300200441086a2220200441d8016a41086a2221290300370300200420042903d801370300200441e8026a41386a22222010290300370300200441e8026a41306a22102018290300370300200441e8026a41286a22182019290300370300200441e8026a41206a2219200c290300370300200d2009290300370300200e200a290300370300200f200b290300370300200420042903303703e802201d2009290300370300201f200a2903003703002021200b290300370300200420042903303703d801200620222903003703002007201029030037030020082018290300370300200420053602c803200420192903003703a803200441cc036a22052004290300370200200441d4036a2020290300370200200441dc036a201e290300370200200441e4036a201c290300370200200441ec036a201b290300370200200441f4036a201a2802003602002006290300211120072007290300221220027c22133703002006201120037c2013201254ad7c37030020082903002111200420042903a803221220027c22133703a8032008201120037c2013201254ad7c370300200441f0006a20012002200310a50220043502702102200441f0006a41106a2903002111200441f0006a41086a2903002103200441d8016a200441a8036a10b50402402005280200450d0020042802c803102a0b200242018521020c070b200441a8036a200110b10420042d00a8034101470d0520044180036a200441c1036a290000370300200441e8026a41106a200441b9036a290000370300200441e8026a41086a200441b1036a290000370300200420042900a9033703e802200441306a200441e8026a2002200310a50220043502304201852102200441306a41106a2903002111200441306a41086a29030021030c060b200441a8036a20012002200310a50220043502a8034201852102200441b8036a2903002111200441b0036a29030021030c050b410d41011037000b41c4d1c3004133200441f8036a419cd9c3001038000b410e41011037000b41c4d1c3004133200441f8036a419cd9c3001038000b420021020b2000200337030820002002370300200041106a201137030020044180046a24000bc80201057f230041e0006b22022400200242f3e885db96cddbb320370308200241086a2001412c6a2001290300200141086a290300417f410f10a9020240410e10282203450d002003410029008aaf44370000200341066a4100290090af443700002002428e808080e001370234200220033602302000200241306a108f012002280238210320022802302100200241c0006a41186a22044200370300200241c0006a41106a22054200370300200241c0006a41086a220642003703002002420037034020002003200241c0006a1000200241106a41186a2004290300370300200241106a41106a2005290300370300200241106a41086a20062903003703002002200229034037031002402002280234450d002002280230102a0b200241203602442002200241106a3602402001200241c0006a10b604200241e0006a24000f0b410e41011037000bce0101027f230041106b2202240020024100360208200242013703002000412c6a2002108f012002200036020c2002410c6a200210a3012002200041106a36020c2002410c6a200210a30120002802202103200041286a2802002200200210b40102402000450d002003200041186c6a210003402002200336020c2002410c6a200210a301200341106a200210a0012000200341186a2203470d000b0b2002280204210320012802002001280204200228020022002002280208100702402003450d002000102a0b200241106a24000bf30901047f230041e0026b22052400200541a0016a41086a22064200370300200542003703a00141a990c6004119200541a0016a1008200541086a41086a2006290300370300200520052903a00137030841002106200541003602a001200541086a4110200541a0016a10062107024002400240024020052802a0012208417f460d002007450d0020084104490d01200728000021062007102a0b02402006417f6a220720064d0d00200541133602080c020b200541086a200710ca0320052802084113460d01200541a0016a200541086a419801109a051a20052802a8022107200541a0016a106a200720014d0d01200041828ac50036020420004101360200200041086a41c7003602002002106a0c020b41c4d1c3004133200541a0016a419cd9c3001038000b200541a0016a41086a22074200370300200542003703a00141a990c6004119200541a0016a1008200541086a41086a2007290300370300200520052903a0013703082005200641016a3602a001200541086a4110200541a0016a41041007200541a0016a2002418801109a051a200520033a00b002200520043602ac02200520013602a802024002400240024002400240411a10282207450d00200741186a41002f00ce88453b0000200741106a41002900c68845370000200741086a41002900be8845370000200741002900b688453700002007411a4134102c2207450d012007200636001a200541086a41186a22014200370300200541086a41106a22024200370300200541086a41086a22044200370300200542003703082007411e200541086a1000200541b8026a41186a2001290300370300200541b8026a41106a2002290300370300200541b8026a41086a2004290300370300200520052903083703b8022007102a200541003602102005420137030820052802a8022101410410282207450d022005410436020c20052005280210220241046a36021020052007360208200720026a2001360000200541a0016a200541086a10eb01024020052d00b002220741024b0d00024002400240024020070e03000102000b410021010c020b410121010c010b410221010b200520013a00df0202400240200528020c20052802102207460d00200528020821020c010b200741016a22022007490d07200741017422042002200420024b1b22044100480d070240024020070d002004102821020c010b200528020820072004102c21020b2002450d052005200436020c20052002360208200528021021070b2005200741016a360210200220076a20013a00000b20052802ac02210202400240200528020c2201200528021022076b4104490d00200528020821010c010b200741046a22042007490d06200141017422072004200720044b1b22074100480d060240024020010d002007102821010c010b200528020820012007102c21010b2001450d052005200736020c20052001360208200528021021070b2005200741046a360210200120076a2002360000200528020c2107200541b8026a4120200528020822012005280210100702402007450d002001102a0b200541a0016a106a200541ac016a2006360200200541a9016a20033a0000200541a8016a41033a0000200541053a00a00141014100200541a0016a10cc0120004100360200200020063602040c060b411a41011037000b413441011037000b410441011037000b200441011037000b200741011037000b1031000b200541e0026a24000bfe0201047f230041e0006b2202240002400240411310282203450d002003410f6a41002800e38945360000200341086a41002900dc8945370000200341002900d48945370000200341134126102c2203450d0120032001360013200241c0006a41186a22044200370300200241c0006a41106a22054200370300200241c0006a41086a220142003703002002420037034020034117200241c0006a1000200241186a2004290300370300200241106a2005290300370300200241086a2001290300370300200220022903403703002003102a200241c0006a200210e003200241306a41086a2001290300370300200241206a41086a200241c0006a411c6a2802003602002002200229034037033020022002290254370320024020022802502203450d002000200229033037030020002002290320370214200041086a200241306a41086a2903003703002000411c6a200241206a41086a2802003602000b20002003360210200241e0006a24000f0b411341011037000b412641011037000b130020004111360204200041cc8bc5003602000b3400200041f9aac50036020420004100360200200041146a410f360200200041106a4184abc500360200200041086a42093702000b4f01027f230041106b2202240002404101102822030d00410141011037000b200341003a0000200041086a4101360200200241013602042002200336020020002002290300370200200241106a24000b5b01027f23004190016b22022400200241133602000240410110282203450d00200341003a0000200042818080801037020420002003360200024020022802004113460d002002106a0b20024190016a24000f0b410141011037000bfd0201057f230041c0006b22022400200241206a4200370300200241186a4200370300200241086a41086a4200370300200241003a0028200242003703082002410036023820024201370330200241086a200241306a108f0102400240024020022d0028220341064b0d000240024002400240024002400240024020030e0700010203040506000b410021040c060b410121040c050b410221040c040b410321040c030b410421040c020b410521040c010b410621040b200220043a003f02400240200228023420022802382203460d00200228023021050c010b200341016a22052003490d03200341017422062005200620054b1b22064100480d030240024020030d002006102821050c010b200228023020032006102c21050b2005450d022002200636023420022005360230200228023821030b2002200341016a360238200520036a20043a00000b20002002290330370200200041086a200241306a41086a280200360200200241c0006a24000f0b200641011037000b1031000b4001017f230041106b2202240020024100360208200242013703004100200210b401200041086a200228020836020020002002290300370200200241106a24000b130020004106360204200041acc7c5003602000b3201017f02404104102822020d00410441011037000b20004284808080c00037020420002002360200200241809c313600000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180a3053600000b3e01017f02404110102822020d00411041011037000b20024200370008200242808084fea6dee111370000200042908080808002370204200020023602000b3201017f02404104102822020d00410441011037000b20004284808080c0003702042000200236020020024180de343600000ba30301047f230041c0006b22022400024002400240411310282203450d002003410f6a41002800e38945360000200341086a41002900dc8945370000200341002900d48945370000200341134126102c2203450d0120032000360013200241206a41186a22004200370300200241206a41106a22044200370300200241206a41086a220542003703002002420037032020034117200241206a1000200241186a2000290300370300200241106a2004290300370300200241086a2005290300370300200220022903203703002003102a411010282203450d02200320012903003700002003200141086a2903003700082002429080808080023702242002200336022020012802102104200141186a2802002203200241206a10b40102402003450d00200341057421002004210303402003200241206a108f01200341206a2103200041606a22000d000b0b2002280224210320024120200228022022002002280228100702402003450d002000102a0b0240200141146a280200450d002004102a0b200241c0006a24000f0b411341011037000b412641011037000b411041011037000bc01401077f230041d0016b2204240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240411a10282205450d00200541186a41002f00ce88453b0000200541106a41002900c68845370000200541086a41002900be8845370000200541002900b688453700002005411a4134102c2205450d012005200136001a200441e0006a41186a22064200370300200441e0006a41106a22074200370300200441e0006a41086a22084200370300200442003703602005411e200441e0006a1000200441306a41186a2006290300370300200441306a41106a2007290300370300200441306a41086a2008290300370300200420042903603703302005102a0240200441306a41204101410041001003417f470d0041b7d5c50021000c110b200441146a200041086a2900003702002004411c6a200041106a290000370200200441246a200041186a290000370200200420013602082004200029000037020c411010282205450d02200541002900a68845370000200541086a41002900ae88453700002004429080808080023702b401200420053602b001200541104120102c2205450d03200441203602b401200420042802b801220641046a3602b801200420053602b001200520066a2001360000200441086a410472200441b0016a108f0120042802b801210520042802b0012106200441e0006a41186a22074200370300200441e0006a41106a22084200370300200441e0006a41086a220942003703002004420037036020062005200441e0006a1000200441306a41186a2007290300370300200441306a41106a2008290300370300200441306a41086a200929030037030020042004290360370330024020042802b401450d0020042802b001102a0b200441306a41204101410041001003417f470d0f200441086a41186a200041186a290000370300200441086a41106a200041106a290000370300200441086a41086a200041086a29000037030020042000290000370308411310282205450d042005410f6a41002800a88945360000200541086a41002900a18945370000200541002900998945370000200541134126102c2205450d0520052001360013200441e0006a41186a22064200370300200441e0006a41106a22074200370300200441e0006a41086a220842003703002004420037036020054117200441e0006a1000200441306a41186a2006290300370300200441306a41106a2007290300370300200441306a41086a2008290300370300200420042903603703302005102a20044100360260200441306a4120200441e0006a100621050240024020042802602207417f460d002007210620050d010b20044100360268200442013703604100200441e0006a10b4012004280268210620042802642107200428026021050b200420063602582004200736025420042005360250024002402006450d00200441e0006a20052006410110d60220042802604101470d012004280254450d102004280250102a0c100b4101200441d0006a10b401200441086a200441d0006a108f010c0d0b200428026421080240200441ec006a2802002205200441e8006a2802002206460d002004280258200520066b6a220741206a2209417f4c0d070240024020090d004101210a0c010b20091028220a450d090b20042009360284012004200a360280012004200736028801200420044180016a3602602008200441e0006a200510d70120072005490d0920042802880122082007490d0a200428025822082006490d0b20042802800121092004280250210a2004200720056b2207360290012004200820066b22083602940120072008470d0c200920056a200a20066a2007109a051a200441086a20044180016a108f012004280288012106200428028401210720042802800121052004280254450d0e2004280250102a0c0e0b2004200441d0006a3602602008200441e0006a200610d701200441086a200441d0006a108f010c0c0b411a41011037000b413441011037000b411041011037000b412041011037000b411341011037000b412641011037000b1036000b200941011037000b200520071044000b20072008103c000b200620081044000b200441b0016a41146a4108360200200441bc016a412536020020044198016a41146a41033602002004420337029c01200441c8afc60036029801200441253602b401200420044190016a3602c801200420044194016a3602cc0120044204370370200442013702642004419cb0c6003602602004200441b0016a3602a8012004200441e0006a3602c0012004200441cc016a3602b8012004200441c8016a3602b00120044198016a41d8b0c600103e000b2004280258210620042802542107200428025021050b2005450d00200441306a41202005200610072007450d012005102a0c010b412010282206450d0220062004290308370000200641186a200441086a41186a290300370000200641106a200441086a41106a290300370000200641086a200441086a41086a290300370000411310282207450d03410021052007410f6a41002800a88945360000200741086a41002900a18945370000200741002900998945370000200741134126102c2207450d0420072001360013200441e0006a41186a22084200370300200441e0006a41106a22094200370300200441e0006a41086a220a42003703002004420037036020074117200441e0006a1000200441306a41186a2008290300370300200441306a41106a2009290300370300200441306a41086a200a290300370300200420042903603703302007102a20044100360268200442013703604101200441e0006a10b4010340200620056a200441e0006a108f014120200541206a2205470d000b20042802642105200441306a4120200428026022072004280268100702402005450d002007102a0b2006102a0b200441146a200041086a2900003702002004411c6a200041106a290000370200200441246a200041186a290000370200200420013602082004200029000037020c411010282205450d04200541002900a68845370000200541086a41002900ae88453700002004429080808080023702b401200420053602b001200541104120102c2205450d05200441203602b401200420042802b801220041046a3602b801200420053602b001200520006a2001360000200441086a410472200441b0016a108f0120042802b801210520042802b0012100200441e0006a41186a22064200370300200441e0006a41106a22014200370300200441e0006a41086a220742003703002004420037036020002005200441e0006a1000200441306a41186a2006290300370300200441306a41106a2001290300370300200441306a41086a200729030037030020042004290360370330024020042802b401450d0020042802b001102a0b410110282205450d0641002100200541807f410020021b2003723a0000200441306a41202005410110072005102a0b200441d0016a240020000f0b412041011037000b411341011037000b412641011037000b411041011037000b412041011037000b410141011037000bc76501037f230041206b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020002d00000eac010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab0100010b2002200128021841dfd6c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000cab010b2002200128021841f0d6c500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000caa010b2002200128021841fbd6c50041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca9010b2002200128021841fed6c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a4184d7c500105d21000ca8010b200220012802184194d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a4184d7c500105d21000ca7010b200220012802184198d7c50041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a4184d7c500105d21000ca6010b20022001280218419ad7c50041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca5010b20022001280218419ed7c50041032001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca4010b2002200128021841a1d7c50041022001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000ca3010b2002200128021841a3d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000ca2010b2002200128021841a7d7c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41b0d7c500105d21000ca1010b2002200128021841c0d7c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000ca0010b2002200128021841c6d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c9f010b2002200128021841cad7c500410c2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041016a36020c20012002410c6a41d8d7c500105d21000c9e010b2002200128021841e8d7c50041042001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9d010b2002200128021841ecd7c50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c9c010b2002200128021841f2d7c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c9b010b2002200128021841fad7c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c9a010b200220012802184182d8c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c99010b20022001280218418ad8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c98010b200220012802184193d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c97010b20022001280218419cd8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c96010b2002200128021841a3d8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c95010b2002200128021841aad8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c94010b2002200128021841b1d8c50041072001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c93010b2002200128021841b8d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c92010b2002200128021841c1d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c91010b2002200128021841cad8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c90010b2002200128021841d4d8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8f010b2002200128021841ded8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8e010b2002200128021841e7d8c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8d010b2002200128021841f0d8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8c010b2002200128021841fad8c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8b010b200220012802184184d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c8a010b20022001280218418ed9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c89010b200220012802184198d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c88010b2002200128021841a0d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c87010b2002200128021841a8d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c86010b2002200128021841b0d9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c85010b2002200128021841b8d9c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c84010b2002200128021841c1d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c83010b2002200128021841cbd9c50041092001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c82010b2002200128021841d4d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c81010b2002200128021841ded9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21012002200041086a36020c20012002410c6a41a8d6c500105d21000c80010b2002200128021841e8d9c500410d2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41d8d7c500105d21000c7f0b2002200128021841f5d9c500410a2001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041016a36020c200241106a2002410c6a41d8d7c500105d21000c7e0b2002200128021841ffd9c50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a4188dac500105d21000c7d0b200220012802184198dac50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41a0dac500105d21000c7c0b2002200128021841b0dac50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041046a36020c200241106a2002410c6a41a8d6c500105d21000c7b0b2002200128021841b8dac50041082001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200041086a36020c200241106a2002410c6a41c0dac500105d21000c7a0b2002200128021841d0dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c790b2002200128021841d6dac50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c780b2002200128021841dbdac50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c770b2002200128021841e0dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c760b2002200128021841e6dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c750b2002200128021841ecdac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c740b2002200128021841f2dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c730b2002200128021841f8dac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c720b2002200128021841fedac50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c710b200220012802184184dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c700b20022001280218418adbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6f0b200220012802184190dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6e0b200220012802184196dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6d0b20022001280218419bdbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6c0b2002200128021841a0dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6b0b2002200128021841a6dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c6a0b2002200128021841acdbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c690b2002200128021841b2dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c680b2002200128021841b8dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c670b2002200128021841bedbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c660b2002200128021841c4dbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c650b2002200128021841cadbc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c640b2002200128021841d0dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c630b2002200128021841d5dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c620b2002200128021841dadbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c610b2002200128021841dfdbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c600b2002200128021841e4dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5f0b2002200128021841e9dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5e0b2002200128021841eedbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5d0b2002200128021841f3dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5c0b2002200128021841f8dbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5b0b2002200128021841fddbc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c5a0b200220012802184182dcc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c590b200220012802184187dcc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c580b20022001280218418cdcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c570b200220012802184192dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c560b200220012802184198dcc50041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c550b2002200128021841a1dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c540b2002200128021841a7dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c530b2002200128021841addcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c520b2002200128021841b3dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c510b2002200128021841badcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c500b2002200128021841c1dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4f0b2002200128021841c8dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4e0b2002200128021841cfdcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4d0b2002200128021841d5dcc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4c0b2002200128021841dadcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4b0b2002200128021841e0dcc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c4a0b2002200128021841e6dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c490b2002200128021841eddcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c480b2002200128021841f4dcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c470b2002200128021841fbdcc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c460b200220012802184182ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c450b200220012802184188ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c440b20022001280218418eddc50041092001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c430b200220012802184197ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c420b20022001280218419dddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c410b2002200128021841a3ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c400b2002200128021841a9ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3f0b2002200128021841b0ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3e0b2002200128021841b7ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3d0b2002200128021841beddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3c0b2002200128021841c5ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3b0b2002200128021841cbddc50041052001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c3a0b2002200128021841d0ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c390b2002200128021841d6ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c380b2002200128021841dcddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c370b2002200128021841e3ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c360b2002200128021841eaddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c350b2002200128021841f1ddc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c340b2002200128021841f8ddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c330b2002200128021841feddc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c320b200220012802184184dec50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c310b20022001280218418bdec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c300b200220012802184193dec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2f0b20022001280218419bdec500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2e0b2002200128021841a5dec50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2d0b2002200128021841acdec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2c0b2002200128021841b2dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2b0b2002200128021841b8dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c2a0b2002200128021841bedec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c290b2002200128021841c4dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c280b2002200128021841cadec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c270b2002200128021841d0dec500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c260b2002200128021841dbdec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c250b2002200128021841e1dec50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c240b2002200128021841e7dec50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c230b2002200128021841eedec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c220b2002200128021841f6dec50041082001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c210b2002200128021841fedec500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c200b200220012802184188dfc50041072001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1f0b20022001280218418fdfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1e0b200220012802184195dfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1d0b20022001280218419bdfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1c0b2002200128021841a1dfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1b0b2002200128021841a7dfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c1a0b2002200128021841addfc50041062001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c190b2002200128021841b3dfc500410b2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c180b2002200128021841bedfc500410a2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c170b2002200128021841c8dfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c160b2002200128021841d4dfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c150b2002200128021841e0dfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c140b2002200128021841ecdfc500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c130b2002200128021841f8dfc500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c120b200220012802184185e0c500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c110b200220012802184192e0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c100b20022001280218419ee0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0f0b2002200128021841aae0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0e0b2002200128021841b6e0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0d0b2002200128021841c2e0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0c0b2002200128021841d0e0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0b0b2002200128021841dee0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c0a0b2002200128021841ece0c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c090b2002200128021841fae0c500410c2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c080b200220012802184186e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c070b200220012802184194e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c060b2002200128021841a2e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c050b2002200128021841b0e1c500410e2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c040b2002200128021841bee1c500410d2001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c030b2002200128021841cbe1c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c020b2002200128021841dce1c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000c010b2002200128021841ede1c50041112001411c6a28020028020c1100003a001820022001360210200241003a001920024100360214200241106a21000b20002d00082101024020002802042203450d00200141ff0171210441012101024020040d00024020034101470d0020002d0009450d00200028020022042d00004104710d0041012101200428021841f4afc00041012004411c6a28020028020c1100000d010b2000280200220128021841c8a4c60041012001411c6a28020028020c11000021010b200020013a00080b200241206a2400200141ff01714100470bcd0203027f017e017f23004180016b220224002000280200210002400240024002400240200128020022034110710d002000280200210020034120710d012000ac22042004423f8722047c2004852000417f73411f762001103f21000c020b20002802002103410021000340200220006a41ff006a2003410f712205413072200541d7006a2005410a491b3a00002000417f6a2100200341047622030d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021030340200220036a41ff006a2000410f712205413072200541376a2005410a491b3a00002003417f6a2103200041047622000d000b20034180016a22004181014f0d0220014101419087c0004102200220036a4180016a410020036b104221000b20024180016a240020000f0b20034180011044000b20004180011044000bcd0202027f027e23004180016b220224002000280200210002400240024002400240200128020022034110710d002000290300210420034120710d0120042004423f8722057c2005852004427f552001103f21000c020b20002903002104410021000340200220006a41ff006a2004a7410f712203413072200341d7006a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004a7410f712203413072200341376a2003410a491b3a00002000417f6a2100200442048822044200520d000b20004180016a22034181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20034180011044000b20034180011044000bc00201037f23004180016b220224002000280200210002400240024002400240200128020022034110710d0020002d0000210420034120710d012004ad42ff018341012001103f21000c020b20002d00002104410021000340200220006a41ff006a2004410f712203413072200341d7006a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000c010b410021000340200220006a41ff006a2004410f712203413072200341376a2003410a491b3a00002000417f6a21002004410476410f7122040d000b20004180016a22044181014f0d0220014101419087c0004102200220006a4180016a410020006b104221000b20024180016a240020000f0b20044180011044000b20044180011044000bd30101017f230041106b22022400024002400240024020002d00000e03010200010b2002200128021841fee1c500410b2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b200220012802184189e2c500410c2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b200220012802184195e2c500410d2001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000b8a0201027f230041106b2202240020002802002802002100200128021841b8d6c500410b2001411c6a28020028020c1100002103200241003a0005200220033a0004200220013602002002200036020c200241c3d6c50041052002410c6a41c8d6c500105c21012002200041086a36020c200141d8d6c50041072002410c6a41a8d6c500105c1a20022d00042101024020022d0005450d00200141ff0171210041012101024020000d0020022802002201411c6a28020028020c210020012802182103024020012d00004104710d00200341eeafc0004102200011000021010c010b200341f0afc0004101200011000021010b200220013a00040b200241106a2400200141ff01714100470b890501047f230041d0006b220224002000280200220041046a28020021032000280200210041012104200128021841adafc00041012001411c6a28020028020c110000210502402003450d0020022000360204024020050d00024020012d0000410471450d0041012104200128021841afafc0004101200128021c28020c1100000d012001280200210541012104200241013a001720022005360218200241b0afc00036023420022001290218370308200220012d00303a00482002200128020436021c200220012902283703402002200129022037033820022001290210370328200220012902083703202002200241176a3602102002200241086a360230200241046a200241186a10d8010d01200228023041c8afc0004102200228023428020c11000021040c010b200241046a200110d80121040b024020034101470d00200421050c010b200041046a21002003410274417c6a210320042105034020022000360204200541ff0171210441012105024020040d00024020012802002204410471450d00200241013a001720022004360218200241b0afc00036023420022001290218370308200220012d00303a00482002200128020436021c200220012902283703402002200129022037033820022001290210370328200220012902083703202002200241176a3602102002200241086a360230200241046a200241186a10d8010d01200228023041c8afc0004102200228023428020c11000021050c010b200128021841caafc0004102200128021c28020c1100000d00200241046a200110d80121050b200041046a21002003417c6a22030d000b0b41012100024020050d00200128021841aeafc0004101200128021c28020c11000021000b200241d0006a240020000b19002000200141186a280200360204200020012802103602000bc50201037f230041206b2202240002400240200028020022002d00004104470d002002200128021841b7e2c50041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841bfe2c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41c4e2c500105d210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470b0c002000280200200110d0040b8f0201017f230041106b220224000240024002400240024020002d00000e0401020300010b2002200128021841d4e2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c030b2002200128021841d7e2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c020b2002200128021841dae2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841dde2c50041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040b200241106a240020000bc00201037f230041206b220224000240024020002d00004104470d002002200128021841b7e2c50041082001411c6a28020028020c11000022003a001820022001360210200241003a0019200241003602140c010b2002200128021841bfe2c50041052001411c6a28020028020c1100003a001820022001360210200241003a0019200241003602142002200036020c200241106a2002410c6a41c4e2c500105d210120022d0018210020022802142203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241206a2400200041ff01714100470b0c002000280200200110c6040bed0902067f017e024020010d00200041ac013a00000f0b024002400240024002400240024020012d00002202414f6a41fb004f0d000c010b02400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e312c2c0001022c2c0304052c06072c2c08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292c0b20012d00012103410221020c2b0b20012d00012103410321020c2a0b20012d00012103410421020c290b200141046a2802002104410721020c270b200141046a2802002104410821020c260b200141046a2802002105410c10282204450d272005280204220641ffffffff03712006470d2820064102742201417f4c0d280240024020010d00410421070c010b200110282207450d2a0b02402006450d00200528020021012006410274210320072102034020022001280200360200200241046a2102200141046a21012003417c6a22030d000b0b200420063602042004200736020020042005280208360208410921020c250b200141046a2802002104410b21020c240b200141046a280200210420012d00012103410c21020c240b200141046a2802002104410f21020c220b200141046a2802002104411021020c210b200141046a2802002104411121020c200b200141046a2802002104411221020c1f0b200141046a2802002104411321020c1e0b200141046a280200210420013502082108411421020c1d0b200141046a280200210420013502082108411521020c1c0b200141046a280200210420013502082108411621020c1b0b200141046a280200210420013502082108411721020c1a0b200141046a280200210420013502082108411821020c190b200141046a280200210420013502082108411921020c180b200141046a280200210420013502082108411a21020c170b200141046a280200210420013502082108411b21020c160b200141046a280200210420013502082108411c21020c150b200141046a280200210420013502082108411d21020c140b200141046a280200210420013502082108411e21020c130b200141046a280200210420013502082108411f21020c120b200141046a280200210420013502082108412021020c110b200141046a280200210420013502082108412121020c100b200141046a280200210420013502082108412221020c0f0b200141046a280200210420013502082108412321020c0e0b200141046a280200210420013502082108412421020c0d0b200141046a280200210420013502082108412521020c0c0b200141046a280200210420013502082108412621020c0b0b200141046a280200210420013502082108412721020c0a0b200141046a280200210420013502082108412821020c090b200141046a280200210420013502082108412921020c080b200141046a280200210420013502082108412a21020c070b20012d00012103412b21020c070b20012d00012103412c21020c060b200141046a2802002104412d21020c040b20012903082108412e21020c020b200141046a2802002104412f21020c020b20012903082108413021020b0b0b200020033a0001200020023a0000200041086a2008370300200041046a20043602000f0b410c41041037000b1036000b200141041037000bba0201037f230041106b220224000240024020002802000d002002200128021841e0e2c50041042001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b2002200128021841e4e2c50041042001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41e8e2c500105d210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470b22002001419daec0004198aec00020002802002d000022001b4104410520001b10450bd60501087f230041106b220324002002280208220441546a2105200241106a280200220641306c210702400340410021082007450d01200741506a21072005412c6a2109200541306a220a210520092d00004103470d000b200a41086a2802002207450d00200741286c2105200a28020041186a2107410021080340200820072d0000456a2108200741286a2107200541586a22050d000b0b02400240024002400240024002400240200120086b220a20014b0d00200641306c2107200441546a210503402007450d02200741506a21072005412c6a2108200541306a2209210520082d0000410c470d000b200941086a280200200a4b0d02411e102822070d05411e41011037000b412c102822070d02412c41011037000b412c102822070d02412c41011037000b2009280200200a41186c6a28020821072003200a200210dd0420032802004101460d0320032802042105200041003602002000200520076a3602040c040b2000200736020420004101360200200741286a41002800fee545360000200741206a41002900f6e545370000200741186a41002900eee545370000200741106a41002900e6e545370000200741086a41002900dee545370000200741002900d6e545370000200041086a42ac808080c0053702000c030b2000200736020420004101360200200741286a41002800aae645360000200741206a41002900a2e645370000200741186a410029009ae645370000200741106a4100290092e645370000200741086a410029008ae64537000020074100290082e645370000200041086a42ac808080c0053702000c020b2000200736020420004101360200200741166a41002900c4e645370000200741106a41002900bee645370000200741086a41002900b6e645370000200741002900aee645370000200041086a429e808080e0033702000c010b20002003290204370204200041013602002000410c6a2003410c6a2802003602000b200341106a24000b8d0301067f230041106b220224000240024002400240200041046a2802002203200041086a28020022046b20012802042205200128020022066b4104762207490d00200028020021030c010b200420076a22062004490d02200341017422052006200520064b1b220641ffffffff00712006470d02200641047422054100480d020240024020030d002005102821030c010b200028020020034104742005102c21030b2003450d0120002003360200200041046a2006360200200041086a280200210420012802042105200128020021060b0240024020062005470d00410021060c010b2001200641106a3602000b2002200610d304024020022d000041ac01460d00200320044104746a2106034020062002290300370300200641086a200241086a29030037030002400240200128020022052001280204470d00410021050c010b2001200541106a3602000b200441016a2104200641106a21062002200510d30420022d000041ac01470d000b0b200041086a2004360200200241106a24000f0b200541081037000b1031000b1000200028020035020041012001103f0be00a01067f024002400240024020012d00002202414f6a41fb00490d0002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020020e312a2a0001022a2a0304052a06072a2a08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a0b200020012d00013a0001200041023a00000f0b200020012d00013a0001200041033a00000f0b200020012d00013a0001200041043a00000f0b200041046a200141046a280200360200200041073a00000f0b200041046a200141046a280200360200200041083a00000f0b200141046a2802002103410c10282204450d252003280204220541ffffffff03712005470d2620054102742201417f4c0d260240024020010d00410421060c010b200110282206450d280b02402005450d00200328020021012005410274210720062102034020022001280200360200200241046a2102200141046a21012007417c6a22070d000b0b200420053602042004200636020020042003280208360208200041046a2004360200200041093a00000f0b200041046a200141046a2802003602002000410b3a00000f0b200020012d00013a0001200041046a200141046a2802003602002000410c3a00000f0b200041046a200141046a2802003602002000410f3a00000f0b200041046a200141046a280200360200200041103a00000f0b200041046a200141046a280200360200200041113a00000f0b200041046a200141046a280200360200200041123a00000f0b200041046a200141046a280200360200200041133a00000f0b200041046a200141046a290200370200200041143a00000f0b200041046a200141046a290200370200200041153a00000f0b200041046a200141046a290200370200200041163a00000f0b200041046a200141046a290200370200200041173a00000f0b200041046a200141046a290200370200200041183a00000f0b200041046a200141046a290200370200200041193a00000f0b200041046a200141046a2902003702002000411a3a00000f0b200041046a200141046a2902003702002000411b3a00000f0b200041046a200141046a2902003702002000411c3a00000f0b200041046a200141046a2902003702002000411d3a00000f0b200041046a200141046a2902003702002000411e3a00000f0b200041046a200141046a2902003702002000411f3a00000f0b200041046a200141046a290200370200200041203a00000f0b200041046a200141046a290200370200200041213a00000f0b200041046a200141046a290200370200200041223a00000f0b200041046a200141046a290200370200200041233a00000f0b200041046a200141046a290200370200200041243a00000f0b200041046a200141046a290200370200200041253a00000f0b200041046a200141046a290200370200200041263a00000f0b200041046a200141046a290200370200200041273a00000f0b200041046a200141046a290200370200200041283a00000f0b200041046a200141046a290200370200200041293a00000f0b200041046a200141046a2902003702002000412a3a00000f0b200020012d00013a00012000412b3a00000f0b200020012d00013a00012000412c3a00000f0b200041046a200141046a2802003602002000412d3a00000f0b200041086a200141086a2903003703002000412e3a00000f0b200041046a200141046a2802003602002000412f3a00000f0b200041086a200141086a290300370300413021020b200020023a00000f0b410c41041037000b1036000b200141041037000bea0302057f017e02402001450d00034020002802940321002001417f6a22010d000b0b02402002450d004100210341002101034002400240200120002f01064f0d00200020014105746a220441c4006a2802002105200441386a2802002106200441346a2802002107200141016a21010c010b02400240200028020022010d002003ad210841002104410021010c010b20003301044220862003ad842108410121040b2000102a2008a72103024002402008422088a7220620012f01064f0d00200121050c010b034002400240200128020022050d002003ad2108410021050c010b200441016a210420013301044220862003ad8421080b2001102a2008a72103200521012008422088a7220620052f01064f0d000b0b200641027420056a4198036a2802002100200520064105746a220141c4006a2802002105200141386a2802002106200141346a280200210702402004417f6a2201450d00034020002802940321002001417f6a22010d000b0b410021010b20054102460d012002417f6a210202402006450d002007102a0b20020d000b0b0240200041f8b9c000460d00200028020021012000102a2001450d00200128020021052001102a2005450d00024020052802002201450d0003402005102a2001210520012802002200210120000d000b0b2005102a0b0bba09010b7f230041e0006b22032400200320013602202002280208220441546a2105200241106a280200220641306c210202400340024020020d00410021070c020b200241506a21022005412c6a2107200541306a2208210520072d00004102470d000b200341186a200810fa0320032802182107200328021c21020b2002410020071b2109200641306c2102200441546a21052007410420071b210a02400340024020020d004100210b0c020b200241506a21022005412c6a2107200541306a2208210520072d00004104470d000b200341106a200810fa032003280210210b2003280214210c0b200641306c2102200441546a2105200b4104200b1b210d02400240024002400240024003402002450d01200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200841086a2802002202450d00200241286c2107200828020041186a2102410021050340200520022d0000456a2105200241286a2102200741586a22070d000b200520014d0d01200641306c2102200441546a2105024003402002450d01200241506a21022005412c6a2107200541306a2208210520072d00004103470d000b200341086a200810fa0320032802082202200328020c41286c6a21070240024002400340024002400240200720026b41f8004b0d0020022007460d0d2002411c6a2105034020022d0018450d02200541286a2105200241286a22022007470d000c0e0b0b20022d00180d01200241186a2105200241286a21080c040b2005410c6a21080c040b200241c0006a22052d0000450d010240200241e8006a22052d0000450d0020024190016a2105200241a0016a2208210220052d00000d010c030b0b200241f8006a21080c010b200241d0006a21080b200541046a21050b2001450d0303402001417f6a210120082102024002400340024002400240200720026b41f8004b0d0020022007460d0d2002411c6a2105034020022d0018450d02200541286a2105200241286a22022007460d0e0c000b0b20022d00180d01200241186a2105200241286a21080c040b2005410c6a210820010d040c080b200241c0006a22052d0000450d010240200241e8006a22052d0000450d0020024190016a2105200241a0016a2208210220052d00000d010c030b0b200241f8006a21080c010b200241d0006a21080b20010d000b200541046a21050c030b41cce6c50041c2001050000b410021050b0240200c4100200b1b200120056b22024d0d00200d20024102746a22050d010b200341cc006a41013602002003420237023c200341ece7c5003602382003410136022c2003200341286a3602482003200341206a360228200341d0006a200341386a1033200341d0006a21020c010b2003200528020022023602240240200920024d0d00200a20024104746a2202450d0020002002360204410021020c020b200341cc006a4102360200200341dc006a41013602002003420337023c200341fce7c500360238200341013602542003200341d0006a3602482003200341206a3602582003200341246a360250200341286a200341386a1033200341286a21020b20022802002105200041086a200229020437020020002005360204410121020b20002002360200200341e0006a24000f0b418ee7c50041dd001050000bf80d01067f0240024020002d00002201410e4b0d00024002400240024002400240024002400240024002400240024020010e0f0001020304050607080e090e0a0b0c000b200041086a280200450d0d200041046a280200102a0f0b0240200041086a280200450d00200041046a280200102a0b200041146a280200450d0c200041106a280200102a0f0b02402000410c6a2802002202450d00200041046a28020021012002410474210203400240200141046a280200450d002001280200102a0b200141106a2101200241706a22020d000b0b200041086a280200450d0b2000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241286c210203400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200241586a22020d000b0b200041086a280200450d0a2000280204102a0f0b200041086a280200450d09200041046a280200102a0f0b200041086a280200450d08200041046a280200102a0f0b200041086a280200450d07200041046a280200102a0f0b02402000410c6a2802002201450d00200041046a280200220320014104746a21040340024020032802082202450d0020032802002101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341106a21010240200341046a280200450d002003280200102a0b2001210320012004470d000b0b200041086a280200450d062000280204102a0f0b02402000410c6a2802002202450d00200041046a2802002101200241146c210203400240200141046a280200450d002001280200102a0b200141146a21012002416c6a22020d000b0b200041086a280200450d052000280204102a0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102a0b2003411c6a21010240200341146a280200450d002003280210102a0b2001210320012004470d000b0b200041086a280200450d042000280204102a0f0b02402000410c6a2802002201450d00200041046a2802002203200141186c6a210403400240200341046a280200450d002003280200102a0b0240200341146a2802002202450d00200328020c2101200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341186a21010240200341106a280200450d00200328020c102a0b2001210320012004470d000b0b200041086a280200450d032000280204102a0f0b02402000410c6a2802002201450d00200041046a28020022032001411c6c6a21040340024020032802042201450d0002402003410c6a2802002202450d00200241047421020340024020012d00004109470d000240200141046a2205280200220628020441ffffffff0371450d002006280200102a200528020021060b2006102a0b200141106a2101200241706a22020d000b0b200341086a280200450d002003280204102a0b2003411c6a21010240200341146a280200450d002003280210102a0b2001210320012004470d000b0b200041086a280200450d022000280204102a0f0b0240200041046a2802002201450d00200041086a280200450d002001102a0b0240200041146a2802002201450d0002402000411c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200041186a280200450d002000280214102a0b200041246a2802002203450d0102402000412c6a2802002201450d00200320014104746a210403402003220541106a2103024020052802042201450d0002402005410c6a2802002202450d002002410c6c21020340024020012802002206450d00200141046a280200450d002006102a0b2001410c6a2101200241746a22020d000b0b200541086a280200450d002005280204102a0b20032004470d000b0b200041286a280200450d012000280224102a0c010b0240200041086a280200450d00200041046a280200102a0b0240200041146a2802002201450d00200041186a280200450d002001102a0b200041246a280200450d00200041206a280200102a0f0b0bd65e010c7f23004190016b220324002003200136021c2002280208220441546a2105200241106a280200220641306c21010240024002400240024002400240024002400240024002400240024003402001450d01200141506a21012005412c6a2107200541306a2208210520072d00004104470d000b200641306c2101200441546a210503402001450d02200141506a21012005412c6a2107200541306a2209210520072d0000410c470d000b200641306c2101200441546a210503402001450d03200141506a21012005412c6a2107200541306a2204210520072d00004102470d000b02404100280280b1464105490d002003410136023c20032003411c6a3602384100280284b146210120034188016a41980136020020034180016a42ed80808010370300200341f8006a4125360200200341f0006a4101360200200341e0006a4201370300200341d8006a410a360200200341fcf0c50036027c200341d7f0c500360274200341ec006a200341386a360200200341f8edc50036025c200341cdf0c500360254200341053602504188b1c60041b8aec600200141024622011b200341d0006a41c8b0c00041e0b0c00020011b2802101102000b200341106a200810fa032003280214200328021c22014d0d03200328021020014102746a2201450d03200341086a200410fa030240200328020c200128020022014d0d00200328020820014104746a22010d050b412510282201450d052001411d6a410029009dee45370000200141186a4100290098ee45370000200141106a4100290090ee45370000200141086a4100290088ee4537000020014100290080ee45370000200041086a42a5808080d00437020020002001360204200041013602000c0d0b411310282201450d082001410f6a41002800d3ed45360000200141086a41002900cced45370000200141002900c4ed45370000200041086a4293808080b00237020020002001360204200041013602000c0c0b410f10282201450d06200141076a41002900deed45370000200141002900d7ed45370000200041086a428f808080f00137020020002001360204200041013602000c0b0b410f10282201450d04200141076a41002900eded45370000200141002900e6ed45370000200041086a428f808080f00137020020002001360204200041013602000c0a0b412510282201450d022001411d6a410029009dee45370000200141186a4100290098ee45370000200141106a4100290090ee45370000200141086a4100290088ee4537000020014100290080ee45370000200041086a42a5808080d00437020020002001360204200041013602000c090b02400240200941086a280200200328021c22054b0d00412710282201450d012001411f6a41002900c4ee45370000200141186a41002900bdee45370000200141106a41002900b5ee45370000200141086a41002900adee45370000200141002900a5ee45370000200041086a42a7808080f00437020020002001360204200041013602000c0a0b20092802002109200341206a41086a420037030020034280808080c00037032020012d000d2107410021012003410036024020032007410447220a36023c2003200a360238200341003a0044024002400240024002404100280280b14641044b0d00200341d0006a41086a200341386a41086a29030037030020032003290338370350200341206a410472210b200341d0006a21070c010b2003412d36024c2003200341386a3602484100280284b146210120034188016a41cb0036020020034180016a42ed80808010370300200341f8006a4125360200200341f0006a4101360200200341e0006a4201370300200341d0006a41086a2207410a360200200341fcf0c50036027c200341d7f0c500360274200341ec006a200341c8006a360200200341cceec50036025c200341cdf0c500360254200341053602504188b1c60041b8aec600200141024622011b200341d0006a41c8b0c00041e0b0c00020011b280210110200200328022c2108200328022821012007200341386a41086a29030037030020032003290338370350200341206a410472210b200341d0006a210720082001470d010b200141016a22082001490d01200141017422062008200620084b1b220841ffffffff00712008470d01200841047422064100480d010240024020010d002006102821010c010b200b28020020014104742006102c21010b2001450d02200b200136020020032008360228200328022c21080b200b28020020084104746a22012007290200370200200141086a200741086a2902003702002003200328022c41016a36022c410021072009200541186c6a2201280214450d092009200541186c6a410c6a2109200141146a2108200341d0006a410472210c410021074100210103400240200328022020074d0d00200341d0006a200341206a410010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c0d0b2007200328022020032802542d000c1b21070b02400240024002400240024002402001200828020022054f0d002003200928020020014104746a220536023402404100280280b1464105490d002003412936023c2003200341346a3602384100280284b1462105200341c90136028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341b0aec60036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328023421050b024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020052d000022060eac0102220000002201030405060708090a0b0c0d0e0f1010101010101010101010101010111111111111111111121314141414151616161616161616161615161616161616161616161616161616161616161616161717171818181818181818181818181818181717171818181818181818181818181818181717171717171718181818181818171717171717171818181818181819191919191919191919191919191919191919191919191919020b20052d00012105200320032802203602402003200541044722053602382003200641034720057136023c200341003a004402404100280280b1464105490d002003412d36024c2003200341386a3602484100280284b1462105200341cb0036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341cceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341c8006a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b200341d0006a41086a2206200341386a41086a290300370300200320032903383703500240200328022c22052003280228470d00200541016a220d2005490d242005410174220e200d200e200d4b1b220d41ffffffff0071200d470d24200d410474220e4100480d240240024020050d00200e102821050c010b200b2802002005410474200e102c21050b2005450d1d200b20053602002003200d360228200328022c21050b200b28020020054104746a22052003290350370200200541086a20062903003702002003200328022c41016a36022c0c210b4100210502404100280280b1464105490d000240200328022c2206417f6a220d20064b0d00200b280200200d4104746a4100200d2006491b21050b2003412e36024c200320053602382003200341386a3602484100280284b1462105200341d30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341d4eec50036025c2003410a360258200341cdf0c500360254200341053602502003200341c8006a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b0240200328022c2205450d0020032005417f6a220536022c200b28020020054104746a22052d000c4102470d1a0b411710282201450d1c2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c2c0b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b0240200328022c2205417f6a220620054f0d00200620054d0d180b411710282201450d1e2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c2b0b200341d0006a200341206a200541046a28020010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c2b0b200341d0006a200341206a200328025428020410e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c2b0b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102822010d01411741011037000b200b28020020064104746a41013a000c0c1f0b2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c2a0b200341d0006a200341206a200541046a28020010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c2a0b200341d0006a200341206a2003280254280204220510e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c2a0b200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c2a0b2003200536024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c1e0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c290b200341d0006a200341206a200541046a28020028020810e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c290b2003280254280204210d2005280204220628020441027421052006280200210602400340024020050d00200341d0006a200341206a200d10e4042003280250450d0220002003290350370204200041013602002000410c6a200341d8006a2802003602000c2b0b200341d0006a200341206a200628020010e304024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c2b0b2005417c6a2105200641046a21062003280254280204200d460d000b412710282201450d1a2001411f6a41002900b1ef45370000200141186a41002900aaef45370000200141106a41002900a2ef45370000200141086a410029009aef4537000020014100290092ef45370000200041086a42a7808080f00437020020002001360204200041013602000c290b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102822010d01411741011037000b200b28020020064104746a41013a000c0c1d0b2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c280b200341d0006a200341206a200a10e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c280b02404100280280b1464105490d004100280284b1462105200341c10036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003420437026c20034201370360200341f4eec50036025c2003410a360258200341cdf0c500360254200341053602504188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b2802101102000b024002400240200328022c2205417f6a220620054f0d00200620054d0d010b4117102822010d01411741011037000b200b28020020064104746a41013a000c0c1c0b2001410f6a41002900ebee45370000200141086a41002900e4ee45370000200141002900dcee45370000200041086a4297808080f00237020020002001360204200041013602000c270b200341d0006a200541046a280200200210db04024020032802504101470d00200041013602002000200c2902003702042000410c6a200c41086a2802003602000c270b200341d0006a200341206a2003280254220528020810e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c270b200320052d000d410447220536024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c1b0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c260b2003200410fa03024002402003280204200541046a28020022054d0d002003280200220620054104746a220d0d010b410e10282201450d18200141066a41002900bfef45370000200141002900b9ef45370000200041086a428e808080e00137020020002001360204200041013602000c260b200341d0006a200341206a200620054104746a28020810e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c260b2003200d2d000d410447220536024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c1a0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c250b200341d0006a200341206a410110e4042003280250450d1820002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b200341d0006a200341206a410210e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c240b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c180b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c230b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c170b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c220b200341d0006a200341206a410110e4042003280250450d1520002003290350370204200041013602002000410c6a200341d8006a2802003602000c210b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c210b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c150b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c200b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c140b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1f0b200341d0006a200341206a410110e4042003280250450d1220002003290350370204200041013602002000410c6a200341d8006a2802003602000c1e0b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1e0b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c120b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1d0b200341d0006a200341206a410210e4042003280250450d1020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1c0b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c100b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1b0b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c1b0b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0f0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c1a0b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0e0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c190b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c190b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0d0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c180b200341d0006a200341206a410210e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c180b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0c0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c170b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c170b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0b0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c160b200341d0006a200341206a410210e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c160b410121052003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c0a0b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c150b41012105200341d0006a200341206a410110e40402402003280250450d0020002003290350370204200041013602002000410c6a200341d8006a2802003602000c150b2003410136024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328024821050b024002402003280220220620056a220520064f0d00410e102822010d01410e41011037000b200320053602200c090b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c140b200b28020020064104746a41013a000c0c070b2005280200210620032005280208220536023802404100280280b1464105490d002003410136024c2003200341386a3602484100280284b1462105200341db0036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341c8efc50036025c2003410a360258200341cdf0c500360254200341053602502003200341c8006a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b280210110200200328023821050b200320053602202003200636024802404100280280b1464105490d002003410136023c2003200341c8006a3602384100280284b1462105200341e30036028801200342ed8080801037038001200341fcf0c50036027c20034125360278200341d7f0c5003602742003410136027020034201370360200341fceec50036025c2003410a360258200341cdf0c500360254200341053602502003200341386a36026c4188b1c60041b8aec600200541024622051b200341d0006a41c8b0c00041e0b0c00020051b28021011020020032802202105200328024821060b0240200520066a220620054f0d00410e102822010d11410e41011037000b200320063602200c060b41d0efc500200120051034000b200e41041037000b411741011037000b412741011037000b410e41011037000b411741011037000b200141016a22012008280200490d000c0a0b0b1031000b200641041037000b412741011037000b412541011037000b412541011037000b410f41011037000b410f41011037000b411341011037000b200141066a410029008aef4537000020014100290084ef45370000200041086a428e808080e00137020020002001360204200041013602000c010b20004100360200200020073602042003280228450d01200b280200102a0c010b2003280228450d00200b280200102a0b20034190016a24000bf50202057f017e02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034103746a220329020021072003200020044103746a220429020037020020042007370200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024103746a220329020021072003200020044103746a2204290200370200200420073702002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034103746a220129020021072001200020044103746a2200290200370200200020073702000b0f0b41a8e9c500200420011034000b4198e9c500200320011034000bd50302047f017e024020014101762202450d0003402002417f6a2202210302400240024003402003410174220441017221050240200441026a220420014f0d00200520014f0d0220042005200020054103746a280200200020044103746a280200491b21050b200520014f0d03200320014f0d02200020034103746a2203280200200020054103746a22042802004f0d03200329020021062003200429020037020020042006370200200521030c000b0b41e8eac500200520011034000b41f8eac500200320011034000b20020d000b0b0240024020014102490d002001210403402004417f6a220420014f0d02200029020021062000200020044103746a2205290200370200200520063702004100210302400240024003402003410174220241017221050240200241026a220220044f0d00200520044f0d0220022005200020054103746a280200200020024103746a280200491b21050b200520044f0d03200320044f0d02200020034103746a2203280200200020054103746a22022802004f0d03200329020021062003200229020037020020022006370200200521030c000b0b41e8eac500200520041034000b41f8eac500200320041034000b200441014b0d000b0b0f0b41a8e9c500200420011034000bea04050a7f017e017f017e027f200041686a21022001417f6a2103200041086a2104410021052001413249210641012107024003400240024020072001490d00410021080c010b410121082000200741037422096a220a280200220b200a41786a280200490d00200420096a210803404101210a20032007460d03200741016a21072008280200220a200b4f2109200841086a2108200a210b20090d000b200720014921080b2007200146210a20060d0120072001460d010240024002400240024002402007417f6a220b20014f0d002008450d012000200b4103746a220b290200210c200b20002007410374220d6a2208290200220e3702002008200c37020020074102490d0520002007417e6a220a4103746a220f280200200ea722094d0d05200b200f290200370200200a450d0420002007417d6a220a4103746a28020020094d0d042002200d6a210b0340200b41086a200b290200370200200a450d03200a417f6a210a200b41786a220b28020020094b0d000b200a41016a210b0c030b4198e9c500200b20011034000b41a8e9c500200720011034000b4100210b0b2000200b4103746a210f0b200f200e3702000b200541016a21050240200120076b220a4102490d00200828020820082802004f0d002008290200210c20082008290208370200200841086a210f0240200a4103490d002008280210200ca722104f0d00200841106a21094103210b4102210d0340200d41037420086a220f41786a2009290200370200200b200a4f0d01200b4103742109200b210d200b41016a210b200820096a22092802002010490d000b0b200f200c3702000b20054105470d000b4100210a0b200a0bcc0201027f230041106b2202240020002802002802002100200128021841ebecc50041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241f0ecc500410e2002410c6a4180edc500105c21012002200036020c20014190edc50041092002410c6a419cedc500105c21012002200041046a36020c200141acedc500410c2002410c6a419cedc500105c21012002200041086a36020c200141b8edc500410c2002410c6a419cedc500105c1a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341eeafc0004102200111000021000c010b200341f0afc0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470bc20201027f230041106b22022400200128021841ebecc50041052001411c6a28020028020c1100002103200241003a0005200220033a00042002200136020020022000410c6a36020c200241f0ecc500410e2002410c6a4180edc500105c21012002200036020c20014190edc50041092002410c6a419cedc500105c21012002200041046a36020c200141acedc500410c2002410c6a419cedc500105c21012002200041086a36020c200141b8edc500410c2002410c6a419cedc500105c1a20022d00042100024020022d0005450d00200041ff0171210141012100024020010d0020022802002200411c6a28020028020c210120002802182103024020002d00004104710d00200341eeafc0004102200111000021000c010b200341f0afc0004101200111000021000b200220003a00040b200241106a2400200041ff01714100470b9b0201027f024002400240024002402001410c6a2802002203417f6a220420034d0d00411610282201450d01200020013602042001410e6a41002900ddf245370000200141086a41002900d7f245370000200141002900cff245370000200041086a4296808080e0023702000c040b0240200420026b220220044d0d00411b10282201450d0220002001360204200141176a41002800fcf245360000200141106a41002900f5f245370000200141086a41002900edf245370000200141002900e5f245370000200041086a429b808080b0033702000c040b200320024d0d022000200128020420024104746a360204200041003602000f0b411641011037000b411b41011037000b4180f3c500200220031034000b200041013602000bc50401027f230041d0006b220324002003200236020402404100280280b1464105490d002003410136020c2003200341046a3602084100280284b1462102200341c8006a41ef00360200200341c0006a42ed80808010370300200341386a4125360200200341306a4101360200200341206a4201370300200341186a410a360200200341fcf0c50036023c200341d7f0c5003602342003412c6a200341086a360200200341f8f1c50036021c200341cdf0c500360214200341053602104188b1c60041b8aec600200241024622021b200341106a41c8b0c00041e0b0c00020021b280210110200200328020421020b0240024002402002450d00200341106a2001410010e30420032802104101470d012000200341106a4104722202290200370200200041086a200241086a2802003602000c020b200041003602000c010b02400240024002402001280200220220032802142204280208460d00200220032802046b220420024d0d02410f102822020d01410f41011037000b024020042d000c0d00412510282202450d03200042a5808080d004370204200020023602002002411d6a410029009df245370000200241186a4100290098f245370000200241106a4100290090f245370000200241086a4100290088f24537000020024100290080f2453700000c040b200041003602000c030b2000428f808080f00137020420002002360200200241076a41002900acf245370000200241002900a5f2453700000c020b20004100360200200120043602000c010b412541011037000b200341d0006a24000bac0301047f230041c0006b2202240020002802002100410121030240200128021841baaec000410c2001411c6a28020028020c1100000d0002400240200028020822030d0020002802002203200028020428020c11070042e4aec285979ba58811520d012002200336020c2002412b36021420022002410c6a36021020012802182104200128021c2105410121032002413c6a41013602002002420237022c200241c8aec0003602282002200241106a36023820042005200241286a10350d020c010b2002200336020c2002412f36021420022002410c6a36021020012802182104200128021c2105410121032002413c6a41013602002002420237022c200241c8aec0003602282002200241106a36023820042005200241286a10350d010b200241106a41146a4101360200200241106a410c6a4101360200200241043602142002200041186a3602202002200041146a36021820022000410c6a36021020012802182100200128021c2101200241286a41146a41033602002002420337022c200241d8aec0003602282002200241106a36023820002001200241286a103521030b200241c0006a240020030b1500200120002802002200280200200028020410450b080020002001100b0bbe04020d7f017e230041c0006b22032400200128020022042001280208220541047422066a210720012802042108200421010240024002402005450d00200641706a2109200341306a410172210a200341306a41026a2106200341206a410172220b41076a210c20042101034020012d000021052006200141036a2d00003a00002003200141016a2f00003b01300240200541ac01470d00200141106a21010c020b2003410c6a41026a20062d0000220d3a0000200320032f0130220e3b010c200141046a280200210f200141086a2903002110200a200e3b0000200a41026a200d3a0000200320053a0030200320103703382003200f360234200341206a200341306a200210e9042003200b2900003703102003200c290000370017024020032d00202205411f470d00200941706a2109200141106a22012007470d010c030b0b200020053a000020002003290310370001200041086a200329001737000002402009450d00200141106a210103400240024020012d000022054109460d00200541ac01470d010c030b0240200141046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b200141106a22012007470d000b0b2008450d022004102a0c020b20012007460d0003400240024020012d000022054109460d00200541ac01470d010c030b0240200141046a280200220528020441ffffffff0371450d002005280200102a0b2005102a0b200141106a22012007470d000b0b02402008450d002004102a0b2000411f3a00000b200341c0006a24000bcbd60202097f017e230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dad0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450db00120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490df001200441017422072006200720064b1b22074100480df0010240024020040d002007102821060c010b200928020020042007102c21060b2006450db00120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df1012004410174220a2006200a20064b1b220a4100480df1010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490def01200441017422072006200720064b1b22074100480def010240024020040d002007102821060c010b200928020020042007102c21060b2006450db10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df0012004410174220a2006200a20064b1b220a4100480df0010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490dee01200441017422062005200620054b1b22064100480dee010240024020040d002006102821050c010b200928020020042006102c21050b2005450db20120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a200210ea042003210420032d0000411f470d930320012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490def012004410174220a2006200a20064b1b220a4100480def010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db401200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490ded01200441017422062005200620054b1b22064100480ded010240024020040d002006102821050c010b200228020420042006102c21050b2005450db30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490dec01200441017422072006200720064b1b22074100480dec010240024020040d002007102821060c010b200928020020042007102c21060b2006450db30120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490ded012004410174220a2006200a20064b1b220a4100480ded010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490deb01200441017422072006200720064b1b22074100480deb010240024020040d002007102821060c010b200928020020042007102c21060b2006450db40120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490dec012004410174220a2006200a20064b1b220a4100480dec010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490deb01200441017422062005200620054b1b22064100480deb010240024020040d002006102821050c010b200928020020042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dea01200441017422062005200620054b1b22064100480dea010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490de901200441017422062005200620054b1b22064100480de9010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de801200441017422072006200720064b1b22074100480de8010240024020040d002007102821060c010b200928020020042007102c21060b2006450db60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de9012004410174220a2006200a20064b1b220a4100480de9010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db801200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de701200441017422072006200720064b1b22074100480de7010240024020040d002007102821060c010b200928020020042007102c21060b2006450db70120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de8012004410174220a2006200a20064b1b220a4100480de8010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db901200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de601200441017422072006200720064b1b22074100480de6010240024020040d002007102821060c010b200928020020042007102c21060b2006450db80120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de7012004410174220a2006200a20064b1b220a4100480de7010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dba01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de501200441017422072006200720064b1b22074100480de5010240024020040d002007102821060c010b200928020020042007102c21060b2006450db90120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de6012004410174220a2006200a20064b1b220a4100480de6010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbb01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de401200441017422072006200720064b1b22074100480de4010240024020040d002007102821060c010b200928020020042007102c21060b2006450dba0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de5012004410174220a2006200a20064b1b220a4100480de5010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbc01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de301200441017422082007200820074b1b22084100480de3010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de4012004410174220b2007200b20074b1b220b4100480de4010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de401200441017422092006200920064b1b22094100480de4010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dbe012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de201200441017422082007200820074b1b22084100480de2010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de3012004410174220b2007200b20074b1b220b4100480de3010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de301200441017422092006200920064b1b22094100480de3010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de101200441017422082007200820074b1b22084100480de1010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de2012004410174220b2007200b20074b1b220b4100480de2010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de201200441017422092006200920064b1b22094100480de2010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de001200441017422082007200820074b1b22084100480de0010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de1012004410174220b2007200b20074b1b220b4100480de1010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de101200441017422092006200920064b1b22094100480de1010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddf01200441017422082007200820074b1b22084100480ddf010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de0012004410174220b2007200b20074b1b220b4100480de0010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de001200441017422092006200920064b1b22094100480de0010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dde01200441017422082007200820074b1b22084100480dde010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddf012004410174220b2007200b20074b1b220b4100480ddf010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddf01200441017422092006200920064b1b22094100480ddf010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc8012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddd01200441017422082007200820074b1b22084100480ddd010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc70120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dde012004410174220b2007200b20074b1b220b4100480dde010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dde01200441017422092006200920064b1b22094100480dde010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dca012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddc01200441017422082007200820074b1b22084100480ddc010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc90120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddd012004410174220b2007200b20074b1b220b4100480ddd010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcb01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddd01200441017422092006200920064b1b22094100480ddd010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dcc012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddb01200441017422082007200820074b1b22084100480ddb010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddc012004410174220b2007200b20074b1b220b4100480ddc010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddc01200441017422092006200920064b1b22094100480ddc010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dce012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dda01200441017422082007200820074b1b22084100480dda010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddb012004410174220b2007200b20074b1b220b4100480ddb010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddb01200441017422092006200920064b1b22094100480ddb010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd901200441017422082007200820074b1b22084100480dd9010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dda012004410174220b2007200b20074b1b220b4100480dda010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dda01200441017422092006200920064b1b22094100480dda010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd801200441017422082007200820074b1b22084100480dd8010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd9012004410174220b2007200b20074b1b220b4100480dd9010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd901200441017422092006200920064b1b22094100480dd9010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd701200441017422082007200820074b1b22084100480dd7010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd8012004410174220b2007200b20074b1b220b4100480dd8010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd801200441017422092006200920064b1b22094100480dd8010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd601200441017422082007200820074b1b22084100480dd6010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da3022004410174220b2007200b20074b1b220b4100480da3020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da302200441017422092006200920064b1b22094100480da3020240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da102200441017422082007200820074b1b22084100480da1020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da2022004410174220b2007200b20074b1b220b4100480da2020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dda01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da202200441017422092006200920064b1b22094100480da2020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da002200441017422082007200820074b1b22084100480da0020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dda0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da1022004410174220b2007200b20074b1b220b4100480da1020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450ddc01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da102200441017422092006200920064b1b22094100480da1020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddd012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9f02200441017422082007200820074b1b22084100480d9f020240024020040d002008102821070c010b200a28020020042008102c21070b2007450ddc0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da0022004410174220b2007200b20074b1b220b4100480da0020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dde01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da002200441017422092006200920064b1b22094100480da0020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddf012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9e02200441017422082007200820074b1b22084100480d9e020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dde0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9f022004410174220b2007200b20074b1b220b4100480d9f020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9f02200441017422092006200920064b1b22094100480d9f020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de1012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9d02200441017422082007200820074b1b22084100480d9d020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de00120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9e022004410174220b2007200b20074b1b220b4100480d9e020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9e02200441017422092006200920064b1b22094100480d9e020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de3012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9c02200441017422082007200820074b1b22084100480d9c020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de20120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9d022004410174220b2007200b20074b1b220b4100480d9d020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9d02200441017422092006200920064b1b22094100480d9d020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de5012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9b02200441017422082007200820074b1b22084100480d9b020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de40120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9c022004410174220b2007200b20074b1b220b4100480d9c020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9c02200441017422092005200920054b1b22094100480d9c020240024020040d002009102821050c010b200a28020020042009102c21050b2005450de7012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a02200441017422082007200820074b1b22084100480d9a020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de60120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b022004410174220b2007200b20074b1b220b4100480d9b020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b02200441017422092006200920064b1b22094100480d9b020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9902200441017422082007200820074b1b22084100480d99020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a022004410174220b2007200b20074b1b220b4100480d9a020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dea01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a02200441017422092006200920064b1b22094100480d9a020240024020040d002009102821060c010b200a28020020042009102c21060b2006450deb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450dea0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422072005200720054b1b22074100480d96020240024020040d002007102821050c010b200228020420042007102c21050b2005450dec0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a000020032006200210eb042003210420032d0000411f470def020c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450dec0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c200210ec042003210420032d0000411f470dee020c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9402200441017422082005200820054b1b22084100480d94020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d9402200541017422042008200420084b1b22044100480d94020240024020050d002004102821050c010b200628020020052004102c21050b2005450ded0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9302200441017422072005200720054b1b22074100480d93020240024020040d002007102821050c010b200628020020042007102c21050b2005450ded0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d9302200541017422042007200420074b1b22044100480d93020240024020050d002004102821050c010b200628020020052004102c21050b2005450dee0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490def01200441017422062005200620054b1b22064100480def010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dba02200441017422062005200620054b1b22064100480dba020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db902200441017422062005200620054b1b22064100480db9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db802200441017422062005200620054b1b22064100480db8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db702200441017422062005200620054b1b22064100480db7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db602200441017422062005200620054b1b22064100480db6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db502200441017422062005200620054b1b22064100480db5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db402200441017422062005200620054b1b22064100480db4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db302200441017422062005200620054b1b22064100480db3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db202200441017422062005200620054b1b22064100480db2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db102200441017422062005200620054b1b22064100480db1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db002200441017422062005200620054b1b22064100480db0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daf02200441017422062005200620054b1b22064100480daf020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae02200441017422062005200620054b1b22064100480dae020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad02200441017422062005200620054b1b22064100480dad020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac02200441017422062005200620054b1b22064100480dac020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dab02200441017422062005200620054b1b22064100480dab020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daa02200441017422062005200620054b1b22064100480daa020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da902200441017422062005200620054b1b22064100480da9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da802200441017422062005200620054b1b22064100480da8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da702200441017422062005200620054b1b22064100480da7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da602200441017422062005200620054b1b22064100480da6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da502200441017422062005200620054b1b22064100480da5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da402200441017422062005200620054b1b22064100480da4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da302200441017422062005200620054b1b22064100480da3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da202200441017422062005200620054b1b22064100480da2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da102200441017422062005200620054b1b22064100480da1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da002200441017422062005200620054b1b22064100480da0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f02200441017422062005200620054b1b22064100480d9f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9e02200441017422062005200620054b1b22064100480d9e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9d02200441017422062005200620054b1b22064100480d9d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9c02200441017422062005200620054b1b22064100480d9c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9b02200441017422062005200620054b1b22064100480d9b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9a02200441017422062005200620054b1b22064100480d9a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9902200441017422062005200620054b1b22064100480d99020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9802200441017422062005200620054b1b22064100480d98020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9702200441017422062005200620054b1b22064100480d97020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422062005200620054b1b22064100480d96020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9402200441017422062005200620054b1b22064100480d94020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9302200441017422062005200620054b1b22064100480d93020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470df1010240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0cf1010b200641011037000b200641011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200a41011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b1031000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200841011037000b200841011037000b200841011037000b200741011037000b200641011037000b200841011037000b200441011037000b200741011037000b200441011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0b200341106a24000bb60301057f2004410c6a2105200441086a2106024002400240034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d04200741017422092008200920084b1b22094100480d040240024020070d002009102821080c010b200428020420072009102c21080b2008450d022004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b024020022003460d002004410c6a2105200441086a2106034020022802002101034002400240200628020020052802002207460d00200428020421080c010b200741016a22082007490d06200741017422092008200920084b1b22094100480d060240024020070d002009102821080c010b200428020420072009102c21080b2008450d052004200836020420062009360200200528020021070b2005200741016a360200200820076a200141807f72200141ff0071200141077622071b3a00002007210120070d000b200241046a22022003470d000b0b2000411f3a00000f0b200941011037000b200941011037000b1031000baf0301067f024002400240024020014107752203200141c00071220472452003417f4720044572460d002002410c6a2105200241086a2106034002400240200628020020052802002204460d00200228020421070c010b200441016a22072004490d05200441017422082007200820074b1b22084100480d050240024020040d002008102821070c010b200228020420042008102c21070b2007450d032002200736020420062008360200200528020021040b2005200441016a360200200720046a200141807f723a0000200341c000712104200321012003410775220721032007200472452007417f4720044572470d000b0b02400240200241086a2802002002410c6a2802002204460d00200228020421030c010b200441016a22032004490d03200441017422072003200720034b1b22074100480d030240024020040d002007102821030c010b200228020420042007102c21030b2003450d0220022003360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200320046a200141ff00713a00002000411f3a00000f0b200841011037000b200741011037000b1031000bb30302017e067f024002400240024020014207872203502001a7220441c00071452205712003427f52200572460d002002410c6a2106200241086a2107034002400240200728020020062802002205460d00200228020421080c010b200541016a22082005490d05200541017422092008200920084b1b22094100480d050240024020050d002009102821080c010b200228020420052009102c21080b2008450d032002200836020420072009360200200628020021050b2006200541016a360200200820056a200441807f723a00002003a72104200342078722012103200150200441c00071452205712001427f52200572470d000b0b02400240200241086a2802002002410c6a2802002205460d00200228020421080c010b200541016a22082005490d03200541017422062008200620084b1b22064100480d030240024020050d002006102821080c010b200228020420052006102c21080b2008450d0220022008360204200241086a20063602002002410c6a28020021050b2002410c6a200541016a360200200820056a200441ff00713a00002000411f3a00000f0b200941011037000b200641011037000b1031000be103010a7f230041306b22022400200241216a220341076a210441002105410021064100210741002108410821090240024002400340200241186a200110ee04024020022802184101470d002000200229021c370204200041013602002000410c6a200241186a410c6a29020037020002402007450d00200921070340024020072d00004109470d000240200741046a220a280200220528020441ffffffff0371450d002005280200102a200a28020021050b2005102a0b200741106a2107200641706a22060d000b0b2008450d042009102a0c040b200220032900003703082002200429000037000f20022d0020210a2002200229000f37001f200220022903083703180240024020072008470d00200741016a220b2007490d032005200b2005200b4b1b220841ffffffff00712008470d032008410474220b4100480d030240024020070d00200b102821090c010b20092006200b102c21090b2009450d010b200920066a220b200a3a0000200b41016a2002290318370000200b41086a200229001f370000200541026a2105200641106a2106200741016a2107200a41ff01714106460d030c010b0b200b41081037000b1031000b20002009360204200041003602002000410c6a2007360200200041086a20083602000b200241306a24000b80b601020b7f017e230041f0006b2202240002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d02200320054f0d0120052003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c640b2001280200220620046a2d000021072001410c6a2208200536020002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240200741bf014b0d0020070ec001b902b902010203b90200000000000405060708090a00000000000000000b0c000000000d0e0f101100000012131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901b9020b2000410b3a000420004101360200200041056a20073a00000cbc020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da302200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410221070cbf020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1033200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbf020b4102210a410221070cba020b4103210a410221070cb9020b4101210a0b410221070cb7020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da302200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410321070cbe020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1033200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbe020b4102210a410321070cb9020b4103210a410321070cb8020b4101210a0b410321070cb6020b024002400240024002400240024020032005460d00200441026a21092005417f460de00120032009490da302200620056a2c00002101200820093602004100210a0240200141004e0d00411921090c020b0240200141017441807f71200172220141ff0171220541847e6a220941034d0d0041062109200541c001470d034104210a410421070cbd020b20090e0404030506040b200241013a0047200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c7006a360238200241c8006a200241d8006a1033200241326a200241d0006a2802003601002002200229034837012a2002200229012837031820022002412e6a29010037011e410521090b2002200229011e37010e200220022903183703080b200020013a0005200020093a000420002002290308370106200041013602002000410c6a200229010e3701000cbd020b4102210a410421070cb8020b4103210a410421070cb7020b4101210a0b410421070cb5020b410621070cb4020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb8020b410721070cb3020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb7020b410821070cb2020b200241d8006a200110ef044104210a200228025822074101460da201200241e0006a280200210b41002106200228025c210c02400240200241e4006a280200220941027422050d00410021040c010b2005410275220441ffffffff03712004470dda01200441027422034100480dda0120031028220a450dd9010b02402009450d00200941027421032005417c6a2106200a2109200c2105034020092005280200360200200941046a2109200541046a21052003417c6a22030d000b200641027641016a21060b0240200b450d00200c102a0b20022d005c4105470db0022007450db00220022802640da3010cb0020b410a21070cb0020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb4020b410b21070caf020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddd012003200541016a22044f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210720082004360200200741ff00712001411f71742009722109200141076a2101200421052007418001710d000b20014120490d01410d210120074110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb3020b0240024020032004460d00200441016a22012004490ddb01200320014f0d0120012003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000cb3020b200620046a2d0000210520082001360200024020050d00410c21074100210a0caf020b200041163a000420004101360200200041056a20053a00000cb2020b410d21070cad020b410e21070cac020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cb0020b410f21070cab020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000caf020b411021070caa020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cae020b411121070ca9020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cad020b411221070ca8020b410021014100210902400240034002402001411f4d0d00410f21010c020b0240024020032005460d002005417f460ddc012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010c020b200620056a2d0000210420082007360200200441ff00712001411f71742009722109200141076a2101200721052004418001710d000b20014120490d01410d210120044110490d010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000cac020b411321070ca7020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddd01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000cab020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9c010b20032001460d9a012001417f460dd9012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9b010b200aad210d411421070ca6020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dde01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000caa020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9d010b20032001460d9b012001417f460dda012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9c010b200aad210d411521070ca5020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ddf01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca9020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9e010b20032001460d9c012001417f460ddb012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9d010b200aad210d411621070ca4020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca8020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010c9f010b20032001460d9d012001417f460ddc012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9e010b200aad210d411721070ca3020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de101200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca7020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca0010b20032001460d9e012001417f460ddd012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0d9f010b200aad210d411821070ca2020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de201200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca6020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca1010b20032001460d9f012001417f460dde012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da0010b200aad210d411921070ca1020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de301200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca5020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca2010b20032001460da0012001417f460ddf012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da1010b200aad210d411a21070ca0020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de401200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca4020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca3010b20032001460da1012001417f460de0012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da2010b200aad210d411b21070c9f020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de501200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca3020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca4010b20032001460da2012001417f460de1012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da3010b200aad210d411c21070c9e020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de601200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca2020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca5010b20032001460da3012001417f460de2012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da4010b200aad210d411d21070c9d020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de701200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca1020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca6010b20032001460da4012001417f460de3012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da5010b200aad210d411e21070c9c020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de801200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000ca0020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca7010b20032001460da5012001417f460de4012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da6010b200aad210d411f21070c9b020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450de901200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9f020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca8010b20032001460da6012001417f460de5012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b41202107024020054120490d00410d21012004410f4b0da7010b200aad210d0c9a020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dea01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9e020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010ca9010b20032001460da7012001417f460de6012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da8010b200aad210d412121070c99020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450deb01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9d020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caa010b20032001460da8012001417f460de7012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0da9010b200aad210d412221070c98020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dec01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9c020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cab010b20032001460da9012001417f460de8012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daa010b200aad210d412321070c97020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450ded01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9b020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cac010b20032001460daa012001417f460de9012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dab010b200aad210d412421070c96020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450dee01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c9a020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cad010b20032001460dab012001417f460dea012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dac010b200aad210d412521070c95020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450def01200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c99020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cae010b20032001460dac012001417f460deb012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dad010b200aad210d412621070c94020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c98020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010caf010b20032001460dad012001417f460dec012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0dae010b200aad210d412721070c93020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df101200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c97020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb0010b20032001460dae012001417f460ded012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0daf010b200aad210d412821070c92020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df201200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c96020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb1010b20032001460daf012001417f460dee012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db0010b200aad210d412921070c91020b410120036b2107200441026a21014100210541002109024002400240034002402005411f4d0d00410f21010c020b02400240200720016a4102460d002001450df301200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320022802282109200228022c210520022802302103410521010c030b200620016a417f6a2d0000210420082001360200200441ff00712005411f71742009722109200141016a2101200541076a21052004418001710d000b20054120490d0220044110490d02410d21010b0b2000200136020420004101360200200041106a20033602002000410c6a2005360200200041086a20093602000c95020b2001417f6a2101410021054100210a034002402005411f4d0d00410f21010cb2010b20032001460db0012001417f460def012003200141016a2207490d8f02200620016a2d0000210420082007360200200441ff00712005411f7174200a72210a200541076a2105200721012004418001710d000b024020054120490d00410d21012004410f4b0db1010b200aad210d412a21070c90020b0240024020032005460d00200441026a21012005417f460df001200320014f0d0120012003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c94020b200620056a2d0000210920082001360200024020090d00412b21074100210a0c90020b200041153a000420004101360200200041056a20093a00000c93020b0240024020032005460d00200441026a21012005417f460df001200320014f0d0120012003103c000b200241013a0048200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241c8006a360238200241086a200241d8006a1033200241336a200241106a2802003600002002200229030837002b2002200229002837031820022002412f6a29000037001f200041053a0004200020022903183700052000410c6a200229001f370000200041013602000c93020b200620056a2d0000210920082001360200024020090d00412c21074100210a0c8f020b200041153a000420004101360200200041056a20093a00000c92020b41002101410021090240024002400340410d210a2001411f4b0d010240024020032005460d002005417f460df4012003200541016a22074f0d01200541016a2003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a10334105210a0c020b200620056a2c0000210420082007360200200441ff00712001411f71742009722109200141076a21012007210520044100480d000b200441c00071210502402001411f4b0d0020050d020b0240024020014120490d0020050d010b200441ff01714108490d0320014120490d032005450d010c030b20044180017241ff017141f7014b0d020b2000200a36020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c93020b2009417f2001411f71747221090b412d21070c8d020b4200210d4100210102400240024002400340410e21072001413f4b0d010240024020032005460d002005417f460df5012003200541016a22094f0d01200541016a2003103c000b200241013a0008200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241086a360238200241286a200241d8006a10332002290328210d20022802302101410521070c030b200620056a2d0000210420082009360200200441ff0071220aad2001413f71ad86200d84210d200141076a210120092105200441187441187522094100480d000b200941c00071210502402001413f4b0d0020050d030b02400240200141c000490d0020050d010b200141c000490d0420090d010c040b200a41ff00460d030b0b200020073a0004200020022f00183b000520004101360200200041106a2001360200200041086a200d370200200041076a2002411a6a2d00003a00000c92020b200d427f2001413f71ad8684210d0b412e21070c8c020b02400240200320056b4104490d00200441056a21012005417b4b0df001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a103320004281808080d000370300200041086a2002290228370200200041106a200241286a41086a2802003602000c90020b200620056a280000210920082001360200412f21070c8b020b02400240200320056b4108490d00200441096a2101200541774b0df001200320014f0d0120012003103c000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a10332002290328210d200041106a2002280230360200200041086a200d37020020004281808080d0003703000c8f020b200620056a290000210d20082001360200413021070c8a020b413121070c89020b413221070c88020b413321070c87020b413421070c86020b413521070c85020b413621070c84020b413721070c83020b413821070c82020b413921070c81020b413a21070c80020b413b21070cff010b413c21070cfe010b413d21070cfd010b413e21070cfc010b413f21070cfb010b41c00021070cfa010b41c10021070cf9010b41c20021070cf8010b41c30021070cf7010b41c40021070cf6010b41c50021070cf5010b41c60021070cf4010b41c70021070cf3010b41c80021070cf2010b41c90021070cf1010b41ca0021070cf0010b41cb0021070cef010b41cc0021070cee010b41cd0021070ced010b41ce0021070cec010b41cf0021070ceb010b41d00021070cea010b41d10021070ce9010b41d20021070ce8010b41d30021070ce7010b41d40021070ce6010b41d50021070ce5010b41d60021070ce4010b41d70021070ce3010b41d80021070ce2010b41d90021070ce1010b41da0021070ce0010b41db0021070cdf010b41dc0021070cde010b41dd0021070cdd010b41de0021070cdc010b41df0021070cdb010b41e00021070cda010b41e10021070cd9010b41e20021070cd8010b41e30021070cd7010b41e40021070cd6010b41e50021070cd5010b41e60021070cd4010b41e70021070cd3010b41e80021070cd2010b41e90021070cd1010b41ea0021070cd0010b41eb0021070ccf010b41ec0021070cce010b41ed0021070ccd010b41ee0021070ccc010b41ef0021070ccb010b41f00021070cca010b41f10021070cc9010b41f20021070cc8010b41f30021070cc7010b41f40021070cc6010b41f50021070cc5010b41f60021070cc4010b41f70021070cc3010b41f80021070cc2010b41f90021070cc1010b41fa0021070cc0010b41fb0021070cbf010b41fc0021070cbe010b41fd0021070cbd010b41fe0021070cbc010b41ff0021070cbb010b41800121070cba010b41810121070cb9010b41820121070cb8010b41830121070cb7010b41840121070cb6010b41850121070cb5010b41860121070cb4010b41870121070cb3010b41880121070cb2010b41890121070cb1010b418a0121070cb0010b418b0121070caf010b418c0121070cae010b418d0121070cad010b418e0121070cac010b418f0121070cab010b41900121070caa010b41910121070ca9010b41920121070ca8010b41930121070ca7010b41940121070ca6010b41950121070ca5010b41960121070ca4010b41970121070ca3010b41980121070ca2010b41990121070ca1010b419a0121070ca0010b419b0121070c9f010b419c0121070c9e010b419d0121070c9d010b419e0121070c9c010b419f0121070c9b010b41a00121070c9a010b41a10121070c99010b41a20121070c98010b41a30121070c97010b41a40121070c96010b41a50121070c95010b41a60121070c94010b41a70121070c93010b41a80121070c92010b41a90121070c91010b41aa0121070c90010b41ab0121070c8f010b200041013602002000200241d8006a41047222012902003702042000410c6a200141086a2902003702000c92010b2002280260102a0c8c010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8f010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8d010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c8b010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c89010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c87010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c85010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c83010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c81010b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7f0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7d0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c7b0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c790b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c770b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c750b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c730b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c710b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6f0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6d0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c6b0b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c690b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c670b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c650b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a2802003602000c630b417f20051044000b417f20091044000b417f20091044000b417f20091044000b417f200541016a1044000b417f200541016a1044000b200341041037000b1031000b417f200541016a1044000b417f200541016a1044000b417f20011044000b417f200541016a1044000b417f200541016a1044000b417f200541016a1044000b417f200541016a1044000b417f200541016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f200141016a1044000b417f20011044000b417f20011044000b417f200541016a1044000b417f200541016a1044000b200520011044000b200520011044000b20092003103c000b20092003103c000b20092003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b200141016a2003103c000b02400240024002400240024020042006460d0020042006490d01024020060d00024020040d004104210a0c020b200a102a4104210a0c010b200a200441027420064102742209102c220a450d020b4100210941002104034002402009411f4d0d00410f21010c0a0b20012802082207200128020c2205460d08200541016a22032005490d0320072003490d04200128020020056a2d0000210520082003360200200541ff00712009411f71742004722104200941076a21092005418001710d000b20094120490d04410d21012005410f4b0d080c040b41dcfdc5001032000b200941041037000b417f20031044000b20032007103c000b410c10282209450d0120092004360208200920063602042009200a360200410921070b20004100360200200041106a200d3703002000410c6a2009360200200041096a200a3a0000200041086a20073a00000c030b410c41041037000b200241013a0018200241ec006a41013602002002420137025c200241a4e2c5003602582002412636023c2002200241386a3602682002200241186a360238200241286a200241d8006a1033410521010b2000200136020420004101360200200041086a2002290228370200200041106a200241286a41086a280200360200200641ffffffff0371450d00200a102a0b200241f0006a24000bd60703067f017e067f230041d0006b220224004100210341002104024002400240024002400240024002400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005103c000b200241013a0027200241cc006a41013602002002420137023c200241a4e2c5003602382002412636021c2002200241186a3602482002200241276a360218200241286a200241386a1033410521030c020b200128020020066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b200241086a41086a200241286a41086a280200220136020020022002290228220837030820002003360204200041086a2008370200200041106a2001360200200041013602000c0a0b20024100360210200242043703082004450d0841042109410021034100210a03402003210b200a220c41016a210a410021034100210503402003411f4b0d04024002402001280208220d200128020c2206460d00200641016a22072006490d05200d20074f0d012007200d103c000b2002200b36020c2002200c360210200241013a0027200241cc006a41013602002002420137023c200241a4e2c5003602382002412636021c2002200241186a3602482002200241276a360218200241286a200241386a103320022802282103200228022c2106200228023021074100210e410521010c090b200128020020066a2d000021062001200736020c200641ff00712003411f71742005722105200341076a21032006418001710d000b024020034120490d002006410f4d0d002002200b36020c2002200c360210410d21010c070b02400240200c200b460d00200b2103200c210b0c010b200b41016a2203200b490d06200b41017422062003200620034b1b220341ffffffff03712003470d06200341027422064100480d0602400240200b0d002006102821090c010b2009200b4102742006102c21090b2009450d05200220093602080b2005410876210e2009200b4102746a2005360200200a2004460d080c000b0b417f20071044000b417f20071044000b2002200b36020c2002200c360210410f21010c020b200641041037000b1031000b0b20004101360200200041106a20073602002000410c6a2006360200200041086a20033602002000200e410874200172360204200b450d022009102a0c020b2002200336020c2002200a3602100b20002002290308370204200041003602002000410c6a200241106a2802003602000b200241d0006a24000bcbd60202097f017e230041106b22032400024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020012d00000eac01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01ab01000b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41003a00000cab010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dad0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41013a00000caa010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dad0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41023a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df501200441017422082005200820054b1b22084100480df5010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca9010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450dae0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41033a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df401200441017422082005200820054b1b22084100480df4010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca8010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450daf0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41043a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490df301200441017422082005200820054b1b22084100480df3010240024020040d002008102821050c010b200628020020042008102c21050b2005450db00120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a42c0818386fcdffffe7c2007410473ad42078342038688a7413f7141c000723a00000ca7010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41053a00000ca6010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450db00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410b3a00000ca5010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490df001200441017422072006200720064b1b22074100480df0010240024020040d002007102821060c010b200928020020042007102c21060b2006450db00120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410c3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df1012004410174220a2006200a20064b1b220a4100480df1010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db201200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca5010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490def01200441017422072006200720064b1b22074100480def010240024020040d002007102821060c010b200928020020042007102c21060b2006450db10120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a410d3a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490df0012004410174220a2006200a20064b1b220a4100480df0010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db301200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca4010b0b200241046a210902400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490dee01200441017422062005200620054b1b22064100480dee010240024020040d002006102821050c010b200928020020042006102c21050b2005450db20120022005360204200241086a20063602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a410e3a0000200320012802042204280204220520042802002204200420054102746a200210ea042003210420032d0000411f470d930320012802042802082105200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490def012004410174220a2006200a20064b1b220a4100480def010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db401200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca3010b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490ded01200441017422062005200620054b1b22064100480ded010240024020040d002006102821050c010b200228020420042006102c21050b2005450db30120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a410f3a00000ca1010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490dec01200441017422072006200720064b1b22074100480dec010240024020040d002007102821060c010b200928020020042007102c21060b2006450db30120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41103a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490ded012004410174220a2006200a20064b1b220a4100480ded010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db501200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000ca1010b0b200241046a2109200141046a280200210520012d0001210b02400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490deb01200441017422072006200720064b1b22074100480deb010240024020040d002007102821060c010b200928020020042007102c21060b2006450db40120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41113a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490dec012004410174220a2006200a20064b1b220a4100480dec010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db601200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b02400240200241086a2802002002410c6a2802002204460d00200928020021050c010b200441016a22052004490deb01200441017422062005200620054b1b22064100480deb010240024020040d002006102821050c010b200928020020042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a200b3a00000c9f010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dea01200441017422062005200620054b1b22064100480dea010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411a3a00000c9e010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490de901200441017422062005200620054b1b22064100480de9010240024020040d002006102821050c010b200228020420042006102c21050b2005450db60120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a411b3a00000c9d010b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de801200441017422072006200720064b1b22074100480de8010240024020040d002007102821060c010b200928020020042007102c21060b2006450db60120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41203a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de9012004410174220a2006200a20064b1b220a4100480de9010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db801200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9d010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de701200441017422072006200720064b1b22074100480de7010240024020040d002007102821060c010b200928020020042007102c21060b2006450db70120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41213a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de8012004410174220a2006200a20064b1b220a4100480de8010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450db901200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9c010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de601200441017422072006200720064b1b22074100480de6010240024020040d002007102821060c010b200928020020042007102c21060b2006450db80120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41223a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de7012004410174220a2006200a20064b1b220a4100480de7010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dba01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9b010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de501200441017422072006200720064b1b22074100480de5010240024020040d002007102821060c010b200928020020042007102c21060b2006450db90120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41233a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de6012004410174220a2006200a20064b1b220a4100480de6010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbb01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c9a010b0b200241046a2109200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200928020021060c010b200441016a22062004490de401200441017422072006200720064b1b22074100480de4010240024020040d002007102821060c010b200928020020042007102c21060b2006450dba0120022006360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200620046a41243a0000200241086a2108034002400240200828020020072802002204460d00200928020021060c010b200441016a22062004490de5012004410174220a2006200a20064b1b220a4100480de5010240024020040d00200a102821060c010b20092802002004200a102c21060b2006450dbc01200220063602042008200a360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c99010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de301200441017422082007200820074b1b22084100480de3010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41283a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de4012004410174220b2007200b20074b1b220b4100480de4010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de401200441017422092006200920064b1b22094100480de4010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dbe012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c98010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de201200441017422082007200820074b1b22084100480de2010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41293a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de3012004410174220b2007200b20074b1b220b4100480de3010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dbf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de301200441017422092006200920064b1b22094100480de3010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c97010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de101200441017422082007200820074b1b22084100480de1010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dbf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de2012004410174220b2007200b20074b1b220b4100480de2010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de201200441017422092006200920064b1b22094100480de2010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c96010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490de001200441017422082007200820074b1b22084100480de0010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de1012004410174220b2007200b20074b1b220b4100480de1010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de101200441017422092006200920064b1b22094100480de1010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c95010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddf01200441017422082007200820074b1b22084100480ddf010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490de0012004410174220b2007200b20074b1b220b4100480de0010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490de001200441017422092006200920064b1b22094100480de0010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c94010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dde01200441017422082007200820074b1b22084100480dde010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddf012004410174220b2007200b20074b1b220b4100480ddf010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc701200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddf01200441017422092006200920064b1b22094100480ddf010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dc8012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c93010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddd01200441017422082007200820074b1b22084100480ddd010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc70120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dde012004410174220b2007200b20074b1b220b4100480dde010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dc901200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dde01200441017422092006200920064b1b22094100480dde010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dca012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c92010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddc01200441017422082007200820074b1b22084100480ddc010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dc90120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a412f3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddd012004410174220b2007200b20074b1b220b4100480ddd010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcb01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddd01200441017422092006200920064b1b22094100480ddd010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dcc012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c91010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490ddb01200441017422082007200820074b1b22084100480ddb010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcb0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41303a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddc012004410174220b2007200b20074b1b220b4100480ddc010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcd01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddc01200441017422092006200920064b1b22094100480ddc010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dce012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c90010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dda01200441017422082007200820074b1b22084100480dda010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcd0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41313a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490ddb012004410174220b2007200b20074b1b220b4100480ddb010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dcf01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490ddb01200441017422092006200920064b1b22094100480ddb010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd0012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8f010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd901200441017422082007200820074b1b22084100480dd9010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dcf0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41323a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dda012004410174220b2007200b20074b1b220b4100480dda010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd101200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dda01200441017422092006200920064b1b22094100480dda010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd2012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8e010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd801200441017422082007200820074b1b22084100480dd8010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd10120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41333a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd9012004410174220b2007200b20074b1b220b4100480dd9010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd301200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd901200441017422092006200920064b1b22094100480dd9010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd4012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8d010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd701200441017422082007200820074b1b22084100480dd7010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd30120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41343a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490dd8012004410174220b2007200b20074b1b220b4100480dd8010240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd501200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490dd801200441017422092006200920064b1b22094100480dd8010240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd6012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8c010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490dd601200441017422082007200820074b1b22084100480dd6010240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd50120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41353a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da3022004410174220b2007200b20074b1b220b4100480da3020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dd801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da302200441017422092006200920064b1b22094100480da3020240024020040d002009102821060c010b200a28020020042009102c21060b2006450dd9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8b010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da102200441017422082007200820074b1b22084100480da1020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dd80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41363a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da2022004410174220b2007200b20074b1b220b4100480da2020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dda01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da202200441017422092006200920064b1b22094100480da2020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c8a010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490da002200441017422082007200820074b1b22084100480da0020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dda0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41373a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da1022004410174220b2007200b20074b1b220b4100480da1020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450ddc01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da102200441017422092006200920064b1b22094100480da1020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddd012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c89010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9f02200441017422082007200820074b1b22084100480d9f020240024020040d002008102821070c010b200a28020020042008102c21070b2007450ddc0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41383a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490da0022004410174220b2007200b20074b1b220b4100480da0020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dde01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490da002200441017422092006200920064b1b22094100480da0020240024020040d002009102821060c010b200a28020020042009102c21060b2006450ddf012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c88010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9e02200441017422082007200820074b1b22084100480d9e020240024020040d002008102821070c010b200a28020020042008102c21070b2007450dde0120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a41393a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9f022004410174220b2007200b20074b1b220b4100480d9f020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de001200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9f02200441017422092006200920064b1b22094100480d9f020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de1012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c87010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9d02200441017422082007200820074b1b22084100480d9d020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de00120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413a3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9e022004410174220b2007200b20074b1b220b4100480d9e020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de201200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9e02200441017422092006200920064b1b22094100480d9e020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de3012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c86010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9c02200441017422082007200820074b1b22084100480d9c020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de20120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413b3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9d022004410174220b2007200b20074b1b220b4100480d9d020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de401200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9d02200441017422092006200920064b1b22094100480d9d020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de5012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c85010b0b200241046a210a200141086a2802002106200141046a280200210502400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9b02200441017422082007200820074b1b22084100480d9b020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de40120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413c3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9c022004410174220b2007200b20074b1b220b4100480d9c020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de601200220073602042009200b360200200828020021040b2008200441016a360200200720046a200541807f72200541ff0071200541077622041b3a00002004210520040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021050c010b200441016a22052004490d9c02200441017422092005200920054b1b22094100480d9c020240024020040d002009102821050c010b200a28020020042009102c21050b2005450de7012002200536020420082009360200200728020021040b2007200441016a360200200520046a200641807f72200641ff0071200641077622041b3a00002004210620040d000c84010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9a02200441017422082007200820074b1b22084100480d9a020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de60120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413d3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9b022004410174220b2007200b20074b1b220b4100480d9b020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450de801200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9b02200441017422092006200920064b1b22094100480d9b020240024020040d002009102821060c010b200a28020020042009102c21060b2006450de9012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c83010b0b200241046a210a200141086a2802002105200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200a28020021070c010b200441016a22072004490d9902200441017422082007200820074b1b22084100480d99020240024020040d002008102821070c010b200a28020020042008102c21070b2007450de80120022007360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200720046a413e3a0000200241086a2109034002400240200928020020082802002204460d00200a28020021070c010b200441016a22072004490d9a022004410174220b2007200b20074b1b220b4100480d9a020240024020040d00200b102821070c010b200a2802002004200b102c21070b2007450dea01200220073602042009200b360200200828020021040b2008200441016a360200200720046a200641807f72200641ff0071200641077622041b3a00002004210620040d000b2002410c6a2107200241086a2108034002400240200828020020072802002204460d00200a28020021060c010b200441016a22062004490d9a02200441017422092006200920064b1b22094100480d9a020240024020040d002009102821060c010b200a28020020042009102c21060b2006450deb012002200636020420082009360200200728020021040b2007200441016a360200200620046a200541807f72200541ff0071200541077622041b3a00002004210520040d000c82010b0b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450dea0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a413f3a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9802200441017422082005200820054b1b22084100480d98020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c80010b200241046a210620012d0001210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450deb0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c0003a000002400240200241086a28020020082802002204460d00200628020021050c010b200441016a22052004490d9702200441017422082005200820054b1b22084100480d97020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a200441016a360200200520046a20073a00000c7f0b200141046a280200210602400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422072005200720054b1b22074100480d96020240024020040d002007102821050c010b200228020420042007102c21050b2005450dec0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c1003a000020032006200210eb042003210420032d0000411f470def020c7e0b200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450dec0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c2003a00002003200c200210ec042003210420032d0000411f470dee020c7d0b200241046a2106200141046a280200210702400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9402200441017422082005200820054b1b22084100480d94020240024020040d002008102821050c010b200628020020042008102c21050b2005450dec0120022005360204200241086a20083602002002410c6a28020021040b2002410c6a2208200441016a360200200520046a41c3003a000002400240200241086a2802002205200828020022046b4104490d00200628020021050c010b200441046a22082004490d9402200541017422042008200420084b1b22044100480d94020240024020050d002004102821050c010b200628020020052004102c21050b2005450ded0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441046a360200200520046a20073600000c7c0b200241046a2106200141086a290300210c02400240200241086a2802002002410c6a2802002204460d00200628020021050c010b200441016a22052004490d9302200441017422072005200720054b1b22074100480d93020240024020040d002007102821050c010b200628020020042007102c21050b2005450ded0120022005360204200241086a20073602002002410c6a28020021040b2002410c6a2207200441016a360200200520046a41c4003a000002400240200241086a2802002205200728020022046b4108490d00200628020021050c010b200441086a22072004490d9302200541017422042007200420074b1b22044100480d93020240024020050d002004102821050c010b200628020020052004102c21050b2005450dee0120022005360204200241086a20043602002002410c6a28020021040b2002410c6a200441086a360200200520046a200c3700000c7b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c5003a00000c7a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c6003a00000c790b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c7003a00000c780b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c8003a00000c770b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41c9003a00000c760b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ca003a00000c750b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cb003a00000c740b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cc003a00000c730b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cd003a00000c720b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ce003a00000c710b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41cf003a00000c700b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d0003a00000c6f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d1003a00000c6e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d2003a00000c6d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d3003a00000c6c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d4003a00000c6b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d5003a00000c6a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d6003a00000c690b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d7003a00000c680b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d8003a00000c670b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41d9003a00000c660b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41da003a00000c650b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41db003a00000c640b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dc003a00000c630b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41dd003a00000c620b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41de003a00000c610b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41df003a00000c600b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e0003a00000c5f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e1003a00000c5e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e2003a00000c5d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e3003a00000c5c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e4003a00000c5b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e5003a00000c5a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e6003a00000c590b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e7003a00000c580b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490def01200441017422062005200620054b1b22064100480def010240024020040d002006102821050c010b200228020420042006102c21050b2005450dee0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e8003a00000c570b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dba02200441017422062005200620054b1b22064100480dba020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41e9003a00000c560b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db902200441017422062005200620054b1b22064100480db9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ea003a00000c550b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db802200441017422062005200620054b1b22064100480db8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41eb003a00000c540b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db702200441017422062005200620054b1b22064100480db7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ec003a00000c530b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db602200441017422062005200620054b1b22064100480db6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ed003a00000c520b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db502200441017422062005200620054b1b22064100480db5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ee003a00000c510b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db402200441017422062005200620054b1b22064100480db4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ef003a00000c500b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db302200441017422062005200620054b1b22064100480db3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f0003a00000c4f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db202200441017422062005200620054b1b22064100480db2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f1003a00000c4e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db102200441017422062005200620054b1b22064100480db1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f2003a00000c4d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490db002200441017422062005200620054b1b22064100480db0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f3003a00000c4c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daf02200441017422062005200620054b1b22064100480daf020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f4003a00000c4b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dae02200441017422062005200620054b1b22064100480dae020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f5003a00000c4a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dad02200441017422062005200620054b1b22064100480dad020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f6003a00000c490b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dac02200441017422062005200620054b1b22064100480dac020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f7003a00000c480b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dab02200441017422062005200620054b1b22064100480dab020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f8003a00000c470b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490daa02200441017422062005200620054b1b22064100480daa020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41f9003a00000c460b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da902200441017422062005200620054b1b22064100480da9020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fa003a00000c450b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da802200441017422062005200620054b1b22064100480da8020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fb003a00000c440b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da702200441017422062005200620054b1b22064100480da7020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fc003a00000c430b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da602200441017422062005200620054b1b22064100480da6020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fd003a00000c420b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da502200441017422062005200620054b1b22064100480da5020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41fe003a00000c410b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da402200441017422062005200620054b1b22064100480da4020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ff003a00000c400b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da302200441017422062005200620054b1b22064100480da3020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4180013a00000c3f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da202200441017422062005200620054b1b22064100480da2020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4181013a00000c3e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da102200441017422062005200620054b1b22064100480da1020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4182013a00000c3d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490da002200441017422062005200620054b1b22064100480da0020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4183013a00000c3c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9f02200441017422062005200620054b1b22064100480d9f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4184013a00000c3b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9e02200441017422062005200620054b1b22064100480d9e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4185013a00000c3a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9d02200441017422062005200620054b1b22064100480d9d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4186013a00000c390b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9c02200441017422062005200620054b1b22064100480d9c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4187013a00000c380b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9b02200441017422062005200620054b1b22064100480d9b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4188013a00000c370b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9a02200441017422062005200620054b1b22064100480d9a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4189013a00000c360b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9902200441017422062005200620054b1b22064100480d99020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418a013a00000c350b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9802200441017422062005200620054b1b22064100480d98020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418b013a00000c340b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9702200441017422062005200620054b1b22064100480d97020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418c013a00000c330b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9602200441017422062005200620054b1b22064100480d96020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418d013a00000c320b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9502200441017422062005200620054b1b22064100480d95020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418e013a00000c310b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9402200441017422062005200620054b1b22064100480d94020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a418f013a00000c300b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9302200441017422062005200620054b1b22064100480d93020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4190013a00000c2f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9202200441017422062005200620054b1b22064100480d92020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4191013a00000c2e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9102200441017422062005200620054b1b22064100480d91020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4192013a00000c2d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d9002200441017422062005200620054b1b22064100480d90020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4193013a00000c2c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8f02200441017422062005200620054b1b22064100480d8f020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4194013a00000c2b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8e02200441017422062005200620054b1b22064100480d8e020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4195013a00000c2a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8d02200441017422062005200620054b1b22064100480d8d020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4196013a00000c290b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8c02200441017422062005200620054b1b22064100480d8c020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4197013a00000c280b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8b02200441017422062005200620054b1b22064100480d8b020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4198013a00000c270b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8a02200441017422062005200620054b1b22064100480d8a020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a4199013a00000c260b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8902200441017422062005200620054b1b22064100480d89020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419a013a00000c250b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8802200441017422062005200620054b1b22064100480d88020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419b013a00000c240b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8702200441017422062005200620054b1b22064100480d87020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419c013a00000c230b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8602200441017422062005200620054b1b22064100480d86020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419d013a00000c220b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8502200441017422062005200620054b1b22064100480d85020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419e013a00000c210b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8402200441017422062005200620054b1b22064100480d84020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a419f013a00000c200b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8302200441017422062005200620054b1b22064100480d83020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a0013a00000c1f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8202200441017422062005200620054b1b22064100480d82020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a1013a00000c1e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8102200441017422062005200620054b1b22064100480d81020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a2013a00000c1d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490d8002200441017422062005200620054b1b22064100480d80020240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a3013a00000c1c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dff01200441017422062005200620054b1b22064100480dff010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a4013a00000c1b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfe01200441017422062005200620054b1b22064100480dfe010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a5013a00000c1a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfd01200441017422062005200620054b1b22064100480dfd010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a6013a00000c190b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a7013a00000c180b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a8013a00000c170b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41a9013a00000c160b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41aa013a00000c150b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ab013a00000c140b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ac013a00000c130b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ad013a00000c120b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ae013a00000c110b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41af013a00000c100b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b0013a00000c0f0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b1013a00000c0e0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b2013a00000c0d0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df001200441017422062005200620054b1b22064100480df0010240024020040d002006102821050c010b200228020420042006102c21050b2005450def0120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b3013a00000c0c0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfc01200441017422062005200620054b1b22064100480dfc010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b4013a00000c0b0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfb01200441017422062005200620054b1b22064100480dfb010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b5013a00000c0a0b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490dfa01200441017422062005200620054b1b22064100480dfa010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b6013a00000c090b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df901200441017422062005200620054b1b22064100480df9010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b7013a00000c080b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df801200441017422062005200620054b1b22064100480df8010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b8013a00000c070b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df701200441017422062005200620054b1b22064100480df7010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41b9013a00000c060b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df601200441017422062005200620054b1b22064100480df6010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41ba013a00000c050b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df501200441017422062005200620054b1b22064100480df5010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bb013a00000c040b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df401200441017422062005200620054b1b22064100480df4010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bc013a00000c030b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df301200441017422062005200620054b1b22064100480df3010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bd013a00000c020b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df201200441017422062005200620054b1b22064100480df2010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41be013a00000c010b02400240200241086a2802002002410c6a2802002204460d00200228020421050c010b200441016a22052004490df101200441017422062005200620054b1b22064100480df1010240024020040d002006102821050c010b200228020420042006102c21050b2005450df00120022005360204200241086a20063602002002410c6a28020021040b2002410c6a200441016a360200200520046a41bf013a00000b2000411f3a000020012d00004109470df1010240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0cf1010b200641011037000b200641011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200841011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200a41011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200641011037000b200641011037000b200641011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200741011037000b200a41011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b1031000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200b41011037000b200941011037000b200841011037000b200841011037000b200841011037000b200841011037000b200741011037000b200641011037000b200841011037000b200441011037000b200741011037000b200441011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b200641011037000b1031000b20002004290200370200200041086a200441086a29020037020020012d00004109470d000240200141046a280200220228020441ffffffff0371450d002002280200102a200128020421020b2002102a0b200341106a24000bfb07030e7f017e017f200241086a2103200241046a210420012802002205210602400240024002400240034002400240200428020020032802002207460d00200228020021080c010b200741016a22082007490d02200741017422092008200920084b1b22094100480d020240024020070d002009102821080c010b200228020020072009102c21080b2008450d032002200836020020042009360200200328020021070b2003200741016a360200200820076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b2001280204220a2001410c6a2802002206410c6c6a210b200141086a280200210c200a21072006450d03200a21072005450d03200b41746a210d200241086a210841002107200a210e02400340200e2103024003402003280200220f0d01200741016a2107200b2003410c6a2203470d000c080b0b2003410c6a210e200741016a21102005417f6a2105200341046a290200211102400240034002400240200241046a220428020020082802002206460d00200228020021090c010b200641016a22092006490d06200641017422012009200120094b1b22014100480d060240024020060d002001102821090c010b200228020020062001102c21090b2009450d022002200936020020042001360200200828020021060b2008200641016a360200200920066a200741807f72200741ff0071200741077622061b3a0000200621072006450d020c000b0b200141011037000b2011422088a7221221060240034002400240200428020020082802002207460d00200228020021090c010b200741016a22092007490d05200741017422012009200120094b1b22014100480d050240024020070d002001102821090c010b200228020020072001102c21090b2009450d022002200936020020042001360200200828020021070b2008200741016a360200200920076a200641807f72200641ff0071200641077622071b3a00002007210620070d000b0240024020042802002206200828020022076b2012490d00200228020021060c010b200720126a22092007490d04200641017422072009200720094b1b22074100480d040240024020060d002007102821060c010b200228020020062007102c21060b2006450d032002200636020020042007360200200828020021070b2008200720126a360200200620076a200f2012109a051a02402011a7450d00200f102a0b200d2003460d052010210720050d010c050b0b200141011037000b200741011037000b1031000b200941011037000b2003410c6a21070b2007200b460d000340024020072802002206450d00200741046a280200450d002006102a0b2007410c6a2207200b470d000b0b0240200c450d00200a102a0b2000411f3a00000bcb0401067f200441046a2105024002400240024002400240200441086a2802002004410c6a2802002206460d00200528020021070c010b200641016a22072006490d04200641017422082007200820074b1b22084100480d040240024020060d002008102821070c010b200528020020062008102c21070b2007450d0120042007360204200441086a20083602002004410c6a28020021060b2004410c6a2208200641016a360200200720066a20024101463a0000200441086a2109034002400240200928020020082802002206460d00200528020021070c010b200641016a22072006490d052006410174220a2007200a20074b1b220a4100480d050240024020060d00200a102821070c010b20052802002006200a102c21070b2007450d03200420073602042009200a360200200828020021060b2008200641016a360200200720066a200141807f72200141ff0071200141077622061b3a00002006210120060d000b024020024101470d002004410c6a2107200441086a2108034002400240200828020020072802002206460d00200528020021010c010b200641016a22012006490d06200641017422092001200920014b1b22094100480d060240024020060d002009102821010c010b200528020020062009102c21010b2001450d052004200136020420082009360200200728020021060b2007200641016a360200200120066a200341807f72200341ff0071200341077622061b3a00002006210320060d000b0b2000411f3a00000f0b200841011037000b200a41011037000b200941011037000b1031000bb007010a7f230041d0006b2202240002400240024002400240024020012802082203200128020c2204460d00200441016a22052004490d02200320054f0d0120052003103c000b200241013a001f200241cc006a41013602002002420137023c200241a4e2c500360238200241263602342002200241306a36024820022002411f6a360230200241206a200241386a10332002411b6a200241286a28020036000020022002290320370013200220022900103703002002200241176a290000370007200041053a0004200020022903003700052000410c6a2002290007370000200041013602000c040b2001280200220620046a2d000021072001200536020c024020074102490d00200041173a000420004101360200200041056a20073a00000c040b410120036b2108200441026a2104410021054100210902400240034002402005411f4d0d00410f21050c020b02400240200820046a4102460d002004450d06200320044f0d0120042003103c000b200241013a0000200241cc006a41013602002002420137023c200241a4e2c500360238200241263602342002200241306a36024820022002360230200241106a200241386a1033410521050c020b200620046a417f6a2d0000210a2001200436020c200a41ff00712005411f71742009722109200441016a2104200541076a2105200a418001710d000b20054120490d01410d2105200a4110490d010b2000200536020420004101360200200041086a2002290210370200200041106a200241106a41086a2802003602000c040b4100210502402007410171450d002004417f6a2104410021054100210b02400240034002402005411f4d0d00410f21040c020b0240024020032004460d002004417f460d082003200441016a22084f0d01200441016a2003103c000b200241013a0000200241cc006a41013602002002420137023c200241a4e2c500360238200241263602342002200241306a36024820022002360230200241106a200241386a1033410521040c020b200620046a2d0000210a2001200836020c200a41ff00712005411f7174200b72210b200541076a210520082104200a418001710d000b20054120490d01410d2104200a4110490d010b2000200436020420004101360200200041086a2002290210370200200041106a200241106a41086a2802003602000c050b410121050b20002009360204200041003602002000410c6a200b360200200041086a20053602000c030b417f20051044000b417f20041044000b417f200441016a1044000b200241d0006a24000bee0201067f230041c0006b2202240041002103410021040240024003400240024002402003411f4b0d002001280204220520012802082206460d01200641016a22072006490d04200520074f0d0220072005103c000b200041013602002000410f3a00040c040b200241013a000f200241346a410136020020024201370224200241a4e2c5003602202002412636023c2002200241386a36023020022002410f6a360238200241106a200241206a10332002410b6a200241186a28020036000020022002290310370003200041053a0004200020022900003700052000410c6a200241076a290000370000200041013602000c030b200128020020066a2d0000210620012007360208200641ff00712003411f71742004722104200341076a21032006418001710d000b0240024020034120490d002006410f4b0d010b20004100360200200020043602040c020b200041013602002000410d3a00040c010b417f20071044000b200241c0006a24000bd806010a7f20012802042103200128020021044100210541002106410021074101210820012802082209210a02400240024002400340024020062007470d002005200641016a220b2005200b4b1b22074100480d050240024020060d002007102821080c010b200820062007102c21080b2008450d020b200820066a200a41807f72200a41ff0071200a410776220b1b3a0000200541026a2105200641016a2106200b210a200b0d000b0240200720066b20094f0d00200620096a220a2006490d0420074101742205200a2005200a4b1b220a4100480d040240024020070d00200a102821080c010b20082007200a102c21080b2008450d02200a21070b200820066a20042009109a051a02402003450d002004102a0b200128020c210c0240200720096b20066b200141146a280200220a490d002009200a6a20066a21030c030b200920066a2205200a6a22032005490d03200741017422052003200520034b1b22054100480d030240024020070d002005102821080c010b200820072005102c21080b02402008450d00200521070c030b200541011037000b200741011037000b200a41011037000b200820096a20066a200c200a109a051a200241086a210b200241046a21092003210a024002400340024002402009280200200b2802002206460d00200228020021050c010b200641016a22052006490d04200641017422042005200420054b1b22044100480d040240024020060d002004102821050c010b200228020020062004102c21050b2005450d022002200536020020092004360200200b28020021060b200b200641016a360200200520066a200a41807f72200a41ff0071200a41077622061b3a00002006210a20060d000b02400240200241046a280200220a200241086a28020022066b2003490d002002280200210a0c010b200620036a22052006490d03200a41017422062005200620054b1b22064100480d0302400240200a0d0020061028210a0c010b2002280200200a2006102c210a0b200a450d022002200a360200200241046a2006360200200241086a28020021060b200241086a200620036a360200200a20066a20082003109a051a02402007450d002008102a0b2000411f3a00000240200141106a280200450d00200c102a0b0f0b200441011037000b200641011037000b1031000bf20103027f017e057f024020002802082201200028020c460d00034020002001411c6a36020820012802102202450d01200141146a2902002103024020012802042204450d00200141086a280200210502402001410c6a2802002201450d0020014104742106200421010340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102a200728020021080b2008102a0b200141106a2101200641706a22060d000b0b2005450d002004102a0b02402003a7450d002002102a0b20002802082201200028020c470d000b0b02402000280204450d002000280200102a0b0be50101067f024020002802082201200028020c460d0003402000200141186a36020820012802002202450d01200141146a2802002103200141106a2802002104200128020c210502402001280204450d002002102a0b02402003450d0020034104742103200521010340024020012d00004109470d000240200141046a2206280200220228020441ffffffff0371450d002002280200102a200628020021020b2002102a0b200141106a2101200341706a22030d000b0b02402004450d002005102a0b20002802082201200028020c470d000b0b02402000280204450d002000280200102a0b0bf20103027f017e057f024020002802082201200028020c460d00034020002001411c6a36020820012802102202450d01200141146a2902002103024020012802042204450d00200141086a280200210502402001410c6a2802002201450d0020014104742106200421010340024020012d00004109470d000240200141046a2207280200220828020441ffffffff0371450d002008280200102a200728020021080b2008102a0b200141106a2101200641706a22060d000b0b2005450d002004102a0b02402003a7450d002002102a0b20002802082201200028020c470d000b0b02402000280204450d002000280200102a0b0bce0101057f024020002802082201450d00200028020022022001411c6c6a21030340024020022802042200450d0002402002410c6a2802002201450d00200141047421010340024020002d00004109470d000240200041046a2204280200220528020441ffffffff0371450d002005280200102a200428020021050b2005102a0b200041106a2100200141706a22010d000b0b200241086a280200450d002002280204102a0b2002411c6a21000240200241146a280200450d002002280210102a0b2000210220002003470d000b0b0b90d20106067f017e057f017e117f027e2300419081046b220224000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002402001280204220320012802082204460d00200441016a22052004490d02200320054f0d0120052003103c000b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210420022802fc8004210120004101360200200041003a00042001450d2b2004102a0c2b0b200128020020046a2d00002104200120053602082004410c4b0d03024002400240024020040e0d0001161514131211060d0c0b05000b200241e8006a200110f40441012106200228026c2107024020022802684101470d0020074108762101200241f8006a2802002104200241e8006a41086a29030021080c270b41002109200241e8006a4100418080011099051a410021034100210a2007450d20410021054100210a410121064100210b0340024002402001280204220c200128020822036b2007200b6b220441808001200441808001491b2204490d00200320046a220d2003490d05200c200d4f0d01200d200c103c000b200241013a00e880042002418c81046a4101360200200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241e880046a360218200241306a200241f880046a10332002290330210820022802382104410521070240200a450d002006102a0b0c280b200241e8006a200128020020036a2004109a051a2001200d36020802400240200a20056b2004490d00200520046a21030c010b200520046a22032005490d23200a410174220d2003200d20034b1b220d4100480d2302400240200a0d00200d102821060c010b2006200a200d102c21060b2006450d03200d210a0b200620056a200241e8006a2004109a051a2003210520072004200b6a220b4b0d000c210b0b200241e8006a200110fb04024020022802684101470d00200228026c22044108762105200241e8006a41086a2903002208422088210e200241f8006a28020021030c1f0b200241fc006a280200210f200241f8006a2802002101200241f4006a2802002103200241f0006a2802002110200228026c210b4100210441002109024002400240034002402004411f4d0d00410f21040c020b0240024020032001460d002001417f460d052003200141016a22054f0d01200141016a2003103c000b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241c8006a200241e8006a1033410521040c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b20044120490d01410d210420064110490d010b200241f880046a41086a200241c8006a41086a28020022033602002002200229034822083703f880042008422088a721092008a721060c1f0b200241003602602002420437035802400240024020090d00410421010c010b410020036b2111200b41026a2112410120036b21134100210a410421014100211441002115410021160340201621170240024020032005460d000240200541016a22042005490d000240024020032004490d000240200b20056a2d0000220441e000460d00411821050c250b201741016a211641022118200541026a210441002106410321192012211a4100211b024002400340201a21072019210c2018210d02402006411f4d0d00410f21050c020b02400240201320046a4102460d002004450d06200320044f0d0120042003103c000b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f88004370320410521050c020b200b20046a417f6a2d0000221c41ff00712006411f7174201b72211b200d41016a2118200c41016a2119200741016a211a200441016a2104200641076a2106201c418001710d000b20064120490d01201c4110490d01410d21050b200241e880046a41086a200241206a41086a28020022033602002002200229032022083703e880042008a721064100210420022802ec800421090c240b41002118200241003602382002420137033002400240201b0d002004417f6a21064101211c4100211a4100211d0c010b201120056a211e410021194101211c4100211a034002400240024002400240201e200d6a450d002005200c6a2204450d02200320044f0d0120042003103c000b200220193602342002201a3602382002201c360230200241013a00e880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022802f88004210620022802fc80042109200228028081042103410521050c280b200720056a2c000022044100480d0102400240200441c00071450d00200441807f72220441ff017141fb014b0d010b200220193602342002201a3602382002201c360230410621050c270b0240201a2019460d002019211d201a21060c030b201941016a22062019490d2e2019410174221d2006201d20064b1b221d4100480d2e0240024020190d00201d1028211c0c010b201c2019201d102c211c0b0240201c450d0020192106201d21190c030b201d41011037000b417f20041044000b200220193602342002201a3602382002201c360230411921050c240b201c20066a2004417f733a0000200d41016a210d200c41016a210c200741016a2107201b201a41016a221a470d000b2002201d3602342002201a3602382002201c3602302005200d6a21060b201c411076411074221b201c41087641ff0171410874221972201c41ff0171221c72210c4100210d024003404100210402402018411f4d0d00410f21050c230b0240024020032006460d002006417f460d032003200641016a22054f0d01200641016a2003103c000b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050c230b200b20066a2d0000220741ff00712018411f7174200d72210d201841076a2118200521062007418001710d000b20184120490d052007410f4d0d05410d21050c210b417f200641016a1044000b20042003103c000b417f20041044000b417f20041044000b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050c200b0240200d41014d0d004104210541e885c6002106412421090c1b0b024002400240200d0e020001000b410421060c010b20032005460d1a024002400240200541016a220d2005490d002003200d490d010240200b20056a2c0000220441004e0d00411921050c200b41062105200441c00071450d02200441807f72220441ff017141fb014d0d022004417f732106200d21050c030b417f200541016a1044000b200541016a2003103c000b0c1c0b024020172015470d00024020142015460d00201421150c010b201441016a22042014490d252014410174220d2004200d20044b1b221541ffffffff00712015470d25201541047422044100480d250240024020140d002004102821010c010b200120144104742004102c21010b2001450d032002201536025c20022001360258201521140b200120174104746a2204201f4180807c71200641ff01714108747241e00072221f36020c2004201a3602082004201d36020420042019201c72201b72360200200a41106a210a2002201636026020162009470d000b0b2005200f462104200229025c2208422088210e02402010450d00200b102a0b200ea721052008a721092004450d1e2005ad4220862009ad842108410221030c2a0b200441041037000b417f200141016a1044000b200d41011037000b2003200d1044000b417f20051044000b200241e8006a200110fb04024020022802684101470d00200041013602002000200241e8006a41047222012902003702042000410c6a200141086a2902003702000c290b200241fc006a280200210d200241f8006a2802002104200241f4006a2802002105200241f0006a280200210a200228026c210b410021034100210102400240034002402003411f4d0d00410f21040c080b20052004460d062004417f460d012005200441016a2206490d02200b20046a2d0000220941ff00712003411f71742001722101200341076a2103200621042009418001710d000b20034120490d04410d21042009410f4b0d060c040b417f200441016a1044000b200441016a2005103c000b200241e8006a200110fb04024020022802684101470d00200041013602002000200241e8006a41047222012902003702042000410c6a200141086a2902003702000c280b200241fc006a280200210d200241f8006a2802002104200241f4006a2802002105200241f0006a280200210a200228026c210b410021034100210102400240034002402003411f4d0d00410f21040c0d0b20052004460d0b2004417f460d012005200441016a2206490d02200b20046a2d0000220941ff00712003411f71742001722101200341076a2103200621042009418001710d000b20034120490d09410d21042009410f4b0d0b0c090b417f200441016a1044000b200441016a2005103c000b200041123a000420004101360200200041056a20043a00000c260b200d20064621040240200a450d00200b102a0b02402004450d00410b21030c220b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a10332002418381046a200241386a280200360000200220022903303700fb8004200041053a0004200020022900f880043700052000410c6a200241ff80046a290000370000200041013602000c250b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033410521040b2000200436020420004101360200200041086a20022902f88004370200200041106a200241f880046a41086a280200360200200a450d23200b102a0c230b200241e8006a200110fb040240024020022802684101470d00200228026c22014108762106200241e8006a41086a2903002208422088210e200241f8006a280200210b0c010b200241c0006a200241fc006a280200360200200241386a200241f4006a2902003703002002200229026c37033041002101410021050240024002400240024002400240034002402001411f4d0d00410f210d0c020b0240024020022802382209200228023c2204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241c8006a200241e8006a10334105210d0c020b200228023020046a2d000021042002200336023c200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210d20044110490d010b200241f880046a41086a200241c8006a41086a280200220b3602002002200229034822083703f880042008422088a721072008a7210c410021060c040b200241003602502002420437034802400240024020050d00410421010c010b4100210d0340200d41016a210d41002101410021090240024002400240024002400240034002402001411f4d0d00410f210d0c030b20022802382206200228023c2204460d01200441016a22032004490d0420062003490d06200228023020046a2d000021042002200336023c200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d022004410f4d0d02410d210d0c010b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241f880046a200241e8006a1033200241e880046a41086a200241f880046a41086a280200360200200220022903f8800422083703e880042008a7210c4105210d0b20022802f08004210b20022802ec80042107410021060c0a0b200241e8006a200241306a10ed04024020022802684101470d00200228026c220d41087621062002280278210b200228027421072002280270210c0c0a0b200228027421192002280270211c200228026c211a410021044100210b02400240034002402004411f4d0d00410f210d0c020b0240024020022802382206200228023c2203460d00200341016a22012003490d06200620014f0d0120012006103c000b200241013a00e880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f8800422083703202008a7210c4105210d0c030b2002280230220a20036a2d000021032002200136023c200341ff00712004411f7174200b72210b200441076a21042003418001710d000b20044120490d0520034110490d05410d210d0b0b2002280228210b200228022421070c080b417f20031044000b417f20011044000b20032006103c000b4100211b200241e8006a4100418080041099051a02400240200b0d00410121184100210c0c010b4100211b41012118410021034100210702400240034002400240200620016b200b20076b220441808004200441808004491b2204490d00200120046a220c2001490d032006200c4f0d01200c2006103c000b200241013a00202002410136028c8104200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241206a360218200241e880046a200241f880046a103320022802e88004210c20022802ec8004210720022802f08004210b4105210d201b450d092018102a0c090b200241e8006a200a20016a2004109a051a2002200c36023c02400240201b20036b2004490d00200320046a210c0c010b200320046a220c2003490d24201b4101742201200c2001200c4b1b22014100480d2402400240201b0d002001102821180c010b2018201b2001102c21180b2018450d032001211b0b201820036a200241e8006a2004109a051a200b200420076a22074d0d03200228023c2101200228023821062002280230210a200c21030c000b0b2001200c1044000b200141011037000b024020022802502203200228024c470d00200341016a22012003490d20200341017422042001200420014b1b2204ad421c7e2208422088a70d202008a722064100480d200240024020030d002006102821010c010b20022802482003411c6c2006102c21010b2001450d032002200436024c200220013602480b200228024822012003411c6c6a2204200941087622063b0001200420183602102004201a360204200420093a0000200441036a20064110763a0000200441186a200c360200200441146a201b3602002004410c6a2019360200200441086a201c3602002002200341016a360250200d2005470d000b0b200228023c2002280240462104200229024c2208422088210e02402002280234450d002002280230102a0b20014108762105200ea721032008a7210a2004450d052005410874200141ff01717221012003ad422086200aad842108410d21030c250b200641041037000b417f20031044000b02402019450d0020194104742104201a21010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b41002106201c450d00201a102a0b2002280248211b024020022802502201450d00201b2001411c6c6a210a201b21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102a0b2009411c6a21010240200941146a280200450d002009280210102a0b200121092001200a470d000b0b200228024c450d00201b102a0b2006410874200d41ff01717221012007ad220e422086200cad8421082002280234450d012002280230102a0c010b2005410874200141ff017172210d20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022903f88004210820022802808104210b02402003450d00200d2003411c6c6a2106200d21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102a0b2009411c6a21010240200941146a280200450d002009280210102a0b2001210920012006470d000b0b2008422088210e4105210141002106200a450d00200d102a0b20004101360200200041106a200b360200200041086a200e422086200842ffffffff0f838437020020002006410874200141ff0171723602040c220b200241e8006a200110fb040240024020022802684101470d00200228026c220a4108762104200241e8006a41086a2903002208422088210e200241f8006a280200210d0c010b200241fc006a280200211b200241f8006a2802002101200241f4006a2802002105200241f0006a2802002107200228026c210b410021044100210902400240024002400240024002400240024002400240034002402004411f4d0d00410f210a0c020b0240024020052001460d002001417f460d052005200141016a22034f0d01200141016a2005103c000b200241013a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a10334105210a0c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200321012006418001710d000b20044120490d01410d210a20064110490d010b200241306a41086a200241f880046a41086a280200220d360200200220022902f8800422083703302008422088a7210c2008a7211b0c080b2002410036026020024204370358024002400240024020090d00410421010c010b200241f1006a21104100211c0340201c41016a211c410021014100210602400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210a0c020b0240024020052003460d002003417f460d062005200341016a22044f0d01200341016a2005103c000b200241013a00f880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241f880046a360218200241c8006a200241e8006a10334105210a2002280248211b0c030b200b20036a2d0000220a41ff00712001411f71742006722106200141076a210120042103200a418001710d000b20014120490d02200a4110490d02410d210a0b0b2002280250210d200228024c210c0c160b4100210c200241e8006a4100418080011099051a410121180240024020060d00200421034100211a4100210a0c010b4100210d4100211a41002119034002400240200520046b200620196b220141808001200141808001491b2201490d00200420016a22032004490d05200520034f0d0120032005103c000b200241013a00482002410136028c8104200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241c8006a360218200241e880046a200241f880046a103320022802e88004211b20022802ec8004210c20022802f08004210d4105210a201a450d182018102a0c180b200241e8006a200b20046a2001109a051a02400240201a200d6b2001490d00200d20016a210a0c010b200d20016a220a200d490d31201a4101742204200a2004200a4b1b22044100480d3102400240201a0d002004102821180c010b2018201a2004102c21180b2018450d052004211a0b2018200d6a200241e8006a2001109a051a20032104200a210d2006200120196a22194b0d000b0b2002200a3602402002410036023c2002200a3602382002201aad4220862018ad84370330410021014100210d02400240034002402001411f4d0d00410f210a0c020b02400240200a200c460d00200c417f460d08200a200c41016a22064f0d01200c41016a200a103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f880043703204105210a0c020b2018200c6a2d000021042002200636023c200441ff00712001411f7174200d72210d200141076a21012006210c2004418001710d000b20014120490d0120044110490d01410d210a0b200241e880046a41086a200241206a41086a280200220d3602002002200229032022083703e880042008a7211b20022802ec8004210c0c150b41002119200241003602f08004200242043703e8800402400240200d0d004104210f41002118410021160c010b410021184104210f410021160340201821172016221d41016a2116410021014100210c024002400240034002402001411f4d0d00410f21040c020b0240024020022802382218200228023c2204460d00200441016a22062004490d0c201820064f0d0120062018103c000b200241013a00f880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241f880046a360218200241c8006a200241e8006a1033410521042002280248211b0c030b2002280230221a20046a2d0000210a2002200636023c200a41ff00712001411f7174200c72210c200141076a2101200a418001710d000b20014120490d02200a4110490d02410d21040b0b2002280250210d200228024c210c410021010c0c0b02400240024020182006460d00200441026a21042006417f460d0a20182004490d0c201a20066a2c000021012002200436023c0240200141004e0d00411921040c0f0b41062104200141c00071450d0d200141807f72220141ff017141fb014d0d0d201d2017460d0120172118201d21170c020b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241f880046a200241e8006a103320022802f88004211b20022802fc8004210c20022802808104210d410521040c0d0b201741016a22042017490d31201741017422062004200620044b1b221841ffffffff01712018470d31201841037422044100480d310240024020170d0020041028210f0c010b200f20174103742004102c210f0b200f450d092002200f3602e880040b200f20174103746a2204201341807e712001417f7341ff01717222133a00042004200c3602002016200d470d000b200220183602ec8004200220163602f080040b200f20164103746a210d200f2101200f210602400340200d20066b41184d0d01201920012802006a22042019490d132004200141086a2802006a22062004490d132006200141106a2802006a22042006490d13200141186a210a200141206a220621012004200a2802006a22192004490d130c000b0b0340200d2001460d0b201920012802006a22042019492106200141086a21012004211920060d120c000b0b417f200341016a1044000b200420031044000b200441011037000b417f200c41016a1044000b417f20061044000b417f20041044000b200441041037000b20042018103c000b0b200220173602ec80042002201d3602f08004200141ff0171410874200472210a20170d090c0a0b4101210a410021044108211a410021060340200241e8006a200241306a10ee04024020022802684101470d002002280278210d2002280274210c2002280270211b200228026c210a0c070b200241f880046a41026a2201201041026a2d00003a0000200220102f00003b01f8800420022802742117200229037821080240024002400240024020022d0070220d4106470d00200a417f6a210a0c010b200d417e6a41034f0d00200a41016a220c200a4f2119200c210a20190d004115210c41c4fdc500211b4104210a200d4109460d010c0a0b200241e8006a41026a220c20012d00003a0000200220022f01f880043b016820062004460d01200421190c020b0240201728020441ffffffff0371450d002017280200102a0b2017102a0c080b200441016a22012004490d25200441017422062001200620014b1b221941ffffffff00712019470d25201941047422014100480d250240024020040d0020011028211a0c010b201a20044104742001102c211a0b201a450d0420042106201921040b201a20064104746a2201200d3a00002001200837030820012017360204200120022f01683b0001200141036a200c2d00003a0000200641016a2106200a0d000b200228023c200228024046210102402002280234450d002002280230102a0b0240024002402001450d002002280260220a200228025c470d02200a41016a2201200a490d26200a41017422042001200420014b1b220dad42187e2208422088a70d262008a7220441004e0d010c260b20024103410220011b3a00e880042002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022802f88004211b20022802fc8004210c20022802808104210d02402006450d0020064104742104201a21010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b02402019450d00201a102a0b4105210a2018450d0c200f102a0c0c0b02400240200a0d002004102821010c010b2002280258200a41186c2004102c21010b2001450d042002200d36025c200220013602580b20022802582201200a41186c6a2204201a36020c20042016360208200420183602042004200f360200200441146a2006360200200441106a20193602002002200a41016a360260201c2009470d000b0b2003201b462104200229025c2208422088210e02402007450d00200b102a0b200ea721032008a721072004450d0a2003ad4220862007ad842108410c21030c290b200141081037000b200441041037000b417f200141016a1044000b02402006450d0020064104742103201a21010340024020012d00004109470d000240200141046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200141106a2101200341706a22030d000b0b2004450d01201a102a0c010b20022802808104210d20022802fc8004210c411c210a0b2018450d010b200f102a0b2002280234450d002002280230102a0b20022802582118024020022802602201450d002018200141186c6a21062018210903400240200941046a280200450d002009280200102a0b0240200941146a2802002204450d00200928020c2101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941186a21010240200941106a280200450d00200928020c102a0b2001210920012006470d000b0b200228025c450d002018102a0b200a4108762104200cad220e422086201bad8421082007450d01200b102a0c010b20024103410220041b3a0030200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022903f88004210820022802808104210d02402003450d002001200341186c6a210b2001210603400240200641046a280200450d002006280200102a0b0240200641146a2802002203450d00200628020c2104200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200441106a2104200341706a22030d000b0b200641186a21040240200641106a280200450d00200628020c102a0b200421062004200b470d000b0b2008422088210e4105210a410021042007450d002001102a0b20004101360200200041106a200d360200200041086a200e422086200842ffffffff0f838437020020002004410874200a41ff0171723602040c210b200241e8006a200110fb040240024020022802684101470d00200228026c22044108762106200241e8006a41086a2903002208422088210e200241f8006a280200210b0c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f880044100210141002105024002400240024002400240024002400240034002402001411f4d0d00410f210d0c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241e880046a41086a200241306a41086a280200360200200220022903303703e880044105210d0c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210d20044110490d010b200241c8006a41086a200241e880046a41086a280200220b360200200220022903e8800422083703482008422088a721072008a7210c410021060c060b200241003602f08004200242043703e880040240024020050d00410421010c010b4100210b0340200b41016a210b410021014100210902400240024002400240034002402001411f4d0d00410f210d0c030b200228028081042206200228028481042204460d01200441016a22032004490d0920062003490d0c20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d022004410f4d0d02410d210d0c010b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a2802003602002002200229033022083703202008a7210c4105210d0b2002280228210b20022802242107410021060c010b200241e8006a200241f880046a10ed04024020022802684101470d00200228026c220d41087621062002280278210b200228027421072002280270210c0c010b2002280274211b20022802702119200228026c2118200241e8006a200241f880046a10ef0420022802684101470d01200228026c210d2002280278210b200228027421072002280270210c0240201b450d00201b4104742104201821010340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200d41087621062019450d002018102a0b20022802e88004211b024020022802f080042201450d00201b2001411c6c6a210a201b21090340024020092802042201450d0002402009410c6a2802002204450d00200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941086a280200450d002009280204102a0b2009411c6a21010240200941146a280200450d002009280210102a0b200121092001200a470d000b0b20022802ec8004450d08201b102a0c080b4100210a2002280270210c200228026c2107024002402002280274220141027422030d004104210d410021060c010b2003410275220641ffffffff03712006470d1f200641027422044100480d1f20041028220d450d050b02402001450d002003417c6a210a200d210120072104034020012004280200360200200141046a2101200441046a21042003417c6a22030d000b200a41027641016a210a0b0240200c450d002007102a0b024020022802f08004220320022802ec8004470d00200341016a22012003490d1f200341017422042001200420014b1b2204ad421c7e2208422088a70d1f2008a722074100480d1f0240024020030d002007102821010c010b20022802e880042003411c6c2007102c21010b2001450d06200220043602ec8004200220013602e880040b20022802e8800422012003411c6c6a2204200941087622073b00012004200d36021020042018360204200420093a0000200441036a20074110763a0000200441186a200a360200200441146a20063602002004410c6a201b360200200441086a20193602002002200341016a3602f08004200b2005470d000b0b200228028481042002280288810446210420022902ec80042208422088210e024020022802fc8004450d0020022802f88004102a0b200ea721032008a7210d2004450d062003ad422086200dad842108410a21030c240b417f20031044000b417f20031044000b200441041037000b200741041037000b20032006103c000b2006410874200d41ff01717221042007ad220e422086200cad84210820022802fc8004450d0120022802f88004102a0c010b20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1033200229033021082002280238210b02402003450d0020012003411c6c6a210a200121060340024020062802042204450d0002402006410c6a2802002203450d00200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200441106a2104200341706a22030d000b0b200641086a280200450d002006280204102a0b2006411c6a21040240200641146a280200450d002006280210102a0b200421062004200a470d000b0b2008422088210e4105210441002106200d450d002001102a0b20004101360200200041106a200b360200200041086a200e422086200842ffffffff0f838437020020002006410874200441ff0171723602040c200b200d20064621040240200a450d00200b102a0b02402004450d00410921030c1c0b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a10332002418381046a200241386a280200360000200220022903303700fb8004200041053a0004200020022900f880043700052000410c6a200241ff80046a290000370000200041013602000c1f0b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033410521040b2000200436020420004101360200200041086a20022902f88004370200200041106a200241f880046a41086a280200360200200a450d1d200b102a0c1d0b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762104200241e8006a41086a2903002208422088210e200241f8006a28020021090c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f880044100210141002105024002400240024002400240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f21030c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a28020036020020022002290330370320410521030c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210320044110490d010b200241e880046a41086a200241206a41086a28020022093602002002200229032022083703e880042008422088a721062008a7210b0c100b20024100360260200242043703584104210102402005450d004100211b4100210c4100211a0340200241e8006a200241f880046a10fc04024020022802684101470d002002200229027422083703e880042002280270210b200228026c21032008a721060c100b20022802702118200228026c211902400240200228028081042203200228028481042209460d00200941016a22042009490d05200320044f0d0120042003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c0d0b2002280274211c20022802f88004220620096a2d000021072002200436028481040240200741034d0d00410a21040c0f0b0240024002400240024020070e0400010203000b410021074100210b4100210903400240200b411f4d0d00410f21040c140b20032004460d122004417f460d092003200441016a220d490d0e200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41002107200b4120490d03200a410f4d0d03410d21040c120b4100210b410021090340200b411f4b0d0f0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c110b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41012107200b4120490d02200a410f4d0d020c0d0b4100210b410021090340200b411f4b0d0e0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c100b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41022107200b4120490d01200a410f4b0d0c0c010b4100210b410021090340200b411f4b0d0d0240024020032004460d002004417f460d0b2003200441016a220d4f0d01200441016a2003103c000b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10330c0f0b200620046a2d0000210a2002200d3602848104200a41ff0071200b411f71742009722109200b41076a210b200d2104200a418001710d000b41032107200b4120490d00200a410f4b0d0b0b200220093602f08004200220073602ec800420022902ec8004210802400240200c201b460d00201b21030c010b201b41016a2204201b490d24201b41017422032004200320044b1b2203ad42147e220e422088a70d24200ea722044100480d2402400240201b0d002004102821010c010b2001201b41146c2004102c21010b2001450d0920022001360258201b210c2003211b0b2001200c41146c6a2204200837020c2004201c3602082004201836020420042019360200200c41016a210c201a41016a221a2005470d000b2002200336025c2002200c3602600b2002280284810420022802888104462104200229025c2208422088210e024020022802fc8004450d0020022802f88004102a0b200ea721032008a721052004450d0e2003ad4220862005ad842108410821030c290b417f20031044000b417f20041044000b417f200441016a1044000b417f200441016a1044000b417f200441016a1044000b417f200441016a1044000b200441041037000b200441016a2003103c000b410d2104410021070c030b410f2104410021070c020b2002280230210b2002290234210841052104410021070c010b200241013a00482002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241306a200241e8006a10332002280230210b20022902342108410521040b20074108742004722103200220083703e880042008a721062018450d002019102a0b2002200c3602602002201b36025c20022802ec800421090240200c450d00200c41146c21052001210403400240200441046a280200450d002004280200102a0b200441146a21042005416c6a22050d000b0b201b450d012001102a0c010b20024103410220041b3a00e88004200241e8006a41146a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1033200229033021082002280238210902402003450d00200341146c21032001210403400240200441046a280200450d002004280200102a0b200441146a21042003416c6a22030d000b0b2008422088210e41052103410021042005450d012001102a0c010b200341087621042006ad220e422086200bad84210820022802fc8004450d0020022802f88004102a0b20004101360200200041106a2009360200200041086a200e422086200842ffffffff0f838437020020002004410874200341ff0171723602040c1c0b200241e8006a200110fb040240024020022802684101470d00200228026c220b4108762104200241e8006a41086a2903002208422088210e200241f8006a28020021060c010b200241c0006a200241fc006a280200360200200241386a200241f4006a2902003703002002200229026c37033041002101410021090240024002400240024002400240024002400240024002400240034002402001411f4d0d00410f210b0c020b0240024020022802382205200228023c2204460d00200441016a22032004490d05200520034f0d0120032005103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f880043703204105210b0c020b2002280230220620046a2d000021042002200336023c200441ff00712001411f71742009722109200141076a21012004418001710d000b20014120490d01410d210b20044110490d010b200241e880046a41086a200241206a41086a28020022063602002002200229032022083703e880042008422088a721072008a7210d0c0b0b20024100360260200242043703580240024020090d00410421010c010b2009417f6a211b4104210141042110410421094104211c4104211a4100210a4100210c03400240024020052003460d00200341016a220b2003490d052005200b4f0d01200b2005103c000b2002200a36025c2002200c360260200241013a0048200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241e880046a200241e8006a103320022802e88004210d20022802ec8004210720022802f080042106410521010c090b200620036a2c000021042002200b36023c20044100480d0402400240200441c00071450d00200441807f72220441ff017141fb014b0d010b2002200a36025c2002200c360260410621010c080b024002400240024002402005200b460d00200341026a210d200b417f460d0a2005200d4f0d01200d2005103c000b2002200a36025c2002200c360260200241013a0048200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241c8006a360218200241e880046a200241e8006a103320022802e88004210d20022802ec8004210720022802f080042106410521010c010b2006200b6a2d000021032002200d36023c0240200341014b0d004100210520030e020302030b2002200a36025c2002200c360260410c21010b2002418881046a20063602002002418481046a20073602002002418081046a200d360200200220033a00fd8004200220013a00fc80040c0b0b41800221050b200241e8006a200241306a10ed04200228027421072002280270210d200228026c210b024020022802684101470d002002200a36025c2002200c360260200241f8006a28020021060c0b0b02400240200c200a460d00200a2118200c210a0c010b200a41016a2201200a490d1e200a41017422032001200320014b1b221841ffffffff00712018470d1e201841047422034100480d1e02400240200a0d002003102821010c010b201c200a4104742003102c21010b2001450d072002200136025820012110200121092001211c2001211a0b201a200a4104746a220320194180807c712004417f7341ff017172200572221936020c200320073602082003200d3602042003200b360200200a41016a210c0240201b450d00201b417f6a211b200228023c210320022802382105200228023021062018210a0c010b0b2002201836025c2002200c3602600b200228023c2002280240462104200229025c2208422088210e02402002280234450d002002280230102a0b200ea721032008a7210d2004450d092003ad422086200dad842108410721030c230b417f20031044000b417f200b1044000b2002200a36025c2002200c360260411921010c020b417f200d1044000b200341041037000b0b2002418881046a20063602002002418481046a20073602002002418081046a200d360200200220043a00fd8004200220013a00fc80040b200241013a00f8800420022802fc8004210b0b0240200c450d002009200c4104746a210c0340024020092802082204450d0020092802002101200441047421040340024020012d00004109470d000240200141046a2205280200220328020441ffffffff0371450d002003280200102a200528020021030b2003102a0b200141106a2101200441706a22040d000b0b200941106a21010240200941046a280200450d002009280200102a0b200121092001200c470d000b0b200a450d012010102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022903f88004210820022802808104210602402003450d00200120034104746a210a2001210b03400240200b2802082203450d00200b2802002104200341047421030340024020042d00004109470d000240200441046a2209280200220528020441ffffffff0371450d002005280200102a200928020021050b2005102a0b200441106a2104200341706a22030d000b0b200b41106a21040240200b41046a280200450d00200b280200102a0b2004210b2004200a470d000b0b2008422088210e4105210b41002104200d450d012001102a0c010b200b41087621042007ad220e422086200dad8421082002280234450d002002280230102a0b20004101360200200041106a2006360200200041086a200e422086200842ffffffff0f838437020020002004410874200b41ff0171723602040c1b0b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a29020022083703002002200229026c220e3703f88004200ea7210b2008a7210541002104200228028481042101410021030240024002400240024002400240024003402004411f4b0d010240024020052001460d002001417f460d072005200141016a22094f0d01200141016a2005103c000b200220053602848104200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a280200360200200220022903303703204105210b0c030b200b20016a2d0000220641ff00712004411f71742003722103200441076a2104200921012006418001710d000b200220093602848104024020044120490d00410d210b2006410f4b0d020b200241003602382002420437033020030d02410421010c030b200220013602848104410f210b0b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008422088a7210a2008a7210d410021090c040b4104210141002105410021060340200241e8006a200241f880046a10f30420022f006d20022d006f4110747221092002280274210a2002280270210d20022d006c210b024020022802684101470d002002200536023420022006360238200241f8006a28020021042005450d052001102a0c050b0240024020062005460d0020052107200621040c010b200541016a22042005490d16200541017422072004200720044b1b2207ad420c7e2208422088a70d162008a722044100480d160240024020050d002004102821010c010b20012005410c6c2004102c21010b2001450d042002200136023020052104200721050b20012004410c6c6a220420093b00012004200d3602042004200b3a0000200441036a20094110763a0000200441086a200a3602002003200641016a2206470d000b20022007360234200220063602380b200228028481042002280288810446210420022902342108024020022802fc8004450d0020022802f88004102a0b2008a721092004450d032008422088a7ad4220862009ad842108410621030c1b0b417f200141016a1044000b200441041037000b200941ffffff07712205410874200b41ff0171722103200aad220e422086200dad84210820022802fc8004450d0120022802f88004102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a103320022903302208422088210e2002280238210441052103410021052009450d002001102a0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c1a0b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a29020022083703002002200229026c220e3703f88004200ea7210b2008a721034100210420022802848104210141002109024002400240024002400240024002400240024003402004411f4b0d010240024020032001460d002001417f460d072003200141016a22054f0d01200141016a2003103c000b200220033602848104200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a280200360200200220022903303703204105210a0c030b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b200220053602848104024020044120490d00410d210a2006410f4b0d020b41002107200241003602f08004200242043703e8800420090d02410421014100210d0c030b200220013602848104410f210a0b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008a7210b4100210320022802ec8004210d0c060b4104210141012107410021060340024002400240024020032005460d00200541016a22042005490d0720032004490d09200b20056a2c000021032002200436028481040240200341004e0d004119210a0c020b4107210a0240200341c000710d000c020b200341807f7222034170470d02200241e8006a200241f880046a10f30420022f006d20022d006f41107472210320022d006c210a20022802684101470d0320034180feff07714108762105200228027821042002280274210d2002280270210b0c020b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10332002280230210b2002280234210d200228023821044105210a0b0b200220063602ec800420022007417f6a3602f080042005410874200341ff01717221032006450d072001102a0c070b200228027421052002280270210b024002402007417f6a22042006460d002006210d200421060c010b200641016a22042006490d172006410174220d2004200d20044b1b220dad420c7e2208422088a70d172008a722044100480d170240024020060d002004102821010c010b20012006410c6c2004102c21010b2001450d05200220013602e880040b20012006410c6c6a220420033b0001200420053602082004200b3602042004200a3a0000200441036a20034110763a0000024020092007460d00200741016a210720022802848104210520022802808104210320022802f88004210b200d21060c010b0b2002200d3602ec8004200220073602f080040b2002280284810420022802888104462104024020022802fc8004450d0020022802f88004102a0b2004450d052007ad422086200dad842108410521030c1c0b417f200141016a1044000b417f20041044000b200441041037000b20042003103c000b200341ffffff07712205410874200a41ff0171722103200dad220e422086200bad84210820022802fc8004450d0120022802f88004102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a103320022903302208422088210e200228023821044105210341002105200d450d002001102a0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c190b200241e8006a200110fb040240024020022802684101470d00200228026c22044108762105200241e8006a41086a2903002208422088210e200241f8006a28020021030c010b200241fc006a280200210c200241f8006a2802002101200241f4006a2802002103200241f0006a2802002107200228026c210b41002104410021090240024002400240024002400240024002400240034002402004411f4d0d00410f21040c020b0240024020032001460d002001417f460d052003200141016a22054f0d01200141016a2003103c000b200241013a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a1033200241206a41086a200241f880046a41086a280200360200200220022903f88004370320410521040c020b200b20016a2d0000220641ff00712004411f71742009722109200441076a2104200521012006418001710d000b20044120490d01410d210420064110490d010b200241e880046a41086a200241206a41086a28020022033602002002200229032022083703e880042008a7210520022802ec800421090c070b4100211b20024100360238200242043703300240024020090d0041042101410021060c010b41042101410021064100211b034020062118201b221941016a211b20052104410021064100210a03402006411f4b0d050240024020032004460d002004417f460d062003200441016a22054f0d01200441016a2003103c000b2002201836023420022019360238200241013a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241f880046a200241e8006a103320022802f88004210520022802fc80042109200228028081042103410521040c090b200b20046a2d0000220d41ff00712006411f7174200a72210a200641076a210620052104200d418001710d000b024020064120490d00200d410f4d0d002002201836023420022019360238410d21040c070b0240024020192018460d0020182106201921180c010b201841016a22042018490d18201841017422062004200620044b1b220641ffffffff03712006470d18200641027422044100480d180240024020180d002004102821010c010b200120184102742004102c21010b2001450d06200220013602300b200120184102746a200a360200201b2009470d000b200220063602342002201b3602380b2005200c46210402402007450d00200b102a0b2004450d07201bad4220862006ad842108410421030c1d0b417f200141016a1044000b417f200441016a1044000b2002201836023420022019360238410f21040c010b200441041037000b0b2018450d002001102a0b2009ad220e4220862005ad842108410021052007450d01200b102a0c010b20024103410220041b3a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022903f880042208422088210e20022802808104210341052104410021052006450d002001102a0b20004101360200200041106a2003360200200041086a200e422086200842ffffffff0f838437020020002005410874200441ff0171723602040c180b200241e8006a200110fb040240024020022802684101470d00200228026c22034108762105200241e8006a41086a2903002208422088210e200241f8006a28020021040c010b2002418881046a200241fc006a2802003602002002418081046a200241f4006a2902003703002002200229026c3703f8800441002101410021050240024002400240024002400240024002400240034002402001411f4d0d00410f21030c020b02400240200228028081042209200228028481042204460d00200441016a22032004490d05200920034f0d0120032009103c000b200241013a0058200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200241206a41086a200241306a41086a28020036020020022002290330370320410521030c020b20022802f8800420046a2d00002104200220033602848104200441ff00712001411f71742005722105200141076a21012004418001710d000b20014120490d01410d210320044110490d010b200241e880046a41086a200241206a41086a28020022043602002002200229032022083703e880042008422088a721092008a721060c080b200241003602f08004200242043703e8800402400240024020050d00410421010c010b20022802ec8004210720022802f08004210d410021100340200241e8006a200241f880046a10fc042002280274210920022802702118200228026c211a024020022802684101470d002002280278210420182106201a21030c090b200241e8006a200241f880046a10fc042002280274211320022802702119200228026c211c024020022802684101470d00200228027821042019210620132109201c21030c080b0240024002400240024002400240024002400240024002400240024002400240200228028081042203200228028481042206460d00200641016a22012006490d02200320014f0d0120012003103c000b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200228023021062002290234210e4105210a4100211b410021030c150b20022802f88004220c20066a2d000021042002200136028481044100211b0240200441034d0d004109210a410021030c150b024002400240024020040e0400010203000b4100211b410021044100210a034002402004411f4d0d00410f210a0c170b0240024020032001460d002001417f460d072003200141016a220b4f0d01200141016a2003103c000b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200228023021062002290234210e4105210a4100211b0c180b200c20016a2d000021062002200b3602848104200641ff00712004411f7174200a72210a200441076a2104200b21012006418001710d000b4100211b20044120490d0f2006410f4d0d0f410d210a0c150b0240024020032001460d00200641026a21042001417f460d0620032004490d07200c20016a2c0000210120022004360284810402402001417f4a0d00411921030c0e0b200141c000710d010c0c0b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10332002290330210820022802382104410521030c0c0b200141807f7222014170470d0a200241e8006a200241f880046a10f30420022903702108200228026c210a024020022802684101470d00200228027821040c0d0b4101211b0c0f0b200241e8006a200241f880046a10f30420022903702108200228026c210a024020022802684101460d004102211b0c0f0b20022002280278360270200a418080807871211b200a4180807c712103200a41087621040c0c0b0240024020032001460d00200641026a210b2001417f460d062003200b490d08200c20016a2c000021042002200b36028481040240200441004e0d004119210a410021030c170b200441c000710d010c090b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a10334105210a2002290234210e20022802302106410021030c150b200441807f72220441ff017141fc01490d07024002402003200b460d00200641036a2101200b417f460d07200320014f0d0120012003103c000b200241013a00582002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241d8006a360218200241306a200241e8006a1033200228023021062002290234210e4105210a410021030c150b200c200b6a2d0000210b200220013602848104410021030240200b41014d0d00410c210a4100211b200b21040c150b2004417f7321064103211b0240200b0e020e000e0b410121030c0d0b417f20011044000b417f200141016a1044000b417f20041044000b20042003103c000b417f200b1044000b417f20011044000b200b2003103c000b4106210a410021030c0c0b410721030b200141ff0171410874200372210a0b20022004360270200a418080807871211b200a4180807c712103200a41087621040b20022008370368200229026c210e2008a721060c080b0b02400240200d2007460d002007210b0c010b200741016a22012007490d18200741017422042001200420014b1b220bad42287e220e422088a70d18200ea722044100480d180240024020070d002004102821010c010b20022802e88004200741286c2004102c21010b2001450d03200220013602e880042007210d200b21070b20022802e880042201200d41286c6a2204201c36020c20042009360208200420183602042004201a360200200441206a20083702002004411c6a200a3602002004411a6a20033a0000200441196a20063a0000200441186a201b3a0000200441146a2013360200200441106a2019360200200d41016a210d201041016a22102005470d000b2002200b3602ec80042002200d3602f080040b200228028481042002280288810446210420022902ec80042208422088210e024020022802fc8004450d0020022802f88004102a0b200ea721032008a721092004450d072003ad4220862009ad842108410321030c1d0b200441041037000b417f20031044000b0b41002103410021040b200a41ff0171200441ff0171410874722003418080fc077172201b722103200e422088a72104200ea721092019450d00201c102a0b2018450d00201a102a0b200220073602ec80042002200d3602f0800420022802e88004210b0240200d450d00200d41286c2105200b210103400240200141046a280200450d002001280200102a0b0240200141106a280200450d002001410c6a280200102a0b200141286a2101200541586a22050d000b0b2007450d01200b102a0c010b20024103410220041b3a00e88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241e880046a360218200241306a200241e8006a1033200229033021082002280238210402402003450d00200341286c21052001210303400240200341046a280200450d002003280200102a0b0240200341106a280200450d002003410c6a280200102a0b200341286a2103200541586a22050d000b0b2008422088210e41052103410021052009450d012001102a0c010b200341087621052009ad220e4220862006ad84210820022802fc8004450d0020022802f88004102a0b20004101360200200041106a2004360200200041086a200e422086200842ffffffff0f838437020020002005410874200341ff0171723602040c170b200241013a00302002410136027c2002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022802f88004210620022802fc8004210920022d00808104210320022d00818104210720022f01828104210d410521050b0b201d450d03200c102a0c030b0b2019450d00201c102a0b2003411076210d200341087621070b200741ff0171410874200341ff0171722103200d411074210d200441ff0171410874210702402017450d002001210403400240200441046a280200450d002004280200102a0b200441106a2104200a41706a220a0d000b0b2003200d722103200720057221042014450d012001102a0c010b20024103410220041b3a0030200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241306a360218200241f880046a200241e8006a103320022903f88004210820022802808104210302402005450d00200541047421052001210403400240200441046a280200450d002004280200102a0b200441106a2104200541706a22050d000b0b2008422088210e41052104410021052009450d012001102a0c010b200441087621052009ad220e4220862006ad8421082010450d00200b102a0b20004101360200200041106a2003360200200041086a200e422086200842ffffffff0f838437020020002005410874200441ff0171723602040c0d0b41002101410021040240024002400340024020094105470d00410f21070c020b0240024020032009460d00200320094b0d01200941016a2003103c000b200241013a00f88004200241fc006a41013602002002420137026c200241a4e2c5003602682002412636021c2002200241186a3602782002200241f880046a360218200241206a200241e8006a103341052107200229032021080c030b200620096a2d0000220541ff00712001411f71742004722104200141076a2101200941016a220b21092005418001710d000b20014120490d0220054110490d02410d21070b0b2008422088a72109200228022821042008a7210d0c050b024020040d00410021054101211b410021094100210d0c080b200241e8006a41004180081099051a410021054100210d4101211b410021070340024002402003200b6b200420076b22014180082001418008491b2201490d00200b20016a220c200b490d042003200c4f0d01200c2003103c000b200241013a00e880042002418c81046a4101360200200242013702fc8004200241a4e2c5003602f880042002412636021c2002200241186a36028881042002200241e880046a360218200241306a200241f880046a103320022903302208422088a72109200228023821042008a72101410521070240200d450d00201b102a0b2001210d0c060b200241e8006a2006200b6a2001109a051a02400240200d20056b2001490d00200520016a21090c010b200520016a22092005490d02200d410174220b2009200b20094b1b220b4100480d0202400240200d0d00200b1028211b0c010b201b200d200b102c211b0b201b450d04200b210d0b201b20056a200241e8006a2001109a051a20092105200c210b2004200120076a22074d0d040c000b0b1031000b200b200c1044000b200b41011037000b200241e8006a201b2009105420022802684101470d02410821070240200d450d00201b102a0b0b2009ad422086200dad84210841002101200a450d002006102a0b20004101360200200041106a2004360200200041086a200837020020002001410874200741ff0171723602040c060b201b4108762105200c210b0b2003200b490d012003200b6b2201417f4c0d020240024020010d00410121040c010b200110282204450d040b2009ad4220862108200dad210e20042006200b6a2001109a051a2001ad222042208621210240200a450d002006102a0b2008200e8421082021202084210e2005410874201b41ff0171722101410121030b200020033a000420004100360200200041056a20022f00153b0000200041186a200e370200200041146a20043602002000410c6a2008370200200041086a2001360200200041206a2002290200370200200041076a200241176a2d00003a0000200041286a200241086a290200370200200041306a200241106a2802003602000c030b200b20031044000b1036000b200141011037000b2002419081046a24000bf304010b7f230041c080016b220224002002200110f404410121030240024020022802004101470d0020002002290204370204200041013602002000410c6a2002410c6a2902003702000c010b2002280204210420024100418080011099052105410021064100210702400240024002402004450d00410021084100210641012103410021090340024002402001280204220a200128020822076b200420096b220b41808001200b41808001491b220b490d002007200b6a220c2007490d04200a200c4f0d01200c200a103c000b200541013a008f8001200541b480016a4101360200200542013702a48001200541a4e2c5003602a08001200541263602bc80012005200541b880016a3602b0800120052005418f80016a3602b880012005419080016a200541a080016a10332005418b80016a2005419880016a2802003600002005200529039080013700838001200041053a00042000200529008080013700052000410c6a2005418780016a290000370000200041013602002006450d062003102a0c060b2005200128020020076a200b109a05210a2001200c36020802400240200620086b200b490d002008200b6a21070c010b2008200b6a22072008490d052006410174220c2007200c20074b1b220c4100480d050240024020060d00200c102821030c010b20032006200c102c21030b2003450d04200c21060b200320086a200a200b109a051a200721082004200b20096a22094b0d000b0b2000200336020420004100360200200041146a2007360200200041106a41003602002000410c6a2007360200200041086a20063602000c030b2007200c1044000b200c41011037000b1031000b200241c080016a24000b8607010b7f230041d0086b22022400410021034100210402400240024002400240024002400240034002402003411f4d0d00410f21030c020b0240024020012802082205200128020c2206460d00200641016a22072006490d05200520074f0d0120072005103c000b200241013a0089082002411c6a41013602002002420137020c200241a4e2c5003602082002412636029c08200220024198086a360218200220024189086a36029808200241b8086a200241086a1033410521030c020b2001280200220820066a2d000021062001200736020c200641ff00712003411f71742004722104200341076a21032006418001710d000b20034120490d01410d210320064110490d010b2000200336020420004101360200200041086a20022902b808370200200041106a200241b8086a41086a2802003602000c060b024020040d002000428080808010370200200041086a42003702000c060b200241086a41004180081099051a41002106410021094101210a4100210b034002400240200520076b2004200b6b22034180082003418008491b2203490d00200720036a220c2007490d042005200c4f0d01200c2005103c000b200241013a00a708200241cc086a4101360200200242013702bc08200241a4e2c5003602b8082002412636029c08200220024198086a3602c8082002200241a7086a36029808200241a8086a200241b8086a103320024194086a200241b0086a280200360000200220022903a80837008c08200041053a000420002002290089083700052000410c6a20024190086a290000370000200041013602002009450d07200a102a0c070b200241086a200820076a2003109a051a2001200c36020c02400240200920066b2003490d00200620036a210c0c010b200620036a220c2006490d0520094101742207200c2007200c4b1b22074100480d050240024020090d0020071028210a0c010b200a20092007102c210a0b200a450d04200721090b200a20066a200241086a2003109a051a20042003200b6a220b4d0d05200128020c21072001280208210520012802002108200c21060c000b0b417f20071044000b2007200c1044000b200741011037000b1031000b200241086a200a200c1054024020022802084101470d0002402009450d00200a102a0b200041083a0004200041013602000c010b2000200a3602042000410c6a200c360200200041086a2009360200200041003602000b200241d0086a24000b881f03127f017e037f23004180026b220524000240024020014115490d00410121064101210702400240034020012108200021092006200771410173210a024002400240034002400240024002402004450d00024020064101710d002000200110fe042004417f6a21040b2001410276220741036c210b2007410174210c4100210d20014132490d03200741016a210e200020074103746a220f28020020002007417f6a220d4103746a2210280200201041046a2802002210200f41046a280200220f200f20104b1b109c052211450d01417f410120114100481b21100c020b2000200110ff040c0b0b417f200f201047200f2010491b21100b2007200d2010417f4622101b210f024002402000200e4103746a22112802002000200d200720101b22124103746a2207280200200741046a2802002207201141046a280200220d200d20074b1b109c052211450d00417f410120114100481b21070c010b417f200d200747200d2007491b21070b4102410120101b20102007417f4622071b210d024002402000200e201220071b22114103746a22102802002000200f4103746a2207280200200741046a2802002207201041046a2802002210201020074b1b109c05220e450d00417f4101200e4100481b21100c010b417f201020074720102007491b21100b200c4101722107200d2010417f4622126a2113024002402000200c4103746a220d2802002000200c417f6a22104103746a220e280200200e41046a280200220e200d41046a280200220d200d200e4b1b109c052214450d00417f410120144100481b210e0c010b417f200d200e47200d200e491b210e0b200c2010200e417f46220e1b210d2013200e6a211302400240200020074103746a221428020020002010200c200e1b220e4103746a220c280200200c41046a280200220c201441046a28020022102010200c4b1b109c052214450d00417f410120144100481b210c0c010b417f2010200c472010200c491b210c0b2013200c417f46220c6a21100240024020002007200e200c1b22134103746a220c2802002000200d4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b109c05220e450d00417f4101200e4100481b210c0c010b417f200c200747200c2007491b210c0b200b41016a21072010200c417f4622146a2115024002402000200b4103746a220e2802002000200b417f6a220c4103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b109c052216450d00417f410120164100481b21100c010b417f200e201047200e2010491b21100b200b200c2010417f4622101b210e201520106a211502400240200020074103746a22162802002000200c200b20101b22104103746a220c280200200c41046a280200220c201641046a280200220b200b200c4b1b109c052216450d00417f410120164100481b210c0c010b417f200b200c47200b200c491b210c0b2015200c417f46220c6a211502400240200020072010200c1b220b4103746a220c2802002000200e4103746a2207280200200741046a2802002207200c41046a280200220c200c20074b1b109c052210450d00417f410120104100481b21100c010b417f200c200747200c2007491b21100b200f201120121b2107200d201320141b210c200e200b2010417f4622101b210b201520106a210d0b024002402000200c4103746a220e280200200020074103746a2210280200201041046a2802002210200e41046a280200220e200e20104b1b109c05220f450d00417f4101200f4100481b21100c010b417f200e201047200e2010491b21100b200c20072010417f46220e1b2110200d200e6a210d024002402000200b4103746a220f28020020002007200c200e1b220e4103746a2207280200200741046a2802002207200f41046a280200220c200c20074b1b109c05220f450d00417f4101200f4100481b21070c010b417f200c200747200c2007491b21070b200d2007417f46220c6a2107024002400240024002402000200b200e200c1b220d4103746a220b280200200020104103746a220c280200200c41046a280200220c200b41046a280200220b200b200c4b1b109c05220e450d00200e4100480d010c020b200b200c4f0d010b200741016a2207410c490d0102402001410176220b450d00200020014103746a41786a21072000210c0340200c2902002117200c200729020037020020072017370200200c41086a210c200741786a2107200b417f6a220b0d000b0b20012010417f736a2110410121070c020b200d21100b20074521070b0240200745200a724101710d00200020011080050d090b2003450d010240201020014f0d00024002402003280200200020104103746a2207280200200741046a280200220c200341046a280200220b200b200c4b1b109c05220e450d00200e41004e0d010c050b200b200c490d040b200029020021172000200729020037020020072017370200200041786a21122000410c6a2113200041086a2114200028020421072000280200210d4100210b2001210e0340024002400240200b200e417f6a22114f0d002013200b4103746a210c034002400240200d200c417c6a280200200c28020022102007200720104b1b109c05220f450d00200f4100480d030c010b20072010490d020b200c41086a210c2011200b41016a220b470d000c020b0b0240200b20114f0d002012200e4103746a210c2011210e034002400240200d200c280200200c41046a28020022102007200720104b1b109c05220f450d00200f4100480d010c050b200720104f0d040b200c41786a210c200b200e417f6a220e490d000b0b200b21110b200020073602042000200d36020002402001201141016a2207490d00200020074103746a2100200120076b220141154f0d040c0b0b200720011044000b2014200b4103746a221029020021172010200c290200370200200c2017370200200b41016a210b0c000b0b0b41f483c600201020011034000b20080d0141bc83c600410041001034000b20002109200121080b201020084f0d02200929020021172009200920104103746a2207290200370200200720173702002009280204210c2009280200211241002100410021184100211902402008417f6a220e450d002009410c6a21074100211803400240024002402007417c6a2802002012200c2007280200220b200b200c4b1b109c052210450d00201041004e0d010c020b200b200c490d010b200e21190240200e20184d0d00200920084103746a41786a2107200e211903400240024020072802002012200c200741046a280200220b200b200c4b1b109c052210450d00201041004e0d010c030b200b200c490d020b200741786a21072019417f6a221920184b0d000b0b0240024020192018490d00200e2019490d010c040b201820191044000b2019200e103c000b200741086a2107200e201841016a2218470d000b200e2118200e21190b200941086a220720194103746a210e41800121144100211141002110410021014180012106200720184103746a221a210d03400240200e200d6b22074187104b220a0d002007410376220741807f6a200720112000492001201049220b72220f1b21070240200f450d0020062007200b1b210620072014200b1b21140c010b2007200741017622066b21140b024020012010470d00024020060d002005221021010c010b4100210720052110200d210b0340201020073a0000200741016a210702400240200b2802002012200c200b41046a280200220f200f200c4b1b109c052201450d00417f410120014100481b210f0c010b417f200f200c47200f200c491b210f0b200b41086a210b2010200f417f476a211020062007470d000b200521010b024020112000470d00024020140d0020054180016a220021110c010b200e41786a21074100210b20054180016a210003402000200b3a0000200b41016a210b0240024020072802002012200c200741046a280200220f200f200c4b1b109c052211450d00417f410120114100481b210f0c010b417f200f200c47200f200c491b210f0b200741786a21072000200f417f466a21002014200b470d000b20054180016a21110b0240200020116b2207201020016b220b200b20074b1b2213450d00200d20012d00004103746a22072802042115200728020021162007200e20112d0000417f734103746a290200370200024020134101460d00410021070340200e201120076a220b2d0000417f734103746a200d200120076a41016a220f2d00004103746a290200370200200d200f2d00004103746a200e200b41016a2d0000417f734103746a290200370200200741026a210b200741016a220f2107200b2013490d000b2011200f6a21112001200f6a21010b200e20112d0000417f734103746a2207201536020420072016360200201141016a2111200141016a21010b200e20144103746b200e20112000461b210e200d20064103746a200d20012010461b210d200a0d000b02400240200120104f0d00200e21070340200d2010417f6a22102d00004103746a220b2902002117200b200741786a22072902003702002007201737020020012010490d000c020b0b200d2107201120004f0d000340200729020021172007200e2000417f6a22002d0000417f734103746a220b290200370200200b2017370200200741086a210720112000490d000b0b2009200c36020420092012360200024020082007201a6b41037620186a22014d0d00200929020021172009200920014103746a220729020037020020072017370200200820016b220c450d02200c20012001200c4b1b210b20084103762110200741086a2100024002402001200c417f6a220c490d002000200c20022007200410fd04200921000c010b2009200120022003200410fd0420072103200c21010b200b20104f2106201920184d2107200141154f0d010c040b0b41cc83c600200120081034000b41dc83c6001032000b41cc83c600201020081034000b20014102490d00200041786a211341002114410121120340201241037421072012417f6a2110201241016a2112024002400240200020076a22072802002211200020104103746a220f280200200f41046a280200220c200741046a280200220b200b200c4b1b109c05220e450d00200e4100480d010c020b200b200c4f0d010b2007200f29020037020002402010450d002014210c20132107024003400240024020112007280200200741046a280200220e200b200b200e4b1b109c05220d450d00200d4100480d010c030b200b200e4f0d030b20002010417f6a22104103746a210f200741086a2007290200370200200741786a2107200c41016a220e200c49210d200e210c200d450d000b0b200741086a210f0b200f200b360204200f20113602000b2014417f6a2114201341086a211320122001470d000b0b20054180026a24000bf50202057f017e02400240024020014108490d00200141017641feffffff07712202417f6a220320014f0d022001410d74200173220441117620047322044105742004732205417f2001417f6a677622067122044100200120042001491b6b220420014f0d01200020034103746a220329020021072003200020044103746a220429020037020020042007370200024020022001490d00200221030c030b2005410d7420057322044111762004732204410574200473220520067122044100200120042001491b6b220420014f0d01200020024103746a220329020021072003200020044103746a2204290200370200200420073702002002410172220320014f0d022005410d742005732204411176200473220441057420047320067122044100200120042001491b6b220420014f0d01200020034103746a220129020021072001200020044103746a2200290200370200200020073702000b0f0b41cc83c600200420011034000b41bc83c600200320011034000bb20102037f017e024020014101762202450d00200020012002417f6a1081052002417e6a210203402002417f460d012000200120021081052002417f6a21020c000b0b0240024020014102490d00200141037420006a41786a21022001210303402003417f6a220420014f0d02200029020021052000200229020037020020022005370200200020044100108105200241786a210220042103200441014b0d000b0b0f0b41cc83c6002003417f6a20011034000b9a06050a7f017e017f017e037f200041686a2102200041786a2103200141324921044101210541002106024003400240024020052001490d00410021070c010b200320054103746a210841012107034002400240200841086a22092802002008280200200841046a280200220a2008410c6a28020022082008200a4b1b109c05220b450d00200b4100480d030c010b2008200a490d020b4101210a200541016a220520014921072009210820012005470d000c030b0b2005200146210a20040d0120052001460d01024002400240024002402005417f6a220820014f0d002007410171450d01200020084103746a2208290200210c200820002005410374220d6a220b290200220e370200200b200c37020020054102490d0402400240200ea7220f20002005417e6a220a4103746a2210280200201041046a2802002207200841046a2802002209200920074b1b109c052211450d0020114100480d010c060b200920074f0d050b20082010290200370200200a450d032002200d6a2108034002400240200f2008280200200841046a28020022072009200920074b1b109c05220d450d00200d4100480d010c050b200920074f0d050b2000200a417f6a220a4103746a2110200841086a2008290200370200200841786a2108200a0d000c030b0b41bc83c600200820011034000b41cc83c600200520011034000b200841086a21100b201020093602042010200f3602000b200641016a21060240200120056b220d4102490d0002400240200b280208200b280200220f200b41046a2802002209200b410c6a2802002208200820094b1b109c05220a450d00200a4100480d010c020b200820094f0d010b200b41086a2111200b200b2902083702000240200d4103490d004103210a41022107034002400240200b20074103746a2208280200200f2009200841046a2802002207200720094b1b109c052210450d00201041004e0d030c010b200720094f0d020b200841786a20082902003702000240200a200d4f0d00200a2107200a41016a210a200821110c010b0b200821110b2011200f360200201120093602040b20064105470d000b4100210a0b200a0bb60202057f017e03402002410174220341017221040240024002400240200341026a220320014f0d00200420014f0d0102400240200020044103746a2205280200200020034103746a2206280200200641046a2802002206200541046a2802002205200520064b1b109c052207450d00417f410120074100481b21060c010b417f200520064720052006491b21060b200320042006417f461b21040b0240200420014f0d00200220014f0d020240200020024103746a2202280200200020044103746a2203280200200341046a2802002206200241046a2802002205200520064b1b109c052207450d00200741004e0d010c040b20052006490d030b0f0b41c885c600200420011034000b41d885c600200220011034000b200229020021082002200329020037020020032008370200200421020c000b0b1500200120002802002200280200200028020810450bf30201037f230041c0006b22022400200141086a2802002103200128020421042002200128020022013602100240024002402001418080044b0d0002402004450d0020022003360214200120034b0d022003418080044d0d002002413c6a41013602002002420237022c200241f8a7c6003602282002410136021c200241d4a7c6003602182002200241186a3602382002200241286a10330c030b200241003602000c020b2002413c6a41013602002002420237022c200241d8a7c6003602282002410136021c200241d4a7c6003602182002200241186a3602382002200241286a10330c010b200241246a41013602002002413c6a41023602002002420237022c200241e8a7c6003602282002410136021c2002200241186a3602382002200241106a3602202002200241146a3602182002200241286a10330b024002402002280200450d0020002002290300370200200041086a200241086a2802003602000c010b200041003602000b200241c0006a24000bf80501037f230041f0006b2204240002400240024002400240024020012802084102460d00412e10282201450d01200041013a0000200141266a41002900eca946370000200141206a41002900e6a946370000200141186a41002900dea946370000200141106a41002900d6a946370000200141086a41002900cea946370000200141002900c6a946370000200041086a42ae808080e005370200200041046a20013602000c050b02400240024002400240200128020022052d0000416e6a2201411e4b0d004100210620010e1f03000000000000000000000000000000000000000000000000000008040102030b412010282201450d05200041013a0000200141186a410029008caa46370000200141106a4100290084aa46370000200141086a41002900fca946370000200141002900f4a946370000200041086a42a08080808004370200200041046a20013602000c080b410221060c060b410321060c050b20042005280204220136020c0240024020012003490d004194aac6002105200441e8006a2103200441d0006a2101200441c0006a21020c010b200220014101746a22012d0001450d0441a4aac6002105200441386a2103200441206a2101200441106a21020b20034101360204200141146a410136020020012003360210200142023702042001200536020020032004410c6a360200200220011033200041013a00002000410c6a200241086a280200360200200041046a20022902003702000c050b410121060c030b412e41011037000b412041011037000b20012d000021060b0240200541106a2d00004106470d00200041003a0000200020063a00010c010b0240412910282201450d00200041013a0000200141286a41002d00dcaa463a0000200141206a41002900d4aa46370000200141186a41002900ccaa46370000200141106a41002900c4aa46370000200141086a41002900bcaa46370000200141002900b4aa46370000200041086a42a98080809005370200200041046a20013602000c010b412941011037000b200441f0006a24000b86c30103087f027e017f230041f0006b220324000240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024002400240024020022d00000eac0100e1010102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80018101820183018401850186018701880189018a018b018c018d018e018f0190019101920193019401950196019701980199019a019b019c019d019e019f01a001a101a201a301a401a501a601a701a801a901aa01000b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450dab012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490de0012007410174220a2009200a20094b1b22094100480de0010240024020070d002009102821070c010b200128021820072009102c21070b2007450dad01200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060ce0010b0240200141306a2802002204200141346a22052802004f0d002002310001210b200141206a350200210c024020042001412c6a280200470d00200441016a22022004490ddf01200441017422052002200520024b1b220241ffffffff01712002470ddf01200241037422054100480ddf010240024020040d002005102821040c010b200128022820044103742005102c21040b2004450dad01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200b422886200c84370200200141306a2201200128020041016a3602000ce0010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddf012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddf012000200329023c370204200020013602000ce0010b0240200141306a2802002204200141346a22052802004f0d002002310001210b200141206a350200210c024020042001412c6a280200470d00200441016a22022004490dde01200441017422052002200520024b1b220241ffffffff01712002470dde01200241037422054100480dde010240024020040d002005102821040c010b200128022820044103742005102c21040b2004450dad01200120043602282001412c6a2002360200200141306a28020021040b200128022820044103746a200b422886200c8442808080803084370200200141306a2201200128020041016a3602000cdf010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450dde012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dde012000200329023c370204200020013602000cdf010b2002310001210b200341d8006a200141186a200141286a22044100108905024020032d00584101470d002000200329025c370200200041086a200341e4006a2802003602000cdf010b0240200141306a2802002202200141346a22052802004f0d00200141206a350200210c024020022001412c6a280200470d00200241016a22052002490ddd01200241017422062005200620054b1b220541ffffffff01712005470ddd01200541037422064100480ddd010240024020020d002006102821020c010b200428020020024103742006102c21020b2002450dad01200120023602282001412c6a2005360200200141306a28020021020b200128022820024103746a200b422886200c8442808080801084370200200141306a2201200128020041016a3602000cde010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddd012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddd012000200329023c370204200020013602000cde010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450dac012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c2003200136025841e0a2c6004134200341d8006a41d0a2c6001038000b02400240200141286a220228020020044103746a22042d00044101470d002004310005210b200341d8006a200141186a2002108a052003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cdf010b411a10282201450dad01200141186a41002f00aca3463b0000200141106a41002900a4a346370000200141086a410029009ca34637000020014100290094a3463700002000429a808080a003370204200020013602000cde010b0240200141306a2802002204200141346a22052802004f0d00200141206a350200210c024020042001412c6a280200470d00200441016a22052004490ddc01200441017422062005200620054b1b220541ffffffff01712005470ddc01200541037422064100480ddc010240024020040d002006102821020c010b200228020020044103742006102c21020b2002450daf01200120023602282001412c6a2005360200200141306a28020021040b200128022820044103746a200b422886200c8442808080802084370200200141306a2201200128020041016a3602000cdd010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddc012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddc012000200329023c370204200020013602000cdd010b02400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450dae012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c2003200136025841e0a2c6004134200341d8006a41d0a2c6001038000b200141286a220628020020044103746a22042d00052105024020042d00044101470d00200541ff01714104470daf010b0240024020024101460d00200341d8006a200141186a22022006108a052003280258450d0120002003290358370200200041086a200341d8006a41086a2802003602000cde010b20012d003822024104460ddb01200341d8006a200141186a2205200620021089050240024020032d00584101460d000240200141206a2802002204200141246a22072802004f0d00024020042001411c6a280200470d00200441016a22072004490dde01200441017422082007200820074b1b22074100480dde010240024020040d002007102821040c010b200528020020042007102c21040b2004450db401200120043602182001411c6a2007360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cde010b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200736020020032003360268200341106a200341d8006a103320032802102204450ddd012003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450ddd01200329023c210b0c010b200328025c2202450ddc01200341e0006a290300210b0b2000200b370204200020023602000cdd010b200541ff01714104460ddb010240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490ddb01200441017422072006200720064b1b22064100480ddb010240024020040d002006102821020c010b200228020020042006102c21020b2002450db201200120023602182001411c6a2006360200200141206a28020021040b200128021820046a20053a0000200141206a2201200128020041016a3602000cdc010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102202450ddb012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddb012000200329023c370204200020013602000cdc010b2003200241046a280200220236024802400240200141306a280200220420024d0d0020042002417f736a22022004490d0141f2adc600411d1050000b200341ec006a220241023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821042003200329023c37021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a10332003280214450dd1012003280210102a0cd1010b200141286a220428020020024103746a22022d00044103460dd10120022d0005220241ff01714104460dd101200341d8006a200141186a220520042002108905024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490ddb01200441017422072006200720064b1b22064100480ddb010240024020040d002006102821040c010b200528020020042006102c21040b2004450db301200120043602182001411c6a2006360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cd3010b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102204450dd2012003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a10332003280214450dd1012003280210102a0cd1010b200328025c2202450dd101200341e0006a290300210b0cd2010b200241046a2802002102200341d8006a200141186a2206200141286a220541001089050240024020032d00584101470d00200341e0006a290300210b200328025c22010d010cdb010b200141306a28020021042003200236024802400240200420024d0d0020042002417f736a22022004490d0141f2adc600411d1050000b200341ec006a220141023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320043602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821022003200329023c37021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b200329023c210b200328023822010d010cdb010b200528020020024103746a22022d00044103460dda0120022d0005220241ff01714104460dda01200341d8006a200620052002108905024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490ddb01200441017422072005200720054b1b22054100480ddb010240024020040d002005102821040c010b200628020020042005102c21040b2004450db401200120043602182001411c6a2005360200200141206a28020021040b200128021820046a20023a0000200141206a2201200128020041016a3602000cdc010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450ddb012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450ddb01200329023c210b0c010b200328025c2201450dda01200341e0006a290300210b0b2000200b370204200020013602000cda010b200241046a280200220228020421062002280200210420032002280208220536024802400240200141306a280200220220054d0d0020022005417f736a22052002490d0141f2adc600411d1050000b200341ec006a220441023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821022003200329023c37021420032002360210200441013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b2003200329023c370204200320032802383602000ccd010b410421090240200141286a220d280200220720054103746a22052d00044103460d0020052d000521090b200320093a00302006450dc801200941ff0171220a4104460dc701200641027421060340200320042802002205360248200220054d0dca0120022005417f736a220520024f0dce01200720054103746a22052d00044103460dcb0120052d000522084104460dcb01200a2008470dcb01200441046a21042006417c6a22060d000cc9010b0b20012d003822024104460dc501200341d8006a200141186a2205200141286a20021089050240024020032d00584101460d000240200141206a2802002204200141246a22062802004f0d00024020042001411c6a280200470d00200441016a22062004490dd901200441017422072006200720064b1b22064100480dd9010240024020040d002006102821040c010b200528020020042006102c21040b2004450db301200120043602182001411c6a2006360200200141206a28020021040b200128021820046a20023a0000200141206a2202200228020041016a3602000cc8010b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102204450dc7012003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450dc701200329023c210b0c010b200328025c2202450dc601200341e0006a290300210b0b2000200b370204200020023602000cd8010b200128020021042003200241046a2802002202360254024002400240200441386a28020020024b0d00200341ec006a41013602002003420237025c200341e4abc600360258200341013602342003200341306a3602682003200341d4006a360230200341386a200341d8006a1033200341186a200329023c370300200341013602102003200328023822043602140c010b2003200428023020024102746a2802002202360200024002402004412c6a28020020024b0d0041012105200341ec006a41013602002003420237025c20034188acc6003602582003410136024c2003200341c8006a36026820032003360248200341386a200341d8006a1033200341186a200329023c220b370300200b422088a7210720032802382104200ba721020c010b2003411c6a200428022420024104746a22042d000d22073a0000200341186a2004280208220236020020042802002104410021050b20032005360210200320043602142005450d010b200341186a21010cc3010b02402002450d002004417f6a2104200141286a2105200141186a21060340200341d8006a20062005200420026a2d0000108905024020032d00584101470d00200341e0006a2101200328025c21040cc5010b2002417f6a22020d000b0b200741ff01714104460dd6010240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490dd601200241017422052004200520044b1b22044100480dd6010240024020020d002004102821020c010b200128021820022004102c21020b2002450db101200120023602182001411c6a2004360200200141206a28020021020b200128021820026a20073a0000200141206a2201200128020041016a3602000cd7010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450dd6012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382204450dd601200329023c210b0cc3010b200241046a28020021062001280200210220034100360238024002400240200241146a2802000d00200341d8006a41146a41013602002003420237025c200341c4abc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10330c010b200341d8006a200141186a2204200141286a22054100108905024020032d00584101470d00200341e0006a290300210b0cc2010b20012802002207412c6a280200210220032006360238200220064b0d01200341ec006a41013602002003420237025c20034188acc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a10330b2003290214210b200328021022010dc1010cd6010b200728022420064104746a22062d000d2107024020062802082202450d002006280200417f6a21060340200341d8006a20042005200620026a2d0000108905024020032d00584101470d00200341e0006a290300210b0cc2010b2002417f6a22020d000b0b200741ff01714104460dd5010240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dd501200241017422062005200620054b1b22054100480dd5010240024020020d002005102821020c010b200428020020022005102c21020b2002450db101200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20073a0000200141206a2201200128020041016a3602000cd6010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450dd5012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd501200329023c210b0cc0010b200341d8006a200141186a200141286a410410890520032d00584101470dd401200328025c2201450dd4012000200341e0006a290300370204200020013602000cd5010b200341d8006a200141186a2204200141286a22054100108905200341d8006a21020240024020032d00584101460d00200341d8006a200420054104108905200341d8006a210220032d00584101460d00200341d8006a2004200520032d00592206108905200341d8006a210220032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490dd501200241017422072005200720054b1b22054100480dd5010240024020020d002005102821020c010b200428020020022005102c21020b2002450db201200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20063a0000200141206a2201200128020041016a3602000cd6010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450dd5012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd501200329023c210b0c010b200241046a2802002201450dd401200241086a290200210b0b2000200b370204200020013602000cd4010b200341d8006a200141046a200241046a280200108b050240024020032d00584101460d000240200141206a2802002202200141246a22042802004f0d0020032d00592104024020022001411c6a280200470d00200241016a22052002490dd401200241017422062005200620054b1b22054100480dd4010240024020020d002005102821020c010b200128021820022005102c21020b2002450db201200120023602182001411c6a2005360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cd5010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450dd4012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd401200329023c210b0c010b200328025c2201450dd301200341e0006a290300210b0b2000200b370204200020013602000cd3010b2003200241046a2802002202360200200341d8006a200141046a2002108b05024020032d00584101470d002003200328025c22013602382003200341e0006a290300220b37023c0cbb010b200320032d005922023a0030200341d8006a200141186a200141286a4104108905024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380cba010b200320032d005922013a004820014104460dd101200241ff01712001460dd101200341106a41146a41303602002003411c6a4127360200200341d8006a41146a41033602002003420337025c200341d0a3c600360258200341013602142003200341106a3602682003200341c8006a3602202003200341306a36021820032003360210200341386a200341d8006a10330cb9010b200341d8006a200141046a200241046a280200108b050240024020032d00584101460d00200341d8006a200141186a2205200141286a20032d00592204108905024020032d00584101460d000240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490dd301200241017422072006200720064b1b22064100480dd3010240024020020d002006102821020c010b200528020020022006102c21020b2002450db201200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2201200128020041016a3602000cd4010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102202450dd3012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd301200329023c210b0c020b200328025c2201450dd201200341e0006a290300210b0c010b200328025c2201450dd101200341e0006a290300210b0b2000200b370204200020013602000cd1010b200128020021042003200241046a280200220236023802400240200441206a28020020024d0d000240200141206a2802002205200141246a22062802004f0d00200428021820024101746a2d00002102024020052001411c6a280200470d00200541016a22042005490dd101200541017422062004200620044b1b22044100480dd1010240024020050d002004102821050c010b200128021820052004102c21050b2005450db101200120053602182001411c6a2004360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000cd2010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200636020020032003360268200341106a200341d8006a103320032802102202450dd1012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450dd101200329023c210b0c010b200341ec006a41013602002003420237025c200341a8acc6003602582003410136024c2003200341c8006a3602682003200341386a360248200341106a200341d8006a103320032802102201450dd0012003290214210b0b2000200b370204200020013602000cd0010b2003200241046a28020022023602282001280200210420032002360254024002400240200441206a28020020024b0d00200341ec006a41013602002003420237025c200341a8acc6003602582003410136024c2003200341c8006a3602682003200341d4006a360248200341106a200341d8006a10330c010b200428021820024101746a22022d00010d01200341ec006a41013602002003420237025c200341b8acc60036025820034101360204200320033602682003200341d4006a360200200341106a200341d8006a10330b2003280210210120032003290214220b37023c200320013602380cb6010b200320022d000022023a002f200341d8006a200141186a200141286a4104108905024020032d00584101470d00200341c0006a200341e4006a2802003602002003200329025c3703380cb5010b200320032d005922013a00002001200241ff0171460dce0120014104460dce01200341106a41146a41303602002003411c6a4130360200200341d8006a41146a41033602002003420337025c200341e8a3c600360258200341013602142003200341106a3602682003200336022020032003412f6a3602182003200341286a360210200341386a200341d8006a10330cb4010b200341d8006a2001200241046a28020041044100108d052003280258450dcd0120002003290358370200200041086a200341d8006a41086a2802003602000cce010b200341d8006a2001200241046a28020041084101108d052003280258450dcc0120002003290358370200200041086a200341d8006a41086a2802003602000ccd010b200341d8006a2001200241046a28020041044102108d052003280258450dcb0120002003290358370200200041086a200341d8006a41086a2802003602000ccc010b200341d8006a2001200241046a28020041084103108d052003280258450dca0120002003290358370200200041086a200341d8006a41086a2802003602000ccb010b200341d8006a2001200241046a28020041014100108d052003280258450dc90120002003290358370200200041086a200341d8006a41086a2802003602000cca010b200341d8006a2001200241046a28020041014100108d052003280258450dc80120002003290358370200200041086a200341d8006a41086a2802003602000cc9010b200341d8006a2001200241046a28020041024100108d052003280258450dc70120002003290358370200200041086a200341d8006a41086a2802003602000cc8010b200341d8006a2001200241046a28020041024100108d052003280258450dc60120002003290358370200200041086a200341d8006a41086a2802003602000cc7010b200341d8006a2001200241046a28020041014101108d052003280258450dc50120002003290358370200200041086a200341d8006a41086a2802003602000cc6010b200341d8006a2001200241046a28020041014101108d052003280258450dc40120002003290358370200200041086a200341d8006a41086a2802003602000cc5010b200341d8006a2001200241046a28020041024101108d052003280258450dc30120002003290358370200200041086a200341d8006a41086a2802003602000cc4010b200341d8006a2001200241046a28020041024101108d052003280258450dc20120002003290358370200200041086a200341d8006a41086a2802003602000cc3010b200341d8006a2001200241046a28020041044101108d052003280258450dc10120002003290358370200200041086a200341d8006a41086a2802003602000cc2010b200341d8006a2001200241046a28020041044101108d052003280258450dc00120002003290358370200200041086a200341d8006a41086a2802003602000cc1010b200341d8006a2001200241046a28020041044100108e052003280258450dbf0120002003290358370200200041086a200341d8006a41086a2802003602000cc0010b200341d8006a2001200241046a28020041084101108e052003280258450dbe0120002003290358370200200041086a200341d8006a41086a2802003602000cbf010b200341d8006a2001200241046a28020041044102108e052003280258450dbd0120002003290358370200200041086a200341d8006a41086a2802003602000cbe010b200341d8006a2001200241046a28020041084103108e052003280258450dbc0120002003290358370200200041086a200341d8006a41086a2802003602000cbd010b200341d8006a2001200241046a28020041014100108e052003280258450dbb0120002003290358370200200041086a200341d8006a41086a2802003602000cbc010b200341d8006a2001200241046a28020041024100108e052003280258450dba0120002003290358370200200041086a200341d8006a41086a2802003602000cbb010b200341d8006a2001200241046a28020041014101108e052003280258450db90120002003290358370200200041086a200341d8006a41086a2802003602000cba010b200341d8006a2001200241046a28020041024101108e052003280258450db80120002003290358370200200041086a200341d8006a41086a2802003602000cb9010b200341d8006a2001200241046a28020041044101108e052003280258450db70120002003290358370200200041086a200341d8006a41086a2802003602000cb8010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034194abc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103320032802102202450d002003290214210b0c010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db701200241017422052004200520044b1b22044100480db7010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9801200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb8010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db7012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450db701200329023c210b0b2000200b370204200020023602000cb7010b20012802002102200341003602380240024020022802080d00200341ec006a41013602002003420237025c20034194abc60036025820034101360204200320033602682003200341386a360200200341106a200341d8006a103320032802102202450d002003290214210b0c010b200341d8006a200141186a2204200141286a4100108905024020032d00584101460d000240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490db701200241017422062005200620054b1b22054100480db7010240024020020d002005102821020c010b200428020020022005102c21020b2002450d9901200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb8010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102202450db7012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450db701200329023c210b0c010b200328025c2202450db601200341e0006a290300210b0b2000200b370204200020023602000cb6010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db401200241017422052004200520044b1b22044100480db4010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000cb5010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db4012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db4012000200329023c370204200020013602000cb5010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db301200241017422052004200520044b1b22044100480db3010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41013a0000200141206a2201200128020041016a3602000cb4010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db3012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db3012000200329023c370204200020013602000cb4010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db201200241017422052004200520044b1b22044100480db2010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41023a0000200141206a2201200128020041016a3602000cb3010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db2012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db2012000200329023c370204200020013602000cb3010b0240200141206a2802002202200141246a22042802004f0d00024020022001411c6a280200470d00200241016a22042002490db101200241017422052004200520044b1b22044100480db1010240024020020d002004102821020c010b200128021820022004102c21020b2002450d9701200120023602182001411c6a2004360200200141206a28020021020b200128021820026a41033a0000200141206a2201200128020041016a3602000cb2010b200341ec006a220141013602002003420137025c20034190aec600360258200341013602042003200436020020032003360268200341106a200341d8006a103320032802102202450db1012003200329021437021420032002360210200141013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382201450db1012000200329023c370204200020013602000cb2010b200341d8006a20014100108f052003280258450db00120002003290358370200200041086a200341d8006a41086a2802003602000cb1010b200341d8006a200141001090052003280258450daf0120002003290358370200200041086a200341d8006a41086a2802003602000cb0010b200341d8006a200141001090052003280258450dae0120002003290358370200200041086a200341d8006a41086a2802003602000caf010b200341d8006a200141001090052003280258450dad0120002003290358370200200041086a200341d8006a41086a2802003602000cae010b200341d8006a200141001090052003280258450dac0120002003290358370200200041086a200341d8006a41086a2802003602000cad010b200341d8006a200141001090052003280258450dab0120002003290358370200200041086a200341d8006a41086a2802003602000cac010b200341d8006a200141001090052003280258450daa0120002003290358370200200041086a200341d8006a41086a2802003602000cab010b200341d8006a200141001090052003280258450da90120002003290358370200200041086a200341d8006a41086a2802003602000caa010b200341d8006a200141001090052003280258450da80120002003290358370200200041086a200341d8006a41086a2802003602000ca9010b200341d8006a200141001090052003280258450da70120002003290358370200200041086a200341d8006a41086a2802003602000ca8010b200341d8006a200141001090052003280258450da60120002003290358370200200041086a200341d8006a41086a2802003602000ca7010b200341d8006a20014101108f052003280258450da50120002003290358370200200041086a200341d8006a41086a2802003602000ca6010b200341d8006a200141011090052003280258450da40120002003290358370200200041086a200341d8006a41086a2802003602000ca5010b200341d8006a200141011090052003280258450da30120002003290358370200200041086a200341d8006a41086a2802003602000ca4010b200341d8006a200141011090052003280258450da20120002003290358370200200041086a200341d8006a41086a2802003602000ca3010b200341d8006a200141011090052003280258450da10120002003290358370200200041086a200341d8006a41086a2802003602000ca2010b200341d8006a200141011090052003280258450da00120002003290358370200200041086a200341d8006a41086a2802003602000ca1010b200341d8006a200141011090052003280258450d9f0120002003290358370200200041086a200341d8006a41086a2802003602000ca0010b200341d8006a200141011090052003280258450d9e0120002003290358370200200041086a200341d8006a41086a2802003602000c9f010b200341d8006a200141011090052003280258450d9d0120002003290358370200200041086a200341d8006a41086a2802003602000c9e010b200341d8006a200141011090052003280258450d9c0120002003290358370200200041086a200341d8006a41086a2802003602000c9d010b200341d8006a200141011090052003280258450d9b0120002003290358370200200041086a200341d8006a41086a2802003602000c9c010b200341d8006a200141021090052003280258450d9a0120002003290358370200200041086a200341d8006a41086a2802003602000c9b010b200341d8006a200141021090052003280258450d990120002003290358370200200041086a200341d8006a41086a2802003602000c9a010b200341d8006a200141021090052003280258450d980120002003290358370200200041086a200341d8006a41086a2802003602000c99010b200341d8006a200141021090052003280258450d970120002003290358370200200041086a200341d8006a41086a2802003602000c98010b200341d8006a200141021090052003280258450d960120002003290358370200200041086a200341d8006a41086a2802003602000c97010b200341d8006a200141021090052003280258450d950120002003290358370200200041086a200341d8006a41086a2802003602000c96010b200341d8006a200141031090052003280258450d940120002003290358370200200041086a200341d8006a41086a2802003602000c95010b200341d8006a200141031090052003280258450d930120002003290358370200200041086a200341d8006a41086a2802003602000c94010b200341d8006a200141031090052003280258450d920120002003290358370200200041086a200341d8006a41086a2802003602000c93010b200341d8006a200141031090052003280258450d910120002003290358370200200041086a200341d8006a41086a2802003602000c92010b200341d8006a200141031090052003280258450d900120002003290358370200200041086a200341d8006a41086a2802003602000c91010b200341d8006a200141031090052003280258450d8f0120002003290358370200200041086a200341d8006a41086a2802003602000c90010b200341d8006a200141001091052003280258450d8e0120002003290358370200200041086a200341d8006a41086a2802003602000c8f010b200341d8006a200141001091052003280258450d8d0120002003290358370200200041086a200341d8006a41086a2802003602000c8e010b200341d8006a200141001091052003280258450d8c0120002003290358370200200041086a200341d8006a41086a2802003602000c8d010b200341d8006a200141001092052003280258450d8b0120002003290358370200200041086a200341d8006a41086a2802003602000c8c010b200341d8006a200141001092052003280258450d8a0120002003290358370200200041086a200341d8006a41086a2802003602000c8b010b200341d8006a200141001092052003280258450d890120002003290358370200200041086a200341d8006a41086a2802003602000c8a010b200341d8006a200141001092052003280258450d880120002003290358370200200041086a200341d8006a41086a2802003602000c89010b200341d8006a200141001092052003280258450d870120002003290358370200200041086a200341d8006a41086a2802003602000c88010b200341d8006a200141001092052003280258450d860120002003290358370200200041086a200341d8006a41086a2802003602000c87010b200341d8006a200141001092052003280258450d850120002003290358370200200041086a200341d8006a41086a2802003602000c86010b200341d8006a200141001092052003280258450d840120002003290358370200200041086a200341d8006a41086a2802003602000c85010b200341d8006a200141001092052003280258450d830120002003290358370200200041086a200341d8006a41086a2802003602000c84010b200341d8006a200141001092052003280258450d820120002003290358370200200041086a200341d8006a41086a2802003602000c83010b200341d8006a200141001092052003280258450d810120002003290358370200200041086a200341d8006a41086a2802003602000c82010b200341d8006a200141001092052003280258450d800120002003290358370200200041086a200341d8006a41086a2802003602000c81010b200341d8006a200141001092052003280258450d7f20002003290358370200200041086a200341d8006a41086a2802003602000c80010b200341d8006a200141001092052003280258450d7e20002003290358370200200041086a200341d8006a41086a2802003602000c7f0b200341d8006a200141001092052003280258450d7d20002003290358370200200041086a200341d8006a41086a2802003602000c7e0b200341d8006a200141011091052003280258450d7c20002003290358370200200041086a200341d8006a41086a2802003602000c7d0b200341d8006a200141011091052003280258450d7b20002003290358370200200041086a200341d8006a41086a2802003602000c7c0b200341d8006a200141011091052003280258450d7a20002003290358370200200041086a200341d8006a41086a2802003602000c7b0b200341d8006a200141011092052003280258450d7920002003290358370200200041086a200341d8006a41086a2802003602000c7a0b200341d8006a200141011092052003280258450d7820002003290358370200200041086a200341d8006a41086a2802003602000c790b200341d8006a200141011092052003280258450d7720002003290358370200200041086a200341d8006a41086a2802003602000c780b200341d8006a200141011092052003280258450d7620002003290358370200200041086a200341d8006a41086a2802003602000c770b200341d8006a200141011092052003280258450d7520002003290358370200200041086a200341d8006a41086a2802003602000c760b200341d8006a200141011092052003280258450d7420002003290358370200200041086a200341d8006a41086a2802003602000c750b200341d8006a200141011092052003280258450d7320002003290358370200200041086a200341d8006a41086a2802003602000c740b200341d8006a200141011092052003280258450d7220002003290358370200200041086a200341d8006a41086a2802003602000c730b200341d8006a200141011092052003280258450d7120002003290358370200200041086a200341d8006a41086a2802003602000c720b200341d8006a200141011092052003280258450d7020002003290358370200200041086a200341d8006a41086a2802003602000c710b200341d8006a200141011092052003280258450d6f20002003290358370200200041086a200341d8006a41086a2802003602000c700b200341d8006a200141011092052003280258450d6e20002003290358370200200041086a200341d8006a41086a2802003602000c6f0b200341d8006a200141011092052003280258450d6d20002003290358370200200041086a200341d8006a41086a2802003602000c6e0b200341d8006a200141011092052003280258450d6c20002003290358370200200041086a200341d8006a41086a2802003602000c6d0b200341d8006a200141011092052003280258450d6b20002003290358370200200041086a200341d8006a41086a2802003602000c6c0b200341d8006a200141021091052003280258450d6a20002003290358370200200041086a200341d8006a41086a2802003602000c6b0b200341d8006a200141021091052003280258450d6920002003290358370200200041086a200341d8006a41086a2802003602000c6a0b200341d8006a200141021091052003280258450d6820002003290358370200200041086a200341d8006a41086a2802003602000c690b200341d8006a200141021091052003280258450d6720002003290358370200200041086a200341d8006a41086a2802003602000c680b200341d8006a200141021091052003280258450d6620002003290358370200200041086a200341d8006a41086a2802003602000c670b200341d8006a200141021091052003280258450d6520002003290358370200200041086a200341d8006a41086a2802003602000c660b200341d8006a200141021091052003280258450d6420002003290358370200200041086a200341d8006a41086a2802003602000c650b200341d8006a200141021092052003280258450d6320002003290358370200200041086a200341d8006a41086a2802003602000c640b200341d8006a200141021092052003280258450d6220002003290358370200200041086a200341d8006a41086a2802003602000c630b200341d8006a200141021092052003280258450d6120002003290358370200200041086a200341d8006a41086a2802003602000c620b200341d8006a200141021092052003280258450d6020002003290358370200200041086a200341d8006a41086a2802003602000c610b200341d8006a200141021092052003280258450d5f20002003290358370200200041086a200341d8006a41086a2802003602000c600b200341d8006a200141021092052003280258450d5e20002003290358370200200041086a200341d8006a41086a2802003602000c5f0b200341d8006a200141021092052003280258450d5d20002003290358370200200041086a200341d8006a41086a2802003602000c5e0b200341d8006a200141031091052003280258450d5c20002003290358370200200041086a200341d8006a41086a2802003602000c5d0b200341d8006a200141031091052003280258450d5b20002003290358370200200041086a200341d8006a41086a2802003602000c5c0b200341d8006a200141031091052003280258450d5a20002003290358370200200041086a200341d8006a41086a2802003602000c5b0b200341d8006a200141031091052003280258450d5920002003290358370200200041086a200341d8006a41086a2802003602000c5a0b200341d8006a200141031091052003280258450d5820002003290358370200200041086a200341d8006a41086a2802003602000c590b200341d8006a200141031091052003280258450d5720002003290358370200200041086a200341d8006a41086a2802003602000c580b200341d8006a200141031091052003280258450d5620002003290358370200200041086a200341d8006a41086a2802003602000c570b200341d8006a200141031092052003280258450d5520002003290358370200200041086a200341d8006a41086a2802003602000c560b200341d8006a200141031092052003280258450d5420002003290358370200200041086a200341d8006a41086a2802003602000c550b200341d8006a200141031092052003280258450d5320002003290358370200200041086a200341d8006a41086a2802003602000c540b200341d8006a200141031092052003280258450d5220002003290358370200200041086a200341d8006a41086a2802003602000c530b200341d8006a200141031092052003280258450d5120002003290358370200200041086a200341d8006a41086a2802003602000c520b200341d8006a200141031092052003280258450d5020002003290358370200200041086a200341d8006a41086a2802003602000c510b200341d8006a200141031092052003280258450d4f20002003290358370200200041086a200341d8006a41086a2802003602000c500b200341d8006a2001410141001093052003280258450d4e20002003290358370200200041086a200341d8006a41086a2802003602000c4f0b200341d8006a2001410241001093052003280258450d4d20002003290358370200200041086a200341d8006a41086a2802003602000c4e0b200341d8006a2001410241001093052003280258450d4c20002003290358370200200041086a200341d8006a41086a2802003602000c4d0b200341d8006a2001410341001093052003280258450d4b20002003290358370200200041086a200341d8006a41086a2802003602000c4c0b200341d8006a2001410341001093052003280258450d4a20002003290358370200200041086a200341d8006a41086a2802003602000c4b0b200341d8006a2001410041011093052003280258450d4920002003290358370200200041086a200341d8006a41086a2802003602000c4a0b200341d8006a2001410041011093052003280258450d4820002003290358370200200041086a200341d8006a41086a2802003602000c490b200341d8006a2001410241011093052003280258450d4720002003290358370200200041086a200341d8006a41086a2802003602000c480b200341d8006a2001410241011093052003280258450d4620002003290358370200200041086a200341d8006a41086a2802003602000c470b200341d8006a2001410341011093052003280258450d4520002003290358370200200041086a200341d8006a41086a2802003602000c460b200341d8006a2001410341011093052003280258450d4420002003290358370200200041086a200341d8006a41086a2802003602000c450b200341d8006a2001410041021093052003280258450d4320002003290358370200200041086a200341d8006a41086a2802003602000c440b200341d8006a2001410041021093052003280258450d4220002003290358370200200041086a200341d8006a41086a2802003602000c430b200341d8006a2001410141021093052003280258450d4120002003290358370200200041086a200341d8006a41086a2802003602000c420b200341d8006a2001410141021093052003280258450d4020002003290358370200200041086a200341d8006a41086a2802003602000c410b200341d8006a2001410341021093052003280258450d3f20002003290358370200200041086a200341d8006a41086a2802003602000c400b200341d8006a2001410041031093052003280258450d3e20002003290358370200200041086a200341d8006a41086a2802003602000c3f0b200341d8006a2001410041031093052003280258450d3d20002003290358370200200041086a200341d8006a41086a2802003602000c3e0b200341d8006a2001410141031093052003280258450d3c20002003290358370200200041086a200341d8006a41086a2802003602000c3d0b200341d8006a2001410141031093052003280258450d3b20002003290358370200200041086a200341d8006a41086a2802003602000c3c0b200341d8006a2001410241031093052003280258450d3a20002003290358370200200041086a200341d8006a41086a2802003602000c3b0b200341d8006a2001410241001093052003280258450d3920002003290358370200200041086a200341d8006a41086a2802003602000c3a0b200341d8006a2001410341011093052003280258450d3820002003290358370200200041086a200341d8006a41086a2802003602000c390b200341d8006a2001410041021093052003280258450d3720002003290358370200200041086a200341d8006a41086a2802003602000c380b200341d8006a20014101410310930520032802580d1b0c360b411841011037000b200941011037000b200541041037000b200541041037000b200641041037000b411841011037000b411a41011037000b200641041037000b411841011037000b200341ec006a41013602002003420237025c200341b0a3c6003602582003413136023c2003200441056a3602382003200341386a360268200341106a200341d8006a1033200041086a200341106a41086a280200360200200020032903103702000c2d0b200741011037000b200641011037000b200641011037000b200541011037000b200641011037000b200441011037000b200541011037000b200541011037000b200541011037000b200641011037000b200441011037000b200441011037000b200541011037000b200441011037000b200441011037000b200441011037000b200441011037000b20002003290358370200200041086a200341d8006a41086a2802003602000c1b0b200329023c210b200328023821010b2001450d182000200b370204200020013602000c190b200329023c210b200328023821010b2001450d162000200b370204200020013602000c170b200328025c2201450d150b2000200b370204200020013602000c150b2004450d132001290200210b0b2000200b370204200020043602000c130b02400240024002400240200141306a2802002202417f6a220420024f0d00200420024b0d00200128022820044103746a22052802002204200141206a220628020022024b0d01200421010c020b411810282200450d022003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d132007410174220a2009200a20094b1b22094100480d130240024020070d002009102821070c010b200128021820072009102c21070b2007450d03200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c130b411841011037000b200941011037000b200641027421060340200320042802002205360248200220054d0d0220022005417f736a220520024f0d060240200720054103746a22052d00044103460d0020052d00054104470d040b200441046a21042006417c6a22060d000b410421090b200341d8006a200141186a2202200d410010890520032d00584101470d02200341086a200341e4006a2802003602002003200329025c3703000c030b200341ec006a220441023602002003411c6a41013602002003420237025c200341b0adc60036025820034101360214200320023602002003200341106a360268200320033602182003200341c8006a360210200341386a200341d8006a1033200328023821022003200329023c37021420032002360210200441013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b2003200329023c370204200320032802383602000c020b2003411c6a4131360200200341ec006a41023602002003420237025c200341c0a3c6003602582003200541056a360218200341313602142003200341106a3602682003200341306a3602102003200341d8006a10330c010b0240200941ff01714104460d00200341d8006a2002200d200910890502400240024020032d00584101460d000240200141206a2802002204200141246a22052802004f0d00024020042001411c6a280200470d00200441016a22052004490d10200441017422062005200620054b1b22054100480d100240024020040d002005102821020c010b200228020020042005102c21020b2002450d04200120023602182001411c6a2005360200200141206a28020021040b200128021820046a20093a0000200141206a2202200228020041016a3602000c040b200341ec006a220241013602002003420137025c20034190aec600360258200341013602042003200536020020032003360268200341106a200341d8006a103320032802102204450d032003200329021437021420032004360210200241013602002003420137025c200341c4a7c60036025820034128360204200320033602682003200341106a360200200341386a200341d8006a103302402003280214450d002003280210102a0b20032802382202450d03200329023c210b0c010b200328025c2202450d02200341e0006a290300210b0b2003200b370204200320023602000c020b200541011037000b200341003602000b024020032802002202450d0020002003290204370204200020023602000c0d0b0240024002400240200141306a2802002202417f6a220420024f0d00200420024d0d010b411810282200450d012003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b02400240200128022820044103746a22052802002204200141206a220628020022024b0d00200421010c010b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d0d2007410174220a2009200a20094b1b22094100480d0d0240024020070d002009102821070c010b200128021820072009102c21070b2007450d03200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c0d0b411841011037000b200941011037000b41f2adc600411d1050000b20032802382202450d00200329023c210b0c010b200141306a2802002202417f6a220420024f0d01200420024b0d01200128022820044103746a22052802002204200141206a220628020022024b0d02200421010c030b2000200b370204200020023602000c080b411810282200450d022003421837025c20032000360258200341d8006a4100411810870520032003280260220041186a3602602000200328025822016a41184196adc60041181088052003200329025c37025c200320013602584193a2c600413b200341d8006a41d0a2c6001038000b024002402001411c6a280200220720026b200420026b2208490d0020012802182107200221010c010b200220086a22092002490d042007410174220a2009200a20094b1b22094100480d040240024020070d002009102821070c010b200128021820072009102c21070b2007450d03200120073602182001411c6a2009360200200141206a28020021010b200720016a21090240024020084102490d002009410420042002417f736a22021099051a2007200220016a22016a21090c010b2008450d010b200941043a0000200141016a21010b20062001360200200541013a00060c040b411841011037000b200941011037000b1031000b200341d8006a200141186a2006108a052003280258450d0020002003290358370200200041086a200341d8006a41086a2802003602000c010b200041003602000b200341f0006a24000b6401017f230041206b2202240020024132360204200220003602002001411c6a2802002100200128021821012002411c6a41013602002002420137020c200241b0aec6003602082002200236021820012000200241086a10352101200241206a240020010b810101017f024002400240200041046a280200220320016b20024f0d00200120026a22022001490d02200341017422012002200120024b1b22014100480d020240024020030d002001102821020c010b200028020020032001102c21020b2002450d0120002002360200200041046a20013602000b0f0b200141011037000b1031000bd90101017f230041e0006b22042400200420013602082004200336020c024020012003470d00200020022001109a051a200441e0006a24000f0b200441286a41146a4108360200200441346a4125360200200441106a41146a410336020020044203370214200441c8afc6003602102004412536022c2004200441086a36024020042004410c6a360244200442043703582004420137024c2004419cb0c6003602482004200441286a3602202004200441c8006a3602382004200441c4006a3602302004200441c0006a360228200441106a41d8b0c600103e000bb90601037f230041d0006b22042400200420033a000f0240024002400240024020022802082205417f6a220620054f0d00200620054d0d010b411810282202450d012004421837023420042002360230200441306a4100411810870520042004280238220241186a3602382002200428023022056a41184196adc6004118108805200420042902343702342004200536023041e0a2c6004134200441306a41d0a2c6001038000b200141086a2802002105200228020020064103746a2206280200210202400240024020062d0006450d0020052002460d010b024002400240200520024d0d00200141086a2005417f6a2202360200200128020020026a2d00002205417c6a220241014b0d02024020020e020400040b4118102822020d01411841011037000b412b10282202450d05200041013a0000200241276a41002800fea646360000200241206a41002900f7a646370000200241186a41002900efa646370000200241106a41002900e7a646370000200241086a41002900dfa646370000200241002900d7a646370000200041086a42ab808080b005370200200041046a20023602000c060b200241106a41002900a6ad46370000200241086a410029009ead4637000020024100290096ad4637000020044298808080800337022420042002360220200441c4006a410136020020044201370234200441c4a7c6003602302004412836024c2004200441c8006a3602402004200441206a360248200441106a200441306a103302402004280224450d002004280220102a0b200041013a0000200041046a20042903103702002000410c6a200441106a41086a2802003602000c050b0240200341ff017122024104460d0020052002470d020b200041003a0000200020053a00010c040b20004180083b01000c030b200420053a0048200441c4006a4102360200200441206a410c6a41303602002004420237023420044184a7c600360230200441303602242004200441206a3602402004200441c8006a36022820042004410f6a360220200441106a200441306a10332000410c6a200441186a280200360200200041046a2004290310370200200041013a00000c020b411841011037000b412b41011037000b200441d0006a24000bbd0502047f017e230041d0006b22032400024002400240024002400240200241086a2802002204417f6a220520044f0d00200520044d0d010b411810282202450d01200241106a41002900a6ad46370000200241086a410029009ead4637000020024100290096ad4637000020034298808080800337022420032002360220200341cc006a41013602002003420137023c200341c4a7c600360238200341283602142003200341106a3602482003200341206a3602102000200341386a10332003280224450d042003280220102a0c040b0240024002402002280200220620054103746a2d000522054104460d00200341386a200120022005108905024020032d00384101470d002000200329023c370200200041086a200341c4006a2802003602000c070b200241086a2802002204450d01200228020021060b200241086a2004417f6a2202360200200620024103746a290200220742808080808080c0ff0083428080808080808001520d010b411810282202450d02200241106a41002900a6ad46370000200241086a410029009ead4637000020024100290096ad4637000020034298808080800337022420032002360220200341cc006a41013602002003420137023c200341c4a7c600360238200341283602142003200341106a3602482003200341206a3602102000200341386a10332003280224450d042003280220102a0c040b200141086a28020021022003200737030820022007a7470d02200041003602000c030b411841011037000b411841011037000b200341cc006a41023602002003412c6a41013602002003420237023c200341a4a6c60036023820034101360224200320023602342003200341206a3602482003200341086a3602282003200341346a360220200341106a200341386a1033200041086a200341106a41086a280200360200200020032903103702000b200341d0006a24000bac0301057f230041c0006b2203240020032002360200024002402001280204220420024b0d002001280208417c6a21052001410c6a280200410374210102400340024020010d00200320043602042003412c6a4102360200200341306a410c6a41013602002003420337021c200341f0aec600360218200341013602342003200341306a3602282003200341046a36023820032003360230200341086a200341186a10332000410c6a200341106a280200360200200041046a2003290308370200200041013a00000c040b02402004200541046a2802006a220620044f0d00412010282204450d02200041013a0000200441186a41002900e8ae46370000200441106a41002900e0ae46370000200441086a41002900d8ae46370000200441002900d0ae46370000200041086a42a08080808004370200200041046a20043602000c040b200141786a2101200541086a2105200420024b21072006210420070d0020062104200620024d0d000b20052d00002104200041003a0000200020043a00010c020b412041011037000b200041003a00002000200128020020026a2d00003a00010b200341c0006a24000bbd0201037f230041106b220224000240024020002d00004104470d00200220012802184181a5c60041032001411c6a28020028020c11000022003a000820022001360200200241003a0009200241003602040c010b200220012802184184a5c60041082001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a418ca5c600105d210120022d0008210020022802042203450d00200041ff0171210441012100024020040d00024020034101470d0020012d0009450d00200128020022042d00004104710d0041012100200428021841f4afc00041012004411c6a28020028020c1100000d010b2001280200220028021841c8a4c60041012000411c6a28020028020c11000021000b200120003a00080b200241106a2400200041ff01714100470bfe0501037f230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200541386a200141186a2203200141286a410010890520052d00384101470d012000200529023c370200200041086a200541c4006a2802003602000c020b200541cc006a41023602002005411c6a41013602002005420337023c20054180a4c600360238200541013602142005200541106a36024820052005410c6a3602182005200541086a360210200541206a200541386a1033200041086a200541206a41086a280200360200200020052903203702000c010b2001280200210220054100360220024020022802080d00200541cc006a41013602002005420237023c20054194abc600360238200541013602342005200541306a3602482005200541206a360230200541106a200541386a103320052802102202450d0020002005290214370204200020023602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d03200241017422072006200720064b1b22064100480d030240024020020d002006102821020c010b200328020020022006102c21020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20043a0000200141206a2202200228020041016a3602000c030b200541cc006a220241013602002005420137023c20054190aec60036023820054101360234200520063602302005200541306a360248200541106a200541386a103320052802102201450d022005200529021437021420052001360210200241013602002005420137023c200541c4a7c600360238200541283602342005200541306a3602482005200541106a360230200541206a200541386a103302402005280214450d002005280210102a0b20052802202202450d0220002005290224370204200020023602000c030b200641011037000b1031000b200041003602000b200541d0006a24000bae0301017f230041d0006b22052400200520023602082005200336020c024002400240417f41012002411f71742002411f4b1b20034b0d00200128020021022005410036023420022802080d01200541cc006a41013602002005420237023c20054194abc600360238200541013602142005200541106a3602482005200541346a360210200541206a200541386a103320052802202202450d0120002005290224370204200020023602000c020b200541cc006a41023602002005412c6a41013602002005420337023c20054180a4c600360238200541013602242005200541206a36024820052005410c6a3602282005200541086a360220200541106a200541386a1033200041086a200541106a41086a280200360200200020052903103702000c010b200541386a200141186a2202200141286a22032004108905024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200541386a200220034100108905024020052d00384101470d002000200529023c370200200041086a200541c4006a2802003602000c010b200041003602000b200541d0006a24000be50301047f230041c0006b22032400200341286a200141186a2204200141286a20021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d03200241017422062005200620054b1b22054100480d030240024020020d002005102821020c010b200428020020022005102c21020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320053602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200541011037000b1031000b200041003602000b200341c0006a24000b9e0401047f230041c0006b22032400200341286a200141186a2204200141286a220520021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a200420052002108905024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002202200141246a22052802004f0d00024020022001411c6a280200470d00200241016a22052002490d03200241017422062005200620054b1b22054100480d030240024020020d002005102821020c010b200428020020022005102c21020b2002450d02200120023602182001411c6a2005360200200141206a28020021020b200128021820026a41003a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320053602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200541011037000b1031000b200041003602000b200341c0006a24000be50301057f230041c0006b22032400200341286a200141186a2204200141286a20021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d03200541017422072006200720064b1b22064100480d030240024020050d002006102821050c010b200428020020052006102c21050b2005450d02200120053602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320063602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200641011037000b1031000b200041003602000b200341c0006a24000b9e0401057f230041c0006b22032400200341286a200141186a2204200141286a220520021089050240024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b200341286a200420052002108905024020032d00284101470d002000200329022c370200200041086a200341346a2802003602000c010b0240024002400240200141206a2802002205200141246a22062802004f0d00024020052001411c6a280200470d00200541016a22062005490d03200541017422072006200720064b1b22064100480d030240024020050d002006102821040c010b200428020020052006102c21040b2004450d02200120043602182001411c6a2006360200200141206a28020021050b200128021820056a20023a0000200141206a2201200128020041016a3602000c030b2003413c6a220141013602002003420137022c20034190aec60036022820034101360214200320063602102003200341106a360238200341186a200341286a103320032802182202450d022003200329021c37021c20032002360218200141013602002003420137022c200341c4a7c600360228200341283602142003200341106a3602382003200341186a3602102003200341286a10330240200328021c450d002003280218102a0b20032802002201450d0220002003290204370204200020013602000c030b200641011037000b1031000b200041003602000b200341c0006a24000be50301047f230041c0006b22042400200441286a200141186a2205200141286a20021089050240024020042d00284101470d002000200429022c370200200041086a200441346a2802003602000c010b0240024002400240200141206a2802002202200141246a22062802004f0d00024020022001411c6a280200470d00200241016a22062002490d03200241017422072006200720064b1b22064100480d030240024020020d002006102821020c010b200528020020022006102c21020b2002450d02200120023602182001411c6a2006360200200141206a28020021020b200128021820026a20033a0000200141206a2201200128020041016a3602000c030b2004413c6a220141013602002004420137022c20044190aec60036022820044101360214200420063602102004200441106a360238200441186a200441286a103320042802182202450d022004200429021c37021c20042002360218200141013602002004420137022c200441c4a7c600360228200441283602142004200441106a3602382004200441186a3602102004200441286a10330240200428021c450d002004280218102a0b20042802002201450d0220002004290204370204200020013602000c030b200641011037000b1031000b200041003602000b200441c0006a24000b02000b17000240200041046a280200450d002000280200102a0b0b15002000280200220028020020002802082001105f0b100020012000280200200028020810450bfb0101027f230041106b220224002002200128021841b8aec60041052001411c6a28020028020c1100003a000820022001360200200241003a0009200241003602042002200036020c20022002410c6a41c0aec600105d1a20022d00082101024020022802042203450d00200141ff0171210041012101024020000d00024020034101470d0020022d000941ff0171450d00200228020022002d00004104710d0041012101200028021841f4afc00041012000411c6a28020028020c1100000d010b2002280200220128021841c8a4c60041012001411c6a28020028020c11000021010b200220013a00080b200241106a2400200141ff01714100470b2c01017f02402002450d00200021030340200320013a0000200341016a21032002417f6a22020d000b0b20000b3601017f02402002450d00200021030340200320012d00003a0000200341016a2103200141016a21012002417f6a22020d000b0b20000b7101017f0240024020012000490d002002450d01200021030340200320012d00003a0000200141016a2101200341016a21032002417f6a22020d000c020b0b2002450d002001417f6a21012000417f6a21030340200320026a200120026a2d00003a00002002417f6a22020d000b0b20000b4a01037f4100210302402002450d000240034020002d0000220420012d00002205470d01200141016a2101200041016a21002002417f6a2202450d020c000b0b200420056b21030b20030b5701017e02400240200341c000710d002003450d012001410020036b413f71ad8820022003413f71ad220486842102200120048621010c010b20012003413f71ad862102420021010b20002001370300200020023703080b5701017e02400240200341c000710d002003450d0120012003413f71ad2204882002410020036b413f71ad86842101200220048821020c010b20022003413f71ad882101420021020b20002001370300200020023703080b7501027e200020034220882205200142208822067e200320027e7c200420017e7c200342ffffffff0f832203200142ffffffff0f8322017e2204422088200320067e7c22034220887c200342ffffffff0f83200520017e7c22034220887c37030820002003422086200442ffffffff0f83843703000b3e01017f230041106b2205240020052001200220032004410010a205200529030021012000200541086a29030037030820002001370300200541106a24000b4c01017f230041206b22052400200542003703182005420037031020052001200220032004200541106a10a205200529031021012000200529031837030820002001370300200541206a24000be20502037f067e230041306b2206240002400240024002400240024002400240024002402002500d002003500d012004500d02200479a7200279a76b2207413f4b0d0341ff0020076b2108200741016a21070c080b02402004500d0020050d040c060b024002402005450d0020034200510d0620054200370308200520012003823703000c010b20034200510d050b200120038021010c060b2004500d030240024002402001500d0020047b4201510d01200479a7200279a76b2207413e4b0d0241ff0020076b2108200741016a21070c090b02402005450d0020054200370300200520022004823703080b200220048021010c070b02402005450d002005200137030020052004427f7c2002833703080b200220047a423f838821010c060b2005450d040c020b024020037b4201510d0041bf7f200379a7200279a76b22076b2108200741c1006a21070c060b02402005450d002005420037030820052003427f7c2001833703000b20034201510d06200641206a2001200220037aa7109e05200641286a2903002102200629032021010c060b2005450d020b2005200137030020052002370308420021010c020b00000b420021010b420021020c010b200620012002200841ff0071109d05200641106a20012002200741ff0071109e05200641086a2903002102200641106a41086a2903002109200629030021012006290310210a0240024020070d004200210b4200210c0c010b4200210c4200210d03402009420186200a423f8884220b200b427f8520047c200a4201862002423f8884220a427f85220b20037c200b54ad7c423f87220b2004837d200a200b200383220e54ad7d2109200a200e7d210a420020024201862001423f8884842102200d2001420186842101200b420183220b210d2007417f6a22070d000b0b02402005450d002005200a370300200520093703080b200c20024201862001423f8884842102200b20014201868421010b2000200137030020002002370308200641306a24000b0b9bb1060200418080c0000b80b1061800100011000000187f11001700000009030000050000006361706163697479206f766572666c6f77000000a00010004600000063010000130000003300000004000000040000003400000035000000360000006120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f72003700000000000000010000003800000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f666d742f6d6f642e72730101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020202020202020202020202020202020202020202020202020202020202030303030303030303030303030303030404040404000000000000000000000000000802100020000000280210001200000037000000000000000100000039000000696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e646578206973203030303130323033303430353036303730383039313031313132313331343135313631373138313932303231323232333234323532363237323832393330333133323333333433353336333733383339343034313432343334343435343634373438343935303531353235333534353535363537353835393630363136323633363436353636363736383639373037313732373337343735373637373738373938303831383238333834383538363837383838393930393139323933393439353936393739383939000024031000060000002a031000220000006898110018000000170a000005000000696e64657820206f7574206f662072616e676520666f7220736c696365206f66206c656e677468206c03100016000000820310000d00000068981100180000001d0a000005000000736c69636520696e64657820737461727473206174202062757420656e6473206174206030785b2e2e2e5d00560410000b00000002171000160000008f0310000100000040041000160000000308000009000000e01610000e000000ee16100004000000f2161000100000008f0310000100000040041000160000000708000005000000a01610002b000000cb161000150000007a01000015000000560410000b000000610410002600000087041000080000008f041000060000008f03100001000000400410001600000014080000050000007372632f6c6962636f72652f7374722f6d6f642e72736279746520696e64657820206973206e6f742061206368617220626f756e646172793b20697420697320696e7369646520202862797465732029206f662060000000d604100002000000c0041000160000006204000011000000c00410001600000056040000280000007372632f6c6962636f72652f666d742f6d6f642e72732e2e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000f8030000000000000000000000000000000000000000000000000000000000000000feffffffffbfb6000000000000000000ff070000000000f8ffff0000010000000000000000000000c09f9f3d0000000002000000ffffff0700000000000000000000c0ff01000000000000f80f20801010004a000000d012100000020000d01410003a00000000010203040506070809080a0b0c0d0e0f10111213140215161718191a1b1c1d1e1f2002020202020202020202210202020202020202020202020202222324252602270228020202292a2b022c2d2e2f300202310202023202020202020202023302023402020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023502360237020202020202020238023902020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202023a3b3c020202023d02023e3f4041424344454602020247020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202024802020202020202020202024902020202023b020001020202020302020202040205060202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020207020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200010305050606030706080809110a1c0b190c140d120e0d0f0410031212130916011705180219031a071c021d011f1620032b042c022d0b2e01300331023201a702a902aa04ab08fa02fb05fd04fe03ff09ad78798b8da23057588b8c901c1ddd0e0f4b4cfbfc2e2f3f5c5d5fb5e2848d8e9192a9b1babbc5c6c9cadee4e5ff00041112293134373a3b3d494a5d848e92a9b1b4babbc6cacecfe4e500040d0e11122931343a3b4546494a5e646584919b9dc9cecf0d112945495764658d91a9b4babbc5c9dfe4e5f0040d1145496465808184b2bcbebfd5d7f0f183858ba4a6bebfc5c7cecfdadb4898bdcdc6cecf494e4f57595e5f898e8fb1b6b7bfc1c6c7d71116175b5cf6f7feff800d6d71dedf0e0f1f6e6f1c1d5f7d7eaeafbbbcfa16171e1f46474e4f585a5c5e7e7fb5c5d4d5dcf0f1f572738f747596972f5f262e2fa7afb7bfc7cfd7df9a409798308f1fc0c1ceff4e4f5a5b07080f10272feeef6e6f373d3f42459091feff536775c8c9d0d1d8d9e7feff00205f2282df048244081b04061181ac0e80ab351e1580e003190801042f043404070301070607110a500f1207550802041c0a090308030703020303030c0405030b06010e15053a0311070605100757070207150d500443032d03010411060f0c3a041d255f206d046a2580c80582b0031a0682fd035907150b1709140c140c6a060a061a0659072b05460a2c040c040103310b2c041a060b0380ac060a061f414c042d0374083c030f033c0738082b0582ff1118082f112d032010210f808c048297190b158894052f053b07020e180980b030740c80d61a0c0580ff0580b605240c9bc60ad23010848d033709815c1480b80880c73035040a06380846080c06740b1e035a0459098083181c0a16094808808a06aba40c170431a10481da26070c050580a511816d1078282a064c04808d0480be031b030f0d0006010103010402080809020a050b02100111041205131114021502170219041c051d0824016a036b02bc02d102d40cd509d602d702da01e005e102e802ee20f004f906fa020c273b3e4e4f8f9e9e9f060709363d3e56f3d0d104141836375657bd35cecfe01287898e9e040d0e11122931343a4546494a4e4f64655a5cb6b71b1ca8a9d8d909379091a8070a3b3e66698f926f5feeef5a629a9b2728559da0a1a3a4a7a8adbabcc4060b0c151d3a3f4551a6a7cccda007191a22253e3fc5c604202325262833383a484a4c50535556585a5c5e606365666b73787d7f8aa4aaafb0c0d00c72a3a4cbcc6e6f5e227b0503042d036504012f2e80821d03310f1c0424091e052b0544040e2a80aa06240424042808340b018090813709160a088098390363080930160521031b05014038044b052f040a070907402027040c0936033a051a07040c07504937330d33072e080a81261f808128082a808617094e041e0f430e19070a0647092709750b3f412a063b050a0651060105100305808b602048080a80a65e22450b0a060d1339070a362c041080c03c64530c0180a0451b4808531d398107460a1d03474937030e080a0639070a81361980c7320d839b66750b80c48abc842f8fd18247a1b98239072a040260260a460a28051382b05b654b0439071140041c97f80882f3a50d811f3103110408818c89046b050d03090710936080f60a73086e1746809a140c570919808781470385420f1585502b80d52d031a040281703a0501850080d7294c040a04028311444c3d80c23c06010455051b3402810e2c04640c560a0d035d033d391d0d2c040907020e06809a83d60a0d030b05740c59070c140c0438080a0628081e527703310380a60c14040305030d06856a000000601010002000000027000000190000006010100020000000280000002000000060101000200000002a0000001900000060101000200000002b0000001800000060101000200000002c0000002000000000000000000000007372632f6c6962636f72652f756e69636f64652f626f6f6c5f747269652e72730000c0fbef3e00000000000e0000000000000000000000000000f8fffbffffff0700000000000014fe21fe000c00000002000000000000501e2080000c00004006000000000000108639020000002300be2100000c0000fc02000000000000d01e20c0000c0000000400000000000040012080000000000011000000000000c0c13d60000c0000000200000000000090443060000c00000003000000000000581e2080000c00000000845c8000000000000000000000f207807f000000000000000000000000f21f003f000000000000000000030000a002000000000000fe7fdfe0fffeffffff1f40000000000000000000000000e0fd66000000c301001e006420002000000000000000e00000000000001c0000001c0000000c0000000c00000000000000b03f40fe0f200000000000380000000000006000000000020000000000008701040e00008009000000000000407fe51ff89f000000000000ff7f0f0000000000f0170400000000f80f00030000003c3b00000000000040a303000000000000f0cf000000f7fffd211003fffffffffffffffb00100000000000000000ffffffff01000000000000800300000000000000008000000000ffffffff0000000000fc00000000000600000000000000000080f73f000000c0000000000000000000000300440800006000000030000000ffff038000000000c03f000080ff030000000000070000000000c833000000002000000000000000007e660008100000000000100000000000009dc1020000000030400000000000202100000000004000000000ffff0000ffff00000000000000000001000000020003000000000000000000000000000000000000000000000000000004000005000000000000000006000000000000000007000008090a000b0c0d0e0f000010111200001314151600001718191a1b001c0000001d0000000000001e1f202100000000002200230024252600000000270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002829000000000000000000000000000000002a2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000002d2e00002f0000000000000000000000000000000000000000000000000000000000003031320000000000000000000000000000000000000000003300000029000000000000340000000000000000000000000000000000000000000000350036000000000000000000000000000000000000000000000000000037380000383838390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000001000000000000000000c0076ef0000000000087000000006000000000000000f0000000c0ff01000000000002000000000000ff7f0000000000008003000000000078060700000080ef1f000000000000000800030000000000c07f001e000000000000000000000080d34000000080f8070000030000000000005801008000c01f1f0000000000000000ff5c00004000000000000000000000f9a50d000000000000000000000000803cb00100003000000000000000000000f8a70100000000000000000000000028bf00000000e0bc0f0000000000000080ff060000f00c01000000fe0700000000f87980007e0e0000000000fc7f03000000000000000000007fbf0000fcfffffc6d000000000000007eb4bf000000000000000000a3000000000000000000000018000000000000001f000000000000007f0000800000000000000080070000000000000000600000000000000000a0c307f8e70f0000003c00001c00000000000000ffffffffffff7ff8ffffffffff1f2000100000f8feff00007ffffff9db0700000000000000f0000000007f0000000000f00700000000000000000000ffffffffffffffffffffffffffffffffffff000063616c6c656420604f7074696f6e3a3a756e77726170282960206f6e206120604e6f6e65602076616c75657372632f6c6962636f72652f6f7074696f6e2e7273626567696e203c3d20656e642028203c3d2029207768656e20736c6963696e672060206973206f7574206f6620626f756e6473206f66206066616c736574727565426f72726f774572726f72426f72726f774d75744572726f7270616e69636b6564206174200000711710000100000072171000030000003897110000000000701710000100000070171000010000003a27272c20000000cb16100015000000a60400000500000098171000150000008d040000050000007372632f6c6962636f72652f726573756c742e72735b5d0a3a0000000c000000040000003b0000003c0000003d0000002c0a2c203300000004000000040000003e0000003f0000004000000020202020207b20207b0a207d7d28280a2c0000003300000004000000040000004100000033000000040000000400000042000000557466384572726f7276616c69645f75705f746f6572726f725f6c656e00000033000000040000000400000043000000370000000000000001000000440000004500000046000000370000000000000001000000440000004500000046000000901810001e0000005074110013000000b903000009000000617373657274696f6e206661696c65643a20696e646578203c3d206c656e0000c81810001d0000005074110013000000e103000009000000617373657274696f6e206661696c65643a20696e646578203c206c656e0000000019100043000000f60a00003000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962616c6c6f632f7665632e7273000019100043000000020b00002c0000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d7363616c652d636f6465632d312e302e352f7372632f636f6d706163742e72736865616420697320736574207768656e20666972737420656c656d656e7420697320696e7365727465640a090909090909616e6420756e736574207768656e206c61737420656c656d656e742069732072656d6f7665643b0a0909090909096966206865616420697320536f6d65207468656e20697420706f696e747320746f206578697374696e67206b65793b2071656470726576696f75732f6e657874206f6e6c7920636f6e7461696e206578697374696e6720656e74697265733b0a090909090909776520656e756d6572617465207573696e67206e6578743b20656e747279206578697374733b207165646f766572666c6f77206d756c7469706c79696e6720676173206c696d69742062792070726963650000003700000000000000010000004700000048000000490000004a0000004b0000004c0000000c1b1000330000003f1b10004b000000f600000005000000636f6e74726163742073756273797374656d20726573756c74696e6720696e20706f73697469766520696d62616c616e6365212f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f6163636f756e745f64622e72734f6666656e636573205265706f7274730000c01b100019000000e01b100048000000bb0100002d000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f6f70732f61726974682e7273616c726561647920626f72726f776564616c7265616479206d757461626c7920626f72726f7765643700000000000000010000004d0000003700000000000000010000004e000000387d110028000000881c10004300000055000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f6f6666656e6365732f7372632f6c69622e727300881c1000430000005500000001000000551d10003600000054191000630000005e01000005000000000000000000000000000000181d10003d00000054191000630000006501000005000000736869667465642073756666696369656e74206269747320726967687420746f206c656164206f6e6c79206c656164696e67207a65726f733b2071656450726576696f7573206d617463682061726d206d61746368657320616e7974696e67206c657373207468616e20325e33303b2071656400551d10003600000054191000630000008a0100000500000000000000000000000000000000000000000000005419100063000000910100000500000053657373696f6e20486973746f726963616c53657373696f6e734c696e6b616765206973207570646174656420696e206361736520656e7472792069732072656d6f7665643b0a0909090909697420616c7761797320706f696e747320746f206578697374696e67206b6579733b20716564000000000000441f10000700000001010000000000004b1f10000d00000000000000581f10003400000000000000000000000000000000000000389711008c1f100000000000000000009c1f100001000000000000000000000000000000a41f10001600000002010100000000006f8c11000400000000000000738c11000e00000000000000ba1f1000120000000000000038971100cc1f10000000000000000000dc1f100001000000000000000100000000000000e41f10001200000001010000000000006f8c11000400000000000000e7ea1000070000000000000000000000000000000000000038971100f81f10000000000000000000082010000600000000000000010000005265706f7274735265706f727449644f663c543e4f6666656e636544657461696c733c543a3a4163636f756e7449642c20543a3a4964656e74696669636174696f6e5475706c653e3700000000000000010000004f000000a121100052000000436f6e63757272656e745265706f727473496e6465785665633c5265706f727449644f663c543e3e37000000000000000100000050000000572110004a0000005265706f72747342794b696e64496e646578000037000000000000000100000051000000382010004400000038971100000000007c2010002f0000003897110000000000ab20100052000000fd2010005a00000020456e756d65726174657320616c6c207265706f727473206f662061206b696e6420616c6f6e672077697468207468652074696d6520746865792068617070656e65642e20416c6c207265706f7274732061726520736f72746564206279207468652074696d65206f66206f6666656e63652e204e6f74652074686174207468652061637475616c2074797065206f662074686973206d617070696e6720697320605665633c75383e602c207468697320697320626563617573652076616c756573206f6620646966666572656e7420747970657320617265206e6f7420737570706f7274656420617420746865206d6f6d656e7420736f2077652061726520646f696e6720746865206d616e75616c2073657269616c697a6174696f6e2e204120766563746f72206f66207265706f727473206f66207468652073616d65206b696e6420746861742068617070656e6564206174207468652073616d652074696d6520736c6f742e20546865207072696d61727920737472756374757265207468617420686f6c647320616c6c206f6666656e6365207265636f726473206b65796564206279207265706f7274206964656e746966696572732e72656163686564206d6178696d756d2064657074682c2063616e6e6f7420696e7374616e7469617465520000001800000004000000530000005400000055000000560000005700000058000000696e73756666696369656e742072656d61696e696e672062616c616e6365416c69766520636f6e7472616374206f7220746f6d6273746f6e6520616c7265616479206578697374736e6f7420656e6f7567682067617320746f20706179206261736520696e7374616e7469617465206665656e6f7420656e6f7567682067617320746f20706179207472616e736665722066656572656163686564206d6178696d756d2064657074682c2063616e6e6f74206d616b6520612063616c6c6e6f7420656e6f7567682067617320746f2070617920626173652063616c6c20666565636f6e747261637420686173206265656e2065766963746564636f6e74726163742063616e6e6f742062652064657374726f79656420647572696e672072656375727369766520657865637574696f6e61206e657374656420657865637574696f6e20636f6e74657874206d7573742068617665206120706172656e743b20716564696d2d6f6e6c696e653a6f66666c696e4f6666656e63657320436f6e63757272656e745265706f727473496e6465780000005900000008000000040000005a0000007375627374726174652d6e6f64650000df6acb689907609b0200000037e397fc7c91f5e40100000040fe3ad401f8959a03000000d2bc9897eed08f1501000000f78b278be53f454c01000000ed99c5acb25eedf502000000cbca25e39f14238701000000687ad44ad37f03c201000000bc9d89904f5b923f0100000068b66ba122c93fa701000000ab3c0572291feb8b010000006772616e62616265696d6f6e0000000040787d010065cd1d00e1f505d85aae1ec0542205b0508f1f38e4750488467020d853e903603c5121d0bf760338323222a8591903402013236039cd02480ef423a82a8f0268f8d42470955c02b8dab525c05a3302d8c4962648bd1102e0b27727a855f601e8a05828e8fedf0180773929c0cacd01586d1a2af8f1be019053fb2a50d8b201d00edc2be0fca80138edbc2c48f2a001e06d9d2d80669a01c80d7e2e500f9501c0575e2f08b6900140323f30e0278d0148202031b0418a0108a3ff3120e8870120bedf32f0fb85013856c03398698401f0fda03478218301b8d87f35d8178201d8c26036183d8101b8223e37508d800188d21c38c8fc7f0168b5f93898877f01a829d139d8297f0120d6ab3ab8db7e0168ae803b389d7e0100ca9a3b68957e0100000000d3bc100006000000000000005b000000000000000000000000000000000000000000000000000000000000005c0000000000000000000000000000005d0000000000000000000000000000005e0000000000000000000000000000003fa7100004000000000000005f000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000020000000000000000000000000000000000000060000000000000000000000000000000e7df10000900000000000000610000000000000000000000000000000000000000000000000000000000000062000000000000000000000002000000000000000000000000000000000000006300000000000000000000000000000095a410000a00000000000000640000000000000000000000000000000000000000000000000000000000000065000000000000000000000002000000000000000000000000000000000000005e00000000000000000000000000000045db1000070000000000000066000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000670000000000000000000000000000005e000000000000000000000000000000b239100008000000000000006800000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000006a0000000000000000000000000000006b000000000000000000000000000000d92d110007000000000000006c000000000000000000000000000000000000000000000000000000000000006d0000000000000000000000000000006e0000000000000000000000000000006f000000000000000000000000000000158b1000070000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000072000000000000000000000000000000730000000000000000000000000000007955110009000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000007600000000000000000000000000000077000000000000000000000000000000fe65100007000000000000007800000000000000000000000000000000000000000000000000000000000000790000000000000000000000000000007a0000000000000000000000000000005e000000000000000000000000000000382d100012000000000000007b00000000000000000000000000000000000000000000000000000000000000790000000000000000000000000000007a0000000000000000000000000000005e0000000000000000000000000000004a2d100009000000000000007c000000000000000000000000000000000000000000000000000000000000007d0000000000000000000000000000007e0000000000000000000000000000007f000000000000000000000000000000532d10001300000000000000800000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000820000000000000000000000000000005e000000000000000000000000000000662d10000f000000020000000000000000000000000000000000000000000000000000000000000000000000830000000000000000000000020000000000000000000000000000000000000084000000000000000000000000000000752d10000700000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000870000000000000000000000000000005e0000000000000000000000000000000596100008000000000000008800000000000000000000000000000000000000000000000000000000000000890000000000000000000000000000008a0000000000000000000000000000008b0000000000000000000000000000007c2d100009000000000000008c000000000000000000000000000000000000000000000000000000000000008d0000000000000000000000000000008e0000000000000000000000000000008f000000000000000000000000000000161311000400000000000000900000000000000000000000000000000000000000000000000000000000000091000000000000000000000000000000920000000000000000000000000000005e000000000000000000000000000000314610000800000000000000930000000000000000000000000000000000000000000000000000000000000094000000000000000000000000000000950000000000000000000000000000005e000000000000000000000000000000852d1000120000000200000000000000000000000000000000000000000000000000000000000000000000005e000000000000000000000002000000000000000000000000000000000000005e000000000000000000000000000000972d1000080000000000000096000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000970000000000000000000000000000005e0000000000000000000000546563686e6963616c436f6d6d6974746565456c656374696f6e73546563686e6963616c4d656d6265727368697046696e616c697479547261636b65724772616e647061436f6e747261637473417574686f72697479446973636f766572794f6666656e6365735365656420697320616e207574663820737472696e67000000e02d1000480000009b0a00000a000000e02d100048000000a10a00000e00000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000ac2e10000a00000000000000e0151100020000000000000000000000b82e1000010000000000000000000000c02e10000d00000000000000a8431100010000000000000000000000d02e100001000000000000000000000000ea10000800000000000000d82e1000040000000000000000000000f82e100001000000000000004e65774163636f756e740000432f10001b0000005265617065644163636f756e740000002c2f100017000000d043110009000000d04311000900000011441100070000001144110007000000002f10002c000000205472616e7366657220737563636565646564202866726f6d2c20746f2c2076616c75652c2066656573292e20416e206163636f756e7420776173207265617065642e2041206e6577206163636f756e742077617320637265617465642e76657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c75656163636f756e74206c6971756964697479207265737472696374696f6e732070726576656e74207769746864726177616c62656e6566696369617279206163636f756e74206d757374207072652d6578697374746f6f2066657720667265652066756e647320696e206163636f756e747061796d656e7420776f756c64206b696c6c206163636f756e740000000000003c3010001100000000000000503010000100000000000000000000005830100001000000000000004865617274626561745265636569766564000000903010000b00000060301000300000002041206e657720686561727462656174207761732072656365697665642066726f6d2060417574686f72697479496460417574686f726974794964496d4f6e6c696e6520476f73736970417442616c616e63657320546f74616c49737375616e6365496d4f6e6c696e65204b65797342616c616e636573204672656542616c616e636542616c616e63657320526573657276656442616c616e636542616c616e636573204c6f636b7342616c616e6365732056657374696e6700000000000000a03110000800000000000000a8311000020000000000000000000000d8311000170000000000000000000000903210000b000000000000009c321000030000000000000000000000e43210000d00000000000000000000004c3310000e000000000000005c331000030000000000000000000000a433100002000000000000007472616e736665720000000046f1100004000000000000004b22110023000000000000005f55110005000000000000001934100013000000ed35100036000000389711000000000023361000420000006536100048000000ad36100045000000f23610002d00000038971100000000001f371000460000003897110000000000c54d11000b000000653710004c000000b137100033000000e43710005a00000038971100000000003e3810001300000038971100000000005138100054000000a53810004b000000f03810003500000025391000370000005c391000560000003897110000000000d84d11000c0000007365745f62616c616e636500000000005712110003000000000000004b2211002300000000000000d93510000800000000000000193410001300000000000000e13510000c0000000000000019341000130000002c34100025000000389711000000000051341000480000009934100042000000db34100046000000213510003a00000038971100000000005b3510002d0000003897110000000000c54d11000b0000008835100020000000a835100031000000d84d11000c000000666f7263655f7472616e736665720000000000001334100006000000000000004b221100230000000000000046f1100004000000000000004b22110023000000000000005f55110005000000000000001934100013000000b433100054000000083410000b0000002045786163746c7920617320607472616e73666572602c2065786365707420746865206f726967696e206d75737420626520726f6f7420616e642074686520736f75726365206163636f756e74206d6179206265207370656369666965642e736f75726365436f6d706163743c543a3a42616c616e63653e20536574207468652062616c616e636573206f66206120676976656e206163636f756e742e20546869732077696c6c20616c74657220604672656542616c616e63656020616e642060526573657276656442616c616e63656020696e2073746f726167652e2069742077696c6c20616c736f2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d202860546f74616c49737375616e636560292e20496620746865206e65772066726565206f722072657365727665642062616c616e63652069732062656c6f7720746865206578697374656e7469616c206465706f7369742c2069742077696c6c20726573657420746865206163636f756e74206e6f6e636520286073797374656d3a3a4163636f756e744e6f6e636560292e20546865206469737061746368206f726967696e20666f7220746869732063616c6c2069732060726f6f74602e202d20496e646570656e64656e74206f662074686520617267756d656e74732e202d20436f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e64207772697465732e6e65775f667265656e65775f7265736572766564205472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572206163636f756e742e20607472616e73666572602077696c6c207365742074686520604672656542616c616e636560206f66207468652073656e64657220616e642072656365697665722e2049742077696c6c2064656372656173652074686520746f74616c2069737375616e6365206f66207468652073797374656d2062792074686520605472616e73666572466565602e204966207468652073656e6465722773206163636f756e742069732062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c74206f6620746865207472616e736665722c20746865206163636f756e742077696c6c206265207265617065642e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605369676e65646020627920746865207472616e736163746f722e202d20446570656e64656e74206f6e20617267756d656e747320627574206e6f7420637269746963616c2c20676976656e2070726f70657220696d706c656d656e746174696f6e7320666f72202020696e70757420636f6e6669672074797065732e205365652072656c617465642066756e6374696f6e732062656c6f772e202d20497420636f6e7461696e732061206c696d69746564206e756d626572206f6620726561647320616e642077726974657320696e7465726e616c6c7920616e64206e6f20636f6d706c657820636f6d7075746174696f6e2e2052656c617465642066756e6374696f6e733a2020202d2060656e737572655f63616e5f77697468647261776020697320616c776179732063616c6c656420696e7465726e616c6c792062757420686173206120626f756e64656420636f6d706c65786974792e2020202d205472616e7366657272696e672062616c616e63657320746f206163636f756e7473207468617420646964206e6f74206578697374206265666f72652077696c6c20636175736520202020202060543a3a4f6e4e65774163636f756e743a3a6f6e5f6e65775f6163636f756e746020746f2062652063616c6c65642e2020202d2052656d6f76696e6720656e6f7567682066756e64732066726f6d20616e206163636f756e742077696c6c2074726967676572202020202060543a3a4475737452656d6f76616c3a3a6f6e5f756e62616c616e6365646020616e642060543a3a4f6e4672656542616c616e63655a65726f3a3a6f6e5f667265655f62616c616e63655f7a65726f602e42616c616e636573000000000000743b10000d0000000000000000000000813b10000a0000000000000000000000000000000000000000000000000000000000000038971100543c100000000000000000008c3b100001000000000000000100000000000000943b10000700000001010000000000000b4e11000c000000000000009b3b10002b0000000000000000000000000000000000000038971100c83b10000000000000000000d83b100001000000000000000000000000000000e03b10000b00000001010000000000000b4e11000c00000000000000813b10000a0000000000000000000000000000000000000038971100543c10000000000000000000ec3b10000b000000000000000100000000000000443c10000f00000001010000000000000b4e11000c00000000000000813b10000a0000000000000000000000000000000000000038971100543c10000000000000000000643c10000b000000000000000100000000000000bc3c10000500000001010000000000000b4e11000c00000000000000c13c10002c0000000000000000000000000000000000000038971100f03c10000000000000000000003d1000010000000000000001000000546f74616c49737375616e6365543a3a42616c616e636500314210002600000056657374696e6756657374696e675363686564756c653c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e00003700000000000000010000004f000000fb411000360000004672656542616c616e636500813f1000270000003897110000000000a83f100050000000f83f10005d0000005540100055000000aa4010004f000000f9401000510000004a4110001500000038971100000000005f41100057000000b641100045000000526573657276656442616c616e63650037000000000000000100000098000000363d10005d000000933d1000270000003897110000000000ba3d10005b000000153e10004900000038971100000000005e3e10005d000000bb3e10002d0000003897110000000000e83e1000530000003b3f1000460000004c6f636b735665633c42616c616e63654c6f636b3c543a3a42616c616e63652c20543a3a426c6f636b4e756d6265723e3e00000037000000000000000100000050000000083d10002e00000020416e79206c6971756964697479206c6f636b73206f6e20736f6d65206163636f756e742062616c616e6365732e2054686520616d6f756e74206f66207468652062616c616e6365206f66206120676976656e206163636f756e7420746861742069732065787465726e616c6c792072657365727665643b20746869732063616e207374696c6c2067657420736c61736865642c20627574206765747320736c6173686564206c617374206f6620616c6c2e20546869732062616c616e63652069732061202772657365727665272062616c616e63652074686174206f746865722073756273797374656d732075736520696e206f7264657220746f2073657420617369646520746f6b656e73207468617420617265207374696c6c20276f776e65642720627920746865206163636f756e7420686f6c6465722c20627574207768696368206172652073757370656e6461626c652e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e2074686973202772657365727665206163636f756e74272069732064656c657465643a207370656369666963616c6c792c2060526573657276656442616c616e6365602e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c6574656420696620604672656542616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e2920546865202766726565272062616c616e6365206f66206120676976656e206163636f756e742e205468697320697320746865206f6e6c792062616c616e63652074686174206d61747465727320696e207465726d73206f66206d6f7374206f7065726174696f6e73206f6e20746f6b656e732e20497420616c6f6e65206973207573656420746f2064657465726d696e65207468652062616c616e6365207768656e20696e2074686520636f6e747261637420657865637574696f6e20656e7669726f6e6d656e742e205768656e20746869732062616c616e63652066616c6c732062656c6f77207468652076616c7565206f6620604578697374656e7469616c4465706f736974602c207468656e20746865202763757272656e74206163636f756e74272069732064656c657465643a207370656369666963616c6c7920604672656542616c616e6365602e20467572746865722c2074686520604f6e4672656542616c616e63655a65726f602063616c6c6261636b20697320696e766f6b65642c20676976696e672061206368616e636520746f2065787465726e616c206d6f64756c657320746f20636c65616e2075702064617461206173736f6369617465642077697468207468652064656c65746564206163636f756e742e206073797374656d3a3a4163636f756e744e6f6e63656020697320616c736f2064656c657465642069662060526573657276656442616c616e63656020697320616c736f207a65726f2028697420616c736f206765747320636f6c6c617073656420746f207a65726f2069662069742065766572206265636f6d6573206c657373207468616e20604578697374656e7469616c4465706f736974602e20496e666f726d6174696f6e20726567617264696e67207468652076657374696e67206f66206120676976656e206163636f756e742e2054686520746f74616c20756e6974732069737375656420696e207468652073797374656d2e0000000000704310001200000000000000813b10000a000000000000003897110084431000000000000000000094431000010000000000000000000000000011000b00000000000000813b10000a00000000000000389711009c43100000000000000000000c001100010000000000000000000000140011000b00000000000000813b10000a00000000000000389711009c431000000000000000000020001100010000000000000000000000280011001200000000000000813b10000a00000000000000389711009c43100000000000000000003c001100010000000000000000000000440011001200000000000000813b10000a0000000000000038971100ac43100000000000000000006800110001000000000000004578697374656e7469616c4465706f736974000037000000000000000100000099000000bc431000350000003700000000000000010000009a0000003700000000000000010000009b00000020546865206d696e696d756d20616d6f756e7420726571756972656420746f206b65657020616e206163636f756e74206f70656e2e776520676f74207468652076616c696461746f725f69642066726f6d2063757272656e745f76616c696461746f72733b0a09090909090963757272656e745f76616c696461746f727320697320736574206f662063757272656e746c7920616374696e672076616c696461746f72733b0a090909090909746865206d617070696e67206265747765656e207468652076616c696461746f7220696420616e64206974732066756c6c206964656e74696669636174696f6e2073686f756c642062652076616c69643b0a09090909090974687573206046756c6c4964656e74696669636174696f6e4f663a3a636f6e76657274602063616e27742072657475726e20604e6f6e65603b0a09090909090971656473726d6c2f696d2d6f6e6c696e652d776f726b65722d7374617475730030451000480000009b0a00000a0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000a44510000900000000000000b045100002000000000000000000000038971100000000000000000068656172746265617400000000000000a44510000900000000000000e04510001900000000000000f94510000900000000000000024610002f0000004865617274626561743c543a3a426c6f636b4e756d6265723e7369676e61747572653c543a3a417574686f7269747949642061732052756e74696d654170705075626c69633e3a3a5369676e6174757265496d4f6e6c696e650000000000000044471000080000000000000000000000925111000e00000000000000000000000000000000000000000000000000000000000000389711004c47100000000000000000005c4710000100000000000000010000000000000064471000040000000000000000000000684710001300000000000000000000000000000000000000000000000000000000000000389711007c47100000000000000000008c47100001000000000000000100000000000000944710001200000002010100000000009f8d11000c00000000000000a64710000900000000000000e7ea1000070000000000000038971100b04710000000000000000000c0471000020000000000000001000000476f7373697041743700000000000000010000009c00000061481000280000004b6579735665633c543a3a417574686f7269747949643e00370000000000000001000000500000002d4810003400000052656365697665644865617274626561747341757468496e6465780037000000000000000100000051000000d04710003a0000000a4810002300000020466f7220656163682073657373696f6e20696e646578207765206b6565702061206d617070696e67206f662060417574686f7269747949646020746f20606f6666636861696e3a3a4f70617175654e6574776f726b5374617465602e205468652063757272656e7420736574206f66206b6579732074686174206d61792069737375652061206865617274626561742e2054686520626c6f636b206e756d626572207768656e2077652073686f756c6420676f737369702e6e6f7420656e6f75676820667265652066756e64730000387d110028000000b84810004300000096010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f62616c616e6365732f7372632f6c69622e72734f75746461746564206865617274626561742072656365697665642e496e76616c696420686561727462656174207369676e61747572652e4475706c696361746564206865617274626561742e4e6f6e206578697374656e74207075626c6963206b65792eb8481000430000009601000001000000676f74206f766572666c6f7720616674657220616464696e6720612066656520746f2076616c756562616c616e636520746f6f206c6f7720746f2073656e642076616c756564657374696e6174696f6e2062616c616e636520746f6f206869676820746f20726563656976652076616c756576616c756520746f6f206c6f7720746f20637265617465206163636f756e7454696d657374616d702055706461746554696d657374616d7020526563656e7448696e74730000404a100031000000714a10004b0000007d0000000400000046696e616c2068696e74206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b2f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f66696e616c6974792d747261636b65722f7372632f6c69622e7273d44a100023000000714a10004b0000007e0000000400000046696e616c697a6564206865696768742061626f766520626c6f636b206e756d62657200104b100019000000304b100048000000bb0100002d000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f6f70732f61726974682e7273576974686472617720686173206265656e20636865636b65642061626f76653b0a090909647565735f6c696d69746564203c2072656e745f627564676574203c2062616c616e6365202d2073756273697374656e6365203c2062616c616e6365202d206578697374656e7469616c5f6465706f7369743b0a09090971656400005900000008000000040000009d00000054696d657374616d70204f72646572656448696e747354696d657374616d70204d656469616e616c77617973206174206c65617374206f6e6520726563656e742073616d706c653b20716564726563656e7420616e64206f72646572656420636f6e7461696e207468652073616d65206974656d733b2071656400003300000004000000040000009e000000084d100043000000714a10004b000000b600000004000000c04c1000480000009b0a00000a000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e72737072756e696e672064696374617465642062792077696e646f775f73697a6520776869636820697320616c776179732073617475726174656420617420313b207165640000000000784d10000a00000000000000844d10000100000000000000000000009c4d1000020000000000000066696e616c5f68696e74000000000000f26510000400000000000000de4e110017000000ac4d10003d000000e94d10001b0000002048696e7420746861742074686520617574686f72206f66207468697320626c6f636b207468696e6b732074686520626573742066696e616c697a656420626c6f636b2069732074686520676976656e206e756d6265722e00000000744e10000a00000000000000925111000e0000000000000038971100804e10000000000000000000904e1000010000000000000000000000984e10000d00000000000000925111000e0000000000000038971100a84e10000000000000000000b84e1000010000000000000057696e646f7753697a6500003700000000000000010000009f000000074f1000460000005265706f72744c6174656e6379000000370000000000000001000000a0000000c04e100047000000205468652064656c617920616674657220776869636820706f696e74207468696e6773206265636f6d6520737573706963696f75732e2044656661756c7420697320313030302e20546865206e756d626572206f6620726563656e742073616d706c657320746f206b6565702066726f6d207468697320636861696e2e2044656661756c74206973203130312e00000000000000005010000b000000000000008c4311000200000000000000000000000c501000010000000000000000000000145010001000000000000000a8431100010000000000000000000000245010000100000000000000000000002c5010000c0000000000000068ea100001000000000000000000000038501000010000000000000000000000405010000e0000000000000050501000020000000000000000000000605010000100000000000000566f74657252656170656400fe50100015000000426164526561706572536c6173686564ef5010000f00000054616c6c7953746172746564ba5010003500000054616c6c7946696e616c697a65640000184411000e000000184411000e000000685010005200000020412074616c6c792028666f7220617070726f76616c20766f746573206f662073656174287329292068617320656e646564202877697468206f6e65206f72206d6f7265206e6577206d656d62657273292e20412074616c6c792028666f7220617070726f76616c20766f746573206f662073656174287329292068617320737461727465642e20736c6173686564207265617065722072656170656420766f7465722c20726561706572436f756e63696c205265676973746572496e666f4f66436f756e63696c204d656d62657273436f756e63696c204e65787446696e616c697a6540521000480000009b0a00000a000000436f756e63696c205465726d4475726174696f6e436f756e63696c2050726573656e746174696f6e4475726174696f6e436f756e63696c204c6561646572626f617264004052100048000000a10a00000e000000436f756e63696c2043616e64696461746573436f756e63696c20566f746572496e666f4f6647757275206d656469746174696f6e66696e616c697a652063616e206f6e6c792062652063616c6c656420616674657220612074616c6c7920697320737461727465642e436f756e63696c20417070726f76616c734f66436f756e63696c20566f746572730000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000405410000d0000000000000050541000040000000000000000000000b05410001800000000000000000000007055100013000000000000005054100004000000000000000000000084551000060000000000000000000000b45510001300000000000000c8551000040000000000000000000000285610000c0000000000000000000000885610000d0000000000000098561000010000000000000000000000b05610000a000000000000000000000000571000100000000000000010571000010000000000000000000000285710000d0000000000000000000000905710000e00000000000000a0571000030000000000000000000000e8571000090000000000000000000000305810001100000000000000445810000100000000000000000000005c581000030000000000000000000000cce310000d00000000000000745810000100000000000000000000008c581000040000000000000000000000ac5810001900000000000000c8581000010000000000000000000000e0581000020000000000000000000000f05810001100000000000000c85810000100000000000000000000000459100002000000000000007365745f617070726f76616c7300000000000000e46510000500000000000000e96510000900000000000000e4cd10000500000000000000ac5c10001200000000000000f26510000400000000000000f665100008000000000000005f55110005000000000000007a6511000c0000009161100058000000e9611000100000003897110000000000f9611000530000004c6210003000000038971100000000007c62100035000000b162100055000000066310002a00000030631000530000008363100057000000da631000510000002b6410003b0000006664100057000000bd641000370000003897110000000000f46410005400000048651000340000003897110000000000c54d11000b000000d04d1100080000007c65100027000000a365100041000000d84d11000c00000070726f78795f7365745f617070726f76616c7300e060100059000000396110001c0000003897110000000000c54d11000b000000556110003c000000d84d11000c000000726561705f696e6163746976655f766f7465720000000000b76010000e00000000000000fa4e11000c000000000000005712110003000000000000004b2211002300000000000000c56010000900000000000000fa4e11000c00000000000000ce6010001200000000000000ac5c100012000000565f100058000000ae5f100056000000046010002e00000038971100000000003260100045000000389711000000000077601000400000003897110000000000c54d11000b000000d04d1100080000002f5f100027000000d84d11000c000000726574726163745f766f74657200000000000000e4cd10000500000000000000fa4e11000c000000535e10004b00000038971100000000009e5e1000420000003897110000000000e05e10004f0000003897110000000000c54d11000b000000d04d1100080000002f5f100027000000d84d11000c0000007375626d69745f63616e646964616379000000004f5e10000400000000000000fa4e11000c000000be5c10001e0000003897110000000000dc5c1000440000003897110000000000205d100048000000685d100051000000b95d10004c000000055e10001e0000003897110000000000c54d11000b000000235e1000180000003b5e100014000000d84d11000c00000070726573656e745f77696e6e65720000000000009e5c100009000000000000004b2211002300000000000000a75c10000500000000000000645511001500000000000000e4cd10000500000000000000ac5c1000120000007b5b100058000000d35b1000580000002b5c100057000000825c1000070000003897110000000000c54d11000b000000895c100015000000b712110011000000d84d11000c0000007365745f646573697265645f736561747300000000000000d65910000500000000000000fa4e11000c000000bb5a100059000000145b100052000000665b100015000000000000005712110003000000000000004b22110023000000db591000480000003897110000000000235a1000480000006b5a1000500000007365745f70726573656e746174696f6e5f6475726174696f6e00000000000000d65910000500000000000000de4e110017000000805910005600000068591000180000007365745f7465726d5f6475726174696f6e0000001459100054000000685910001800000020536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e74206120766f7465206265696e672070726573656e74656420666f722c2077696c6c20696e766f6b65206066696e616c697a655f766f7465602e20536574207468652070726573656e746174696f6e206475726174696f6e2e2049662074686572652069732063757272656e746c79206120766f7465206265696e672070726573656e74656420666f722c2077696c6c636f756e742052656d6f7665206120706172746963756c6172206d656d6265722066726f6d20746865207365742e20546869732069732065666665637469766520696d6d6564696174656c792e204e6f74653a20412074616c6c792073686f756c642068617070656e20696e7374616e746c7920286966206e6f7420616c726561647920696e20612070726573656e746174696f6e20706572696f642920746f2066696c6c2074686520736561742069662072656d6f76616c206d65616e732074686174207468652064657369726564206d656d6265727320617265206e6f74206d65742e20536574207468652064657369726564206d656d62657220636f756e743b206966206c6f776572207468616e207468652063757272656e7420636f756e742c207468656e2073656174732077696c6c206e6f7420626520757020656c656374696f6e207768656e2074686579206578706972652e204966206d6f72652c207468656e2061206e657720766f74652077696c6c2062652073746172746564206966206f6e65206973206e6f7420616c726561647920696e2070726f67726573732e20436c61696d2074686174206063616e64696461746560206973206f6e65206f662074686520746f70206063617272795f636f756e74202b20646573697265645f7365617473602063616e646964617465732e204f6e6c7920776f726b7320696666207468652070726573656e746174696f6e20706572696f64206973206163746976652e206063616e646964617465602073686f756c642068617665206174206c6561737420636f6c6c656374656420736f6d65206e6f6e2d7a65726f2060746f74616c6020766f74657320616e6420606f726967696e60206d757374206861766520656e6f7567682066756e647320746f2070617920666f72206120706f74656e7469616c20736c6173682e202d204f28766f746572732920636f6d707574652e63616e646964617465746f74616c436f6d706163743c566f7465496e6465783e205375626d6974206f6e6573656c6620666f722063616e6469646163792e204163636f756e74206d757374206861766520656e6f756768207472616e736665727261626c652066756e647320696e20697420746f207061792074686520626f6e642e204e4f54453a20696620606f726967696e602068617320616c72656164792061737369676e656420617070726f76616c7320766961205b607365745f617070726f76616c73605d2c2069742077696c6c204e4f54206861766520616e7920757361626c652066756e647320746f20706173732063616e64696461637920626f6e6420616e64206d75737420666972737420726574726163742e204e6f746520746861742073657474696e6720617070726f76616c732077696c6c206c6f636b2074686520656e746972652062616c616e6365206f662074686520766f74657220756e74696c2072657472616374696f6e206f72206265696e67207265706f727465642e202d20496e646570656e64656e74206f6620696e7075742e202d205468726565204442206368616e6765732e736c6f742052656d6f7665206120766f7465722e20416c6c20766f746573206172652063616e63656c6c656420616e642074686520766f746572206465706f7369742069732072657475726e65642e2054686520696e646578206d7573742062652070726f7669646564206173206578706c61696e656420696e205b60766f7465725f6174605d2066756e6374696f6e2e20416c736f2072656d6f76657320746865206c6f636b206f6e207468652062616c616e6365206f662074686520766f7465722e20536565205b60646f5f7365745f617070726f76616c732829605d2e202d2054776f20666577657220444220656e74726965732c206f6e65204442206368616e67652e2052656d6f7665206120766f7465722e20466f72206974206e6f7420746f206265206120626f6e642d636f6e73756d696e67206e6f2d6f702c20616c6c20617070726f7665642063616e64696461746520696e6469636573206d757374206e6f772062652065697468657220756e72656769737465726564206f72207265676973746572656420746f20612063616e646964617465207468617420726567697374657265642074686520736c6f742061667465722074686520766f7465722067617665207468656972206c61737420617070726f76616c207365742e20426f746820696e6469636573206d7573742062652070726f7669646564206173206578706c61696e656420696e205b60766f7465725f6174605d2066756e6374696f6e2e204d61792062652063616c6c656420627920616e796f6e652e2052657475726e732074686520766f746572206465706f73697420746f20607369676e6564602e7265706f727465725f696e64657877686f5f696e646578617373756d65645f766f74655f696e646578205365742063616e64696461746520617070726f76616c732066726f6d20612070726f78792e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f74732061726520726567697374657265642e202d2053616d6520617320607365745f617070726f76616c73602077697468206f6e65206164646974696f6e616c2073746f7261676520726561642e205365742063616e64696461746520617070726f76616c732e20417070726f76616c20736c6f747320737461792076616c6964206173206c6f6e672061732063616e6469646174657320696e2074686f736520736c6f74732061726520726567697374657265642e204c6f636b73206076616c7565602066726f6d207468652062616c616e6365206f6620606f726967696e6020696e646566696e6974656c792e204f6e6c79205b60726574726163745f766f746572605d206f72205b60726561705f696e6163746976655f766f746572605d2063616e20756e6c6f636b207468652062616c616e63652e206068696e746020617267756d656e7420697320696e74657270726574656420646966666572656e746c79206261736564206f6e3a202d20696620606f726967696e602069732073657474696e6720617070726f76616c7320666f72207468652066697273742074696d653a2054686520696e6465782077696c6c20626520636865636b656420666f722020206265696e6720612076616c6964205f686f6c655f20696e2074686520766f746572206c6973742e2020202d206966207468652068696e7420697320636f72726563746c7920706f696e74696e6720746f206120686f6c652c206e6f206665652069732064656475637465642066726f6d20606f726967696e602e2020202d204f74686572776973652c207468652063616c6c2077696c6c2073756363656564206275742074686520696e6465782069732069676e6f72656420616e642073696d706c792061207075736820746f2074686520202020206c617374206368756e6b207769746820667265652073706163652068617070656e732e20496620746865206e65772070757368206361757365732061206e6577206368756e6b20746f2062652020202020637265617465642c20612066656520696e64696361746564206279205b60566f74696e67466565605d2069732064656475637465642e202d20696620606f726967696e6020697320616c7265616479206120766f7465723a2074686520696e646578205f5f6d7573745f5f2062652076616c696420616e6420706f696e7420746f2074686520636f7272656374202020706f736974696f6e206f662074686520606f726967696e6020696e207468652063757272656e7420766f74657273206c6973742e204e6f7465207468617420616e7920747261696c696e67206066616c73656020766f74657320696e2060766f746573602069732069676e6f7265643b20496e20617070726f76616c20766f74696e672c206e6f7420766f74696e6720666f7220612063616e64696461746520616e6420766f74696e672066616c73652c2061726520657175616c2e202d2054776f20657874726120444220656e74726965732c206f6e65204442206368616e67652e202d20417267756d656e742060766f74657360206973206c696d6974656420696e206c656e67746820746f206e756d626572206f662063616e646964617465732e766f7465735665633c626f6f6c3e68696e74536574496e646578436f756e63696c00000000000000886b1000140000000000000000000000925111000e00000000000000000000000000000000000000000000000000000000000000389711008c76100000000000000000009c6b100001000000000000000100000000000000a46b10000c0000000000000000000000925111000e00000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000b06b100001000000000000000100000000000000b86b10000c0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000c46b100001000000000000000100000000000000ace61000070000000000000000000000cc6b1000230000000000000000000000000000000000000000000000000000000000000038971100386d10000000000000000000f06b100004000000000000000100000000000000106c1000090000000000000000000000196c10000900000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000246c1000010000000000000001000000000000002c6c10000b0000000101000000000000376c100018000000000000004f6c1000110000000000000000000000000000000000000038971100386d100000000000000000003897110000000000000000000100000000000000606c10000e00000001010000000000000b4e11000c000000000000006e6c1000100000000000000000000000000000000000000038971100806c10000000000000000000906c100002000000000000000000000000000000a06c10000b00000001010000000000000b4e11000c00000000000000ab6c1000170000000000000000000000000000000000000038971100c46c10000000000000000000d46c100001000000000000000000000000000000dc6c1000060000000101000000000000f66510000800000000000000e26c1000190000000000000000000000000000000000000038971100386d10000000000000000000fc6c100001000000000000000100000000000000046d10000c0000000000000000000000f66510000800000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000106d100001000000000000000100000000000000186d10000a0000000000000000000000f66510000800000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000246d1000010000000000000001000000000000002c6d10000a0000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100386d10000000000000000000486d100001000000000000000100000000000000506d10000e0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711008c7610000000000000000000606d100001000000000000000100000000000000686d10000c0000000000000000000000746d10002800000000000000000000000000000000000000000000000000000000000000389711009c6d10000000000000000000ac6d100001000000000000000000000000000000b46d10000b0000000000000000000000bf6d1000210000000000000000000000000000000000000000000000000000000000000038971100e06d10000000000000000000f06d100003000000000000000000000000000000a85c11000500000001010000000000000b4e11000c000000000000000b4e11000c0000000000000000000000000000000000000038971100086e10000000000000000000c05c110002000000000000000000000050726573656e746174696f6e4475726174696f6e6f7210004f0000005465726d4475726174696f6e49721000260000004465736972656453656174730f7210003a0000005665633c28543a3a4163636f756e7449642c20543a3a426c6f636b4e756d626572293e00e37010005500000038711000550000008d71100054000000e17110002e000000566f7465436f756e74566f7465496e64657800009c70100047000000417070726f76616c734f6628543a3a4163636f756e7449642c20536574496e646578295665633c417070726f76616c466c61673e5265676973746572496e666f4f6628566f7465496e6465782c20753332290000370000000000000001000000a100000027701000570000007e7010001e000000566f746572496e666f4f66566f746572496e666f3c42616c616e63654f663c543e3e00003700000000000000010000004f0000000670100021000000566f746572735665633c4f7074696f6e3c543a3a4163636f756e7449643e3e00c36f1000430000004e657874566f746572536574846f10003f000000566f746572436f756e7400006a6f10001a00000043616e646964617465730000370000000000000001000000500000004e6f10001c00000043616e646964617465436f756e7400002a6f1000240000004e65787446696e616c697a6528543a3a426c6f636b4e756d6265722c207533322c205665633c543a3a4163636f756e7449643e29370000000000000001000000a2000000e26e1000480000004c6561646572626f6172645665633c2842616c616e63654f663c543e2c20543a3a4163636f756e744964293e3700000000000000010000004f000000186e100058000000706e100059000000c96e1000190000003700000000000000010000004f0000002047657420746865206c6561646572626f61726420696620776527726520696e207468652070726573656e746174696f6e2070686173652e2054686520666972737420656c656d656e742069732074686520776569676874206f66206561636820656e7472793b204974206d617920626520746865206469726563742073756d6d656420617070726f76616c207374616b65732c206f7220612077656967687465642076657273696f6e206f662069742e20536f727465642066726f6d206c6f7720746f20686967682e20546865206163636f756e747320686f6c64696e672074686520736561747320746861742077696c6c206265636f6d652066726565206f6e20746865206e6578742074616c6c792e2043757272656e74206e756d626572206f66206163746976652063616e64696461746573205468652070726573656e742063616e646964617465206c6973742e2043757272656e74206e756d626572206f6620566f746572732e20746865206e65787420667265652073657420746f2073746f7265206120766f74657220696e2e20546869732077696c6c206b6565702067726f77696e672e205468652070726573656e7420766f746572206c69737420286368756e6b656420616e6420636170706564206174205b60564f5445525f5345545f53495a45605d292e20426173696320696e666f726d6174696f6e2061626f7574206120766f7465722e2054686520766f746520696e64657820616e64206c69737420736c6f742074686174207468652063616e646964617465206077686f60207761732072656769737465726564206f7220604e6f6e6560206966207468657920617265206e6f742063757272656e746c7920726567697374657265642e2054686520746f74616c206e756d626572206f6620766f746520726f756e6473207468617420686176652068617070656e6564206f722061726520696e2070726f67726573732e20205468652063757272656e74206d656d626572736869702e205768656e2074686572652773206120766f746520676f696e67206f6e2c20746869732073686f756c64207374696c6c206265207573656420666f722020657865637574697665206d6174746572732e2054686520626c6f636b206e756d62657220287365636f6e6420656c656d656e7420696e20746865207475706c65292069732074686520626c6f636b20746861742020746865697220706f736974696f6e2069732061637469766520756e74696c202863616c63756c61746564206279207468652073756d206f662074686520626c6f636b206e756d626572207768656e2074686520206d656d6265722077617320656c656374656420616e64207468656972207465726d206475726174696f6e292e204e756d626572206f66206163636f756e747320746861742073686f756c6420636f6e737469747574652074686520636f6c6c6563746976652e20486f77206c6f6e67206561636820706f736974696f6e2069732061637469766520666f722e20486f77206c6f6e6720746f2067697665206561636820746f702063616e64696461746520746f2070726573656e74207468656d73656c7665732061667465722074686520766f746520656e64732e000000000000287510000d000000000000007a6511000c000000000000003897110038751000000000000000000048751000020000000000000000000000587510000a000000000000007a6511000c0000000000000038971100687610000000000000000000647510000100000000000000000000006c75100009000000000000007a6511000c0000000000000038971100787510000000000000000000887510000200000000000000000000009875100014000000000000007a6511000c0000000000000038971100ac7510000000000000000000bc751000020000000000000000000000cc7510000a0000000000000076341100030000000000000038971100d87510000000000000000000e8751000020000000000000000000000f87510001300000000000000196c10000900000000000000389711000c76100000000000000000001c761000030000000000000000000000586511000c00000000000000925111000e0000000000000038971100347610000000000000000000447610000200000000000000000000005476100011000000000000007a6511000c000000000000003897110068761000000000000000000078761000010000000000000000000000807610000a00000000000000763411000300000000000000389711008c76100000000000000000009c761000050000000000000000000000c47610000e0000000000000076341100030000000000000038971100d47610000000000000000000e4761000010000000000000000000000ec76100011000000000000007634110003000000000000003897110000771000000000000000000010771000010000000000000043616e646964616379426f6e64000000370000000000000001000000a30000005f7b10004e000000ad7b100014000000566f74696e67426f6e6400001d7b100042000000566f74696e67466565000000370000000000000001000000a4000000b67a10004a000000007b10001d00000050726573656e74536c617368506572566f7465723700000000000000010000009a000000527a100045000000977a10001f0000004361727279436f756e740000370000000000000001000000a5000000e4791000470000002b7a100027000000496e6163746976654772616365506572696f6400370000000000000001000000a6000000477910004c000000937910004b000000de79100006000000370000000000000001000000a7000000f5781000490000003e791000090000004d696e696d756d566f74696e674c6f636b00000037000000000000000100000099000000b67810003f0000004465636179526174696f00003700000000000000010000009c000000637710004d000000b077100041000000f177100047000000387810004a0000008278100034000000564f5445525f5345545f53495a450000370000000000000001000000a80000003f77100024000000415050524f56414c5f5345545f53495a45000000370000000000000001000000a9000000187710002700000020546865206368756e6b2073697a65206f662074686520617070726f76616c20766563746f722e20546865206368756e6b2073697a65206f662074686520766f74657220766563746f722e20446563617920666163746f72206f6620776569676874207768656e206265696e6720616363756d756c617465642e2049742073686f756c64207479706963616c6c792062652073657420746f205f5f6174206c656173745f5f20606d656d626572736869705f73697a65202d316020746f206b6565702074686520636f6c6c656374697665207365637572652e205768656e2073657420746f20604e602c20697420696e64696361746573206028312f4e295e7460206f66207374616b656420697320646563617965642061742077656967687420696e6372656d656e742073746570206074602e20302077696c6c20726573756c7420696e206e6f20776569676874206265696e6720616464656420617420616c6c20286e6f726d616c20617070726f76616c20766f74696e67292e204120726561736f6e61626c652064656661756c742076616c75652069732032342e204d696e696d756d2061626f757420746861742063616e206265207573656420617320746865206c6f636b65642076616c756520666f7220766f74696e672e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e204120726561736f6e61626c652064656661756c742076616c756520697320313030302e20486f77206d616e7920766f746520696e6469636573206e65656420746f20676f20627920616674657220612074617267657420766f7465722773206c61737420766f7465206265666f726520746865792063616e2062652072656170656420696620746865697220617070726f76616c7320617265206d6f6f742e204120726561736f6e61626c652064656661756c742076616c756520697320312e20486f77206d616e792072756e6e6572732d75702073686f756c64206861766520746865697220617070726f76616c73207065727369737420756e74696c20746865206e65787420766f74652e204120726561736f6e61626c652064656661756c742076616c756520697320322e205468652070756e6973686d656e742c2070657220766f7465722c20696620796f752070726f7669646520616e20696e76616c69642070726573656e746174696f6e2e204120726561736f6e61626c652064656661756c742076616c756520697320312e2054686520616d6f756e74206f662066656520706169642075706f6e206561636820766f7465207375626d697373696f6e2c20756e6c6573732069662074686579207375626d69742061205f686f6c655f20696e64657820616e64207265706c6163652069742e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f2062652061626c6520746f207375626d697420766f7465732e20486f77206d7563682073686f756c64206265206c6f636b656420757020696e206f7264657220746f207375626d6974206f6e6527732063616e6469646163792e204120726561736f6e61626c652064656661756c742076616c756520697320392e000000387d110028000000dc7b1000440000000e010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f656c656374696f6e732f7372632f6c69622e7273dc7b1000440000000e01000001000000436f756e63696c2050726f787963616e6e6f74207265617020647572696e672070726573656e746174696f6e20706572696f64766f746520696e646578206e6f742063757272656e7463616e6e6f74207265617020647572696e6720677261636520706572696f6474617267657420666f7220696e616374697669747920636c65616e7570206d757374206265206163746976657265706f72746572206d757374206265206120766f746572696e76616c6964207265706f7274657220696e646578696e76616c69642074617267657420696e646578626164207265706f7274657220696e6465786261642074617267657420696e64657872657472616374696f6e20696e64657820696e76616c696472657472616374696f6e20696e646578206d69736d6174636863616e6e6f742072657472616374207768656e2070726573656e74696e6763616e6e6f742072657472616374206e6f6e2d766f7465726475706c69636174652063616e646964617465207375626d697373696f6e696e76616c69642063616e64696461746520736c6f7463616e64696461746520686173206e6f7420656e6f7567682066756e647363616e6e6f742070726573656e74206f757473696465206f662070726573656e746174696f6e20706572696f64696e646578206e6f742063757272656e747374616b65206465706f736974656420746f2070726573656e742077696e6e657220616e6420626520616464656420746f206c6561646572626f6172642073686f756c64206265206e6f6e2d7a65726f6c6561646572626f617264206d757374206578697374207768696c652070726573656e742070686173652061637469766570726573656e746572206d75737420686176652073756666696369656e7420736c61736861626c652066756e647370726573656e7465642063616e646964617465206d7573742062652063757272656e7463616e646964617465206e6f7420776f72746879206f66206c6561646572626f61726463616e646964617465206d757374206e6f7420666f726d2061206475706c696361746564206d656d62657220696620656c65637465646475706c69636174652070726573656e746174696f6e696e636f727265637420746f74616c6e6f20617070726f76616c206368616e67657320647572696e672070726573656e746174696f6e20706572696f64696e636f727265637420766f746520696e646578616d6f756e74206f662063616e6469646174657320746f207265636569766520617070726f76616c20766f7465732073686f756c64206265206e6f6e2d7a65726f616d6f756e74206f662063616e64696461746520766f7465732063616e6e6f742065786365656420616d6f756e74206f662063616e646964617465736c6f636b65642076616c7565206d757374206265206d6f7265207468616e206c696d697477726f6e6720766f74657220696e6465786e657720766f746572206d75737420686176652073756666696369656e742066756e647320746f207061792074686520626f6e64696e76616c696420766f74657220696e646578000000000000e442110008000000000000008881100001000000000000000000000090811000010000000000000000000000988110000800000000000000c8151100010000000000000000000000a0811000010000000000000000000000a88110000700000000000000b0811000030000000000000000000000c8811000010000000000000000000000d08110000500000000000000c8151100010000000000000000000000d8811000010000000000000000000000e08110000800000000000000c8151100010000000000000000000000e88110000100000000000000ccb710000d000000b98210000e0000005370656e64696e677f8210003a0000004177617264656400ccb710000d0000001144110007000000d0431100090000005f821000200000004275726e740000003c82100023000000526f6c6c6f766572f08110004c000000205370656e64696e67206861732066696e69736865643b20746869732069732074686520616d6f756e74207468617420726f6c6c73206f76657220756e74696c206e657874207370656e642e20536f6d65206f66206f75722066756e64732068617665206265656e206275726e742e20536f6d652066756e64732068617665206265656e20616c6c6f63617465642e205765206861766520656e6465642061207370656e6420706572696f6420616e642077696c6c206e6f7720616c6c6f636174652066756e64732e204e65772070726f706f73616c2e53657373696f6e2056616c696461746f72734772616e64706146696e616c697479205374616c6c656454726561737572792050726f706f73616c730000387d1100280000001c831000430000007f000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f74726561737572792f7372632f6c69622e72734469676573744974656d206e6f7420657175616c0000000000a08310001200000000000000b4831000010000000000000000000000cc83100001000000000000007265706f72745f6d69736265686176696f72000000000000ed8310000700000000000000e7ea100007000000d483100019000000205265706f727420736f6d65206d69736265686176696f722e5f7265706f72744772616e64706146696e616c697479000000000070aa10000b0000000000000000000000238a11002300000000000000000000000000000000000000000000000000000000000000389711008897100000000000000000006c8610000100000000000000010000000000000074861000050000000000000000000000798610001b0000000000000000000000000000000000000000000000000000000000000038971100948610000000000000000000a486100001000000000000000100000000000000ac8610000d0000000000000000000000b9861000230000000000000000000000000000000000000000000000000000000000000038971100b48e10000000000000000000dc86100001000000000000000000000000000000e48610000a0000000000000000000000925111000e0000000000000000000000000000000000000000000000000000000000000038971100788710000000000000000000f086100001000000000000000000000000000000f8861000070000000000000000000000ff8610002000000000000000000000000000000000000000000000000000000000000000389711002087100000000000000000003087100001000000000000000000000000000000388710000c0000000000000000000000448710000500000000000000000000000000000000000000000000000000000000000000389711004c87100000000000000000005c871000020000000000000001000000000000006c8710000c00000001010000000000004487100005000000000000009f8d11000c000000000000000000000000000000000000003897110078871000000000000000000088871000010000000000000000000000308910001b000000537461746553746f72656453746174653c543a3a426c6f636b4e756d6265723e370000000000000001000000aa0000000c8910002400000050656e64696e674368616e676553746f72656450656e64696e674368616e67653c543a3a426c6f636b4e756d6265723edb881000310000004e657874466f726365640000ac8810002f0000005374616c6c656428543a3a426c6f636b4e756d6265722c20543a3a426c6f636b4e756d6265722900370000000000000001000000a1000000888810002400000043757272656e7453657449645365744964000000370000000000000001000000ab00000000881000570000005788100031000000536574496453657373696f6e3700000000000000010000004f00000090871000700000002041206d617070696e672066726f6d206772616e6470612073657420494420746f2074686520696e646578206f6620746865202a6d6f737420726563656e742a2073657373696f6e20666f7220776869636820697473206d656d62657273207765726520726573706f6e7369626c652e20546865206e756d626572206f66206368616e6765732028626f746820696e207465726d73206f66206b65797320616e6420756e6465726c79696e672065636f6e6f6d696320726573706f6e736962696c69746965732920696e20746865202273657422206f66204772616e6470612076616c696461746f72732066726f6d2067656e657369732e20607472756560206966207765206172652063757272656e746c79207374616c6c65642e206e65787420626c6f636b206e756d6265722077686572652077652063616e20666f7263652061206368616e67652e2050656e64696e67206368616e67653a20287369676e616c65642061742c207363686564756c6564206368616e6765292e205374617465206f66207468652063757272656e7420617574686f72697479207365742e205468652063757272656e7420617574686f72697479207365742e000000000078891000080000000000000080891000020000000000000000000000b08910000a000000000000007365745f6b65797300000000dabb10000400000000000000098b10000700000000000000108b10000500000000000000e7ea100007000000008a100039000000398a100048000000818a1000310000003897110000000000b28a1000350000003897110000000000c54d11000b000000e78a100022000000f34d110016000000d84d11000c0000002053657473207468652073657373696f6e206b6579287329206f66207468652066756e6374696f6e2063616c6c657220746f20606b6579602e20416c6c6f777320616e206163636f756e7420746f20736574206974732073657373696f6e206b6579207072696f7220746f206265636f6d696e6720612076616c696461746f722e205468697320646f65736e27742074616b652065666665637420756e74696c20746865206e6578742073657373696f6e2e20546865206469737061746368206f726967696e206f6620746869732066756e6374696f6e206d757374206265207369676e65642e202d204f286c6f67206e2920696e206e756d626572206f66206163636f756e74732e543a3a4b65797370726f6f6653657373696f6e00000000543511000a0000000000000000000000848d1000130000000000000000000000000000000000000000000000000000000000000038971100889710000000000000000000988d100001000000000000000100000000000000a08d10000c00000000000000000000009f8d11000c0000000000000000000000000000000000000000000000000000000000000038971100189710000000000000000000ac8d100001000000000000000100000000000000b48d10000d0000000000000000000000f7431100040000000000000000000000000000000000000000000000000000000000000038971100c48d10000000000000000000d48d100002000000000000000100000000000000e48d10000a0000000000000000000000ee8d10001e00000000000000000000000000000000000000000000000000000000000000389711008897100000000000000000000c8e1000020000000000000001000000000000001c8e10001200000000000000000000002e8e1000080000000000000000000000000000000000000000000000000000000000000038971100889710000000000000000000388e100003000000000000000100000000000000508e1000080000000204010000000000e7ea10000700000000000000588e10000e00000000000000098b1000070000000000000038971100688e10000000000000000000788e100004000000000000000000000000000000988e1000080000000204010000000000e7ea10000700000000000000a08e10001400000000000000588e10000e0000000000000038971100b48e10000000000000000000c48e10000400000000000000000000005665633c543a3a56616c696461746f7249643e008b9110001f00000043757272656e74496e6465786d9110001e0000005175657565644368616e6765640000003700000000000000010000004f000000f69010004e00000044911000290000005175657565644b6579735665633c28543a3a56616c696461746f7249642c20543a3a4b657973293e6f9010004f000000be9010003800000044697361626c656456616c696461746f72735665633c7533323e000002901000200000003897110000000000229010004d0000004e6578744b657973543a3a56616c696461746f72496400003700000000000000010000004f000000db8f10002700000038971100000000002d8f100056000000838f1000580000004b65794f776e6572284b65795479706549642c205665633c75383e293700000000000000010000004f000000e48e10004900000038971100000000002d8f100056000000838f10005800000020546865206f776e6572206f662061206b65792e20546865207365636f6e64206b65792069732074686520604b657954797065496460202b2074686520656e636f646564206b65792e20546865206669727374206b657920697320616c77617973206044454455505f4b45595f5052454649586020746f206861766520616c6c20746865206461746120696e207468652073616d65206272616e6368206f662074686520747269652e20486176696e6720616c6c206461746120696e207468652073616d65206272616e63682073686f756c642070726576656e7420736c6f77696e6720646f776e206f7468657220717565726965732e20546865206e6578742073657373696f6e206b65797320666f7220612076616c696461746f722e20496e6469636573206f662064697361626c65642076616c696461746f72732e205468652073657420697320636c6561726564207768656e20606f6e5f73657373696f6e5f656e64696e67602072657475726e732061206e657720736574206f66206964656e7469746965732e2054686520717565756564206b65797320666f7220746865206e6578742073657373696f6e2e205768656e20746865206e6578742073657373696f6e20626567696e732c207468657365206b6579732077696c6c206265207573656420746f2064657465726d696e65207468652076616c696461746f7227732073657373696f6e206b6579732e20547275652069662074686520756e6465726c79696e672065636f6e6f6d6963206964656e746974696573206f7220776569676874696e6720626568696e64207468652076616c696461746f727320686173206368616e67656420696e20746865207175657565642076616c696461746f72207365742e2043757272656e7420696e646578206f66207468652073657373696f6e2e205468652063757272656e7420736574206f662076616c696461746f72732e000000000000e49110001000000000000000f4911000050000000000000038971100fc91100000000000000000000c921000020000000000000044454455505f4b45595f505245464958265b75385d000000370000000000000001000000ac0000001c92100059000000759210000d0000002055736564206173206669727374206b657920666f7220604e6578744b6579736020616e6420604b65794f776e65726020746f2070757420616c6c20746865206461746120696e746f207468652073616d65206272616e6368206f662074686520747269652e3a73657373696f6e3a6b65797353657373696f6e204e6578744b6579730000000000249310000d000000000000003493100002000000000000000000000064931000090000000000000000000000ac9310000f00000000000000bc931000010000000000000000000000d49310000700000000000000000000000c9410001000000000000000bc9310000100000000000000000000001c941000080000000000000070726f706f73655f7370656e64000000000000005f5511000500000000000000645511001500000000000000fa9510000b000000000000004b22110023000000289510004b000000739510004d000000c0951000150000003897110000000000c54d11000b000000d04d110008000000f111110019000000d595100025000000d84d11000c00000072656a6563745f70726f706f73616c00000000001d9510000b00000000000000e9cd100016000000de9410003f0000003897110000000000c54d11000b000000d04d110008000000f111110019000000514e110010000000d84d11000c000000617070726f76655f70726f706f73616c5c94100057000000b39410002b0000003897110000000000c54d11000b000000d04d110008000000f111110019000000b712110011000000d84d11000c00000020417070726f766520612070726f706f73616c2e2041742061206c617465722074696d652c207468652070726f706f73616c2077696c6c20626520616c6c6f636174656420746f207468652062656e656669636961727920616e6420746865206f726967696e616c206465706f7369742077696c6c2062652072657475726e65642e2052656a65637420612070726f706f736564207370656e642e20546865206f726967696e616c206465706f7369742077696c6c20626520736c61736865642e70726f706f73616c5f69642050757420666f727761726420612073756767657374696f6e20666f72207370656e64696e672e2041206465706f7369742070726f706f7274696f6e616c20746f207468652076616c756520697320726573657276656420616e6420736c6173686564206966207468652070726f706f73616c2069732072656a65637465642e2049742069732072657475726e6564206f6e6365207468652070726f706f73616c20697320617761726465642e202d204f6e65204442206368616e67652c206f6e6520657874726120444220656e7472792e62656e656669636961727954726561737572790000000000000008d010000d0000000000000000000000ccb710000d000000000000000000000000000000000000000000000000000000000000003897110018971000000000000000000028971000010000000000000001000000000000009acf1000090000000101000000000000ccb710000d000000000000003097100024000000000000000000000000000000000000003897110054971000000000000000000064971000010000000000000000000000000000006c97100009000000000000000000000075971000120000000000000000000000000000000000000000000000000000000000000038971100889710000000000000000000989710000100000000000000010000003700000000000000010000009c000000fd9710002900000050726f706f73616c3c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3700000000000000010000004f000000de9710001f000000417070726f76616c735665633c50726f706f73616c496e6465783e0037000000000000000100000050000000a09710003e0000002050726f706f73616c20696e646963657320746861742068617665206265656e20617070726f76656420627574206e6f742079657420617761726465642e2050726f706f73616c7320746861742068617665206265656e206d6164652e204e756d626572206f662070726f706f73616c7320746861742068617665206265656e206d6164652e000000000000089910000c00000000000000149910000700000000000000389711001c99100000000000000000002c9910000200000000000000000000003c99100013000000000000007a6511000c000000000000003897110050991000000000000000000060991000010000000000000000000000689910000b00000000000000925111000e0000000000000038971100749910000000000000000000849910000100000000000000000000008c991000040000000000000014991000070000000000000038971100909910000000000000000000a0991000010000000000000050726f706f73616c426f6e645065726d696c6c00370000000000000001000000ad000000609a100055000000b59a10004400000050726f706f73616c426f6e644d696e696d756d00370000000000000001000000990000000e9a1000520000005370656e64506572696f6400370000000000000001000000ae000000ec991000220000004275726e370000000000000001000000af000000a8991000440000002050657263656e74616765206f662073706172652066756e64732028696620616e7929207468617420617265206275726e7420706572207370656e6420706572696f642e20506572696f64206265747765656e2073756363657373697665207370656e64732e204d696e696d756d20616d6f756e74206f662066756e647320746861742073686f756c6420626520706c6163656420696e2061206465706f73697420666f72206d616b696e6720612070726f706f73616c2e204672616374696f6e206f6620612070726f706f73616c27732076616c756520746861742073686f756c6420626520626f6e64656420696e206f7264657220746f20706c616365207468652070726f706f73616c2e20416e2061636365707465642070726f706f73616c2067657473207468657365206261636b2e20412072656a65637465642070726f706f73616c20646f6573206e6f742e4772616e64706146696e616c6974792050656e64696e674368616e67654772616e64706146696e616c697479205374617465496e636f6e73697374656e74207374617465202d20636f756c646e277420736574746c6520696d62616c616e636520666f722066756e6473207370656e7420627920747265617375727953657373696f6e205175657565644b65797300590000000800000004000000b0000000b10000000000000000000000b20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000590000000800000004000000b0000000b10000000000000000000000b20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000590000000800000004000000b3000000b10000000000000000000000b40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000590000000800000004000000b3000000b10000000000000000000000b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004772616e64706146696e616c697479204e657874466f72636564636f6465206973206e6f7420666f756e647072697374696e6520636f6465206973206e6f7420666f756e647468657265206973206e6f7420656e6f7567682067617320666f722073746f72696e672074686520636f646553657373696f6e204b65794f776e6572000000f0a0100048000000a10a00000e000000f0a01000480000009b0a00000a00000080a0100019000000a0a01000430000003401000009000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f70687261676d656e2f7372632f6c69622e7273000000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e72733897110000000000391411000200000060a110007c000000dca11000490000007900000006000000657865632e7072656661625f6d6f64756c652e696e697469616c2063616e27742062652067726561746572207468616e20657865632e7072656661625f6d6f64756c652e6d6178696d756d3b0a09090909090974687573204d656d6f72793a3a6e6577206d757374206e6f74206661696c3b0a0909090909097165642f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f7761736d2f6d6f642e72736e6f206173736f6369617465642076616c696461746f7220494420666f72206163636f756e742e72656769737465726564206475706c6963617465206b65791c831000430000007f0000000100000050726f706f73657227732062616c616e636520746f6f206c6f774e6f2070726f706f73616c206174207468617420696e64657866696e616c6e756d417574686f727368697020417574686f7237000000000000000100000038000000387d110028000000e8a210003f000000bf000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f626162652f7372632f6c69622e727300e8a210003f000000bf0000000100000073657269616c697a656420617267732073686f756c642062652070726f7669646564206279207468652072756e74696d653b0a090909636f72726563746c792073657269616c697a656420646174612073686f756c6420626520646573657269616c697a61626c653b0a090909716564387d110028000000607d110050000000370100000900000065706f636820696e64696365732077696c6c206e6576657220726561636820325e3634206265666f726520746865206465617468206f662074686520756e6976657273653b207165640000000000000038a410000a0000000000000044a410000100000000000000000000005ca4100001000000000000007365745f756e636c65730000000000007da410000a0000000000000087a410000e00000064a41000190000002050726f76696465206120736574206f6620756e636c65732e6e65775f756e636c65735665633c543a3a4865616465723e417574686f72736869700000000000a8a51000060000000000000000000000aea510003a0000000000000000000000000000000000000000000000000000000000000038971100e8a510000000000000000000f8a510000100000000000000010000000000000000a610000600000000000000000000000b4e11000c000000000000000000000000000000000000000000000000000000000000003897110008a61000000000000000000018a610000100000000000000000000000000000020a610000c0000000000000000000000f74311000400000000000000000000000000000000000000000000000000000000000000389711002ca6100000000000000000003ca61000010000000000000001000000556e636c65735665633c556e636c65456e7472794974656d3c543a3a426c6f636b4e756d6265722c20543a3a486173682c20543a3a4163636f756e7449643e3e370000000000000001000000500000008ca6100007000000417574686f7200003700000000000000010000004f00000073a6100019000000446964536574556e636c65733700000000000000010000004f00000044a610002f000000205768657468657220756e636c6573207765726520616c72656164792073657420696e207468697320626c6f636b2e20417574686f72206f662063757272656e7420626c6f636b2e20556e636c6573417574686f727368697020556e636c6573556e636c657320616c72656164792073657420696e20626c6f636b2e756e636c6520616c726561647920696e636c75646564756e636c652069732067656e65736973756e636c6520697320746f6f206869676820696e20636861696e756e636c6520706172656e74206e6f7420696e20636861696e756e636c65206e6f7420726563656e7420656e6f75676820746f20626520696e636c756465644261626500000000005caa10000a000000000000000000000076f91000030000000000000000000000000000000000000000000000000000000000000038971100e4aa1000000000000000000068aa10000100000000000000010000000000000070aa10000b00000000000000000000007baa1000270000000000000000000000000000000000000000000000000000000000000038971100a4aa10000000000000000000b4aa100001000000000000000100000000000000bcaa10000b000000000000000000000076f91000030000000000000000000000000000000000000000000000000000000000000038971100e4aa10000000000000000000c8aa100002000000000000000100000000000000d8aa10000b000000000000000000000076f91000030000000000000000000000000000000000000000000000000000000000000038971100e4aa10000000000000000000f4aa100001000000000000000100000000000000fcaa10000a000000000000000000000006ab100008000000000000000000000000000000000000000000000000000000000000003897110070ab1000000000000000000010ab10000a00000000000000010000000000000060ab10000e000000000000000000000006ab100008000000000000000000000000000000000000000000000000000000000000003897110070ab1000000000000000000080ab10000100000000000000010000000000000088ab10000c00000000000000000000007634110003000000000000000000000000000000000000000000000000000000000000003897110094ab10000000000000000000a4ab100009000000000000000100000000000000ecab1000110000000101000000000000763411000300000000000000fdab10000d00000000000000000000000000000000000000389711000cac1000000000000000000038971100000000000000000001000000000000001cac10000b000000000000000000000027ac100008000000000000000000000000000000000000000000000000000000000000003897110030ac1000000000000000000040ac100002000000000000000000000045706f6368496e64657800008bb0100015000000417574686f7269746965735665633c28417574686f7269747949642c2042616265417574686f72697479576569676874293e00003700000000000000010000005000000070b010001b00000047656e65736973536c6f74000eb010003e0000004cb010002400000043757272656e74536c6f7400370000000000000001000000ab000000f9af10001500000052616e646f6d6e6573735b75383b2033325d000033ae10002e000000389711000000000061ae10000b00000038971100000000006cae100041000000adae10003e000000ebae10004500000030af10004500000075af100041000000b6af1000430000004e65787452616e646f6d6e6573730000370000000000000001000000b50000001cae1000170000005365676d656e74496e6465783700000000000000010000009c000000d7ac10001f0000003897110000000000f6ac10003d00000033ad10004000000073ad100025000000389711000000000098ad10003b000000d3ad10004200000015ae100007000000556e646572436f6e737472756374696f6e5665633c5b75383b2033325d3e000037000000000000000100000050000000496e697469616c697a65644d61796265567266003700000000000000010000004f00000050ac10004000000090ac1000470000002054656d706f726172792076616c75652028636c656172656420617420626c6f636b2066696e616c697a6174696f6e292077686963682069732060536f6d6560206966207065722d626c6f636b20696e697469616c697a6174696f6e2068617320616c7265616479206265656e2063616c6c656420666f722063757272656e7420626c6f636b2e2052616e646f6d6e65737320756e64657220636f6e737472756374696f6e2e205765206d616b6520612074726164656f6666206265747765656e2073746f7261676520616363657373657320616e64206c697374206c656e6774682e2057652073746f72652074686520756e6465722d636f6e737472756374696f6e2072616e646f6d6e65737320696e207365676d656e7473206f6620757020746f2060554e4445525f434f4e535452554354494f4e5f5345474d454e545f4c454e475448602e204f6e63652061207365676d656e7420726561636865732074686973206c656e6774682c20776520626567696e20746865206e657874206f6e652e20576520726573657420616c6c207365676d656e747320616e642072657475726e20746f206030602061742074686520626567696e6e696e67206f662065766572792065706f63682e204e6578742065706f63682072616e646f6d6e6573732e205468652065706f63682072616e646f6d6e65737320666f7220746865202a63757272656e742a2065706f63682e20232053656375726974792054686973204d555354204e4f54206265207573656420666f722067616d626c696e672c2061732069742063616e20626520696e666c75656e6365642062792061206d616c6963696f75732076616c696461746f7220696e207468652073686f7274207465726d2e204974204d4159206265207573656420696e206d616e792063727970746f677261706869632070726f746f636f6c732c20686f77657665722c20736f206c6f6e67206173206f6e652072656d656d626572732074686174207468697320286c696b652065766572797468696e6720656c7365206f6e2d636861696e29206974206973207075626c69632e20466f72206578616d706c652c2069742063616e20626520757365642077686572652061206e756d626572206973206e656564656420746861742063616e6e6f742068617665206265656e2063686f73656e20627920616e206164766572736172792c20666f7220707572706f7365732073756368206173207075626c69632d636f696e207a65726f2d6b6e6f776c656467652070726f6f66732e2043757272656e7420736c6f74206e756d6265722e2054686520736c6f74206174207768696368207468652066697273742065706f63682061637475616c6c7920737461727465642e2054686973206973203020756e74696c2074686520666972737420626c6f636b206f662074686520636861696e2e2043757272656e742065706f636820617574686f7269746965732e2043757272656e742065706f636820696e6465782e0000000010b110000d0000000000000076f9100003000000000000003897110020b11000000000000000000030b1100002000000000000000000000040b110001100000000000000a3e0100009000000000000003897110054b11000000000000000000064b11000050000000000000045706f63684475726174696f6e000000370000000000000001000000b6000000bcb2100043000000ffb210003f0000004578706563746564426c6f636b54696d65000000370000000000000001000000b70000008cb1100041000000cdb110004400000011b210004100000052b210004200000094b210002800000020546865206578706563746564206176657261676520626c6f636b2074696d6520617420776869636820424142452073686f756c64206265206372656174696e6720626c6f636b732e2053696e636520424142452069732070726f626162696c6973746963206974206973206e6f74207472697669616c20746f20666967757265206f7574207768617420746865206578706563746564206176657261676520626c6f636b2074696d652073686f756c64206265206261736564206f6e2074686520736c6f74206475726174696f6e20616e642074686520736563757269747920706172616d657465722060636020287768657265206031202d20636020726570726573656e7473207468652070726f626162696c697479206f66206120736c6f74206265696e6720656d707479292e20546865206e756d626572206f66202a2a736c6f74732a2a207468617420616e2065706f63682074616b65732e20576520636f75706c652073657373696f6e7320746f2065706f6368732c20692e652e2077652073746172742061206e65772073657373696f6e206f6e636520746865206e65772065706f636820626567696e732e756e636c6573303074696d657374616d702073657420696e20626c6f636b20646f65736e2774206d6174636820736c6f7420696e207365616c4e6f206f74686572206572726f72732061726520616363657074656420616674657220616e2068617264206572726f7221496e686572656e7420776974682073616d65206964656e74696669657220616c726561647920657869737473215468657265206973206f6e6c79206f6e6520666174616c206572726f723b20716564005900000008000000040000009d0000003a65787472696e7369635f696e64657800000000e4421100080000000000000020b5100004000000000000000000000040b5100002000000000000000000000050b51000050000000000000058b5100005000000000000000000000080b5100002000000000000000000000090b51000080000000000000048ea100001000000000000000000000098b51000010000000000000000000000a0b510000b0000000000000048ea1000010000000000000000000000acb51000010000000000000000000000664311000800000000000000b4b51000020000000000000000000000c4b51000010000000000000000000000ccb510000e00000000000000b4b51000020000000000000000000000dcb510000100000000000000d043110009000000ccb710000d000000d9431100040000005eb710000b00000069b7100053000000bcb7100010000000566f746564000000d043110009000000d943110004000000f7431100040000005eb710000b0000005eb710000b000000d6b610004200000018b7100046000000417070726f766564a5b6100031000000446973617070726f7665640070b6100035000000d943110004000000f7431100040000002fb61000410000004d656d62657245786563757465640000e4b510004b00000020412073696e676c65206d656d6265722064696420736f6d6520616374696f6e3b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e207761732065786563757465643b2060626f6f6c6020697320747275652069662072657475726e656420776974686f7574206572726f722e2041206d6f74696f6e20776173206e6f7420617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2077617320617070726f76656420627920746865207265717569726564207468726573686f6c642e2041206d6f74696f6e2028676976656e20686173682920686173206265656e20766f746564206f6e20627920676976656e206163636f756e742c206c656176696e6720612074616c6c79202879657320766f74657320616e64206e6f20766f74657320676976656e20726573706563746976656c7920617320604d656d626572436f756e7460292e4d656d626572436f756e742041206d6f74696f6e2028676976656e20686173682920686173206265656e2070726f706f7365642028627920676976656e206163636f756e742920776974682061207468726573686f6c642028676976656e20604d656d626572436f756e7460292e50726f706f73616c496e64657853797374656d204e756d62657253797374656d2045787472696e73696373526f6f74496e7374616e636531436f6c6c656374697665204d656d62657273496e7374616e636532436f6c6c656374697665204d656d6265727353797374656d2044696765737453797374656d20426c6f636b4861736853797374656d204163636f756e744e6f6e6365000000387d1100280000007cb8100041000000e9000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f73797374656d2f7372632f6c69622e7273000000387d110028000000d8b810004500000083000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6c6c6563746976652f7372632f6c69622e727353797374656d20506172656e744861736853797374656d2052616e646f6d4d6174657269616c0080b9100048000000a10a00000e00000053797374656d204576656e747353797374656d204576656e74546f70696373000000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727300000000d0ba10000a0000000000000038971100000000000000000000000000dcba1000010000000000000000000000e4ba10000600000000000000ecba100001000000000000000000000004bb10000100000000000000000000000cbb10000e000000000000001cbb100001000000000000000000000034bb10000100000000000000000000003cbb1000080000000000000044bb10000100000000000000000000005cbb100001000000000000000000000064bb10000b0000000000000070bb100001000000000000000000000088bb100001000000000000000000000090bb10000c000000000000009cbb1000010000000000000000000000b4bb1000010000000000000066696c6c5f626c6f636b00008bbc10004800000072656d61726b00000000000084bc10000700000000000000e7ea10000700000069bc10001b0000007365745f686561705f706167657300000000000064bc1000050000000000000076f910000300000025bc10003f0000007365745f636f646500000000fc2011000300000000000000e7ea10000700000013bc1000120000007365745f73746f72616765000000000001bc1000050000000000000006bc10000d000000e6bb10001b0000006b696c6c5f73746f7261676500000000dabb10000400000000000000debb100008000000bcbb10001e000000204b696c6c20736f6d65206974656d732066726f6d2073746f726167652e6b6579735665633c4b65793e2053657420736f6d65206974656d73206f662073746f726167652e6974656d735665633c4b657956616c75653e2053657420746865206e657720636f64652e2053657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e7061676573204d616b6520736f6d65206f6e2d636861696e2072656d61726b2e5f72656d61726b20412062696720646973706174636820746861742077696c6c20646973616c6c6f7720616e79206f74686572207472616e73616374696f6e20746f20626520696e636c756465642e53797374656d0000000000000004c210000c00000001010000000000000b4e11000c0000000000000010c21000080000000000000000000000000000000000000038971100e8d21000000000000000000018c210000100000000000000010000000000000020c210000e0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711006cc21000000000000000000030c210000100000000000000000000000000000038c210001300000000000000000000004bc210000600000000000000000000000000000000000000000000000000000000000000389711006cc21000000000000000000054c21000010000000000000000000000000000005cc21000100000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711006cc2100000000000000000007cc210000100000000000000000000000000000084c2100014000000000000000000000098c21000100000000000000000000000000000000000000000000000000000000000000038971100a8c210000000000000000000b8c2100002000000000000000100000000000000c8c21000090000000101000000000000925111000e000000000000007c4f110007000000000000000000000000000000000000003897110078c310000000000000000000d4c2100001000000000000000100000000000000dcc210000d0000000101000000000000763411000300000000000000e7ea1000070000000000000000000000000000000000000038971100ecc210000000000000000000fcc210000100000000000000010000000000000004c310000e000000000000000000000012c3100012000000000000000000000000000000000000000000000000000000000000003897110024c31000000000000000000034c310000200000000000000010000000000000044c31000060000000000000000000000925111000e0000000000000000000000000000000000000000000000000000000000000038971100e8d2100000000000000000004cc310000100000000000000010000000000000054c310000a00000000000000000000007c4f110007000000000000000000000000000000000000000000000000000000000000003897110078c31000000000000000000060c310000100000000000000010000000000000068c310000e00000000000000000000007c4f110007000000000000000000000000000000000000000000000000000000000000003897110078c31000000000000000000088c310000100000000000000010000000000000090c3100006000000000000000000000096c310000b0000000000000000000000000000000000000000000000000000000000000038971100a4c310000000000000000000b4c3100001000000000000000100000000000000bcc31000060000000000000000000000c2c31000230000000000000000000000000000000000000000000000000000000000000038971100e8c310000000000000000000f8c310000100000000000000010000000000000000c410000a00000000000000000000000ac410000a0000000000000000000000000000000000000000000000000000000000000038971100e8d21000000000000000000014c41000010000000000000001000000000000001cc410000b000000020101000000000027c4100002000000000000007c4f1100070000000000000029c41000210000000000000038971100f8d2100000000000000000004cc410000d00000000000000010000004163636f756e744e6f6e6365543a3a496e646578f9ca10001f00000045787472696e736963436f756e740000cbca10002e000000416c6c45787472696e7369637357656967687457656967687400000086ca100045000000416c6c45787472696e736963734c656e3700000000000000010000004f00000036ca1000500000004e6578745765696768744d756c7469706c6965725765696768744d756c7469706c696572370000000000000001000000ab000000c2c91000590000001bca10001b000000426c6f636b486173680000009cc910002600000045787472696e73696344617461000000370000000000000001000000510000004dc910004f00000052616e646f6d4d6174657269616c2869382c205665633c543a3a486173683e29370000000000000001000000b800000090c8100069000000f9c81000540000004e756d62657200004ec8100042000000506172656e7448617368000032c810001c00000045787472696e73696373526f6f740000370000000000000001000000b9000000edc71000450000004469676573744469676573744f663c543e00000037000000000000000100000050000000b1c710003c0000004576656e74735665633c4576656e745265636f72643c543a3a4576656e742c20543a3a486173683e3e000000370000000000000001000000ba00000089c71000280000004576656e74436f756e744576656e74496e6465785bc710002e0000004576656e74546f7069637328295665633c28543a3a426c6f636b4e756d6265722c204576656e74496e646578293e0000b4c4100049000000fdc4100025000000389711000000000022c510004b0000006dc510002a000000389711000000000097c5100054000000ebc51000510000003cc6100039000000389711000000000075c6100053000000c8c61000530000001bc7100040000000204d617070696e67206265747765656e206120746f7069632028726570726573656e74656420627920543a3a486173682920616e64206120766563746f72206f6620696e6465786573206f66206576656e747320696e2074686520603c4576656e74733c543e3e60206c6973742e20546865206669727374206b657920736572766573206e6f20707572706f73652e2054686973206669656c64206973206465636c6172656420617320646f75626c655f6d6170206a75737420666f7220636f6e76656e69656e6365206f66207573696e67206072656d6f76655f707265666978602e20416c6c20746f70696320766563746f727320686176652064657465726d696e69737469632073746f72616765206c6f636174696f6e7320646570656e64696e67206f6e2074686520746f7069632e205468697320616c6c6f7773206c696768742d636c69656e747320746f206c6576657261676520746865206368616e67657320747269652073746f7261676520747261636b696e67206d656368616e69736d20616e6420696e2063617365206f66206368616e67657320666574636820746865206c697374206f66206576656e7473206f6620696e7465726573742e205468652076616c756520686173207468652074797065206028543a3a426c6f636b4e756d6265722c204576656e74496e646578296020626563617573652069662077652075736564206f6e6c79206a7573742074686520604576656e74496e64657860207468656e20696e20636173652069662074686520746f70696320686173207468652073616d6520636f6e74656e7473206f6e20746865206e65787420626c6f636b206e6f206e6f74696669636174696f6e2077696c6c20626520747269676765726564207468757320746865206576656e74206d69676874206265206c6f73742e20546865206e756d626572206f66206576656e747320696e2074686520604576656e74733c543e60206c6973742e204576656e7473206465706f736974656420666f72207468652063757272656e7420626c6f636b2e20446967657374206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2045787472696e7369637320726f6f74206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e2048617368206f66207468652070726576696f757320626c6f636b2e205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e20536572696573206f6620626c6f636b20686561646572732066726f6d20746865206c61737420383120626c6f636b73207468617420616374732061732072616e646f6d2073656564206d6174657269616c2e205468697320697320617272616e67656420617320612072696e6720627566666572207769746820746865206069386020707265666978206265696e672074686520696e64657820696e746f20746865206056656360206f6620746865206f6c6465737420686173682e2045787472696e73696373206461746120666f72207468652063757272656e7420626c6f636b20286d61707320616e2065787472696e736963277320696e64657820746f206974732064617461292e204d6170206f6620626c6f636b206e756d6265727320746f20626c6f636b206861736865732e20546865206e65787420776569676874206d756c7469706c6965722e20546869732073686f756c6420626520757064617465642061742074686520656e64206f66206561636820626c6f636b206261736564206f6e207468652073617475726174696f6e206c6576656c2028776569676874292e20546f74616c206c656e6774682028696e2062797465732920666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2077656967687420666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e20546f74616c2065787472696e7369637320636f756e7420666f72207468652063757272656e7420626c6f636b2e2045787472696e73696373206e6f6e636520666f72206163636f756e74732e496e7374616e636531436f6c6c6563746976652050726f706f73616c73496e7374616e636531436f6c6c65637469766520566f74696e67496e7374616e636532436f6c6c6563746976652050726f706f73616c73496e7374616e636532436f6c6c65637469766520566f74696e6700000000000038cc10000b0000000000000044cc10000100000000000000000000005ccc10000400000000000000000000007ccc1000070000000000000084cc10000100000000000000000000009ccc1000030000000000000000000000b84811000700000000000000b4cc1000020000000000000000000000e4cc100004000000000000000000000070491100040000000000000004cd10000300000000000000000000004ccd100004000000000000007365745f6d656d6265727300000000007ccf10000b00000000000000255c110011000000fbce1000540000004fcf100017000000389711000000000066cf10001600000065786563757465000000000058531100080000000000000075ce10001e00000093ce10003d0000003897110000000000d0ce10002b0000000000000058ce1000090000000000000061ce1000140000000000000058531100080000000000000075ce10001e000000c54d11000b00000006ce1000240000002ace10002e000000d84d11000c000000000000005853110008000000000000007c4f11000700000000000000e4cd10000500000000000000e9cd10001600000000000000ffcd10000700000000000000f743110004000000c54d11000b0000006ccd1000230000008fcd100055000000d84d11000c000000202d20426f756e6465642073746f72616765207265616420616e64207772697465732e202d2057696c6c20626520736c696768746c792068656176696572206966207468652070726f706f73616c20697320617070726f766564202f20646973617070726f7665642061667465722074686520766f74652e696e646578436f6d706163743c50726f706f73616c496e6465783e617070726f7665202d20426f756e6465642073746f7261676520726561647320616e64207772697465732e202d20417267756d656e7420607468726573686f6c6460206861732062656172696e67206f6e207765696768742e7468726573686f6c64436f6d706163743c4d656d626572436f756e743e426f783c3c542061732054726169743c493e3e3a3a50726f706f73616c3e20446973706174636820612070726f706f73616c2066726f6d2061206d656d626572207573696e672074686520604d656d62657260206f726967696e2e204f726967696e206d7573742062652061206d656d626572206f662074686520636f6c6c6563746976652e205365742074686520636f6c6c6563746976652773206d656d62657273686970206d616e75616c6c7920746f20606e65775f6d656d62657273602e204265206e69636520746f2074686520636861696e20616e642070726f76696465206974207072652d736f727465642e20526571756972657320726f6f74206f726967696e2e6e65775f6d656d62657273496e7374616e636531436f6c6c65637469766550726f706f73616c735665633c543a3a486173683e00e8d010002400000050726f706f73616c4f663c542061732054726169743c493e3e3a3a50726f706f73616c00b5d0100033000000566f74696e67566f7465733c543a3a4163636f756e7449643e00000088d010002d00000050726f706f73616c436f756e7400000076d010001200000028d010004e000000205468652063757272656e74206d656d62657273206f662074686520636f6c6c6563746976652e20546869732069732073746f72656420736f7274656420286a7573742062792076616c7565292e2050726f706f73616c7320736f206661722e20566f746573206f6e206120676976656e2070726f706f73616c2c206966206974206973206f6e676f696e672e2041637475616c2070726f706f73616c20666f72206120676976656e20686173682c20696620697427732063757272656e742e2054686520686173686573206f6620746865206163746976652070726f706f73616c732e496e7374616e636532436f6c6c65637469766500000000009acf1000090000000000000000000000a3cf10000c0000000000000000000000000000000000000000000000000000000000000038971100f8d210000000000000000000b0cf100001000000000000000100000000000000b8cf10000a00000001010000000000007c4f11000700000000000000c2cf1000190000000000000000000000000000000000000038971100d8d210000000000000000000dccf100001000000000000000000000000000000e4cf10000600000001010000000000007c4f11000700000000000000eacf1000130000000000000000000000000000000000000038971100d8d21000000000000000000000d010000100000000000000000000000000000008d010000d000000000000000000000076341100030000000000000000000000000000000000000000000000000000000000000038971100e8d21000000000000000000018d0100001000000000000000100000000000000ace61000070000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100f8d21000000000000000000020d010000100000000000000010000003700000000000000010000004f0000003700000000000000010000009c000000370000000000000001000000500000007cb8100041000000e9000000010000003a6865617070616765733a636f646500d8b8100045000000830000000100000070726f706f736572206e6f742061206d656d6265726475706c69636174652070726f706f73616c73206e6f7420616c6c6f776564496e7374616e636531436f6c6c6563746976652050726f706f73616c4f66496e7374616e636531436f6c6c6563746976652050726f706f73616c436f756e7470726f706f73616c206d757374206578697374766f746572206e6f742061206d656d6265726d69736d61746368656420696e6465786475706c696361746520766f74652069676e6f726564496e7374616e636532436f6c6c6563746976652050726f706f73616c4f66496e7374616e636532436f6c6c6563746976652050726f706f73616c436f756e740000000000000064d410000f0000000000000074d4100002000000000000000000000084d4100004000000000000004e65774163636f756e74496e64657800d0431100090000001fd510000c000000a4d41000220000003897110000000000c6d410004100000007d51000180000002041206e6577206163636f756e7420696e646578207761732061737369676e65642e2054686973206576656e74206973206e6f7420747269676765726564207768656e20616e206578697374696e6720696e64657820697320726561737369676e656420746f20616e6f7468657220604163636f756e744964602e4163636f756e74496e6465780050d510001900000070d5100048000000230100000e000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f6c69622e7273d0d510000e000000ded5100048000000220100004a0000006578706c696369742070616e69632f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f6c69622e72730000d0d510000e000000ded5100048000000210100004a00000058d610002b00000083d6100044000000ef0000000400000054696d657374616d70206d7573742062652075706461746564206f6e636520696e2074686520626c6f636b2f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f74696d657374616d702f7372632f6c69622e727300e0d610003000000083d6100044000000e30000000400000054696d657374616d70206d7573742062652075706461746564206f6e6c79206f6e636520696e2074686520626c6f636b28d710004e00000083d6100044000000e40000000400000054696d657374616d70206d75737420696e6372656d656e74206279206174206c65617374203c4d696e696d756d506572696f643e206265747765656e2073657175656e7469616c20626c6f636b7300000000000054d810000b000000000000003897110000000000000000000000000060d8100001000000000000000000000068d810000d000000000000003897110000000000000000000000000078d8100001000000000000000000000080d810000e000000000000003897110000000000000000000000000090d8100001000000000000000000000098d810000c0000000000000038971100000000000000000000000000a4d81000010000000000000000000000acd810000500000000000000b4d81000010000000000000000000000bcd8100001000000000000004d656d626572416464656400c5d91000390000004d656d62657252656d6f7665640000008ad910003b0000004d656d6265727353776170706564000053d91000370000004d656d6265727352657365740dd910004600000044756d6d79000000e0d810002d000000c4d810001c000000205068616e746f6d206d656d6265722c206e6576657220757365642e727374643a3a6d61726b65723a3a5068616e746f6d446174613c284163636f756e7449642c204576656e74293e20546865206d656d62657273686970207761732072657365743b2073656520746865207472616e73616374696f6e20666f722077686f20746865206e6577207365742069732e2054776f206d656d62657273207765726520737761707065643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732072656d6f7665643b2073656520746865207472616e73616374696f6e20666f722077686f2e2054686520676976656e206d656d626572207761732061646465643b2073656520746865207472616e73616374696f6e20666f722077686f2e54696d657374616d70204e6f77496e646963657320456e756d53657400005900000008000000040000009d000000387d11002800000044da1000420000004a000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f696e64696365732f7372632f6c69622e72730000387d110028000000a0da1000450000005c000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f6d656d626572736869702f7372632f6c69622e727300000044da1000420000004a0000000100000054696d657374616d7020746f6f2066617220696e2066757475726520746f206163636570744765747320616e64206465636f6465732074696d657374616d7020696e686572656e742064617461496e646963657300000000fcdb10000b000000000000000000000007dc10000f000000000000000000000000000000000000000000000000000000000000003897110018dc1000000000000000000028dc10000100000000000000010000000000000030dc100007000000010100000000000007dc10000f00000000000000255c1100110000000000000000000000000000000000000038971100b4e61000000000000000000038dc10000100000000000000010000004e657874456e756d536574543a3a4163636f756e74496e64657800003700000000000000010000009c00000056dc10001f000000456e756d5365740040dc1000160000002054686520656e756d65726174696f6e20736574732e20546865206e657874206672656520656e756d65726174696f6e207365742e496e6469636573204e657874456e756d536574e9dd10001c000000b8dc1000440000009e00000003000000c5dd100024000000b8dc100044000000a7000000030000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f6578656375746976652f7372632f6c69622e727393dd100032000000b8dc10004400000001010000030000006cdd100027000000b8dc100044000000090100000400000044dd100028000000b8dc1000440000000f0100000300000053746f7261676520726f6f74206d757374206d6174636820746861742063616c63756c617465642e446967657374206974656d206d757374206d6174636820746861742063616c63756c617465642e4e756d626572206f6620646967657374206974656d73206d757374206d6174636820746861742063616c63756c617465642e5472616e73616374696f6e207472696520726f6f74206d7573742062652076616c69642e506172656e7420686173682073686f756c642062652076616c69642e0000000000000034de1000030000000000000038de100001000000000000000000000050de100009000000000000007365740000000000d2df10000300000000000000d5df10001200000098de1000160000003897110000000000aede10005600000004df10003600000038971100000000003adf1000510000008bdf10001100000038971100000000009cdf10003600000020536574207468652063757272656e742074696d652e20546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6e2070686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e205468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e742073706563696669656420627920604d696e696d756d506572696f64602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d7573742062652060496e686572656e74602e6e6f77436f6d706163743c543a3a4d6f6d656e743e54696d657374616d7000000000a0e01000030000000000000000000000a3e01000090000000000000000000000000000000000000000000000000000000000000038971100ace010000000000000000000bce0100001000000000000000100000000000000c4e01000090000000000000000000000f7431100040000000000000000000000000000000000000000000000000000000000000038971100d0e010000000000000000000e0e010000100000000000000010000004e6f77543a3a4d6f6d656e74370000000000000001000000ab00000015e11000240000004469645570646174650000003700000000000000010000004f000000e8e010002d00000020446964207468652074696d657374616d7020676574207570646174656420696e207468697320626c6f636b3f2043757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e0000000000000074e110000d00000000000000a3e0100009000000000000003897110084e11000000000000000000094e1100004000000000000004d696e696d756d506572696f64000000370000000000000001000000bb000000b4e110005a0000000ee210005a00000068e2100059000000c1e210001c00000020546865206d696e696d756d20706572696f64206265747765656e20626c6f636b732e204265776172652074686174207468697320697320646966666572656e7420746f20746865202a65787065637465642a20706572696f6420746861742074686520626c6f636b2070726f64756374696f6e206170706172617475732070726f76696465732e20596f75722063686f73656e20636f6e73656e7375732073797374656d2077696c6c2067656e6572616c6c7920776f726b2077697468207468697320746f2064657465726d696e6520612073656e7369626c6520626c6f636b2074696d652e20652e672e20466f7220417572612c2069742077696c6c20626520646f75626c65207468697320706572696f64206f6e2064656661756c742073657474696e67732e0000000000000090e310000a000000000000009ce31000010000000000000000000000b4e31000030000000000000000000000cce310000d000000000000009ce31000010000000000000000000000dce31000030000000000000000000000f4e310000b0000000000000000e4100002000000000000000000000030e4100003000000000000000000000048e410000d0000000000000058e4100001000000000000000000000070e4100004000000000000006164645f6d656d6265720000000000005712110003000000000000000b4e11000c000000f2e510001f000000389711000000000011e610002d00000072656d6f76655f6d656d6265720000009ee51000240000003897110000000000c2e5100030000000737761705f6d656d626572000000000095e5100006000000000000000b4e11000c000000000000009be5100003000000000000000b4e11000c00000037e5100030000000389711000000000067e510002e00000072657365745f6d656d626572730000000000000030e510000700000000000000255c11001100000090e4100056000000e6e410001b000000389711000000000001e510002f000000204368616e676520746865206d656d6265727368697020746f2061206e6577207365742c20646973726567617264696e6720746865206578697374696e67206d656d626572736869702e204265206e69636520616e64207061737320606d656d6265727360207072652d736f727465642e204d6179206f6e6c792062652063616c6c65642066726f6d206052657365744f726967696e60206f7220726f6f742e6d656d626572732053776170206f7574206f6e65206d656d626572206072656d6f76656020666f7220616e6f746865722060616464602e204d6179206f6e6c792062652063616c6c65642066726f6d2060537761704f726967696e60206f7220726f6f742e72656d6f76656164642052656d6f76652061206d656d626572206077686f602066726f6d20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d206052656d6f76654f726967696e60206f7220726f6f742e204164642061206d656d626572206077686f6020746f20746865207365742e204d6179206f6e6c792062652063616c6c65642066726f6d20604164644f726967696e60206f7220726f6f742e496e7374616e6365314d656d6265727368697000000000000000ace61000070000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100b4e610000000000000000000c4e610000100000000000000010000004d656d626572730037000000000000000100000050000000cce6100032000000205468652063757272656e74206d656d626572736869702c2073746f72656420617320616e206f726465726564205665632e000080e7100048000000b10100002300000080e7100048000000b20100002300000030e7100049000000870200001d0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f736f72742e7273000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727330e71000490000009d0000003a00000030e7100049000000a400000030000000a0da1000450000005c00000001000000496e7374616e6365314d656d62657273686970204d656d62657273616c72656164792061206d656d626572626164206f726967696e6e6f742061206d656d62657200000080e7100048000000a10a00000e00000054e810001c00000056617269616e74206973206e6576657220636f6e737472756374656480e81000440000000a040000220000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f636f6e7472616374732f7372632f6c69622e727373746f72616765206973206e6f74206e756c6c2c207468657265666f7265206d75737420626520612076616c69642074797065000000000000ea1000080000000000000008ea100003000000000000000000000020ea100001000000000000000000000028ea10000c000000000000008c43110002000000000000000000000034ea10000100000000000000000000003cea10000a0000000000000048ea100001000000000000000000000050ea100001000000000000000000000058ea10000f0000000000000068ea100001000000000000000000000070ea100001000000000000000000000078ea10000a0000000000000084ea100002000000000000000000000094ea1000020000000000000000000000a4ea10000800000000000000acea1000020000000000000000000000bcea100001000000000000005472616e73666572d043110009000000d0431100090000001144110007000000eeeb10005a000000496e7374616e746961746564b7eb100037000000436f646553746f7265640000d94311000400000089eb10002e0000005363686564756c655570646174656400763411000300000059eb100030000000446973706174636865640000d043110009000000f743110004000000eeea10004e0000003ceb10001d000000436f6e7472616374d043110009000000e7ea100007000000c4ea10002300000020416e206576656e742066726f6d20636f6e7472616374206f66206163636f756e742e5665633c75383e20412063616c6c2077617320646973706174636865642066726f6d2074686520676976656e206163636f756e742e2054686520626f6f6c207369676e616c73207768657468657220697420776173207375636365737366756c20657865637574696f6e206f72206e6f742e20547269676765726564207768656e207468652063757272656e74207363686564756c6520697320757064617465642e20436f646520776974682074686520737065636966696564206861736820686173206265656e2073746f7265642e20436f6e7472616374206465706c6f7965642062792061646472657373206174207468652073706563696669656420616464726573732e205472616e736665722068617070656e6564206066726f6d6020746f2060746f60207769746820676976656e206076616c7565602061732070617274206f662061206063616c6c60206f722060696e7374616e7469617465602e436f6e7472616374205072697374696e65436f6465436f6e747261637420436f646553746f72616765436f6e747261637420436f6e7472616374496e666f4f66436f6e747261637420476173507269636500000037000000000000000100000038000000c0ec10004a0000003200000006000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f63757276652e7273000000000000e8ed10000f00000000000000f8ed100001000000000000000000000010ee100003000000000000000000000028ee1000080000000000000030ee100002000000000000000000000060ee1000020000000000000000000000af861100040000000000000070ee1000040000000000000000000000d0ee100007000000000000000000000008ef10000b0000000000000014ef100004000000000000000000000074ef10000a0000000000000000000000c4ef10000f00000000000000d4ef100002000000000000000000000004f0100005000000000000007570646174655f7363686564756c65000000000054f6100008000000000000005cf6100008000000e4f510002d000000389711000000000011f61000430000007075745f636f64650000000092f3100009000000000000009bf310000c00000000000000e0f510000400000000000000e7ea10000700000054f5100057000000abf51000350000000000000046f1100004000000000000004b22110023000000000000005f551100050000000000000064551100150000000000000092f3100009000000000000009bf310000c00000000000000bbf310000400000000000000e7ea100007000000bff3100042000000389711000000000001f410004a0000004bf410002c00000077f4100046000000bdf41000520000000ff5100045000000696e7374616e7469617465000000000089f31000090000000000000064551100150000000000000092f3100009000000000000009bf310000c00000000000000a7f310000900000000000000b0f310000b00000000000000bbf310000400000000000000e7ea10000700000068f110006f0000003897110000000000d7f11000260000003897110000000000fdf11000500000004df21000410000008ef210005b000000e9f210005700000040f310002a0000006af310001f000000636c61696d5f737572636861726765000000000046f1100004000000000000000b4e11000c000000000000004af110000a0000000000000054f11000140000002cf010005c00000088f01000450000003897110000000000cdf010004e0000001bf110002b00000020416c6c6f777320626c6f636b2070726f64756365727320746f20636c61696d206120736d616c6c2072657761726420666f72206576696374696e67206120636f6e74726163742e204966206120626c6f636b2070726f6475636572206661696c7320746f20646f20736f2c206120726567756c61722075736572732077696c6c20626520616c6c6f77656420746f20636c61696d20746865207265776172642e20496620636f6e7472616374206973206e6f742065766963746564206173206120726573756c74206f6620746869732063616c6c2c206e6f20616374696f6e73206172652074616b656e20616e64207468652073656e646572206973206e6f7420656c696769626c6520666f7220746865207265776172642e646573746175785f73656e6465724f7074696f6e3c543a3a4163636f756e7449643e20496e7374616e7469617465732061206e657720636f6e74726163742066726f6d207468652060636f646568617368602067656e65726174656420627920607075745f636f6465602c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e20496e7374616e74696174696f6e20697320657865637574656420617320666f6c6c6f77733a202d205468652064657374696e6174696f6e206164647265737320697320636f6d7075746564206261736564206f6e207468652073656e64657220616e642068617368206f662074686520636f64652e202d2054686520736d6172742d636f6e7472616374206163636f756e7420697320637265617465642061742074686520636f6d707574656420616464726573732e202d20546865206063746f725f636f64656020697320657865637574656420696e2074686520636f6e74657874206f6620746865206e65776c792d63726561746564206163636f756e742e204275666665722072657475726e656420202061667465722074686520657865637574696f6e206973207361766564206173207468652060636f646560206f6620746865206163636f756e742e205468617420636f64652077696c6c20626520696e766f6b656420202075706f6e20616e792063616c6c2072656365697665642062792074686973206163636f756e742e202d2054686520636f6e747261637420697320696e697469616c697a65642e656e646f776d656e746761735f6c696d6974436f6d706163743c4761733e636f64655f68617368436f6465486173683c543e64617461204d616b657320612063616c6c20746f20616e206163636f756e742c206f7074696f6e616c6c79207472616e7366657272696e6720736f6d652062616c616e63652e202a20496620746865206163636f756e74206973206120736d6172742d636f6e7472616374206163636f756e742c20746865206173736f63696174656420636f64652077696c6c20626520657865637574656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e202a20496620746865206163636f756e74206973206120726567756c6172206163636f756e742c20616e792076616c75652077696c6c206265207472616e736665727265642e202a204966206e6f206163636f756e742065786973747320616e64207468652063616c6c2076616c7565206973206e6f74206c657373207468616e20606578697374656e7469616c5f6465706f736974602c206120726567756c6172206163636f756e742077696c6c206265206372656174656420616e6420616e792076616c75652077696c6c206265207472616e736665727265642e2053746f7265732074686520676976656e2062696e617279205761736d20636f646520696e746f2074686520636861696e27732073746f7261676520616e642072657475726e73206974732060636f646568617368602e20596f752063616e20696e7374616e746961746520636f6e747261637473206f6e6c7920776974682073746f72656420636f64652e636f6465205570646174657320746865207363686564756c6520666f72206d65746572696e6720636f6e7472616374732e20546865207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e207468652073746f726564207363686564756c652e7363686564756c655363686564756c6500000000ccf81000080000000000000000000000d4f810000300000000000000000000000000000000000000000000000000000000000000389711007cf910000000000000000000d8f8100001000000000000000100000000000000e0f810000f00000000000000000000005cf61000080000000000000000000000000000000000000000000000000000000000000038971100f0f81000000000000000000000f910000100000000000000010000000000000008f910000c0000000101000000000000b0f310000b00000000000000e7ea100007000000000000000000000000000000000000003897110014f91000000000000000000024f91000010000000000000000000000000000002cf910000b0000000101000000000000b0f310000b0000000000000037f9100016000000000000000000000000000000000000003897110050f91000000000000000000060f910000100000000000000000000000000000068f910000e000000000000000000000076f910000300000000000000000000000000000000000000000000000000000000000000389711007cf9100000000000000000008cf910000100000000000000010000000000000094f910000e00000001010000000000000b4e11000c00000000000000a2f910000f0000000000000000000000000000000000000038971100b4f910000000000000000000c4f9100001000000000000000000000000000000ccf910000800000000000000000000007a6511000c0000000000000000000000000000000000000000000000000000000000000038971100d4f910000000000000000000e4f910000100000000000000010000004761735370656e744761730020fb10002000000043757272656e745363686564756c6500370000000000000001000000bc000000fbfa1000250000005072697374696e65436f64653700000000000000010000004f000000a2fa100059000000436f646553746f726167657761736d3a3a5072656661625761736d4d6f64756c650000003700000000000000010000004f00000049fa1000590000004163636f756e74436f756e746572753634000000370000000000000001000000ab00000034fa100015000000436f6e7472616374496e666f4f66436f6e7472616374496e666f3c543e0000003700000000000000010000004f0000000afa10002a0000004761735072696365370000000000000001000000bd000000ecf910001e00000020546865207072696365206f66206f6e6520756e6974206f66206761732e2054686520636f6465206173736f6369617465642077697468206120676976656e206163636f756e742e20546865207375627472696520636f756e7465722e2041206d617070696e67206265747765656e20616e206f726967696e616c20636f6465206861736820616e6420696e737472756d656e746564207761736d20636f64652c20726561647920666f7220657865637574696f6e2e2041206d617070696e672066726f6d20616e206f726967696e616c20636f6465206861736820746f20746865206f726967696e616c20636f64652c20756e746f756368656420627920696e737472756d656e746174696f6e2e2043757272656e7420636f7374207363686564756c6520666f7220636f6e7472616374732e20476173207370656e7420736f2066617220696e207468697320626c6f636b2e00000000c0fe10001300000000000000925111000e0000000000000038971100d4fe10000000000000000000e4fe100004000000000000000000000004ff100010000000000000007a6511000c00000000000000389711005cff1000000000000000000014ff10000100000000000000000000001cff100011000000000000007634110003000000000000003897110030ff1000000000000000000040ff100002000000000000000000000050ff10000b000000000000007a6511000c00000000000000389711005cff100000000000000000006cff100001000000000000000000000074ff100011000000000000007a6511000c000000000000003897110088ff1000000000000000000098ff1000070000000000000000000000d0ff10000f000000000000007a6511000c0000000000000038971100e0ff10000000000000000000f0ff1000020000000000000000000000000011000b000000000000007a6511000c00000000000000389711007c00110000000000000000000c001100010000000000000000000000140011000b000000000000007a6511000c00000000000000389711007c0011000000000000000000200011000100000000000000000000002800110012000000000000007a6511000c00000000000000389711007c00110000000000000000003c0011000100000000000000000000004400110012000000000000007a6511000c000000000000003897110058001100000000000000000068001100010000000000000000000000700011000b000000000000007a6511000c00000000000000389711007c00110000000000000000008c0011000200000000000000000000009c0011000b00000000000000d4f81000030000000000000038971100cc0011000000000000000000a8001100020000000000000000000000b80011001200000000000000d4f81000030000000000000038971100cc0011000000000000000000dc001100020000000000000000000000ec001100080000000000000076341100030000000000000038971100f4001100000000000000000004011100020000000000000000000000140111000c000000000000007634110003000000000000003897110020011100000000000000000030011100010000000000000000000000380111000d00000000000000d4f810000300000000000000389711004801110000000000000000005801110002000000000000005369676e6564436c61696d48616e646963617000370000000000000001000000be000000080711003800000038971100000000004007110043000000830711001a000000546f6d6273746f6e654465706f736974d30611003500000053746f7261676553697a654f6666736574000000370000000000000001000000a90000005606110054000000aa0611002900000052656e74427974654665650037000000000000000100000099000000090611004d00000052656e744465706f7369744f6666736574000000370000000000000001000000bf0000009104110041000000d2041100160000003897110000000000e80411005a00000042051100560000009805110053000000eb0511001e00000053757263686172676552657761726400370000000000000001000000c00000003e04110039000000770411001a0000005472616e736665724665650019041100250000004372656174696f6e46656500f2031100270000005472616e73616374696f6e426173654665650000bb031100370000005472616e73616374696f6e4279746546656500003700000000000000010000009b0000007803110043000000436f6e7472616374466565003700000000000000010000009a0000002103110050000000710311000700000043616c6c4261736546656500cc02110047000000130311000e000000496e7374616e7469617465426173654665650000370000000000000001000000c1000000760211004e000000c4021100080000004d61784465707468370000000000000001000000c20000001c0211004c000000680211000e0000004d617856616c756553697a65370000000000000001000000c3000000ce0111004e000000426c6f636b4761734c696d6974000000370000000000000001000000c40000006801110049000000b10111001d00000020546865206d6178696d756d20616d6f756e74206f6620676173207468617420636f756c6420626520657870656e6465642070657220626c6f636b2e204120726561736f6e61626c652064656661756c742076616c75652069732031305f3030305f3030302e20546865206d6178696d756d2073697a65206f6620612073746f726167652076616c756520696e2062797465732e204120726561736f6e61626c652064656661756c74206973203136204b69422e20546865206d6178696d756d206e657374696e67206c6576656c206f6620612063616c6c2f696e7374616e746961746520737461636b2e204120726561736f6e61626c652064656661756c742076616c7565206973203130302e20546865206261736520666565206368617267656420666f7220696e7374616e74696174696e67206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203137352e20546865206261736520666565206368617267656420666f722063616c6c696e6720696e746f206120636f6e74726163742e204120726561736f6e61626c652064656661756c742076616c7565206973203133352e205468652066656520726571756972656420746f20696e7374616e7469617465206120636f6e747261637420696e7374616e63652e204120726561736f6e61626c652064656661756c742076616c75652069732032312e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b20746865207065722d6279746520706f7274696f6e2e205468652066656520746f206265207061696420666f72206d616b696e672061207472616e73616374696f6e3b2074686520626173652e205468652066656520726571756972656420746f2063726561746520616e206163636f756e742e205468652066656520726571756972656420746f206d616b652061207472616e736665722e205265776172642074686174206973207265636569766564206279207468652070617274792077686f736520746f75636820686173206c656420746f2072656d6f76616c206f66206120636f6e74726163742e2054686520616d6f756e74206f662066756e6473206120636f6e74726163742073686f756c64206465706f73697420696e206f7264657220746f206f66667365742074686520636f7374206f66206f6e6520627974652e204c6574277320737570706f736520746865206465706f73697420697320312c303030204255202862616c616e636520756e697473292f6279746520616e64207468652072656e7420697320312042552f627974652f6461792c207468656e206120636f6e7472616374207769746820312c3030302c3030302042552074686174207573657320312c303030206279746573206f662073746f7261676520776f756c6420706179206e6f2072656e742e20427574206966207468652062616c616e6365207265647563656420746f203530302c30303020425520616e64207468652073746f7261676520737461796564207468652073616d6520617420312c3030302c207468656e20697420776f756c6420706179203530302042552f6461792e205072696365206f6620612062797465206f662073746f7261676520706572206f6e6520626c6f636b20696e74657276616c2e2053686f756c642062652067726561746572207468616e20302e2053697a65206f66206120636f6e7472616374206174207468652074696d65206f6620696e7374616e746961696f6e2e205468697320697320612073696d706c652077617920746f20656e73757265207468617420656d70747920636f6e747261637473206576656e7475616c6c7920676574732064656c657465642e20546865206d696e696d756d20616d6f756e7420726571756972656420746f2067656e6572617465206120746f6d6273746f6e652e204e756d626572206f6620626c6f636b2064656c617920616e2065787472696e73696320636c61696d20737572636861726765206861732e205768656e20636c61696d207375726368617267652069732063616c6c656420627920616e2065787472696e736963207468652072656e7420697320636865636b656420666f722063757272656e745f626c6f636b202d2064656c617943616e6e6f7420726573746f726520746f20696e6578697374696e67206f7220616c69766520636f6e74726163746d656d6f727976616c69646174696f6e3a20696d706f727420656e74727920706f696e747320746f2061206e6f6e2d6578697374656e74207479706543616e6e6f7420696d706f727420676c6f62616c736d6f64756c6520696d706f7274732061206e6f6e2d6578697374656e742066756e6374696f6e6d6f64756c6520696d706f72747320606578745f7072696e746c6e60206275742064656275672066656174757265732064697361626c656443616e6e6f7420696d706f7274207461626c65736d6f64756c652068617320696d706f7274732066726f6d2061206e6f6e2d27656e7627206e616d6573706163654d656d6f727920696d706f7274206d757374206861766520746865206669656c64206e616d6520276d656d6f7279274d756c7469706c65206d656d6f727920696d706f72747320646566696e65644d6178696d756d206e756d626572206f662070616765732073686f756c6420626520616c77617973206465636c617265642e52657175657374656420696e697469616c206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520726571756573746564206d6178696d756d4d6178696d756d206e756d626572206f662070616765732073686f756c64206e6f74206578636565642074686520636f6e66696775726564206d6178696d756d2e64656661756c743a000000387d11002800000080e8100044000000c80100000100000080e8100044000000c8010000010000006e6577207363686564756c65206d7573742068617665206120677265617465722076657273696f6e207468616e2063757272656e74496e76616c69642073757263686172676520636c61696d3a206f726967696e206d757374206265207369676e6564206f7220696e686572656e7420616e6420617578696c696172792073656e646572206f6e6c792070726f7669646564206f6e20696e686572656e74417574686f72697479446973636f76657279204b657973000000387d110028000000c80a11004e00000034000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f617574686f726974792d646973636f766572792f7372632f6c69622e72730000c80a11004e000000340000000100000000000000ac0b11000500000000000000b40b1100010000000000000000000000bc0b1100010000000000000000000000c40b11000a00000000000000a8431100010000000000000000000000d00b1100010000000000000000000000d80b11000a00000000000000b40b1100010000000000000000000000bc0b110001000000000000005375646964000000f7431100040000001e0c1100180000004b65794368616e6765640000e20b11003c0000005375646f4173446f6e6520546865207375646f6572206a757374207377697463686564206964656e746974793b20746865206f6c64206b657920697320737570706c6965642e2041207375646f206a75737420746f6f6b20706c6163652e707265636f6e646974696f6e3a20616c6c20696d706f7274732073686f756c6420626520636865636b656420616761696e737420746865207369676e617475726573206f6620636f72726573706f6e64696e670a09090909090966756e6374696f6e7320646566696e65642062792060646566696e655f656e762160206d6163726f206279207468652075736572206f6620746865206d6163726f3b0a0909090909097369676e617475726573206f662074686573652066756e6374696f6e7320646566696e6564206279206024706172616d73603b0a09090909090963616c6c7320616c77617973206d616465207769746820617267756d656e7473207479706573206f662077686963682061726520646566696e65642062792074686520636f72726573706f6e64696e6720696d706f7274733b0a09090909090974687573207479706573206f6620617267756d656e74732073686f756c6420626520657175616c20746f2074797065206c69737420696e206024706172616d736020616e640a0909090909096c656e677468206f6620617267756d656e74206c69737420616e642024706172616d732073686f756c6420626520657175616c3b0a0909090909097468757320746869732063616e206e6576657220626520604e6f6e65603b0a0909090909097165643b0a09090909090972657475726e2074797065206572726f7276616c69646174696f6e206572726f72647572696e6720657865637574696f6e00387d110028000000740e11003f00000068000000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f7375646f2f7372632f6c69622e727300740e11003f00000068000000010000006f6e6c79207468652063757272656e74207375646f206b65792063616e207375646f5375646f204b65796f6e6c79207468652063757272656e74207375646f206b65792063616e206368616e676520746865207375646f206b657900400f1100480000009b0a00000a000000400f110048000000a10a00000e0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e7273000000000c1011000400000000000000684a1100010000000000000000000000101011000a00000000000000000000006010110007000000000000006810110001000000000000000000000080101100090000000000000000000000c81011000700000000000000d0101100020000000000000000000000001111000b000000000000007375646fc81211004e0000003897110000000000bd111100340000003897110000000000c54d11000b000000d04d110008000000f1111100190000000a121100180000002212110035000000d84d11000c0000007365745f6b65790000000000fc20110003000000000000004b221100230000005a1211005d0000003897110000000000bd111100340000003897110000000000c54d11000b000000d04d110008000000f111110019000000b712110011000000d84d11000c0000007375646f5f617300000000005712110003000000000000004b221100230000000000000058531100080000000000000060531100100000005811110054000000ac111100110000003897110000000000bd111100340000003897110000000000c54d11000b000000d04d110008000000f1111100190000000a121100180000002212110035000000d84d11000c0000002041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c207769746820605369676e656460206f726967696e2066726f6d206120676976656e206163636f756e742e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2e202d204c696d697465642073746f726167652072656164732e202d204f6e6520444220777269746520286576656e74292e202d20556e6b6e6f776e20776569676874206f662064657269766174697665206070726f706f73616c6020657865637574696f6e2e77686f2041757468656e74696361746573207468652063757272656e74207375646f206b657920616e6420736574732074686520676976656e204163636f756e7449642028606e6577602920617320746865206e6577207375646f206b65792e202d204f6e65204442206368616e67652e2041757468656e7469636174657320746865207375646f206b657920616e64206469737061746368657320612066756e6374696f6e2063616c6c20776974682060526f6f7460206f726967696e2e5375646f000000000000741311000300000000000000000000000b4e11000c0000000000000000000000000000000000000000000000000000000000000038971100781311000000000000000000881311000100000000000000010000004b657900370000000000000001000000c500000090131100210000002054686520604163636f756e74496460206f6620746865207375646f206b65792e0000003b1411000d0000001e1411001b0000003914110002000000dc131100420000001f020000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f6e6f64652f72756e74696d652f7372632f6c69622e727342616420696e70757420646174612070726f766964656420746f203a20657865637574655f626c6f636b5014110010000000696e697469616c697a655f626c6f636b681411000f0000006170706c795f65787472696e736963008014110013000000696e686572656e745f65787472696e73696373009c1411000f000000636865636b5f696e686572656e747300b41411001400000076616c69646174655f7472616e73616374696f6ed01411000f0000006f6666636861696e5f776f726b657200e8141100040000007369676ef4141100060000007665726966790000041511000d0000006163636f756e745f6e6f6e6365000000af86110004000000241511001500000067656e65726174655f73657373696f6e5f6b65797300000000000000c01511000600000000000000c8151100010000000000000000000000d0151100010000000000000000000000d81511000500000000000000e0151100020000000000000000000000f0151100010000000000000000000000f81511001a00000000000000108d110001000000000000000000000014161100020000000000000052657761726400001144110007000000c616110038000000536c617368000000d04311000900000011441100070000007d161100490000004f6c64536c617368696e675265706f7274446973636172646564000024161100470000006b1611001200000020416e206f6c6420736c617368696e67207265706f72742066726f6d2061207072696f72206572612077617320646973636172646564206265636175736520697420636f756c64206e6f742062652070726f6365737365642e204f6e652076616c696461746f722028616e6420697473206e6f6d696e61746f72732920686173206265656e20736c61736865642062792074686520676976656e20616d6f756e742e20416c6c2076616c696461746f72732068617665206265656e2072657761726465642062792074686520676976656e2062616c616e63652e5374616b696e672043757272656e7445726153746172745374616b696e67204e6f6d696e61746f727368656164206f66205374616b696e67204e6f6d696e61746f72735374616b696e672056616c696461746f727368656164206f66205374616b696e672056616c696461746f72735374616b696e67205374616b6572735374616b696e6720426f6e6465645374616b696e67204c65646765725374616b696e672050617965655374616b696e672043757272656e74456c65637465640000000000f81911000400000000000000fc191100030000000000000000000000441a11000f0000000000000000000000bc1a11000a00000000000000c81a1100010000000000000000000000e01a11000e0000000000000000000000501b11000600000000000000581b1100010000000000000000000000701b1100170000000000000000000000281c11001100000000000000389711000000000000000000000000003c1c1100100000000000000000000000bc1c11000800000000000000c41c1100010000000000000000000000dc1c11000b0000000000000000000000341d110008000000000000003c1d1100010000000000000000000000541d11000b0000000000000000000000ac1d1100050000000000000038971100000000000000000000000000b41d11000b00000000000000000000000c1e11000900000000000000181e1100010000000000000000000000301e11000b0000000000000000000000881e11000e00000000000000981e1100010000000000000000000000b01e11000b0000000000000000000000081f110013000000000000001c1f1100010000000000000000000000341f11000100000000000000000000003c1f11000d00000000000000389711000000000000000000000000004c1f1100050000000000000000000000741f11000d0000000000000038971100000000000000000000000000841f1100060000000000000000000000b41f11001100000000000000c81f1100010000000000000000000000e01f11000100000000000000626f6e6400000000412211000a000000000000004b22110023000000000000005f5511000500000000000000645511001500000000000000f12211000500000000000000f622110011000000d72b110059000000302c1100210000003897110000000000512c11004c00000038971100000000009d2c1100490000003897110000000000c54d11000b000000e62c110035000000d04d1100080000001b2d11001a0000003897110000000000352d11005b000000902d110049000000d84d11000c000000626f6e645f6578747261000000000000c92b11000e000000000000006455110015000000a32a110059000000fc2a11000d0000003897110000000000092b1100540000005d2b110059000000b62b11001300000038971100000000005a211100550000003897110000000000c54d11000b000000af2111003a000000d04d1100080000001d55110010000000d84d11000c000000756e626f6e640000000000005f55110005000000000000006455110015000000c8261100550000001d271100400000005d271100490000003897110000000000a627110052000000f8271100300000003897110000000000282811004f000000772811004f000000c62811003f00000038971100000000009c22110055000000389711000000000005291100260000003897110000000000c54d11000b0000002b29110050000000e9211100260000007b29110059000000d42911005c000000302a1100690000001d55110010000000992a11000a00000077697468647261775f756e626f6e646564000000c12411004b00000038971100000000000c2511004d000000592511001300000038971100000000009c2211005500000038971100000000006c2511001b0000003897110000000000c54d11000b0000008725110055000000dc251100510000002d2611003d0000006a2611005e0000000f22110032000000d84d11000c00000076616c696461746500000000a02411000500000000000000a52411001c000000662411003a0000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b000000af2111003a000000e9211100260000000f22110032000000d84d11000c0000006e6f6d696e617465000000003724110007000000000000003e241100280000004e231100440000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b0000009223110049000000db231100260000000124110036000000d84d11000c0000006368696c6c00000007231100320000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b000000af2111003a00000039231100150000000f22110032000000d84d11000c0000007365745f706179656500000000000000f12211000500000000000000f6221100110000006e2211002e0000003897110000000000232111003700000038971100000000009c221100550000003897110000000000c54d11000b000000af2111003a000000e9211100260000000f22110032000000d84d11000c0000007365745f636f6e74726f6c6c6572000000000000412211000a000000000000004b22110023000000ff201100240000003897110000000000232111003700000038971100000000005a211100550000003897110000000000c54d11000b000000af2111003a000000e9211100260000000f22110032000000d84d11000c0000007365745f76616c696461746f725f636f756e740000000000fc2011000300000000000000fa4e11000c000000dc20110020000000666f7263655f6e6f5f65726173000000b02011002c0000003897110000000000c54d11000b000000a020110010000000d84d11000c000000666f7263655f6e65775f657261000000252011005300000078201100280000003897110000000000c54d11000b000000a020110010000000d84d11000c0000007365745f696e76756c6e657261626c6573000000000000001b2011000a00000000000000255c110011000000e81f11003300000020536574207468652076616c696461746f72732077686f2063616e6e6f7420626520736c61736865642028696620616e79292e76616c696461746f727320466f72636520746865726520746f2062652061206e6577206572612061742074686520656e64206f6620746865206e6578742073657373696f6e2e20416674657220746869732c2069742077696c6c20626520726573657420746f206e6f726d616c20286e6f6e2d666f7263656429206265686176696f75722e202d204e6f20617267756d656e74732e20466f72636520746865726520746f206265206e6f206e6577206572617320696e646566696e6974656c792e2054686520696465616c206e756d626572206f662076616c696461746f72732e6e6577202852652d297365742074686520636f6e74726f6c6c6572206f6620612073746173682e20456666656374732077696c6c2062652066656c742061742074686520626567696e6e696e67206f6620746865206e657874206572612e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f206279207468652073746173682c206e6f742074686520636f6e74726f6c6c65722e202d20496e646570656e64656e74206f662074686520617267756d656e74732e20496e7369676e69666963616e7420636f6d706c65786974792e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732e202d2057726974657320617265206c696d6974656420746f2074686520606f726967696e60206163636f756e74206b65792e636f6e74726f6c6c65723c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f75726365202852652d2973657420746865207061796d656e742074617267657420666f72206120636f6e74726f6c6c65722e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f2062792074686520636f6e74726f6c6c65722c206e6f74207468652073746173682e706179656552657761726444657374696e6174696f6e204465636c617265206e6f2064657369726520746f206569746865722076616c6964617465206f72206e6f6d696e6174652e202d20436f6e7461696e73206f6e6520726561642e204465636c617265207468652064657369726520746f206e6f6d696e6174652060746172676574736020666f7220746865206f726967696e20636f6e74726f6c6c65722e202d20546865207472616e73616374696f6e277320636f6d706c65786974792069732070726f706f7274696f6e616c20746f207468652073697a65206f66206074617267657473602c2077686963682069732063617070656420617420604d41585f4e4f4d494e4154494f4e53602e202d20426f74682074686520726561647320616e642077726974657320666f6c6c6f7720612073696d696c6172207061747465726e2e746172676574735665633c3c543a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f757263653e204465636c617265207468652064657369726520746f2076616c696461746520666f7220746865206f726967696e20636f6e74726f6c6c65722e707265667356616c696461746f7250726566733c42616c616e63654f663c543e3e2052656d6f766520616e7920756e6c6f636b6564206368756e6b732066726f6d207468652060756e6c6f636b696e67602071756575652066726f6d206f7572206d616e6167656d656e742e205468697320657373656e7469616c6c7920667265657320757020746861742062616c616e636520746f206265207573656420627920746865207374617368206163636f756e7420746f20646f2077686174657665722069742077616e74732e2053656520616c736f205b6043616c6c3a3a756e626f6e64605d2e202d20436f756c6420626520646570656e64656e74206f6e2074686520606f726967696e6020617267756d656e7420616e6420686f77206d7563682060756e6c6f636b696e6760206368756e6b732065786973742e2020497420696d706c6965732060636f6e736f6c69646174655f756e6c6f636b656460207768696368206c6f6f7073206f76657220604c65646765722e756e6c6f636b696e67602c2077686963682069732020696e6469726563746c7920757365722d636f6e74726f6c6c65642e20536565205b60756e626f6e64605d20666f72206d6f72652064657461696c2e202d20436f6e7461696e732061206c696d69746564206e756d626572206f662072656164732c20796574207468652073697a65206f6620776869636820636f756c64206265206c61726765206261736564206f6e20606c6564676572602e205363686564756c65206120706f7274696f6e206f662074686520737461736820746f20626520756e6c6f636b656420726561647920666f72207472616e73666572206f75742061667465722074686520626f6e6420706572696f6420656e64732e2049662074686973206c656176657320616e20616d6f756e74206163746976656c7920626f6e646564206c657373207468616e20543a3a43757272656e63793a3a6d696e696d756d5f62616c616e636528292c207468656e20697420697320696e6372656173656420746f207468652066756c6c20616d6f756e742e204f6e63652074686520756e6c6f636b20706572696f6420697320646f6e652c20796f752063616e2063616c6c206077697468647261775f756e626f6e6465646020746f2061637475616c6c79206d6f7665207468652066756e6473206f7574206f66206d616e6167656d656e7420726561647920666f72207472616e736665722e204e6f206d6f7265207468616e2061206c696d69746564206e756d626572206f6620756e6c6f636b696e67206368756e6b73202873656520604d41585f554e4c4f434b494e475f4348554e4b5360292063616e20636f2d657869737473206174207468652073616d652074696d652e20496e207468617420636173652c205b6043616c6c3a3a77697468647261775f756e626f6e646564605d206e65656420746f2062652063616c6c656420666972737420746f2072656d6f766520736f6d65206f6620746865206368756e6b732028696620706f737369626c65292e2053656520616c736f205b6043616c6c3a3a77697468647261775f756e626f6e646564605d2e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204c696d697465642062757420706f74656e7469616c6c79206578706c6f697461626c6520636f6d706c65786974792e202d20456163682063616c6c20287265717569726573207468652072656d61696e646572206f662074686520626f6e6465642062616c616e636520746f2062652061626f766520606d696e696d756d5f62616c616e6365602920202077696c6c2063617573652061206e657720656e74727920746f20626520696e73657274656420696e746f206120766563746f722028604c65646765722e756e6c6f636b696e676029206b65707420696e2073746f726167652e202020546865206f6e6c792077617920746f20636c65616e207468652061666f72656d656e74696f6e65642073746f72616765206974656d20697320616c736f20757365722d636f6e74726f6c6c656420766961206077697468647261775f756e626f6e646564602e203c2f7765696768743e2041646420736f6d6520657874726120616d6f756e742074686174206861766520617070656172656420696e207468652073746173682060667265655f62616c616e63656020696e746f207468652062616c616e636520757020666f72207374616b696e672e20557365207468697320696620746865726520617265206164646974696f6e616c2066756e647320696e20796f7572207374617368206163636f756e74207468617420796f75207769736820746f20626f6e642e20556e6c696b65205b60626f6e64605d206f72205b60756e626f6e64605d20746869732066756e6374696f6e20646f6573206e6f7420696d706f736520616e79206c696d69746174696f6e206f6e2074686520616d6f756e7420746861742063616e2062652061646465642e6d61785f6164646974696f6e616c2054616b6520746865206f726967696e206163636f756e74206173206120737461736820616e64206c6f636b207570206076616c756560206f66206974732062616c616e63652e2060636f6e74726f6c6c6572602077696c6c20626520746865206163636f756e74207468617420636f6e74726f6c732069742e206076616c756560206d757374206265206d6f7265207468616e2074686520606d696e696d756d5f62616c616e636560207370656369666965642062792060543a3a43757272656e6379602e20546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f5369676e65645f20627920746865207374617368206163636f756e742e202d20496e646570656e64656e74206f662074686520617267756d656e74732e204d6f64657261746520636f6d706c65786974792e202d20546872656520657874726120444220656e74726965732e204e4f54453a2054776f206f66207468652073746f726167652077726974657320286053656c663a3a626f6e646564602c206053656c663a3a7061796565602920617265205f6e657665725f20636c65616e656420756e6c6573732074686520606f726967696e602066616c6c732062656c6f77205f6578697374656e7469616c206465706f7369745f20616e6420676574732072656d6f76656420617320647573742e5374616b696e6700000000683411000e0000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711006c36110000000000000000007c3411000100000000000000010000000000000084341100150000000000000000000000763411000300000000000000000000000000000000000000000000000000000000000000389711009c3411000000000000000000ac34110001000000000000000100000000000000b43411000d0000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100d03711000000000000000000c434110003000000000000000100000000000000dc3411000600000001010000000000000b4e11000c000000000000000b4e11000c00000000000000000000000000000000000000389711001c3511000000000000000000e434110001000000000000000000000000000000ec3411000600000001010000000000000b4e11000c00000000000000f23411002900000000000000000000000000000000000000389711001c35110000000000000000002c35110001000000000000000000000000000000343511000500000001010000000000000b4e11000c00000000000000f62211001100000000000000000000000000000000000000389711003c35110000000000000000004c35110001000000000000000100000000000000543511000a00000001010100000000000b4e11000c00000000000000a52411001c00000000000000000000000000000000000000389711006035110000000000000000007035110001000000000000000100000000000000783511000a00000001010100000000000b4e11000c00000000000000255c1100110000000000000000000000000000000000000038971100d0371100000000000000000084351100010000000000000001000000000000008c3511000700000001010000000000000b4e11000c0000000000000093351100240000000000000000000000000000000000000038971100b83511000000000000000000c835110004000000000000000100000000000000e83511000e0000000000000000000000255c1100110000000000000000000000000000000000000000000000000000000000000038971100d03711000000000000000000f835110001000000000000000100000000000000003611000a00000000000000000000000a3611000800000000000000000000000000000000000000000000000000000000000000389711006c361100000000000000000014361100010000000000000001000000000000001c3611000f00000000000000000000002b3611000b00000000000000000000000000000000000000000000000000000000000000389711003836110000000000000000004836110001000000000000000100000000000000503611001b00000000000000000000009f8d11000c00000000000000000000000000000000000000000000000000000000000000389711006c36110000000000000000007c36110001000000000000000100000000000000843611001600000000000000000000009a361100090000000000000000000000000000000000000000000000000000000000000038971100a43611000000000000000000b436110001000000000000000100000000000000bc3611000900000000000000000000007a6511000c0000000000000000000000000000000000000000000000000000000000000038971100c83611000000000000000000d836110003000000000000000100000000000000f0361100080000000000000000000000f83611000700000000000000000000000000000000000000000000000000000000000000389711000037110000000000000000001037110001000000000000000100000000000000183711001300000000000000000000002b37110007000000000000000000000000000000000000000000000000000000000000003897110034371100000000000000000044371100030000000000000001000000000000005c3711000a0000000000000000000000663711001d0000000000000000000000000000000000000000000000000000000000000038971100d0371100000000000000000084371100010000000000000001000000000000008c3711000f00000001010000000000000a36110008000000000000009b371100320000000000000000000000000000000000000038971100d03711000000000000000000e037110001000000000000000100000056616c696461746f72436f756e74753332000000da3d11002a0000004d696e696d756d56616c696461746f72436f756e74000000370000000000000001000000c60000008a3d110050000000496e76756c6e657261626c6573000000b63c1100560000000c3d1100530000005f3d11002b000000426f6e6465640000763c1100400000004c65646765725374616b696e674c65646765723c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e003700000000000000010000004f000000253c11005100000050617965650000003700000000000000010000004f000000ec3b11003900000056616c696461746f72730000370000000000000001000000c70000009b3b1100510000004e6f6d696e61746f72730000423b1100590000005374616b6572734578706f737572653c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e00370000000000000001000000c8000000853a110053000000d83a11004600000038971100000000001e3b11002400000043757272656e74456c65637465640000463a11003f00000043757272656e74457261457261496e64657800002f3a11001700000043757272656e7445726153746172744d6f6d656e744f663c543e0000370000000000000001000000ab000000113a11001e00000043757272656e74457261537461727453657373696f6e496e646578003700000000000000010000009c000000dd3911003400000043757272656e74457261506f696e74734561726e6564457261506f696e747300370000000000000001000000c90000009a39110043000000536c6f745374616b65000000370000000000000001000000980000001e3911004c00000038971100000000006a39110030000000466f726365457261466f7263696e67003700000000000000010000004f000000d738110047000000536c6173685265776172644672616374696f6e50657262696c6c0000370000000000000001000000ca000000603811003e00000038971100000000009e38110039000000426f6e646564457261735665633c28457261496e6465782c2053657373696f6e496e646578293e001738110049000000457261536c6173684a6f75726e616c5665633c536c6173684a6f75726e616c456e7472793c543a3a4163636f756e7449642c2042616c616e63654f663c543e3e3e00000037000000000000000100000050000000e83711002f00000020416c6c20736c617368657320746861742068617665206f6363757272656420696e206120676976656e206572612e2041206d617070696e672066726f6d207374696c6c2d626f6e646564206572617320746f207468652066697273742073657373696f6e20696e646578206f662074686174206572612e205468652070657263656e74616765206f662074686520736c617368207468617420697320646973747269627574656420746f207265706f72746572732e205468652072657374206f662074686520736c61736865642076616c75652069732068616e646c6564206279207468652060536c617368602e205472756520696620746865206e6578742073657373696f6e206368616e67652077696c6c2062652061206e657720657261207265676172646c657373206f6620696e6465782e2054686520616d6f756e74206f662062616c616e6365206163746976656c79206174207374616b6520666f7220656163682076616c696461746f7220736c6f742c2063757272656e746c792e2054686973206973207573656420746f20646572697665207265776172647320616e642070756e6973686d656e74732e205265776172647320666f72207468652063757272656e74206572612e205573696e6720696e6469636573206f662063757272656e7420656c6563746564207365742e205468652073657373696f6e20696e646578206174207768696368207468652063757272656e742065726120737461727465642e20546865207374617274206f66207468652063757272656e74206572612e205468652063757272656e742065726120696e6465782e205468652063757272656e746c7920656c65637465642076616c696461746f7220736574206b65796564206279207374617368206163636f756e742049442e204e6f6d696e61746f727320666f72206120706172746963756c6172206163636f756e74207468617420697320696e20616374696f6e207269676874206e6f772e20596f752063616e27742069746572617465207468726f7567682076616c696461746f727320686572652c2062757420796f752063616e2066696e64207468656d20696e207468652053657373696f6e206d6f64756c652e2054686973206973206b6579656420627920746865207374617368206163636f756e742e20546865206d61702066726f6d206e6f6d696e61746f72207374617368206b657920746f2074686520736574206f66207374617368206b657973206f6620616c6c2076616c696461746f727320746f206e6f6d696e6174652e20546865206d61702066726f6d202877616e6e616265292076616c696461746f72207374617368206b657920746f2074686520707265666572656e636573206f6620746861742076616c696461746f722e2057686572652074686520726577617264207061796d656e742073686f756c64206265206d6164652e204b657965642062792073746173682e204d61702066726f6d20616c6c2028756e6c6f636b6564292022636f6e74726f6c6c657222206163636f756e747320746f2074686520696e666f20726567617264696e6720746865207374616b696e672e204d61702066726f6d20616c6c206c6f636b65642022737461736822206163636f756e747320746f2074686520636f6e74726f6c6c6572206163636f756e742e20416e792076616c696461746f72732074686174206d6179206e6576657220626520736c6173686564206f7220666f726369626c79206b69636b65642e20497427732061205665632073696e63652074686579277265206561737920746f20696e697469616c697a6520616e642074686520706572666f726d616e636520686974206973206d696e696d616c2028776520657870656374206e6f206d6f7265207468616e20666f757220696e76756c6e657261626c65732920616e64207265737472696374656420746f20746573746e6574732e204d696e696d756d206e756d626572206f66207374616b696e67207061727469636970616e7473206265666f726520656d657267656e637920636f6e646974696f6e732061726520696d706f7365642e2054686520696465616c206e756d626572206f66207374616b696e67207061727469636970616e74732e00000000743e11000e000000000000009f8d11000c0000000000000038971100843e11000000000000000000943e11000100000000000000000000009c3e11000f000000000000000a361100080000000000000038971100ac3e11000000000000000000bc3e1100010000000000000053657373696f6e735065724572610000370000000000000001000000a5000000fd3e11001c000000426f6e64696e674475726174696f6e00370000000000000001000000cb000000c43e110039000000204e756d626572206f6620657261732074686174207374616b65642066756e6473206d7573742072656d61696e20626f6e64656420666f722e204e756d626572206f662073657373696f6e7320706572206572612e5374616b696e6720536c6f745374616b650000603f110019000000803f110048000000bb0100002d0000005374616b696e6720457261536c6173684a6f75726e616c0000000000617474656d707420746f20646976696465206279207a65726f000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f6f70732f61726974682e72735374616b696e6720496e76756c6e657261626c6573000000387d110028000000f83f1100420000009c020000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f7374616b696e672f7372632f6c69622e72730000f83f1100420000009c02000001000000636f6e74726f6c6c657220616c72656164792070616972656463616e206e6f7420626f6e6420776974682076616c7565206c657373207468616e206d696e696d756d2062616c616e6365737461736820616c726561647920626f6e6465646e6f7420612073746173686e6f74206120636f6e74726f6c6c657263616e206e6f74207363686564756c65206d6f726520756e6c6f636b206368756e6b73746172676574732063616e6e6f7420626520656d7074790000000000e44211000800000000000000ec42110002000000000000000000000038971100000000000000000000000000fc421100060000000000000004431100030000000000000000000000389711000000000000000000000000001c4311000e0000000000000038971100000000000000000000000000389711000000000000000000000000002a431100070000000000000034431100020000000000000000000000389711000000000000000000000000004443110006000000000000004c431100010000000000000000000000389711000000000000000000000000005443110009000000000000004c431100010000000000000000000000389711000000000000000000000000005d43110009000000000000004c4311000100000000000000000000003897110000000000000000000000000066431100080000000000000070431100020000000000000000000000389711000000000000000000000000008043110009000000000000008c431100020000000000000000000000389711000000000000000000000000009c4311000b00000000000000a843110001000000000000000000000038971100000000000000000000000000b04311000600000000000000b843110003000000000000000000000038971100000000000000000050726f706f736564084411000900000011441100070000005461626c6564000008441100090000001144110007000000184411000e00000045787465726e616c5461626c656453746172746564000000e84311000f000000fb4311000d0000005061737365640000e84311000f0000004e6f7450617373656443616e63656c6c656445786563757465640000e84311000f000000f74311000400000044656c656761746564000000d043110009000000d043110009000000556e64656c65676174656400d0431100090000005665746f65640000d043110009000000d943110004000000dd4311000b0000004163636f756e74496448617368426c6f636b4e756d6265725265666572656e64756d496e646578626f6f6c566f74655468726573686f6c6450726f70496e64657842616c616e63655665633c4163636f756e7449643e44656d6f637261637920566f74654f6644656d6f6372616379205265666572656e64756d496e666f4f6644656d6f63726163792044656c65676174696f6e7368656164206f662044656d6f63726163792044656c65676174696f6e7344656d6f6372616379204469737061746368517565756544656d6f637261637920566f74657273466f7244656d6f6372616379205075626c696350726f70730000005045110048000000a10a00000e00000044656d6f6372616379204465706f7369744f664e6f207075626c69632070726f706f73616c732077616974696e6743616e6e6f7420696e6a6563742061207265666572656e64756d207468617420656e6473206561726c696572207468616e2070726563656564696e67207265666572656e64756d000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727344656d6f6372616379204e65787445787465726e616c4e6f2065787465726e616c2070726f706f73616c2077616974696e67000000000000b84811000700000000000000c0481100020000000000000000000000f0481100060000000000000000000000204911000600000000000000284911000100000000000000000000004049110006000000000000000000000070491100040000000000000074491100020000000000000000000000a4491100070000000000000000000000dc4911000a0000000000000074491100020000000000000000000000e8491100070000000000000000000000204a11001000000000000000304a1100010000000000000000000000484a1100020000000000000000000000584a11001000000000000000684a1100010000000000000000000000804a1100020000000000000000000000904a11001900000000000000684a1100010000000000000000000000ac4a1100050000000000000000000000d44a11001800000000000000684a1100010000000000000000000000ec4a1100050000000000000000000000144b11000a00000000000000204b1100030000000000000000000000684b1100080000000000000000000000a84b11000d00000000000000b84b1100010000000000000000000000d04b1100010000000000000000000000d84b11001100000000000000ec4b1100010000000000000000000000044c11000100000000000000000000000c4c11000d000000000000001c4c1100030000000000000000000000644c11000100000000000000000000006c4c11000900000000000000784c1100010000000000000000000000904c1100050000000000000000000000b84c11000c0000000000000038971100000000000000000000000000c44c1100050000000000000000000000ec4c11000c00000000000000784c1100010000000000000000000000f84c1100050000000000000000000000204d11000800000000000000284d1100020000000000000000000000584d1100050000000000000000000000804d11000a00000000000000389711000000000000000000000000008c4d1100050000000000000070726f706f736500000000005853110008000000000000006053110010000000000000005f55110005000000000000006455110015000000f5541100280000003897110000000000c54d11000b000000d04d1100080000003f55110020000000d84d11000c0000007365636f6e640000000000005853110008000000000000002d55110012000000f5541100280000003897110000000000c54d11000b000000d04d1100080000001d55110010000000d84d11000c000000766f746500000000374f110009000000000000000a4f11001800000000000000704911000400000000000000f154110004000000755411004d000000c25411002f0000003897110000000000c54d11000b000000d04d110008000000565411001f000000d84d11000c00000070726f78795f766f74650000c453110054000000185411003e0000003897110000000000c54d11000b000000d04d110008000000565411001f000000d84d11000c000000656d657267656e63795f63616e63656c00000000374f11000900000000000000e84311000f00000070531100540000004c5311000c00000065787465726e616c5f70726f706f7365000000005853110008000000000000006053110010000000005311004c0000004c5311000c00000065787465726e616c5f70726f706f73655f6d616a6f726974790000009252110056000000e852110018000000389711000000000018521100530000006b5211002700000065787465726e616c5f70726f706f73655f64656661756c74a551110052000000f751110021000000389711000000000018521100530000006b52110027000000666173745f747261636b0000000000006f4f11000d000000000000007c4f11000700000000000000855111000d00000000000000925111000e00000000000000a05111000500000000000000925111000e000000834f110054000000d74f110059000000305011003b00000038971100000000006b5011003e000000a95011004b000000f450110055000000495111003c0000007665746f5f65787465726e616c000000000000006f4f11000d000000000000007c4f110007000000404f11002f00000063616e63656c5f7265666572656e64756d00000000000000374f110009000000000000000a4f110018000000224f11001500000063616e63656c5f71756575656400000000000000da4e11000400000000000000de4e11001700000000000000f54e11000500000000000000fa4e11000c00000000000000064f110004000000000000000a4f110018000000b24e1100280000007365745f70726f787900000000000000ad4e110005000000000000000b4e11000c000000874e1100260000003897110000000000c54d11000b000000f34d110016000000d84d11000c00000072657369676e5f70726f7879614e1100260000003897110000000000c54d11000b000000514e110010000000d84d11000c00000072656d6f76655f70726f78792b4e1100260000003897110000000000c54d11000b000000514e110010000000d84d11000c00000064656c656761746500000000094e110002000000000000000b4e11000c00000000000000174e11000a00000000000000214e11000a000000e44d11000f0000003897110000000000c54d11000b000000f34d110016000000d84d11000c000000756e64656c65676174650000b44d1100110000003897110000000000c54d11000b000000d04d110008000000d84d11000c00000020556e64656c656761746520766f74652e2023203c7765696768743e202d204f2831292e2023203c2f7765696768743e2044656c656761746520766f74652e202d204f6e6520657874726120444220656e7472792e746f543a3a4163636f756e744964636f6e76696374696f6e436f6e76696374696f6e20436c656172207468652070726f78792e2043616c6c6564206279207468652073746173682e202d204f6e6520444220636c6561722e20436c656172207468652070726f78792e2043616c6c6564206279207468652070726f78792e205370656369667920612070726f78792e2043616c6c6564206279207468652073746173682e70726f78792043616e63656c20612070726f706f73616c2071756575656420666f7220656e6163746d656e742e7768656e436f6d706163743c543a3a426c6f636b4e756d6265723e7768696368436f6d706163743c7533323e77686174436f6d706163743c5265666572656e64756d496e6465783e2052656d6f76652061207265666572656e64756d2e7265665f696e646578205665746f20616e6420626c61636b6c697374207468652065787465726e616c2070726f706f73616c20686173682e70726f706f73616c5f68617368543a3a48617368205363686564756c65207468652063757272656e746c792065787465726e616c6c792d70726f706f736564206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c656420696d6d6564696174656c792e204966207468657265206973206e6f2065787465726e616c6c792d70726f706f736564207265666572656e64756d2063757272656e746c792c206f72206966207468657265206973206f6e6520627574206974206973206e6f742061206d616a6f726974792d63617272696573207265666572656e64756d207468656e206974206661696c732e202d206070726f706f73616c5f68617368603a205468652068617368206f66207468652063757272656e742065787465726e616c2070726f706f73616c2e202d2060766f74696e675f706572696f64603a2054686520706572696f64207468617420697320616c6c6f77656420666f7220766f74696e67206f6e20746869732070726f706f73616c2e202d206064656c6179603a20546865206e756d626572206f6620626c6f636b20616674657220766f74696e672068617320656e64656420696e20617070726f76616c20616e6420746869732073686f756c64206265202020656e61637465642e20496e6372656173656420746f2060456d657267656e6379566f74696e67506572696f646020696620746f6f206c6f772e766f74696e675f706572696f64543a3a426c6f636b4e756d62657264656c6179205363686564756c652061206e656761746976652d7475726e6f75742d62696173207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e20556e6c696b65206065787465726e616c5f70726f706f7365602c20626c61636b6c697374696e6720686173206e6f20656666656374206f6e207468697320616e64206974206d6179207265706c6163652061207072652d7363686564756c6564206065787465726e616c5f70726f706f7365602063616c6c2e205363686564756c652061206d616a6f726974792d63617272696573207265666572656e64756d20746f206265207461626c6564206e657874206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e205363686564756c652061207265666572656e64756d20746f206265207461626c6564206f6e6365206974206973206c6567616c20746f207363686564756c6520616e2065787465726e616c207265666572656e64756d2e70726f706f73616c426f783c543a3a50726f706f73616c3e205363686564756c6520616e20656d657267656e63792063616e63656c6c6174696f6e206f662061207265666572656e64756d2e2043616e6e6f742068617070656e20747769636520746f207468652073616d6520566f746520696e2061207265666572656e64756d206f6e20626568616c66206f6620612073746173682e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b20206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e202d204f6e65204442206368616e67652c206f6e6520444220656e7472792e20566f746520696e2061207265666572656e64756d2e2049662060766f74652e69735f6179652829602c2074686520766f746520697320746f20656e616374207468652070726f706f73616c3b206f7468657277697365206974206973206120766f746520746f206b65657020746865207374617475732071756f2e566f74652050726f706f736520612073656e73697469766520616374696f6e20746f2062652074616b656e2e202d204f6e6520444220656e7472792e436f6d706163743c50726f70496e6465783e202d2054776f204442206368616e6765732c206f6e6520444220656e7472792e76616c7565436f6d706163743c42616c616e63654f663c543e3e44656d6f6372616379000000000000ac5a11000f0000000000000000000000084411000900000000000000000000000000000000000000000000000000000000000000389711006c5b11000000000000000000bc5a110001000000000000000100000000000000c45a11000b0000000000000000000000cf5a11002b0000000000000000000000000000000000000000000000000000000000000038971100385c11000000000000000000fc5a110001000000000000000100000000000000045b11000900000001010000000000000844110009000000000000000d5b1100210000000000000000000000000000000000000038971100305b11000000000000000000405b110001000000000000000000000000000000485b11000f0000000000000000000000e84311000f00000000000000000000000000000000000000000000000000000000000000389711006c5b11000000000000000000585b110001000000000000000100000000000000605b1100090000000000000000000000e84311000f00000000000000000000000000000000000000000000000000000000000000389711006c5b110000000000000000007c5b110001000000000000000100000000000000845b1100100000000101000000000000e84311000f00000000000000945b11002d0000000000000000000000000000000000000038971100b05c11000000000000000000c45b110001000000000000000000000000000000cc5b11000d0000000101000000000000925111000e00000000000000d95b11002b0000000000000000000000000000000000000038971100045c11000000000000000000145c1100010000000000000001000000000000001c5c1100090000000101000000000000e84311000f00000000000000255c1100110000000000000000000000000000000000000038971100385c11000000000000000000485c110001000000000000000100000000000000505c1100060000000101000000000000565c11001f00000000000000f1541100040000000000000000000000000000000000000038971100785c11000000000000000000885c110004000000000000000100000000000000a85c11000500000001010000000000000b4e11000c000000000000000b4e11000c0000000000000000000000000000000000000038971100b05c11000000000000000000c05c110002000000000000000000000000000000d05c11000b00000001010100000000000b4e11000c00000000000000db5c11001a0000000000000000000000000000000000000038971100f85c11000000000000000000085d110001000000000000000100000000000000105d1100150000000000000000000000f7431100040000000000000000000000000000000000000000000000000000000000000038971100ec5d11000000000000000000285d110002000000000000000100000000000000385d11000c0000000000000000000000445d11001c0000000000000000000000000000000000000000000000000000000000000038971100605d11000000000000000000705d110004000000000000000000000000000000905d11000900000001010000000000007c4f11000700000000000000995d1100230000000000000000000000000000000000000038971100bc5d11000000000000000000cc5d110002000000000000000000000000000000dc5d11000d00000001010000000000007c4f11000700000000000000f7431100040000000000000000000000000000000000000038971100ec5d11000000000000000000fc5d11000100000000000000010000005075626c696350726f70436f756e74006c6311003d0000005075626c696350726f70735665633c2850726f70496e6465782c20543a3a50726f706f73616c2c20543a3a4163636f756e744964293e00004c631100200000004465706f7369744f662842616c616e63654f663c543e2c205665633c543a3a4163636f756e7449643e290000370000000000000001000000a20000002b631100210000005265666572656e64756d436f756e7400df6211004c0000004e65787454616c6c790000003700000000000000010000009c000000ad621100320000005265666572656e64756d496e666f4f66285265666572656e64756d496e666f3c543a3a426c6f636b4e756d6265722c20543a3a50726f706f73616c3e29000000806211002d000000446973706174636851756575655665633c4f7074696f6e3c28543a3a50726f706f73616c2c205265666572656e64756d496e646578293e3e370000000000000001000000500000005062110030000000566f74657273466f725665633c543a3a4163636f756e7449643e0000370000000000000001000000500000002762110029000000566f74654f66285265666572656e64756d496e6465782c20543a3a4163636f756e744964290000003700000000000000010000004f000000e86011005800000040611100530000009361110057000000ea6111003d00000050726f78790000003700000000000000010000004f0000007a6011004c000000c66011002200000044656c65676174696f6e7328543a3a4163636f756e7449642c20436f6e76696374696f6e29000000370000000000000001000000cc0000002a601100500000004c6173745461626c656457617345787465726e616c000000ca5f110056000000206011000a0000004e65787445787465726e616c28543a3a50726f706f73616c2c20566f74655468726573686f6c6429370000000000000001000000cd000000dc5e110056000000325f110055000000875f110029000000b05f11001a000000426c61636b6c69737428543a3a426c6f636b4e756d6265722c205665633c543a3a4163636f756e7449643e29370000000000000001000000a20000004e5e110054000000a25e11003a00000043616e63656c6c6174696f6e730000003700000000000000010000004f000000045e11004a000000205265636f7264206f6620616c6c2070726f706f73616c7320746861742068617665206265656e207375626a65637420746f20656d657267656e63792063616e63656c6c6174696f6e2e2041207265636f7264206f662077686f207665746f656420776861742e204d6170732070726f706f73616c206861736820746f206120706f737369626c65206578697374656e7420626c6f636b206e756d6265722028756e74696c207768656e206974206d6179206e6f742062652072657375626d69747465642920616e642077686f207665746f65642069742e20546865207265666572656e64756d20746f206265207461626c6564207768656e6576657220697420776f756c642062652076616c696420746f207461626c6520616e2065787465726e616c2070726f706f73616c2e20546869732068617070656e73207768656e2061207265666572656e64756d206e6565647320746f206265207461626c656420616e64206f6e65206f662074776f20636f6e646974696f6e7320617265206d65743a202d20604c6173745461626c656457617345787465726e616c60206973206066616c7365603b206f72202d20605075626c696350726f70736020697320656d7074792e205472756520696620746865206c617374207265666572656e64756d207461626c656420776173207375626d69747465642065787465726e616c6c792e2046616c7365206966206974207761732061207075626c69632070726f706f73616c2e2047657420746865206163636f756e742028616e64206c6f636b20706572696f64732920746f20776869636820616e6f74686572206163636f756e742069732064656c65676174696e6720766f74652e2057686f2069732061626c6520746f20766f746520666f722077686f6d2e2056616c7565206973207468652066756e642d686f6c64696e67206163636f756e742c206b65792069732074686520766f74652d7472616e73616374696f6e2d73656e64696e67206163636f756e742e204765742074686520766f746520696e206120676976656e207265666572656e64756d206f66206120706172746963756c617220766f7465722e2054686520726573756c74206973206d65616e696e6766756c206f6e6c792069662060766f746572735f666f726020696e636c756465732074686520766f746572207768656e2063616c6c6564207769746820746865207265666572656e64756d2028796f75276c6c20676574207468652064656661756c742060566f7465602076616c7565206f7468657277697365292e20496620796f7520646f6e27742077616e7420746f20636865636b2060766f746572735f666f72602c207468656e20796f752063616e20616c736f20636865636b20666f722073696d706c65206578697374656e636520776974682060566f74654f663a3a657869737473602066697273742e204765742074686520766f7465727320666f72207468652063757272656e742070726f706f73616c2e205175657565206f66207375636365737366756c207265666572656e646120746f20626520646973706174636865642e20496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e20546865206e657874207265666572656e64756d20696e64657820746861742073686f756c642062652074616c6c6965642e20546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e6461207374617274656420736f206661722e2054686f73652077686f2068617665206c6f636b65642061206465706f7369742e20546865207075626c69632070726f706f73616c732e20556e736f727465642e20546865206e756d626572206f6620287075626c6963292070726f706f73616c7320746861742068617665206265656e206d61646520736f206661722e00000000000000fc6411000f00000000000000925111000e00000000000000389711000c65110000000000000000001c651100050000000000000000000000446511000c00000000000000925111000e0000000000000038971100e0651100000000000000000050651100010000000000000000000000586511000c00000000000000925111000e0000000000000038971100e06511000000000000000000646511000100000000000000000000006c6511000e000000000000007a6511000c000000000000003897110088651100000000000000000098651100010000000000000000000000a06511001500000000000000925111000e0000000000000038971100b86511000000000000000000c8651100010000000000000000000000d06511000d00000000000000925111000e0000000000000038971100e06511000000000000000000f06511000100000000000000456e6163746d656e74506572696f6400370000000000000001000000ce0000003f6711005c00000038971100000000009b6711004c000000e76711005a00000041681100270000004c61756e6368506572696f640667110039000000566f74696e67506572696f64d86611002e0000004d696e696d756d4465706f73697442616c616e63654f663c543e0000370000000000000001000000cf0000008b6611004d000000456d657267656e6379566f74696e67506572696f64000000370000000000000001000000d0000000506611003b000000436f6f6c6f6666506572696f64000000370000000000000001000000d1000000f86511005800000020506572696f6420696e20626c6f636b7320776865726520616e2065787465726e616c2070726f706f73616c206d6179206e6f742062652072652d7375626d6974746564206166746572206265696e67207665746f65642e204d696e696d756d20766f74696e6720706572696f6420616c6c6f77656420666f7220616e20656d657267656e6379207265666572656e64756d2e20546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e20486f77206f6674656e2028696e20626c6f636b732920746f20636865636b20666f72206e657720766f7465732e20486f77206f6674656e2028696e20626c6f636b7329206e6577207075626c6963207265666572656e646120617265206c61756e636865642e20546865206d696e696d756d20706572696f64206f66206c6f636b696e6720616e642074686520706572696f64206265747765656e20612070726f706f73616c206265696e6720617070726f76656420616e6420656e61637465642e2049742073686f756c642067656e6572616c6c792062652061206c6974746c65206d6f7265207468616e2074686520756e7374616b6520706572696f6420746f20656e73757265207468617420766f74696e67207374616b657273206861766520616e206f70706f7274756e69747920746f2072656d6f7665207468656d73656c7665732066726f6d207468652073797374656d20696e207468652063617365207768657265207468657920617265206f6e20746865206c6f73696e672073696465206f66206120766f74652e387d11002800000080681100440000004f010000010000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f73726d6c2f64656d6f63726163792f7372632f6c69622e7273036b110023000000d96a11002a00000080681100440000004f0100000100000076616c756520746f6f206c6f7770726f706f73657227732062616c616e636520746f6f206c6f7763616e206f6e6c79207365636f6e6420616e206578697374696e672070726f706f73616c7365636f6e64657227732062616c616e636520746f6f206c6f7744656d6f63726163792050726f78796e6f7420612070726f787944656d6f63726163792043616e63656c6c6174696f6e7370726f706f73616c207374696c6c20626c61636b6c697374656470726f706f73616c20616c7265616479206d61646544656d6f637261637920426c61636b6c697374696e76616c696420686173686e6578742065787465726e616c2070726f706f73616c206e6f742073696d706c65206d616a6f726974796e6f2070726f706f73616c206d616465756e6b6e6f776e2070726f706f73616c6e6f2065787465726e616c2070726f706f73616c6964656e74697479206d6179206e6f74207665746f20612070726f706f73616c207477696365616c726561647920612070726f787977726f6e672070726f78796e6f742064656c656761746564756e6b6e6f776e20696e64657863616e6e6f742063616e63656c207468652073616d652070726f706f73616c20747769636570726f706f73616c206e6f7420666f756e64766f746520676976656e20666f7220696e76616c6964207265666572656e64756d2e696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64653a205f5f5068616e746f6d4974656d2073686f756c64206e6576657220626520757365642e00003300000004000000040000002500000042725461626c65446174617461626c65330000000400000004000000d200000064656661756c744636345265696e74657270726574493634556e726561636861626c654e6f70426c6f636b00330000000400000004000000d30000004c6f6f704966456c7365456e6442724272496642725461626c650000330000000400000004000000d400000052657475726e43616c6c43616c6c496e6469726563740000330000000400000004000000d500000044726f7053656c6563744765744c6f63616c5365744c6f63616c5465654c6f63616c476574476c6f62616c536574476c6f62616c4933324c6f61644936344c6f61644633324c6f61644636344c6f61644933324c6f616438534933324c6f616438554933324c6f61643136534933324c6f61643136554936344c6f616438534936344c6f616438554936344c6f61643136534936344c6f61643136554936344c6f61643332534936344c6f616433325549333253746f726549363453746f726546333253746f726546363453746f726549333253746f72653849333253746f7265313649363453746f72653849363453746f7265313649363453746f7265333243757272656e744d656d6f727947726f774d656d6f7279493332436f6e737400330000000400000004000000d6000000493634436f6e7374330000000400000004000000d7000000463332436f6e7374463634436f6e73743300000004000000040000000900000049333245717a49333245714933324e654933324c74534933324c74554933324774534933324774554933324c65534933324c655549333247655349333247655549363445717a49363445714936344e654936344c74534936344c74554936344774534936344774554936344c65534936344c655549363447655349363447655546333245714633324e654633324c7446333247744633324c65463332476546363445714636344e654636344c7446363447744636344c654636344765493332436c7a49333243747a493332506f70636e744933324164644933325375624933324d756c493332446976534933324469765549333252656d5349333252656d55493332416e644933324f72493332586f7249333253686c4933325368725349333253687255493332526f746c493332526f7472493634436c7a49363443747a493634506f70636e744936344164644936345375624936344d756c493634446976534936344469765549363452656d5349363452656d55493634416e644936344f72493634586f7249363453686c4936345368725349363453687255493634526f746c493634526f74724633324162734633324e65674633324365696c463332466c6f6f724633325472756e634633324e656172657374463332537172744633324164644633325375624633324d756c4633324469764633324d696e4633324d6178463332436f70797369676e4636344162734636344e65674636344365696c463634466c6f6f724636345472756e634636344e656172657374463634537172744636344164644636345375624636344d756c4636344469764636344d696e4636344d6178463634436f70797369676e493332577261704936344933325472756e63534633324933325472756e63554633324933325472756e63534636344933325472756e6355463634493634457874656e6453493332493634457874656e64554933324936345472756e63534633324936345472756e63554633324936345472756e63534636344936345472756e6355463634463332436f6e7665727453493332463332436f6e7665727455493332463332436f6e7665727453493634463332436f6e766572745549363446333244656d6f7465463634463634436f6e7665727453493332463634436f6e7665727455493332463634436f6e7665727453493634463634436f6e766572745549363446363450726f6d6f74654633324933325265696e746572707265744633324936345265696e746572707265744636344633325265696e74657270726574493332496e76616c696444617461547261696c696e6744617461556e6578706563746564456f6600002c7111000b000000492f4f204572726f723a204e6f526573756c7456616c7565330000000400000004000000d80000004636344933324936344633324e6f6e65536f6d65330000000400000004000000d9000000656e7600907111005d0000001201000016000000000000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f6761732f6d6f642e72736c6173745f696e6465782069732067726561746572207468616e20303b206c6173745f696e64657820697320737461636b2073697a65202d20313b2071656470721100660000001001000017000000447211002500000043616c6c20746f2066756e6374696f6e2074686174206f75742d6f662d626f756e64733a20000000000000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f737461636b5f6865696768742f6d6f642e7273546869732073686f756c64206265206120696e646578206f66206120646566696e65642066756e6374696f6e44756520746f2076616c69646174696f6e20636f64652073656374696f6e2073686f756c642065786973747346756e6374696f6e20626f6479206973206f7574206f6620626f756e647366756e6374696f6e20696d706f727420636f756e74206973206e6f74207a65726f3b20696d706f72742073656374696f6e206d757374206578697374733b2071656466756e635f696478206973206c657373207468616e2066756e6374696f6e20696d706f72747320636f756e743b0a090909096e74682066756e6374696f6e20696d706f7274206d7573742062652060536f6d65603b0a0909090971656400f495110012000000417411000f000000147411000a0000001e74110014000000327411000f0000005369676e61747572652020287370656369666965642062792066756e6320292069736e277420646566696e6564206973206e6f7420646566696e65647372632f6c6962616c6c6f632f7665632e7273007c7411001c0000005074110013000000cc04000009000000617373657274696f6e206661696c65643a20656e64203c3d206c656e2075110048000000b1010000230000002075110048000000b201000023000000d074110049000000870200001d00000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f736f72742e7273000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e7273d0741100490000009d0000003a000000d074110049000000a4000000300000004d761100120000005f7611000c0000006066756e635f696478602073686f756c6420636f6d652066726f6d20606e6565645f7468756e6b73603b0a09090909606e6565645f7468756e6b736020697320706f70756c617465642077697468207468652073616d65206974656d73207468617420696e20607265706c6163656d656e745f6d6170603b0a090909097165644174207468697320706f696e7420616e20696e646578206d7573742062652061737369676e656420746f2065616368207468756e6b66756e6374696f6e207769746820696478202069736e277420666f756e644672616d6569735f706f6c796d6f72706869630000330000000400000004000000da000000656e645f6172697479000000330000000400000004000000250000006272616e63685f617269747973746172745f6865696768744e6f2066756e6374696f6e2073656374696f6e4e6f20636f64652073656374696f6e4e6f20747970652073656374696f6e000000e47911000a00000046756e6374696f6e206973206e6f7420666f756e6420696e2066756e632073656374696f6e46756e6374696f6e20626f647920666f722074686520696e6465782069736e277420666f756e64d87911000c000000447911000b000000737461636b206d757374206265206e6f6e2d656d70747900397911000b000000f078110006000000737461636b206f766572666c6f774172697479206f6620616c6c206a756d702d74617267657473206d75737420626520657175616c54797065206e6f7420666f756e6400e978110007000000e07711006d000000c8000000110000002f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f737461636b5f6865696768742f6d61785f6865696768742e72736d61785f686569676874707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768742f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f707761736d2d7574696c732d302e31312e302f7372632f737461636b5f6865696768742f6d61785f6865696768742e72737472756e633a20707573683a2000003479110005000000747279696e6720746f20706f70206d6f72652076616c756573207468616e20707573686564737461636b20756e646572666c6f77706f703a20756e726561636861626c65706f705f6672616d653a20636f6e74726f6c20737461636b20697320656d707479636f6e74726f6c20737461636b206f75742d6f662d626f756e647390791100480000009b0a00000a0000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e7273707573685f6672616d653a2066756e635f6964783a206578745f6368696c645f73746f726167655f726f6f74206e657665722072657475726e73207533323a3a6d61785f76616c75653b2071656452756e74696d65206d656d6f7279206578686175737465642e2041626f7274696e6753797374656d2073746174652063757272656e746c792070726576656e74732074686973207472616e73616374696f6e5472616e73616374696f6e20646f6573206e6f742068617665207265717569726564207065726d697373696f6e73496e76616c6964206f726967696e496e76616c69645472616e73616374696f6e20637573746f6d206572726f725472616e73616374696f6e20776f756c642065786861757374732074686520626c6f636b206c696d6974735472616e73616374696f6e2068617320616e20616e6369656e7420626972746820626c6f636b5472616e73616374696f6e20686173206120626164207369676e61747572655472616e73616374696f6e206973206f757464617465645472616e73616374696f6e2077696c6c2062652076616c696420696e2074686520667574757265496e6162696c69747920746f2070617920736f6d6520666565732028652e672e206163636f756e742062616c616e636520746f6f206c6f77295472616e73616374696f6e2063616c6c206973206e6f74206578706563746564556e6b6e6f776e5472616e73616374696f6e20637573746f6d206572726f72436f756c64206e6f742066696e6420616e20756e7369676e65642076616c696461746f7220666f722074686520756e7369676e6564207472616e73616374696f6e436f756c64206e6f74206c6f6f6b757020696e666f726d6174696f6e20726571756972656420746f2076616c696461746520746865207472616e73616374696f6e00a07c110019000000c07c1100500000005800000022000000000000000000000000000000617474656d707420746f20646976696465206279207a65726f000000000000002f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d7072696d6974697665732f7372632f67656e657269632f6572612e727348617368206e6f7420657175616c0000387d110028000000607d1100500000008700000009000000696e7465726e616c206572726f723a20656e746572656420756e726561636861626c6520636f64652f686f6d652f616e6472652f576f726b62656e63682f706172697479746563682f7375627374726174652f636f72652f73722d73616e64626f782f7372632f2e2e2f776974686f75745f7374642e7273387d110028000000607d1100500000009000000009000000417574686f727368697020446964536574556e636c6573426162652045706f6368496e6465784261626520417574686f726974696573426162652047656e65736973536c6f74426162652043757272656e74536c6f74426162652052616e646f6d6e65737342616265204e65787452616e646f6d6e65737342616265205365676d656e74496e6465784261626520556e646572436f6e737472756374696f6e4261626520496e697469616c697a656462616265736c6f74436f756c64206e6f74206465636f64652072657175657374656420696e686572656e742074797065214241424520696e686572656e742064617461206e6f7420666f756e64746f6f206d616e7920696e737472756374696f6e73000000f47e110024000000187f1100170000005d02000009000000547269656420746f20736872696e6b20746f2061206c61726765722063617061636974797372632f6c6962616c6c6f632f7261775f7665632e7273436f6e7472616374204761735370656e74436f6e74726163742043757272656e745363686564756c65436f6e7472616374204163636f756e74436f756e7465726761736578745f7365745f73746f726167656578745f6765745f73746f726167656578745f63616c6c6578745f696e7374616e74696174656578745f72657475726e6578745f63616c6c65726578745f616464726573736578745f6761735f70726963656578745f6761735f6c6566746578745f62616c616e63656578745f76616c75655f7472616e736665727265646578745f72616e646f6d6578745f6e6f776578745f6d696e696d756d5f62616c616e63656578745f64697370617463685f63616c6c6578745f726573746f72655f746f6578745f736372617463685f73697a656578745f736372617463685f726561646578745f736372617463685f77726974656578745f6465706f7369745f6576656e746578745f7365745f72656e745f616c6c6f77616e63656578745f72656e745f616c6c6f77616e63656578745f7072696e746c6e6578745f626c6f636b5f6e756d6265724e6f6e2d656d7074792066756e6374696f6e20626f647920657870656374656400a68111000f000000b581110002000000b7811100030000001881110030000000488111005e0000007a00000005000000617373657274696f6e206661696c65643a20636f6e746578742e6672616d655f737461636b2e69735f656d70747928292f686f6d652f616e6472652f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7761736d692d76616c69646174696f6e2d302e322e302f7372632f66756e632e7273417420696e737472756374696f6e202840293a2000008082110048000000b1010000230000008082110048000000b201000023000000598211001c0000006898110018000000e50300000d0000001082110049000000870200001d0000000000000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f736f72742e7273617373657274696f6e206661696c65643a206d6964203c3d206c656e00000000000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e727310821100490000009d0000003a0000001082110049000000a40000003000000052657475726e207479706573206c656e6774682073686f756c642062652030206f722031178511001e000000358511001f00000066756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2071656466756e6374696f6e5f73656374696f6e5f6c656e20213d20303b2066756e6374696f6e5f73656374696f6e5f6c656e203d3d20636f64655f73656374696f6e5f6c656e3b207165640000fd8411001a000000d88411000a000000e28411001b00000073746172742066756e6374696f6e20657870656374656420746f20686176652074797065205b5d202d3e205b5d000000c784110011000000a78411002000000087841100200000005f841100280000007365676d656e74206f66667365742073686f756c642072657475726e2049333270617373697665206d656d6f7279207365676d656e747320617265206e6f7420737570706f727465647061737369766520656c656d656e74207365676d656e747320617265206e6f7420737570706f72746564746f6f206d616e79206d656d6f727920726567696f6e7320696e20696e6465782073706163653a20746f6f206d616e79207461626c657320696e20696e6465782073706163653a20747279696e6720746f20696d706f7274206d757461626c6520676c6f62616c206475706c6963617465206578706f72742046756e6374696f6e20232072656164696e672f76616c69646174696f6e206572726f723a204d697373696e6720626f647920666f722066756e6374696f6e206c656e677468206f662066756e6374696f6e2073656374696f6e206973202c207768696c65206c656e206f6620636f64652073656374696f6e2069732043616e2774206465636f6465207761736d20636f64654d6f64756c65206973206e6f742076616c69646d6f64756c65206465636c6172657320696e7465726e616c206d656d6f72796d756c7469706c65207461626c6573206465636c617265647461626c652065786365656473206d6178696d756d2073697a6520616c6c6f776564757365206f6620666c6f6174696e6720706f696e74207479706520696e2066756e6374696f6e20747970657320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e206c6f63616c7320697320666f7262696464656e757365206f6620666c6f6174696e6720706f696e74207479706520696e20676c6f62616c7320697320666f7262696464656e67617320696e737472756d656e746174696f6e206661696c6564737461636b2068656967687420696e737472756d656e746174696f6e206661696c656463616c6c6465706c6f796465706c6f792066756e6374696f6e2069736e2774206578706f72746564756e6b6e6f776e206578706f72743a20657870656374696e67206f6e6c79206465706c6f7920616e642063616c6c2066756e6374696f6e7366756e6374696f6e206861732061206e6f6e2d6578697374656e7420747970656578706f72742072656665727320746f206e6f6e2d6578697374656e742066756e6374696f6e657870656374656420612066756e6374696f6e656e74727920706f696e7420706f696e747320746f20616e20696d706f727465642066756e6374696f6e656e74727920706f696e74206861732077726f6e67207369676e617475726563616c6c2066756e6374696f6e2069736e2774206578706f727465646572726f722073657269616c697a696e6720696e737472756d656e746564206d6f64756c6500000000000001000000020000000400000008000000100000002000000044656d6f6372616379205075626c696350726f70436f756e7444656d6f6372616379205265666572656e64756d436f756e7444656d6f6372616379204e65787454616c6c7944656d6f6372616379204c6173745461626c656457617345787465726e616c436f756e63696c20446573697265645365617473436f756e63696c20566f7465436f756e74436f756e63696c204e657874566f746572536574436f756e63696c20566f746572436f756e74436f756e63696c2043616e646964617465436f756e7454696d657374616d7020496e697469616c697a6564000000000000708911000e0000000000000080891100010000000000000000000000888911000100000000000000000000009089110006000000000000003897110000000000000000000000000098891100010000000000000000000000a0891100070000000000000038971100000000000000000000000000a889110001000000000000004e6577417574686f7269746965730000238a110023000000ff891100240000005061757365640000d889110027000000526573756d656400b0891100280000002043757272656e7420617574686f726974792073657420686173206265656e20726573756d65642e2043757272656e7420617574686f726974792073657420686173206265656e207061757365642e204e657720617574686f726974792073657420686173206265656e206170706c6965642e5665633c28417574686f7269747949642c20417574686f72697479576569676874293e4772616e64706146696e616c69747920417574686f7269746965734772616e64706146696e616c6974792043757272656e7453657449644772616e64706146696e616c69747920536574496453657373696f6e4f6666636861696e206572726f723a206665746368696e67206e6574776f726b207374617465206661696c6564214f6666636861696e206572726f723a207369676e696e67206661696c6564214f6666636861696e206572726f723a206465636f64696e6720576f726b6572537461747573206661696c6564214f6666636861696e206572726f723a207375626d697474696e67207472616e73616374696f6e206661696c656421496d4f6e6c696e65205265636569766564486561727462656174734f6666656e636573205265706f72747342794b696e64496e6465780000000000a48b11000700000000000000ac8b1100020000000000000000000000bc8b110002000000000000004f6666656e6365006f8c110004000000738c11000e000000cc8b110055000000218c11004e00000020546865726520697320616e206f6666656e6365207265706f72746564206f662074686520676976656e20606b696e64602068617070656e656420617420746865206073657373696f6e5f696e6465786020616e6420286b696e642d7370656369666963292074696d6520736c6f742e2054686973206576656e74206973206e6f74206465706f736974656420666f72206475706c696361746520736c61736865732e4b696e644f706171756554696d65536c6f7453657373696f6e2053746f72656452616e676553657373696f6e2043757272656e74496e64657853657373696f6e205175657565644368616e67656453657373696f6e2044697361626c656456616c696461746f72730000000000048d11000a00000000000000108d1100010000000000000000000000188d110002000000000000004e657753657373696f6e00009f8d11000c000000288d1100550000007d8d110022000000204e65772073657373696f6e206861732068617070656e65642e204e6f746520746861742074686520617267756d656e74206973207468652073657373696f6e20696e6465782c206e6f742074686520626c6f636b206e756d626572206173207468652074797065206d6967687420737567676573742e53657373696f6e496e64657800c08d110048000000a10a00000e000000000000002f72757374632f316464313838343839313633366430656235313135376431333732333030373662636632303632372f7372632f6c6962636f72652f736c6963652f6d6f642e72735374616b696e672056616c696461746f72436f756e745374616b696e67204d696e696d756d56616c696461746f72436f756e745374616b696e672043757272656e744572615374616b696e672043757272656e74457261537461727453657373696f6e496e6465785374616b696e672043757272656e74457261506f696e74734561726e65645374616b696e6720466f7263654572615374616b696e6720536c6173685265776172644672616374696f6e5374616b696e6720426f6e646564457261730000000000248f1100100000000000000038971100000000000000000000000000348f11000100000000000000000000003c8f11000f000000000000004c8f1100010000000000000000000000548f1100010000000000000045787472696e736963537563636573737e8f11002500000045787472696e7369634661696c656400718f11000d0000005c8f11001500000020416e2065787472696e736963206661696c65642e44697370617463684572726f7220416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e52657175697265526f6f744f726967696e526571756972655369676e65644f726967696e426c6f636b46756c6c4261645369676e617475726543616e206e6f74206c6f6f6b7570526571756972654e6f4f726967696e53797374656d2045787472696e736963436f756e7453797374656d20416c6c45787472696e7369637357656967687453797374656d20416c6c45787472696e736963734c656e53797374656d204e6578745765696768744d756c7469706c69657253797374656d2045787472696e7369634461746153797374656d204576656e74436f756e7474696d737461703054696d657374616d7020696e686572656e742064617461206973206e6f742070726f76696465642e496e76616c69642074696d657374616d7020696e686572656e74206461746120656e636f64696e672e54696d657374616d702044696455706461746554726561737572792050726f706f73616c436f756e74547265617375727920417070726f76616c736d616b655f746f705f6672616d655f706f6c796d6f72706869632069732063616c6c6564207769746820656d707479206672616d6520737461636b0000db0000000c00000004000000dc000000746869732066756e6374696f6e2063616e27742062652063616c6c6564207769746820656d707479206672616d6520737461636b4d6973706c6163656420656c736520696e737472756374696f6e0000d8921100470000001f931100050000009c92110037000000d3921100050000006a921100170000006192110009000000b29411001400000049921100180000006192110009000000b294110014000000189211001d00000035921100130000004892110001000000546f6f206c61726765206d656d6f727920616c69676e6d656e7420325e20286578706563746564206174206d6f73742029547279696e6720746f2075706461746520676c6f62616c20206f66207479706520547279696e6720746f20757064617465206c6f63616c20416e795370656369666963330000000400000004000000d80000004c6162656c7320696e2062725f7461626c6520706f696e747320746f20626c6f636b206f6620646966666572656e742074797065733a2020616e6420496620626c6f636b20776974686f757420656c736520726571756972656420746f2068617665204e6f526573756c7420626c6f636b20747970652e204275742069742068617320207479706534931100180000004c9311000b000000556e657870656374656420737461636b20686569676874202c20657870656374656420547279696e6720746f2061636365737320706172656e74206672616d6520737461636b2076616c7565732e00009493110017000000ab9311001600000045787065637465642076616c7565206f66207479706520206f6e20746f70206f6620737461636b2e20476f7420000000cc93110007000000537461636b3a20000000010056941100240000002c94110006000000329411000e000000409411001600000008941100240000002c941100060000006d6178696d756d206d656d6f72792073697a65206d757374206265206174206d6f7374202070616765736d6178696d756d206c696d697420206973206c657373207468616e206d696e696d756d20696e697469616c206d656d6f72792073697a65206d757374206265206174206d6f73742000008c94110026000000b294110014000000547279696e6720746f20696e697469616c697a65207661726961626c65206f6620747970652020776974682076616c7565206f66207479706520496e69742065787072657373696f6e2073686f756c6420616c776179732062652077697468206c656e67746820324e6f6e20636f6e7374616e74206f70636f646520696e20696e697420657870725d951100070000006f951100220000005d95110007000000649511000b00000045787072657373696f6e20646f65736e277420656e647320776974682060656e6460206f70636f6465476c6f62616c20206973206d757461626c6520646f65736e277420657869737473206f72206e6f742079657420646566696e6564000000a495110010000000b49511000f0000004d656d6f727920617420696e6465782020646f65736e27742065786973747300d49511000f000000b49511000f0000005461626c6520617420696e6465782000f495110012000000b49511000f00000046756e6374696f6e20617420696e646578200000189611000e000000b49511000f0000005479706520617420696e6465782000008696110010000000b49511000f0000005896110010000000789611000e00000058961100100000006896110010000000457870656374656420676c6f62616c2020746f20626520696d6d757461626c6520746f206265206d757461626c65476c6f62616c20617420696e646578206e6f6e2d656d70747920737461636b2065787065637465640000c096110020000000e096110012000000747279696e6720746f206765742076616c756520617420706f736974696f6e20206f6e20737461636b206f662073697a6520636865636b656420636f75706c65206f66206c696e65732061626f7665001897110015000000657863656564656420737461636b206c696d69742000000038971100000000004572726f72000000330000000400000004000000dd0000004c6f63616c732072616e6765206e6f7420696e2033322d6269742072616e67658897110022000000aa97110015000000bf97110007000000547279696e6720746f20616363657373206c6f63616c207769746820696e64657820207768656e20746865726520617265206f6e6c7920206c6f63616c730000e09711002d0000000d9811000c0000001998110003000000617373657274696f6e206661696c65643a2060286c656674203d3d20726967687429600a20206c6566743a2060602c0a2072696768743a2060603a20249811003400000064657374696e6174696f6e20616e6420736f7572636520736c69636573206861766520646966666572656e74206c656e67746873689811001800000058080000090000007372632f6c6962636f72652f736c6963652f6d6f642e7273004180b1c6000b08000000000000000000bfbb03046e616d6501b6bb03a305000e6578745f626c616b65325f323536011f6578745f6765745f616c6c6f63617465645f6368696c645f73746f7261676502176578745f636c6561725f6368696c645f73746f7261676503146578745f6765745f73746f726167655f696e746f04166578745f6b696c6c5f6368696c645f73746f7261676505156578745f7365745f6368696c645f73746f7261676506196578745f6765745f616c6c6f63617465645f73746f72616765070f6578745f7365745f73746f72616765080c6578745f74776f785f31323809116578745f636c6561725f73746f726167650a126578745f737232353531395f7665726966790b0e6578745f7072696e745f757466380c0d6578745f7072696e745f6e756d0d166578745f6368696c645f73746f726167655f726f6f740e106578745f636c6561725f7072656669780f166578745f73616e64626f785f6d656d6f72795f6e6577101b6578745f73616e64626f785f6d656d6f72795f74656172646f776e11176578745f73616e64626f785f696e7374616e746961746512126578745f73616e64626f785f696e766f6b65131d6578745f73616e64626f785f696e7374616e63655f74656172646f776e14106578745f73746f726167655f726f6f7415186578745f73746f726167655f6368616e6765735f726f6f7416126578745f656432353531395f76657269667917166578745f73616e64626f785f6d656d6f72795f67657418166578745f73616e64626f785f6d656d6f72795f736574190d6578745f7072696e745f6865781a106578745f69735f76616c696461746f721b156578745f6c6f63616c5f73746f726167655f6765741c216578745f6c6f63616c5f73746f726167655f636f6d706172655f616e645f7365741d116578745f6e6574776f726b5f73746174651e106578745f737232353531395f7369676e1f166578745f7375626d69745f7472616e73616374696f6e20156578745f6c6f63616c5f73746f726167655f73657421146578745f656432353531395f67656e657261746522146578745f737232353531395f67656e657261746523236578745f626c616b65325f3235365f656e756d6572617465645f747269655f726f6f74240a6578745f6d616c6c6f6325086578745f6672656526176578745f737232353531395f7075626c69635f6b657973270b6578745f74776f785f3634280c5f5f727573745f616c6c6f63290a5f5f72675f616c6c6f632a0e5f5f727573745f6465616c6c6f632b0c5f5f72675f6465616c6c6f632c0e5f5f727573745f7265616c6c6f632d0c5f5f72675f7265616c6c6f632e135f5f727573745f616c6c6f635f7a65726f65642f115f5f72675f616c6c6f635f7a65726f65643009686173685f746573743134616c6c6f633a3a7261775f7665633a3a63617061636974795f6f766572666c6f773a3a68636164633139656466653965313035353229636f72653a3a70616e69636b696e673a3a70616e69633a3a68613237623135356231613762656131643325616c6c6f633a3a666d743a3a666f726d61743a3a68373139333337636638383237333534323436636f72653a3a70616e69636b696e673a3a70616e69635f626f756e64735f636865636b3a3a68613834643033333136663462356666613523636f72653a3a666d743a3a77726974653a3a68373639626232616366663461376638613648616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a616c6c6f636174655f696e3a3a7b7b636c6f737572657d7d3a3a68303032666333346665303731316264303708727573745f6f6f6d382e636f72653a3a726573756c743a3a756e777261705f6661696c65643a3a6864623133323335353631653632346136393a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68633133653134623932623865333434343a3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68373137336662316338303332343364353b3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68613062616630316338386562366162373c34636f72653a3a736c6963653a3a736c6963655f696e6465785f6c656e5f6661696c3a3a68656632663938626564366266373533643d4e636f72653a3a666d743a3a6e756d3a3a696d703a3a3c696d706c20636f72653a3a666d743a3a446973706c617920666f72207533323e3a3a666d743a3a68303438303937613766373038326163303e2d636f72653a3a70616e69636b696e673a3a70616e69635f666d743a3a68346637396263373939663330393733323f2f636f72653a3a666d743a3a6e756d3a3a696d703a3a666d745f7536343a3a68383932326134393263623337346536624011727573745f626567696e5f756e77696e6441313c5420617320636f72653a3a616e793a3a416e793e3a3a747970655f69643a3a68303837626662333038396434323234304235636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a68313538353734313262386634366265634343636f72653a3a666d743a3a466f726d61747465723a3a7061645f696e74656772616c3a3a77726974655f7072656669783a3a68363936303565363538343765653566304436636f72653a3a736c6963653a3a736c6963655f696e6465785f6f726465725f6661696c3a3a6835353833396665343434333633396662452c636f72653a3a666d743a3a466f726d61747465723a3a7061643a3a6862663133663132313734343633363530462e636f72653a3a7374723a3a736c6963655f6572726f725f6661696c3a3a686237366535353838326633366137346647323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6830303136373764333333316431623262484a3c636f72653a3a6f70733a3a72616e67653a3a52616e67653c4964783e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686339373033363631643132393261316649323c6368617220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68303731343665363835653563656332624a3d636f72653a3a756e69636f64653a3a626f6f6c5f747269653a3a426f6f6c547269653a3a6c6f6f6b75703a3a68616234336463613764383766373731634b49636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a68373032373631646266343866333635364c34636f72653a3a666d743a3a417267756d656e7456313a3a73686f775f7573697a653a3a68303764326632623133316361643036374d453c636f72653a3a63656c6c3a3a426f72726f774572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68326433626561393162376638333331354e483c636f72653a3a63656c6c3a3a426f72726f774d75744572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68383634373335313833373766363262364f323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6836323735643962386134343631633938502e636f72653a3a6f7074696f6e3a3a6578706563745f6661696c65643a3a683163333163613936623063653034653051303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6864396534343966646163316334353532522e636f72653a3a736c6963653a3a6d656d6368723a3a6d656d6368723a3a6839323166353536393537323230396564538001636f72653a3a7374723a3a7472616974733a3a3c696d706c20636f72653a3a736c6963653a3a536c696365496e6465783c7374723e20666f7220636f72653a3a6f70733a3a72616e67653a3a52616e67653c7573697a653e3e3a3a696e6465783a3a7b7b636c6f737572657d7d3a3a68376561353565643561313134353233665427636f72653a3a7374723a3a66726f6d5f757466383a3a68393936353463313839323463653036345530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a683566363963313432356330613037353356533c636f72653a3a666d743a3a6275696c646572733a3a5061644164617074657220617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a6865393736373038366566313830663239572f636f72653a3a666d743a3a57726974653a3a77726974655f636861723a3a6835376138336636353030656231663365582e636f72653a3a666d743a3a57726974653a3a77726974655f666d743a3a6835616339306139346131333230656233593a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f7374723a3a68306138363933663139633766366666665a3b3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f636861723a3a68636638393338356535396637623637615b3a3c266d7574205720617320636f72653a3a666d743a3a57726974653e3a3a77726974655f666d743a3a68383637616663663734396563326230325c3a636f72653a3a666d743a3a6275696c646572733a3a44656275675374727563743a3a6669656c643a3a68646430303731316136373965613430345d39636f72653a3a666d743a3a6275696c646572733a3a44656275675475706c653a3a6669656c643a3a68393065333464346262613566643437365e443c636f72653a3a666d743a3a417267756d656e747320617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68626634386164393337636464313931615f313c73747220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686637313733623038663233376563326360303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686530393630373933333765373636363961303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a683931653862363165666339613332346262423c636f72653a3a7374723a3a557466384572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686166363337373838663261376137313063303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833396433666631363039386537383237643e3c636f72653a3a666d743a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a686464366234323235356566653732333065383c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a656e61626c65643a3a686365346336373635363834626464353866343c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a6c6f673a3a686463373536653930643966306231373167363c6c6f673a3a4e6f704c6f67676572206173206c6f673a3a4c6f673e3a3a666c7573683a3a683533303838393235643430663439313868693c636f72653a3a697465723a3a61646170746572733a3a46696c7465724d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6838653863316664626539333838346163694b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68663530663164396638316533336133346a30636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68323434346236303933336133646533306b7d7061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72202851302c205230293e3a3a6465636f64653a3a68333464663538646264396436366233626c6b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68323661353531326466306130366630326d543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68376638333330366130393338636466636e2d616c6c6f633a3a7665633a3a5665633c543e3a3a72657461696e3a3a68356638643836666366306661623534356f443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a683032363437663936366662386566376170443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a683339393163366632303237333937323471443c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a686566656166643264633364616137393472463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683162353632313133646564343136383473543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683039636136373637663535386430666574543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683134393565336533346436663466623675543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683136303731343633646432653861656276543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683262653166343131363934633333326577543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683266353961316562306564306263356578543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a683266666136396263346264313332613379543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68343634633337336136666331646362347a9f013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68383962656633636262333533326338617b543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68353335363332653631633034346136637c543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68383862356330343234613539346162647d543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68393130613036323863303037356534637e543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68613962383762393439623233386535347f753c73725f7072696d6974697665733a3a67656e657269633a3a6865616465723a3a4865616465723c4e756d6265722c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68316665643862623861336335356666388001543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a686337333532366633613336356262663281017f6e6f64655f72756e74696d653a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a6465636f64653a3a68333130306265306638643432366337618201543c616c6c6f633a3a7665633a3a5665633c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68646332643431646231373737373966618301513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68333930383730653562343365626334618401513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68346235353034353038313230323761658501693c636f72653a3a697465723a3a61646170746572733a3a46696c7465724d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6864386638303832353262313639643938860168636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4d75743c413e20666f7220266d757420463e3a3a63616c6c5f6d75743a3a68616338303437376531623137353030658701513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a68376163313434383630363561393861358801513c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a66726f6d5f697465723a3a6838646539353166376338633363373834890130636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68303032396532383461626336653161348a01793c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a68346366353833643730356531323330398b017b3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a68373233336337366666386563623337638c017273726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a68633632613631323832356230656538308d0180013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a68363336343837393532646263326661308e017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a68626433333036616562666336626362358f01463c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68653566313862323833376430363465349001793c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6834396339306230636239366136303838910185013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a667265655f62616c616e63653a3a68383966356130363566393565373865319201743c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4469726563744163636f756e7444622061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a68643530643334363435306561343137639301723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a683833306434623064366665663163303194018d013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6d616b655f667265655f62616c616e63655f62653a3a68386234623564326136633936643835629501613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a683131363062303861386164636233646296017573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6866633362376362623662393231306232970191013c73726d6c5f636f6e7472616374733a3a54726965496446726f6d506172656e74436f756e7465723c543e2061732073726d6c5f636f6e7472616374733a3a54726965496447656e657261746f723c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a747269655f69643a3a686161356339313864623663376232333398013773726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a626c6f636b5f6e756d6265723a3a68653533383938356333383936373334639901723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a68363064383435646236353836623862669a017573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a68383232653933386530363765323330359b01613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a68373635323739333664343963626361349c017773726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6d75746174653a3a68363839653731333562643437646538339d017773726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6d75746174653a3a68323138376639326134336161343632319e016b3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68616238326334383138373537326534309f016c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6830386561633136356661396637393538a001713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7533323e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6864653530373162386130653734333633a101713c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c7536343e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6835653932376533663634393764666562a201303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836633166636332326337613565393130a301723c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163745265663c753132383e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6865323831616332613336303138303565a401303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6861393633376463316164363838343137a501783c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a6837313537343363326237386233626138a6017b3c73726d6c5f696e64696365733a3a616464726573733a3a416464726573733c4163636f756e7449642c4163636f756e74496e6465783e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832626663373164323632393930636138a7017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f73746f726167653a3a6839346337326433373239326630393437a80184013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f72656e745f616c6c6f77616e63653a3a6838626464373063336465333638653932a901cd0173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f494d504c5f454e434f44455f464f525f4c696e6b6167653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4c696e6b6167653c4b65793e3e3a3a656e636f64655f746f3a3a6835333330396563306462363039336239aa01cd0173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a5f494d504c5f454e434f44455f464f525f4c696e6b6167653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a4c696e6b6167653c4b65793e3e3a3a656e636f64655f746f3a3a6865393330353763396263376337323461ab0184013c73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c473e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6838643238373730663035386262636565ac016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a53746f726167654c696e6b65644d61703a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6838383431306663323634343831633764ad0184013c73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c473e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6865386566633638356136363861353930ae016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a53746f726167654c696e6b65644d61703a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6835313634396637613236326262653938af0184013c73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a456e756d657261746f723c4b2c562c473e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6866396432363165633964396131623766b0016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a53746f726167654c696e6b65644d61703a3a73746f726167655f6c696e6b65645f6d61705f66696e616c5f6b65793a3a6835356235363734623230613437653865b1017d7061726974795f7363616c655f636f6465633a3a636f6465633a3a696e6e65725f7475706c655f696d706c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72202851302c205230293e3a3a6465636f64653a3a6865373864623462383164613762393330b2013d73726d6c5f6f6666656e6365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6836363030663338636433666133303631b301743c73726d6c5f6f6666656e6365733a3a5f5f476574427974655374727563745265706f72747342794b696e64496e6465783c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831636238373936303566366365663164b4016c3c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832333939613538336430656438336234b5014d73726d6c5f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a696e7374616e74696174653a3a6836623966633736373531646261363534b60181013c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6e74726163745f6578697374733a3a6836616130363564356539663732313132b7014b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6861613261623366303331336232356636b8013173726d6c5f636f6e7472616374733a3a657865633a3a7472616e736665723a3a6837373362356236396662646161313137b9013973726d6c5f636f6e7472616374733a3a7761736d3a3a636f64655f63616368653a3a6c6f61643a3a6866323337613535386232383836373039ba01593c73726d6c5f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732073726d6c5f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a6831333937356561393739303766376236bb01783c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a636f6d6d69743a3a6836616339326635393738306465653137bc018c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a656e737572655f63616e5f77697468647261773a3a6839626535636564373733626261363035bd0148616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6832343561663334383230376130353433be0130636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6835323765316362333634383130643564bf017f3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f636f64655f686173683a3a6866353465663532326365346138316461c0017d3c73726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4f7665726c61794163636f756e7444623c543e2061732073726d6c5f636f6e7472616374733a3a6163636f756e745f64623a3a4163636f756e7444623c543e3e3a3a6765745f62616c616e63653a3a6831313131303862313035626263336366c1014673726d6c5f636f6e7472616374733a3a657865633a3a457865637574696f6e436f6e746578743c542c562c4c3e3a3a63616c6c3a3a6839353866323730643039323832636563c2014273726d6c5f636f6e7472616374733a3a72656e743a3a7472795f65766963745f6f725f616e645f7061795f72656e743a3a6863336336633731646632616562646432c3013c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6864633565333763353634646262616336c4013f7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64655f746f3a3a6831613165646131353962323138616264c501c7013c73726d6c5f6f6666656e6365733a3a4d6f64756c653c543e2061732073725f7374616b696e675f7072696d6974697665733a3a6f6666656e63653a3a5265706f72744f6666656e63653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449642c3c542061732073726d6c5f6f6666656e6365733a3a54726169743e3a3a4964656e74696669636174696f6e5475706c652c4f3e3e3a3a7265706f72745f6f6666656e63653a3a6832383939313265386363346166666539c6014b3c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832633136623336633063663237386639c7016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6838636333303466313030626264666365c801437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6861623165653031323634626232353937c90141616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a7365617263683a3a7365617263685f747265653a3a6834353339376134376233366633383934ca01613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6863623836653530643234616238333461cb01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6831633062376138643436393335636534cc014073726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6576656e745f696e64657865643a3a6834313461616236326136396366376638cd0134636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f6e7461696e733a3a6863616665643431346630633236373166ce013673726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6465706f7369745f6c6f673a3a6865613866373434663735656363653135cf017e3c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736c6173683a3a6866643562376165396361393035363832d00189013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f6372656174696e673a3a6836373839333262303737623239363337d1015373725f7072696d6974697665733a3a50657262696c6c3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a7b7b636c6f737572657d7d3a3a6838323439353335646130363233616166d2015373725f7072696d6974697665733a3a50657262696c6c3a3a66726f6d5f726174696f6e616c5f617070726f78696d6174696f6e3a3a7b7b636c6f737572657d7d3a3a6833333938303938366437323438633665d3014b73725f7072696d6974697665733a3a7472616974733a3a4163636f756e744964436f6e76657273696f6e3a3a696e746f5f6163636f756e743a3a6839633438346130663064333336626130d4019a0173726d6c5f7374616b696e673a3a5f494d504c5f4445434f44455f464f525f4578706f737572653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f7374616b696e673a3a4578706f737572653c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6837393935333333636162333938616263d501483c73726d6c5f6f6666656e6365733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837303239393466376333643337643031d6015c3c73726d6c5f6f6666656e6365733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6832386366306335363565653635396665d701703c7061726974795f7363616c655f636f6465633a3a636f6d706163743a3a436f6d706163743c543e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6830373463363933373136623438643830d801303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830313735343962623362373765363161d901406e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73797374656d3a3a6838353435663263626138613161386365da01416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f696e64696365733a3a6839656632383931386338356161373231db01426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f62616c616e6365733a3a6835613762623764323431326363363930dc01416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7374616b696e673a3a6861386530623037316263646566366661dd01416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f73657373696f6e3a3a6837336536323763303639326138663139de01436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f64656d6f63726163793a3a6863633261336536646130336365323230df014e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f6c6c6563746976655f496e7374616e6365313a3a6836656163653863306136333236353131e001436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f656c656374696f6e733a3a6832623263323461633638353163356334e1014e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6d656d626572736869705f496e7374616e6365313a3a6863616165316234326264323238666536e201416e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6772616e6470613a3a6834613630316463343234393033386164e301426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f74726561737572793a3a6863333761653137623166353232663861e401436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f636f6e7472616374733a3a6865343131326666386464386131633438e5013e6e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f7375646f3a3a6861316434653964343230393738353039e601436e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f696d5f6f6e6c696e653a3a6836356133633932336635663033326535e701426e6f64655f72756e74696d653a3a52756e74696d653a3a5f5f6d6f64756c655f6576656e74735f6f6666656e6365733a3a6862633937306433383331323331343235e8018d016e6f64655f72756e74696d653a3a5f494d504c5f4445434f44455f464f525f53657373696f6e4b6579733a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72206e6f64655f72756e74696d653a3a53657373696f6e4b6579733e3a3a6465636f64653a3a6834616339333937656166633633346665e9018a0173726d6c5f636f6c6c6563746976653a3a5f494d504c5f4445434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a6465636f64653a3a6831333130353934363139353131333335ea018b0173726d6c5f636f6e7472616374733a3a5f494d504c5f4445434f44455f464f525f5363686564756c653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6e7472616374733a3a5363686564756c653e3a3a6465636f64653a3a6834396636343234393334303165366132eb0182016e6f64655f72756e74696d653a3a5f494d504c5f454e434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a43616c6c3e3a3a656e636f64655f746f3a3a6832373361383431636330393135346263ec01723c73725f7072696d6974697665733a3a67656e657269633a3a6469676573743a3a4469676573744974656d3c486173683e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a6830376364313565343730393839633137ed018d0173726d6c5f636f6c6c6563746976653a3a5f494d504c5f454e434f44455f464f525f43616c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e3e3a3a656e636f64655f746f3a3a6835626138363964316265616430313464ee018e0173726d6c5f636f6e7472616374733a3a5f494d504c5f454e434f44455f464f525f5363686564756c653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6e7472616374733a3a5363686564756c653e3a3a656e636f64655f746f3a3a6866346132356361353138616335333261ef01437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6834306664363130326135353165306162f0012b616c6c6f633a3a736c6963653a3a6d657267655f736f72743a3a6833316161333833653836616137363032f10184016e6f64655f72756e74696d653a3a5f494d504c5f454e434f44455f464f525f4576656e743a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72206e6f64655f72756e74696d653a3a4576656e743e3a3a656e636f64655f746f3a3a6836643335653535356638613331303163f201a20173726d6c5f636f6c6c6563746976653a3a5f494d504c5f454e434f44455f464f525f5261774576656e743a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6c6c6563746976653a3a5261774576656e743c486173682c4163636f756e7449642c493e3e3a3a656e636f64655f746f3a3a6834343930633836383033333235343464f301653c6e6f64655f72756e74696d653a3a43616c6c2061732073725f7072696d6974697665733a3a776569676874733a3a4765744469737061746368496e666f3e3a3a6765745f64697370617463685f696e666f3a3a6830343764353632386132636561316131f401583c6e6f64655f72756e74696d653a3a43616c6c2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6838336539363263643433313230313431f501583c73726d6c5f626162653a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6830613865393037323432653436316137f601437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6862373562336361323964663636363363f7017273726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a6765743a3a6836313935643964653537363138303536f8013573726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a617574686f723a3a6837616231333433646161623761326263f9013973726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7265776172645f62795f6964733a3a6834663135326364303734323563613964fa01673c73726d6c5f617574686f726974795f646973636f766572793a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a6862373861323639343666653063343330fb013973726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a63757272656e745f696e6465783a3a6862643032343430373930666636353431fc016f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a6863323531613265623837643836373037fd013773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6865363039313833643065313763373335fe013473726d6c5f696e64696365733a3a4d6f64756c653c543e3a3a656e756d5f7365743a3a6834626439326135376534613539343639ff014a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a683331333837306130366564383137366380025d3c73726d6c5f636f6e7472616374733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683337653735393432376661653439323181029c0173726d6c5f74726561737572793a3a5f494d504c5f4445434f44455f464f525f50726f706f73616c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f74726561737572793a3a50726f706f73616c3c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a6862653536383862356333373963656531820291013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a736c6173685f72657365727665643a3a683935323531313561306238396239363483028a013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a726573657276653a3a6835373538346635383335346464633662840295013c73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a686361376465303135316236633762653285024a73726d6c5f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733a3a7365745f6d656d626572735f736f727465643a3a683538373630336262373262373332656386025d3c73726d6c5f656c656374696f6e733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68343237636433356333343061653264318702603c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68613438353966393862646662343236348802603c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683732373531613862373434313363383089025d3c73726d6c5f64656d6f63726163793a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68653734393864343238613132313430328a02a40173726d6c5f7374616b696e673a3a5f494d504c5f4445434f44455f464f525f5374616b696e674c65646765723a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f7374616b696e673a3a5374616b696e674c65646765723c4163636f756e7449642c42616c616e63653e3e3a3a6465636f64653a3a68323763626335363133383261626464638b026f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68316232373866353234623633623030388c026f73726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a646f75626c655f6d61703a3a53746f72616765446f75626c654d61703a3a73746f726167655f646f75626c655f6d61705f66696e616c5f6b65793a3a68643338646665333337366133616133618d025b3c73726d6c5f7374616b696e673a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a68326662643138643966363865313162638e0281013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7472616e736665723a3a68393839356531356133343461393931338f023f73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f667265655f62616c616e63653a3a686338383364396561623864346264333390024373726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a7365745f72657365727665645f62616c616e63653a3a686434313335333537336630653135303591025b3c73726d6c5f696e64696365733a3a43616c6c3c543e2061732073725f7072696d6974697665733a3a7472616974733a3a446973706174636861626c653e3a3a64697370617463683a3a683836643831653663633431313261616292023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a683235616265373531383235343639656293027f3c73726d6c5f696e64696365733a3a4d6f64756c653c543e2061732073726d6c5f73797374656d3a3a4f6e4e65774163636f756e743c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f6e65775f6163636f756e743a3a683233616438626236666435383861326194023873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a686461366639373031343963386135303795023673726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6b696c6c5f73746173683a3a683130383536663739323263306461306596023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a686634613737393939303031643038636297027573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6837383737326333616663356337353965980281013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a77697468647261773a3a683562396534326566383633636534646199023e73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a76657374696e675f62616c616e63653a3a68626238373339643133333535626236339a023473726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6c6f636b733a3a68333638393134633832333539393965379b02483c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f64653e3a3a6465636f64653a3a68353835323237626435376637343932309c027573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a68633038636165316435373833636636349d0286013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a746f74616c5f62616c616e63653a3a68643763643637643234383134613861659e02653c73726d6c5f62616c616e6365733a3a54616b65466565733c542c493e2061732073725f7072696d6974697665733a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a68376236613935643336393266623835389f023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6830653936393331313632366135383439a0023d73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6862323666653064306530393634336432a1023d73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a746f74616c5f69737375616e63653a3a6862373662663765313663613336633032a2023f73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6835653663653264363439656133316565a3026f3c73726d6c5f62616c616e6365733a3a5f5f476574427974655374727563744672656542616c616e63653c542c493e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861383137633863343936663239343566a4024873726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6834313966353063313539363139383666a5028e013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a43757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6465706f7369745f696e746f5f6578697374696e673a3a6830386464613432346263363434343536a6023c73726d6c5f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6862663230666535343038633831396532a7023e73726d6c5f696d5f6f6e6c696e653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6861643765666566376438653664313064a8028c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a657874656e645f6c6f636b3a3a6862363338363539643233333631623664a90289013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4c6f636b61626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a7365745f6c6f636b3a3a6836396238393930643162313061313162aa028c013c73726d6c5f62616c616e6365733a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a52657365727661626c6543757272656e63793c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a756e726573657276653a3a6832313164383839393835333764303834ab02437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6830666563303961653439666334326261ac023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6864663432393736333738383031613830ad023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6862353065623633303432396164376434ae024a3c73726d6c5f62616c616e6365733a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6865353039326631653139383330613864af02493c73726d6c5f696d5f6f6e6c696e653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831666134356231303637653363663366b002613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6835313936613536623066393933653735b102723c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a496e746f497465723c4b2c563e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832366232363063316563313961636339b202437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6833353837313637353866383936316335b3027573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6839613865636263363866646163613530b402303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832336661343463613531383764656463b5024d636f72653a3a666d743a3a6e756d3a3a3c696d706c20636f72653a3a666d743a3a446562756720666f72207573697a653e3a3a666d743a3a68373032373631646266343866333635362e323334b6024373726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6837323862643265653064663338323230b7024e73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6863643962646630323731313235383765b8029f013c73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5265706f72744c6174656e637944656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865613333313236376432326439396637b9029c013c73726d6c5f66696e616c6974795f747261636b65723a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a57696e646f7753697a6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865373839396264363034313435393935ba02d5017375627374726174655f636f6e73656e7375735f626162655f7072696d6974697665733a3a6469676573743a3a5f494d504c5f4445434f44455f464f525f526177426162655072654469676573743a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f636f6e73656e7375735f626162655f7072696d6974697665733a3a6469676573743a3a526177426162655072654469676573743e3a3a6465636f64653a3a6831633662323537393730353733386134bb024b616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a566163616e74456e7472793c4b2c563e3a3a696e736572743a3a6831626132303333613836643063323539bc02613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6830346361333431346265366331306336bd028c013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4f6e496e697469616c697a653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6830613231343334363663376138326632be023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831396564393438326431653338623932bf024073726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a63616e6469646174655f7265675f696e666f3a3a6831373937623930333666633766346466c0023873726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a616c6c5f766f746572733a3a6861316534646265623437323035653037c1023a73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a617070726f76616c735f6f663a3a6832306234303633356262643638613261c202960173726d6c5f656c656374696f6e733a3a5f494d504c5f4445434f44455f464f525f566f746572496e666f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f656c656374696f6e733a3a566f746572496e666f3c42616c616e63653e3e3a3a6465636f64653a3a6830316262336439643662306561626533c3024a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6836306436643261353030666463656265c4022d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6835643130393431636331373563363639c50295013c73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e2061732073726d6c5f737570706f72743a3a7472616974733a3a4368616e67654d656d626572733c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6368616e67655f6d656d626572735f736f727465643a3a6864653264326333356566393630353236c6023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6835393066393834646333383132663735c7023c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6831343362643439666263383664393238c8023e73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6866653130333861666166393439343565c902713c73726d6c5f656c656374696f6e733a3a5f5f4765744279746553747275637443616e646964617465436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834643433333035643361333633333334ca02713c73726d6c5f656c656374696f6e733a3a5f5f476574427974655374727563745265676973746572496e666f4f663c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837363362656236383261363832343365cb024773726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6862376137636130316332323031333132cc0299013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a564f5445525f5345545f53495a4544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866366135363965663662643639346637cd0295013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e67426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838613264656532666338373233633965ce0297013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e67506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863653338613432616462313537383438cf029e013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a496e6163746976654772616365506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866363330386163656461376137343234d00295013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4361727279436f756e7444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833653330626135303162636236366136d10294013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a566f74696e6746656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864333434393535393035313936363639d20298013c73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616e646964616379426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839393639666163356137666662626663d302493c73726d6c5f656c656374696f6e733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6838393533343563316230373032343266d4023e73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a646f5f7365745f617070726f76616c733a3a6830356233326237643335643433376531d5023a73726d6c5f656c656374696f6e733a3a4d6f64756c653c543e3a3a72656d6f76655f766f7465723a3a6864343234646366303966313037613632d602497061726974795f7363616c655f636f6465633a3a656e636f64655f617070656e643a3a657874726163745f6c656e6774685f646174613a3a6866643865656134353734643132643761d7023a73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6830316131646133303365313665336564d8023c73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6864313433326339303364323232303332d902663c73726d6c5f6772616e6470613a3a5f5f4765744279746553747275637453746174653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861633430666337353837316663386439da023c7061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a656e636f64653a3a6866613262363366396564623731643938db023a73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6839336165366236373664623230343535dc023c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6835383233613635353036306435633137dd024573726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864363061643832333262393932383237de0299013c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a44454455505f4b45595f50524546495844656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861626566343565663162336261356236df02763c73726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a54776f783634436f6e6361742061732073726d6c5f737570706f72743a3a73746f726167653a3a6861736865643a3a53746f726167654861736865723e3a3a686173683a3a6830336164393834343263623061383436e002437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6866396638336564633862303663363035e102437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6839623462623063373566323965326431e2023b73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6864623530656536616665326164663166e3023d73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6866303933303965666331326462656261e4024673726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6865616232643963386538373037313930e5028e013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4275726e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6862376133356263656433663732633433e602870173725f7072696d6974697665733a3a5f494d504c5f454e434f44455f464f525f50657262696c6c3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073725f7072696d6974697665733a3a50657262696c6c3e3a3a656e636f64653a3a6830306536383731383739316332643562e70295013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5370656e64506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864653636393366366136366337323939e80296013c73726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a50726f706f73616c426f6e6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830656261613063366636366431356332e9023673726d6c5f74726561737572793a3a4d6f64756c653c543e3a3a70726f706f73616c733a3a6863663030323230323662663936306562ea028a013c73726d6c5f73657373696f6e3a3a4d6f64756c653c543e2061732073725f7072696d6974697665733a3a7472616974733a3a4f6e496e697469616c697a653c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a426c6f636b4e756d6265723e3e3a3a6f6e5f696e697469616c697a653a3a6835333934366339396564396363636432eb023673726d6c5f626162653a3a4d6f64756c653c543e3a3a646f5f696e697469616c697a653a3a6832613837383633353631643739633635ec023373726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7374616b6572733a3a6861393931653433343637656664343439ed0286013c73726d6c5f7374616b696e673a3a4d6f64756c653c543e2061732073726d6c5f73657373696f6e3a3a4f6e53657373696f6e456e64696e673c3c542061732073726d6c5f73797374656d3a3a54726169743e3a3a4163636f756e7449643e3e3a3a6f6e5f73657373696f6e5f656e64696e673a3a6831616537633337663639326237646539ee023b73726d6c5f6772616e6470613a3a4d6f64756c653c543e3a3a7363686564756c655f6368616e67653a3a6863663437383934313665623338366464ef023773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6864313234373039313533353736666336f002437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6837383364333039663738623432326336f1024b3c5b543b205f5d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a6832333063333531613138336135356361f20230636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6835363637303838653535663233666638f302633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6832303361323762636366356561396333f402683c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a73697a655f68696e743a3a6832346639626639393362356461613335f5023e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6833383534363563373835376562323363f602633c636f72653a3a697465723a3a61646170746572733a3a4d61703c492c463e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a6835333163646162346661313032336566f7023e636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723a3a6e74683a3a6830656136623430363665613539646464f8024273726d6c5f636f6e7472616374733a3a7761736d3a3a707265706172653a3a707265706172655f636f6e74726163743a3a6836323964316235366163326233306638f9024a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6833663662373961343438356135623362fa02437061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653a3a7573696e675f656e636f6465643a3a6839303831646161613832616561363963fb026a636f72653a3a6f70733a3a66756e6374696f6e3a3a696d706c733a3a3c696d706c20636f72653a3a6f70733a3a66756e6374696f6e3a3a466e4f6e63653c413e20666f7220266d757420463e3a3a63616c6c5f6f6e63653a3a6833313938663239346337633037623537fc02663c73726d6c5f636f6e7472616374733a3a7761736d3a3a5761736d566d2061732073726d6c5f636f6e7472616374733a3a657865633a3a566d3c543e3e3a3a657865637574653a3a7b7b636c6f737572657d7d3a3a6832326566363933396635303938656631fd027d3c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6761733a3a6832623037396439643933646632663439fe025273725f73616e64626f783a3a696d703a3a456e7669726f6e6d656e74446566696e6974696f6e4275696c6465723c543e3a3a6164645f686f73745f66756e633a3a6837613337346132656234333561666165ff0289013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f73746f726167653a3a6833316361656264633564353264303138800389013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6765745f73746f726167653a3a6831306431663335653165616632636130810382013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c3a3a6862623530306664353561356239323037820389013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f696e7374616e74696174653a3a6832616439353630656131333639626339830384013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72657475726e3a3a6861636564646338343232366335616233840384013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f63616c6c65723a3a6834636231663539323330323861356630850385013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f616464726573733a3a6833613661303262393533303630646139860387013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f70726963653a3a6864376232663834643362623864393663870386013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6761735f6c6566743a3a6861373962343335303839303935373465880385013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f62616c616e63653a3a686339306131366437336261366433336589038f013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f76616c75655f7472616e736665727265643a3a68336165393265656438623133313066658a0384013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72616e646f6d3a3a68643635336131613637663332626464368b0381013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6e6f773a3a68616461313738623139303562636263618c038d013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6d696e696d756d5f62616c616e63653a3a68613038303466373261376563343666378d038b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f64697370617463685f63616c6c3a3a68383035303832366164303961386335628e0388013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f726573746f72655f746f3a3a68633132333439626561366435393336308f038a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f73697a653a3a683538306530613263333566306331646490038a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f726561643a3a683663373534623336306337633265613991038b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f736372617463685f77726974653a3a683632343433353932626339633736616592038b013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f6465706f7369745f6576656e743a3a6838306238323039323537373365616633930390013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7365745f72656e745f616c6c6f77616e63653a3a683466323433313333626532356363666194038c013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f72656e745f616c6c6f77616e63653a3a6839363463323461623138626436633334950385013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f7072696e746c6e3a3a686637366431396430353439356163373596038a013c73726d6c5f636f6e7472616374733a3a7761736d3a3a72756e74696d653a3a456e762061732073726d6c5f636f6e7472616374733a3a7761736d3a3a656e765f6465663a3a46756e6374696f6e496d706c50726f76696465723c453e3e3a3a696d706c733a3a6578745f626c6f636b5f6e756d6265723a3a686433623536316436376666623763643497033273725f73616e64626f783a3a696d703a3a64697370617463685f7468756e6b3a3a68386536656133346363343135383566389803ad017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f4445434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a6465636f64653a3a68363636646563623130363065303136389903b0017375627374726174655f7072696d6974697665733a3a73616e64626f783a3a5f494d504c5f454e434f44455f464f525f547970656456616c75653a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a73616e64626f783a3a547970656456616c75653e3a3a656e636f64655f746f3a3a68366638396436616535373364656261659a033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a68656566626338616663316366666162389b033d73726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a68613865633662663666313730656535339c033f73726d6c5f617574686f72736869703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68323836393939663633396233306133669d03703c73726d6c5f617574686f72736869703a3a5f5f47657442797465537472756374446964536574556e636c65733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68356131666536346139393034343766639e038a033c285475706c65456c656d656e74302c205475706c65456c656d656e74312c205475706c65456c656d656e74322c205475706c65456c656d656e74332c205475706c65456c656d656e74342c205475706c65456c656d656e74352c205475706c65456c656d656e74362c205475706c65456c656d656e74372c205475706c65456c656d656e74382c205475706c65456c656d656e74392c205475706c65456c656d656e7431302c205475706c65456c656d656e7431312c205475706c65456c656d656e7431322c205475706c65456c656d656e7431332c205475706c65456c656d656e7431342c205475706c65456c656d656e7431352c205475706c65456c656d656e7431362c205475706c65456c656d656e7431372c205475706c65456c656d656e7431382c205475706c65456c656d656e743139292061732073725f7072696d6974697665733a3a7472616974733a3a4f6e46696e616c697a653c426c6f636b4e756d6265723e3e3a3a6f6e5f66696e616c697a653a3a68326334616136396565373634306235359f037573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6835326236326535373661623038396433a0033173726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6e6f773a3a6834363532613662336165366264626163a103443c73726d6c5f626162653a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6835316562616163646438636565393939a2033973726d6c5f626162653a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838626464366437316663366336386133a303683c73726d6c5f626162653a3a5f5f4765744279746553747275637452616e646f6d6e6573733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831646266336432303235653433663633a4034273726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6832653030663433376237636334623732a50397013c73726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4578706563746564426c6f636b54696d6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834383432303533646236336462623264a60393013c73726d6c5f626162653a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a45706f63684475726174696f6e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6866373362303132363134623132356364a7033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6837346264393230333636623666316562a8033173726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a72616e646f6d3a3a6836306461326464656333373364646436a9033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861623464373335663864656363386661aa03930173726d6c5f73797374656d3a3a5f494d504c5f454e434f44455f464f525f4576656e745265636f72643a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f73797374656d3a3a4576656e745265636f72643c452c543e3e3a3a656e636f64655f746f3a3a6831323131373037393638613835333637ab0330636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6836616262343766373764373233383832ac033973726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6839396533616666666131613734653864ad033b73726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838613435343333313564303062363733ae03663c73726d6c5f73797374656d3a3a5f5f476574427974655374727563744576656e74733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837643032313739653635613738326563af03693c73726d6c5f73797374656d3a3a5f5f47657442797465537472756374426c6f636b486173683c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6831343962353364336363646564316439b0036e3c73726d6c5f73797374656d3a3a5f5f4765744279746553747275637452616e646f6d4d6174657269616c3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838346564373366313834376166366434b1034473726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6834613439316239383530666636343565b2033373726d6c5f73797374656d3a3a4d6f64756c653c543e3a3a66696e616c697a653a3a6861336164316265613362353165373663b303920173726d6c5f636f6c6c6563746976653a3a5f494d504c5f4445434f44455f464f525f566f7465733a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a4465636f646520666f722073726d6c5f636f6c6c6563746976653a3a566f7465733c4163636f756e7449643e3e3a3a6465636f64653a3a6831666334646262316561653233396639b4034a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6865373436613266666630383837623565b5033f73726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6866373435383836616563616334393835b6034173726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6831336536643135376135613433613432b7034173726d6c5f636f6c6c6563746976653a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6834353831653732656334363130393330b8034273726d6c5f73797374656d3a3a436865636b5765696768743c543e3a3a636865636b5f626c6f636b5f6c656e6774683a3a6837666561303334346333386136616365b9033c73726d6c5f73797374656d3a3a436865636b5765696768743c543e3a3a636865636b5f7765696768743a3a6834326632643563336464616539323165ba03463c616c6c6f633a3a626f7865643a3a426f783c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831393764386331333362343930343066bb03473c73726d6c5f696e64696365733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831303562663766353932313861333062bc03473c73726d6c5f7374616b696e673a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6831396539646437656462396264616366bd03493c73726d6c5f64656d6f63726163793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6836636635383139356236626464353231be034c3c73726d6c5f6d656d626572736869703a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837323735633464666230386236643532bf03493c73726d6c5f636f6e7472616374733a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6862373936623731343832366162363138c003443c73726d6c5f7375646f3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6865393938653136373161363737386139c103533c73726d6c5f617574686f726974795f646973636f766572793a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837346565386530313939376239383937c203463c73726d6c5f73797374656d3a3a43616c6c3c543e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6833626664323638333734663362376338c3034c3c73726d6c5f636f6c6c6563746976653a3a43616c6c3c542c493e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6837663834326331386439383539653138c4033c73726d6c5f696e64696365733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6837303666626537316539373135376665c5037573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6862383665646132366239376363326534c603d80173725f7072696d6974697665733a3a7472616e73616374696f6e5f76616c69646974793a3a5f494d504c5f454e434f44455f464f525f5472616e73616374696f6e56616c69646974794572726f723a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073725f7072696d6974697665733a3a7472616e73616374696f6e5f76616c69646974793a3a5472616e73616374696f6e56616c69646974794572726f723e3a3a656e636f64655f746f3a3a6831626165383133323764396564653362c7037173726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a696e697469616c697a655f626c6f636b3a3a6834626664366136356235623930656539c8033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f65787465726e616c3a3a6862613562643931393264343264353735c9033b73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6c61756e63685f7075626c69633a3a6864623438343534306330333732386561ca033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a7265666572656e64756d5f696e666f3a3a6833333765323135653936613163383731cb033873726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f746572735f666f723a3a6837306138346438373431306364346230cc033573726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a766f74655f6f663a3a6831613037316366663431353331376631cd033d73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a64656c6567617465645f766f7465733a3a6832663566356266663563303233643636ce033e73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a636c6561725f7265666572656e64756d3a3a6866666637373262613837616630303565cf03443c6e6f64655f72756e74696d653a3a43616c6c20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832616531373964653035366164666439d0037973726d6c5f6578656375746976653a3a4578656375746976653c53797374656d2c426c6f636b2c436f6e746578742c556e7369676e656456616c696461746f722c416c6c4d6f64756c65733e3a3a6170706c795f65787472696e7369635f776974685f6c656e3a3a6830363363313039363438386337343964d103a5013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e2061732073725f7072696d6974697665733a3a7472616974733a3a436865636b61626c653c4c6f6f6b75703e3e3a3a636865636b3a3a6835353432373336616466623430333761d2036e3c73726d6c5f636f6e7472616374733a3a436865636b426c6f636b4761734c696d69743c543e2061732073725f7072696d6974697665733a3a7472616974733a3a5369676e6564457874656e73696f6e3e3a3a76616c69646174653a3a6834613539353938646632343262313836d303363c5420617320636f72653a3a636f6e766572743a3a496e746f3c553e3e3a3a696e746f3a3a6832653964376331393038323734626436d4033c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6836356634343632646235343435393338d5033e73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6865636431373939313835396165306236d6034773726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864353861656165393464373762386164d70398013c73726d6c5f74696d657374616d703a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6864623734353962613435343235656461d8033f73726d6c5f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a63616c6c5f66756e6374696f6e733a3a6861613637353666646431666439393661d9034173726d6c5f6d656d626572736869703a3a4d6f64756c653c542c493e3a3a73746f726167655f6d657461646174613a3a6838656137343163663931396330333264da0334636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6861613934663035386431333531633466db032e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6834333461393733383437303165333236dc033c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6835653664306564386338306561613034dd03593c73725f7072696d6974697665733a3a416e795369676e61747572652061732073725f7072696d6974697665733a3a7472616974733a3a5665726966793e3a3a7665726966793a3a6865653661376232666164623063306337de033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831313330393632353863393833353939df033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6831333135303466353262396465616136e0033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861656430393864653237386637643631e1033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a6765743a3a6861666432643465663565656365613936e2033773726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a7075743a3a6838333637626463333564323039376438e303c40173726d6c5f636f6e7472616374733a3a5f494d504c5f454e434f44455f464f525f526177416c697665436f6e7472616374496e666f3a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f722073726d6c5f636f6e7472616374733a3a526177416c697665436f6e7472616374496e666f3c436f6465486173682c42616c616e63652c426c6f636b4e756d6265723e3e3a3a656e636f64655f746f3a3a6837343039376637333530333664356132e4033873726d6c5f737570706f72743a3a73746f726167653a3a756e6861736865643a3a74616b653a3a6839643530626664316331393964383432e5037773726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a76616c75653a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f7261676556616c75653c543e20666f7220473e3a3a6d75746174653a3a6833393630323862623831616532396435e6033c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6865373235383163383635373736343031e7033e73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838353138373039636366353134386634e8036b3c73726d6c5f636f6e7472616374733a3a5f5f4765744279746553747275637447617350726963653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837646161333630313731323962626161e903723c73726d6c5f636f6e7472616374733a3a5f5f4765744279746553747275637443757272656e745363686564756c653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830613432353664383239653035616630ea034773726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6839373030323763326334383864663966eb0398013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426c6f636b4761734c696d697444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835326264363965373737633864653839ec0397013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d617856616c756553697a6544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863653266336335666664386535346666ed0393013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d6178446570746844656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839373239663263633533653864316636ee0396013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a43616c6c4261736546656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830613062653632333537663633303232ef0396013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a436f6e747261637446656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836643062623334363530643336623765f0039d013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5472616e73616374696f6e4279746546656544656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861653066326564313066333062336431f1039a013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53757263686172676552657761726444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835643765346164343430313363316363f2039c013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a52656e744465706f7369744f666673657444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830653366346264376531366535323031f3039c013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a53746f7261676553697a654f666673657444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6836666162343733336233653630636665f4039e013c73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a5369676e6564436c61696d48616e646963617044656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832363431363262343562363133336365f5033773726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a626172655f63616c6c3a3a6862393261343137333037323335353038f6033773726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a6761735f70726963653a3a6861353534306331613131336131343632f7033e73726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a63757272656e745f7363686564756c653a3a6835393231353035363931356330383436f8033873726d6c5f636f6e7472616374733a3a4d6f64756c653c543e3a3a726573746f72655f746f3a3a6863613537313665383565633061613434f9034573726d6c5f636f6e7472616374733a3a7761736d3a3a707265706172653a3a436f6e74726163744d6f64756c653a3a6e65773a3a6838326533383933383863653766636635fa03467061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a436f646553656374696f6e3a3a626f646965733a3a6864393864326364313131613035613531fb0348616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e3a3a696e736572743a3a6865373064323632373339343561313363fc033c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a66726f6d5f6d6f64756c653a3a6834643832616331306433343833336233fd03537061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a7265736f6c76655f747970655f7265663a3a6861643034326537313830333035313963fe03a9017061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a3c696d706c20636f72653a3a636f6e766572743a3a46726f6d3c7061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c6553636166666f6c643e20666f72207061726974795f7761736d3a3a656c656d656e74733a3a6d6f64756c653a3a4d6f64756c653e3a3a66726f6d3a3a6836643231633062653130613035343964ff0344707761736d5f7574696c733a3a6761733a3a436f756e7465723a3a66696e616c697a655f6d6574657265645f626c6f636b3a3a686362636565306234333463346631643080042d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a68656165383561343031313132353734348104507061726974795f7761736d3a3a6275696c6465723a3a6d6f64756c653a3a4d6f64756c654275696c6465723c463e3a3a707573685f66756e6374696f6e3a3a6865396131343838383163653163323132820430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a686464633764633436363333376535353783043c707761736d5f7574696c733a3a737461636b5f6865696768743a3a696e6a6563745f6c696d697465723a3a686635333865316430386135653339666384046b3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a683633316637353930306465663336646285046b3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a6e6578743a3a686536383437396137393936386537646686046f3c636f72653a3a697465723a3a61646170746572733a3a526573756c745368756e743c492c453e20617320636f72653a3a697465723a3a7472616974733a3a6974657261746f723a3a4974657261746f723e3a3a7472795f666f6c643a3a686631323333633761626466646630306287049f013c73725f7072696d6974697665733a3a67656e657269633a3a756e636865636b65645f65787472696e7369633a3a556e636865636b656445787472696e7369633c416464726573732c43616c6c2c5369676e61747572652c45787472613e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64653a3a686661623762663862623438396439613888043773726d6c5f7375646f3a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a683535306364366435376331373164303289043973726d6c5f7375646f3a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a68303362303139613732626139303138328a04613c73726d6c5f7375646f3a3a5f5f476574427974655374727563744b65793c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a68383731363333663133333061636665378b04a5017375627374726174655f7072696d6974697665733a3a737232353531393a3a5f494d504c5f454e434f44455f464f525f5075626c69633a3a3c696d706c207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f646520666f72207375627374726174655f7072696d6974697665733a3a737232353531393a3a5075626c69633e3a3a656e636f64653a3a68613163366230616563303734343431648c040c436f72655f76657273696f6e8d0412436f72655f657865637574655f626c6f636b8e04693c73725f7072696d6974697665733a3a7472616974733a3a426c616b6554776f3235362061732073725f7072696d6974697665733a3a7472616974733a3a486173683e3a3a6f7264657265645f747269655f726f6f743a3a68373739373939656532646161363861618f0415436f72655f696e697469616c697a655f626c6f636b9004114d657461646174615f6d657461646174619104483c5b545d206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68666533386331353361356163326164389204683c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a68393131356662623533323965303964399304683c73726d6c5f6d657461646174613a3a4465636f6465446966666572656e743c422c4f3e206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a656e636f64655f746f3a3a683930613566666362353464373266346694041c426c6f636b4275696c6465725f6170706c795f65787472696e73696395041b426c6f636b4275696c6465725f66696e616c697a655f626c6f636b960420426c6f636b4275696c6465725f696e686572656e745f65787472696e7369637397043873726d6c5f74696d657374616d703a3a657874726163745f696e686572656e745f646174613a3a686362316436643834626362643035333698041c426c6f636b4275696c6465725f636865636b5f696e686572656e7473990418426c6f636b4275696c6465725f72616e646f6d5f736565649a042b5461676765645472616e73616374696f6e51756575655f76616c69646174655f7472616e73616374696f6e9b045673725f7072696d6974697665733a3a7472616e73616374696f6e5f76616c69646974793a3a56616c69645472616e73616374696f6e3a3a636f6d62696e655f776974683a3a68353736346238623566396161613662309c04214f6666636861696e576f726b65724170695f6f6666636861696e5f776f726b65729d0480013c73726d6c5f696d5f6f6e6c696e653a3a737232353531393a3a6170705f737232353531393a3a5075626c6963206173207375627374726174655f6170706c69636174696f6e5f63727970746f3a3a7472616974733a3a52756e74696d654170705075626c69633e3a3a616c6c3a3a68613834343166646339353935386136399e041e4772616e6470614170695f6772616e6470615f617574686f7269746965739f0415426162654170695f636f6e66696775726174696f6ea00421417574686f72697479446973636f766572794170695f617574686f726974696573a1041a417574686f72697479446973636f766572794170695f7369676ea2041c417574686f72697479446973636f766572794170695f766572696679a3041d4163636f756e744e6f6e63654170695f6163636f756e745f6e6f6e6365a40411436f6e7472616374734170695f63616c6ca5042153657373696f6e4b6579735f67656e65726174655f73657373696f6e5f6b657973a604820173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6838663434353163653739313862313333a704820173726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6c696e6b65645f6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654c696e6b65644d61703c4b2c563e20666f7220473e3a3a72656d6f76653a3a6861663431626330376265363732653261a8043a73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6832383266383039373163393635623735a9043c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6830613933393034626364613731633464aa04743c73726d6c5f7374616b696e673a3a5f5f47657442797465537472756374536c6173685265776172644672616374696f6e3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6830373539636563383531333663626462ab04773c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637443757272656e74457261506f696e74734561726e65643c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6863346466393062396266616466383466ac04703c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637443757272656e7445726153746172743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861346332306237316637343535343862ad04683c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563745374616b6572733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6834653030616266353365363433633733ae046b3c73726d6c5f7374616b696e673a3a5f5f4765744279746553747275637456616c696461746f72733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6839633736316334353032636466336536af04763c73726d6c5f7374616b696e673a3a5f5f476574427974655374727563744d696e696d756d56616c696461746f72436f756e743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6861336434623962346538633532666237b0044073726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a736c61736861626c655f62616c616e63655f6f663a3a6861636135383433363936353265613265b1043273726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a626f6e6465643a3a6830636562393635626631386363616232b2044573726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6837306665313036376639643939383935b30498013c73726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a426f6e64696e674475726174696f6e44656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832623535646136383130626464303061b4043773726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a6d616b655f7061796f75743a3a6832376631663237613230333735323861b5043973726d6c5f7374616b696e673a3a4d6f64756c653c543e3a3a7570646174655f6c65646765723a3a6832376563613564613530643864656139b6044a3c58206173207061726974795f7363616c655f636f6465633a3a636f6465633a3a456e636f64653e3a3a7573696e675f656e636f6465643a3a6866633236366266623663653230323433b7043f73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a696e6a6563745f7265666572656e64756d3a3a6866346266323835623039613038383533b8043873726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6465706f7369745f6f663a3a6833636363393431363966326232643635b9043c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a63616c6c5f66756e6374696f6e733a3a6831646437343931353664623131643533ba043e73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a73746f726167655f6d657461646174613a3a6838336233383939373363343862666435bb046c3c73726d6c5f64656d6f63726163793a3a5f5f47657442797465537472756374426c61636b6c6973743c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838623533343432616361336431616461bc046f3c73726d6c5f64656d6f63726163793a3a5f5f476574427974655374727563744e65787445787465726e616c3c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6837643466363231333432643433663038bd046e3c73726d6c5f64656d6f63726163793a3a5f5f4765744279746553747275637444656c65676174696f6e733c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833626665323435333261616465653139be04703c73726d6c5f64656d6f63726163793a3a5f5f47657442797465537472756374446973706174636851756575653c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6835356135336235653738653362353537bf044773726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a6864666466353637383338323064313530c00497013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4c61756e6368506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6865623830643136316665383833373935c104a0013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456d657267656e6379566f74696e67506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6833316232323132653732363163316232c20499013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a4d696e696d756d4465706f73697444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6832363265623533316566353366303065c3049a013c73726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a6d6f64756c655f636f6e7374616e74735f6d657461646174613a3a456e6163746d656e74506572696f6444656661756c74427974654765747465723c543e2061732073726d6c5f6d657461646174613a3a44656661756c74427974653e3a3a64656661756c745f627974653a3a6838343565333534353965616136613466c4047573726d6c5f737570706f72743a3a73746f726167653a3a67656e657261746f723a3a6d61703a3a3c696d706c2073726d6c5f737570706f72743a3a73746f726167653a3a53746f726167654d61703c4b2c563e20666f7220473e3a3a696e736572743a3a6832623431383266303634326531386431c5043573726d6c5f64656d6f63726163793a3a4d6f64756c653c543e3a3a646f5f766f74653a3a6834376438626636343531373064396363c604553c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832333130333466623262396161316637c704303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830376539663164633463383837333064c804303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6833613863363935663762313962666661c904303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6862343766326134326533363431363234ca04443c7061726974795f7761736d3a3a696f3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6836656663396633373739323336343738cb04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6863373733386638313465306262636138cc04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6865336235353835366335366563383866cd04457061726974795f7761736d3a3a656c656d656e74733a3a7365676d656e743a3a446174615365676d656e743a3a76616c75653a3a6861333366626161653136643036353336ce04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6831613930373663633036623361623965cf04303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6835653364383861646633663531633032d004553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6832333362653833316563653732373563d104553c7061726974795f7761736d3a3a656c656d656e74733a3a74797065733a3a426c6f636b5479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6838376433336131303565663737663430d204303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839343630376237663435333334613836d30433636f72653a3a6f7074696f6e3a3a4f7074696f6e3c26543e3a3a636c6f6e65643a3a6833336430666462656635333766383862d404453c636f72653a3a6f7074696f6e3a3a4f7074696f6e3c543e20617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6834643038393932373338626235366665d504303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6839626562663532613237376634306665d60440707761736d5f7574696c733a3a737461636b5f6865696768743a3a636f6d707574655f737461636b5f636f73743a3a6832656332613464616131633336616664d704533c616c6c6f633a3a7665633a3a5665633c543e20617320616c6c6f633a3a7665633a3a53706563457874656e643c542c493e3e3a3a737065635f657874656e643a3a6833663135373864636638623165303366d804323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6833333964366132336633616239353839d904593c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e20617320636f72653a3a636c6f6e653a3a436c6f6e653e3a3a636c6f6e653a3a6832303531346563626537613764663764da04613c616c6c6f633a3a636f6c6c656374696f6e733a3a62747265653a3a6d61703a3a42547265654d61703c4b2c563e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6865646336386533623863393232303938db043f707761736d5f7574696c733a3a737461636b5f6865696768743a3a7265736f6c76655f66756e635f747970653a3a6835666661376165643139363735653632dc0430636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6834383364613531306533653334653735dd0441707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a636f6d707574653a3a6830646665316537373831363437623164de0434636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6835353237373135663731363338343330df042e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a6833386430383365613239326630376635e0043c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a6833396131373737326563303238336633e104303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6830316234393736623730636366393962e2045a3c707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a4672616d6520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a6837373362393934386530363033303234e30446707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a6672616d653a3a6838653765623332646462333937343230e4044b707761736d5f7574696c733a3a737461636b5f6865696768743a3a6d61785f6865696768743a3a537461636b3a3a706f705f76616c7565733a3a6837613665336661633565303837386131e504323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6839353333633564346536303161336562e604323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6838333065633835663931653437646439e7044e73725f696f3a3a696d703a3a6578743a3a65787465726e5f66756e6374696f6e735f686f73745f696d706c3a3a6578745f7072696e745f757466383a3a6831316330336538356431303265376435e804683c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6833643262383038376431613430623032e9046b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6861376364656439653336396133323630ea047d3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973745772697465723c492c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6835653237663566326461333132313031eb046f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6833356432333232326631633463663837ec046f3c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a566172496e743634206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6836666134636162356466656233633936ed046c3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e697445787072206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6861353061613066336466316663643961ee046f3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6838663538373638626466643663363436ef04793c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a436f756e7465644c6973743c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6830326534363637616133663639633832f0046b3c7061726974795f7761736d3a3a656c656d656e74733a3a6f70733a3a496e737472756374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6866616531383734653335636562616238f104713c7061726974795f7761736d3a3a656c656d656e74733a3a696e6465785f6d61703a3a496e6465784d61703c543e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6837353163336164613534326365643464f204783c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6866653634336337356161613937393331f3047c3c7061726974795f7761736d3a3a656c656d656e74733a3a696d706f72745f656e7472793a3a526573697a61626c654c696d697473206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6834643135366137643832646366653437f404743c7061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a56617255696e743332206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6862396165303366373735323163303237f504713c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a437573746f6d53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a53657269616c697a653e3a3a73657269616c697a653a3a6864383435613264366361663338313736f6044b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6833303831373966353539376166373962f7044b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6862636562656465393336303030353930f8044b3c616c6c6f633a3a7665633a3a496e746f497465723c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6864356438333636626133356134666363f904463c616c6c6f633a3a7665633a3a5665633c543e20617320636f72653a3a6f70733a3a64726f703a3a44726f703e3a3a64726f703a3a6830393432356365343637643235646564fa046f3c7061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e206173207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a653e3a3a646573657269616c697a653a3a6835373532633363323332363061333635fb04457061726974795f7761736d3a3a656c656d656e74733a3a73656374696f6e3a3a53656374696f6e5265616465723a3a6e65773a3a6866656161316461386338643835366362fc0486017061726974795f7761736d3a3a656c656d656e74733a3a7072696d6974697665733a3a3c696d706c207061726974795f7761736d3a3a656c656d656e74733a3a446573657269616c697a6520666f7220616c6c6f633a3a737472696e673a3a537472696e673e3a3a646573657269616c697a653a3a6832303434366565303237346466653739fd042d636f72653a3a736c6963653a3a736f72743a3a726563757273653a3a6862353339623432353939316562373937fe0434636f72653a3a736c6963653a3a736f72743a3a627265616b5f7061747465726e733a3a6866623631656536316166636362646537ff042e636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a683038653936383835383561383932643480053c636f72653a3a736c6963653a3a736f72743a3a7061727469616c5f696e73657274696f6e5f736f72743a3a683631623461353636613537323964363781053b636f72653a3a736c6963653a3a736f72743a3a68656170736f72743a3a7b7b636c6f737572657d7d3a3a68343831336137356561636161653734378205323c265420617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a68663961303537303266333235643366618305397761736d695f76616c69646174696f6e3a3a76616c69646174655f6d656d6f72795f747970653a3a68386330623261323731393065373038328405347761736d695f76616c69646174696f6e3a3a657870725f636f6e73745f747970653a3a683232363566313162343233326265373685054a7761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a737465703a3a68353864303463346465383638653431658605473c7761736d695f76616c69646174696f6e3a3a4572726f7220617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a6837353566373166363063653234393764870537616c6c6f633a3a7261775f7665633a3a5261775665633c542c413e3a3a726573657276653a3a683462396237323936623436336634353588053b636f72653a3a736c6963653a3a3c696d706c205b545d3e3a3a636f70795f66726f6d5f736c6963653a3a68383832353431646433666436326537318905347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f76616c75653a3a68656337393434626366663764623131668a05347761736d695f76616c69646174696f6e3a3a66756e633a3a706f705f6c6162656c3a3a68326336353735376131376361383336338b05407761736d695f76616c69646174696f6e3a3a7574696c3a3a4c6f63616c733a3a747970655f6f665f6c6f63616c3a3a68383162303837636564666462346434388c05543c7761736d695f76616c69646174696f6e3a3a66756e633a3a537461636b56616c75655479706520617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68633739643161663136313838663435368d05537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6c6f61643a3a68366138333538613164613464626566308e05547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f73746f72653a3a68636564333562656564653636653562628f05557761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f746573746f703a3a68616533303233333361636330633266319005547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f72656c6f703a3a68376534356165623939363562643230379105537761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f756e6f703a3a68313765386433643566626361383862399205547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f62696e6f703a3a68333830663663353461613061383264399305547761736d695f76616c69646174696f6e3a3a66756e633a3a46756e6374696f6e56616c69646174696f6e436f6e746578743a3a76616c69646174655f6376746f703a3a6835353663323836383738376336363661940530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a6830363931663361393762336664333466950530636f72653a3a7074723a3a7265616c5f64726f705f696e5f706c6163653a3a68613966613837316265643663366635309605303c265420617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68393761376132643963636263616632399705453c616c6c6f633a3a737472696e673a3a537472696e6720617320636f72653a3a666d743a3a446973706c61793e3a3a666d743a3a683630376665306161343865353334636298054c3c7761736d695f76616c69646174696f6e3a3a737461636b3a3a4572726f7220617320636f72653a3a666d743a3a44656275673e3a3a666d743a3a68653966363833643036366338313166359905066d656d7365749a05066d656d6370799b05076d656d6d6f76659c05066d656d636d709d05095f5f6173686c7469339e05095f5f6c7368727469339f05085f5f6d756c746933a005095f5f75646976746933a105095f5f756d6f64746933a2050c5f5f756469766d6f6474693400550970726f64756365727302086c616e6775616765010452757374000c70726f6365737365642d62790105727573746325312e33392e302d6e696768746c79202831646431383834383920323031392d30392d323229", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b6579730cd914acf7b89329ae59e8f7e3b8f1ee7a4f5f68d4749cca82814f2f5b1d6bbb": "0x9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0xc98362e2ca21b342cc749022ed9b560e4d29ec9862a960c2538c314f1d279635": "0x149ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e3180973474718099c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d1268655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0x6e4ab2ac5a7cf9b1829eacc84a75bde0804be01fc31c9419ea72407f50a33384": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0x366a192e1ce90bf109f11cf4d4bdab1ce310d835c09411b1be3ad53814e33196": "0x000001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65", + "0x125dc846383907f5846f72ce53ca0e4b": "0x00ca9a3b000000000000000000000000", + "0x46cef122497fefa60faf6c66d3ef05caf9870446796ae11f0a4f734fee993d8b": "0x00", + "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b6579737f325c981c2b001f5fe8c51cc7b89e50ebb1f60feb7ab3fa3bc79d6ab71d45cb": "0x9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", + "0x71020fee971bd00e8248d1830b8cffbe5b9cf4de1ea2911a1665c44fd70ab6f3": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26630f0000c16ff286230f0000c16ff2862300", + "0xfff675c76ad8a5dfbd7db9a4e80f7c0ece595ad1878d2b6fca6086b2483a055b": "0x0000c16ff28623000000000000000000", + "0x2b334d6ac6698775ed17edf8cd3cbd9dae56cead0d69cb54f6af6aaecba544d8": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0xdfaac108e0d4bc78fc9419a7fcfa84dc": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde789c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0x3ae31af9a378162eb2736f26855c9ad8": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x3a65787472696e7369635f696e646578": "0x00000000", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797346c8960f8387b17441ee2be48a0896e48d3580e922c6e1cd8f53a621370c1e49": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0x7e6064dc0e78ffebb59b3053826a9467": "0x109c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d1268655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0xc1fdc3d212357bc2fa98f2a77b941f0c": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d6568655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde789c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b65797301dd273832961ca94116fd224019ea1370c0e3d27bebb1041b35651146d17832": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78", + "0x686f6c72b7b80bad8dba022335cb7c9e4556ac7ea200008da8046e3178eb89c1": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x2d5205eddfc20f1a616c0391abb78a3920e823abe7ed33cfd7945dd1a1bf8651": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", + "0x040ff70c23416b89ce6afb75ee0d362e": "0x00000000", + "0x121725e2f949944d00a8c011c0db54ae07b84a6ca772adf3c65417345d91522d": "0x0000c16ff28623000000000000000000", + "0x9c16fd03b96712dc0751bb0d63bc05aa": "0x00e1f505", + "0x8f9a319405d14f3953657373696f6e204b65794f776e6572343a73657373696f6e3a6b657973d1ae046d940202772415992434f839d8c546542e3055143c430f7eec87f7cb69": "0xf26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663", + "0xccea67b51b4fa33ecbff70a8977ad91d9c60d620f3ab5ac9626dea15cde023b7": "0x0ff6ffc06ff286230ff6ffc06ff2862300", + "0x886726f904d8372fdabb7707870c2fad": "0x1000299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f43780100000000000000482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a0100000000000000482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e01000000000000006e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91060100000000000000", + "0x68c8d2f39c4605e65218c22c5664917047e4900c797b7dd33999d94213c75049": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", + "0x7eb7a404bf7e3466c3f6c5914e25edfaab48b1e24fd29ea5a94deaaa1aba80e6": "0x0001547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65019c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12", + "0xdfa1667c116b77971ada377f9bd9c485a0566b8e477ae01969120423f2f124ea": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x92f53c21a80e624b3c606bc8ec0ce2a3003c4fe385bed33998bf4dc79b8970f2": "0x547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d650f0000c16ff286230f0000c16ff2862300", + "0xb2029f8665aac509629f2d28cea790a3": "0x10f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c26633919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d655633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde787932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d129becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe96993326e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f91066e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106", + "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b657973e54094c2d5af8ae10b91e1288f4f59f2946d7738f2c509b7effd909e5e9ba0ad": "0x5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a", + "0x78f4ad73d6b7279f8d06f359e363c829": "0x0000a49d8fc957363600000000000000", + "0xfd0cbba69a04d769ddcdbb15f5123c98041978f5241f33f78f62b48e3a02b740": "0x047374616b696e67200000c16ff28623000000000000000000ffffffff0f", + "0x26ac4a74e1ba94e0e7dbfc3b2aea083cf3c0f0d80eb999c7cebb340ee8934da9": "0x68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde780f0000c16ff286230f0000c16ff2862300", + "0xf4adb4c4f708c4b753657373696f6e204e6578744b657973343a73657373696f6e3a6b65797394f72a73893fbd00b11fcce65a014cc5b9ff5066ec15aa6be068b4cabfe67fdb": "0x3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f437800299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378", + "0x4ac2684a5a20e7a5adf17ed7aa792a3f6334a0505f02b2a44c3934d36cc4ee0a": "0xc8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e", + "0xa5e869ecc1b914a6b0cf5f02b874f5eb90f1739fbd3edd01e5835d1517fd9f72": "0x781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276" + }, + {} + ] } } diff --git a/node/cli/src/browser.rs b/node/cli/src/browser.rs new file mode 100644 index 0000000000000000000000000000000000000000..702d67b55afa5dfd2d15e443c1b4e509d7c163c2 --- /dev/null +++ b/node/cli/src/browser.rs @@ -0,0 +1,159 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use crate::ChainSpec; +use futures::{prelude::*, sync::oneshot, sync::mpsc}; +use libp2p::wasm_ext; +use log::{debug, info}; +use std::sync::Arc; +use substrate_service::{AbstractService, RpcSession, Roles as ServiceRoles, Configuration, config::DatabaseConfig}; +use wasm_bindgen::prelude::*; + +/// Starts the client. +/// +/// You must pass a libp2p transport that supports . +#[wasm_bindgen] +pub fn start_client(wasm_ext: wasm_ext::ffi::Transport) -> Result { + start_inner(wasm_ext) + .map_err(|err| JsValue::from_str(&err.to_string())) +} + +fn start_inner(wasm_ext: wasm_ext::ffi::Transport) -> Result> { + console_error_panic_hook::set_once(); + console_log::init_with_level(log::Level::Info); + + // Build the configuration to pass to the service. + let config = { + let wasm_ext = wasm_ext::ExtTransport::new(wasm_ext); + let chain_spec = ChainSpec::FlamingFir.load().map_err(|e| format!("{:?}", e))?; + let mut config = Configuration::<(), _, _>::default_with_spec_and_base_path(chain_spec, None); + config.network.transport = network::config::TransportConfig::Normal { + wasm_external_transport: Some(wasm_ext.clone()), + enable_mdns: false, + }; + config.telemetry_external_transport = Some(wasm_ext); + config.roles = ServiceRoles::LIGHT; + config.name = "Browser node".to_string(); + config.database = { + let db = Arc::new(kvdb_memorydb::create(10)); + DatabaseConfig::Custom(db) + }; + config + }; + + info!("Substrate browser node"); + info!(" version {}", config.full_version()); + info!(" by Parity Technologies, 2017-2019"); + info!("Chain specification: {}", config.chain_spec.name()); + info!("Node name: {}", config.name); + info!("Roles: {:?}", config.roles); + + // Create the service. This is the most heavy initialization step. + let mut service = crate::service::new_light(config).map_err(|e| format!("{:?}", e))?; + + // We now dispatch a background task responsible for processing the service. + // + // The main action performed by the code below consists in polling the service with + // `service.poll()`. + // The rest consists in handling RPC requests. + let (rpc_send_tx, mut rpc_send_rx) = mpsc::unbounded::(); + wasm_bindgen_futures::spawn_local(futures::future::poll_fn(move || { + loop { + match rpc_send_rx.poll() { + Ok(Async::Ready(Some(message))) => { + let fut = service.rpc_query(&message.session, &message.rpc_json); + let _ = message.send_back.send(Box::new(fut)); + }, + Ok(Async::NotReady) => break, + Err(_) | Ok(Async::Ready(None)) => return Ok(Async::Ready(())), + } + } + + loop { + match service.poll().map_err(|_| ())? { + Async::Ready(()) => return Ok(Async::Ready(())), + Async::NotReady => break + } + } + + Ok(Async::NotReady) + })); + + Ok(Client { + rpc_send_tx, + }) +} + +/// A running client. +#[wasm_bindgen] +pub struct Client { + rpc_send_tx: mpsc::UnboundedSender, +} + +struct RpcMessage { + rpc_json: String, + session: RpcSession, + send_back: oneshot::Sender, Error = ()>>>, +} + +#[wasm_bindgen] +impl Client { + /// Allows starting an RPC request. Returns a `Promise` containing the result of that request. + #[wasm_bindgen(js_name = "rpcSend")] + pub fn rpc_send(&mut self, rpc: &str) -> js_sys::Promise { + let rpc_session = RpcSession::new(mpsc::channel(1).0); + let (tx, rx) = oneshot::channel(); + let _ = self.rpc_send_tx.unbounded_send(RpcMessage { + rpc_json: rpc.to_owned(), + session: rpc_session, + send_back: tx, + }); + let fut = rx + .map_err(|_| ()) + .and_then(|fut| fut) + .map(|s| JsValue::from_str(&s.unwrap_or(String::new()))) + .map_err(|_| JsValue::NULL); + wasm_bindgen_futures::future_to_promise(fut) + } + + /// Subscribes to an RPC pubsub endpoint. + #[wasm_bindgen(js_name = "rpcSubscribe")] + pub fn rpc_subscribe(&mut self, rpc: &str, callback: js_sys::Function) { + let (tx, rx) = mpsc::channel(4); + let rpc_session = RpcSession::new(tx); + let (fut_tx, fut_rx) = oneshot::channel(); + let _ = self.rpc_send_tx.unbounded_send(RpcMessage { + rpc_json: rpc.to_owned(), + session: rpc_session.clone(), + send_back: fut_tx, + }); + let fut_rx = fut_rx + .map_err(|_| ()) + .and_then(|fut| fut); + wasm_bindgen_futures::spawn_local(fut_rx.then(|_| Ok(()))); + wasm_bindgen_futures::spawn_local(rx.for_each(move |s| { + match callback.call1(&callback, &JsValue::from_str(&s)) { + Ok(_) => Ok(()), + Err(_) => Err(()), + } + }).then(move |v| { + // We need to keep `rpc_session` alive. + debug!("RPC subscription has ended"); + drop(rpc_session); + v + })); + } +} diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index acedb5c14bb42919cec5ef841df13812b00d3cfa..04fb41c211009b4856dac0c3241593f5b8e26a3f 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -16,28 +16,46 @@ //! Substrate chain configurations. -use primitives::{Pair, Public, crypto::UncheckedInto}; -pub use node_primitives::{AccountId, Balance}; +use chain_spec::ChainSpecExtension; +use primitives::{Pair, Public, crypto::UncheckedInto, sr25519}; +use serde::{Serialize, Deserialize}; use node_runtime::{ - BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, - ElectionsConfig, GrandpaConfig, ImOnlineConfig, IndicesConfig, Perbill, - SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, SystemConfig, - TechnicalCommitteeConfig, WASM_BINARY, + BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, GrandpaConfig, + ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, + SudoConfig, SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, }; -use node_runtime::constants::{time::*, currency::*}; -pub use node_runtime::GenesisConfig; +use node_runtime::Block; +use node_runtime::constants::currency::*; use substrate_service; use hex_literal::hex; use substrate_telemetry::TelemetryEndpoints; use grandpa_primitives::{AuthorityId as GrandpaId}; use babe_primitives::{AuthorityId as BabeId}; -use im_online::AuthorityId as ImOnlineId; +use im_online::sr25519::{AuthorityId as ImOnlineId}; +use sr_primitives::{Perbill, traits::{Verify, IdentifyAccount}}; + +pub use node_primitives::{AccountId, Balance, Signature}; +pub use node_runtime::GenesisConfig; + +type AccountPublic = ::Signer; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; -/// Specialized `ChainSpec`. -pub type ChainSpec = substrate_service::ChainSpec; +/// Node `ChainSpec` extensions. +/// +/// Additional parameters for some Substrate core modules, +/// customizable from the chain spec. +#[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] +pub struct Extensions { + /// Block numbers with known hashes. + pub fork_blocks: client::ForkBlocks, +} +/// Specialized `ChainSpec`. +pub type ChainSpec = substrate_service::ChainSpec< + GenesisConfig, + Extensions, +>; /// Flaming Fir testnet generator pub fn flaming_fir_config() -> Result { ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..]) @@ -56,127 +74,64 @@ fn staging_testnet_config_genesis() -> GenesisConfig { let initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId)> = vec![( // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy - hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].unchecked_into(), + hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].into(), // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq - hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].unchecked_into(), - // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 - hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), - // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC - hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), + hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].into(), // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), ),( // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2 - hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].unchecked_into(), + hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].into(), // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF - hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].unchecked_into(), - // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ - hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), - // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE - hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), + hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].into(), // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), ),( // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp - hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].unchecked_into(), + hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].into(), // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9 - hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].unchecked_into(), - // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH - hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), - // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d - hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), + hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].into(), // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), ),( // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9 - hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].unchecked_into(), + hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].into(), // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn - hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].unchecked_into(), - // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x - hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), - // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 - hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), + hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].into(), // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), )]; // generated with secret: subkey inspect "$secret"/fir - let endowed_accounts: Vec = vec![ + let root_key: AccountId = hex![ // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo - hex!["9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809"].unchecked_into(), - ]; + "9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809" + ].into(); - const ENDOWMENT: Balance = 10_000_000 * DOLLARS; - const STASH: Balance = 100 * DOLLARS; + let endowed_accounts: Vec = vec![root_key.clone()]; - GenesisConfig { - system: Some(SystemConfig { - code: WASM_BINARY.to_vec(), - changes_trie_config: Default::default(), - }), - balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned() - .map(|k| (k, ENDOWMENT)) - .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) - .collect(), - vesting: vec![], - }), - indices: Some(IndicesConfig { - ids: endowed_accounts.iter().cloned() - .chain(initial_authorities.iter().map(|x| x.0.clone())) - .collect::>(), - }), - session: Some(SessionConfig { - keys: initial_authorities.iter().map(|x| { - (x.0.clone(), session_keys(x.2.clone(), x.3.clone(), x.4.clone())) - }).collect::>(), - }), - staking: Some(StakingConfig { - current_era: 0, - offline_slash: Perbill::from_parts(1_000_000), - validator_count: 7, - offline_slash_grace: 4, - minimum_validator_count: 4, - stakers: initial_authorities.iter().map(|x| { - (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator) - }).collect(), - invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), - .. Default::default() - }), - democracy: Some(DemocracyConfig::default()), - collective_Instance1: Some(CouncilConfig { - members: vec![], - phantom: Default::default(), - }), - collective_Instance2: Some(TechnicalCommitteeConfig { - members: vec![], - phantom: Default::default(), - }), - elections: Some(ElectionsConfig { - members: vec![], - presentation_duration: 1 * DAYS, - term_duration: 28 * DAYS, - desired_seats: 0, - }), - contracts: Some(ContractsConfig { - current_schedule: Default::default(), - gas_price: 1 * MILLICENTS, - }), - sudo: Some(SudoConfig { - key: endowed_accounts[0].clone(), - }), - babe: Some(BabeConfig { - authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), - }), - im_online: Some(ImOnlineConfig { - gossip_at: 0, - keys: initial_authorities.iter().map(|x| x.4.clone()).collect(), - }), - grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), - }), - membership_Instance1: Some(Default::default()), - } + testnet_genesis( + initial_authorities, + root_key, + Some(endowed_accounts), + false, + ) } /// Staging testnet config. @@ -190,7 +145,7 @@ pub fn staging_testnet_config() -> ChainSpec { Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])), None, None, - None, + Default::default(), ) } @@ -201,12 +156,18 @@ pub fn get_from_seed(seed: &str) -> ::Pu .public() } +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId where + AccountPublic: From<::Public> +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} /// Helper function to generate stash, controller and session key from seed pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, GrandpaId, BabeId, ImOnlineId) { ( - get_from_seed::(&format!("{}//stash", seed)), - get_from_seed::(seed), + get_account_id_from_seed::(&format!("{}//stash", seed)), + get_account_id_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), get_from_seed::(seed), @@ -222,38 +183,41 @@ pub fn testnet_genesis( ) -> GenesisConfig { let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(|| { vec![ - get_from_seed::("Alice"), - get_from_seed::("Bob"), - get_from_seed::("Charlie"), - get_from_seed::("Dave"), - get_from_seed::("Eve"), - get_from_seed::("Ferdie"), - get_from_seed::("Alice//stash"), - get_from_seed::("Bob//stash"), - get_from_seed::("Charlie//stash"), - get_from_seed::("Dave//stash"), - get_from_seed::("Eve//stash"), - get_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), ] }); const ENDOWMENT: Balance = 10_000_000 * DOLLARS; const STASH: Balance = 100 * DOLLARS; - let desired_seats = (endowed_accounts.len() / 2 - initial_authorities.len()) as u32; - GenesisConfig { system: Some(SystemConfig { code: WASM_BINARY.to_vec(), changes_trie_config: Default::default(), }), - indices: Some(IndicesConfig { - ids: endowed_accounts.clone(), - }), balances: Some(BalancesConfig { - balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect(), + balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT)) + .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) + .collect(), vesting: vec![], }), + indices: Some(IndicesConfig { + ids: endowed_accounts.iter().cloned() + .chain(initial_authorities.iter().map(|x| x.0.clone())) + .collect::>(), + }), session: Some(SessionConfig { keys: initial_authorities.iter().map(|x| { (x.0.clone(), session_keys(x.2.clone(), x.3.clone(), x.4.clone())) @@ -261,14 +225,13 @@ pub fn testnet_genesis( }), staking: Some(StakingConfig { current_era: 0, - minimum_validator_count: 1, - validator_count: 2, - offline_slash: Perbill::zero(), - offline_slash_grace: 0, + validator_count: initial_authorities.len() as u32 * 2, + minimum_validator_count: initial_authorities.len() as u32, stakers: initial_authorities.iter().map(|x| { (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator) }).collect(), invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), + slash_reward_fraction: Perbill::from_percent(10), .. Default::default() }), democracy: Some(DemocracyConfig::default()), @@ -280,14 +243,6 @@ pub fn testnet_genesis( members: vec![], phantom: Default::default(), }), - elections: Some(ElectionsConfig { - members: endowed_accounts.iter() - .filter(|&endowed| initial_authorities.iter().find(|&(_, controller, ..)| controller == endowed).is_none()) - .map(|a| (a.clone(), 1000000)).collect(), - presentation_duration: 10, - term_duration: 1000000, - desired_seats: desired_seats, - }), contracts: Some(ContractsConfig { current_schedule: contracts::Schedule { enable_println, // this should only be enabled on development chains @@ -299,16 +254,16 @@ pub fn testnet_genesis( key: root_key, }), babe: Some(BabeConfig { - authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), + authorities: vec![], }), - im_online: Some(ImOnlineConfig{ - gossip_at: 0, - keys: initial_authorities.iter().map(|x| x.4.clone()).collect(), + im_online: Some(ImOnlineConfig { + keys: vec![], }), grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + authorities: vec![], }), membership_Instance1: Some(Default::default()), + treasury: Some(Default::default()), } } @@ -317,7 +272,7 @@ fn development_config_genesis() -> GenesisConfig { vec![ get_authority_keys_from_seed("Alice"), ], - get_from_seed::("Alice"), + get_account_id_from_seed::("Alice"), None, true, ) @@ -325,7 +280,16 @@ fn development_config_genesis() -> GenesisConfig { /// Development config (single validator Alice) pub fn development_config() -> ChainSpec { - ChainSpec::from_genesis("Development", "dev", development_config_genesis, vec![], None, None, None, None) + ChainSpec::from_genesis( + "Development", + "dev", + development_config_genesis, + vec![], + None, + None, + None, + Default::default(), + ) } fn local_testnet_genesis() -> GenesisConfig { @@ -334,7 +298,7 @@ fn local_testnet_genesis() -> GenesisConfig { get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob"), ], - get_from_seed::("Alice"), + get_account_id_from_seed::("Alice"), None, false, ) @@ -342,21 +306,31 @@ fn local_testnet_genesis() -> GenesisConfig { /// Local testnet config (multivalidator Alice + Bob) pub fn local_testnet_config() -> ChainSpec { - ChainSpec::from_genesis("Local Testnet", "local_testnet", local_testnet_genesis, vec![], None, None, None, None) + ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + local_testnet_genesis, + vec![], + None, + None, + None, + Default::default(), + ) } #[cfg(test)] pub(crate) mod tests { use super::*; + use crate::service::new_full; + use substrate_service::Roles; use service_test; - use crate::service::Factory; fn local_testnet_genesis_instant_single() -> GenesisConfig { testnet_genesis( vec![ get_authority_keys_from_seed("Alice"), ], - get_from_seed::("Alice"), + get_account_id_from_seed::("Alice"), None, false, ) @@ -372,7 +346,7 @@ pub(crate) mod tests { None, None, None, - None, + Default::default(), ) } @@ -386,13 +360,22 @@ pub(crate) mod tests { None, None, None, - None, + Default::default(), ) } #[test] #[ignore] fn test_connectivity() { - service_test::connectivity::(integration_test_config_with_two_authorities()); + service_test::connectivity( + integration_test_config_with_two_authorities(), + |config| new_full(config), + |mut config| { + // light nodes are unsupported + config.roles = Roles::FULL; + new_full(config) + }, + true, + ); } } diff --git a/node/cli/src/cli.rs b/node/cli/src/cli.rs new file mode 100644 index 0000000000000000000000000000000000000000..4bddb50b4bcac95d6c9084cbd398dcdb5d037318 --- /dev/null +++ b/node/cli/src/cli.rs @@ -0,0 +1,210 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub use substrate_cli::error; +use tokio::prelude::Future; +use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; +pub use substrate_cli::{VersionInfo, IntoExit, NoCustom, SharedParams, ExecutionStrategyParam}; +use substrate_service::{AbstractService, Roles as ServiceRoles, Configuration}; +use log::info; +use structopt::{StructOpt, clap::App}; +use substrate_cli::{display_role, parse_and_prepare, AugmentClap, GetLogFilter, ParseAndPrepare}; +use crate::{service, ChainSpec, load_spec}; +use crate::factory_impl::FactoryState; +use transaction_factory::RuntimeAdapter; +use client::ExecutionStrategies; + +/// Custom subcommands. +#[derive(Clone, Debug, StructOpt)] +pub enum CustomSubcommands { + /// The custom factory subcommmand for manufacturing transactions. + #[structopt( + name = "factory", + about = "Manufactures num transactions from Alice to random accounts. \ + Only supported for development or local testnet." + )] + Factory(FactoryCmd), +} + +impl GetLogFilter for CustomSubcommands { + fn get_log_filter(&self) -> Option { + None + } +} + +/// The `factory` command used to generate transactions. +/// Please note: this command currently only works on an empty database! +#[derive(Debug, StructOpt, Clone)] +pub struct FactoryCmd { + /// How often to repeat. This option only has an effect in mode `MasterToNToM`. + #[structopt(long="rounds", default_value = "1")] + pub rounds: u64, + + /// MasterToN: Manufacture `num` transactions from the master account + /// to `num` randomly created accounts, one each. + /// + /// MasterTo1: Manufacture `num` transactions from the master account + /// to exactly one other randomly created account. + /// + /// MasterToNToM: Manufacture `num` transactions from the master account + /// to `num` randomly created accounts. + /// From each of these randomly created accounts manufacture + /// a transaction to another randomly created account. + /// Repeat this `rounds` times. If `rounds` = 1 the behavior + /// is the same as `MasterToN`.{n} + /// A -> B, A -> C, A -> D, ... x `num`{n} + /// B -> E, C -> F, D -> G, ...{n} + /// ... x `rounds` + /// + /// These three modes control manufacturing. + #[structopt(long="mode", default_value = "MasterToN")] + pub mode: transaction_factory::Mode, + + /// Number of transactions to generate. In mode `MasterNToNToM` this is + /// the number of transactions per round. + #[structopt(long="num", default_value = "8")] + pub num: u64, + + #[allow(missing_docs)] + #[structopt(flatten)] + pub shared_params: SharedParams, + + /// The means of execution used when calling into the runtime while importing blocks. + #[structopt( + long = "execution", + value_name = "STRATEGY", + possible_values = &ExecutionStrategyParam::variants(), + case_insensitive = true, + default_value = "NativeElseWasm" + )] + pub execution: ExecutionStrategyParam, +} + +impl AugmentClap for FactoryCmd { + fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + FactoryCmd::augment_clap(app) + } +} + +/// Parse command line arguments into service configuration. +pub fn run(args: I, exit: E, version: substrate_cli::VersionInfo) -> error::Result<()> where + I: IntoIterator, + T: Into + Clone, + E: IntoExit, +{ + type Config = Configuration<(), A, B>; + + match parse_and_prepare::(&version, "substrate-node", args) { + ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, + |exit, _cli_args, _custom_args, config: Config<_, _>| { + info!("{}", version.name); + info!(" version {}", config.full_version()); + info!(" by Parity Technologies, 2017-2019"); + info!("Chain specification: {}", config.chain_spec.name()); + info!("Node name: {}", config.name); + info!("Roles: {}", display_role(&config)); + let runtime = RuntimeBuilder::new().name_prefix("main-tokio-").build() + .map_err(|e| format!("{:?}", e))?; + match config.roles { + ServiceRoles::LIGHT => run_until_exit( + runtime, + service::new_light(config)?, + exit + ), + _ => run_until_exit( + runtime, + service::new_full(config)?, + exit + ), + } + }), + ParseAndPrepare::BuildSpec(cmd) => cmd.run::(load_spec), + ParseAndPrepare::ExportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>| + Ok(new_full_start!(config).0), load_spec, exit), + ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), + ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>| + Ok(new_full_start!(config).0), load_spec), + ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { + let mut config: Config<_, _> = substrate_cli::create_config_with_db_path( + load_spec, + &cli_args.shared_params, + &version, + )?; + config.execution_strategies = ExecutionStrategies { + importing: cli_args.execution.into(), + block_construction: cli_args.execution.into(), + other: cli_args.execution.into(), + ..Default::default() + }; + + match ChainSpec::from(config.chain_spec.id()) { + Some(ref c) if c == &ChainSpec::Development || c == &ChainSpec::LocalTestnet => {}, + _ => panic!("Factory is only supported for development and local testnet."), + } + + let factory_state = FactoryState::new( + cli_args.mode.clone(), + cli_args.num, + cli_args.rounds, + ); + + let service_builder = new_full_start!(config).0; + transaction_factory::factory::, _, _, _, _, _>( + factory_state, + service_builder.client(), + service_builder.select_chain() + .expect("The select_chain is always initialized by new_full_start!; QED") + ).map_err(|e| format!("Error in transaction factory: {}", e))?; + + Ok(()) + } + } +} + +fn run_until_exit( + mut runtime: Runtime, + service: T, + e: E, +) -> error::Result<()> +where + T: AbstractService, + E: IntoExit, +{ + let (exit_send, exit) = exit_future::signal(); + + let informant = substrate_cli::informant::build(&service); + runtime.executor().spawn(exit.until(informant).map(|_| ())); + + // we eagerly drop the service so that the internal exit future is fired, + // but we need to keep holding a reference to the global telemetry guard + let _telemetry = service.telemetry(); + + let service_res = { + let exit = e.into_exit().map_err(|_| error::Error::Other("Exit future failed.".into())); + let service = service.map_err(|err| error::Error::Service(err)); + let select = service.select(exit).map(|_| ()).map_err(|(err, _)| err); + runtime.block_on(select) + }; + + exit_send.fire(); + + // TODO [andre]: timeout this future #1318 + let _ = runtime.shutdown_on_idle().wait(); + + service_res +} diff --git a/node/cli/src/factory_impl.rs b/node/cli/src/factory_impl.rs index 6345a851f28ab115f8d3b846ef40ffd4458c1a5b..48fb7b237f1e67b5a6d0613dda0c4ff362fcecac 100644 --- a/node/cli/src/factory_impl.rs +++ b/node/cli/src/factory_impl.rs @@ -23,17 +23,22 @@ use rand::rngs::StdRng; use codec::{Encode, Decode}; use keyring::sr25519::Keyring; -use node_runtime::{Call, CheckedExtrinsic, UncheckedExtrinsic, SignedExtra, BalancesCall, ExistentialDeposit}; +use node_runtime::{ + Call, CheckedExtrinsic, UncheckedExtrinsic, SignedExtra, BalancesCall, ExistentialDeposit, + MinimumPeriod +}; +use node_primitives::Signature; use primitives::{sr25519, crypto::Pair}; -use sr_primitives::{generic::Era, traits::{Block as BlockT, Header as HeaderT, SignedExtension}}; +use sr_primitives::{ + generic::Era, traits::{Block as BlockT, Header as HeaderT, SignedExtension, Verify, IdentifyAccount} +}; use transaction_factory::RuntimeAdapter; use transaction_factory::modes::Mode; use inherents::InherentData; use timestamp; use finality_tracker; -// TODO get via api: ::MinimumPeriod::get(). See #2587. -const MINIMUM_PERIOD: u64 = 99; +type AccountPublic = ::Signer; pub struct FactoryState { block_no: N, @@ -51,11 +56,13 @@ type Number = <::Header as HeaderT>::Number; impl FactoryState { fn build_extra(index: node_primitives::Index, phase: u64) -> node_runtime::SignedExtra { ( + system::CheckVersion::new(), system::CheckGenesis::new(), system::CheckEra::from(Era::mortal(256, phase)), system::CheckNonce::from(index), system::CheckWeight::new(), - balances::TakeFees::from(0) + transaction_payment::ChargeTransactionPayment::from(0), + Default::default(), ) } } @@ -132,12 +139,12 @@ impl RuntimeAdapter for FactoryState { key: &Self::Secret, destination: &Self::AccountId, amount: &Self::Balance, + version: u32, genesis_hash: &::Hash, prior_block_hash: &::Hash, ) -> ::Extrinsic { let index = self.extract_index(&sender, prior_block_hash); let phase = self.extract_phase(*prior_block_hash); - sign::(CheckedExtrinsic { signed: Some((sender.clone(), Self::build_extra(index, phase))), function: Call::Balances( @@ -146,11 +153,11 @@ impl RuntimeAdapter for FactoryState { (*amount).into() ) ) - }, key, (genesis_hash.clone(), prior_block_hash.clone(), (), (), ())) + }, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), (), ())) } fn inherent_extrinsics(&self) -> InherentData { - let timestamp = self.block_no as u64 * MINIMUM_PERIOD; + let timestamp = (self.block_no as u64 + 1) * MinimumPeriod::get(); let mut inherent = InherentData::new(); inherent.put_data(timestamp::INHERENT_IDENTIFIER, ×tamp) @@ -161,12 +168,11 @@ impl RuntimeAdapter for FactoryState { } fn minimum_balance() -> Self::Balance { - // TODO get correct amount via api. See #2587. ExistentialDeposit::get() } fn master_account_id() -> Self::AccountId { - Keyring::Alice.pair().public() + Keyring::Alice.to_account_id() } fn master_account_secret() -> Self::Secret { @@ -176,7 +182,7 @@ impl RuntimeAdapter for FactoryState { /// Generates a random `AccountId` from `seed`. fn gen_random_account_id(seed: &Self::Number) -> Self::AccountId { let pair: sr25519::Pair = sr25519::Pair::from_seed(&gen_seed_bytes(*seed)); - pair.public().into() + AccountPublic::from(pair.public()).into_account() } /// Generates a random `Secret` from `seed`. diff --git a/node/cli/src/lib.rs b/node/cli/src/lib.rs index 4e3cfa7f0109217f81512f29fc3905e5cb1e97a2..78660ae92e3c5d00d066dddf82e4eb5e2044b036 100644 --- a/node/cli/src/lib.rs +++ b/node/cli/src/lib.rs @@ -15,26 +15,35 @@ // along with Substrate. If not, see . //! Substrate CLI library. +//! +//! This package has two Cargo features: +//! +//! - `cli` (default): exposes functions that parse command-line options, then start and run the +//! node as a CLI application. +//! +//! - `browser`: exposes the content of the `browser` module, which consists of exported symbols +//! that are meant to be passed through the `wasm-bindgen` utility and called from JavaScript. +//! Despite its name the produced WASM can theoretically also be used from NodeJS, although this +//! hasn't been tested. #![warn(missing_docs)] #![warn(unused_extern_crates)] -pub use cli::error; pub mod chain_spec; + +#[macro_use] mod service; +#[cfg(feature = "browser")] +mod browser; +#[cfg(feature = "cli")] +mod cli; +#[cfg(feature = "cli")] mod factory_impl; -use tokio::prelude::Future; -use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; -pub use cli::{VersionInfo, IntoExit, NoCustom, SharedParams, ExecutionStrategyParam}; -use substrate_service::{ServiceFactory, Roles as ServiceRoles}; -use std::ops::Deref; -use log::info; -use structopt::{StructOpt, clap::App}; -use cli::{AugmentClap, GetLogFilter, parse_and_prepare, ParseAndPrepare}; -use crate::factory_impl::FactoryState; -use transaction_factory::RuntimeAdapter; -use client::ExecutionStrategies; +#[cfg(feature = "browser")] +pub use browser::*; +#[cfg(feature = "cli")] +pub use cli::*; /// The chain specification option. #[derive(Clone, Debug, PartialEq)] @@ -49,80 +58,6 @@ pub enum ChainSpec { StagingTestnet, } -/// Custom subcommands. -#[derive(Clone, Debug, StructOpt)] -pub enum CustomSubcommands { - /// The custom factory subcommmand for manufacturing transactions. - #[structopt( - name = "factory", - about = "Manufactures num transactions from Alice to random accounts. \ - Only supported for development or local testnet." - )] - Factory(FactoryCmd), -} - -impl GetLogFilter for CustomSubcommands { - fn get_log_filter(&self) -> Option { - None - } -} - -/// The `factory` command used to generate transactions. -/// Please note: this command currently only works on an empty database! -#[derive(Debug, StructOpt, Clone)] -pub struct FactoryCmd { - /// How often to repeat. This option only has an effect in mode `MasterToNToM`. - #[structopt(long="rounds", default_value = "1")] - pub rounds: u64, - - /// MasterToN: Manufacture `num` transactions from the master account - /// to `num` randomly created accounts, one each. - /// - /// MasterTo1: Manufacture `num` transactions from the master account - /// to exactly one other randomly created account. - /// - /// MasterToNToM: Manufacture `num` transactions from the master account - /// to `num` randomly created accounts. - /// From each of these randomly created accounts manufacture - /// a transaction to another randomly created account. - /// Repeat this `rounds` times. If `rounds` = 1 the behavior - /// is the same as `MasterToN`.{n} - /// A -> B, A -> C, A -> D, ... x `num`{n} - /// B -> E, C -> F, D -> G, ...{n} - /// ... x `rounds` - /// - /// These three modes control manufacturing. - #[structopt(long="mode", default_value = "MasterToN")] - pub mode: transaction_factory::Mode, - - /// Number of transactions to generate. In mode `MasterNToNToM` this is - /// the number of transactions per round. - #[structopt(long="num", default_value = "8")] - pub num: u64, - - #[allow(missing_docs)] - #[structopt(flatten)] - pub shared_params: SharedParams, - - /// The means of execution used when calling into the runtime while importing blocks. - #[structopt( - long = "execution", - value_name = "STRATEGY", - raw( - possible_values = "&ExecutionStrategyParam::variants()", - case_insensitive = "true", - default_value = r#""NativeElseWasm""# - ) - )] - pub execution: ExecutionStrategyParam, -} - -impl AugmentClap for FactoryCmd { - fn augment_clap<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { - FactoryCmd::augment_clap(app) - } -} - /// Get a chain config from a spec setting. impl ChainSpec { pub(crate) fn load(self) -> Result { @@ -151,104 +86,3 @@ fn load_spec(id: &str) -> Result, String> { None => None, }) } - -/// Parse command line arguments into service configuration. -pub fn run(args: I, exit: E, version: cli::VersionInfo) -> error::Result<()> where - I: IntoIterator, - T: Into + Clone, - E: IntoExit, -{ - match parse_and_prepare::(&version, "substrate-node", args) { - ParseAndPrepare::Run(cmd) => cmd.run(load_spec, exit, |exit, _cli_args, _custom_args, config| { - info!("{}", version.name); - info!(" version {}", config.full_version()); - info!(" by Parity Technologies, 2017-2019"); - info!("Chain specification: {}", config.chain_spec.name()); - info!("Node name: {}", config.name); - info!("Roles: {:?}", config.roles); - let runtime = RuntimeBuilder::new().name_prefix("main-tokio-").build() - .map_err(|e| format!("{:?}", e))?; - match config.roles { - ServiceRoles::LIGHT => run_until_exit( - runtime, - service::Factory::new_light(config).map_err(|e| format!("{:?}", e))?, - exit - ), - _ => run_until_exit( - runtime, - service::Factory::new_full(config).map_err(|e| format!("{:?}", e))?, - exit - ), - }.map_err(|e| format!("{:?}", e)) - }), - ParseAndPrepare::BuildSpec(cmd) => cmd.run(load_spec), - ParseAndPrepare::ExportBlocks(cmd) => cmd.run::(load_spec, exit), - ParseAndPrepare::ImportBlocks(cmd) => cmd.run::(load_spec, exit), - ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec), - ParseAndPrepare::RevertChain(cmd) => cmd.run::(load_spec), - ParseAndPrepare::CustomCommand(CustomSubcommands::Factory(cli_args)) => { - let mut config = cli::create_config_with_db_path( - load_spec, - &cli_args.shared_params, - &version, - )?; - config.execution_strategies = ExecutionStrategies { - importing: cli_args.execution.into(), - block_construction: cli_args.execution.into(), - other: cli_args.execution.into(), - ..Default::default() - }; - - match ChainSpec::from(config.chain_spec.id()) { - Some(ref c) if c == &ChainSpec::Development || c == &ChainSpec::LocalTestnet => {}, - _ => panic!("Factory is only supported for development and local testnet."), - } - - let factory_state = FactoryState::new( - cli_args.mode.clone(), - cli_args.num, - cli_args.rounds, - ); - transaction_factory::factory::>( - factory_state, - config, - ).map_err(|e| format!("Error in transaction factory: {}", e))?; - - Ok(()) - } - } -} - -fn run_until_exit( - mut runtime: Runtime, - service: T, - e: E, -) -> error::Result<()> where - T: Deref>, - T: Future + Send + 'static, - C: substrate_service::Components, - E: IntoExit, -{ - let (exit_send, exit) = exit_future::signal(); - - let informant = cli::informant::build(&service); - runtime.executor().spawn(exit.until(informant).map(|_| ())); - - // we eagerly drop the service so that the internal exit future is fired, - // but we need to keep holding a reference to the global telemetry guard - let _telemetry = service.telemetry(); - - let service_res = { - let exit = e.into_exit().map_err(|_| error::Error::Other("Exit future failed.".into())); - let service = service.map_err(|err| error::Error::Service(err)); - let select = service.select(exit).map(|_| ()).map_err(|(err, _)| err); - runtime.block_on(select) - }; - - exit_send.fire(); - - // TODO [andre]: timeout this future #1318 - let _ = runtime.shutdown_on_idle().wait(); - - service_res -} diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 90c76eda84cbe2f37215169aa90fe050307ff8cc..09056591143ec668e1e8c652af03d7e94c827be8 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -16,294 +16,346 @@ #![warn(unused_extern_crates)] -//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. +//! Service implementation. Specialized wrapper over substrate service. use std::sync::Arc; -use std::time::Duration; -use babe::{import_queue, start_babe, BabeImportQueue, Config}; +use babe; use client::{self, LongestChain}; use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; use node_executor; -use futures::prelude::*; use node_primitives::Block; use node_runtime::{GenesisConfig, RuntimeApi}; use substrate_service::{ - FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, - FullClient, LightClient, LightBackend, FullExecutor, LightExecutor, - error::{Error as ServiceError}, + AbstractService, ServiceBuilder, config::Configuration, error::{Error as ServiceError}, }; use transaction_pool::{self, txpool::{Pool as TransactionPool}}; use inherents::InherentDataProviders; use network::construct_simple_protocol; -use substrate_service::construct_service_factory; -use substrate_service::TelemetryOnConnect; + +use substrate_service::{Service, NetworkStatus}; +use client::{Client, LocalCallExecutor}; +use client_db::Backend; +use sr_primitives::traits::Block as BlockT; +use node_executor::NativeExecutor; +use network::NetworkService; +use offchain::OffchainWorkers; +use primitives::Blake2Hasher; construct_simple_protocol! { /// Demo protocol attachment for substrate. pub struct NodeProtocol where Block = Block { } } -type BabeBlockImportForService = babe::BabeBlockImport< - FullBackend, - FullExecutor, - ::Block, - grandpa::BlockImportForService, - ::RuntimeApi, - client::Client< - FullBackend, - FullExecutor, - ::Block, - ::RuntimeApi - >, ->; - -/// Node specific configuration -pub struct NodeConfig { - /// GRANDPA and BABE connection to import block. - // FIXME #1134 rather than putting this on the config, let's have an actual intermediate setup state - pub import_setup: Option<( - BabeBlockImportForService, - grandpa::LinkHalfForService, - babe::BabeLink, - )>, - /// Tasks that were created by previous setup steps and should be spawned. - pub tasks_to_spawn: Option + Send>>>, - inherent_data_providers: InherentDataProviders, -} - -impl Default for NodeConfig where F: substrate_service::ServiceFactory { - fn default() -> NodeConfig { - NodeConfig { - import_setup: None, - inherent_data_providers: InherentDataProviders::new(), - tasks_to_spawn: None, - } - } -} - -construct_service_factory! { - struct Factory { - Block = Block, - RuntimeApi = RuntimeApi, - NetworkProtocol = NodeProtocol { |config| Ok(NodeProtocol::new()) }, - RuntimeDispatch = node_executor::Executor, - FullTransactionPoolApi = - transaction_pool::ChainApi< - client::Client, FullExecutor, Block, RuntimeApi>, - Block - > { - |config, client| - Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) - }, - LightTransactionPoolApi = - transaction_pool::ChainApi< - client::Client, LightExecutor, Block, RuntimeApi>, - Block - > { - |config, client| - Ok(TransactionPool::new(config, transaction_pool::ChainApi::new(client))) - }, - Genesis = GenesisConfig, - Configuration = NodeConfig, - FullService = FullComponents { - |config: FactoryFullConfiguration| FullComponents::::new(config) - }, - AuthoritySetup = { - |mut service: Self::FullService| { - let (block_import, link_half, babe_link) = - service.config_mut().custom.import_setup.take() - .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); - - // spawn any futures that were created in the previous setup steps - if let Some(tasks) = service.config_mut().custom.tasks_to_spawn.take() { - for task in tasks { - service.spawn_task( - task.select(service.on_exit()) - .map(|_| ()) - .map_err(|_| ()) - ); - } - } - - if service.config().roles.is_authority() { - let proposer = substrate_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; - - let client = service.client(); - let select_chain = service.select_chain() - .ok_or(ServiceError::SelectChainRequired)?; - - let babe_config = babe::BabeParams { - config: Config::get_or_compute(&*client)?, - keystore: service.keystore(), - client, - select_chain, - block_import, - env: proposer, - sync_oracle: service.network(), - inherent_data_providers: service.config() - .custom.inherent_data_providers.clone(), - force_authoring: service.config().force_authoring, - time_source: babe_link, - }; - - let babe = start_babe(babe_config)?; - let select = babe.select(service.on_exit()).then(|_| Ok(())); - - // the BABE authoring task is considered infallible, i.e. if it - // fails we take down the service with it. - service.spawn_essential_task(select); - } - - let config = grandpa::Config { - // FIXME #1578 make this available through chainspec - gossip_duration: Duration::from_millis(333), - justification_period: 4096, - name: Some(service.config().name.clone()), - keystore: Some(service.keystore()), - }; - - match (service.config().roles.is_authority(), service.config().disable_grandpa) { - (false, false) => { - // start the lightweight GRANDPA observer - service.spawn_task(Box::new(grandpa::run_grandpa_observer( - config, - link_half, - service.network(), - service.on_exit(), - )?)); - }, - (true, false) => { - // start the full GRANDPA voter - let telemetry_on_connect = TelemetryOnConnect { - telemetry_connection_sinks: service.telemetry_on_connect_stream(), - }; - let grandpa_config = grandpa::GrandpaParams { - config: config, - link: link_half, - network: service.network(), - inherent_data_providers: - service.config().custom.inherent_data_providers.clone(), - on_exit: service.on_exit(), - telemetry_on_connect: Some(telemetry_on_connect), - }; - - // the GRANDPA voter task is considered infallible, i.e. - // if it fails we take down the service with it. - service.spawn_essential_task(grandpa::run_grandpa_voter(grandpa_config)?); - }, - (_, true) => { - grandpa::setup_disabled_grandpa( - service.client(), - &service.config().custom.inherent_data_providers, - service.network(), - )?; - }, - } - - Ok(service) - } - }, - LightService = LightComponents - { |config| >::new(config) }, - FullImportQueue = BabeImportQueue - { - | - config: &mut FactoryFullConfiguration, - client: Arc>, - select_chain: Self::SelectChain, - transaction_pool: Option>>, - | - { - let (block_import, link_half) = - grandpa::block_import::<_, _, _, RuntimeApi, FullClient, _>( - client.clone(), client.clone(), select_chain +/// Starts a `ServiceBuilder` for a full service. +/// +/// Use this macro if you don't actually need the full service, but just the builder in order to +/// be able to perform chain operations. +macro_rules! new_full_start { + ($config:expr) => {{ + type RpcExtension = jsonrpc_core::IoHandler; + let mut import_setup = None; + let inherent_data_providers = inherents::InherentDataProviders::new(); + + let builder = substrate_service::ServiceBuilder::new_full::< + node_primitives::Block, node_runtime::RuntimeApi, node_executor::Executor + >($config)? + .with_select_chain(|_config, backend| { + Ok(client::LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client| + Ok(transaction_pool::txpool::Pool::new(config, transaction_pool::FullChainApi::new(client))) + )? + .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { + let select_chain = select_chain.take() + .ok_or_else(|| substrate_service::Error::SelectChainRequired)?; + let (grandpa_block_import, grandpa_link) = + grandpa::block_import::<_, _, _, node_runtime::RuntimeApi, _, _>( + client.clone(), &*client, select_chain )?; - let justification_import = block_import.clone(); + let justification_import = grandpa_block_import.clone(); + + let (block_import, babe_link) = babe::block_import( + babe::Config::get_or_compute(&*client)?, + grandpa_block_import, + client.clone(), + client.clone(), + )?; - let (import_queue, babe_link, babe_block_import, pruning_task) = import_queue( - Config::get_or_compute(&*client)?, - block_import, + let import_queue = babe::import_queue( + babe_link.clone(), + block_import.clone(), Some(Box::new(justification_import)), None, client.clone(), client, - config.custom.inherent_data_providers.clone(), - transaction_pool, + inherent_data_providers.clone(), )?; - config.custom.import_setup = Some((babe_block_import.clone(), link_half, babe_link)); - config.custom.tasks_to_spawn = Some(vec![Box::new(pruning_task)]); - + import_setup = Some((block_import, grandpa_link, babe_link)); Ok(import_queue) - }}, - LightImportQueue = BabeImportQueue - { |config: &FactoryFullConfiguration, client: Arc>| { - #[allow(deprecated)] - let fetch_checker = client.backend().blockchain().fetcher() - .upgrade() - .map(|fetcher| fetcher.checker().clone()) - .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; - let block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, LightClient>( - client.clone(), Arc::new(fetch_checker), client.clone() - )?; + })? + .with_rpc_extensions(|client, pool, _backend| -> RpcExtension { + node_rpc::create(client, pool) + })?; - let finality_proof_import = block_import.clone(); - let finality_proof_request_builder = - finality_proof_import.create_finality_proof_request_builder(); + (builder, import_setup, inherent_data_providers) + }} +} - // FIXME: pruning task isn't started since light client doesn't do `AuthoritySetup`. - let (import_queue, ..) = import_queue::<_, _, _, _, _, _, TransactionPool>( - Config::get_or_compute(&*client)?, - block_import, - None, - Some(Box::new(finality_proof_import)), - client.clone(), - client, - config.custom.inherent_data_providers.clone(), - None, +/// Creates a full service from the configuration. +/// +/// We need to use a macro because the test suit doesn't work with an opaque service. It expects +/// concrete types instead. +macro_rules! new_full { + ($config:expr, $with_startup_data: expr) => {{ + use futures::sync::mpsc; + use network::DhtEvent; + + let ( + is_authority, + force_authoring, + name, + disable_grandpa + ) = ( + $config.roles.is_authority(), + $config.force_authoring, + $config.name.clone(), + $config.disable_grandpa + ); + + // sentry nodes announce themselves as authorities to the network + // and should run the same protocols authorities do, but it should + // never actively participate in any consensus process. + let participates_in_consensus = is_authority && !$config.sentry_mode; + + let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config); + + // Dht event channel from the network to the authority discovery module. Use bounded channel to ensure + // back-pressure. Authority discovery is triggering one event per authority within the current authority set. + // This estimates the authority set size to be somewhere below 10 000 thereby setting the channel buffer size to + // 10 000. + let (dht_event_tx, _dht_event_rx) = + mpsc::channel::(10_000); + + let service = builder.with_network_protocol(|_| Ok(crate::service::NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, client)) as _) + )? + .with_dht_event_tx(dht_event_tx)? + .build()?; + + let (block_import, grandpa_link, babe_link) = import_setup.take() + .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + + ($with_startup_data)(&block_import, &babe_link); + + if participates_in_consensus { + let proposer = substrate_basic_authorship::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }; + + let client = service.client(); + let select_chain = service.select_chain() + .ok_or(substrate_service::Error::SelectChainRequired)?; + + let babe_config = babe::BabeParams { + keystore: service.keystore(), + client, + select_chain, + env: proposer, + block_import, + sync_oracle: service.network(), + inherent_data_providers: inherent_data_providers.clone(), + force_authoring, + babe_link, + }; + + let babe = babe::start_babe(babe_config)?; + service.spawn_essential_task(babe); + } + + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if participates_in_consensus { + Some(service.keystore()) + } else { + None + }; + + let config = grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: std::time::Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: true, + keystore, + is_authority, + }; + + match (is_authority, disable_grandpa) { + (false, false) => { + // start the lightweight GRANDPA observer + service.spawn_task(grandpa::run_grandpa_observer( + config, + grandpa_link, + service.network(), + service.on_exit(), + )?); + }, + (true, false) => { + // start the full GRANDPA voter + let grandpa_config = grandpa::GrandpaParams { + config: config, + link: grandpa_link, + network: service.network(), + inherent_data_providers: inherent_data_providers.clone(), + on_exit: service.on_exit(), + telemetry_on_connect: Some(service.telemetry_on_connect_stream()), + voting_rule: grandpa::VotingRulesBuilder::default().build(), + }; + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + service.spawn_essential_task(grandpa::run_grandpa_voter(grandpa_config)?); + }, + (_, true) => { + grandpa::setup_disabled_grandpa( + service.client(), + &inherent_data_providers, + service.network(), )?; + }, + } - Ok((import_queue, finality_proof_request_builder)) - }}, - SelectChain = LongestChain, Self::Block> - { |config: &FactoryFullConfiguration, client: Arc>| { - #[allow(deprecated)] - Ok(LongestChain::new(client.backend().clone())) - } - }, - FinalityProofProvider = { |client: Arc>| { - Ok(Some(Arc::new(GrandpaFinalityProofProvider::new(client.clone(), client)) as _)) - }}, - } + Ok((service, inherent_data_providers)) + }}; + ($config:expr) => {{ + new_full!($config, |_, _| {}) + }} +} + +#[allow(dead_code)] +type ConcreteBlock = node_primitives::Block; +#[allow(dead_code)] +type ConcreteClient = + Client< + Backend, + LocalCallExecutor, + NativeExecutor>, + ConcreteBlock, + node_runtime::RuntimeApi + >; +#[allow(dead_code)] +type ConcreteBackend = Backend; + +/// A specialized configuration object for setting up the node.. +pub type NodeConfiguration = Configuration; + +/// Builds a new service for a full client. +pub fn new_full(config: NodeConfiguration) +-> Result< + Service< + ConcreteBlock, + ConcreteClient, + LongestChain, + NetworkStatus, + NetworkService::Hash>, + TransactionPool>, + OffchainWorkers< + ConcreteClient, + >::OffchainStorage, + ConcreteBlock, + > + >, + ServiceError, +> +{ + new_full!(config).map(|(service, _)| service) } +/// Builds a new service for a light client. +pub fn new_light(config: NodeConfiguration) +-> Result { + type RpcExtension = jsonrpc_core::IoHandler; + let inherent_data_providers = InherentDataProviders::new(); + + let service = ServiceBuilder::new_light::(config)? + .with_select_chain(|_config, backend| { + Ok(LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client| + Ok(TransactionPool::new(config, transaction_pool::FullChainApi::new(client))) + )? + .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { + let fetch_checker = fetcher + .map(|fetcher| fetcher.checker().clone()) + .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; + let grandpa_block_import = grandpa::light_block_import::<_, _, _, RuntimeApi, _>( + client.clone(), backend, Arc::new(fetch_checker), client.clone() + )?; + + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = + finality_proof_import.create_finality_proof_request_builder(); + + let (babe_block_import, babe_link) = babe::block_import( + babe::Config::get_or_compute(&*client)?, + grandpa_block_import, + client.clone(), + client.clone(), + )?; + + let import_queue = babe::import_queue( + babe_link, + babe_block_import, + None, + Some(Box::new(finality_proof_import)), + client.clone(), + client, + inherent_data_providers.clone(), + )?; + + Ok((import_queue, finality_proof_request_builder)) + })? + .with_network_protocol(|_| Ok(NodeProtocol::new()))? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .with_rpc_extensions(|client, pool, _backend| -> RpcExtension { + node_rpc::create(client, pool) + })? + .build()?; + + Ok(service) +} #[cfg(test)] mod tests { use std::sync::Arc; use babe::CompatibleDigestItem; use consensus_common::{ - Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy + Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy, BlockImport, }; - use node_primitives::DigestItem; - use node_runtime::{BalancesCall, Call, UncheckedExtrinsic}; + use node_primitives::{Block, DigestItem, Signature}; + use node_runtime::{BalancesCall, Call, UncheckedExtrinsic, Address}; use node_runtime::constants::{currency::CENTS, time::SLOT_DURATION}; use codec::{Encode, Decode}; - use primitives::{ - crypto::Pair as CryptoPair, blake2_256, - sr25519::Public as AddressPublic, H256, + use primitives::{crypto::Pair as CryptoPair, H256}; + use sr_primitives::{ + generic::{BlockId, Era, Digest, SignedPayload}, + traits::Block as BlockT, + traits::Verify, + OpaqueExtrinsic, }; - use sr_primitives::{generic::{BlockId, Era, Digest}, traits::Block, OpaqueExtrinsic}; use timestamp; use finality_tracker; use keyring::AccountKeyring; - use substrate_service::ServiceFactory; - use service_test::SyncService; - use crate::service::Factory; + use substrate_service::{AbstractService, Roles}; + use crate::service::new_full; + use sr_primitives::traits::IdentifyAccount; + + type AccountPublic = ::Signer; #[cfg(feature = "rhd")] fn test_sync() { @@ -358,8 +410,14 @@ mod tests { let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); OpaqueExtrinsic(v) }; - service_test::sync::( + service_test::sync( chain_spec::integration_test_config(), + |config| new_full(config), + |mut config| { + // light nodes are unsupported + config.roles = Roles::FULL; + new_full(config) + }, block_factory, extrinsic_factory, ); @@ -376,127 +434,156 @@ mod tests { let chain_spec = crate::chain_spec::tests::integration_test_config_with_single_authority(); + // For the block factory let mut slot_num = 1u64; - let block_factory = |service: &SyncService<::FullService>| { - let service = service.get(); - let mut inherent_data = service - .config() - .custom - .inherent_data_providers - .create_inherent_data() - .expect("Creates inherent data."); - inherent_data.replace_data(finality_tracker::INHERENT_IDENTIFIER, &1u64); - - let parent_id = BlockId::number(service.client().info().chain.best_number); - let parent_header = service.client().header(&parent_id).unwrap().unwrap(); - let mut proposer_factory = substrate_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; - - let mut digest = Digest::::default(); - - // even though there's only one authority some slots might be empty, - // so we must keep trying the next slots until we can claim one. - let babe_pre_digest = loop { - inherent_data.replace_data(timestamp::INHERENT_IDENTIFIER, &(slot_num * SLOT_DURATION)); - if let Some(babe_pre_digest) = babe::test_helpers::claim_slot( - &*service.client(), - &parent_id, - slot_num, - (278, 1000), - &keystore, - ) { - break babe_pre_digest; - } - slot_num += 1; - }; + // For the extrinsics factory + let bob = Arc::new(AccountKeyring::Bob.pair()); + let charlie = Arc::new(AccountKeyring::Charlie.pair()); + let mut index = 0; - digest.push(::babe_pre_digest(babe_pre_digest)); - - let mut proposer = proposer_factory.init(&parent_header).unwrap(); - let new_block = futures03::executor::block_on(proposer.propose( - inherent_data, - digest, - std::time::Duration::from_secs(1), - )).expect("Error making test block"); - - let (new_header, new_body) = new_block.deconstruct(); - let pre_hash = new_header.hash(); - // sign the pre-sealed hash of the block and then - // add it to a digest item. - let to_sign = pre_hash.encode(); - let signature = alice.sign(&to_sign[..]); - let item = ::babe_seal( - signature.into(), - ); - slot_num += 1; + service_test::sync( + chain_spec, + |config| { + let mut setup_handles = None; + new_full!(config, | + block_import: &babe::BabeBlockImport<_, _, Block, _, _, _>, + babe_link: &babe::BabeLink, + | { + setup_handles = Some((block_import.clone(), babe_link.clone())); + }).map(move |(node, x)| (node, (x, setup_handles.unwrap()))) + }, + |mut config| { + // light nodes are unsupported + config.roles = Roles::FULL; + new_full(config) + }, + |service, &mut (ref inherent_data_providers, (ref mut block_import, ref babe_link))| { + let mut inherent_data = inherent_data_providers + .create_inherent_data() + .expect("Creates inherent data."); + inherent_data.replace_data(finality_tracker::INHERENT_IDENTIFIER, &1u64); + + let parent_id = BlockId::number(service.client().info().chain.best_number); + let parent_header = service.client().header(&parent_id).unwrap().unwrap(); + let mut proposer_factory = substrate_basic_authorship::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }; - BlockImportParams { - origin: BlockOrigin::File, - header: new_header, - justification: None, - post_digests: vec![item], - body: Some(new_body), - finalized: true, - auxiliary: Vec::new(), - fork_choice: ForkChoiceStrategy::LongestChain, - } - }; + let mut digest = Digest::::default(); + + // even though there's only one authority some slots might be empty, + // so we must keep trying the next slots until we can claim one. + let babe_pre_digest = loop { + inherent_data.replace_data(timestamp::INHERENT_IDENTIFIER, &(slot_num * SLOT_DURATION)); + if let Some(babe_pre_digest) = babe::test_helpers::claim_slot( + slot_num, + &parent_header, + &*service.client(), + &keystore, + &babe_link, + ) { + break babe_pre_digest; + } - let bob = Arc::new(AccountKeyring::Bob.pair()); - let charlie = Arc::new(AccountKeyring::Charlie.pair()); + slot_num += 1; + }; - let mut index = 0; - let extrinsic_factory = |service: &SyncService<::FullService>| { - let amount = 5 * CENTS; - let to = AddressPublic::from_raw(bob.public().0); - let from = AddressPublic::from_raw(charlie.public().0); - let genesis_hash = service.get().client().block_hash(0).unwrap().unwrap(); - let signer = charlie.clone(); - - let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); - - let check_genesis = system::CheckGenesis::new(); - let check_era = system::CheckEra::from(Era::Immortal); - let check_nonce = system::CheckNonce::from(index); - let check_weight = system::CheckWeight::new(); - let take_fees = balances::TakeFees::from(0); - let extra = (check_genesis, check_era, check_nonce, check_weight, take_fees); - - let raw_payload = (function, extra.clone(), genesis_hash, genesis_hash); - let signature = raw_payload.using_encoded(|payload| if payload.len() > 256 { - signer.sign(&blake2_256(payload)[..]) - } else { - signer.sign(payload) - }); - let xt = UncheckedExtrinsic::new_signed( - raw_payload.0, - from.into(), - signature.into(), - extra, - ).encode(); - let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); + digest.push(::babe_pre_digest(babe_pre_digest)); + + let mut proposer = proposer_factory.init(&parent_header).unwrap(); + let new_block = futures03::executor::block_on(proposer.propose( + inherent_data, + digest, + std::time::Duration::from_secs(1), + )).expect("Error making test block"); + + let (new_header, new_body) = new_block.deconstruct(); + let pre_hash = new_header.hash(); + // sign the pre-sealed hash of the block and then + // add it to a digest item. + let to_sign = pre_hash.encode(); + let signature = alice.sign(&to_sign[..]); + let item = ::babe_seal( + signature.into(), + ); + slot_num += 1; - index += 1; - OpaqueExtrinsic(v) - }; + let params = BlockImportParams { + origin: BlockOrigin::File, + header: new_header, + justification: None, + post_digests: vec![item], + body: Some(new_body), + finalized: true, + auxiliary: Vec::new(), + fork_choice: ForkChoiceStrategy::LongestChain, + }; - service_test::sync::( - chain_spec, - block_factory, - extrinsic_factory, + block_import.import_block(params, Default::default()) + .expect("error importing test block"); + }, + |service, _| { + let amount = 5 * CENTS; + let to: Address = AccountPublic::from(bob.public()).into_account().into(); + let from: Address = AccountPublic::from(charlie.public()).into_account().into(); + let genesis_hash = service.client().block_hash(0).unwrap().unwrap(); + let best_block_id = BlockId::number(service.client().info().chain.best_number); + let version = service.client().runtime_version_at(&best_block_id).unwrap().spec_version; + let signer = charlie.clone(); + + let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); + + let check_version = system::CheckVersion::new(); + let check_genesis = system::CheckGenesis::new(); + let check_era = system::CheckEra::from(Era::Immortal); + let check_nonce = system::CheckNonce::from(index); + let check_weight = system::CheckWeight::new(); + let payment = transaction_payment::ChargeTransactionPayment::from(0); + let extra = ( + check_version, + check_genesis, + check_era, + check_nonce, + check_weight, + payment, + Default::default(), + ); + let raw_payload = SignedPayload::from_raw( + function, + extra, + (version, genesis_hash, genesis_hash, (), (), (), ()) + ); + let signature = raw_payload.using_encoded(|payload| { + signer.sign(payload) + }); + let (function, extra, _) = raw_payload.deconstruct(); + let xt = UncheckedExtrinsic::new_signed( + function, + from.into(), + signature.into(), + extra, + ).encode(); + let v: Vec = Decode::decode(&mut xt.as_slice()).unwrap(); + + index += 1; + OpaqueExtrinsic(v) + }, ); } #[test] #[ignore] fn test_consensus() { - use super::Factory; - - service_test::consensus::( + service_test::consensus( crate::chain_spec::tests::integration_test_config_with_two_authorities(), + |config| new_full(config), + |mut config| { + // light nodes are unsupported + config.roles = Roles::FULL; + new_full(config) + }, vec![ "//Alice".into(), "//Bob".into(), diff --git a/node/executor/Cargo.toml b/node/executor/Cargo.toml index d1886c2ab6ea928b153afaafe0ba2ed32a990909..93f29910edbe05edfa66e4d0772315a7bd234914 100644 --- a/node/executor/Cargo.toml +++ b/node/executor/Cargo.toml @@ -6,7 +6,7 @@ description = "Substrate node implementation in Rust." edition = "2018" [dependencies] -trie-root = "0.15.0" +trie-root = "0.15.2" codec = { package = "parity-scale-codec", version = "1.0.0" } runtime_io = { package = "sr-io", path = "../../core/sr-io" } state_machine = { package = "substrate-state-machine", path = "../../core/state-machine" } @@ -17,21 +17,29 @@ node-primitives = { path = "../primitives" } node-runtime = { path = "../runtime" } [dev-dependencies] +node-testing = { path = "../testing" } test-client = { package = "substrate-test-client", path = "../../core/test-client" } -keyring = { package = "substrate-keyring", path = "../../core/keyring" } sr-primitives = { path = "../../core/sr-primitives" } runtime_support = { package = "srml-support", path = "../../srml/support" } balances = { package = "srml-balances", path = "../../srml/balances" } +transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment" } session = { package = "srml-session", path = "../../srml/session" } -staking = { package = "srml-staking", path = "../../srml/staking" } system = { package = "srml-system", path = "../../srml/system" } timestamp = { package = "srml-timestamp", path = "../../srml/timestamp" } treasury = { package = "srml-treasury", path = "../../srml/treasury" } contracts = { package = "srml-contracts", path = "../../srml/contracts" } grandpa = { package = "srml-grandpa", path = "../../srml/grandpa" } indices = { package = "srml-indices", path = "../../srml/indices" } -wabt = "~0.7.4" +wabt = "0.9.2" +criterion = "0.3.0" [features] -benchmarks = [] +wasmtime = [ + "substrate-executor/wasmtime", +] stress-test = [] + +[[bench]] +name = "bench" +harness = false + diff --git a/node/executor/benches/bench.rs b/node/executor/benches/bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..53e544ee0e9692cf192dbe8cc711bc8151422a38 --- /dev/null +++ b/node/executor/benches/bench.rs @@ -0,0 +1,200 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{Decode, Encode}; +use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; +use node_executor::Executor; +use node_primitives::{BlockNumber, Hash}; +use node_runtime::{ + Block, BuildStorage, Call, CheckedExtrinsic, GenesisConfig, Header, UncheckedExtrinsic, +}; +use node_runtime::constants::currency::*; +use node_testing::keyring::*; +use primitives::{Blake2Hasher, NativeOrEncoded, NeverNativeValue}; +use primitives::storage::well_known_keys; +use primitives::traits::CodeExecutor; +use runtime_support::Hashable; +use state_machine::TestExternalities as CoreTestExternalities; +use substrate_executor::{NativeExecutor, RuntimeInfo, WasmExecutionMethod, Externalities}; + +criterion_group!(benches, bench_execute_block); +criterion_main!(benches); + +/// The wasm runtime code. +const COMPACT_CODE: &[u8] = node_runtime::WASM_BINARY; + +const GENESIS_HASH: [u8; 32] = [69u8; 32]; + +const VERSION: u32 = node_runtime::VERSION.spec_version; + +const HEAP_PAGES: u64 = 20; + +type TestExternalities = CoreTestExternalities; + +#[derive(Debug)] +enum ExecutionMethod { + Native, + Wasm(WasmExecutionMethod), +} + +fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { + node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) +} + +fn new_test_ext(genesis_config: &GenesisConfig) -> TestExternalities { + let mut test_ext = TestExternalities::new_with_code( + COMPACT_CODE, + genesis_config.build_storage().unwrap(), + ); + ext.with_ext(|ext| { + ext.place_storage(well_known_keys::HEAP_PAGES.to_vec(), Some(HEAP_PAGES.encode())); + }); + test_ext +} + +fn construct_block( + executor: &NativeExecutor, + ext: &mut E, + number: BlockNumber, + parent_hash: Hash, + extrinsics: Vec, +) -> (Vec, Hash) { + use trie::{TrieConfiguration, trie_types::Layout}; + + // sign extrinsics. + let extrinsics = extrinsics.into_iter().map(sign).collect::>(); + + // calculate the header fields that we can. + let extrinsics_root = Layout::::ordered_trie_root( + extrinsics.iter().map(Encode::encode) + ).to_fixed_bytes() + .into(); + + let header = Header { + parent_hash, + number, + extrinsics_root, + state_root: Default::default(), + digest: Default::default(), + }; + + // execute the block to get the real header. + executor.call::<_, NeverNativeValue, fn() -> _>( + ext, + "Core_initialize_block", + &header.encode(), + true, + None, + ).0.unwrap(); + + for i in extrinsics.iter() { + executor.call::<_, NeverNativeValue, fn() -> _>( + ext, + "BlockBuilder_apply_extrinsic", + &i.encode(), + true, + None, + ).0.unwrap(); + } + + let header = match executor.call::<_, NeverNativeValue, fn() -> _>( + ext, + "BlockBuilder_finalize_block", + &[0u8;0], + true, + None, + ).0.unwrap() { + NativeOrEncoded::Native(_) => unreachable!(), + NativeOrEncoded::Encoded(h) => Header::decode(&mut &h[..]).unwrap(), + }; + + let hash = header.blake2_256(); + (Block { header, extrinsics }.encode(), hash.into()) +} + + +fn test_blocks(genesis_config: &GenesisConfig, executor: &NativeExecutor) + -> Vec<(Vec, Hash)> +{ + let mut test_ext = new_test_ext(genesis_config); + let mut block1_extrinsics = vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(timestamp::Call::set(42 * 1000)), + }, + ]; + block1_extrinsics.extend((0..20).map(|i| { + CheckedExtrinsic { + signed: Some((alice(), signed_extra(i, 0))), + function: Call::Balances(balances::Call::transfer(bob().into(), 1 * DOLLARS)), + } + })); + let block1 = test_ext.with_ext(|ext| construct_block( + executor, + &mut ext, + 1, + GENESIS_HASH.into(), + block1_extrinsics, + )); + + vec![block1] +} + +fn bench_execute_block(c: &mut Criterion) { + c.bench_function_over_inputs( + "execute blocks", + |b, strategy| { + let genesis_config = node_testing::genesis::config(false, Some(COMPACT_CODE)); + let (use_native, wasm_method) = match strategy { + ExecutionMethod::Native => (true, WasmExecutionMethod::Interpreted), + ExecutionMethod::Wasm(wasm_method) => (false, *wasm_method), + }; + let executor = NativeExecutor::new(wasm_method, None); + + // Get the runtime version to initialize the runtimes cache. + { + let mut test_ext = new_test_ext(&genesis_config); + test_ext.with_ext(|mut ext| executor.runtime_version(&mut ext)); + } + + let blocks = test_blocks(&genesis_config, &executor); + + b.iter_batched_ref( + || new_test_ext(&genesis_config), + |test_ext| { + for block in blocks.iter() { + test_ext.with_ext(|mut ext| + executor.call::<_, NeverNativeValue, fn() -> _>( + &mut ext, + "Core_execute_block", + &block.0, + use_native, + None, + ).0.unwrap() + ); + } + }, + BatchSize::LargeInput, + ); + }, + vec![ + ExecutionMethod::Native, + ExecutionMethod::Wasm(WasmExecutionMethod::Interpreted), + #[cfg(feature = "wasmtime")] + ExecutionMethod::Wasm(WasmExecutionMethod::Compiled), + ], + ); +} diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index c2e442fd580b140a785d001bc56f7809b12ef81e..3e7363293f22fabf3ac9a9418fbdc68e2d98ffed 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -17,12 +17,7 @@ //! A `CodeExecutor` specialization which uses natively compiled runtime when the wasm to be //! executed is equivalent to the natively compiled code. -#![cfg_attr(feature = "benchmarks", feature(test))] - -#[cfg(feature = "benchmarks")] extern crate test; - pub use substrate_executor::NativeExecutor; -pub use substrate_executor::RuntimesCache; use substrate_executor::native_executor_instance; // Declare an instance of the native executor named `Executor`. Include the wasm binary as the @@ -30,37 +25,38 @@ use substrate_executor::native_executor_instance; native_executor_instance!( pub Executor, node_runtime::api::dispatch, - node_runtime::native_version, - node_runtime::WASM_BINARY + node_runtime::native_version ); #[cfg(test)] mod tests { + use substrate_executor::error::Result; use super::Executor; - use {balances, contracts, indices, staking, system, timestamp}; - use runtime_io; - use substrate_executor::WasmExecutor; + use {balances, contracts, indices, system, timestamp}; use codec::{Encode, Decode, Joiner}; - use keyring::{AccountKeyring, Ed25519Keyring, Sr25519Keyring}; - use runtime_support::{Hashable, StorageValue, StorageMap, assert_eq_error_rate, traits::Currency}; - use state_machine::{CodeExecutor, Externalities, TestExternalities as CoreTestExternalities}; - use primitives::{ twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, NativeOrEncoded}; - use node_primitives::{Hash, BlockNumber, AccountId, Balance, Index}; - use sr_primitives::traits::{Header as HeaderT, Hash as HashT, Convert}; - use sr_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; - use sr_primitives::weights::{WeightMultiplier, GetDispatchInfo}; + use runtime_support::{Hashable, StorageValue, StorageMap, traits::Currency}; + use state_machine::TestExternalities as CoreTestExternalities; + use primitives::{ + Blake2Hasher, NeverNativeValue, NativeOrEncoded, map, + traits::{CodeExecutor, Externalities}, storage::well_known_keys, + }; + use sr_primitives::{ + Fixed64, + traits::{Header as HeaderT, Hash as HashT, Convert}, ApplyResult, + transaction_validity::InvalidTransaction, weights::GetDispatchInfo, + }; use contracts::ContractAddressFor; + use substrate_executor::{NativeExecutor, WasmExecutionMethod}; use system::{EventRecord, Phase}; use node_runtime::{ Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, - GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System, SystemConfig, - GrandpaConfig, IndicesConfig, ContractsConfig, Event, SessionKeys, SignedExtra, - TransferFee, TransactionBaseFee, TransactionByteFee, + System, TransactionPayment, Event, TransferFee, TransactionBaseFee, TransactionByteFee, + WeightFeeCoefficient, constants::currency::*, }; - use node_runtime::constants::currency::*; - use node_runtime::impls::WeightToFee; + use node_runtime::impls::LinearWeightToFee; + use node_primitives::{Balance, Hash, BlockNumber}; + use node_testing::keyring::*; use wabt; - use primitives::map; /// The wasm runtime code. /// @@ -79,78 +75,24 @@ mod tests { const GENESIS_HASH: [u8; 32] = [69u8; 32]; + const VERSION: u32 = node_runtime::VERSION.spec_version; + type TestExternalities = CoreTestExternalities; + fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { + node_testing::keyring::sign(xt, VERSION, GENESIS_HASH) + } + /// Default transfer fee - fn transfer_fee(extrinsic: &E) -> Balance { + fn transfer_fee(extrinsic: &E, fee_multiplier: Fixed64) -> Balance { let length_fee = TransactionBaseFee::get() + TransactionByteFee::get() * (extrinsic.encode().len() as Balance); let weight = default_transfer_call().get_dispatch_info().weight; - // NOTE: this is really hard to apply, since the multiplier of each block needs to be fetched - // before the block, while we compute this after the block. - // weight = >::next_weight_multiplier().apply_to(weight); - let weight_fee = ::WeightToFee::convert(weight); - length_fee + weight_fee + TransferFee::get() - } - - fn alice() -> AccountId { - AccountKeyring::Alice.into() - } - - fn bob() -> AccountId { - AccountKeyring::Bob.into() - } - - fn charlie() -> AccountId { - AccountKeyring::Charlie.into() - } + let weight_fee = ::WeightToFee::convert(weight); - fn dave() -> AccountId { - AccountKeyring::Dave.into() - } - - fn eve() -> AccountId { - AccountKeyring::Eve.into() - } - - fn ferdie() -> AccountId { - AccountKeyring::Ferdie.into() - } - - fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { - match xt.signed { - Some((signed, extra)) => { - let payload = (xt.function, extra.clone(), GENESIS_HASH, GENESIS_HASH); - let key = AccountKeyring::from_public(&signed).unwrap(); - let signature = payload.using_encoded(|b| { - if b.len() > 256 { - key.sign(&runtime_io::blake2_256(b)) - } else { - key.sign(b) - } - }).into(); - UncheckedExtrinsic { - signature: Some((indices::address::Address::Id(signed), signature, extra)), - function: payload.0, - } - } - None => UncheckedExtrinsic { - signature: None, - function: xt.function, - }, - } - } - - fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { - ( - system::CheckGenesis::new(), - system::CheckEra::from(Era::mortal(256, 0)), - system::CheckNonce::from(nonce), - system::CheckWeight::new(), - balances::TakeFees::from(extra_fee) - ) + fee_multiplier.saturated_multiply_accumulate(length_fee + weight_fee) + TransferFee::get() } fn default_transfer_call() -> balances::Call { @@ -168,28 +110,51 @@ mod tests { Header::new(n, Default::default(), Default::default(), [69; 32].into(), Default::default()) } - fn executor() -> ::substrate_executor::NativeExecutor { - substrate_executor::NativeExecutor::new(None) + fn executor() -> NativeExecutor { + NativeExecutor::new(WasmExecutionMethod::Interpreted, None) + } + + fn set_heap_pages(ext: &mut E, heap_pages: u64) { + ext.place_storage(well_known_keys::HEAP_PAGES.to_vec(), Some(heap_pages.encode())); + } + + fn executor_call< + R:Decode + Encode + PartialEq, + NC: FnOnce() -> std::result::Result + std::panic::UnwindSafe + >( + t: &mut TestExternalities, + method: &str, + data: &[u8], + use_native: bool, + native_call: Option, + ) -> (Result>, bool) { + t.with_ext(|mut ext| executor().call::<_, R, NC>( + &mut ext, + method, + data, + use_native, + native_call, + )) } #[test] fn panic_execution_with_foreign_code_gives_error() { let mut t = TestExternalities::::new_with_code(BLOATY_CODE, (map![ - blake2_256(&>::key_for(alice())).to_vec() => { + >::hashed_key_for(alice()) => { 69_u128.encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { 69_u128.encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { 0_u128.encode() }, - blake2_256(&>::key_for(0)).to_vec() => { + >::hashed_key_for(0) => { vec![0u8; 32] } ], map![])); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), @@ -197,7 +162,7 @@ mod tests { None, ).0; assert!(r.is_ok()); - let v = executor().call::<_, NeverNativeValue, fn() -> _>( + let v = executor_call:: _>( &mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), @@ -205,27 +170,27 @@ mod tests { None, ).0.unwrap(); let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); - assert_eq!(r, Err(ApplyError::CantPay)); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); } #[test] fn bad_extrinsic_with_native_equivalent_code_gives_error() { let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - blake2_256(&>::key_for(alice())).to_vec() => { + >::hashed_key_for(alice()) => { 69_u128.encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { 69_u128.encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { 0_u128.encode() }, - blake2_256(&>::key_for(0)).to_vec() => { + >::hashed_key_for(0) => { vec![0u8; 32] } ], map![])); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), @@ -233,7 +198,7 @@ mod tests { None, ).0; assert!(r.is_ok()); - let v = executor().call::<_, NeverNativeValue, fn() -> _>( + let v = executor_call:: _>( &mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), @@ -241,23 +206,23 @@ mod tests { None, ).0.unwrap(); let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); - assert_eq!(r, Err(ApplyError::CantPay)); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); } #[test] fn successful_execution_with_native_equivalent_code_gives_ok() { let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - blake2_256(&>::key_for(alice())).to_vec() => { + >::hashed_key_for(alice()) => { (111 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { (111 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32] + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] ], map![])); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), @@ -265,7 +230,10 @@ mod tests { None, ).0; assert!(r.is_ok()); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + + let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + let r = executor_call:: _>( &mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), @@ -274,8 +242,8 @@ mod tests { ).0; assert!(r.is_ok()); - runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); } @@ -283,17 +251,17 @@ mod tests { #[test] fn successful_execution_with_foreign_code_gives_ok() { let mut t = TestExternalities::::new_with_code(BLOATY_CODE, (map![ - blake2_256(&>::key_for(alice())).to_vec() => { + >::hashed_key_for(alice()) => { (111 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { (111 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32] + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] ], map![])); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), @@ -301,7 +269,10 @@ mod tests { None, ).0; assert!(r.is_ok()); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + + let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + let r = executor_call:: _>( &mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), @@ -310,92 +281,17 @@ mod tests { ).0; assert!(r.is_ok()); - runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); } - fn to_session_keys( - ed25519_keyring: &Ed25519Keyring, - sr25519_keyring: &Sr25519Keyring, - ) -> SessionKeys { - SessionKeys { - grandpa: ed25519_keyring.to_owned().public().into(), - babe: sr25519_keyring.to_owned().public().into(), - im_online: sr25519_keyring.to_owned().public().into(), - } - } - fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { - let mut ext = TestExternalities::new_with_code(code, GenesisConfig { - system: Some(SystemConfig { - changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { - digest_interval: 2, - digest_levels: 2, - }) } else { None }, - .. Default::default() - }), - indices: Some(IndicesConfig { - ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], - }), - balances: Some(BalancesConfig { - balances: vec![ - (alice(), 111 * DOLLARS), - (bob(), 100 * DOLLARS), - (charlie(), 100_000_000 * DOLLARS), - (dave(), 111 * DOLLARS), - (eve(), 101 * DOLLARS), - (ferdie(), 100 * DOLLARS), - ], - vesting: vec![], - }), - session: Some(SessionConfig { - keys: vec![ - (alice(), to_session_keys( - &Ed25519Keyring::Alice, - &Sr25519Keyring::Alice, - )), - (bob(), to_session_keys( - &Ed25519Keyring::Bob, - &Sr25519Keyring::Bob, - )), - (charlie(), to_session_keys( - &Ed25519Keyring::Charlie, - &Sr25519Keyring::Charlie, - )), - ] - }), - staking: Some(StakingConfig { - current_era: 0, - stakers: vec![ - (dave(), alice(), 111 * DOLLARS, staking::StakerStatus::Validator), - (eve(), bob(), 100 * DOLLARS, staking::StakerStatus::Validator), - (ferdie(), charlie(), 100 * DOLLARS, staking::StakerStatus::Validator) - ], - validator_count: 3, - minimum_validator_count: 0, - offline_slash: Perbill::zero(), - offline_slash_grace: 0, - invulnerables: vec![alice(), bob(), charlie()], - .. Default::default() - }), - contracts: Some(ContractsConfig { - current_schedule: Default::default(), - gas_price: 1 * MILLICENTS, - }), - babe: Some(Default::default()), - grandpa: Some(GrandpaConfig { - authorities: vec![], - }), - im_online: Some(Default::default()), - democracy: Some(Default::default()), - collective_Instance1: Some(Default::default()), - collective_Instance2: Some(Default::default()), - membership_Instance1: Some(Default::default()), - elections: Some(Default::default()), - sudo: Some(Default::default()), - }.build_storage().unwrap()); + let mut ext = TestExternalities::new_with_code( + code, + node_testing::genesis::config(support_changes_trie, Some(code)).build_storage().unwrap(), + ); ext.changes_trie_storage().insert(0, GENESIS_HASH.into(), Default::default()); ext } @@ -426,7 +322,7 @@ mod tests { }; // execute the block to get the real header. - executor().call::<_, NeverNativeValue, fn() -> _>( + executor_call:: _>( env, "Core_initialize_block", &header.encode(), @@ -435,7 +331,7 @@ mod tests { ).0.unwrap(); for i in extrinsics.iter() { - executor().call::<_, NeverNativeValue, fn() -> _>( + executor_call:: _>( env, "BlockBuilder_apply_extrinsic", &i.encode(), @@ -444,7 +340,7 @@ mod tests { ).0.unwrap(); } - let header = match executor().call::<_, NeverNativeValue, fn() -> _>( + let header = match executor_call:: _>( env, "BlockBuilder_finalize_block", &[0u8;0], @@ -548,7 +444,10 @@ mod tests { let (block1, block2) = blocks(); - executor().call::<_, NeverNativeValue, fn() -> _>( + let mut alice_last_known_balance: Balance = Default::default(); + let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + executor_call:: _>( &mut t, "Core_execute_block", &block1.0, @@ -556,22 +455,28 @@ mod tests { None, ).0.unwrap(); - runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); + alice_last_known_balance = Balances::total_balance(&alice()); let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), event: Event::system(system::Event::ExtrinsicSuccess), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::treasury(treasury::RawEvent::Deposit(1984800000000)), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::balances(balances::RawEvent::Transfer( alice().into(), bob().into(), 69 * DOLLARS, - 1 * CENTS + 1 * CENTS, )), topics: vec![], }, @@ -583,7 +488,10 @@ mod tests { ]; assert_eq!(System::events(), events); }); - executor().call::<_, NeverNativeValue, fn() -> _>( + + fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + executor_call:: _>( &mut t, "Core_execute_block", &block2.0, @@ -591,18 +499,14 @@ mod tests { None, ).0.unwrap(); - runtime_io::with_externalities(&mut t, || { - // NOTE: fees differ slightly in tests that execute more than one block due to the - // weight update. Hence, using `assert_eq_error_rate`. - assert_eq_error_rate!( + t.execute_with(|| { + assert_eq!( Balances::total_balance(&alice()), - 32 * DOLLARS - 2 * transfer_fee(&xt()), - 10_000 + alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm), ); - assert_eq_error_rate!( + assert_eq!( Balances::total_balance(&bob()), - 179 * DOLLARS - transfer_fee(&xt()), - 10_000 + 179 * DOLLARS - transfer_fee(&xt(), fm), ); let events = vec![ EventRecord { @@ -610,6 +514,11 @@ mod tests { event: Event::system(system::Event::ExtrinsicSuccess), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(1), + event: Event::treasury(treasury::RawEvent::Deposit(1984780231392)), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: Event::balances( @@ -627,6 +536,11 @@ mod tests { event: Event::system(system::Event::ExtrinsicSuccess), topics: vec![], }, + EventRecord { + phase: Phase::ApplyExtrinsic(2), + event: Event::treasury(treasury::RawEvent::Deposit(1984780231392)), + topics: vec![], + }, EventRecord { phase: Phase::ApplyExtrinsic(2), event: Event::balances( @@ -655,25 +569,41 @@ mod tests { let (block1, block2) = blocks(); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); + let mut alice_last_known_balance: Balance = Default::default(); + let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier); - runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); + executor_call:: _>( + &mut t, + "Core_execute_block", + &block1.0, + false, + None, + ).0.unwrap(); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm)); assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); + alice_last_known_balance = Balances::total_balance(&alice()); }); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block2.0).unwrap(); + fm = t.execute_with(TransactionPayment::next_fee_multiplier); + + executor_call:: _>( + &mut t, + "Core_execute_block", + &block2.0, + false, + None, + ).0.unwrap(); - runtime_io::with_externalities(&mut t, || { - assert_eq_error_rate!( + t.execute_with(|| { + assert_eq!( Balances::total_balance(&alice()), - 32 * DOLLARS - 2 * transfer_fee(&xt()), - 10_000 + alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm), ); - assert_eq_error_rate!( + assert_eq!( Balances::total_balance(&bob()), - 179 * DOLLARS - 1 * transfer_fee(&xt()), - 10_000 + 179 * DOLLARS - 1 * transfer_fee(&xt(), fm), ); }); } @@ -799,7 +729,7 @@ mod tests { CheckedExtrinsic { signed: Some((charlie(), signed_extra(1, 0))), function: Call::Contracts( - contracts::Call::create::(1 * DOLLARS, 10_000, transfer_ch, Vec::new()) + contracts::Call::instantiate::(1 * DOLLARS, 10_000, transfer_ch, Vec::new()) ), }, CheckedExtrinsic { @@ -818,9 +748,15 @@ mod tests { let mut t = new_test_ext(COMPACT_CODE, false); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE,"Core_execute_block", &b.0).unwrap(); + executor_call:: _>( + &mut t, + "Core_execute_block", + &b.0, + false, + None, + ).0.unwrap(); - runtime_io::with_externalities(&mut t, || { + t.execute_with(|| { // Verify that the contract constructor worked well and code of TRANSFER contract is actually deployed. assert_eq!( &contracts::ContractInfoOf::::get(addr) @@ -835,14 +771,15 @@ mod tests { #[test] fn wasm_big_block_import_fails() { let mut t = new_test_ext(COMPACT_CODE, false); + t.with_ext(|mut ext| set_heap_pages(&mut ext, 4)); - let result = WasmExecutor::new().call( + let result = executor_call:: _>( &mut t, - 4, - COMPACT_CODE, "Core_execute_block", - &block_with_size(42, 0, 120_000).0 - ); + &block_with_size(42, 0, 120_000).0, + false, + None, + ).0; assert!(result.is_err()); // Err(Wasmi(Trap(Trap { kind: Host(AllocatorOutOfSpace) }))) } @@ -850,7 +787,7 @@ mod tests { fn native_big_block_import_succeeds() { let mut t = new_test_ext(COMPACT_CODE, false); - executor().call::<_, NeverNativeValue, fn() -> _>( + executor_call:: _>( &mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0, @@ -864,7 +801,7 @@ mod tests { let mut t = new_test_ext(COMPACT_CODE, false); assert!( - executor().call::<_, NeverNativeValue, fn() -> _>( + executor_call:: _>( &mut t, "Core_execute_block", &block_with_size(42, 0, 120_000).0, @@ -877,48 +814,71 @@ mod tests { #[test] fn panic_execution_gives_error() { let mut t = TestExternalities::::new_with_code(BLOATY_CODE, (map![ - blake2_256(&>::key_for(alice())).to_vec() => { + >::hashed_key_for(alice()) => { 0_u128.encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { 0_u128.encode() }, - twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32] + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] ], map![])); - let r = WasmExecutor::new() - .call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u32))); + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + false, + None, + ).0; assert!(r.is_ok()); - let r = WasmExecutor::new() - .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); + let r = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + false, + None, + ).0.unwrap().into_encoded(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, Err(ApplyError::CantPay)); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); } #[test] fn successful_execution_gives_ok() { let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - blake2_256(&>::key_for(alice())).to_vec() => { + >::hashed_key_for(alice()) => { (111 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { (111 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32] + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] ], map![])); - let r = WasmExecutor::new() - .call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u32))); + let r = executor_call:: _>( + &mut t, + "Core_initialize_block", + &vec![].and(&from_block_number(1u32)), + false, + None, + ).0; assert!(r.is_ok()); - let r = WasmExecutor::new() - .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); - let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, Ok(ApplyOutcome::Success)); - - runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt())); + let fm = t.execute_with(TransactionPayment::next_fee_multiplier); + let r = executor_call:: _>( + &mut t, + "BlockBuilder_apply_extrinsic", + &vec![].and(&xt()), + false, + None, + ).0.unwrap().into_encoded(); + ApplyResult::decode(&mut &r[..]) + .unwrap() + .expect("Extrinsic could be applied") + .expect("Extrinsic did not fail"); + + t.execute_with(|| { + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt(), fm)); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); } @@ -930,7 +890,7 @@ mod tests { let block = Block::decode(&mut &block_data[..]).unwrap(); let mut t = new_test_ext(COMPACT_CODE, true); - executor().call::<_, NeverNativeValue, fn() -> _>( + executor_call:: _>( &mut t, "Core_execute_block", &block.encode(), @@ -938,7 +898,7 @@ mod tests { None, ).0.unwrap(); - assert!(t.storage_changes_root(GENESIS_HASH.into()).unwrap().is_some()); + assert!(t.with_ext(|mut ext| ext.storage_changes_root(GENESIS_HASH.into()).unwrap()).is_some()); } #[test] @@ -946,35 +906,39 @@ mod tests { let block1 = changes_trie_block(); let mut t = new_test_ext(COMPACT_CODE, true); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); + executor_call:: _>( + &mut t, + "Core_execute_block", + &block1.0, + false, + None, + ).0.unwrap(); - assert!(t.storage_changes_root(GENESIS_HASH.into()).unwrap().is_some()); + assert!(t.with_ext(|mut ext| ext.storage_changes_root(GENESIS_HASH.into()).unwrap()).is_some()); } #[test] fn should_import_block_with_test_client() { - use test_client::{ClientExt, TestClientBuilder, consensus::BlockOrigin}; - - let client = TestClientBuilder::default() - .build_with_native_executor::(executor()) - .0; + use node_testing::client::{ClientExt, TestClientBuilderExt, TestClientBuilder, consensus::BlockOrigin}; + let client = TestClientBuilder::new().build(); let block1 = changes_trie_block(); let block_data = block1.0; - let block = Block::decode(&mut &block_data[..]).unwrap(); + let block = node_primitives::Block::decode(&mut &block_data[..]).unwrap(); client.import(BlockOrigin::Own, block).unwrap(); } #[test] - fn weight_multiplier_increases_and_decreases_on_big_weight() { + fn fee_multiplier_increases_and_decreases_on_big_weight() { let mut t = new_test_ext(COMPACT_CODE, false); - let mut prev_multiplier = WeightMultiplier::default(); + // initial fee multiplier must be zero + let mut prev_multiplier = Fixed64::from_parts(0); - runtime_io::with_externalities(&mut t, || { - assert_eq!(System::next_weight_multiplier(), prev_multiplier); + t.execute_with(|| { + assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier); }); let mut tt = new_test_ext(COMPACT_CODE, false); @@ -1016,7 +980,7 @@ mod tests { println!("++ Block 1 size: {} / Block 2 size {}", block1.0.encode().len(), block2.0.encode().len()); // execute a big block. - executor().call::<_, NeverNativeValue, fn() -> _>( + executor_call:: _>( &mut t, "Core_execute_block", &block1.0, @@ -1025,15 +989,15 @@ mod tests { ).0.unwrap(); // weight multiplier is increased for next block. - runtime_io::with_externalities(&mut t, || { - let fm = System::next_weight_multiplier(); + t.execute_with(|| { + let fm = TransactionPayment::next_fee_multiplier(); println!("After a big block: {:?} -> {:?}", prev_multiplier, fm); assert!(fm > prev_multiplier); prev_multiplier = fm; }); // execute a big block. - executor().call::<_, NeverNativeValue, fn() -> _>( + executor_call:: _>( &mut t, "Core_execute_block", &block2.0, @@ -1042,8 +1006,8 @@ mod tests { ).0.unwrap(); // weight multiplier is increased for next block. - runtime_io::with_externalities(&mut t, || { - let fm = System::next_weight_multiplier(); + t.execute_with(|| { + let fm = TransactionPayment::next_fee_multiplier(); println!("After a small block: {:?} -> {:?}", prev_multiplier, fm); assert!(fm < prev_multiplier); }); @@ -1056,20 +1020,20 @@ mod tests { // weight of transfer call as of now: 1_000_000 // if weight of the cheapest weight would be 10^7, this would be 10^9, which is: // - 1 MILLICENTS in substrate node. - // - 1 milldot based on current polkadot runtime. + // - 1 milli-dot based on current polkadot runtime. // (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`) let mut t = TestExternalities::::new_with_code(COMPACT_CODE, (map![ - blake2_256(&>::key_for(alice())).to_vec() => { + >::hashed_key_for(alice()) => { (100 * DOLLARS).encode() }, - blake2_256(&>::key_for(bob())).to_vec() => { + >::hashed_key_for(bob()) => { (10 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => { + >::hashed_key().to_vec() => { (110 * DOLLARS).encode() }, - twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32] + >::hashed_key().to_vec() => vec![0u8; 16], + >::hashed_key_for(0) => vec![0u8; 32] ], map![])); let tip = 1_000_000; @@ -1078,7 +1042,7 @@ mod tests { function: Call::Balances(default_transfer_call()), }); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), @@ -1087,7 +1051,7 @@ mod tests { ).0; assert!(r.is_ok()); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt.clone()), @@ -1096,7 +1060,7 @@ mod tests { ).0; assert!(r.is_ok()); - runtime_io::with_externalities(&mut t, || { + t.execute_with(|| { assert_eq!(Balances::total_balance(&bob()), (10 + 69) * DOLLARS); // Components deducted from alice's balances: // - Weight fee @@ -1111,7 +1075,7 @@ mod tests { balance_alice -= length_fee; let weight = default_transfer_call().get_dispatch_info().weight; - let weight_fee = WeightToFee::convert(weight); + let weight_fee = LinearWeightToFee::::convert(weight); // we know that weight to fee multiplier is effect-less in block 1. assert_eq!(weight_fee as Balance, MILLICENTS); @@ -1130,6 +1094,7 @@ mod tests { fn block_weight_capacity_report() { // Just report how many transfer calls you could fit into a block. The number should at least // be a few hundred (250 at the time of writing but can change over time). Runs until panic. + use node_primitives::Index; // execution ext. let mut t = new_test_ext(COMPACT_CODE, false); @@ -1171,7 +1136,7 @@ mod tests { len / 1024 / 1024, ); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "Core_execute_block", &block.0, @@ -1196,6 +1161,7 @@ mod tests { // Just report how big a block can get. Executes until panic. Should be ignored unless if // manually inspected. The number should at least be a few megabytes (5 at the time of // writing but can change over time). + use node_primitives::Index; // execution ext. let mut t = new_test_ext(COMPACT_CODE, false); @@ -1234,7 +1200,7 @@ mod tests { len / 1024 / 1024, ); - let r = executor().call::<_, NeverNativeValue, fn() -> _>( + let r = executor_call:: _>( &mut t, "Core_execute_block", &block.0, @@ -1251,21 +1217,4 @@ mod tests { block_number += 1; } } - - #[cfg(feature = "benchmarks")] - mod benches { - use super::*; - use test::Bencher; - - #[bench] - fn wasm_execute_block(b: &mut Bencher) { - let (block1, block2) = blocks(); - - b.iter(|| { - let mut t = new_test_ext(COMPACT_CODE, false); - WasmExecutor::new().call(&mut t, "Core_execute_block", &block1.0).unwrap(); - WasmExecutor::new().call(&mut t, "Core_execute_block", &block2.0).unwrap(); - }); - } - } } diff --git a/node/primitives/Cargo.toml b/node/primitives/Cargo.toml index 654347273fb71d109bf005dcc2bb33d3bb0cedd1..25725449a3a5a17f736a65a1c62953cc6847fc71 100644 --- a/node/primitives/Cargo.toml +++ b/node/primitives/Cargo.toml @@ -5,10 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } [dev-dependencies] @@ -18,9 +15,6 @@ pretty_assertions = "0.6.1" [features] default = ["std"] std = [ - "codec/std", "primitives/std", - "rstd/std", "sr-primitives/std", - "serde", ] diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index 431ba17c00bbeca51948fa2cd47a8dc2efe97ac3..b6a5ec05655c5ff90cf4e9180ecb90b52dcd020b 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -21,21 +21,20 @@ #![cfg_attr(not(feature = "std"), no_std)] use sr_primitives::{ - generic, traits::{Verify, BlakeTwo256}, OpaqueExtrinsic, AnySignature + generic, traits::{Verify, BlakeTwo256, IdentifyAccount}, OpaqueExtrinsic, MultiSignature }; /// An index to a block. pub type BlockNumber = u32; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = AnySignature; +pub type Signature = MultiSignature; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. -pub type AccountId = ::Signer; +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; -/// The type for looking up accounts. We don't expect more than 4 billion of them, but you -/// never know... +/// The type for looking up accounts. We don't expect more than 4 billion of them. pub type AccountIndex = u32; /// Balance of an account. @@ -60,9 +59,6 @@ pub type DigestItem = generic::DigestItem; /// Header type. pub type Header = generic::Header; /// Block type. -pub type Block = generic::Block; +pub type Block = generic::Block; /// Block ID. pub type BlockId = generic::BlockId; - -/// Opaque, encoded, unchecked extrinsic. -pub type UncheckedExtrinsic = OpaqueExtrinsic; diff --git a/node/rpc-client/Cargo.toml b/node/rpc-client/Cargo.toml index ea255808e463e47d2f6c0d3bdf15044b0b827815..bc30f598bbc22a31d20b9c79cee4d3b2681ab304 100644 --- a/node/rpc-client/Cargo.toml +++ b/node/rpc-client/Cargo.toml @@ -5,10 +5,10 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -env_logger = "0.6" -futures = "0.1.26" -hyper = "0.12" -jsonrpc-core-client = { version = "12.0.0", features = ["http", "ws"] } -log = "0.4" +env_logger = "0.7.0" +futures = "0.1.29" +hyper = "0.12.35" +jsonrpc-core-client = { version = "14.0.3", features = ["http", "ws"] } +log = "0.4.8" node-primitives = { path = "../primitives" } substrate-rpc = { path = "../../core/rpc", version = "2.0.0" } diff --git a/node/rpc/Cargo.toml b/node/rpc/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..5d2b3ac85832d11b42fd7a9c183708f0ac85ce3e --- /dev/null +++ b/node/rpc/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "node-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../core/client" } +jsonrpc-core = "14.0.3" +node-primitives = { path = "../primitives" } +node-runtime = { path = "../runtime" } +sr-primitives = { path = "../../core/sr-primitives" } +srml-contracts-rpc = { path = "../../srml/contracts/rpc/" } +srml-transaction-payment-rpc = { path = "../../srml/transaction-payment/rpc/" } +srml-system-rpc = { path = "../../srml/system/rpc/" } +transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..99321373f8f8c5b81f91514281cf8435cdecc62f --- /dev/null +++ b/node/rpc/src/lib.rs @@ -0,0 +1,65 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A collection of node-specific RPC methods. +//! +//! Since `substrate` core functionality makes no assumptions +//! about the modules used inside the runtime, so do +//! RPC methods defined in `substrate-rpc` crate. +//! It means that `core/rpc` can't have any methods that +//! need some strong assumptions about the particular runtime. +//! +//! The RPCs available in this crate however can make some assumptions +//! about how the runtime is constructed and what `SRML` modules +//! are part of it. Therefore all node-runtime-specific RPCs can +//! be placed here or imported from corresponding `SRML` RPC definitions. + +#![warn(missing_docs)] + +use std::sync::Arc; + +use node_primitives::{Block, AccountId, Index, Balance}; +use node_runtime::UncheckedExtrinsic; +use sr_primitives::traits::ProvideRuntimeApi; +use transaction_pool::txpool::{ChainApi, Pool}; + +/// Instantiate all RPC extensions. +pub fn create(client: Arc, pool: Arc>) -> jsonrpc_core::IoHandler where + C: ProvideRuntimeApi, + C: client::blockchain::HeaderBackend, + C: Send + Sync + 'static, + C::Api: srml_system_rpc::AccountNonceApi, + C::Api: srml_contracts_rpc::ContractsRuntimeApi, + C::Api: srml_transaction_payment_rpc::TransactionPaymentRuntimeApi, + P: ChainApi + Sync + Send + 'static, + M: jsonrpc_core::Metadata + Default, +{ + use srml_system_rpc::{System, SystemApi}; + use srml_contracts_rpc::{Contracts, ContractsApi}; + use srml_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; + + let mut io = jsonrpc_core::IoHandler::default(); + io.extend_with( + SystemApi::to_delegate(System::new(client.clone(), pool)) + ); + io.extend_with( + ContractsApi::to_delegate(Contracts::new(client.clone())) + ); + io.extend_with( + TransactionPaymentApi::to_delegate(TransactionPayment::new(client)) + ); + io +} diff --git a/node/runtime/Cargo.toml b/node/runtime/Cargo.toml index 7ffb29e0784ce59db45f9877fd2b6a2e48bb7890..0aa2dc551ef3ad6ea79ebdae8950ea251820dc98 100644 --- a/node/runtime/Cargo.toml +++ b/node/runtime/Cargo.toml @@ -6,85 +6,104 @@ edition = "2018" build = "build.rs" [dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } integer-sqrt = { version = "0.1.2" } +rustc-hex = { version = "2.0", optional = true } safe-mix = { version = "1.0", default-features = false } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } +serde = { version = "1.0.101", optional = true } + +babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } client = { package = "substrate-client", path = "../../core/client", default-features = false } +node-primitives = { path = "../primitives", default-features = false } +offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } +substrate-keyring = { path = "../../core/keyring", optional = true } +substrate-session = { path = "../../core/session", default-features = false } version = { package = "sr-version", path = "../../core/sr-version", default-features = false } -support = { package = "srml-support", path = "../../srml/support", default-features = false } + authorship = { package = "srml-authorship", path = "../../srml/authorship", default-features = false } babe = { package = "srml-babe", path = "../../srml/babe", default-features = false } -babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } -consensus-primitives = { package = "substrate-consensus-common-primitives", path = "../../core/consensus/common/primitives", default-features = false } balances = { package = "srml-balances", path = "../../srml/balances", default-features = false } -contracts = { package = "srml-contracts", path = "../../srml/contracts", default-features = false } collective = { package = "srml-collective", path = "../../srml/collective", default-features = false } +contracts = { package = "srml-contracts", path = "../../srml/contracts", default-features = false } +contracts-rpc-runtime-api = { package = "srml-contracts-rpc-runtime-api", path = "../../srml/contracts/rpc/runtime-api/", default-features = false } democracy = { package = "srml-democracy", path = "../../srml/democracy", default-features = false } -elections = { package = "srml-elections", path = "../../srml/elections", default-features = false } +elections-phragmen = { package = "srml-elections-phragmen", path = "../../srml/elections-phragmen", default-features = false } executive = { package = "srml-executive", path = "../../srml/executive", default-features = false } finality-tracker = { package = "srml-finality-tracker", path = "../../srml/finality-tracker", default-features = false } grandpa = { package = "srml-grandpa", path = "../../srml/grandpa", default-features = false } +im-online = { package = "srml-im-online", path = "../../srml/im-online", default-features = false } indices = { package = "srml-indices", path = "../../srml/indices", default-features = false } membership = { package = "srml-membership", path = "../../srml/membership", default-features = false } +nicks = { package = "srml-nicks", path = "../../srml/nicks", default-features = false } +offences = { package = "srml-offences", path = "../../srml/offences", default-features = false } +randomness-collective-flip = { package = "srml-randomness-collective-flip", path = "../../srml/randomness-collective-flip", default-features = false } session = { package = "srml-session", path = "../../srml/session", default-features = false, features = ["historical"] } staking = { package = "srml-staking", path = "../../srml/staking", default-features = false } +srml-staking-reward-curve = { path = "../../srml/staking/reward-curve"} +sudo = { package = "srml-sudo", path = "../../srml/sudo", default-features = false } +support = { package = "srml-support", path = "../../srml/support", default-features = false } system = { package = "srml-system", path = "../../srml/system", default-features = false } +system-rpc-runtime-api = { package = "srml-system-rpc-runtime-api", path = "../../srml/system/rpc/runtime-api/", default-features = false } timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default-features = false } treasury = { package = "srml-treasury", path = "../../srml/treasury", default-features = false } -sudo = { package = "srml-sudo", path = "../../srml/sudo", default-features = false } -im-online = { package = "srml-im-online", path = "../../srml/im-online", default-features = false } -node-primitives = { path = "../primitives", default-features = false } -rustc-hex = { version = "2.0", optional = true } -serde = { version = "1.0", optional = true } -substrate-keyring = { path = "../../core/keyring", optional = true } -substrate-session = { path = "../../core/session", default-features = false } +utility = { package = "srml-utility", path = "../../srml/utility", default-features = false } +transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment", default-features = false } +transaction-payment-rpc-runtime-api = { package = "srml-transaction-payment-rpc-runtime-api", path = "../../srml/transaction-payment/rpc/runtime-api/", default-features = false } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.2", path = "../../core/utils/wasm-builder-runner" } +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.4", path = "../../core/utils/wasm-builder-runner" } + +[dev-dependencies] +runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] -no_std = [ - "contracts/core", -] std = [ - "codec/std", - "primitives/std", - "rstd/std", - "sr-primitives/std", - "support/std", "authorship/std", - "babe/std", "babe-primitives/std", - "consensus-primitives/std", + "babe/std", "balances/std", - "contracts/std", + "client/std", + "codec/std", "collective/std", + "contracts/std", + "contracts-rpc-runtime-api/std", "democracy/std", - "elections/std", + "elections-phragmen/std", "executive/std", "finality-tracker/std", "grandpa/std", + "im-online/std", "indices/std", "membership/std", + "nicks/std", + "node-primitives/std", + "offchain-primitives/std", + "offences/std", + "primitives/std", + "randomness-collective-flip/std", + "rstd/std", + "rustc-hex", + "safe-mix/std", + "serde", "session/std", + "sr-primitives/std", + "sr-staking-primitives/std", "staking/std", + "substrate-keyring", + "substrate-session/std", + "sudo/std", + "support/std", "system/std", + "system-rpc-runtime-api/std", "timestamp/std", "treasury/std", - "sudo/std", + "utility/std", + "transaction-payment/std", + "transaction-payment-rpc-runtime-api/std", "version/std", - "node-primitives/std", - "serde", - "safe-mix/std", - "client/std", - "rustc-hex", - "substrate-keyring", - "offchain-primitives/std", - "im-online/std", - "substrate-session/std", ] diff --git a/node/runtime/build.rs b/node/runtime/build.rs index a5f22fd0171467ee714f04a3feb583137d5a890c..f5c2f98a75c8abbe2d7fa8cb16058bd0d5cea851 100644 --- a/node/runtime/build.rs +++ b/node/runtime/build.rs @@ -21,7 +21,7 @@ fn main() { "wasm_binary.rs", WasmBuilderSource::CratesOrPath { path: "../../core/utils/wasm-builder", - version: "1.0.4", + version: "1.0.8", }, // This instructs LLD to export __heap_base as a global variable, which is used by the // external memory allocator. diff --git a/node/runtime/src/constants.rs b/node/runtime/src/constants.rs index f728efb3be89ff096341e257a5422937cfed48a0..fba4c7ac79e563dc06a1fa572df726fe07fed91c 100644 --- a/node/runtime/src/constants.rs +++ b/node/runtime/src/constants.rs @@ -40,11 +40,19 @@ pub mod time { /// that are expressed in blocks. The rest of the code should use /// `SLOT_DURATION` instead (like the timestamp module for calculating the /// minimum period). + /// + /// If using BABE with secondary slots (default) then all of the slots will + /// always be assigned, in which case `MILLISECS_PER_BLOCK` and + /// `SLOT_DURATION` should have the same value. + /// /// - pub const MILLISECS_PER_BLOCK: Moment = 6000; + pub const MILLISECS_PER_BLOCK: Moment = 3000; pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000; - pub const SLOT_DURATION: Moment = 1650; + pub const SLOT_DURATION: Moment = MILLISECS_PER_BLOCK; + + // 1 in 4 blocks (on average, not counting collisions) will be primary BABE blocks. + pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 10 * MINUTES; pub const EPOCH_DURATION_IN_SLOTS: u64 = { @@ -58,19 +66,3 @@ pub mod time { pub const HOURS: BlockNumber = MINUTES * 60; pub const DAYS: BlockNumber = HOURS * 24; } - -// CRITICAL NOTE: The system module maintains two constants: a _maximum_ block weight and a -// _ratio_ of it yielding the portion which is accessible to normal transactions (reserving the rest -// for operational ones). `TARGET_BLOCK_FULLNESS` is entirely independent and the system module is -// not aware of if, nor should it care about it. This constant simply denotes on which ratio of the -// _maximum_ block weight we tweak the fees. It does NOT care about the type of the dispatch. -// -// For the system to be configured in a sane way, `TARGET_BLOCK_FULLNESS` should always be less than -// the ratio that `system` module uses to find normal transaction quota. -/// Fee-related. -pub mod fee { - pub use sr_primitives::Perbill; - - /// The block saturation level. Fees will be updates based on this value. - pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); -} diff --git a/node/runtime/src/impls.rs b/node/runtime/src/impls.rs index 2e1fcc8826e035a174d36b1bbac79cae96015c57..69b782e807dfcfd00eed563db27bd67353769c41 100644 --- a/node/runtime/src/impls.rs +++ b/node/runtime/src/impls.rs @@ -17,12 +17,11 @@ //! Some configurable implementations as associated type for the substrate runtime. use node_primitives::Balance; -use sr_primitives::weights::{Weight, WeightMultiplier}; +use sr_primitives::weights::Weight; use sr_primitives::traits::{Convert, Saturating}; -use sr_primitives::Fixed64; -use support::traits::{OnUnbalanced, Currency}; -use crate::{Balances, Authorship, MaximumBlockWeight, NegativeImbalance}; -use crate::constants::fee::TARGET_BLOCK_FULLNESS; +use sr_primitives::{Fixed64, Perbill}; +use support::traits::{OnUnbalanced, Currency, Get}; +use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance}; pub struct Author; impl OnUnbalanced for Author { @@ -47,48 +46,34 @@ impl Convert for CurrencyToVoteHandler { fn convert(x: u128) -> Balance { x * Self::factor() } } -/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the -/// node's balance type. -/// -/// This should typically create a mapping between the following ranges: -/// - [0, system::MaximumBlockWeight] -/// - [Balance::min, Balance::max] -/// -/// Yet, it can be used for any other sort of change to weight-fee. Some examples being: -/// - Setting it to `0` will essentially disable the weight fee. -/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. -/// -/// By default, substrate node will have a weight range of [0, 1_000_000_000]. -pub struct WeightToFee; -impl Convert for WeightToFee { - fn convert(x: Weight) -> Balance { +/// Convert from weight to balance via a simple coefficient multiplication +/// The associated type C encapsulates a constant in units of balance per weight +pub struct LinearWeightToFee(rstd::marker::PhantomData); + +impl> Convert for LinearWeightToFee { + fn convert(w: Weight) -> Balance { // substrate-node a weight of 10_000 (smallest non-zero weight) to be mapped to 10^7 units of // fees, hence: - Balance::from(x).saturating_mul(1_000) + let coefficient = C::get(); + Balance::from(w).saturating_mul(coefficient) } } -/// A struct that updates the weight multiplier based on the saturation level of the previous block. -/// This should typically be called once per-block. -/// -/// This assumes that weight is a numeric value in the u32 range. +/// Update the given multiplier based on the following formula /// -/// Given `TARGET_BLOCK_FULLNESS = 1/2`, a block saturation greater than 1/2 will cause the system -/// fees to slightly grow and the opposite for block saturations less than 1/2. -/// -/// Formula: -/// diff = (target_weight - current_block_weight) +/// diff = (previous_block_weight - target_weight) /// v = 0.00004 /// next_weight = weight * (1 + (v . diff) + (v . diff)^2 / 2) /// +/// Where `target_weight` must be given as the `Get` implementation of the `T` generic type. /// https://research.web3.foundation/en/latest/polkadot/Token%20Economics/#relay-chain-transaction-fees -pub struct WeightMultiplierUpdateHandler; +pub struct TargetedFeeAdjustment(rstd::marker::PhantomData); -impl Convert<(Weight, WeightMultiplier), WeightMultiplier> for WeightMultiplierUpdateHandler { - fn convert(previous_state: (Weight, WeightMultiplier)) -> WeightMultiplier { - let (block_weight, multiplier) = previous_state; +impl> Convert for TargetedFeeAdjustment { + fn convert(multiplier: Fixed64) -> Fixed64 { + let block_weight = System::all_extrinsics_weight(); let max_weight = MaximumBlockWeight::get(); - let target_weight = (TARGET_BLOCK_FULLNESS * max_weight) as u128; + let target_weight = (T::get() * max_weight) as u128; let block_weight = block_weight as u128; // determines if the first_term is positive @@ -100,8 +85,8 @@ impl Convert<(Weight, WeightMultiplier), WeightMultiplier> for WeightMultiplierU // 0.00004 = 4/100_000 = 40_000/10^9 let v = Fixed64::from_rational(4, 100_000); - // 0.00004^2 = 16/10^10 ~= 2/10^9. Taking the future /2 into account, then it is just 1 parts - // from a billionth. + // 0.00004^2 = 16/10^10 ~= 2/10^9. Taking the future /2 into account, then it is just 1 + // parts from a billionth. let v_squared_2 = Fixed64::from_rational(1, 1_000_000_000); let first_term = v.saturating_mul(diff); @@ -113,17 +98,17 @@ impl Convert<(Weight, WeightMultiplier), WeightMultiplier> for WeightMultiplierU // Note: this is merely bounded by how big the multiplier and the inner value can go, // not by any economical reasoning. let excess = first_term.saturating_add(second_term); - multiplier.saturating_add(WeightMultiplier::from_fixed(excess)) + multiplier.saturating_add(excess) } else { - // first_term > second_term + // Proof: first_term > second_term. Safe subtraction. let negative = first_term - second_term; - multiplier.saturating_sub(WeightMultiplier::from_fixed(negative)) + multiplier.saturating_sub(negative) // despite the fact that apply_to saturates weight (final fee cannot go below 0) // it is crucially important to stop here and don't further reduce the weight fee // multiplier. While at -1, it means that the network is so un-congested that all // transactions have no weight fee. We stop here and only increase if the network // became more busy. - .max(WeightMultiplier::from_rational(-1, 1)) + .max(Fixed64::from_rational(-1, 1)) } } } @@ -132,21 +117,20 @@ impl Convert<(Weight, WeightMultiplier), WeightMultiplier> for WeightMultiplierU mod tests { use super::*; use sr_primitives::weights::Weight; - use sr_primitives::Perbill; + use sr_primitives::assert_eq_error_rate; use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime}; - use crate::constants::currency::*; + use crate::{constants::currency::*, TransactionPayment, TargetBlockFullness}; fn max() -> Weight { MaximumBlockWeight::get() } fn target() -> Weight { - TARGET_BLOCK_FULLNESS * max() + TargetBlockFullness::get() * max() } // poc reference implementation. - #[allow(dead_code)] - fn weight_multiplier_update(block_weight: Weight) -> Perbill { + fn fee_multiplier_update(block_weight: Weight, previous: Fixed64) -> Fixed64 { let block_weight = block_weight as f32; let v: f32 = 0.00004; @@ -157,146 +141,225 @@ mod tests { // Current saturation in terms of weight let s = block_weight; - let fm = 1.0 + (v * (s/m - ss/m)) + (v.powi(2) * (s/m - ss/m).powi(2)) / 2.0; - // return a per-bill-like value. - let fm = if fm >= 1.0 { fm - 1.0 } else { 1.0 - fm }; - Perbill::from_parts((fm * 1_000_000_000_f32) as u32) + let fm = v * (s/m - ss/m) + v.powi(2) * (s/m - ss/m).powi(2) / 2.0; + let addition_fm = Fixed64::from_parts((fm * 1_000_000_000_f32).round() as i64); + previous.saturating_add(addition_fm) + } + + fn feemul(parts: i64) -> Fixed64 { + Fixed64::from_parts(parts) } - fn wm(parts: i64) -> WeightMultiplier { - WeightMultiplier::from_parts(parts) + fn run_with_system_weight(w: Weight, assertions: F) where F: Fn() -> () { + let mut t: runtime_io::TestExternalities = + system::GenesisConfig::default().build_storage::().unwrap().into(); + t.execute_with(|| { + System::set_block_limits(w, 0); + assertions() + }); + } + + #[test] + fn fee_multiplier_update_poc_works() { + let fm = Fixed64::from_rational(0, 1); + let test_set = vec![ + (0, fm.clone()), + (100, fm.clone()), + (target(), fm.clone()), + (max() / 2, fm.clone()), + (max(), fm.clone()), + ]; + test_set.into_iter().for_each(|(w, fm)| { + run_with_system_weight(w, || { + assert_eq_error_rate!( + fee_multiplier_update(w, fm).into_inner(), + TargetedFeeAdjustment::::convert(fm).into_inner(), + 5, + ); + }) + }) } #[test] fn empty_chain_simulation() { // just a few txs per_block. - let block_weight = 1000; - let mut wm = WeightMultiplier::default(); - let mut iterations: u64 = 0; - loop { - let next = WeightMultiplierUpdateHandler::convert((block_weight, wm)); - wm = next; - if wm == WeightMultiplier::from_rational(-1, 1) { break; } - iterations += 1; - } - println!("iteration {}, new wm = {:?}. Weight fee is now zero", iterations, wm); + let block_weight = 0; + run_with_system_weight(block_weight, || { + let mut fm = Fixed64::default(); + let mut iterations: u64 = 0; + loop { + let next = TargetedFeeAdjustment::::convert(fm); + fm = next; + if fm == Fixed64::from_rational(-1, 1) { break; } + iterations += 1; + } + println!("iteration {}, new fm = {:?}. Weight fee is now zero", iterations, fm); + assert!(iterations > 50_000, "This assertion is just a warning; Don't panic. \ + Current substrate/polkadot node are configured with a _slow adjusting fee_ \ + mechanism. Hence, it is really unlikely that fees collapse to zero even on an \ + empty chain in less than at least of couple of thousands of empty blocks. But this \ + simulation indicates that fees collapsed to zero after {} almost-empty blocks. \ + Check it", + iterations, + ); + }) } #[test] #[ignore] fn congested_chain_simulation() { // `cargo test congested_chain_simulation -- --nocapture` to get some insight. + // almost full. The entire quota of normal transactions is taken. - let block_weight = AvailableBlockRatio::get() * max(); - let tx_weight = 1000; - let mut wm = WeightMultiplier::default(); - let mut iterations: u64 = 0; - loop { - let next = WeightMultiplierUpdateHandler::convert((block_weight, wm)); - if wm == next { break; } - wm = next; - iterations += 1; - let fee = ::WeightToFee::convert(wm.apply_to(tx_weight)); - println!( - "iteration {}, new wm = {:?}. Fee at this point is: {} millicents, {} cents, {} dollars", - iterations, - wm, - fee / MILLICENTS, - fee / CENTS, - fee / DOLLARS - ); - } + let block_weight = AvailableBlockRatio::get() * max() - 100; + + // Default substrate minimum. + let tx_weight = 10_000; + + run_with_system_weight(block_weight, || { + // initial value configured on module + let mut fm = Fixed64::default(); + assert_eq!(fm, TransactionPayment::next_fee_multiplier()); + + let mut iterations: u64 = 0; + loop { + let next = TargetedFeeAdjustment::::convert(fm); + // if no change, panic. This should never happen in this case. + if fm == next { panic!("The fee should ever increase"); } + fm = next; + iterations += 1; + let fee = ::WeightToFee::convert(tx_weight); + let adjusted_fee = fm.saturated_multiply_accumulate(fee); + println!( + "iteration {}, new fm = {:?}. Fee at this point is: {} units / {} millicents, \ + {} cents, {} dollars", + iterations, + fm, + adjusted_fee, + adjusted_fee / MILLICENTS, + adjusted_fee / CENTS, + adjusted_fee / DOLLARS, + ); + } + }); } #[test] fn stateless_weight_mul() { - // Light block. Fee is reduced a little. - assert_eq!( - WeightMultiplierUpdateHandler::convert((target() / 4, WeightMultiplier::default())), - wm(-7500) - ); - // a bit more. Fee is decreased less, meaning that the fee increases as the block grows. - assert_eq!( - WeightMultiplierUpdateHandler::convert((target() / 2, WeightMultiplier::default())), - wm(-5000) - ); - // ideal. Original fee. No changes. - assert_eq!( - WeightMultiplierUpdateHandler::convert((target(), WeightMultiplier::default())), - wm(0) - ); - // // More than ideal. Fee is increased. - assert_eq!( - WeightMultiplierUpdateHandler::convert(((target() * 2), WeightMultiplier::default())), - wm(10000) - ); + run_with_system_weight(target() / 4, || { + // Light block. Fee is reduced a little. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(-7500), + ); + }); + run_with_system_weight(target() / 2, || { + // a bit more. Fee is decreased less, meaning that the fee increases as the block grows. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(-5000), + ); + + }); + run_with_system_weight(target(), || { + // ideal. Original fee. No changes. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(0), + ); + }); + run_with_system_weight(target() * 2, || { + // // More than ideal. Fee is increased. + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(10000), + ); + }); } #[test] fn stateful_weight_mul_grow_to_infinity() { - assert_eq!( - WeightMultiplierUpdateHandler::convert((target() * 2, WeightMultiplier::default())), - wm(10000) - ); - assert_eq!( - WeightMultiplierUpdateHandler::convert((target() * 2, wm(10000))), - wm(20000) - ); - assert_eq!( - WeightMultiplierUpdateHandler::convert((target() * 2, wm(20000))), - wm(30000) - ); - // ... - assert_eq!( - WeightMultiplierUpdateHandler::convert((target() * 2, wm(1_000_000_000))), - wm(1_000_000_000 + 10000) - ); + run_with_system_weight(target() * 2, || { + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(10000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(10000)), + feemul(20000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(20000)), + feemul(30000) + ); + // ... + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(1_000_000_000)), + feemul(1_000_000_000 + 10000) + ); + }); } #[test] fn stateful_weight_mil_collapse_to_minus_one() { - assert_eq!( - WeightMultiplierUpdateHandler::convert((0, WeightMultiplier::default())), - wm(-10000) - ); - assert_eq!( - WeightMultiplierUpdateHandler::convert((0, wm(-10000))), - wm(-20000) - ); - assert_eq!( - WeightMultiplierUpdateHandler::convert((0, wm(-20000))), - wm(-30000) - ); - // ... - assert_eq!( - WeightMultiplierUpdateHandler::convert((0, wm(1_000_000_000 * -1))), - wm(-1_000_000_000) - ); + run_with_system_weight(0, || { + assert_eq!( + TargetedFeeAdjustment::::convert(Fixed64::default()), + feemul(-10000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(-10000)), + feemul(-20000) + ); + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(-20000)), + feemul(-30000) + ); + // ... + assert_eq!( + TargetedFeeAdjustment::::convert(feemul(1_000_000_000 * -1)), + feemul(-1_000_000_000) + ); + }) } #[test] fn weight_to_fee_should_not_overflow_on_large_weights() { let kb = 1024 as Weight; let mb = kb * kb; - let max_fm = WeightMultiplier::from_fixed(Fixed64::from_natural(i64::max_value())); - - vec![0, 1, 10, 1000, kb, 10 * kb, 100 * kb, mb, 10 * mb, Weight::max_value() / 2, Weight::max_value()] - .into_iter() - .for_each(|i| { - WeightMultiplierUpdateHandler::convert((i, WeightMultiplier::default())); + let max_fm = Fixed64::from_natural(i64::max_value()); + + // check that for all values it can compute, correctly. + vec![ + 0, + 1, + 10, + 1000, + kb, + 10 * kb, + 100 * kb, + mb, + 10 * mb, + Weight::max_value() / 2, + Weight::max_value() + ].into_iter().for_each(|i| { + run_with_system_weight(i, || { + let next = TargetedFeeAdjustment::::convert(Fixed64::default()); + let truth = fee_multiplier_update(i, Fixed64::default()); + assert_eq_error_rate!(truth.into_inner(), next.into_inner(), 5); }); + }); // Some values that are all above the target and will cause an increase. let t = target(); vec![t + 100, t * 2, t * 4] .into_iter() .for_each(|i| { - let fm = WeightMultiplierUpdateHandler::convert(( - i, - max_fm - )); - // won't grow. The convert saturates everything. - assert_eq!(fm, max_fm); + run_with_system_weight(i, || { + let fm = TargetedFeeAdjustment::::convert(max_fm); + // won't grow. The convert saturates everything. + assert_eq!(fm, max_fm); + }) }); } } diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index e4bbf01e7c8dbd3ad53de2e01ef8d4cd6ef13d1e..7bc2cf633a35d17d681967276d6b87b1dda5c4e7 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -22,46 +22,47 @@ use rstd::prelude::*; use support::{ - construct_runtime, parameter_types, traits::{SplitTwoWays, Currency} + construct_runtime, parameter_types, traits::{SplitTwoWays, Currency, Randomness} }; use primitives::u32_trait::{_1, _2, _3, _4}; use node_primitives::{ AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Moment, Signature, }; -use babe::{AuthorityId as BabeId}; -use grandpa::fg_primitives::{self, ScheduledChange}; +use grandpa::fg_primitives; use client::{ block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult}, runtime_api as client_api, impl_runtime_apis }; -use sr_primitives::{ApplyResult, impl_opaque_keys, generic, create_runtime_str, key_types}; +use sr_primitives::{Permill, Perbill, ApplyResult, impl_opaque_keys, generic, create_runtime_str}; +use sr_primitives::curve::PiecewiseLinear; use sr_primitives::transaction_validity::TransactionValidity; use sr_primitives::weights::Weight; use sr_primitives::traits::{ - BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, + self, BlakeTwo256, Block as BlockT, NumberFor, StaticLookup, SaturatedConversion, + OpaqueKeys, }; use version::RuntimeVersion; -use elections::VoteIndex; #[cfg(any(feature = "std", test))] use version::NativeVersion; use primitives::OpaqueMetadata; use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight}; -use im_online::{AuthorityId as ImOnlineId}; -use finality_tracker::{DEFAULT_REPORT_LATENCY, DEFAULT_WINDOW_SIZE}; +use im_online::sr25519::{AuthorityId as ImOnlineId}; +use transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; +use contracts_rpc_runtime_api::ContractExecResult; +use system::offchain::TransactionSubmitter; #[cfg(any(feature = "std", test))] pub use sr_primitives::BuildStorage; pub use timestamp::Call as TimestampCall; pub use balances::Call as BalancesCall; pub use contracts::Gas; -pub use sr_primitives::{Permill, Perbill}; pub use support::StorageValue; pub use staking::StakerStatus; /// Implementations of some helper traits passed into runtime modules as associated types. pub mod impls; -use impls::{CurrencyToVoteHandler, WeightMultiplierUpdateHandler, Author, WeightToFee}; +use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment}; /// Constant values used within the runtime. pub mod constants; @@ -80,8 +81,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 141, - impl_version: 141, + spec_version: 192, + impl_version: 191, apis: RUNTIME_API_VERSIONS, }; @@ -106,8 +107,9 @@ pub type DealWithFees = SplitTwoWays< parameter_types! { pub const BlockHashCount: BlockNumber = 250; pub const MaximumBlockWeight: Weight = 1_000_000_000; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } impl system::Trait for Runtime { @@ -120,12 +122,17 @@ impl system::Trait for Runtime { type AccountId = AccountId; type Lookup = Indices; type Header = generic::Header; - type WeightMultiplierUpdate = WeightMultiplierUpdateHandler; type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = Version; +} + +impl utility::Trait for Runtime { + type Event = Event; + type Call = Call; } parameter_types! { @@ -136,6 +143,7 @@ parameter_types! { impl babe::Trait for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; + type EpochChangeTrigger = babe::ExternalTrigger; } impl indices::Trait for Runtime { @@ -149,8 +157,6 @@ parameter_types! { pub const ExistentialDeposit: Balance = 1 * DOLLARS; pub const TransferFee: Balance = 1 * CENTS; pub const CreationFee: Balance = 1 * CENTS; - pub const TransactionBaseFee: Balance = 1 * CENTS; - pub const TransactionByteFee: Balance = 10 * MILLICENTS; } impl balances::Trait for Runtime { @@ -158,15 +164,29 @@ impl balances::Trait for Runtime { type OnFreeBalanceZero = ((Staking, Contracts), Session); type OnNewAccount = Indices; type Event = Event; - type TransactionPayment = DealWithFees; type DustRemoval = (); type TransferPayment = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; +} + +parameter_types! { + pub const TransactionBaseFee: Balance = 1 * CENTS; + pub const TransactionByteFee: Balance = 10 * MILLICENTS; + // setting this to zero will disable the weight fee. + pub const WeightFeeCoefficient: Balance = 1_000; + // for a sane configuration, this should always be less than `AvailableBlockRatio`. + pub const TargetBlockFullness: Perbill = Perbill::from_percent(25); +} + +impl transaction_payment::Trait for Runtime { + type Currency = Balances; + type OnTransactionPayment = DealWithFees; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; - type WeightToFee = WeightToFee; + type WeightToFee = LinearWeightToFee; + type FeeMultiplierUpdate = TargetedFeeAdjustment; } parameter_types! { @@ -186,37 +206,31 @@ impl authorship::Trait for Runtime { type FindAuthor = session::FindAccountFromAuthorIndex; type UncleGenerations = UncleGenerations; type FilterUncle = (); - type EventHandler = Staking; + type EventHandler = (Staking, ImOnline); } -type SessionHandlers = (Grandpa, Babe, ImOnline); - impl_opaque_keys! { pub struct SessionKeys { - #[id(key_types::GRANDPA)] - pub grandpa: GrandpaId, - #[id(key_types::BABE)] - pub babe: BabeId, - #[id(key_types::IM_ONLINE)] - pub im_online: ImOnlineId, + pub grandpa: Grandpa, + pub babe: Babe, + pub im_online: ImOnline, } } -// NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler. -// The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in -// `SessionKeys`. -// TODO: Introduce some structure to tie these together to make it a bit less of a footgun. This -// should be easy, since OneSessionHandler trait provides the `Key` as an associated type. #2858 +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); +} impl session::Trait for Runtime { type OnSessionEnding = Staking; - type SessionHandler = SessionHandlers; + type SessionHandler = ::KeyTypeIdProviders; type ShouldEndSession = Babe; type Event = Event; type Keys = SessionKeys; - type ValidatorId = AccountId; + type ValidatorId = ::AccountId; type ValidatorIdOf = staking::StashOf; type SelectInitialValidators = Staking; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; } impl session::historical::Trait for Runtime { @@ -224,22 +238,38 @@ impl session::historical::Trait for Runtime { type FullIdentificationOf = staking::ExposureOf; } +srml_staking_reward_curve::build! { + const REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, // 10% - must be equal to MaxReward below. + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + parameter_types! { - pub const SessionsPerEra: session::SessionIndex = 6; + pub const SessionsPerEra: sr_staking_primitives::SessionIndex = 6; pub const BondingDuration: staking::EraIndex = 24 * 28; + pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; + pub const MaxReward: Perbill = Perbill::from_percent(10); + // ^^^ 10% - must be equal to max_inflation, above. } impl staking::Trait for Runtime { type Currency = Balances; type Time = Timestamp; type CurrencyToVote = CurrencyToVoteHandler; - type OnRewardMinted = Treasury; + type RewardRemainder = Treasury; type Event = Event; - type Slash = (); - type Reward = (); + type Slash = Treasury; // send the slashed funds to the treasury. + type Reward = (); // rewards are minted from the void type SessionsPerEra = SessionsPerEra; type BondingDuration = BondingDuration; type SessionInterface = Self; + type RewardCurve = RewardCurve; + type MaxPossibleReward = MaxReward; } parameter_types! { @@ -288,31 +318,24 @@ impl collective::Trait for Runtime { parameter_types! { pub const CandidacyBond: Balance = 10 * DOLLARS; pub const VotingBond: Balance = 1 * DOLLARS; - pub const VotingFee: Balance = 2 * DOLLARS; - pub const PresentSlashPerVoter: Balance = 1 * CENTS; - pub const CarryCount: u32 = 6; - // one additional vote should go by before an inactive voter can be reaped. - pub const InactiveGracePeriod: VoteIndex = 1; - pub const ElectionsVotingPeriod: BlockNumber = 2 * DAYS; - pub const DecayRatio: u32 = 0; + pub const TermDuration: BlockNumber = 7 * DAYS; + pub const DesiredMembers: u32 = 13; + pub const DesiredRunnersUp: u32 = 7; } -impl elections::Trait for Runtime { +impl elections_phragmen::Trait for Runtime { type Event = Event; type Currency = Balances; - type BadPresentation = (); - type BadReaper = (); - type BadVoterIndex = (); - type LoserCandidate = (); - type ChangeMembers = Council; + type CurrencyToVote = CurrencyToVoteHandler; type CandidacyBond = CandidacyBond; type VotingBond = VotingBond; - type VotingFee = VotingFee; - type PresentSlashPerVoter = PresentSlashPerVoter; - type CarryCount = CarryCount; - type InactiveGracePeriod = InactiveGracePeriod; - type VotingPeriod = ElectionsVotingPeriod; - type DecayRatio = DecayRatio; + type TermDuration = TermDuration; + type DesiredMembers = DesiredMembers; + type DesiredRunnersUp = DesiredRunnersUp; + type LoserCandidate = (); + type BadReport = (); + type KickedMember = (); + type ChangeMembers = Council; } type TechnicalCollective = collective::Instance2; @@ -344,7 +367,6 @@ impl treasury::Trait for Runtime { type ApproveOrigin = collective::EnsureMembers<_4, AccountId, CouncilCollective>; type RejectOrigin = collective::EnsureMembers<_2, AccountId, CouncilCollective>; type Event = Event; - type MintedForSpending = (); type ProposalRejection = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ProposalBondMinimum; @@ -358,29 +380,36 @@ parameter_types! { pub const ContractTransactionBaseFee: Balance = 1 * CENTS; pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS; pub const ContractFee: Balance = 1 * CENTS; + pub const TombstoneDeposit: Balance = 1 * DOLLARS; + pub const RentByteFee: Balance = 1 * DOLLARS; + pub const RentDepositOffset: Balance = 1000 * DOLLARS; + pub const SurchargeReward: Balance = 150 * DOLLARS; } impl contracts::Trait for Runtime { type Currency = Balances; + type Time = Timestamp; + type Randomness = RandomnessCollectiveFlip; type Call = Call; type Event = Event; type DetermineContractAddress = contracts::SimpleAddressDeterminator; type ComputeDispatchFee = contracts::DefaultDispatchFeeComputor; type TrieIdGenerator = contracts::TrieIdFromParentCounter; type GasPayment = (); + type RentPayment = (); type SignedClaimHandicap = contracts::DefaultSignedClaimHandicap; - type TombstoneDeposit = contracts::DefaultTombstoneDeposit; + type TombstoneDeposit = TombstoneDeposit; type StorageSizeOffset = contracts::DefaultStorageSizeOffset; - type RentByteFee = contracts::DefaultRentByteFee; - type RentDepositOffset = contracts::DefaultRentDepositOffset; - type SurchargeReward = contracts::DefaultSurchargeReward; + type RentByteFee = RentByteFee; + type RentDepositOffset = RentDepositOffset; + type SurchargeReward = SurchargeReward; type TransferFee = ContractTransferFee; type CreationFee = ContractCreationFee; type TransactionBaseFee = ContractTransactionBaseFee; type TransactionByteFee = ContractTransactionByteFee; type ContractFee = ContractFee; type CallBaseFee = contracts::DefaultCallBaseFee; - type CreateBaseFee = contracts::DefaultCreateBaseFee; + type InstantiateBaseFee = contracts::DefaultInstantiateBaseFee; type MaxDepth = contracts::DefaultMaxDepth; type MaxValueSize = contracts::DefaultMaxValueSize; type BlockGasLimit = contracts::DefaultBlockGasLimit; @@ -391,10 +420,25 @@ impl sudo::Trait for Runtime { type Proposal = Call; } +type SubmitTransaction = TransactionSubmitter; + +parameter_types! { + pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _; +} + impl im_online::Trait for Runtime { + type AuthorityId = ImOnlineId; type Call = Call; type Event = Event; - type UncheckedExtrinsic = UncheckedExtrinsic; + type SubmitTransaction = SubmitTransaction; + type ReportUnresponsiveness = Offences; + type SessionDuration = SessionDuration; +} + +impl offences::Trait for Runtime { + type Event = Event; + type IdentificationTuple = session::historical::IdentificationTuple; + type OnOffenceHandler = Staking; } impl grandpa::Trait for Runtime { @@ -402,8 +446,8 @@ impl grandpa::Trait for Runtime { } parameter_types! { - pub const WindowSize: BlockNumber = DEFAULT_WINDOW_SIZE.into(); - pub const ReportLatency: BlockNumber = DEFAULT_REPORT_LATENCY.into(); + pub const WindowSize: BlockNumber = 101; + pub const ReportLatency: BlockNumber = 1000; } impl finality_tracker::Trait for Runtime { @@ -412,6 +456,52 @@ impl finality_tracker::Trait for Runtime { type ReportLatency = ReportLatency; } +parameter_types! { + pub const ReservationFee: Balance = 1 * DOLLARS; + pub const MinLength: usize = 3; + pub const MaxLength: usize = 16; +} + +impl nicks::Trait for Runtime { + type Event = Event; + type Currency = Balances; + type ReservationFee = ReservationFee; + type Slashed = Treasury; + type ForceOrigin = collective::EnsureMember; + type MinLength = MinLength; + type MaxLength = MaxLength; +} + +impl system::offchain::CreateTransaction for Runtime { + type Public = ::Signer; + type Signature = Signature; + + fn create_transaction>( + call: Call, + public: Self::Public, + account: AccountId, + index: Index, + ) -> Option<(Call, ::SignaturePayload)> { + let period = 1 << 8; + let current_block = System::block_number().saturated_into::(); + let tip = 0; + let extra: SignedExtra = ( + system::CheckVersion::::new(), + system::CheckGenesis::::new(), + system::CheckEra::::from(generic::Era::mortal(period, current_block)), + system::CheckNonce::::from(index), + system::CheckWeight::::new(), + transaction_payment::ChargeTransactionPayment::::from(tip), + Default::default(), + ); + let raw_payload = SignedPayload::new(call, extra).ok()?; + let signature = F::sign(public, &raw_payload)?; + let address = Indices::unlookup(account); + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (address, signature, extra))) + } +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -419,24 +509,29 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic { System: system::{Module, Call, Storage, Config, Event}, + Utility: utility::{Module, Call, Event}, Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)}, Timestamp: timestamp::{Module, Call, Storage, Inherent}, Authorship: authorship::{Module, Call, Storage, Inherent}, Indices: indices, - Balances: balances, + Balances: balances::{default, Error}, + TransactionPayment: transaction_payment::{Module, Storage}, Staking: staking::{default, OfflineWorker}, Session: session::{Module, Call, Storage, Event, Config}, Democracy: democracy::{Module, Call, Storage, Config, Event}, Council: collective::::{Module, Call, Storage, Origin, Event, Config}, TechnicalCommittee: collective::::{Module, Call, Storage, Origin, Event, Config}, - Elections: elections::{Module, Call, Storage, Event, Config}, + Elections: elections_phragmen::{Module, Call, Storage, Event}, TechnicalMembership: membership::::{Module, Call, Storage, Event, Config}, FinalityTracker: finality_tracker::{Module, Call, Inherent}, Grandpa: grandpa::{Module, Call, Storage, Config, Event}, - Treasury: treasury::{Module, Call, Storage, Event}, + Treasury: treasury::{Module, Call, Storage, Config, Event}, Contracts: contracts, Sudo: sudo, - ImOnline: im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, + ImOnline: im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, + Offences: offences::{Module, Call, Storage, Event}, + RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage}, + Nicks: nicks::{Module, Call, Storage, Event}, } ); @@ -452,14 +547,18 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + system::CheckVersion, system::CheckGenesis, system::CheckEra, system::CheckNonce, system::CheckWeight, - balances::TakeFees + transaction_payment::ChargeTransactionPayment, + contracts::CheckBlockGasLimit, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. @@ -504,7 +603,7 @@ impl_runtime_apis! { } fn random_seed() -> ::Hash { - System::random_seed() + RandomnessCollectiveFlip::random_seed() } } @@ -521,58 +620,111 @@ impl_runtime_apis! { } impl fg_primitives::GrandpaApi for Runtime { - fn grandpa_pending_change(digest: &DigestFor) - -> Option>> - { - Grandpa::pending_change(digest) - } - - fn grandpa_forced_change(digest: &DigestFor) - -> Option<(NumberFor, ScheduledChange>)> - { - Grandpa::forced_change(digest) - } - fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> { Grandpa::grandpa_authorities() } } impl babe_primitives::BabeApi for Runtime { - fn startup_data() -> babe_primitives::BabeConfiguration { + fn configuration() -> babe_primitives::BabeConfiguration { // The choice of `c` parameter (where `1 - c` represents the // probability of a slot being empty), is done in accordance to the // slot duration and expected target block time, for safely // resisting network delays of maximum two seconds. // babe_primitives::BabeConfiguration { - median_required_blocks: 1000, slot_duration: Babe::slot_duration(), - c: (278, 1000), + epoch_length: EpochDuration::get(), + c: PRIMARY_PROBABILITY, + genesis_authorities: Babe::authorities(), + randomness: Babe::randomness(), + secondary_slots: true, } } + } - fn epoch() -> babe_primitives::Epoch { - babe_primitives::Epoch { - start_slot: Babe::epoch_start_slot(), - authorities: Babe::authorities(), - epoch_index: Babe::epoch_index(), - randomness: Babe::randomness(), - duration: EpochDuration::get(), + impl system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl contracts_rpc_runtime_api::ContractsApi for Runtime { + fn call( + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: u64, + input_data: Vec, + ) -> ContractExecResult { + let exec_result = Contracts::bare_call( + origin, + dest.into(), + value, + gas_limit, + input_data, + ); + match exec_result { + Ok(v) => ContractExecResult::Success { + status: v.status, + data: v.data, + }, + Err(_) => ContractExecResult::Error, } } + + fn get_storage( + address: AccountId, + key: [u8; 32], + ) -> contracts_rpc_runtime_api::GetStorageResult { + Contracts::get_storage(address, key).map_err(|rpc_err| { + use contracts::GetStorageError; + use contracts_rpc_runtime_api::{GetStorageError as RpcGetStorageError}; + /// Map the contract error into the RPC layer error. + match rpc_err { + GetStorageError::ContractDoesntExist => RpcGetStorageError::ContractDoesntExist, + GetStorageError::IsTombstone => RpcGetStorageError::IsTombstone, + } + }) + } } - impl consensus_primitives::ConsensusApi for Runtime { - fn authorities() -> Vec { - Babe::authorities().into_iter().map(|(a, _)| a).collect() + impl transaction_payment_rpc_runtime_api::TransactionPaymentApi< + Block, + Balance, + UncheckedExtrinsic, + > for Runtime { + fn query_info(uxt: UncheckedExtrinsic, len: u32) -> RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) } } impl substrate_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { - let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string")); + let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s) + .expect("Seed is an utf8 string")); SessionKeys::generate(seed) } } } +#[cfg(test)] +mod tests { + use super::*; + use system::offchain::SubmitSignedTransaction; + + fn is_submit_signed_transaction(_arg: T) where + T: SubmitSignedTransaction< + Runtime, + Call, + Extrinsic=UncheckedExtrinsic, + CreateTransaction=Runtime, + Signer=ImOnlineId, + >, + {} + + #[test] + fn validate_bounds() { + let x = SubmitTransaction::default(); + is_submit_signed_transaction(x); + } +} diff --git a/node/testing/Cargo.toml b/node/testing/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..8a4c08ed11bd2e53d0d844cd0fb64f721858dba1 --- /dev/null +++ b/node/testing/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "node-testing" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Test utilities for Substrate node." +edition = "2018" + +[dependencies] +balances = { package = "srml-balances", path = "../../srml/balances" } +client = { package = "substrate-client", path = "../../core/client" } +contracts = { package = "srml-contracts", path = "../../srml/contracts" } +grandpa = { package = "srml-grandpa", path = "../../srml/grandpa" } +indices = { package = "srml-indices", path = "../../srml/indices" } +keyring = { package = "substrate-keyring", path = "../../core/keyring" } +node-executor = { path = "../executor" } +node-primitives = { path = "../primitives" } +node-runtime = { path = "../runtime" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +sr-io = { path = "../../core/sr-io" } +sr-primitives = { path = "../../core/sr-primitives" } +runtime_support = { package = "srml-support", path = "../../srml/support" } +session = { package = "srml-session", path = "../../srml/session" } +staking = { package = "srml-staking", path = "../../srml/staking" } +substrate-executor = { path = "../../core/executor" } +system = { package = "srml-system", path = "../../srml/system" } +test-client = { package = "substrate-test-client", path = "../../core/test-client" } +timestamp = { package = "srml-timestamp", path = "../../srml/timestamp" } +treasury = { package = "srml-treasury", path = "../../srml/treasury" } +transaction-payment = { package = "srml-transaction-payment", path = "../../srml/transaction-payment" } +wabt = "0.9.2" diff --git a/node/testing/src/client.rs b/node/testing/src/client.rs new file mode 100644 index 0000000000000000000000000000000000000000..3b16f2cbcb97d801500e1bb8ffbef3f2e0c9bb9c --- /dev/null +++ b/node/testing/src/client.rs @@ -0,0 +1,73 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Utilites to build a `TestClient` for `node-runtime`. + +use sr_primitives::BuildStorage; + +/// Re-export test-client utilities. +pub use test_client::*; + +/// Call executor for `node-runtime` `TestClient`. +pub type Executor = substrate_executor::NativeExecutor; + +/// Default backend type. +pub type Backend = client_db::Backend; + +/// Test client type. +pub type Client = client::Client< + Backend, + client::LocalCallExecutor, + node_primitives::Block, + node_runtime::RuntimeApi, +>; + +/// Genesis configuration parameters for `TestClient`. +#[derive(Default)] +pub struct GenesisParameters { + support_changes_trie: bool, +} + +impl test_client::GenesisInit for GenesisParameters { + fn genesis_storage(&self) -> (StorageOverlay, ChildrenStorageOverlay) { + crate::genesis::config(self.support_changes_trie, None).build_storage().unwrap() + } +} + +/// A `test-runtime` extensions to `TestClientBuilder`. +pub trait TestClientBuilderExt: Sized { + /// Create test client builder. + fn new() -> Self; + + /// Build the test client. + fn build(self) -> Client; +} + +impl TestClientBuilderExt for test_client::TestClientBuilder< + client::LocalCallExecutor, + Backend, + GenesisParameters, +> { + fn new() -> Self{ + Self::default() + } + + fn build(self) -> Client { + self.build_with_native_executor(None).0 + } +} + + diff --git a/node/testing/src/genesis.rs b/node/testing/src/genesis.rs new file mode 100644 index 0000000000000000000000000000000000000000..0b99052f250269fe9b58694f7b8f469a2544c0d5 --- /dev/null +++ b/node/testing/src/genesis.rs @@ -0,0 +1,99 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Genesis Configuration. + +use crate::keyring::*; +use keyring::{Ed25519Keyring, Sr25519Keyring}; +use node_runtime::{ + GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig, + GrandpaConfig, IndicesConfig, ContractsConfig, WASM_BINARY, +}; +use node_runtime::constants::currency::*; +use primitives::ChangesTrieConfiguration; +use sr_primitives::Perbill; + + +/// Create genesis runtime configuration for tests. +pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig { + GenesisConfig { + system: Some(SystemConfig { + changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { + digest_interval: 2, + digest_levels: 2, + }) } else { None }, + code: code.map(|x| x.to_vec()).unwrap_or_else(|| WASM_BINARY.to_vec()), + }), + indices: Some(IndicesConfig { + ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], + }), + balances: Some(BalancesConfig { + balances: vec![ + (alice(), 111 * DOLLARS), + (bob(), 100 * DOLLARS), + (charlie(), 100_000_000 * DOLLARS), + (dave(), 111 * DOLLARS), + (eve(), 101 * DOLLARS), + (ferdie(), 100 * DOLLARS), + ], + vesting: vec![], + }), + session: Some(SessionConfig { + keys: vec![ + (alice(), to_session_keys( + &Ed25519Keyring::Alice, + &Sr25519Keyring::Alice, + )), + (bob(), to_session_keys( + &Ed25519Keyring::Bob, + &Sr25519Keyring::Bob, + )), + (charlie(), to_session_keys( + &Ed25519Keyring::Charlie, + &Sr25519Keyring::Charlie, + )), + ] + }), + staking: Some(StakingConfig { + current_era: 0, + stakers: vec![ + (dave(), alice(), 111 * DOLLARS, staking::StakerStatus::Validator), + (eve(), bob(), 100 * DOLLARS, staking::StakerStatus::Validator), + (ferdie(), charlie(), 100 * DOLLARS, staking::StakerStatus::Validator) + ], + validator_count: 3, + minimum_validator_count: 0, + slash_reward_fraction: Perbill::from_percent(10), + invulnerables: vec![alice(), bob(), charlie()], + .. Default::default() + }), + contracts: Some(ContractsConfig { + current_schedule: Default::default(), + gas_price: 1 * MILLICENTS, + }), + babe: Some(Default::default()), + grandpa: Some(GrandpaConfig { + authorities: vec![], + }), + im_online: Some(Default::default()), + democracy: Some(Default::default()), + collective_Instance1: Some(Default::default()), + collective_Instance2: Some(Default::default()), + membership_Instance1: Some(Default::default()), + sudo: Some(Default::default()), + treasury: Some(Default::default()), + } +} diff --git a/node/testing/src/keyring.rs b/node/testing/src/keyring.rs new file mode 100644 index 0000000000000000000000000000000000000000..ca44a53880fc1f661443987406e6158e2a8778aa --- /dev/null +++ b/node/testing/src/keyring.rs @@ -0,0 +1,102 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test accounts. + +use keyring::{AccountKeyring, Sr25519Keyring, Ed25519Keyring}; +use node_primitives::{AccountId, Balance, Index}; +use node_runtime::{CheckedExtrinsic, UncheckedExtrinsic, SessionKeys, SignedExtra}; +use sr_primitives::generic::Era; +use codec::Encode; + +/// Alice's account id. +pub fn alice() -> AccountId { AccountKeyring::Alice.into() } + +/// Bob's account id. +pub fn bob() -> AccountId { + AccountKeyring::Bob.into() +} + +/// Charlie's account id. +pub fn charlie() -> AccountId { + AccountKeyring::Charlie.into() +} + +/// Dave's account id. +pub fn dave() -> AccountId { + AccountKeyring::Dave.into() +} + +/// Eve's account id. +pub fn eve() -> AccountId { + AccountKeyring::Eve.into() +} + +/// Ferdie's account id. +pub fn ferdie() -> AccountId { + AccountKeyring::Ferdie.into() +} + +/// Convert keyrings into `SessionKeys`. +pub fn to_session_keys( + ed25519_keyring: &Ed25519Keyring, + sr25519_keyring: &Sr25519Keyring, +) -> SessionKeys { + SessionKeys { + grandpa: ed25519_keyring.to_owned().public().into(), + babe: sr25519_keyring.to_owned().public().into(), + im_online: sr25519_keyring.to_owned().public().into(), + } +} + +/// Returns transaction extra. +pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { + ( + system::CheckVersion::new(), + system::CheckGenesis::new(), + system::CheckEra::from(Era::mortal(256, 0)), + system::CheckNonce::from(nonce), + system::CheckWeight::new(), + transaction_payment::ChargeTransactionPayment::from(extra_fee), + Default::default(), + ) +} + +/// Sign given `CheckedExtrinsic`. +pub fn sign(xt: CheckedExtrinsic, version: u32, genesis_hash: [u8; 32]) -> UncheckedExtrinsic { + match xt.signed { + Some((signed, extra)) => { + let payload = (xt.function, extra.clone(), version, genesis_hash, genesis_hash); + let key = AccountKeyring::from_account_id(&signed).unwrap(); + let signature = payload.using_encoded(|b| { + if b.len() > 256 { + key.sign(&sr_io::blake2_256(b)) + } else { + key.sign(b) + } + }).into(); + UncheckedExtrinsic { + signature: Some((indices::address::Address::Id(signed), signature, extra)), + function: payload.0, + } + } + None => UncheckedExtrinsic { + signature: None, + function: xt.function, + }, + } +} + diff --git a/node/testing/src/lib.rs b/node/testing/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..71a22d9b57f2555095b5b5ab67701945a2dd6897 --- /dev/null +++ b/node/testing/src/lib.rs @@ -0,0 +1,24 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A set of testing utilities for Substrate Node. + +#![warn(missing_docs)] + +pub mod client; +pub mod genesis; +pub mod keyring; + diff --git a/rustdoc-header.html b/rustdoc-header.html new file mode 100644 index 0000000000000000000000000000000000000000..a679d5e299da7a79e6fd52aa3594a78053b7d641 --- /dev/null +++ b/rustdoc-header.html @@ -0,0 +1,10 @@ + + + + diff --git a/scripts/build-only-wasm.sh b/scripts/build-only-wasm.sh new file mode 100755 index 0000000000000000000000000000000000000000..b6da3319c8214aeca3ca54b76fda87d83077eec5 --- /dev/null +++ b/scripts/build-only-wasm.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env sh + +# Script for building only the WASM binary of the given project. + +set -e + +PROJECT_ROOT=`git rev-parse --show-toplevel` + +if [ "$#" -lt 1 ]; then + echo "You need to pass the name of the crate you want to compile!" + exit 1 +fi + +WASM_BUILDER_RUNNER="$PROJECT_ROOT/target/release/wbuild-runner/$1" + +if [ -z "$2" ]; then + export WASM_TARGET_DIRECTORY=$(pwd) +else + export WASM_TARGET_DIRECTORY=$2 +fi + +if [ -d $WASM_BUILDER_RUNNER ]; then + export DEBUG=false + export OUT_DIR="$PROJECT_ROOT/target/release/build" + cargo run --release --manifest-path="$WASM_BUILDER_RUNNER/Cargo.toml" \ + | grep -vE "cargo:rerun-if-|Executing build command" +else + cargo build --release -p $1 +fi diff --git a/scripts/gitlab/check_runtime.sh b/scripts/gitlab/check_runtime.sh index 725c5077c56494838ba283a59bddf991585bbdef..cd988718d05db52814bf107e15a7e6c63038b0ee 100755 --- a/scripts/gitlab/check_runtime.sh +++ b/scripts/gitlab/check_runtime.sh @@ -32,7 +32,7 @@ github_label () { # check if the wasm sources changed if ! git diff --name-only origin/master...${CI_COMMIT_SHA} \ - | grep -q -e '^node/src/runtime' -e '^srml/' -e '^core/sr-' + | grep -q -e '^node/src/runtime' -e '^srml/' -e '^core/sr-' | grep -v -e '^core/sr-arithmetic/fuzzer' then cat <<-EOT diff --git a/scripts/init.sh b/scripts/init.sh index cf5ecf97926fea7a5e8fd2a91df96853f90e8ee7..1405a41ef333e6af863080d83f854d3edb5fb4fa 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -10,7 +10,3 @@ if [ -z $CI_PROJECT_NAME ] ; then fi rustup target add wasm32-unknown-unknown --toolchain nightly - -# Install wasm-gc. It's useful for stripping slimming down wasm binaries. -command -v wasm-gc || \ - cargo +nightly install --git https://github.com/alexcrichton/wasm-gc --force diff --git a/scripts/node-template-release/Cargo.toml b/scripts/node-template-release/Cargo.toml index 34aadc971f1aaa78b2f53860e668d294cee52eb0..8a43435b20d83be0f69007eedb6888acbc2c3282 100644 --- a/scripts/node-template-release/Cargo.toml +++ b/scripts/node-template-release/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" toml = "0.4" tar = "0.4" glob = "0.2" -structopt = "0.2" +structopt = "0.3" tempfile = "3" fs_extra = "1" git2 = "0.8" diff --git a/scripts/node-template-release/src/main.rs b/scripts/node-template-release/src/main.rs index 4036104f6030a243f44deaf25664597ad13ed69b..7fde9c86847200126b1a86cf30678f2591a0a0f3 100644 --- a/scripts/node-template-release/src/main.rs +++ b/scripts/node-template-release/src/main.rs @@ -88,37 +88,46 @@ fn replace_path_dependencies_with_git(cargo_toml_path: &Path, commit_id: &str, c // remove `Cargo.toml` cargo_toml_path.pop(); - let mut dependencies: toml::value::Table = match cargo_toml - .remove("dependencies") - .and_then(|v| v.try_into().ok()) { - Some(deps) => deps, - None => return, - }; - - let deps_rewritten = dependencies - .iter() - .filter_map(|(k, v)| v.clone().try_into::().ok().map(move |v| (k, v))) - .filter(|t| t.1.contains_key("path")) - .filter(|t| { - // if the path does not exists, we need to add this as git dependency - t.1.get("path").unwrap().as_str().map(|path| !cargo_toml_path.join(path).exists()).unwrap_or(false) - }) - .map(|(k, mut v)| { - // remove `path` and add `git` and `rev` - v.remove("path"); - v.insert("git".into(), SUBSTRATE_GIT_URL.into()); - v.insert("rev".into(), commit_id.into()); - - (k.clone(), v.into()) - }).collect::>(); - - dependencies.extend(deps_rewritten.into_iter()); - - cargo_toml.insert("dependencies".into(), dependencies.into()); + for table in &["dependencies", "build-dependencies"] { + let mut dependencies: toml::value::Table = match cargo_toml + .remove(table) + .and_then(|v| v.try_into().ok()) { + Some(deps) => deps, + None => continue, + }; + + let deps_rewritten = dependencies + .iter() + .filter_map(|(k, v)| v.clone().try_into::().ok().map(move |v| (k, v))) + .filter(|t| t.1.contains_key("path")) + .filter(|t| { + // if the path does not exists, we need to add this as git dependency + t.1.get("path").unwrap().as_str().map(|path| !cargo_toml_path.join(path).exists()).unwrap_or(false) + }) + .map(|(k, mut v)| { + // remove `path` and add `git` and `rev` + v.remove("path"); + v.insert("git".into(), SUBSTRATE_GIT_URL.into()); + v.insert("rev".into(), commit_id.into()); + + (k.clone(), v.into()) + }).collect::>(); + + dependencies.extend(deps_rewritten.into_iter()); + + cargo_toml.insert(table.into(), dependencies.into()); + } } -/// Add `profile.release` = `panic = unwind` to the given `Cargo.toml` -fn cargo_toml_add_profile_release(cargo_toml: &mut CargoToml) { +/// Update the top level (workspace) `Cargo.toml` file. +/// +/// - Adds `profile.release` = `panic = unwind` +/// - Adds `workspace` definition +fn update_top_level_cargo_toml( + cargo_toml: &mut CargoToml, + workspace_members: Vec<&PathBuf>, + node_template_path: &Path, +) { let mut panic_unwind = toml::value::Table::new(); panic_unwind.insert("panic".into(), "unwind".into()); @@ -126,6 +135,24 @@ fn cargo_toml_add_profile_release(cargo_toml: &mut CargoToml) { profile.insert("release".into(), panic_unwind.into()); cargo_toml.insert("profile".into(), profile.into()); + + let members = workspace_members.iter() + .map(|p| + p.strip_prefix(node_template_path) + .expect("Workspace member is a child of the node template path!") + .parent() + // We get the `Cargo.toml` paths as workspace members, but for the `members` field + // we just need the path. + .expect("The given path ends with `Cargo.toml` as file name!") + .display() + .to_string() + ) + .collect::>(); + + let mut members_section = toml::value::Table::new(); + members_section.insert("members".into(), members.into()); + + cargo_toml.insert("workspace".into(), members_section.into()); } fn write_cargo_toml(path: &Path, cargo_toml: CargoToml) { @@ -137,10 +164,24 @@ fn write_cargo_toml(path: &Path, cargo_toml: CargoToml) { /// Build and test the generated node-template fn build_and_test(path: &Path, cargo_tomls: &[PathBuf]) { // Build node - assert!(Command::new("cargo").args(&["build", "--all"]).current_dir(path).status().expect("Compiles node").success()); + assert!( + Command::new("cargo") + .args(&["build", "--all"]) + .current_dir(path) + .status() + .expect("Compiles node") + .success() + ); // Test node - assert!(Command::new("cargo").args(&["test", "--all"]).current_dir(path).status().expect("Tests node").success()); + assert!( + Command::new("cargo") + .args(&["test", "--all"]) + .current_dir(path) + .status() + .expect("Tests node") + .success() + ); // Remove all `target` directories for toml in cargo_tomls { @@ -174,14 +215,20 @@ fn main() { let cargo_tomls = find_cargo_tomls(build_dir.path().to_owned()); let commit_id = get_git_commit_id(&options.node_template); + let top_level_cargo_toml_path = node_template_path.join("Cargo.toml"); cargo_tomls.iter().for_each(|t| { let mut cargo_toml = parse_cargo_toml(&t); replace_path_dependencies_with_git(&t, &commit_id, &mut cargo_toml); - // If this is the top-level `Cargo.toml`, add `profile.release` - if &node_template_path.join("Cargo.toml") == t { - cargo_toml_add_profile_release(&mut cargo_toml); + // Check if this is the top level `Cargo.toml`, as this requires some special treatments. + if top_level_cargo_toml_path == *t { + // All workspace member `Cargo.toml` file paths. + let workspace_members = cargo_tomls.iter() + .filter(|p| **p != top_level_cargo_toml_path) + .collect(); + + update_top_level_cargo_toml(&mut cargo_toml, workspace_members, &node_template_path); } write_cargo_toml(&t, cargo_toml); diff --git a/srml/assets/Cargo.toml b/srml/assets/Cargo.toml index 2badb461303cd4aa390a00840d4d25e0423ce9fc..052a3045b21647e9251546ed0ae37dd8d86f5632 100644 --- a/srml/assets/Cargo.toml +++ b/srml/assets/Cargo.toml @@ -5,19 +5,19 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } # Needed for various traits. In our case, `OnFinalize`. sr-primitives = { path = "../../core/sr-primitives", default-features = false } # Needed for type-safe access to storage DB. -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } # `system` module provides us with all sorts of useful stuff and macros depend on it being around. system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] primitives = { package = "substrate-primitives", path = "../../core/primitives" } -sr-std = { path = "../../core/sr-std" } -runtime_io = { package = "sr-io", path = "../../core/sr-io" } +rstd = { package = "sr-std", path = "../../core/sr-std" } +runtime-io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] @@ -25,6 +25,6 @@ std = [ "serde", "codec/std", "sr-primitives/std", - "srml-support/std", + "support/std", "system/std", ] diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index d5ae95c559539d82466cd8c010b0616a78a21645..5c8b1bbd610a3c436eb9a1dae54ab7e62a297766 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -130,7 +130,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use srml_support::{StorageValue, StorageMap, Parameter, decl_module, decl_event, decl_storage, ensure}; +use support::{Parameter, decl_module, decl_event, decl_storage, ensure}; use sr_primitives::traits::{Member, SimpleArithmetic, Zero, StaticLookup}; use system::ensure_signed; use sr_primitives::traits::One; @@ -149,7 +149,7 @@ pub trait Trait: system::Trait { decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Issue a new class of fungible assets. There are, and will only ever be, `total` /// such assets and they'll all belong to the `origin` initially. It will have an /// identifier `AssetId` instance: this will be specified in the `Issued` event. @@ -159,7 +159,7 @@ decl_module! { let id = Self::next_asset_id(); >::mutate(|id| *id += One::one()); - >::insert((id, origin.clone()), total); + >::insert((id, &origin), total); >::insert(id, total); Self::deposit_event(RawEvent::Issued(id, origin, total)); @@ -186,7 +186,7 @@ decl_module! { /// Destroy any assets of `id` owned by `origin`. fn destroy(origin, #[compact] id: T::AssetId) { let origin = ensure_signed(origin)?; - let balance = >::take((id, origin.clone())); + let balance = >::take((id, &origin)); ensure!(!balance.is_zero(), "origin balance should be non-zero"); >::mutate(id, |total_supply| *total_supply -= balance); @@ -196,10 +196,11 @@ decl_module! { } decl_event!( - pub enum Event - where ::AccountId, - ::Balance, - ::AssetId { + pub enum Event where + ::AccountId, + ::Balance, + ::AssetId, + { /// Some assets were issued. Issued(AssetId, AccountId, Balance), /// Some assets were transferred. @@ -214,7 +215,7 @@ decl_storage! { /// The number of units of assets held by any given account. Balances: map (T::AssetId, T::AccountId) => T::Balance; /// The next asset identifier up for grabs. - NextAssetId get(next_asset_id): T::AssetId; + NextAssetId get(fn next_asset_id): T::AssetId; /// The total unit supply of an asset. TotalSupply: map T::AssetId => T::Balance; } @@ -239,9 +240,8 @@ impl Module { mod tests { use super::*; - use runtime_io::with_externalities; - use srml_support::{impl_outer_origin, assert_ok, assert_noop, parameter_types}; - use primitives::{H256, Blake2Hasher}; + use support::{impl_outer_origin, assert_ok, assert_noop, parameter_types}; + use primitives::H256; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; @@ -271,12 +271,12 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } impl Trait for Test { type Event = (); @@ -287,13 +287,13 @@ mod tests { // This function basically just builds a genesis storage key/value store according to // our desired mockup. - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { system::GenesisConfig::default().build_storage::().unwrap().into() } #[test] fn issuing_asset_units_to_issuer_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 1), 100); }); @@ -301,7 +301,7 @@ mod tests { #[test] fn querying_total_supply_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 1), 100); assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); @@ -318,7 +318,7 @@ mod tests { #[test] fn transferring_amount_above_available_balance_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 1), 100); assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); @@ -328,8 +328,8 @@ mod tests { } #[test] - fn transferring_amount_less_than_available_balance_should_not_work() { - with_externalities(&mut new_test_ext(), || { + fn transferring_amount_more_than_available_balance_should_not_work() { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 1), 100); assert_ok!(Assets::transfer(Origin::signed(1), 0, 2, 50)); @@ -343,7 +343,7 @@ mod tests { #[test] fn transferring_less_than_one_unit_should_not_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 1), 100); assert_noop!(Assets::transfer(Origin::signed(1), 0, 2, 0), "transfer amount should be non-zero"); @@ -352,7 +352,7 @@ mod tests { #[test] fn transferring_more_units_than_total_supply_should_not_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 1), 100); assert_noop!(Assets::transfer(Origin::signed(1), 0, 2, 101), "origin account balance must be greater than or equal to the transfer amount"); @@ -361,7 +361,7 @@ mod tests { #[test] fn destroying_asset_balance_with_positive_balance_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 1), 100); assert_ok!(Assets::destroy(Origin::signed(1), 0)); @@ -370,7 +370,7 @@ mod tests { #[test] fn destroying_asset_balance_with_zero_balance_should_not_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Assets::issue(Origin::signed(1), 100)); assert_eq!(Assets::balance(0, 2), 0); assert_noop!(Assets::destroy(Origin::signed(2), 0), "origin balance should be non-zero"); diff --git a/srml/aura/Cargo.toml b/srml/aura/Cargo.toml index 955831ba299104ddd35f360bb2a99f43333aaef1..f1c37b7c08d45fe7ec2cadcf608d1c407e7dbc15 100644 --- a/srml/aura/Cargo.toml +++ b/srml/aura/Cargo.toml @@ -5,38 +5,37 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] +app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +serde = { version = "1.0.101", optional = true } +session = { package = "srml-session", path = "../session", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } -srml-support = { path = "../support", default-features = false } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives", default-features = false} system = { package = "srml-system", path = "../system", default-features = false } timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } -staking = { package = "srml-staking", path = "../staking", default-features = false } -session = { package = "srml-session", path = "../session", default-features = false } -substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives", default-features = false} [dev-dependencies] -lazy_static = "1.0" +lazy_static = "1.4.0" parking_lot = "0.9.0" -runtime_io = { package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] std = [ - "serde", + "app-crypto/std", "codec/std", + "inherents/std", + "runtime-io/std", + "primitives/std", "rstd/std", - "srml-support/std", + "serde", "sr-primitives/std", - "primitives/std", + "support/std", + "substrate-consensus-aura-primitives/std", "system/std", "timestamp/std", - "staking/std", - "inherents/std", - "substrate-consensus-aura-primitives/std", - "app-crypto/std", ] diff --git a/srml/aura/src/lib.rs b/srml/aura/src/lib.rs index 6d707fc8e195f79416a4f421042c0e9d8df7e125..f27cb98c0131d817e9091765f952bb202aebb6ec 100644 --- a/srml/aura/src/lib.rs +++ b/srml/aura/src/lib.rs @@ -31,9 +31,6 @@ //! //! ## Related Modules //! -//! - [Staking](../srml_staking/index.html): The Staking module is called in Aura to enforce slashing -//! if validators miss a certain number of slots (see the [`StakingSlasher`](./struct.StakingSlasher.html) -//! struct and associated method). //! - [Timestamp](../srml_timestamp/index.html): The Timestamp module is used in Aura to track //! consensus rounds (via `slots`). //! - [Consensus](../srml_consensus/index.html): The Consensus module does not relate directly to Aura, @@ -51,11 +48,14 @@ pub use timestamp; use rstd::{result, prelude::*}; -use codec::Encode; -use srml_support::{decl_storage, decl_module, Parameter, storage::StorageValue, traits::Get}; -use app_crypto::AppPublic; +use codec::{Encode, Decode}; +use support::{ + decl_storage, decl_module, Parameter, traits::{Get, FindAuthor}, + ConsensusEngineId, +}; use sr_primitives::{ - traits::{SaturatedConversion, Saturating, Zero, One, Member, IsMember}, generic::DigestItem, + RuntimeAppPublic, + traits::{SaturatedConversion, Saturating, Zero, Member, IsMember}, generic::DigestItem, }; use timestamp::OnTimestampSet; #[cfg(feature = "std")] @@ -63,9 +63,7 @@ use timestamp::TimestampInherentData; use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; #[cfg(feature = "std")] use inherents::{InherentDataProviders, ProvideInherentData}; -use substrate_consensus_aura_primitives::{AURA_ENGINE_ID, ConsensusLog}; -#[cfg(feature = "std")] -use codec::Decode; +use substrate_consensus_aura_primitives::{AURA_ENGINE_ID, ConsensusLog, AuthorityIndex}; mod mock; mod tests; @@ -142,30 +140,22 @@ impl ProvideInherentData for InherentDataProvider { } } -/// Something that can handle Aura consensus reports. -pub trait HandleReport { - fn handle_report(report: AuraReport); -} - -impl HandleReport for () { - fn handle_report(_report: AuraReport) { } -} - pub trait Trait: timestamp::Trait { - /// The logic for handling reports. - type HandleReport: HandleReport; - /// The identifier type for an authority. - type AuthorityId: Member + Parameter + AppPublic + Default; + type AuthorityId: Member + Parameter + RuntimeAppPublic + Default; } decl_storage! { trait Store for Module as Aura { /// The last timestamp. - LastTimestamp get(last) build(|_| 0.into()): T::Moment; + LastTimestamp get(fn last) build(|_| 0.into()): T::Moment; /// The current authorities - pub Authorities get(authorities) config(): Vec; + pub Authorities get(fn authorities): Vec; + } + add_extra_genesis { + config(authorities): Vec; + build(|config| Module::::initialize_authorities(&config.authorities)) } } @@ -183,11 +173,29 @@ impl Module { ); >::deposit_log(log.into()); } + + fn initialize_authorities(authorities: &[T::AuthorityId]) { + if !authorities.is_empty() { + assert!(>::get().is_empty(), "Authorities are already initialized!"); + >::put(authorities); + } + } +} + +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; } impl session::OneSessionHandler for Module { type Key = T::AuthorityId; + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| k).collect::>(); + Self::initialize_authorities(&authorities); + } + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) where I: Iterator { @@ -200,16 +208,34 @@ impl session::OneSessionHandler for Module { } } } + fn on_disabled(i: usize) { let log: DigestItem = DigestItem::Consensus( AURA_ENGINE_ID, - ConsensusLog::::OnDisabled(i as u64).encode(), + ConsensusLog::::OnDisabled(i as AuthorityIndex).encode(), ); >::deposit_log(log.into()); } } +impl FindAuthor for Module { + fn find_author<'a, I>(digests: I) -> Option where + I: 'a + IntoIterator + { + for (id, mut data) in digests.into_iter() { + if id == AURA_ENGINE_ID { + if let Ok(slot_num) = u64::decode(&mut data) { + let author_index = slot_num % Self::authorities().len() as u64; + return Some(author_index as u32) + } + } + } + + None + } +} + impl IsMember for Module { fn is_member(authority_id: &T::AuthorityId) -> bool { Self::authorities() @@ -218,34 +244,6 @@ impl IsMember for Module { } } -/// A report of skipped authorities in Aura. -#[derive(Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct AuraReport { - // The first skipped slot. - start_slot: usize, - // The number of times authorities were skipped. - skipped: usize, -} - -impl AuraReport { - /// Call the closure with (`validator_indices`, `punishment_count`) for each - /// validator to punish. - pub fn punish(&self, validator_count: usize, mut punish_with: F) - where F: FnMut(usize, usize) - { - // If all validators have been skipped, then it implies some sort of - // systematic problem common to all rather than a minority of validators - // not fulfilling their specific duties. In this case, it doesn't make - // sense to punish anyone, so we guard against it. - if self.skipped < validator_count { - for index in 0..self.skipped { - punish_with((self.start_slot + index) % validator_count, 1); - } - } - } -} - impl Module { /// Determine the Aura slot-duration based on the Timestamp module configuration. pub fn slot_duration() -> T::Moment { @@ -254,9 +252,9 @@ impl Module { ::MinimumPeriod::get().saturating_mul(2.into()) } - fn on_timestamp_set(now: T::Moment, slot_duration: T::Moment) { + fn on_timestamp_set(now: T::Moment, slot_duration: T::Moment) { let last = Self::last(); - ::LastTimestamp::put(now.clone()); + ::LastTimestamp::put(now); if last.is_zero() { return; @@ -264,43 +262,18 @@ impl Module { assert!(!slot_duration.is_zero(), "Aura slot duration cannot be zero."); - let last_slot = last / slot_duration.clone(); - let first_skipped = last_slot.clone() + One::one(); + let last_slot = last / slot_duration; let cur_slot = now / slot_duration; assert!(last_slot < cur_slot, "Only one block may be authored per slot."); - if cur_slot == first_skipped { return } - - let skipped_slots = cur_slot - last_slot - One::one(); - H::handle_report(AuraReport { - start_slot: first_skipped.saturated_into::(), - skipped: skipped_slots.saturated_into::(), - }) + // TODO [#3398] Generate offence report for all authorities that skipped their slots. } } impl OnTimestampSet for Module { fn on_timestamp_set(moment: T::Moment) { - Self::on_timestamp_set::(moment, Self::slot_duration()) - } -} - -/// A type for performing slashing based on Aura reports. -pub struct StakingSlasher(::rstd::marker::PhantomData); - -impl HandleReport for StakingSlasher { - fn handle_report(report: AuraReport) { - use staking::SessionInterface; - let validators = T::SessionInterface::validators(); - - report.punish( - validators.len(), - |idx, slash_count| { - let v = validators[idx].clone(); - staking::Module::::on_offline_validator(v, slash_count); - } - ); + Self::on_timestamp_set(moment, Self::slot_duration()) } } diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index aac3f63f974ae7031d6aadaaa632ea2092cfe852..5c55e8bdd58dfbdbede54cdf3605cef317f88ebf 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -24,9 +24,9 @@ use sr_primitives::{ traits::IdentityLookup, Perbill, testing::{Header, UintAuthorityId}, }; -use srml_support::{impl_outer_origin, parameter_types}; +use support::{impl_outer_origin, parameter_types}; use runtime_io; -use primitives::{H256, Blake2Hasher}; +use primitives::H256; impl_outer_origin!{ pub enum Origin for Test {} @@ -54,12 +54,12 @@ impl system::Trait for Test { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } impl timestamp::Trait for Test { @@ -69,11 +69,10 @@ impl timestamp::Trait for Test { } impl Trait for Test { - type HandleReport = (); type AuthorityId = AuthorityId; } -pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities { +pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig::{ authorities: authorities.into_iter().map(|a| UintAuthorityId(a).to_public_key()).collect(), @@ -81,5 +80,4 @@ pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities; pub type Aura = Module; diff --git a/srml/aura/src/tests.rs b/srml/aura/src/tests.rs index 12deeb99a8d3e52e056c679e09eb79ac15d6714a..a90ec3a861e84f1d2ac1702efb315ff3fdd150f9 100644 --- a/srml/aura/src/tests.rs +++ b/srml/aura/src/tests.rs @@ -18,75 +18,12 @@ #![cfg(test)] -use lazy_static::lazy_static; -use crate::mock::{System, Aura, new_test_ext}; -use sr_primitives::traits::Header; -use runtime_io::with_externalities; -use parking_lot::Mutex; -use crate::{AuraReport, HandleReport}; +use crate::mock::{Aura, new_test_ext}; #[test] -fn aura_report_gets_skipped_correctly() { - let mut report = AuraReport { - start_slot: 3, - skipped: 15, - }; - - let mut validators = vec![0; 10]; - report.punish(10, |idx, count| validators[idx] += count); - assert_eq!(validators, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - - let mut validators = vec![0; 10]; - report.skipped = 5; - report.punish(10, |idx, count| validators[idx] += count); - assert_eq!(validators, vec![0, 0, 0, 1, 1, 1, 1, 1, 0, 0]); - - let mut validators = vec![0; 10]; - report.start_slot = 8; - report.punish(10, |idx, count| validators[idx] += count); - assert_eq!(validators, vec![1, 1, 1, 0, 0, 0, 0, 0, 1, 1]); - - let mut validators = vec![0; 4]; - report.start_slot = 1; - report.skipped = 3; - report.punish(4, |idx, count| validators[idx] += count); - assert_eq!(validators, vec![0, 1, 1, 1]); - - let mut validators = vec![0; 4]; - report.start_slot = 2; - report.punish(4, |idx, count| validators[idx] += count); - assert_eq!(validators, vec![1, 0, 1, 1]); -} - -#[test] -fn aura_reports_offline() { - lazy_static! { - static ref SLASH_COUNTS: Mutex> = Mutex::new(vec![0; 4]); - } - - struct HandleTestReport; - impl HandleReport for HandleTestReport { - fn handle_report(report: AuraReport) { - let mut counts = SLASH_COUNTS.lock(); - report.punish(counts.len(), |idx, count| counts[idx] += count); - } - } - - with_externalities(&mut new_test_ext(vec![0, 1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - let slot_duration = Aura::slot_duration(); - - Aura::on_timestamp_set::(5 * slot_duration, slot_duration); - let header = System::finalize(); - - // no slashing when last step was 0. - assert_eq!(SLASH_COUNTS.lock().as_slice(), &[0, 0, 0, 0]); - - System::initialize(&2, &header.hash(), &Default::default(), &Default::default()); - Aura::on_timestamp_set::(8 * slot_duration, slot_duration); - let _header = System::finalize(); - - // Steps 6 and 7 were skipped. - assert_eq!(SLASH_COUNTS.lock().as_slice(), &[0, 0, 1, 1]); +fn initial_values() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert_eq!(Aura::last(), 0u64); + assert_eq!(Aura::authorities().len(), 4); }); } diff --git a/srml/authority-discovery/Cargo.toml b/srml/authority-discovery/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..3968ab52aec6638aa6b03ce7edb756e2c042c900 --- /dev/null +++ b/srml/authority-discovery/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "srml-authority-discovery" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +serde = { version = "1.0.101", optional = true } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +session = { package = "srml-session", path = "../session", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "app-crypto/std", + "codec/std", + "primitives/std", + "rstd/std", + "runtime-io/std", + "serde", + "session/std", + "sr-primitives/std", + "support/std", + "system/std", +] diff --git a/srml/authority-discovery/src/lib.rs b/srml/authority-discovery/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..8c2951f3acbccf2de15a025d7123f73c5542cd34 --- /dev/null +++ b/srml/authority-discovery/src/lib.rs @@ -0,0 +1,362 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Authority discovery module. +//! +//! This module is used by the `core/authority-discovery` to retrieve the +//! current set of authorities, learn its own authority id as well as sign and +//! verify messages to and from other authorities. +//! +//! ## Dependencies +//! +//! This module depends on an externally defined session key type, specified via +//! `Trait::AuthorityId` in the respective node runtime implementation. + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use app_crypto::RuntimeAppPublic; +use codec::FullCodec; +use rstd::prelude::*; +use support::{decl_module, decl_storage}; + +/// The module's config trait. +pub trait Trait: system::Trait + session::Trait { + type AuthorityId: RuntimeAppPublic + Default + FullCodec + PartialEq; +} + +decl_storage! { + trait Store for Module as AuthorityDiscovery { + /// The current set of keys that may issue a heartbeat. + Keys get(fn keys): Vec; + } + add_extra_genesis { + config(keys): Vec; + build(|config| Module::::initialize_keys(&config.keys)) + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + } +} + +impl Module { + /// Returns own authority identifier iff it is part of the current authority + /// set, otherwise this function returns None. The restriction might be + /// softened in the future in case a consumer needs to learn own authority + /// identifier. + fn authority_id() -> Option { + let authorities = Keys::::get(); + + let local_keys = T::AuthorityId::all(); + + authorities.into_iter().find_map(|authority| { + if local_keys.contains(&authority) { + Some(authority) + } else { + None + } + }) + } + + /// Retrieve authority identifiers of the current authority set. + pub fn authorities() -> Vec { + Keys::::get() + } + + /// Sign the given payload with the private key corresponding to the given authority id. + pub fn sign( + payload: &Vec, + ) -> Option<( + <::AuthorityId as RuntimeAppPublic>::Signature, + T::AuthorityId, + )> { + let authority_id = Module::::authority_id()?; + authority_id.sign(payload).map(|s| (s, authority_id)) + } + + /// Verify the given signature for the given payload with the given + /// authority identifier. + pub fn verify( + payload: &Vec, + signature: <::AuthorityId as RuntimeAppPublic>::Signature, + authority_id: T::AuthorityId, + ) -> bool { + authority_id.verify(payload, &signature) + } + + fn initialize_keys(keys: &[T::AuthorityId]) { + if !keys.is_empty() { + assert!(Keys::::get().is_empty(), "Keys are already initialized!"); + Keys::::put(keys); + } + } +} + +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; +} + +impl session::OneSessionHandler for Module { + type Key = T::AuthorityId; + + fn on_genesis_session<'a, I: 'a>(validators: I) + where + I: Iterator, + { + let keys = validators.map(|x| x.1).collect::>(); + Self::initialize_keys(&keys); + } + + fn on_new_session<'a, I: 'a>(_changed: bool, _validators: I, next_validators: I) + where + I: Iterator, + { + // Remember who the authorities are for the new session. + Keys::::put(next_validators.map(|x| x.1).collect::>()); + } + + fn on_disabled(_i: usize) { + // ignore + } +} + +#[cfg(test)] +mod tests { + use super::*; + use app_crypto::Pair; + use primitives::{testing::KeyStore, crypto::key_types, sr25519, H256, traits::KeystoreExt}; + use runtime_io::TestExternalities; + use sr_primitives::{ + testing::{Header, UintAuthorityId}, traits::{ConvertInto, IdentityLookup, OpaqueKeys}, + Perbill, KeyTypeId, + }; + use support::{impl_outer_origin, parameter_types}; + + type AuthorityDiscovery = Module; + type SessionIndex = u32; + + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + impl Trait for Test { + type AuthorityId = babe_primitives::AuthorityId; + } + + type AuthorityId = babe_primitives::AuthorityId; + + pub struct TestOnSessionEnding; + impl session::OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { + None + } + } + + parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); + } + + impl session::Trait for Test { + type OnSessionEnding = TestOnSessionEnding; + type Keys = UintAuthorityId; + type ShouldEndSession = session::PeriodicSessions; + type SessionHandler = TestSessionHandler; + type Event = (); + type ValidatorId = AuthorityId; + type ValidatorIdOf = ConvertInto; + type SelectInitialValidators = (); + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; + } + + impl session::historical::Trait for Test { + type FullIdentification = (); + type FullIdentificationOf = (); + } + + pub type BlockNumber = u64; + + parameter_types! { + pub const Period: BlockNumber = 1; + pub const Offset: BlockNumber = 0; + pub const UncleGenerations: u64 = 0; + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = BlockNumber; + type Call = (); + type Hash = H256; + type Hashing = ::sr_primitives::traits::BlakeTwo256; + type AccountId = AuthorityId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + } + + impl_outer_origin! { + pub enum Origin for Test {} + } + + pub struct TestSessionHandler; + impl session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[key_types::DUMMY]; + + fn on_new_session( + _changed: bool, + _validators: &[(AuthorityId, Ks)], + _queued_validators: &[(AuthorityId, Ks)], + ) { + } + + fn on_disabled(_validator_index: usize) {} + + fn on_genesis_session(_validators: &[(AuthorityId, Ks)]) {} + } + + #[test] + fn authority_id_fn_returns_intersection_of_current_authorities_and_keys_in_key_store() { + // Create keystore and generate key. + let key_store = KeyStore::new(); + key_store + .write() + .sr25519_generate_new(key_types::BABE, None) + .expect("Generates key."); + + // Retrieve key to later check if we got the right one. + let public_key = key_store + .read() + .sr25519_public_keys(key_types::BABE) + .pop() + .unwrap(); + let authority_id = AuthorityId::from(public_key); + + // Build genesis. + let mut t = system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + GenesisConfig:: { + keys: vec![authority_id.clone()], + } + .assimilate_storage(&mut t) + .unwrap(); + + // Create externalities. + let mut externalities = TestExternalities::new(t); + externalities.register_extension(KeystoreExt(key_store)); + + externalities.execute_with(|| { + assert_eq!( + authority_id, + AuthorityDiscovery::authority_id().expect("Retrieving public key.") + ); + }); + } + + #[test] + fn authority_id_fn_does_not_return_key_outside_current_authority_set() { + // Create keystore and generate key. + let key_store = KeyStore::new(); + key_store + .write() + .sr25519_generate_new(key_types::BABE, None) + .expect("Generates key."); + + // Build genesis. + let mut t = system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + // Generate random authority set. + let keys = vec![(); 5] + .iter() + .map(|_x| sr25519::Pair::generate_with_phrase(None).0.public()) + .map(AuthorityId::from) + .collect(); + + GenesisConfig:: { keys: keys } + .assimilate_storage(&mut t) + .unwrap(); + + // Create externalities. + let mut externalities = TestExternalities::new(t); + externalities.register_extension(KeystoreExt(key_store)); + + externalities.execute_with(|| { + assert_eq!(None, AuthorityDiscovery::authority_id()); + }); + } + + #[test] + fn sign_and_verify_workflow() { + // Create keystore and generate key. + let key_store = KeyStore::new(); + key_store + .write() + .sr25519_generate_new(key_types::BABE, None) + .expect("Generates key."); + + // Retrieve key to later check if we got the right one. + let public_key = key_store + .read() + .sr25519_public_keys(key_types::BABE) + .pop() + .unwrap(); + let authority_id = AuthorityId::from(public_key); + + // Build genesis. + let mut t = system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + GenesisConfig:: { + keys: vec![authority_id.clone()], + } + .assimilate_storage(&mut t) + .unwrap(); + + // Create externalities. + let mut externalities = TestExternalities::new(t); + externalities.register_extension(KeystoreExt(key_store)); + + externalities.execute_with(|| { + let payload = String::from("test payload").into_bytes(); + let (sig, authority_id) = AuthorityDiscovery::sign(&payload).expect("signature"); + + assert!(AuthorityDiscovery::verify( + &payload, + sig.clone(), + authority_id.clone(), + )); + + assert!(!AuthorityDiscovery::verify( + &String::from("other payload").into_bytes(), + sig, + authority_id, + )) + }); + } +} diff --git a/srml/authorship/Cargo.toml b/srml/authorship/Cargo.toml index e7f7b0941b6a293693dff357de98722778c5cead..a59976c69909656deb8e0f31aee178d49ff8ec68 100644 --- a/srml/authorship/Cargo.toml +++ b/srml/authorship/Cargo.toml @@ -11,9 +11,10 @@ codec = { package = "parity-scale-codec", version = "1.0.0", default-features = inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } +impl-trait-for-tuples = "0.1.3" [features] default = ["std"] @@ -23,7 +24,7 @@ std = [ "inherents/std", "sr-primitives/std", "rstd/std", - "srml-support/std", + "support/std", "system/std", - "runtime_io/std", + "runtime-io/std", ] diff --git a/srml/authorship/src/lib.rs b/srml/authorship/src/lib.rs index 32dd140e82ff57fe5d63c10f583066ba78d5b9f2..173af5f729cbb8df5b306e40916b01eb6f38a71b 100644 --- a/srml/authorship/src/lib.rs +++ b/srml/authorship/src/lib.rs @@ -22,12 +22,12 @@ use rstd::{result, prelude::*}; use rstd::collections::btree_set::BTreeSet; -use srml_support::{decl_module, decl_storage, for_each_tuple, StorageValue}; -use srml_support::traits::{FindAuthor, VerifySeal, Get}; -use srml_support::dispatch::Result as DispatchResult; +use support::{decl_module, decl_storage}; +use support::traits::{FindAuthor, VerifySeal, Get}; +use support::dispatch::Result as DispatchResult; use codec::{Encode, Decode}; use system::ensure_none; -use sr_primitives::traits::{SimpleArithmetic, Header as HeaderT, One, Zero}; +use sr_primitives::traits::{Header as HeaderT, One, Zero}; use sr_primitives::weights::SimpleDispatchInfo; use inherents::{ RuntimeString, InherentIdentifier, ProvideInherent, @@ -112,6 +112,7 @@ pub trait Trait: system::Trait { /// An event handler for the authorship module. There is a dummy implementation /// for `()`, which does nothing. +#[impl_trait_for_tuples::impl_for_tuples(30)] pub trait EventHandler { /// Note that the given account ID is the author of the current block. fn note_author(author: Author); @@ -121,30 +122,6 @@ pub trait EventHandler { fn note_uncle(author: Author, age: BlockNumber); } -macro_rules! impl_event_handler { - () => ( - impl EventHandler for () { - fn note_author(_author: A) { } - fn note_uncle(_author: A, _age: B) { } - } - ); - - ( $($t:ident)* ) => { - impl),*> - EventHandler for ($($t,)*) - { - fn note_author(author: Author) { - $($t::note_author(author.clone());)* - } - fn note_uncle(author: Author, age: BlockNumber) { - $($t::note_uncle(author.clone(), age.clone());)* - } - } - } -} - -for_each_tuple!(impl_event_handler); - /// Additional filtering on uncles that pass preliminary ancestry checks. /// /// This should do work such as checking seals @@ -218,8 +195,8 @@ where } } -#[derive(Encode, Decode)] -#[cfg_attr(any(feature = "std", test), derive(PartialEq, Debug))] +#[derive(Encode, Decode, sr_primitives::RuntimeDebug)] +#[cfg_attr(any(feature = "std", test), derive(PartialEq))] enum UncleEntryItem { InclusionHeight(BlockNumber), Uncle(Hash, Option), @@ -236,29 +213,14 @@ decl_storage! { } } -fn prune_old_uncles( - minimum_height: BlockNumber, - uncles: &mut Vec> -) where BlockNumber: SimpleArithmetic { - let prune_entries = uncles.iter().take_while(|item| match item { - UncleEntryItem::Uncle(_, _) => true, - UncleEntryItem::InclusionHeight(height) => height < &minimum_height, - }); - let prune_index = prune_entries.count(); - - let _ = uncles.drain(..prune_index); -} - decl_module! { pub struct Module for enum Call where origin: T::Origin { fn on_initialize(now: T::BlockNumber) { let uncle_generations = T::UncleGenerations::get(); - let mut uncles = ::Uncles::get(); - // prune uncles that are older than the allowed number of generations. if uncle_generations <= now { let minimum_height = now - uncle_generations; - prune_old_uncles(minimum_height, &mut uncles) + Self::prune_old_uncles(minimum_height) } ::DidSetUncles::put(false); @@ -387,6 +349,18 @@ impl Module { // check uncle validity. T::FilterUncle::filter_uncle(&uncle, accumulator) } + + fn prune_old_uncles(minimum_height: T::BlockNumber) { + let mut uncles = ::Uncles::get(); + let prune_entries = uncles.iter().take_while(|item| match item { + UncleEntryItem::Uncle(_, _) => true, + UncleEntryItem::InclusionHeight(height) => height < &minimum_height, + }); + let prune_index = prune_entries.count(); + + let _ = uncles.drain(..prune_index); + ::Uncles::put(uncles); + } } impl ProvideInherent for Module { @@ -438,13 +412,11 @@ impl ProvideInherent for Module { #[cfg(test)] mod tests { use super::*; - use runtime_io::with_externalities; - use primitives::{H256, Blake2Hasher}; - use sr_primitives::traits::{BlakeTwo256, IdentityLookup}; - use sr_primitives::testing::Header; - use sr_primitives::generic::DigestItem; - use sr_primitives::Perbill; - use srml_support::{parameter_types, impl_outer_origin, ConsensusEngineId}; + use primitives::H256; + use sr_primitives::{ + traits::{BlakeTwo256, IdentityLookup}, testing::Header, generic::DigestItem, Perbill, + }; + use support::{parameter_types, impl_outer_origin, ConsensusEngineId}; impl_outer_origin!{ pub enum Origin for Test {} @@ -470,12 +442,12 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } parameter_types! { @@ -560,7 +532,7 @@ mod tests { ) } - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { let t = system::GenesisConfig::default().build_storage::().unwrap(); t.into() } @@ -568,20 +540,26 @@ mod tests { #[test] fn prune_old_uncles_works() { use UncleEntryItem::*; - let mut uncles = vec![ - InclusionHeight(1u32), Uncle((), Some(())), Uncle((), None), Uncle((), None), - InclusionHeight(2u32), Uncle((), None), - InclusionHeight(3u32), Uncle((), None), - ]; - - prune_old_uncles(3, &mut uncles); - - assert_eq!(uncles, vec![InclusionHeight(3), Uncle((), None)]); + new_test_ext().execute_with(|| { + let hash = Default::default(); + let author = Default::default(); + let uncles = vec![ + InclusionHeight(1u64), Uncle(hash, Some(author)), Uncle(hash, None), Uncle(hash, None), + InclusionHeight(2u64), Uncle(hash, None), + InclusionHeight(3u64), Uncle(hash, None), + ]; + + ::Uncles::put(uncles); + Authorship::prune_old_uncles(3); + + let uncles = ::Uncles::get(); + assert_eq!(uncles, vec![InclusionHeight(3u64), Uncle(hash, None)]); + }) } #[test] fn rejects_bad_uncles() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let author_a = 69; struct CanonChain { @@ -694,7 +672,7 @@ mod tests { #[test] fn sets_author_lazily() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let author = 42; let mut header = seal_header( create_header(1, Default::default(), [1; 32].into()), diff --git a/srml/babe/Cargo.toml b/srml/babe/Cargo.toml index 76bd849a95594d79b3e9920a3caf8aae40421bc5..dc82906650bef2db9a405e0fd753ad16620b8bb6 100644 --- a/srml/babe/Cargo.toml +++ b/srml/babe/Cargo.toml @@ -5,24 +5,26 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -hex-literal = "0.2" +hex-literal = "0.2.1" codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.93", optional = true } +serde = { version = "1.0.101", optional = true } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -staking = { package = "srml-staking", path = "../staking", default-features = false } -srml-support = { path = "../support", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } session = { package = "srml-session", path = "../session", default-features = false } babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false, features = [ "wasm-nice-panic-message" ] } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } [dev-dependencies] -lazy_static = "1.3.0" +lazy_static = "1.4.0" parking_lot = "0.9.0" +sr-version = { path = "../../core/sr-version", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives" } +test-runtime = { package = "substrate-test-runtime", path = "../../core/test-runtime" } [features] default = ["std"] @@ -30,13 +32,13 @@ std = [ "serde", "codec/std", "rstd/std", - "srml-support/std", + "support/std", "sr-primitives/std", + "sr-staking-primitives/std", "system/std", "timestamp/std", "inherents/std", "babe-primitives/std", "session/std", - "runtime_io/std", - "staking/std", + "runtime-io/std", ] diff --git a/srml/babe/src/lib.rs b/srml/babe/src/lib.rs index 02099aace84e4c16047631d466019734e9326cd1..e12e123daf6f265a5cb921e5857e0a00eecce33a 100644 --- a/srml/babe/src/lib.rs +++ b/srml/babe/src/lib.rs @@ -14,27 +14,41 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Consensus extension module for BABE consensus. +//! Consensus extension module for BABE consensus. Collects on-chain randomness +//! from VRF outputs and manages epoch transitions. #![cfg_attr(not(feature = "std"), no_std)] -#![forbid(unused_must_use, unsafe_code, unused_variables, dead_code)] - +#![forbid(unused_must_use, unsafe_code, unused_variables, unused_must_use)] +#![deny(unused_imports)] pub use timestamp; use rstd::{result, prelude::*}; -use srml_support::{decl_storage, decl_module, StorageValue, StorageMap, traits::FindAuthor, traits::Get}; -use timestamp::{OnTimestampSet}; -use sr_primitives::{generic::DigestItem, ConsensusEngineId}; -use sr_primitives::traits::{IsMember, SaturatedConversion, Saturating, RandomnessBeacon, Convert}; +use support::{decl_storage, decl_module, traits::FindAuthor, traits::Get}; +use timestamp::OnTimestampSet; +use sr_primitives::{generic::DigestItem, ConsensusEngineId, Perbill}; +use sr_primitives::traits::{IsMember, SaturatedConversion, Saturating, RandomnessBeacon}; +use sr_staking_primitives::{ + SessionIndex, + offence::{Offence, Kind}, +}; #[cfg(feature = "std")] use timestamp::TimestampInherentData; use codec::{Encode, Decode}; use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; #[cfg(feature = "std")] use inherents::{InherentDataProviders, ProvideInherentData}; -use babe_primitives::{BABE_ENGINE_ID, ConsensusLog, BabeWeight, Epoch, RawBabePreDigest}; +use babe_primitives::{ + BABE_ENGINE_ID, ConsensusLog, BabeAuthorityWeight, NextEpochDescriptor, RawBabePreDigest, + SlotNumber, +}; pub use babe_primitives::{AuthorityId, VRF_OUTPUT_LENGTH, PUBLIC_KEY_LENGTH}; +#[cfg(all(feature = "std", test))] +mod tests; + +#[cfg(all(feature = "std", test))] +mod mock; + /// The BABE inherent identifier. pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot"; @@ -108,8 +122,52 @@ impl ProvideInherentData for InherentDataProvider { } pub trait Trait: timestamp::Trait { - type EpochDuration: Get; + /// The amount of time, in slots, that each epoch should last. + type EpochDuration: Get; + + /// The expected average block time at which BABE should be creating + /// blocks. Since BABE is probabilistic it is not trivial to figure out + /// what the expected average block time should be based on the slot + /// duration and the security parameter `c` (where `1 - c` represents + /// the probability of a slot being empty). type ExpectedBlockTime: Get; + + /// BABE requires some logic to be triggered on every block to query for whether an epoch + /// has ended and to perform the transition to the next epoch. + /// + /// Typically, the `ExternalTrigger` type should be used. An internal trigger should only be used + /// when no other module is responsible for changing authority set. + type EpochChangeTrigger: EpochChangeTrigger; +} + +/// Trigger an epoch change, if any should take place. +pub trait EpochChangeTrigger { + /// Trigger an epoch change, if any should take place. This should be called + /// during every block, after initialization is done. + fn trigger(now: T::BlockNumber); +} + +/// A type signifying to BABE that an external trigger +/// for epoch changes (e.g. srml-session) is used. +pub struct ExternalTrigger; + +impl EpochChangeTrigger for ExternalTrigger { + fn trigger(_: T::BlockNumber) { } // nothing - trigger is external. +} + +/// A type signifying to BABE that it should perform epoch changes +/// with an internal trigger, recycling the same authorities forever. +pub struct SameAuthoritiesForever; + +impl EpochChangeTrigger for SameAuthoritiesForever { + fn trigger(now: T::BlockNumber) { + if >::should_epoch_change(now) { + let authorities = >::authorities(); + let next_authorities = authorities.clone(); + + >::enact_epoch_change(authorities, next_authorities); + } + } } /// The length of the BABE randomness @@ -117,21 +175,22 @@ pub const RANDOMNESS_LENGTH: usize = 32; const UNDER_CONSTRUCTION_SEGMENT_LENGTH: usize = 256; +type MaybeVrf = Option<[u8; 32 /* VRF_OUTPUT_LENGTH */]>; + decl_storage! { trait Store for Module as Babe { /// Current epoch index. - pub EpochIndex get(epoch_index): u64; + pub EpochIndex get(fn epoch_index): u64; /// Current epoch authorities. - pub Authorities get(authorities) config(): Vec<(AuthorityId, BabeWeight)>; + pub Authorities get(fn authorities): Vec<(AuthorityId, BabeAuthorityWeight)>; - /// Slot at which the current epoch started. It is possible that no - /// block was authored at the given slot and the epoch change was - /// signalled later than this. - pub EpochStartSlot get(epoch_start_slot): u64; + /// The slot at which the first epoch actually started. This is 0 + /// until the first block of the chain. + pub GenesisSlot get(fn genesis_slot): u64; /// Current slot number. - pub CurrentSlot get(current_slot): u64; + pub CurrentSlot get(fn current_slot): u64; /// The epoch randomness for the *current* epoch. /// @@ -146,7 +205,7 @@ decl_storage! { // NOTE: the following fields don't use the constants to define the // array size because the metadata API currently doesn't resolve the // variable to its underlying value. - pub Randomness get(randomness): [u8; 32 /* RANDOMNESS_LENGTH */]; + pub Randomness get(fn randomness): [u8; 32 /* RANDOMNESS_LENGTH */]; /// Next epoch randomness. NextRandomness: [u8; 32 /* RANDOMNESS_LENGTH */]; @@ -162,6 +221,14 @@ decl_storage! { /// epoch. SegmentIndex build(|_| 0): u32; UnderConstruction: map u32 => Vec<[u8; 32 /* VRF_OUTPUT_LENGTH */]>; + + /// Temporary value (cleared at block finalization) which is `Some` + /// if per-block initialization has already been called for current block. + Initialized get(fn initialized): Option; + } + add_extra_genesis { + config(authorities): Vec<(AuthorityId, BabeAuthorityWeight)>; + build(|config| Module::::initialize_authorities(&config.authorities)) } } @@ -180,25 +247,19 @@ decl_module! { const ExpectedBlockTime: T::Moment = T::ExpectedBlockTime::get(); /// Initialization - fn on_initialize() { - for digest in Self::get_inherent_digests() - .logs - .iter() - .filter_map(|s| s.as_pre_runtime()) - .filter_map(|(id, mut data)| if id == BABE_ENGINE_ID { - RawBabePreDigest::decode(&mut data).ok() - } else { - None - }) - { - if EpochStartSlot::get() == 0 { - EpochStartSlot::put(digest.slot_number); - } - - CurrentSlot::put(digest.slot_number); - Self::deposit_vrf_output(&digest.vrf_output); - - return; + fn on_initialize(now: T::BlockNumber) { + Self::do_initialize(now); + } + + /// Block finalization + fn on_finalize() { + // at the end of the block, we can safely include the new VRF output + // from this block into the under-construction randomness. If we've determined + // that this block was the first in a new epoch, the changeover logic has + // already occurred at this point, so the under-construction randomness + // will only contain outputs from the right epoch. + if let Some(Some(vrf_output)) = Initialized::take() { + Self::deposit_vrf_output(&vrf_output); } } } @@ -219,9 +280,16 @@ impl FindAuthor for Module { { for (id, mut data) in digests.into_iter() { if id == BABE_ENGINE_ID { - return Some(RawBabePreDigest::decode(&mut data).ok()?.authority_index); + let pre_digest = RawBabePreDigest::decode(&mut data).ok()?; + return Some(match pre_digest { + RawBabePreDigest::Primary { authority_index, .. } => + authority_index, + RawBabePreDigest::Secondary { authority_index, .. } => + authority_index, + }); } } + return None; } } @@ -235,9 +303,61 @@ impl IsMember for Module { } impl session::ShouldEndSession for Module { - fn should_end_session(_: T::BlockNumber) -> bool { - let diff = CurrentSlot::get().saturating_sub(EpochStartSlot::get()); - diff >= T::EpochDuration::get() + fn should_end_session(now: T::BlockNumber) -> bool { + // it might be (and it is in current implementation) that session module is calling + // should_end_session() from it's own on_initialize() handler + // => because session on_initialize() is called earlier than ours, let's ensure + // that we have synced with digest before checking if session should be ended. + Self::do_initialize(now); + + Self::should_epoch_change(now) + } +} + +// TODO [slashing]: @marcio use this, remove the dead_code annotation. +/// A BABE equivocation offence report. +/// +/// When a validator released two or more blocks at the same slot. +#[allow(dead_code)] +struct BabeEquivocationOffence { + /// A babe slot number in which this incident happened. + slot: u64, + /// The session index in which the incident happened. + session_index: SessionIndex, + /// The size of the validator set at the time of the offence. + validator_set_count: u32, + /// The authority that produced the equivocation. + offender: FullIdentification, +} + +impl Offence for BabeEquivocationOffence { + const ID: Kind = *b"babe:equivocatio"; + type TimeSlot = u64; + + fn offenders(&self) -> Vec { + vec![self.offender.clone()] + } + + fn session_index(&self) -> SessionIndex { + self.session_index + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> Self::TimeSlot { + self.slot + } + + fn slash_fraction( + offenders_count: u32, + validator_set_count: u32, + ) -> Perbill { + // the formula is min((3k / n)^2, 1) + let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count); + // _ ^ 2 + x.square() } } @@ -249,15 +369,81 @@ impl Module { ::MinimumPeriod::get().saturating_mul(2.into()) } + /// Determine whether an epoch change should take place at this block. + /// Assumes that initialization has already taken place. + pub fn should_epoch_change(now: T::BlockNumber) -> bool { + // The epoch has technically ended during the passage of time + // between this block and the last, but we have to "end" the epoch now, + // since there is no earlier possible block we could have done it. + // + // The exception is for block 1: the genesis has slot 0, so we treat + // epoch 0 as having started at the slot of block 1. We want to use + // the same randomness and validator set as signalled in the genesis, + // so we don't rotate the epoch. + now != sr_primitives::traits::One::one() && { + let diff = CurrentSlot::get().saturating_sub(Self::current_epoch_start()); + diff >= T::EpochDuration::get() + } + } + + /// DANGEROUS: Enact an epoch change. Should be done on every block where `should_epoch_change` has returned `true`, + /// and the caller is the only caller of this function. + /// + /// Typically, this is not handled directly by the user, but by higher-level validator-set manager logic like + /// `srml-session`. + pub fn enact_epoch_change( + authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + next_authorities: Vec<(AuthorityId, BabeAuthorityWeight)>, + ) { + // PRECONDITION: caller has done initialization and is guaranteed + // by the session module to be called before this. + #[cfg(debug_assertions)] + { + assert!(Self::initialized().is_some()) + } + + // Update epoch index + let epoch_index = EpochIndex::get() + .checked_add(1) + .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); + + EpochIndex::put(epoch_index); + Authorities::put(authorities); + + // Update epoch randomness. + let next_epoch_index = epoch_index + .checked_add(1) + .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); + + // Returns randomness for the current epoch and computes the *next* + // epoch randomness. + let randomness = Self::randomness_change_epoch(next_epoch_index); + Randomness::put(randomness); + + // After we update the current epoch, we signal the *next* epoch change + // so that nodes can track changes. + let next_randomness = NextRandomness::get(); + + let next = NextEpochDescriptor { + authorities: next_authorities, + randomness: next_randomness, + }; + + Self::deposit_consensus(ConsensusLog::NextEpochData(next)) + } + + // finds the start slot of the current epoch. only guaranteed to + // give correct results after `do_initialize` of the first block + // in the chain (as its result is based off of `GenesisSlot`). + fn current_epoch_start() -> SlotNumber { + (EpochIndex::get() * T::EpochDuration::get()) + GenesisSlot::get() + } + fn deposit_consensus(new: U) { let log: DigestItem = DigestItem::Consensus(BABE_ENGINE_ID, new.encode()); >::deposit_log(log.into()) } - fn get_inherent_digests() -> system::DigestOf { - >::digest() - } - fn deposit_vrf_output(vrf_output: &[u8; VRF_OUTPUT_LENGTH]) { let segment_idx = ::get(); let mut segment = ::get(&segment_idx); @@ -268,11 +454,67 @@ impl Module { } else { // move onto the next segment and update the index. let segment_idx = segment_idx + 1; - ::insert(&segment_idx, vec![*vrf_output].as_ref()); + ::insert(&segment_idx, &vec![*vrf_output]); ::put(&segment_idx); } } + fn do_initialize(now: T::BlockNumber) { + // since do_initialize can be called twice (if session module is present) + // => let's ensure that we only modify the storage once per block + let initialized = Self::initialized().is_some(); + if initialized { + return; + } + + let maybe_pre_digest = >::digest() + .logs + .iter() + .filter_map(|s| s.as_pre_runtime()) + .filter_map(|(id, mut data)| if id == BABE_ENGINE_ID { + RawBabePreDigest::decode(&mut data).ok() + } else { + None + }) + .next(); + + let maybe_vrf = maybe_pre_digest.and_then(|digest| { + // on the first non-zero block (i.e. block #1) + // this is where the first epoch (epoch #0) actually starts. + // we need to adjust internal storage accordingly. + if GenesisSlot::get() == 0 { + GenesisSlot::put(digest.slot_number()); + debug_assert_ne!(GenesisSlot::get(), 0); + + // deposit a log because this is the first block in epoch #0 + // we use the same values as genesis because we haven't collected any + // randomness yet. + let next = NextEpochDescriptor { + authorities: Self::authorities(), + randomness: Self::randomness(), + }; + + Self::deposit_consensus(ConsensusLog::NextEpochData(next)) + } + + CurrentSlot::put(digest.slot_number()); + + if let RawBabePreDigest::Primary { vrf_output, .. } = digest { + // place the VRF output into the `Initialized` storage item + // and it'll be put onto the under-construction randomness + // later, once we've decided which epoch this block is in. + Some(vrf_output) + } else { + None + } + }); + + Initialized::put(maybe_vrf); + + // enact epoch change, if necessary. + T::EpochChangeTrigger::trigger::(now) + } + /// Call this function exactly once when an epoch changes, to update the /// randomness. Returns the new randomness. fn randomness_change_epoch(next_epoch_index: u64) -> [u8; RANDOMNESS_LENGTH] { @@ -292,79 +534,44 @@ impl Module { this_randomness } + fn initialize_authorities(authorities: &[(AuthorityId, BabeAuthorityWeight)]) { + if !authorities.is_empty() { + assert!(Authorities::get().is_empty(), "Authorities are already initialized!"); + Authorities::put(authorities); + } + } } impl OnTimestampSet for Module { fn on_timestamp_set(_moment: T::Moment) { } } -impl session::OneSessionHandler for Module { +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = AuthorityId; +} + +impl session::OneSessionHandler for Module { type Key = AuthorityId; - fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, queued_validators: I) + + fn on_genesis_session<'a, I: 'a>(validators: I) where I: Iterator { - use staking::BalanceOf; - let to_votes = |b: BalanceOf| { - , u64>>::convert(b) - }; - - // Update epoch index - let epoch_index = EpochIndex::get() - .checked_add(1) - .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); - - EpochIndex::put(epoch_index); + let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + Self::initialize_authorities(&authorities); + } - // Update authorities. - let authorities = validators.map(|(account, k)| { - (k, to_votes(staking::Module::::stakers(account).total)) + fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, queued_validators: I) + where I: Iterator + { + let authorities = validators.map(|(_account, k)| { + (k, 1) }).collect::>(); - Authorities::put(authorities); - - // Update epoch start slot. - let now = CurrentSlot::get(); - EpochStartSlot::mutate(|previous| { - loop { - // on the first epoch we must account for skipping at least one - // whole epoch, in case the first block is authored with a slot - // number far in the past. - if now.saturating_sub(*previous) < T::EpochDuration::get() { - break; - } - - *previous = previous.saturating_add(T::EpochDuration::get()); - } - }); - - // Update epoch randomness. - let next_epoch_index = epoch_index - .checked_add(1) - .expect("epoch indices will never reach 2^64 before the death of the universe; qed"); - - // Returns randomness for the current epoch and computes the *next* - // epoch randomness. - let randomness = Self::randomness_change_epoch(next_epoch_index); - Randomness::put(randomness); - - // After we update the current epoch, we signal the *next* epoch change - // so that nodes can track changes. - let next_authorities = queued_validators.map(|(account, k)| { - (k, to_votes(staking::Module::::stakers(account).total)) + let next_authorities = queued_validators.map(|(_account, k)| { + (k, 1) }).collect::>(); - let next_epoch_start_slot = EpochStartSlot::get().saturating_add(T::EpochDuration::get()); - let next_randomness = NextRandomness::get(); - - let next = Epoch { - epoch_index: next_epoch_index, - start_slot: next_epoch_start_slot, - duration: T::EpochDuration::get(), - authorities: next_authorities, - randomness: next_randomness, - }; - - Self::deposit_consensus(ConsensusLog::NextEpochData(next)) + Self::enact_epoch_change(authorities, next_authorities) } fn on_disabled(i: usize) { diff --git a/srml/babe/src/mock.rs b/srml/babe/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..d7aed7b42a3fe27e513ec7276ea3e1ccecd4d2d8 --- /dev/null +++ b/srml/babe/src/mock.rs @@ -0,0 +1,109 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities +#![allow(dead_code, unused_imports)] + +use super::{Trait, Module, GenesisConfig}; +use babe_primitives::AuthorityId; +use sr_primitives::{ + traits::IdentityLookup, Perbill, testing::{Header, UintAuthorityId}, impl_opaque_keys, +}; +use sr_version::RuntimeVersion; +use support::{impl_outer_origin, parameter_types}; +use runtime_io; +use primitives::{H256, Blake2Hasher}; + +impl_outer_origin!{ + pub enum Origin for Test {} +} + +type DummyValidatorId = u64; + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Test; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const MinimumPeriod: u64 = 1; + pub const EpochDuration: u64 = 3; + pub const ExpectedBlockTime: u64 = 1; + pub const Version: RuntimeVersion = test_runtime::VERSION; + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(16); +} + +impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Version = Version; + type Hashing = sr_primitives::traits::BlakeTwo256; + type AccountId = DummyValidatorId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; +} + +impl_opaque_keys! { + pub struct MockSessionKeys { + pub dummy: UintAuthorityId, + } +} + +impl session::Trait for Test { + type Event = (); + type ValidatorId = ::AccountId; + type ShouldEndSession = Babe; + type SessionHandler = (Babe,Babe,); + type OnSessionEnding = (); + type ValidatorIdOf = (); + type SelectInitialValidators = (); + type Keys = MockSessionKeys; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +impl timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = Babe; + type MinimumPeriod = MinimumPeriod; +} + +impl Trait for Test { + type EpochDuration = EpochDuration; + type ExpectedBlockTime = ExpectedBlockTime; + type EpochChangeTrigger = crate::ExternalTrigger; +} + +pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig { + authorities: authorities.into_iter().map(|a| (UintAuthorityId(a).to_public_key(), 1)).collect(), + }.assimilate_storage::(&mut t).unwrap(); + t.into() +} + +pub type System = system::Module; +pub type Babe = Module; diff --git a/srml/babe/src/tests.rs b/srml/babe/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..f860375de487a646cf7ed89efec13bb9a859d0ef --- /dev/null +++ b/srml/babe/src/tests.rs @@ -0,0 +1,126 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Consensus extension module tests for BABE consensus. + +use super::*; +use mock::{new_test_ext, Babe, Test}; +use sr_primitives::{traits::OnFinalize, testing::{Digest, DigestItem}}; +use session::ShouldEndSession; + +const EMPTY_RANDOMNESS: [u8; 32] = [ + 74, 25, 49, 128, 53, 97, 244, 49, + 222, 202, 176, 2, 231, 66, 95, 10, + 133, 49, 213, 228, 86, 161, 164, 127, + 217, 153, 138, 37, 48, 192, 248, 0, +]; + +fn make_pre_digest( + authority_index: babe_primitives::AuthorityIndex, + slot_number: babe_primitives::SlotNumber, + vrf_output: [u8; babe_primitives::VRF_OUTPUT_LENGTH], + vrf_proof: [u8; babe_primitives::VRF_PROOF_LENGTH], +) -> Digest { + let digest_data = babe_primitives::RawBabePreDigest::Primary { + authority_index, + slot_number, + vrf_output, + vrf_proof, + }; + let log = DigestItem::PreRuntime(babe_primitives::BABE_ENGINE_ID, digest_data.encode()); + Digest { logs: vec![log] } +} + +#[test] +fn empty_randomness_is_correct() { + let s = compute_randomness([0; RANDOMNESS_LENGTH], 0, std::iter::empty(), None); + assert_eq!(s, EMPTY_RANDOMNESS); +} + +#[test] +fn initial_values() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert_eq!(Babe::authorities().len(), 4) + }) +} + +#[test] +fn check_module() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert!(!Babe::should_end_session(0), "Genesis does not change sessions"); + assert!(!Babe::should_end_session(200000), + "BABE does not include the block number in epoch calculations"); + }) +} + +type System = system::Module; + +#[test] +fn first_block_epoch_zero_start() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + let genesis_slot = 100; + let first_vrf = [1; 32]; + let pre_digest = make_pre_digest( + 0, + genesis_slot, + first_vrf, + [0xff; 64], + ); + + assert_eq!(Babe::genesis_slot(), 0); + System::initialize(&1, &Default::default(), &Default::default(), &pre_digest); + + // see implementation of the function for details why: we issue an + // epoch-change digest but don't do it via the normal session mechanism. + assert!(!Babe::should_end_session(1)); + assert_eq!(Babe::genesis_slot(), genesis_slot); + assert_eq!(Babe::current_slot(), genesis_slot); + assert_eq!(Babe::epoch_index(), 0); + + Babe::on_finalize(1); + let header = System::finalize(); + + assert_eq!(SegmentIndex::get(), 0); + assert_eq!(UnderConstruction::get(0), vec![first_vrf]); + assert_eq!(Babe::randomness(), [0; 32]); + assert_eq!(NextRandomness::get(), [0; 32]); + + assert_eq!(header.digest.logs.len(), 2); + assert_eq!(pre_digest.logs.len(), 1); + assert_eq!(header.digest.logs[0], pre_digest.logs[0]); + + let authorities = Babe::authorities(); + let consensus_log = babe_primitives::ConsensusLog::NextEpochData( + babe_primitives::NextEpochDescriptor { + authorities, + randomness: Babe::randomness(), + } + ); + let consensus_digest = DigestItem::Consensus(BABE_ENGINE_ID, consensus_log.encode()); + + // first epoch descriptor has same info as last. + assert_eq!(header.digest.logs[1], consensus_digest.clone()) + }) +} + +#[test] +fn authority_index() { + new_test_ext(vec![0, 1, 2, 3]).execute_with(|| { + assert_eq!( + Babe::find_author((&[(BABE_ENGINE_ID, &[][..])]).into_iter().cloned()), None, + "Trivially invalid authorities are ignored") + }) +} diff --git a/srml/balances/Cargo.toml b/srml/balances/Cargo.toml index d3ac0c96b37efce873e3f13c1500f49d8ef853ce..f7f6041c6bb1629b99c3571f27925050a5669a62 100644 --- a/srml/balances/Cargo.toml +++ b/srml/balances/Cargo.toml @@ -5,18 +5,19 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } substrate-keyring = { path = "../../core/keyring", optional = true } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } +transaction-payment = { package = "srml-transaction-payment", path = "../transaction-payment" } [features] default = ["std"] @@ -26,7 +27,7 @@ std = [ "substrate-keyring", "codec/std", "rstd/std", - "srml-support/std", + "support/std", "sr-primitives/std", "system/std", ] diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 66d0ee028495f411c7dee374012ec0b3455a0489..e22dba3fee47757f7ecd970a7cbd2a4e199bfb43 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -72,8 +72,6 @@ //! - [`Imbalance`](../srml_support/traits/trait.Imbalance.html): Functions for handling //! imbalances between total issuance in the system and account balances. Must be used when a function //! creates new funds (e.g. a reward) or destroys some funds (e.g. a system fee). -//! - [`MakePayment`](../srml_support/traits/trait.MakePayment.html): Simple trait designed -//! for hooking into a transaction payment. //! - [`IsDeadAccount`](../srml_system/trait.IsDeadAccount.html): Determiner to say whether a //! given account is unused. //! @@ -97,7 +95,7 @@ //! The Contract module uses the `Currency` trait to handle gas payment, and its types inherit from `Currency`: //! //! ``` -//! use srml_support::traits::Currency; +//! use support::traits::Currency; //! # pub trait Trait: system::Trait { //! # type Currency: Currency; //! # } @@ -111,14 +109,14 @@ //! The Staking module uses the `LockableCurrency` trait to lock a stash account's funds: //! //! ``` -//! use srml_support::traits::{WithdrawReasons, LockableCurrency}; +//! use support::traits::{WithdrawReasons, LockableCurrency}; //! use sr_primitives::traits::Bounded; //! pub trait Trait: system::Trait { //! type Currency: LockableCurrency; //! } //! # struct StakingLedger { //! # stash: ::AccountId, -//! # total: <::Currency as srml_support::traits::Currency<::AccountId>>::Balance, +//! # total: <::Currency as support::traits::Currency<::AccountId>>::Balance, //! # phantom: std::marker::PhantomData, //! # } //! # const STAKING_ID: [u8; 8] = *b"staking "; @@ -150,21 +148,25 @@ #![cfg_attr(not(feature = "std"), no_std)] use rstd::prelude::*; -use rstd::{cmp, result, mem}; +use rstd::{cmp, result, mem, fmt::Debug}; use codec::{Codec, Encode, Decode}; -use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module}; -use srml_support::traits::{ - UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced, - WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, - Imbalance, SignedImbalance, ReservableCurrency, Get, +use support::{ + StorageValue, Parameter, decl_event, decl_storage, decl_module, + traits::{ + UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced, + WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, + Imbalance, SignedImbalance, ReservableCurrency, Get, + }, + dispatch::Result, }; -use srml_support::dispatch::Result; -use sr_primitives::traits::{ - Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug, - Saturating, Bounded, SignedExtension, SaturatedConversion, DispatchError, Convert, +use sr_primitives::{ + RuntimeDebug, + traits::{ + Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDeserialize, + Saturating, Bounded, + }, + weights::SimpleDispatchInfo, }; -use sr_primitives::transaction_validity::{TransactionPriority, ValidTransaction}; -use sr_primitives::weights::{DispatchInfo, SimpleDispatchInfo, Weight}; use system::{IsDeadAccount, OnNewAccount, ensure_signed, ensure_root}; mod mock; @@ -172,16 +174,10 @@ mod tests; pub use self::imbalances::{PositiveImbalance, NegativeImbalance}; -pub const DEFAULT_EXISTENTIAL_DEPOSIT: u32 = 0; -pub const DEFAULT_TRANSFER_FEE: u32 = 0; -pub const DEFAULT_CREATION_FEE: u32 = 0; -pub const DEFAULT_TRANSACTION_BASE_FEE: u32 = 0; -pub const DEFAULT_TRANSACTION_BYTE_FEE: u32 = 0; - pub trait Subtrait: system::Trait { /// The balance of an account. type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + - MaybeSerializeDebug + From; + MaybeSerializeDeserialize + Debug + From; /// A function that is invoked when the free-balance has fallen below the existential deposit and /// has been reduced to zero. @@ -200,21 +196,12 @@ pub trait Subtrait: system::Trait { /// The fee required to create an account. type CreationFee: Get; - - /// The fee to be paid for making a transaction; the base. - type TransactionBaseFee: Get; - - /// The fee to be paid for making a transaction; the per-byte portion. - type TransactionByteFee: Get; - - /// Convert a weight value into a deductible fee based on the currency type. - type WeightToFee: Convert; } pub trait Trait: system::Trait { /// The balance of an account. type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + - MaybeSerializeDebug + From; + MaybeSerializeDeserialize + Debug + From; /// A function that is invoked when the free-balance has fallen below the existential deposit and /// has been reduced to zero. @@ -225,9 +212,6 @@ pub trait Trait: system::Trait { /// Handler for when a new account is created. type OnNewAccount: OnNewAccount; - /// Handler for the unbalanced reduction when taking transaction fees. - type TransactionPayment: OnUnbalanced>; - /// Handler for the unbalanced reduction when taking fees associated with balance /// transfer (which may also include account creation). type TransferPayment: OnUnbalanced>; @@ -246,15 +230,6 @@ pub trait Trait: system::Trait { /// The fee required to create an account. type CreationFee: Get; - - /// The fee to be paid for making a transaction; the base. - type TransactionBaseFee: Get; - - /// The fee to be paid for making a transaction; the per-byte portion. - type TransactionByteFee: Get; - - /// Convert a weight value into a deductible fee based on the currency type. - type WeightToFee: Convert; } impl, I: Instance> Subtrait for T { @@ -264,9 +239,6 @@ impl, I: Instance> Subtrait for T { type ExistentialDeposit = T::ExistentialDeposit; type TransferFee = T::TransferFee; type CreationFee = T::CreationFee; - type TransactionBaseFee = T::TransactionBaseFee; - type TransactionByteFee = T::TransactionByteFee; - type WeightToFee = T::WeightToFee; } decl_event!( @@ -284,8 +256,7 @@ decl_event!( ); /// Struct to encode the vesting schedule of an individual account. -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)] pub struct VestingSchedule { /// Locked amount at genesis. pub locked: Balance, @@ -312,8 +283,7 @@ impl Ves } } -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct BalanceLock { pub id: LockIdentifier, pub amount: Balance, @@ -324,12 +294,12 @@ pub struct BalanceLock { decl_storage! { trait Store for Module, I: Instance=DefaultInstance> as Balances { /// The total units issued in the system. - pub TotalIssuance get(total_issuance) build(|config: &GenesisConfig| { + pub TotalIssuance get(fn total_issuance) build(|config: &GenesisConfig| { config.balances.iter().fold(Zero::zero(), |acc: T::Balance, &(_, n)| acc + n) }): T::Balance; /// Information regarding the vesting of a given account. - pub Vesting get(vesting) build(|config: &GenesisConfig| { + pub Vesting get(fn vesting) build(|config: &GenesisConfig| { // Generate initial vesting configuration // * who - Account which we are generating vesting configuration for // * begin - Block when the account will start to vest @@ -366,7 +336,7 @@ decl_storage! { /// /// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. - pub FreeBalance get(free_balance) + pub FreeBalance get(fn free_balance) build(|config: &GenesisConfig| config.balances.clone()): map T::AccountId => T::Balance; @@ -381,10 +351,10 @@ decl_storage! { /// /// `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets /// collapsed to zero if it ever becomes less than `ExistentialDeposit`.) - pub ReservedBalance get(reserved_balance): map T::AccountId => T::Balance; + pub ReservedBalance get(fn reserved_balance): map T::AccountId => T::Balance; /// Any liquidity locks on some account balances. - pub Locks get(locks): map T::AccountId => Vec>; + pub Locks get(fn locks): map T::AccountId => Vec>; } add_extra_genesis { config(balances): Vec<(T::AccountId, T::Balance)>; @@ -404,13 +374,7 @@ decl_module! { /// The fee required to create an account. const CreationFee: T::Balance = T::CreationFee::get(); - /// The fee to be paid for making a transaction; the base. - const TransactionBaseFee: T::Balance = T::TransactionBaseFee::get(); - - /// The fee to be paid for making a transaction; the per-byte portion. - const TransactionByteFee: T::Balance = T::TransactionByteFee::get(); - - fn deposit_event() = default; + fn deposit_event() = default; /// Transfer some liquid free balance to another account. /// @@ -433,6 +397,8 @@ decl_module! { /// `T::OnNewAccount::on_new_account` to be called. /// - Removing enough funds from an account will trigger /// `T::DustRemoval::on_unbalanced` and `T::OnFreeBalanceZero::on_free_balance_zero`. + /// - `transfer_keep_alive` works the same way as `transfer`, but has an additional + /// check that the transfer will not kill the origin account. /// /// # #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] @@ -443,7 +409,7 @@ decl_module! { ) { let transactor = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - >::transfer(&transactor, &dest, value)?; + >::transfer(&transactor, &dest, value, ExistenceRequirement::AllowDeath)?; } /// Set the balances of a given account. @@ -459,7 +425,7 @@ decl_module! { /// - Independent of the arguments. /// - Contains a limited number of reads and writes. /// # - #[weight = SimpleDispatchInfo::FixedOperational(500_000)] + #[weight = SimpleDispatchInfo::FixedOperational(50_000)] fn set_balance( origin, who: ::Source, @@ -485,6 +451,39 @@ decl_module! { } Self::set_reserved_balance(&who, new_reserved); } + + /// Exactly as `transfer`, except the origin must be root and the source account may be + /// specified. + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + pub fn force_transfer( + origin, + source: ::Source, + dest: ::Source, + #[compact] value: T::Balance + ) { + ensure_root(origin)?; + let source = T::Lookup::lookup(source)?; + let dest = T::Lookup::lookup(dest)?; + >::transfer(&source, &dest, value, ExistenceRequirement::AllowDeath)?; + } + + /// Same as the [`transfer`] call, but with a check that the transfer will not kill the + /// origin account. + /// + /// 99% of the time you want [`transfer`] instead. + /// + /// [`transfer`]: struct.Module.html#method.transfer + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + pub fn transfer_keep_alive( + origin, + dest: ::Source, + #[compact] value: T::Balance + ) { + let transactor = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + >::transfer(&transactor, &dest, value, ExistenceRequirement::KeepAlive)?; + } + } } @@ -751,7 +750,7 @@ mod imbalances { // This works as long as `increase_total_issuance_by` doesn't use the Imbalance // types (basically for charging fees). // This should eventually be refactored so that the three type items that do -// depend on the Imbalance type (TransactionPayment, TransferPayment, DustRemoval) +// depend on the Imbalance type (TransferPayment, DustRemoval) // are placed in their own SRML module. struct ElevatedTrait, I: Instance>(T, I); impl, I: Instance> Clone for ElevatedTrait { @@ -771,32 +770,28 @@ impl, I: Instance> system::Trait for ElevatedTrait { type AccountId = T::AccountId; type Lookup = T::Lookup; type Header = T::Header; - type WeightMultiplierUpdate = T::WeightMultiplierUpdate; type Event = (); type BlockHashCount = T::BlockHashCount; type MaximumBlockWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; type AvailableBlockRatio = T::AvailableBlockRatio; + type Version = T::Version; } impl, I: Instance> Trait for ElevatedTrait { type Balance = T::Balance; type OnFreeBalanceZero = T::OnFreeBalanceZero; type OnNewAccount = T::OnNewAccount; type Event = (); - type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); type ExistentialDeposit = T::ExistentialDeposit; type TransferFee = T::TransferFee; type CreationFee = T::CreationFee; - type TransactionBaseFee = T::TransactionBaseFee; - type TransactionByteFee = T::TransactionByteFee; - type WeightToFee = T::WeightToFee; } impl, I: Instance> Currency for Module where - T::Balance: MaybeSerializeDebug + T::Balance: MaybeSerializeDeserialize + Debug { type Balance = T::Balance; type PositiveImbalance = PositiveImbalance; @@ -823,12 +818,12 @@ where } fn burn(mut amount: Self::Balance) -> Self::PositiveImbalance { - >::mutate(|issued| - issued.checked_sub(&amount).unwrap_or_else(|| { + >::mutate(|issued| { + *issued = issued.checked_sub(&amount).unwrap_or_else(|| { amount = *issued; Zero::zero() - }) - ); + }); + }); PositiveImbalance::new(amount) } @@ -849,13 +844,13 @@ where fn ensure_can_withdraw( who: &T::AccountId, _amount: T::Balance, - reason: WithdrawReason, + reasons: WithdrawReasons, new_balance: T::Balance, ) -> Result { - match reason { - WithdrawReason::Reserve | WithdrawReason::Transfer if Self::vesting_balance(who) > new_balance => - return Err("vesting balance too high to send value"), - _ => {} + if reasons.intersects(WithdrawReason::Reserve | WithdrawReason::Transfer) + && Self::vesting_balance(who) > new_balance + { + return Err("vesting balance too high to send value"); } let locks = Self::locks(who); if locks.is_empty() { @@ -867,7 +862,7 @@ where .all(|l| now >= l.until || new_balance >= l.amount - || !l.reasons.contains(reason) + || !l.reasons.intersects(reasons) ) { Ok(()) @@ -876,7 +871,12 @@ where } } - fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { + fn transfer( + transactor: &T::AccountId, + dest: &T::AccountId, + value: Self::Balance, + existence_requirement: ExistenceRequirement, + ) -> Result { let from_balance = Self::free_balance(transactor); let to_balance = Self::free_balance(dest); let would_create = to_balance.is_zero(); @@ -893,7 +893,7 @@ where if would_create && value < T::ExistentialDeposit::get() { return Err("value too low to create account"); } - Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?; + Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer.into(), new_from_balance)?; // NOTE: total stake being stored in the same type means that this could never overflow // but better to be safe than sorry. @@ -903,6 +903,12 @@ where }; if transactor != dest { + if existence_requirement == ExistenceRequirement::KeepAlive { + if new_from_balance < Self::minimum_balance() { + return Err("transfer would kill account"); + } + } + Self::set_free_balance(transactor, new_from_balance); if !>::exists(dest) { Self::new_account(dest, new_to_balance); @@ -918,14 +924,21 @@ where fn withdraw( who: &T::AccountId, value: Self::Balance, - reason: WithdrawReason, + reasons: WithdrawReasons, liveness: ExistenceRequirement, ) -> result::Result { - if let Some(new_balance) = Self::free_balance(who).checked_sub(&value) { - if liveness == ExistenceRequirement::KeepAlive && new_balance < T::ExistentialDeposit::get() { + let old_balance = Self::free_balance(who); + if let Some(new_balance) = old_balance.checked_sub(&value) { + // if we need to keep the account alive... + if liveness == ExistenceRequirement::KeepAlive + // ...and it would be dead afterwards... + && new_balance < T::ExistentialDeposit::get() + // ...yet is was alive before + && old_balance >= T::ExistentialDeposit::get() + { return Err("payment would kill account") } - Self::ensure_can_withdraw(who, value, reason, new_balance)?; + Self::ensure_can_withdraw(who, value, reasons, new_balance)?; Self::set_free_balance(who, new_balance); Ok(NegativeImbalance::new(value)) } else { @@ -1026,13 +1039,13 @@ where impl, I: Instance> ReservableCurrency for Module where - T::Balance: MaybeSerializeDebug + T::Balance: MaybeSerializeDeserialize + Debug { fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool { Self::free_balance(who) .checked_sub(&value) .map_or(false, |new_balance| - Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve, new_balance).is_ok() + Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve.into(), new_balance).is_ok() ) } @@ -1046,7 +1059,7 @@ where return Err("not enough free funds") } let new_balance = b - value; - Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve, new_balance)?; + Self::ensure_can_withdraw(who, value, WithdrawReason::Reserve.into(), new_balance)?; Self::set_reserved_balance(who, Self::reserved_balance(who) + value); Self::set_free_balance(who, new_balance); Ok(()) @@ -1089,7 +1102,7 @@ where impl, I: Instance> LockableCurrency for Module where - T::Balance: MaybeSerializeDebug + T::Balance: MaybeSerializeDeserialize + Debug { type Moment = T::BlockNumber; @@ -1161,92 +1174,9 @@ where } } -/// Require the transactor pay for themselves and maybe include a tip to gain additional priority -/// in the queue. -#[derive(Encode, Decode, Clone, Eq, PartialEq)] -pub struct TakeFees, I: Instance = DefaultInstance>(#[codec(compact)] T::Balance); - -impl, I: Instance> TakeFees { - /// utility constructor. Used only in client/factory code. - #[cfg(feature = "std")] - pub fn from(fee: T::Balance) -> Self { - Self(fee) - } - - /// Compute the final fee value for a particular transaction. - /// - /// The final fee is composed of: - /// - _length-fee_: This is the amount paid merely to pay for size of the transaction. - /// - _weight-fee_: This amount is computed based on the weight of the transaction. Unlike - /// size-fee, this is not input dependent and reflects the _complexity_ of the execution - /// and the time it consumes. - /// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed - /// transactions can have a tip. - fn compute_fee(len: usize, info: DispatchInfo, tip: T::Balance) -> T::Balance { - let len_fee = if info.pay_length_fee() { - let len = T::Balance::from(len as u32); - let base = T::TransactionBaseFee::get(); - let per_byte = T::TransactionByteFee::get(); - base.saturating_add(per_byte.saturating_mul(len)) - } else { - Zero::zero() - }; - - let weight_fee = { - // cap the weight to the maximum defined in runtime, otherwise it will be the `Bounded` - // maximum of its data type, which is not desired. - let capped_weight = info.weight.min(::MaximumBlockWeight::get()); - let weight_update = >::next_weight_multiplier(); - let adjusted_weight = weight_update.apply_to(capped_weight); - T::WeightToFee::convert(adjusted_weight) - }; - - len_fee.saturating_add(weight_fee).saturating_add(tip) - } -} - -#[cfg(feature = "std")] -impl, I: Instance> rstd::fmt::Debug for TakeFees { - fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - self.0.fmt(f) - } -} - -impl, I: Instance + Clone + Eq> SignedExtension for TakeFees { - type AccountId = T::AccountId; - type Call = T::Call; - type AdditionalSigned = (); - type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } - - fn validate( - &self, - who: &Self::AccountId, - _call: &Self::Call, - info: DispatchInfo, - len: usize, - ) -> rstd::result::Result { - // pay any fees. - let fee = Self::compute_fee(len, info, self.0); - let imbalance = >::withdraw( - who, - fee, - WithdrawReason::TransactionPayment, - ExistenceRequirement::KeepAlive, - ).map_err(|_| DispatchError::Payment)?; - T::TransactionPayment::on_unbalanced(imbalance); - - let mut r = ValidTransaction::default(); - // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which - // will be a bit more than setting the priority to tip. For now, this is enough. - r.priority = fee.saturated_into::(); - Ok(r) - } -} - impl, I: Instance> IsDeadAccount for Module where - T::Balance: MaybeSerializeDebug + T::Balance: MaybeSerializeDeserialize + Debug { fn is_dead_account(who: &T::AccountId) -> bool { Self::total_balance(who).is_zero() diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index 954d500a1076be24ff02d607c7d40b0dd567f5a6..600d0e6fb78799dd796ab9a66d4dd67bbe133225 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -18,12 +18,12 @@ #![cfg(test)] -use sr_primitives::{Perbill, traits::{Convert, IdentityLookup}, testing::Header, +use sr_primitives::{Perbill, traits::{ConvertInto, IdentityLookup}, testing::Header, weights::{DispatchInfo, Weight}}; -use primitives::{H256, Blake2Hasher}; +use primitives::H256; use runtime_io; -use srml_support::{impl_outer_origin, parameter_types}; -use srml_support::traits::Get; +use support::{impl_outer_origin, parameter_types}; +use support::traits::Get; use std::cell::RefCell; use crate::{GenesisConfig, Module, Trait}; @@ -35,10 +35,6 @@ thread_local! { static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); static TRANSFER_FEE: RefCell = RefCell::new(0); static CREATION_FEE: RefCell = RefCell::new(0); - static TRANSACTION_BASE_FEE: RefCell = RefCell::new(0); - static TRANSACTION_BYTE_FEE: RefCell = RefCell::new(1); - static TRANSACTION_WEIGHT_FEE: RefCell = RefCell::new(1); - static WEIGHT_TO_FEE: RefCell = RefCell::new(1); } pub struct ExistentialDeposit; @@ -56,23 +52,6 @@ impl Get for CreationFee { fn get() -> u64 { CREATION_FEE.with(|v| *v.borrow()) } } -pub struct TransactionBaseFee; -impl Get for TransactionBaseFee { - fn get() -> u64 { TRANSACTION_BASE_FEE.with(|v| *v.borrow()) } -} - -pub struct TransactionByteFee; -impl Get for TransactionByteFee { - fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) } -} - -pub struct WeightToFee(u64); -impl Convert for WeightToFee { - fn convert(t: Weight) -> u64 { - WEIGHT_TO_FEE.with(|v| *v.borrow() * (t as u64)) - } -} - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Runtime; @@ -92,33 +71,38 @@ impl system::Trait for Runtime { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); +} +parameter_types! { + pub const TransactionBaseFee: u64 = 0; + pub const TransactionByteFee: u64 = 1; +} +impl transaction_payment::Trait for Runtime { + type Currency = Module; + type OnTransactionPayment = (); + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = ConvertInto; + type FeeMultiplierUpdate = (); } impl Trait for Runtime { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); type Event = (); - type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = WeightToFee; } pub struct ExtBuilder { - transaction_base_fee: u64, - transaction_byte_fee: u64, - weight_to_fee: u64, existential_deposit: u64, transfer_fee: u64, creation_fee: u64, @@ -128,9 +112,6 @@ pub struct ExtBuilder { impl Default for ExtBuilder { fn default() -> Self { Self { - transaction_base_fee: 0, - transaction_byte_fee: 0, - weight_to_fee: 0, existential_deposit: 0, transfer_fee: 0, creation_fee: 0, @@ -140,12 +121,6 @@ impl Default for ExtBuilder { } } impl ExtBuilder { - pub fn transaction_fees(mut self, base_fee: u64, byte_fee: u64, weight_fee: u64) -> Self { - self.transaction_base_fee = base_fee; - self.transaction_byte_fee = byte_fee; - self.weight_to_fee = weight_fee; - self - } pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { self.existential_deposit = existential_deposit; self @@ -174,11 +149,8 @@ impl ExtBuilder { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee); CREATION_FEE.with(|v| *v.borrow_mut() = self.creation_fee); - TRANSACTION_BASE_FEE.with(|v| *v.borrow_mut() = self.transaction_base_fee); - TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.transaction_byte_fee); - WEIGHT_TO_FEE.with(|v| *v.borrow_mut() = self.weight_to_fee); } - pub fn build(self) -> runtime_io::TestExternalities { + pub fn build(self) -> runtime_io::TestExternalities { self.set_associated_consts(); let mut t = system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig:: { @@ -210,7 +182,6 @@ impl ExtBuilder { pub type System = system::Module; pub type Balances = Module; - pub const CALL: &::Call = &(); /// create a transaction info struct from weight. Handy to avoid building the whole struct. diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index edbb198f341ee5e3b859f3aa858bb919b60d6abc..8afec6f697de137d2b3328e64eaea43ff7bd769f 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -20,12 +20,14 @@ use super::*; use mock::{Balances, ExtBuilder, Runtime, System, info_from_weight, CALL}; -use runtime_io::with_externalities; -use srml_support::{ +use sr_primitives::traits::SignedExtension; +use support::{ assert_noop, assert_ok, assert_err, traits::{LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons, - Currency, ReservableCurrency} + Currency, ReservableCurrency, ExistenceRequirement::AllowDeath} }; +use transaction_payment::ChargeTransactionPayment; +use system::RawOrigin; const ID_1: LockIdentifier = *b"1 "; const ID_2: LockIdentifier = *b"2 "; @@ -33,11 +35,11 @@ const ID_3: LockIdentifier = *b"3 "; #[test] fn basic_locking_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { assert_eq!(Balances::free_balance(&1), 10); Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 5), + >::transfer(&1, &2, 5, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); @@ -45,65 +47,65 @@ fn basic_locking_should_work() { #[test] fn partial_locking_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } #[test] fn lock_removal_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); Balances::remove_lock(ID_1, &1); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } #[test] fn lock_replacement_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all()); Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } #[test] fn double_locking_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); Balances::set_lock(ID_2, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } #[test] fn combination_locking_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, u64::max_value(), 0, WithdrawReasons::none()); Balances::set_lock(ID_2, &1, 0, u64::max_value(), WithdrawReasons::none()); Balances::set_lock(ID_3, &1, 0, 0, WithdrawReasons::all()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } #[test] fn lock_value_extension_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 3), + >::transfer(&1, &2, 3, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); @@ -111,21 +113,20 @@ fn lock_value_extension_should_work() { #[test] fn lock_reasons_should_work() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(1) - .monied(true).transaction_fees(0, 1, 0) - .build(), - || { + ExtBuilder::default() + .existential_deposit(1) + .monied(true) + .build() + .execute_with(|| { Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into()); assert_noop!( - >::transfer(&1, &2, 1), + >::transfer(&1, &2, 1, AllowDeath), "account liquidity restrictions prevent withdrawal" ); assert_ok!(>::reserve(&1, 1)); // NOTE: this causes a fee payment. - assert!( as SignedExtension>::pre_dispatch( - TakeFees::from(1), + assert!( as SignedExtension>::pre_dispatch( + ChargeTransactionPayment::from(1), &1, CALL, info_from_weight(1), @@ -133,13 +134,13 @@ fn lock_reasons_should_work() { ).is_ok()); Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); assert_noop!( >::reserve(&1, 1), "account liquidity restrictions prevent withdrawal" ); - assert!( as SignedExtension>::pre_dispatch( - TakeFees::from(1), + assert!( as SignedExtension>::pre_dispatch( + ChargeTransactionPayment::from(1), &1, CALL, info_from_weight(1), @@ -147,50 +148,49 @@ fn lock_reasons_should_work() { ).is_ok()); Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into()); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); assert_ok!(>::reserve(&1, 1)); - assert!( as SignedExtension>::pre_dispatch( - TakeFees::from(1), + assert!( as SignedExtension>::pre_dispatch( + ChargeTransactionPayment::from(1), &1, CALL, info_from_weight(1), 0, ).is_err()); - } - ); + }); } #[test] fn lock_block_number_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 1), + >::transfer(&1, &2, 1, AllowDeath), "account liquidity restrictions prevent withdrawal" ); System::set_block_number(2); - assert_ok!(>::transfer(&1, &2, 1)); + assert_ok!(>::transfer(&1, &2, 1, AllowDeath)); }); } #[test] fn lock_block_number_extension_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); System::set_block_number(2); Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all()); assert_noop!( - >::transfer(&1, &2, 3), + >::transfer(&1, &2, 3, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); @@ -198,20 +198,20 @@ fn lock_block_number_extension_should_work() { #[test] fn lock_reasons_extension_should_work() { - with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { + ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| { Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into()); assert_noop!( - >::transfer(&1, &2, 6), + >::transfer(&1, &2, 6, AllowDeath), "account liquidity restrictions prevent withdrawal" ); }); @@ -219,34 +219,30 @@ fn lock_reasons_extension_should_work() { #[test] fn default_indexing_on_new_accounts_should_not_work2() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .creation_fee(50) - .monied(true) - .build(), - || { - + ExtBuilder::default() + .existential_deposit(10) + .creation_fee(50) + .monied(true) + .build() + .execute_with(|| { assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist // ext_deposit is 10, value is 9, not satisfies for ext_deposit assert_noop!( Balances::transfer(Some(1).into(), 5, 9), - "value too low to create account" + "value too low to create account", ); assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist assert_eq!(Balances::free_balance(&1), 100); - }, - ); + }); } #[test] fn reserved_balance_should_prevent_reclaim_count() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(256 * 1) - .monied(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(256 * 1) + .monied(true) + .build() + .execute_with(|| { System::inc_account_nonce(&2); assert_eq!(Balances::is_dead_account(&2), false); assert_eq!(Balances::is_dead_account(&5), true); @@ -273,14 +269,13 @@ fn reserved_balance_should_prevent_reclaim_count() { assert_ok!(Balances::transfer(Some(4).into(), 6, 256 * 1 + 0x69)); assert_eq!(Balances::total_balance(&6), 256 * 1 + 0x69); assert_eq!(Balances::is_dead_account(&6), false); - }, - ); + }); } #[test] fn reward_should_work() { - with_externalities(&mut ExtBuilder::default().monied(true).build(), || { + ExtBuilder::default().monied(true).build().execute_with(|| { assert_eq!(Balances::total_balance(&1), 10); assert_ok!(Balances::deposit_into_existing(&1, 10).map(drop)); assert_eq!(Balances::total_balance(&1), 20); @@ -290,12 +285,11 @@ fn reward_should_work() { #[test] fn dust_account_removal_should_work() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(100) - .monied(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(100) + .monied(true) + .build() + .execute_with(|| { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); assert_eq!(Balances::total_balance(&2), 2000); @@ -304,19 +298,17 @@ fn dust_account_removal_should_work() { assert_eq!(Balances::total_balance(&2), 0); assert_eq!(Balances::total_balance(&5), 1901); assert_eq!(System::account_nonce(&2), 0); - }, - ); + }); } #[test] fn dust_account_removal_should_work2() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(100) - .creation_fee(50) - .monied(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(100) + .creation_fee(50) + .monied(true) + .build() + .execute_with(|| { System::inc_account_nonce(&2); assert_eq!(System::account_nonce(&2), 1); assert_eq!(Balances::total_balance(&2), 2000); @@ -325,13 +317,12 @@ fn dust_account_removal_should_work2() { assert_eq!(Balances::total_balance(&2), 0); assert_eq!(Balances::total_balance(&5), 1851); assert_eq!(System::account_nonce(&2), 0); - }, - ); + }); } #[test] fn balance_works() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 42); assert_eq!(Balances::free_balance(&1), 42); assert_eq!(Balances::reserved_balance(&1), 0); @@ -344,7 +335,7 @@ fn balance_works() { #[test] fn balance_transfer_works() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::transfer(Some(1).into(), 2, 69)); assert_eq!(Balances::total_balance(&1), 42); @@ -352,9 +343,23 @@ fn balance_transfer_works() { }); } +#[test] +fn force_transfer_works() { + ExtBuilder::default().build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 111); + assert_noop!( + Balances::force_transfer(Some(2).into(), 1, 2, 69), + "RequireRootOrigin", + ); + assert_ok!(Balances::force_transfer(RawOrigin::Root.into(), 1, 2, 69)); + assert_eq!(Balances::total_balance(&1), 42); + assert_eq!(Balances::total_balance(&2), 69); + }); +} + #[test] fn reserving_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_eq!(Balances::total_balance(&1), 111); @@ -371,16 +376,19 @@ fn reserving_balance_should_work() { #[test] fn balance_transfer_when_reserved_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 69)); - assert_noop!(Balances::transfer(Some(1).into(), 2, 69), "balance too low to send value"); + assert_noop!( + Balances::transfer(Some(1).into(), 2, 69), + "balance too low to send value", + ); }); } #[test] fn deducting_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 69)); assert_eq!(Balances::free_balance(&1), 42); @@ -389,7 +397,7 @@ fn deducting_balance_should_work() { #[test] fn refunding_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 42); Balances::set_reserved_balance(&1, 69); Balances::unreserve(&1, 69); @@ -400,7 +408,7 @@ fn refunding_balance_should_work() { #[test] fn slashing_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 69)); assert!(Balances::slash(&1, 69).1.is_zero()); @@ -412,7 +420,7 @@ fn slashing_balance_should_work() { #[test] fn slashing_incomplete_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 42); assert_ok!(Balances::reserve(&1, 21)); assert_eq!(Balances::slash(&1, 69).1, 27); @@ -424,7 +432,7 @@ fn slashing_incomplete_balance_should_work() { #[test] fn unreserving_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 111)); Balances::unreserve(&1, 42); @@ -435,7 +443,7 @@ fn unreserving_balance_should_work() { #[test] fn slashing_reserved_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 111)); assert_eq!(Balances::slash_reserved(&1, 42).1, 0); @@ -447,7 +455,7 @@ fn slashing_reserved_balance_should_work() { #[test] fn slashing_incomplete_reserved_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 42)); assert_eq!(Balances::slash_reserved(&1, 69).1, 27); @@ -459,7 +467,7 @@ fn slashing_incomplete_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 110); let _ = Balances::deposit_creating(&2, 1); assert_ok!(Balances::reserve(&1, 110)); @@ -473,7 +481,7 @@ fn transferring_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_to_nonexistent_should_fail() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 111)); assert_noop!(Balances::repatriate_reserved(&1, &2, 42), "beneficiary account must pre-exist"); @@ -482,7 +490,7 @@ fn transferring_reserved_balance_to_nonexistent_should_fail() { #[test] fn transferring_incomplete_reserved_balance_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let _ = Balances::deposit_creating(&1, 110); let _ = Balances::deposit_creating(&2, 1); assert_ok!(Balances::reserve(&1, 41)); @@ -496,13 +504,13 @@ fn transferring_incomplete_reserved_balance_should_work() { #[test] fn transferring_too_high_value_should_not_panic() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { >::insert(1, u64::max_value()); >::insert(2, 1); assert_err!( Balances::transfer(Some(1).into(), 2, u64::max_value()), - "destination balance too high to receive value" + "destination balance too high to receive value", ); assert_eq!(Balances::free_balance(&1), u64::max_value()); @@ -512,89 +520,76 @@ fn transferring_too_high_value_should_not_panic() { #[test] fn account_create_on_free_too_low_with_other() { - with_externalities( - &mut ExtBuilder::default().existential_deposit(100).build(), - || { - let _ = Balances::deposit_creating(&1, 100); - assert_eq!(>::get(), 100); + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 100); + assert_eq!(>::get(), 100); - // No-op. - let _ = Balances::deposit_creating(&2, 50); - assert_eq!(Balances::free_balance(&2), 0); - assert_eq!(>::get(), 100); - } - ) + // No-op. + let _ = Balances::deposit_creating(&2, 50); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(>::get(), 100); + }) } #[test] fn account_create_on_free_too_low() { - with_externalities( - &mut ExtBuilder::default().existential_deposit(100).build(), - || { - // No-op. - let _ = Balances::deposit_creating(&2, 50); - assert_eq!(Balances::free_balance(&2), 0); - assert_eq!(>::get(), 0); - } - ) + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + // No-op. + let _ = Balances::deposit_creating(&2, 50); + assert_eq!(Balances::free_balance(&2), 0); + assert_eq!(>::get(), 0); + }) } #[test] fn account_removal_on_free_too_low() { - with_externalities( - &mut ExtBuilder::default().existential_deposit(100).build(), - || { - assert_eq!(>::get(), 0); + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + assert_eq!(>::get(), 0); - // Setup two accounts with free balance above the existential threshold. - let _ = Balances::deposit_creating(&1, 110); - let _ = Balances::deposit_creating(&2, 110); + // Setup two accounts with free balance above the existential threshold. + let _ = Balances::deposit_creating(&1, 110); + let _ = Balances::deposit_creating(&2, 110); - assert_eq!(Balances::free_balance(&1), 110); - assert_eq!(Balances::free_balance(&2), 110); - assert_eq!(>::get(), 220); + assert_eq!(Balances::free_balance(&1), 110); + assert_eq!(Balances::free_balance(&2), 110); + assert_eq!(>::get(), 220); - // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 will be below the existential threshold. - // This should lead to the removal of all balance of this account. - assert_ok!(Balances::transfer(Some(1).into(), 2, 20)); + // Transfer funds from account 1 of such amount that after this transfer + // the balance of account 1 will be below the existential threshold. + // This should lead to the removal of all balance of this account. + assert_ok!(Balances::transfer(Some(1).into(), 2, 20)); - // Verify free balance removal of account 1. - assert_eq!(Balances::free_balance(&1), 0); - assert_eq!(Balances::free_balance(&2), 130); + // Verify free balance removal of account 1. + assert_eq!(Balances::free_balance(&1), 0); + assert_eq!(Balances::free_balance(&2), 130); - // Verify that TotalIssuance tracks balance removal when free balance is too low. - assert_eq!(>::get(), 130); - }, - ); + // Verify that TotalIssuance tracks balance removal when free balance is too low. + assert_eq!(>::get(), 130); + }); } #[test] fn transfer_overflow_isnt_exploitable() { - with_externalities( - &mut ExtBuilder::default().creation_fee(50).build(), - || { - // Craft a value that will overflow if summed with `creation_fee`. - let evil_value = u64::max_value() - 49; - - assert_err!( - Balances::transfer(Some(1).into(), 5, evil_value), - "got overflow after adding a fee to value" - ); - } - ); + ExtBuilder::default().creation_fee(50).build().execute_with(|| { + // Craft a value that will overflow if summed with `creation_fee`. + let evil_value = u64::max_value() - 49; + + assert_err!( + Balances::transfer(Some(1).into(), 5, evil_value), + "got overflow after adding a fee to value", + ); + }); } #[test] fn check_vesting_status() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(256) - .monied(true) - .vesting(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(256) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { assert_eq!(System::block_number(), 1); let user1_free_balance = Balances::free_balance(&1); let user2_free_balance = Balances::free_balance(&2); @@ -645,19 +640,17 @@ fn check_vesting_status() { assert_eq!(Balances::vesting_balance(&2), 0); // Account 2 has fully vested by block 30 assert_eq!(Balances::vesting_balance(&12), 0); // Account 2 has fully vested by block 30 - } - ); + }); } #[test] fn unvested_balance_should_not_transfer() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .vesting(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { assert_eq!(System::block_number(), 1); let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 100); // Account 1 has free balance @@ -665,40 +658,36 @@ fn unvested_balance_should_not_transfer() { assert_eq!(Balances::vesting_balance(&1), 45); assert_noop!( Balances::transfer(Some(1).into(), 2, 56), - "vesting balance too high to send value" + "vesting balance too high to send value", ); // Account 1 cannot send more than vested amount - } - ); + }); } #[test] fn vested_balance_should_transfer() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .vesting(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { assert_eq!(System::block_number(), 1); let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 100); // Account 1 has free balance // Account 1 has only 5 units vested at block 1 (plus 50 unvested) assert_eq!(Balances::vesting_balance(&1), 45); assert_ok!(Balances::transfer(Some(1).into(), 2, 55)); - } - ); + }); } #[test] fn extra_balance_should_transfer() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .monied(true) - .vesting(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(10) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { assert_eq!(System::block_number(), 1); assert_ok!(Balances::transfer(Some(3).into(), 1, 100)); assert_ok!(Balances::transfer(Some(3).into(), 2, 100)); @@ -716,19 +705,17 @@ fn extra_balance_should_transfer() { // Account 2 has no units vested at block 1, but gained 100 assert_eq!(Balances::vesting_balance(&2), 200); assert_ok!(Balances::transfer(Some(2).into(), 3, 100)); // Account 2 can send extra units gained - } - ); + }); } #[test] fn liquid_funds_should_transfer_with_delayed_vesting() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(256) - .monied(true) - .vesting(true) - .build(), - || { + ExtBuilder::default() + .existential_deposit(256) + .monied(true) + .vesting(true) + .build() + .execute_with(|| { assert_eq!(System::block_number(), 1); let user12_free_balance = Balances::free_balance(&12); @@ -746,46 +733,30 @@ fn liquid_funds_should_transfer_with_delayed_vesting() { // Account 12 can still send liquid funds assert_ok!(Balances::transfer(Some(12).into(), 3, 256 * 5)); - } - ); -} - -#[test] -fn signed_extension_take_fees_work() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(10) - .transaction_fees(10, 1, 5) - .monied(true) - .build(), - || { - let len = 10; - assert!(TakeFees::::from(0).pre_dispatch(&1, CALL, info_from_weight(5), len).is_ok()); - assert_eq!(Balances::free_balance(&1), 100 - 20 - 25); - assert!(TakeFees::::from(5 /* tipped */).pre_dispatch(&1, CALL, info_from_weight(3), len).is_ok()); - assert_eq!(Balances::free_balance(&1), 100 - 20 - 25 - 20 - 5 - 15); - } - ); -} - -#[test] -fn signed_extension_take_fees_is_bounded() { - with_externalities( - &mut ExtBuilder::default() - .existential_deposit(1000) - .transaction_fees(0, 0, 1) - .monied(true) - .build(), - || { - use sr_primitives::weights::Weight; - - // maximum weight possible - assert!(TakeFees::::from(0).pre_dispatch(&1, CALL, info_from_weight(Weight::max_value()), 10).is_ok()); - // fee will be proportional to what is the actual maximum weight in the runtime. - assert_eq!( - Balances::free_balance(&1), - (10000 - ::MaximumBlockWeight::get()) as u64 - ); - } - ); + }); +} + +#[test] +fn burn_must_work() { + ExtBuilder::default().monied(true).build().execute_with(|| { + let init_total_issuance = Balances::total_issuance(); + let imbalance = Balances::burn(10); + assert_eq!(Balances::total_issuance(), init_total_issuance - 10); + drop(imbalance); + assert_eq!(Balances::total_issuance(), init_total_issuance); + }); +} + +#[test] +fn transfer_keep_alive_works() { + ExtBuilder::default().existential_deposit(1).build().execute_with(|| { + let _ = Balances::deposit_creating(&1, 100); + assert_err!( + Balances::transfer_keep_alive(Some(1).into(), 2, 100), + "transfer would kill account" + ); + assert_eq!(Balances::is_dead_account(&1), false); + assert_eq!(Balances::total_balance(&1), 100); + assert_eq!(Balances::total_balance(&2), 0); + }); } diff --git a/srml/collective/Cargo.toml b/srml/collective/Cargo.toml index 7aaba7c29f7b8d2bb554d1de637e02de5b15ecca..347a289b57b89b457e0894a4dd54ab815dbd6aa3 100644 --- a/srml/collective/Cargo.toml +++ b/srml/collective/Cargo.toml @@ -5,18 +5,18 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -hex-literal = "0.2.0" +hex-literal = "0.2.1" balances = { package = "srml-balances", path = "../balances" } [features] @@ -27,8 +27,8 @@ std = [ "primitives/std", "rstd/std", "serde", - "runtime_io/std", - "srml-support/std", + "runtime-io/std", + "support/std", "sr-primitives/std", "system/std", ] diff --git a/srml/collective/src/lib.rs b/srml/collective/src/lib.rs index 9dafa6721c8d26683312c4f9e65c222d09068539..37c1482f9ba15e785a1e784bb7f7aed53142a208 100644 --- a/srml/collective/src/lib.rs +++ b/srml/collective/src/lib.rs @@ -25,11 +25,13 @@ use rstd::{prelude::*, result}; use primitives::u32_trait::Value as U32; +use sr_primitives::RuntimeDebug; use sr_primitives::traits::{Hash, EnsureOrigin}; use sr_primitives::weights::SimpleDispatchInfo; -use srml_support::{ - dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, traits::ChangeMembers, - StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure +use support::{ + dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, + traits::{ChangeMembers, InitializeMembers}, decl_module, decl_event, + decl_storage, ensure, }; use system::{self, ensure_signed, ensure_root}; @@ -54,8 +56,7 @@ pub trait Trait: system::Trait { } /// Origin for the collective module. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] pub enum RawOrigin { /// It has been condoned by a given number of members of the collective from a given total. Members(MemberCount, MemberCount), @@ -68,8 +69,7 @@ pub enum RawOrigin { /// Origin for the collective module. pub type Origin = RawOrigin<::AccountId, I>; -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] /// Info for keeping track of a motion being voted on. pub struct Votes { /// The proposal's unique index. @@ -85,18 +85,20 @@ pub struct Votes { decl_storage! { trait Store for Module, I: Instance=DefaultInstance> as Collective { /// The hashes of the active proposals. - pub Proposals get(proposals): Vec; + pub Proposals get(fn proposals): Vec; /// Actual proposal for a given hash, if it's current. - pub ProposalOf get(proposal_of): map T::Hash => Option<>::Proposal>; + pub ProposalOf get(fn proposal_of): map T::Hash => Option<>::Proposal>; /// Votes on a given proposal, if it is ongoing. - pub Voting get(voting): map T::Hash => Option>; + pub Voting get(fn voting): map T::Hash => Option>; /// Proposals so far. - pub ProposalCount get(proposal_count): u32; + pub ProposalCount get(fn proposal_count): u32; /// The current members of the collective. This is stored sorted (just by value). - pub Members get(members) config(): Vec; + pub Members get(fn members): Vec; } add_extra_genesis { config(phantom): rstd::marker::PhantomData; + config(members): Vec; + build(|config| Module::::initialize_members(&config.members)) } } @@ -127,7 +129,7 @@ decl_event!( // operational class. decl_module! { pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Set the collective's membership manually to `new_members`. Be nice to the chain and /// provide it pre-sorted. @@ -278,7 +280,16 @@ impl, I: Instance> ChangeMembers for Module { } ); } - >::put_ref(new); + >::put(new); + } +} + +impl, I: Instance> InitializeMembers for Module { + fn initialize_members(members: &[T::AccountId]) { + if !members.is_empty() { + assert!(>::get().is_empty(), "Members are already initialized!"); + >::put(members); + } } } @@ -367,13 +378,13 @@ impl< #[cfg(test)] mod tests { use super::*; - use srml_support::{Hashable, assert_ok, assert_noop, parameter_types}; + use support::{Hashable, assert_ok, assert_noop, parameter_types}; use system::{EventRecord, Phase}; use hex_literal::hex; - use runtime_io::with_externalities; - use primitives::{H256, Blake2Hasher}; + use primitives::H256; use sr_primitives::{ - Perbill, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, BuildStorage + Perbill, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, + BuildStorage, }; use crate as collective; @@ -394,11 +405,11 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type WeightMultiplierUpdate = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } impl Trait for Test { type Origin = Origin; @@ -414,7 +425,7 @@ mod tests { pub type Block = sr_primitives::generic::Block; pub type UncheckedExtrinsic = sr_primitives::generic::UncheckedExtrinsic; - srml_support::construct_runtime!( + support::construct_runtime!( pub enum Test where Block = Block, NodeBlock = Block, @@ -426,7 +437,7 @@ mod tests { } ); - fn make_ext() -> runtime_io::TestExternalities { + fn make_ext() -> runtime_io::TestExternalities { GenesisConfig { collective_Instance1: Some(collective::GenesisConfig { members: vec![1, 2, 3], @@ -438,7 +449,7 @@ mod tests { #[test] fn motions_basic_environment_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); assert_eq!(Collective::members(), vec![1, 2, 3]); assert_eq!(Collective::proposals(), Vec::::new()); @@ -451,7 +462,7 @@ mod tests { #[test] fn removal_of_old_voters_votes_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); let hash = BlakeTwo256::hash_of(&proposal); @@ -485,7 +496,7 @@ mod tests { #[test] fn removal_of_old_voters_votes_works_with_set_members() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); let hash = BlakeTwo256::hash_of(&proposal); @@ -519,7 +530,7 @@ mod tests { #[test] fn propose_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); let hash = proposal.blake2_256().into(); @@ -548,7 +559,7 @@ mod tests { #[test] fn motions_ignoring_non_collective_proposals_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); assert_noop!( @@ -560,29 +571,35 @@ mod tests { #[test] fn motions_ignoring_non_collective_votes_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); let hash: H256 = proposal.blake2_256().into(); assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_noop!(Collective::vote(Origin::signed(42), hash.clone(), 0, true), "voter not a member"); + assert_noop!( + Collective::vote(Origin::signed(42), hash.clone(), 0, true), + "voter not a member", + ); }); } #[test] fn motions_ignoring_bad_index_collective_vote_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(3); let proposal = make_proposal(42); let hash: H256 = proposal.blake2_256().into(); assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()))); - assert_noop!(Collective::vote(Origin::signed(2), hash.clone(), 1, true), "mismatched index"); + assert_noop!( + Collective::vote(Origin::signed(2), hash.clone(), 1, true), + "mismatched index", + ); }); } #[test] fn motions_revoting_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); let hash: H256 = proposal.blake2_256().into(); @@ -591,13 +608,19 @@ mod tests { Collective::voting(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![1], nays: vec![] }) ); - assert_noop!(Collective::vote(Origin::signed(1), hash.clone(), 0, true), "duplicate vote ignored"); + assert_noop!( + Collective::vote(Origin::signed(1), hash.clone(), 0, true), + "duplicate vote ignored", + ); assert_ok!(Collective::vote(Origin::signed(1), hash.clone(), 0, false)); assert_eq!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 2, ayes: vec![], nays: vec![1] }) ); - assert_noop!(Collective::vote(Origin::signed(1), hash.clone(), 0, false), "duplicate vote ignored"); + assert_noop!( + Collective::vote(Origin::signed(1), hash.clone(), 0, false), + "duplicate vote ignored", + ); assert_eq!(System::events(), vec![ EventRecord { @@ -627,7 +650,7 @@ mod tests { #[test] fn motions_disapproval_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); let hash: H256 = proposal.blake2_256().into(); @@ -670,7 +693,7 @@ mod tests { #[test] fn motions_approval_works() { - with_externalities(&mut make_ext(), || { + make_ext().execute_with(|| { System::set_block_number(1); let proposal = make_proposal(42); let hash: H256 = proposal.blake2_256().into(); diff --git a/srml/contracts/COMPLEXITY.md b/srml/contracts/COMPLEXITY.md index c582de4264f841f2b5d4024081b5ddb641bd6907..a29127f778f7ebc37f048a2bcb302e081385564f 100644 --- a/srml/contracts/COMPLEXITY.md +++ b/srml/contracts/COMPLEXITY.md @@ -123,7 +123,7 @@ While these functions only modify the local `Map`, if changes made by them are c **complexity**: Each lookup has a logarithmical computing time to the number of already inserted entries. No additional memory is required. -## create_contract +## instantiate_contract Calls `contract_exists` and if it doesn't exist, do not modify the local `Map` similarly to `set_rent_allowance`. @@ -174,7 +174,7 @@ Assuming marshaled size of a balance value is of the constant size we can neglec ## Initialization -Before a call or create can be performed the execution context must be initialized. +Before a call or instantiate can be performed the execution context must be initialized. For the first call or instantiation in the handling of an extrinsic, this involves two calls: @@ -213,7 +213,7 @@ and on top of that at most once per block: - `kill_child_storage` - mutation of `ContractInfoOf` -Loading code most likely will trigger a DB read, since the code is immutable and therefore will not get into the cache (unless a suicide removes it, or it has been created in the same call chain). +Loading code most likely will trigger a DB read, since the code is immutable and therefore will not get into the cache (unless a suicide removes it, or it has been instantiated in the same call chain). Also, `transfer` can make up to 2 DB reads and up to 2 DB writes (if flushed to the storage) in the standard case. If removal of the source account takes place then it will additionally perform a DB write per one storage entry that the account has. @@ -223,15 +223,15 @@ Finally, all changes are `commit`-ted into the underlying overlay. The complexit - Only for the first invocation of the contract: up to 5 DB reads and one DB write as well as logic executed by `ensure_can_withdraw`, `withdraw`, `make_free_balance_be`. - On top of that for every invocation: Up to 5 DB reads. DB read of the code is of dynamic size. There can also be up to 2 DB writes (if flushed to the storage). Additionally, if the source account removal takes place a DB write will be performed per one storage entry that the account has. -## Create +## Instantiate -This function takes the code of the constructor and input data. Creation of a contract consists of the following steps: +This function takes the code of the constructor and input data. Instantiation of a contract consists of the following steps: 1. Initialization of the execution context. 2. Calling `DetermineContractAddress` hook to determine an address for the contract, -3. `transfer`-ing funds between self and the newly created contract. +3. `transfer`-ing funds between self and the newly instantiated contract. 4. Executing the constructor code. This will yield the final code of the code. -5. Storing the code for the newly created contract in the overlay. +5. Storing the code for the newly instantiated contract in the overlay. 6. Committing overlayed changed to the underlying `AccountDb`. **Note** that the complexity of executing the constructor code should be considered separately. @@ -303,7 +303,7 @@ Loading `input_data` should be charged in any case. **complexity**: All complexity comes from loading buffers and executing `call` executive function. The former component is proportional to the sizes of `callee`, `value` and `input_data` buffers. The latter component completely depends on the complexity of `call` executive function, and also dominated by it. -## ext_create +## ext_instantiate This function receives the following arguments: @@ -317,13 +317,13 @@ It consists of the following steps: 1. Loading `init_code` buffer from the sandbox memory (see sandboxing memory get) and then decoding it. 2. Loading `value` buffer from the sandbox memory and then decoding it. 3. Loading `input_data` buffer from the sandbox memory. -4. Invoking `create` executive function. +4. Invoking `instantiate` executive function. Loading of `value` buffer should be charged. This is because the size of the buffer is specified by the calling code, even though marshaled representation is, essentially, of constant size. This can be fixed by assigning an upper bound for size for `Balance`. Loading `init_code` and `input_data` should be charged in any case. -**complexity**: All complexity comes from loading buffers and executing `create` executive function. The former component is proportional to the sizes of `init_code`, `value` and `input_data` buffers. The latter component completely depends on the complexity of `create` executive function and also dominated by it. +**complexity**: All complexity comes from loading buffers and executing `instantiate` executive function. The former component is proportional to the sizes of `init_code`, `value` and `input_data` buffers. The latter component completely depends on the complexity of `instantiate` executive function and also dominated by it. ## ext_return diff --git a/srml/contracts/Cargo.toml b/srml/contracts/Cargo.toml index a013571edf3577faee1db3336611ece7a77e468f..365566cfb547e23324891402cfb106116d526d22 100644 --- a/srml/contracts/Cargo.toml +++ b/srml/contracts/Cargo.toml @@ -5,32 +5,30 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } -pwasm-utils = { version = "0.6.1", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +pwasm-utils = { version = "0.11.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -parity-wasm = { version = "0.31", default-features = false } -wasmi-validation = { version = "0.1", default-features = false } +parity-wasm = { version = "0.40.3", default-features = false } +wasmi-validation = { version = "0.2.0", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sandbox = { package = "sr-sandbox", path = "../../core/sr-sandbox", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } -timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } [dev-dependencies] -wabt = "~0.7.4" -assert_matches = "1.1" -hex-literal = "0.2.0" +wabt = "0.9.2" +assert_matches = "1.3.0" +hex-literal = "0.2.1" balances = { package = "srml-balances", path = "../balances" } -hex = "0.3" +hex = "0.3.2" +timestamp = { package = "srml-timestamp", path = "../timestamp" } +randomness-collective-flip = { package = "srml-randomness-collective-flip", path = "../randomness-collective-flip" } [features] default = ["std"] -core = [ - "wasmi-validation/core", -] std = [ "serde", "codec/std", @@ -39,9 +37,8 @@ std = [ "runtime-io/std", "rstd/std", "sandbox/std", - "srml-support/std", + "support/std", "system/std", - "timestamp/std", "parity-wasm/std", "pwasm-utils/std", "wasmi-validation/std", diff --git a/srml/contracts/rpc/Cargo.toml b/srml/contracts/rpc/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..f9d51452f412f9d78c3e2c12ba3ff8d0eebc43ab --- /dev/null +++ b/srml/contracts/rpc/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "srml-contracts-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../../core/client" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +primitives = { package = "substrate-primitives", path = "../../../core/primitives" } +rpc-primitives = { package = "substrate-rpc-primitives", path = "../../../core/rpc/primitives" } +serde = { version = "1.0.101", features = ["derive"] } +sr-primitives = { path = "../../../core/sr-primitives" } +srml-contracts-rpc-runtime-api = { path = "./runtime-api" } diff --git a/srml/contracts/rpc/runtime-api/Cargo.toml b/srml/contracts/rpc/runtime-api/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..2a36ed2c96cc451e622b4c58418f0bb28bf48287 --- /dev/null +++ b/srml/contracts/rpc/runtime-api/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "srml-contracts-rpc-runtime-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../../../core/client", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../../../core/sr-std", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +sr-primitives = { path = "../../../../core/sr-primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "client/std", + "codec/std", + "rstd/std", + "serde", + "sr-primitives/std", +] diff --git a/srml/contracts/rpc/runtime-api/src/lib.rs b/srml/contracts/rpc/runtime-api/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..054f110beb4d0f202bf7d963a8d97615a2ebabc5 --- /dev/null +++ b/srml/contracts/rpc/runtime-api/src/lib.rs @@ -0,0 +1,90 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime API definition required by Contracts RPC extensions. +//! +//! This API should be imported and implemented by the runtime, +//! of a node that wants to use the custom RPC extension +//! adding Contracts access methods. + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::vec::Vec; +use codec::{Encode, Decode, Codec}; +use sr_primitives::RuntimeDebug; + +/// A result of execution of a contract. +#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub enum ContractExecResult { + /// The contract returned successfully. + /// + /// There is a status code and, optionally, some data returned by the contract. + Success { + /// Status code returned by the contract. + status: u8, + /// Output data returned by the contract. + /// + /// Can be empty. + data: Vec, + }, + /// The contract execution either trapped or returned an error. + Error, +} + +/// A result type of the get storage call. +/// +/// See [`ContractsApi::get_storage`] for more info. +pub type GetStorageResult = Result>, GetStorageError>; + +/// The possible errors that can happen querying the storage of a contract. +#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)] +pub enum GetStorageError { + /// The given address doesn't point on a contract. + ContractDoesntExist, + /// The specified contract is a tombstone and thus cannot have any storage. + IsTombstone, +} + +client::decl_runtime_apis! { + /// The API to interact with contracts without using executive. + pub trait ContractsApi where + AccountId: Codec, + Balance: Codec, + { + /// Perform a call from a specified account to a given contract. + /// + /// See the contracts' `call` dispatchable function for more details. + fn call( + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: u64, + input_data: Vec, + ) -> ContractExecResult; + + /// Query a given storage key in a given contract. + /// + /// Returns `Ok(Some(Vec))` if the storage value exists under the given key in the + /// specified account and `Ok(None)` if it doesn't. If the account specified by the address + /// doesn't exist, or doesn't have a contract or if the contract is a tombstone, then `Err` + /// is returned. + fn get_storage( + address: AccountId, + key: [u8; 32], + ) -> GetStorageResult; + } +} diff --git a/srml/contracts/rpc/src/lib.rs b/srml/contracts/rpc/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..91783df99617eebf3d3ae41cb77d4664ac23d846 --- /dev/null +++ b/srml/contracts/rpc/src/lib.rs @@ -0,0 +1,187 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Node-specific RPC methods for interaction with contracts. + +use std::sync::Arc; + +use client::blockchain::HeaderBackend; +use codec::Codec; +use jsonrpc_core::{Error, ErrorCode, Result}; +use jsonrpc_derive::rpc; +use primitives::{H256, Bytes}; +use rpc_primitives::number; +use serde::{Deserialize, Serialize}; +use sr_primitives::{ + generic::BlockId, + traits::{Block as BlockT, ProvideRuntimeApi}, +}; + +pub use self::gen_client::Client as ContractsClient; +pub use srml_contracts_rpc_runtime_api::{ + self as runtime_api, ContractExecResult, ContractsApi as ContractsRuntimeApi, GetStorageResult, +}; + +const RUNTIME_ERROR: i64 = 1; +const CONTRACT_DOESNT_EXIST: i64 = 2; +const CONTRACT_IS_A_TOMBSTONE: i64 = 3; + +// A private newtype for converting `GetStorageError` into an RPC error. +struct GetStorageError(runtime_api::GetStorageError); +impl From for Error { + fn from(e: GetStorageError) -> Error { + use runtime_api::GetStorageError::*; + match e.0 { + ContractDoesntExist => Error { + code: ErrorCode::ServerError(CONTRACT_DOESNT_EXIST), + message: "The specified contract doesn't exist.".into(), + data: None, + }, + IsTombstone => Error { + code: ErrorCode::ServerError(CONTRACT_IS_A_TOMBSTONE), + message: "The contract is a tombstone and doesn't have any storage.".into(), + data: None, + } + } + } +} + +/// A struct that encodes RPC parameters required for a call to a smart-contract. +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct CallRequest { + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: number::NumberOrHex, + input_data: Bytes, +} + +/// Contracts RPC methods. +#[rpc] +pub trait ContractsApi { + /// Executes a call to a contract. + /// + /// This call is performed locally without submitting any transactions. Thus executing this + /// won't change any state. Nonetheless, the calling state-changing contracts is still possible. + /// + /// This method is useful for calling getter-like methods on contracts. + #[rpc(name = "contracts_call")] + fn call( + &self, + call_request: CallRequest, + at: Option, + ) -> Result; + + /// Returns the value under a specified storage `key` in a contract given by `address` param, + /// or `None` if it is not set. + #[rpc(name = "contracts_getStorage")] + fn get_storage( + &self, + address: AccountId, + key: H256, + at: Option, + ) -> Result>; +} + +/// An implementation of contract specific RPC methods. +pub struct Contracts { + client: Arc, + _marker: std::marker::PhantomData, +} + +impl Contracts { + /// Create new `Contracts` with the given reference to the client. + pub fn new(client: Arc) -> Self { + Contracts { + client, + _marker: Default::default(), + } + } +} + +impl ContractsApi<::Hash, AccountId, Balance> + for Contracts +where + Block: BlockT, + C: Send + Sync + 'static, + C: ProvideRuntimeApi, + C: HeaderBackend, + C::Api: ContractsRuntimeApi, + AccountId: Codec, + Balance: Codec, +{ + fn call( + &self, + call_request: CallRequest, + at: Option<::Hash>, + ) -> Result { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| + // If the block hash is not supplied assume the best block. + self.client.info().best_hash)); + + let CallRequest { + origin, + dest, + value, + gas_limit, + input_data, + } = call_request; + let gas_limit = gas_limit.to_number().map_err(|e| Error { + code: ErrorCode::InvalidParams, + message: e, + data: None, + })?; + + let exec_result = api + .call(&at, origin, dest, value, gas_limit, input_data.to_vec()) + .map_err(|e| Error { + code: ErrorCode::ServerError(RUNTIME_ERROR), + message: "Runtime trapped while executing a contract.".into(), + data: Some(format!("{:?}", e).into()), + })?; + + Ok(exec_result) + } + + fn get_storage( + &self, + address: AccountId, + key: H256, + at: Option<::Hash>, + ) -> Result> { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| + // If the block hash is not supplied assume the best block. + self.client.info().best_hash)); + + let get_storage_result = api + .get_storage(&at, address, key.into()) + .map_err(|e| + // Handle general API calling errors. + Error { + code: ErrorCode::ServerError(RUNTIME_ERROR), + message: "Runtime trapped while querying storage.".into(), + data: Some(format!("{:?}", e).into()), + })? + .map_err(GetStorageError)? + .map(Bytes); + + Ok(get_storage_result) + } +} diff --git a/srml/contracts/src/account_db.rs b/srml/contracts/src/account_db.rs index 5cfd0d3a65fa8dc77c5584cefdcbd730cc401092..50bd1fd40e97d34a319dc9b590c2f5ffd977d7c4 100644 --- a/srml/contracts/src/account_db.rs +++ b/srml/contracts/src/account_db.rs @@ -26,19 +26,65 @@ use rstd::collections::btree_map::{BTreeMap, Entry}; use rstd::prelude::*; use runtime_io::blake2_256; use sr_primitives::traits::{Bounded, Zero}; -use srml_support::traits::{Currency, Get, Imbalance, SignedImbalance, UpdateBalanceOutcome}; -use srml_support::{storage::child, StorageMap}; +use support::traits::{Currency, Get, Imbalance, SignedImbalance, UpdateBalanceOutcome}; +use support::{storage::child, StorageMap}; use system; // Note: we don't provide Option because we can't create // the trie_id in the overlay, thus we provide an overlay on the fields // specifically. pub struct ChangeEntry { + /// If Some(_), then the account balance is modified to the value. If None and `reset` is false, + /// the balance unmodified. If None and `reset` is true, the balance is reset to 0. balance: Option>, - /// If None, the code_hash remains untouched. + /// If Some(_), then a contract is instantiated with the code hash. If None and `reset` is false, + /// then the contract code is unmodified. If None and `reset` is true, the contract is deleted. code_hash: Option>, + /// If Some(_), then the rent allowance is set to the value. If None and `reset` is false, then + /// the rent allowance is unmodified. If None and `reset` is true, the contract is deleted. rent_allowance: Option>, storage: BTreeMap>>, + /// If true, indicates that the existing contract and all its storage entries should be removed + /// and replaced with the fields on this change entry. Otherwise, the fields on this change + /// entry are updates merged into the existing contract info and storage. + reset: bool, +} + +impl ChangeEntry { + fn balance(&self) -> Option> { + self.balance.or_else(|| { + if self.reset { + Some(>::zero()) + } else { + None + } + }) + } + + fn code_hash(&self) -> Option>> { + if self.reset { + Some(self.code_hash) + } else { + self.code_hash.map(Some) + } + } + + fn rent_allowance(&self) -> Option>> { + if self.reset { + Some(self.rent_allowance) + } else { + self.rent_allowance.map(Some) + } + } + + fn storage(&self, location: &StorageKey) -> Option>> { + let value = self.storage.get(location).cloned(); + if self.reset { + Some(value.unwrap_or(None)) + } else { + value + } + } } // Cannot derive(Default) since it erroneously bounds T by Default. @@ -49,6 +95,7 @@ impl Default for ChangeEntry { balance: Default::default(), code_hash: Default::default(), storage: Default::default(), + reset: false, } } } @@ -98,7 +145,7 @@ impl AccountDb for DirectAccountDb { fn commit(&mut self, s: ChangeSet) { let mut total_imbalance = SignedImbalance::zero(); for (address, changed) in s.into_iter() { - if let Some(balance) = changed.balance { + if let Some(balance) = changed.balance() { let (imbalance, outcome) = T::Currency::make_free_balance_be(&address, balance); total_imbalance = total_imbalance.merge(imbalance); if let UpdateBalanceOutcome::AccountKilled = outcome { @@ -109,9 +156,10 @@ impl AccountDb for DirectAccountDb { } } - if changed.code_hash.is_some() - || changed.rent_allowance.is_some() + if changed.code_hash().is_some() + || changed.rent_allowance().is_some() || !changed.storage.is_empty() + || changed.reset { let old_info = match >::get(&address) { Some(ContractInfo::Alive(alive)) => Some(alive), @@ -120,20 +168,40 @@ impl AccountDb for DirectAccountDb { Some(ContractInfo::Tombstone(_)) => continue, }; - let mut new_info = if let Some(info) = old_info.clone() { - info - } else if let Some(code_hash) = changed.code_hash { - AliveContractInfo:: { - code_hash, - storage_size: T::StorageSizeOffset::get(), - trie_id: ::TrieIdGenerator::trie_id(&address), - deduct_block: >::block_number(), - rent_allowance: >::max_value(), - last_write: None, + let mut new_info = match (changed.reset, old_info.clone(), changed.code_hash) { + // Existing contract is being modified. + (false, Some(info), _) => info, + // Existing contract is being removed. + (true, Some(info), None) => { + child::kill_storage(&info.trie_id); + >::remove(&address); + continue; } - } else { - // No contract exist and no code_hash provided - continue; + // Existing contract is being replaced by a new one. + (true, Some(info), Some(code_hash)) => { + child::kill_storage(&info.trie_id); + AliveContractInfo:: { + code_hash, + storage_size: T::StorageSizeOffset::get(), + trie_id: ::TrieIdGenerator::trie_id(&address), + deduct_block: >::block_number(), + rent_allowance: >::max_value(), + last_write: None, + } + } + // New contract is being instantiated. + (_, None, Some(code_hash)) => { + AliveContractInfo:: { + code_hash, + storage_size: T::StorageSizeOffset::get(), + trie_id: ::TrieIdGenerator::trie_id(&address), + deduct_block: >::block_number(), + rent_allowance: >::max_value(), + last_write: None, + } + } + // There is no existing at the address nor a new one to be instantiated. + (_, None, None) => continue, }; if let Some(rent_allowance) = changed.rent_allowance { @@ -210,7 +278,7 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { } /// Return an error if contract already exists (either if it is alive or tombstone) - pub fn create_contract( + pub fn instantiate_contract( &mut self, account: &T::AccountId, code_hash: CodeHash, @@ -227,6 +295,19 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { Ok(()) } + + /// Mark a contract as deleted. + pub fn destroy_contract(&mut self, account: &T::AccountId) { + let mut local = self.local.borrow_mut(); + local.insert( + account.clone(), + ChangeEntry { + reset: true, + ..Default::default() + } + ); + } + /// Assume contract exists pub fn set_rent_allowance(&mut self, account: &T::AccountId, rent_allowance: BalanceOf) { self.local @@ -254,36 +335,35 @@ impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { self.local .borrow() .get(account) - .and_then(|a| a.storage.get(location)) - .cloned() + .and_then(|changes| changes.storage(location)) .unwrap_or_else(|| self.underlying.get_storage(account, trie_id, location)) } fn get_code_hash(&self, account: &T::AccountId) -> Option> { self.local .borrow() .get(account) - .and_then(|changes| changes.code_hash) - .or_else(|| self.underlying.get_code_hash(account)) + .and_then(|changes| changes.code_hash()) + .unwrap_or_else(|| self.underlying.get_code_hash(account)) } fn get_rent_allowance(&self, account: &T::AccountId) -> Option> { self.local .borrow() .get(account) - .and_then(|changes| changes.rent_allowance) - .or_else(|| self.underlying.get_rent_allowance(account)) + .and_then(|changes| changes.rent_allowance()) + .unwrap_or_else(|| self.underlying.get_rent_allowance(account)) } fn contract_exists(&self, account: &T::AccountId) -> bool { self.local .borrow() .get(account) - .map(|a| a.code_hash.is_some()) + .and_then(|changes| changes.code_hash().map(|code_hash| code_hash.is_some())) .unwrap_or_else(|| self.underlying.contract_exists(account)) } fn get_balance(&self, account: &T::AccountId) -> BalanceOf { self.local .borrow() .get(account) - .and_then(|a| a.balance) + .and_then(|changes| changes.balance()) .unwrap_or_else(|| self.underlying.get_balance(account)) } fn commit(&mut self, s: ChangeSet) { @@ -293,10 +373,14 @@ impl<'a, T: Trait> AccountDb for OverlayAccountDb<'a, T> { match local.entry(address) { Entry::Occupied(e) => { let mut value = e.into_mut(); - value.balance = changed.balance.or(value.balance); - value.code_hash = changed.code_hash.or(value.code_hash); - value.rent_allowance = changed.rent_allowance.or(value.rent_allowance); - value.storage.extend(changed.storage.into_iter()); + if changed.reset { + *value = changed; + } else { + value.balance = changed.balance.or(value.balance); + value.code_hash = changed.code_hash.or(value.code_hash); + value.rent_allowance = changed.rent_allowance.or(value.rent_allowance); + value.storage.extend(changed.storage.into_iter()); + } } Entry::Vacant(e) => { e.insert(changed); diff --git a/srml/contracts/src/exec.rs b/srml/contracts/src/exec.rs index 5ba02d43a0ffe68d1d99bdf4e260a4b35a043b47..08fd8999a4780d56b95ab721031da82558a00abc 100644 --- a/srml/contracts/src/exec.rs +++ b/srml/contracts/src/exec.rs @@ -22,14 +22,14 @@ use crate::rent; use rstd::prelude::*; use sr_primitives::traits::{Bounded, CheckedAdd, CheckedSub, Zero}; -use srml_support::traits::{WithdrawReason, Currency}; -use timestamp; +use support::traits::{WithdrawReason, Currency, Time, Randomness}; pub type AccountIdOf = ::AccountId; pub type CallOf = ::Call; -pub type MomentOf = ::Moment; +pub type MomentOf = <::Time as Time>::Moment; pub type SeedOf = ::Hash; pub type BlockNumberOf = ::BlockNumber; +pub type StorageKey = [u8; 32]; /// A type that represents a topic of an event. At the moment a hash is used. pub type TopicOf = ::Hash; @@ -61,7 +61,7 @@ impl ExecReturnValue { /// VM-specific errors during execution (eg. division by 0, OOB access, failure to satisfy some /// precondition of a system call, etc.) or errors with the orchestration (eg. out-of-gas errors, a /// non-existent destination contract, etc.). -#[cfg_attr(test, derive(Debug))] +#[cfg_attr(test, derive(sr_primitives::RuntimeDebug))] pub struct ExecError { pub reason: &'static str, /// This is an allocated buffer that may be reused. The buffer must be cleared explicitly @@ -75,17 +75,16 @@ pub type ExecResult = Result; /// wrap the error string into an ExecutionError with the provided buffer and return from the /// enclosing function. This macro is used instead of .map_err(..)? in order to avoid taking /// ownership of buffer unless there is an error. +#[macro_export] macro_rules! try_or_exec_error { ($e:expr, $buffer:expr) => { match $e { Ok(val) => val, - Err(reason) => return Err(ExecError { reason, buffer: $buffer }), + Err(reason) => return Err($crate::exec::ExecError { reason, buffer: $buffer }), } } } -pub type StorageKey = [u8; 32]; - /// An interface that provides access to the external environment in which the /// smart-contract is executed. /// @@ -154,6 +153,9 @@ pub trait Ext { /// Returns a reference to the timestamp of the current block fn now(&self) -> &MomentOf; + /// Returns the minimum balance that is required for creating an account. + fn minimum_balance(&self) -> BalanceOf; + /// Returns a random number for the current block with the given subject. fn random(&self, subject: &[u8]) -> SeedOf; @@ -188,15 +190,6 @@ pub trait Loader { fn load_main(&self, code_hash: &CodeHash) -> Result; } -/// Struct that records a request to deposit an event with a list of topics. -#[cfg_attr(any(feature = "std", test), derive(Debug, PartialEq, Eq))] -pub struct IndexedEvent { - /// A list of topics this event will be deposited with. - pub topics: Vec, - /// The event to deposit. - pub event: Event, -} - /// A trait that represent a virtual machine. /// /// You can view a virtual machine as something that takes code, an input data buffer, @@ -237,7 +230,8 @@ impl Token for ExecFeeToken { } } -#[cfg_attr(any(feature = "std", test), derive(Debug, PartialEq, Eq, Clone))] +#[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq, Clone))] +#[derive(sr_primitives::RuntimeDebug)] pub enum DeferredAction { DepositEvent { /// A list of topics this event will be deposited with. @@ -267,6 +261,7 @@ pub enum DeferredAction { } pub struct ExecutionContext<'a, T: Trait + 'a, V, L> { + pub parent: Option<&'a ExecutionContext<'a, T, V, L>>, pub self_account: T::AccountId, pub self_trie_id: Option, pub overlay: OverlayAccountDb<'a, T>, @@ -275,7 +270,7 @@ pub struct ExecutionContext<'a, T: Trait + 'a, V, L> { pub config: &'a Config, pub vm: &'a V, pub loader: &'a L, - pub timestamp: T::Moment, + pub timestamp: MomentOf, pub block_number: T::BlockNumber, } @@ -291,6 +286,7 @@ where /// account (not a contract). pub fn top_level(origin: T::AccountId, cfg: &'a Config, vm: &'a V, loader: &'a L) -> Self { ExecutionContext { + parent: None, self_trie_id: None, self_account: origin, overlay: OverlayAccountDb::::new(&DirectAccountDb), @@ -299,7 +295,7 @@ where config: &cfg, vm: &vm, loader: &loader, - timestamp: >::now(), + timestamp: T::Time::now(), block_number: >::block_number(), } } @@ -308,6 +304,7 @@ where -> ExecutionContext<'b, T, V, L> { ExecutionContext { + parent: Some(self), self_trie_id: trie_id, self_account: dest, overlay: OverlayAccountDb::new(&self.overlay), @@ -385,13 +382,29 @@ where nested.loader.load_main(&dest_code_hash), input_data ); - nested.vm + let output = nested.vm .execute( &executable, nested.new_call_context(caller, value), input_data, gas_meter, - ) + )?; + + // Destroy contract if insufficient remaining balance. + if nested.overlay.get_balance(&dest) < nested.config.existential_deposit { + let parent = nested.parent + .expect("a nested execution context must have a parent; qed"); + if parent.is_live(&dest) { + return Err(ExecError { + reason: "contract cannot be destroyed during recursive execution", + buffer: output.data, + }); + } + + nested.overlay.destroy_contract(&dest); + } + + Ok(output) } None => Ok(ExecReturnValue { status: STATUS_SUCCESS, data: Vec::new() }), } @@ -407,7 +420,7 @@ where ) -> Result<(T::AccountId, ExecReturnValue), ExecError> { if self.depth == self.config.max_depth as usize { return Err(ExecError { - reason: "reached maximum depth, cannot create", + reason: "reached maximum depth, cannot instantiate", buffer: input_data, }); } @@ -434,7 +447,7 @@ where let output = self.with_nested_context(dest.clone(), dest_trie_id, |nested| { try_or_exec_error!( - nested.overlay.create_contract(&dest, code_hash.clone()), + nested.overlay.instantiate_contract(&dest, code_hash.clone()), input_data ); @@ -464,6 +477,14 @@ where gas_meter, )?; + // Error out if insufficient remaining balance. + if nested.overlay.get_balance(&dest) < nested.config.existential_deposit { + return Err(ExecError { + reason: "insufficient remaining balance", + buffer: output.data, + }); + } + // Deposit an instantiation event. nested.deferred.push(DeferredAction::DepositEvent { event: RawEvent::Instantiated(caller.clone(), dest.clone()), @@ -507,6 +528,13 @@ where Ok(output) } + + /// Returns whether a contract, identified by address, is currently live in the execution + /// stack, meaning it is in the middle of an execution. + fn is_live(&self, account: &T::AccountId) -> bool { + &self.self_account == account || + self.parent.map_or(false, |parent| parent.is_live(account)) + } } #[cfg_attr(test, derive(Debug, PartialEq, Eq))] @@ -613,7 +641,7 @@ fn transfer<'a, T: Trait, V: Vm, L: Loader>( if would_create && value < ctx.config.existential_deposit { return Err("value too low to create account"); } - T::Currency::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?; + T::Currency::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer.into(), new_from_balance)?; let new_to_balance = match to_balance.checked_add(&value) { Some(b) => b, @@ -636,7 +664,7 @@ struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm + 'b, L: Loader> { ctx: &'a mut ExecutionContext<'b, T, V, L>, caller: T::AccountId, value_transferred: BalanceOf, - timestamp: T::Moment, + timestamp: MomentOf, block_number: T::BlockNumber, } @@ -725,13 +753,17 @@ where } fn random(&self, subject: &[u8]) -> SeedOf { - system::Module::::random(subject) + T::Randomness::random(subject) } - fn now(&self) -> &T::Moment { + fn now(&self) -> &MomentOf { &self.timestamp } + fn minimum_balance(&self) -> BalanceOf { + self.ctx.config.existential_deposit + } + fn deposit_event(&mut self, topics: Vec, data: Vec) { self.ctx.deferred.push(DeferredAction::DepositEvent { topics, @@ -771,16 +803,11 @@ mod tests { BalanceOf, ExecFeeToken, ExecutionContext, Ext, Loader, TransferFeeKind, TransferFeeToken, Vm, ExecResult, RawEvent, DeferredAction, }; - use crate::account_db::AccountDb; - use crate::exec::{ExecReturnValue, ExecError, STATUS_SUCCESS}; - use crate::gas::GasMeter; - use crate::tests::{ExtBuilder, Test}; - use crate::{CodeHash, Config}; - use runtime_io::with_externalities; - use std::cell::RefCell; - use std::rc::Rc; - use std::collections::HashMap; - use std::marker::PhantomData; + use crate::{ + account_db::AccountDb, gas::GasMeter, tests::{ExtBuilder, Test}, + exec::{ExecReturnValue, ExecError, STATUS_SUCCESS}, CodeHash, Config, + }; + use std::{cell::RefCell, rc::Rc, collections::HashMap, marker::PhantomData}; use assert_matches::assert_matches; const ALICE: u64 = 1; @@ -905,10 +932,10 @@ mod tests { exec_success() }); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.create_contract(&BOB, exec_ch).unwrap(); + ctx.overlay.instantiate_contract(&BOB, exec_ch).unwrap(); assert_matches!( ctx.call(BOB, value, &mut gas_meter, data), @@ -925,7 +952,7 @@ mod tests { let dest = BOB; // This test verifies that base fee for call is taken. - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let vm = MockVm::new(); let loader = MockLoader::empty(); let cfg = Config::preload(); @@ -943,7 +970,7 @@ mod tests { }); // This test verifies that base fee for instantiation is taken. - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let mut loader = MockLoader::empty(); let code = loader.insert(|_| exec_success()); @@ -973,7 +1000,7 @@ mod tests { let vm = MockVm::new(); let loader = MockLoader::empty(); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); ctx.overlay.set_balance(&origin, 100); @@ -1005,10 +1032,10 @@ mod tests { |_| Ok(ExecReturnValue { status: 1, data: Vec::new() }) ); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.create_contract(&BOB, return_ch).unwrap(); + ctx.overlay.instantiate_contract(&BOB, return_ch).unwrap(); ctx.overlay.set_balance(&origin, 100); ctx.overlay.set_balance(&dest, 0); @@ -1031,95 +1058,86 @@ mod tests { let dest = BOB; // This test sends 50 units of currency to a non-existent account. - // This should create lead to creation of a new account thus + // This should lead to creation of a new account thus // a fee should be charged. - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let vm = MockVm::new(); - let loader = MockLoader::empty(); - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.set_balance(&origin, 100); - ctx.overlay.set_balance(&dest, 0); - - let mut gas_meter = GasMeter::::with_limit(1000, 1); - - let result = ctx.call(dest, 50, &mut gas_meter, vec![]); - assert_matches!(result, Ok(_)); - - let mut toks = gas_meter.tokens().iter(); - match_tokens!( - toks, - ExecFeeToken::Call, - TransferFeeToken { - kind: TransferFeeKind::AccountCreate, - gas_price: 1u64 - }, - ); - }, - ); + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let vm = MockVm::new(); + let loader = MockLoader::empty(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 0); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.call(dest, 50, &mut gas_meter, vec![]); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!( + toks, + ExecFeeToken::Call, + TransferFeeToken { + kind: TransferFeeKind::AccountCreate, + gas_price: 1u64 + }, + ); + }); // This one is similar to the previous one but transfer to an existing account. // In this test we expect that a regular transfer fee is charged. - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let vm = MockVm::new(); - let loader = MockLoader::empty(); - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.set_balance(&origin, 100); - ctx.overlay.set_balance(&dest, 15); - - let mut gas_meter = GasMeter::::with_limit(1000, 1); - - let result = ctx.call(dest, 50, &mut gas_meter, vec![]); - assert_matches!(result, Ok(_)); - - let mut toks = gas_meter.tokens().iter(); - match_tokens!( - toks, - ExecFeeToken::Call, - TransferFeeToken { - kind: TransferFeeKind::Transfer, - gas_price: 1u64 - }, - ); - }, - ); + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let vm = MockVm::new(); + let loader = MockLoader::empty(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 15); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.call(dest, 50, &mut gas_meter, vec![]); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!( + toks, + ExecFeeToken::Call, + TransferFeeToken { + kind: TransferFeeKind::Transfer, + gas_price: 1u64 + }, + ); + }); // This test sends 50 units of currency as an endownment to a newly - // created contract. - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let mut loader = MockLoader::empty(); - let code = loader.insert(|_| exec_success()); - - let vm = MockVm::new(); - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - - ctx.overlay.set_balance(&origin, 100); - ctx.overlay.set_balance(&dest, 15); - - let mut gas_meter = GasMeter::::with_limit(1000, 1); - - let result = ctx.instantiate(50, &mut gas_meter, &code, vec![]); - assert_matches!(result, Ok(_)); - - let mut toks = gas_meter.tokens().iter(); - match_tokens!( - toks, - ExecFeeToken::Instantiate, - TransferFeeToken { - kind: TransferFeeKind::ContractInstantiate, - gas_price: 1u64 - }, - ); - }, - ); + // instantiated contract. + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let mut loader = MockLoader::empty(); + let code = loader.insert(|_| exec_success()); + + let vm = MockVm::new(); + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); + + ctx.overlay.set_balance(&origin, 100); + ctx.overlay.set_balance(&dest, 15); + + let mut gas_meter = GasMeter::::with_limit(1000, 1); + + let result = ctx.instantiate(50, &mut gas_meter, &code, vec![]); + assert_matches!(result, Ok(_)); + + let mut toks = gas_meter.tokens().iter(); + match_tokens!( + toks, + ExecFeeToken::Instantiate, + TransferFeeToken { + kind: TransferFeeKind::ContractInstantiate, + gas_price: 1u64 + }, + ); + }); } #[test] @@ -1132,7 +1150,7 @@ mod tests { let vm = MockVm::new(); let loader = MockLoader::empty(); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); ctx.overlay.set_balance(&origin, 0); @@ -1166,10 +1184,10 @@ mod tests { |_| Ok(ExecReturnValue { status: STATUS_SUCCESS, data: vec![1, 2, 3, 4] }) ); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.create_contract(&BOB, return_ch).unwrap(); + ctx.overlay.instantiate_contract(&BOB, return_ch).unwrap(); let result = ctx.call( dest, @@ -1197,10 +1215,10 @@ mod tests { |_| Ok(ExecReturnValue { status: 1, data: vec![1, 2, 3, 4] }) ); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.create_contract(&BOB, return_ch).unwrap(); + ctx.overlay.instantiate_contract(&BOB, return_ch).unwrap(); let result = ctx.call( dest, @@ -1225,10 +1243,10 @@ mod tests { }); // This one tests passing the input data into a contract via call. - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.create_contract(&BOB, input_data_ch).unwrap(); + ctx.overlay.instantiate_contract(&BOB, input_data_ch).unwrap(); let result = ctx.call( BOB, @@ -1250,7 +1268,7 @@ mod tests { }); // This one tests passing the input data into a contract via instantiate. - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); @@ -1294,10 +1312,10 @@ mod tests { exec_success() }); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.create_contract(&BOB, recurse_ch).unwrap(); + ctx.overlay.instantiate_contract(&BOB, recurse_ch).unwrap(); let result = ctx.call( BOB, @@ -1338,12 +1356,12 @@ mod tests { exec_success() }); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(origin, &cfg, &vm, &loader); - ctx.overlay.create_contract(&dest, bob_ch).unwrap(); - ctx.overlay.create_contract(&CHARLIE, charlie_ch).unwrap(); + ctx.overlay.instantiate_contract(&dest, bob_ch).unwrap(); + ctx.overlay.instantiate_contract(&CHARLIE, charlie_ch).unwrap(); let result = ctx.call( dest, @@ -1380,11 +1398,11 @@ mod tests { exec_success() }); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.create_contract(&BOB, bob_ch).unwrap(); - ctx.overlay.create_contract(&CHARLIE, charlie_ch).unwrap(); + ctx.overlay.instantiate_contract(&BOB, bob_ch).unwrap(); + ctx.overlay.instantiate_contract(&CHARLIE, charlie_ch).unwrap(); let result = ctx.call( BOB, @@ -1404,23 +1422,20 @@ mod tests { let mut loader = MockLoader::empty(); let dummy_ch = loader.insert(|_| exec_success()); - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - assert_matches!( - ctx.instantiate( - 0, // <- zero endowment - &mut GasMeter::::with_limit(10000, 1), - &dummy_ch, - vec![], - ), - Err(_) - ); - } - ); + assert_matches!( + ctx.instantiate( + 0, // <- zero endowment + &mut GasMeter::::with_limit(10000, 1), + &dummy_ch, + vec![], + ), + Err(_) + ); + }); } #[test] @@ -1432,38 +1447,35 @@ mod tests { |_| Ok(ExecReturnValue { status: STATUS_SUCCESS, data: vec![80, 65, 83, 83] }) ); - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.set_balance(&ALICE, 1000); - - let created_contract_address = assert_matches!( - ctx.instantiate( - 100, - &mut GasMeter::::with_limit(10000, 1), - &dummy_ch, - vec![], - ), - Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address - ); + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_balance(&ALICE, 1000); - // Check that the newly created account has the expected code hash and - // there are instantiation event. - assert_eq!(ctx.overlay.get_code_hash(&created_contract_address).unwrap(), dummy_ch); - assert_eq!(&ctx.events(), &[ - DeferredAction::DepositEvent { - event: RawEvent::Transfer(ALICE, created_contract_address, 100), - topics: Vec::new(), - }, - DeferredAction::DepositEvent { - event: RawEvent::Instantiated(ALICE, created_contract_address), - topics: Vec::new(), - } - ]); - } - ); + let instantiated_contract_address = assert_matches!( + ctx.instantiate( + 100, + &mut GasMeter::::with_limit(10000, 1), + &dummy_ch, + vec![], + ), + Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address + ); + + // Check that the newly created account has the expected code hash and + // there are instantiation event. + assert_eq!(ctx.overlay.get_code_hash(&instantiated_contract_address).unwrap(), dummy_ch); + assert_eq!(&ctx.events(), &[ + DeferredAction::DepositEvent { + event: RawEvent::Transfer(ALICE, instantiated_contract_address, 100), + topics: Vec::new(), + }, + DeferredAction::DepositEvent { + event: RawEvent::Instantiated(ALICE, instantiated_contract_address), + topics: Vec::new(), + } + ]); + }); } #[test] @@ -1475,28 +1487,25 @@ mod tests { |_| Ok(ExecReturnValue { status: 1, data: vec![70, 65, 73, 76] }) ); - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.set_balance(&ALICE, 1000); - - let created_contract_address = assert_matches!( - ctx.instantiate( - 100, - &mut GasMeter::::with_limit(10000, 1), - &dummy_ch, - vec![], - ), - Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address - ); + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_balance(&ALICE, 1000); - // Check that the account has not been created. - assert!(ctx.overlay.get_code_hash(&created_contract_address).is_none()); - assert!(ctx.events().is_empty()); - } - ); + let instantiated_contract_address = assert_matches!( + ctx.instantiate( + 100, + &mut GasMeter::::with_limit(10000, 1), + &dummy_ch, + vec![], + ), + Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address + ); + + // Check that the account has not been created. + assert!(ctx.overlay.get_code_hash(&instantiated_contract_address).is_none()); + assert!(ctx.events().is_empty()); + }); } #[test] @@ -1505,12 +1514,12 @@ mod tests { let mut loader = MockLoader::empty(); let dummy_ch = loader.insert(|_| exec_success()); - let created_contract_address = Rc::new(RefCell::new(None::)); - let creator_ch = loader.insert({ + let instantiated_contract_address = Rc::new(RefCell::new(None::)); + let instantiator_ch = loader.insert({ let dummy_ch = dummy_ch.clone(); - let created_contract_address = Rc::clone(&created_contract_address); + let instantiated_contract_address = Rc::clone(&instantiated_contract_address); move |ctx| { - // Instantiate a contract and save it's address in `created_contract_address`. + // Instantiate a contract and save it's address in `instantiated_contract_address`. let (address, output) = ctx.ext.instantiate( &dummy_ch, 15u64, @@ -1518,45 +1527,42 @@ mod tests { vec![] ).unwrap(); - *created_contract_address.borrow_mut() = address.into(); + *instantiated_contract_address.borrow_mut() = address.into(); Ok(output) } }); - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.set_balance(&ALICE, 1000); - ctx.overlay.create_contract(&BOB, creator_ch).unwrap(); + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_balance(&ALICE, 1000); + ctx.overlay.instantiate_contract(&BOB, instantiator_ch).unwrap(); - assert_matches!( - ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), vec![]), - Ok(_) - ); + assert_matches!( + ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), vec![]), + Ok(_) + ); - let created_contract_address = created_contract_address.borrow().as_ref().unwrap().clone(); - - // Check that the newly created account has the expected code hash and - // there are instantiation event. - assert_eq!(ctx.overlay.get_code_hash(&created_contract_address).unwrap(), dummy_ch); - assert_eq!(&ctx.events(), &[ - DeferredAction::DepositEvent { - event: RawEvent::Transfer(ALICE, BOB, 20), - topics: Vec::new(), - }, - DeferredAction::DepositEvent { - event: RawEvent::Transfer(BOB, created_contract_address, 15), - topics: Vec::new(), - }, - DeferredAction::DepositEvent { - event: RawEvent::Instantiated(BOB, created_contract_address), - topics: Vec::new(), - }, - ]); - } - ); + let instantiated_contract_address = instantiated_contract_address.borrow().as_ref().unwrap().clone(); + + // Check that the newly created account has the expected code hash and + // there are instantiation event. + assert_eq!(ctx.overlay.get_code_hash(&instantiated_contract_address).unwrap(), dummy_ch); + assert_eq!(&ctx.events(), &[ + DeferredAction::DepositEvent { + event: RawEvent::Transfer(ALICE, BOB, 20), + topics: Vec::new(), + }, + DeferredAction::DepositEvent { + event: RawEvent::Transfer(BOB, instantiated_contract_address, 15), + topics: Vec::new(), + }, + DeferredAction::DepositEvent { + event: RawEvent::Instantiated(BOB, instantiated_contract_address), + topics: Vec::new(), + }, + ]); + }); } #[test] @@ -1567,10 +1573,10 @@ mod tests { let dummy_ch = loader.insert( |_| Err(ExecError { reason: "It's a trap!", buffer: Vec::new() }) ); - let creator_ch = loader.insert({ + let instantiator_ch = loader.insert({ let dummy_ch = dummy_ch.clone(); move |ctx| { - // Instantiate a contract and save it's address in `created_contract_address`. + // Instantiate a contract and save it's address in `instantiated_contract_address`. assert_matches!( ctx.ext.instantiate( &dummy_ch, @@ -1585,29 +1591,26 @@ mod tests { } }); - with_externalities( - &mut ExtBuilder::default().existential_deposit(15).build(), - || { - let cfg = Config::preload(); - let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); - ctx.overlay.set_balance(&ALICE, 1000); - ctx.overlay.create_contract(&BOB, creator_ch).unwrap(); + ExtBuilder::default().existential_deposit(15).build().execute_with(|| { + let cfg = Config::preload(); + let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); + ctx.overlay.set_balance(&ALICE, 1000); + ctx.overlay.instantiate_contract(&BOB, instantiator_ch).unwrap(); - assert_matches!( - ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), vec![]), - Ok(_) - ); + assert_matches!( + ctx.call(BOB, 20, &mut GasMeter::::with_limit(1000, 1), vec![]), + Ok(_) + ); - // The contract wasn't created so we don't expect to see an instantiation - // event here. - assert_eq!(&ctx.events(), &[ - DeferredAction::DepositEvent { - event: RawEvent::Transfer(ALICE, BOB, 20), - topics: Vec::new(), - }, - ]); - } - ); + // The contract wasn't instantiated so we don't expect to see an instantiation + // event here. + assert_eq!(&ctx.events(), &[ + DeferredAction::DepositEvent { + event: RawEvent::Transfer(ALICE, BOB, 20), + topics: Vec::new(), + }, + ]); + }); } #[test] @@ -1621,7 +1624,7 @@ mod tests { exec_success() }); - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let cfg = Config::preload(); let mut ctx = ExecutionContext::top_level(ALICE, &cfg, &vm, &loader); diff --git a/srml/contracts/src/gas.rs b/srml/contracts/src/gas.rs index a5811e81a0c3bd3fe54df01b72ccd8d188aabf3d..64997fbe81fdf6c697b752dbe62afa11c64a6726 100644 --- a/srml/contracts/src/gas.rs +++ b/srml/contracts/src/gas.rs @@ -16,10 +16,12 @@ use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; use rstd::convert::TryFrom; -use sr_primitives::BLOCK_FULL; -use sr_primitives::traits::{CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto}; -use srml_support::StorageValue; -use srml_support::traits::{Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReason}; +use sr_primitives::traits::{ + CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto, +}; +use support::{ + traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReason}, StorageValue, +}; #[cfg(test)] use std::{any::Any, fmt::Debug}; @@ -200,14 +202,6 @@ pub fn buy_gas( transactor: &T::AccountId, gas_limit: Gas, ) -> Result<(GasMeter, NegativeImbalanceOf), &'static str> { - // Check if the specified amount of gas is available in the current block. - // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. - let gas_available = T::BlockGasLimit::get() - >::gas_spent(); - if gas_limit > gas_available { - // gas limit reached, revert the transaction and retry again in the future - return Err(BLOCK_FULL); - } - // Buy the specified amount of gas. let gas_price = >::gas_price(); let cost = if gas_price.is_zero() { @@ -221,7 +215,7 @@ pub fn buy_gas( let imbalance = T::Currency::withdraw( transactor, cost, - WithdrawReason::Fee, + WithdrawReason::Fee.into(), ExistenceRequirement::KeepAlive )?; diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 9f9fae52922bfe87ab66097f43a3a66e6f55917d..df38747cc5d521aa3048fc50314e3f00cd92ccde 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -25,14 +25,14 @@ //! //! This module extends accounts based on the `Currency` trait to have smart-contract functionality. It can //! be used with other modules that implement accounts based on `Currency`. These "smart-contract accounts" -//! have the ability to create smart-contracts and make calls to other contract and non-contract accounts. +//! have the ability to instantiate smart-contracts and make calls to other contract and non-contract accounts. //! //! The smart-contract code is stored once in a `code_cache`, and later retrievable via its `code_hash`. //! This means that multiple smart-contracts can be instantiated from the same `code_cache`, without replicating //! the code each time. //! //! When a smart-contract is called, its associated code is retrieved via the code hash and gets executed. -//! This call can alter the storage entries of the smart-contract account, create new smart-contracts, +//! This call can alter the storage entries of the smart-contract account, instantiate new smart-contracts, //! or call other smart-contracts. //! //! Finally, when an account is reaped, its associated code and storage of the smart-contract account @@ -59,14 +59,24 @@ //! ### Dispatchable functions //! //! * `put_code` - Stores the given binary Wasm code into the chain's storage and returns its `code_hash`. -//! * `create` - Deploys a new contract from the given `code_hash`, optionally transferring some balance. -//! This creates a new smart contract account and calls its contract deploy handler to initialize the contract. +//! * `instantiate` - Deploys a new contract from the given `code_hash`, optionally transferring some balance. +//! This instantiates a new smart contract account and calls its contract deploy handler to +//! initialize the contract. //! * `call` - Makes a call to an account, optionally transferring some balance. //! +//! ### Signed Extensions +//! +//! The contracts module defines the following extension: +//! +//! - [`CheckBlockGasLimit`]: Ensures that the transaction does not exceeds the block gas limit. +//! +//! The signed extension needs to be added as signed extra to the transaction type to be used in the +//! runtime. +//! //! ## Usage //! -//! The Contract module is a work in progress. The following examples show how this Contract module can be -//! used to create and call contracts. +//! The Contract module is a work in progress. The following examples show how this Contract module +//! can be used to instantiate and call contracts. //! //! * [`ink`](https://github.com/paritytech/ink) is //! an [`eDSL`](https://wiki.haskell.org/Embedded_domain_specific_language) that enables writing @@ -89,29 +99,35 @@ mod rent; #[cfg(test)] mod tests; -use crate::exec::{ExecutionContext, ExecResult}; +use crate::exec::ExecutionContext; use crate::account_db::{AccountDb, DirectAccountDb}; -pub use crate::gas::{Gas, GasMeter}; use crate::wasm::{WasmLoader, WasmVm}; +pub use crate::gas::{Gas, GasMeter}; +pub use crate::exec::{ExecResult, ExecReturnValue, ExecError, StatusCode}; + #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; use primitives::crypto::UncheckedFrom; -use rstd::{prelude::*, marker::PhantomData}; +use rstd::{prelude::*, marker::PhantomData, fmt::Debug}; use codec::{Codec, Encode, Decode}; use runtime_io::blake2_256; -use sr_primitives::traits::{ - Hash, StaticLookup, Zero, MaybeSerializeDebug, Member +use sr_primitives::{ + traits::{Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension}, + weights::DispatchInfo, + transaction_validity::{ + ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError, + }, + RuntimeDebug, }; -use srml_support::dispatch::{Result, Dispatchable}; -use srml_support::{ - Parameter, StorageMap, StorageValue, decl_module, decl_event, decl_storage, storage::child, - parameter_types, +use support::dispatch::{Result, Dispatchable}; +use support::{ + Parameter, decl_module, decl_event, decl_storage, storage::child, + parameter_types, IsSubType }; -use srml_support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get}; +use support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get, Time, Randomness}; use system::{ensure_signed, RawOrigin, ensure_root}; use primitives::storage::well_known_keys::CHILD_STORAGE_KEY_PREFIX; -use timestamp; pub type CodeHash = ::Hash; pub type TrieId = Vec; @@ -128,8 +144,7 @@ pub trait ComputeDispatchFee { /// Information for managing an acocunt and its sub trie abstraction. /// This is the required info to cache for an account -#[derive(Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, RuntimeDebug)] pub enum ContractInfo { Alive(AliveContractInfo), Tombstone(TombstoneContractInfo), @@ -192,9 +207,7 @@ pub type AliveContractInfo = /// Information for managing an account and its sub trie abstraction. /// This is the required info to cache for an account. -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct RawAliveContractInfo { /// Unique ID for the subtree encoded as a bytes vector. pub trie_id: TrieId, @@ -213,15 +226,14 @@ pub struct RawAliveContractInfo { pub type TombstoneContractInfo = RawTombstoneContractInfo<::Hash, ::Hashing>; -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Encode, Decode, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)] pub struct RawTombstoneContractInfo(H, PhantomData); impl RawTombstoneContractInfo where - H: Member + MaybeSerializeDebug + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + rstd::hash::Hash - + Codec, + H: Member + MaybeSerializeDeserialize+ Debug + + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + + rstd::hash::Hash + Codec, Hasher: Hash, { fn new(storage_root: &[u8], code_hash: H) -> Self { @@ -283,56 +295,58 @@ pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; parameter_types! { - /// A resonable default value for [`Trait::SignedClaimedHandicap`]. + /// A reasonable default value for [`Trait::SignedClaimedHandicap`]. pub const DefaultSignedClaimHandicap: u32 = 2; - /// A resonable default value for [`Trait::TombstoneDeposit`]. + /// A reasonable default value for [`Trait::TombstoneDeposit`]. pub const DefaultTombstoneDeposit: u32 = 16; - /// A resonable default value for [`Trait::StorageSizeOffset`]. + /// A reasonable default value for [`Trait::StorageSizeOffset`]. pub const DefaultStorageSizeOffset: u32 = 8; - /// A resonable default value for [`Trait::RentByteFee`]. + /// A reasonable default value for [`Trait::RentByteFee`]. pub const DefaultRentByteFee: u32 = 4; - /// A resonable default value for [`Trait::RentDepositOffset`]. + /// A reasonable default value for [`Trait::RentDepositOffset`]. pub const DefaultRentDepositOffset: u32 = 1000; - /// A resonable default value for [`Trait::SurchargeReward`]. + /// A reasonable default value for [`Trait::SurchargeReward`]. pub const DefaultSurchargeReward: u32 = 150; - /// A resonable default value for [`Trait::TransferFee`]. + /// A reasonable default value for [`Trait::TransferFee`]. pub const DefaultTransferFee: u32 = 0; - /// A resonable default value for [`Trait::CreationFee`]. - pub const DefaultCreationFee: u32 = 0; - /// A resonable default value for [`Trait::TransactionBaseFee`]. + /// A reasonable default value for [`Trait::InstantiationFee`]. + pub const DefaultInstantiationFee: u32 = 0; + /// A reasonable default value for [`Trait::TransactionBaseFee`]. pub const DefaultTransactionBaseFee: u32 = 0; - /// A resonable default value for [`Trait::TransactionByteFee`]. + /// A reasonable default value for [`Trait::TransactionByteFee`]. pub const DefaultTransactionByteFee: u32 = 0; - /// A resonable default value for [`Trait::ContractFee`]. + /// A reasonable default value for [`Trait::ContractFee`]. pub const DefaultContractFee: u32 = 21; - /// A resonable default value for [`Trait::CallBaseFee`]. + /// A reasonable default value for [`Trait::CallBaseFee`]. pub const DefaultCallBaseFee: u32 = 1000; - /// A resonable default value for [`Trait::CreateBaseFee`]. - pub const DefaultCreateBaseFee: u32 = 1000; - /// A resonable default value for [`Trait::MaxDepth`]. - pub const DefaultMaxDepth: u32 = 1024; - /// A resonable default value for [`Trait::MaxValueSize`]. + /// A reasonable default value for [`Trait::InstantiateBaseFee`]. + pub const DefaultInstantiateBaseFee: u32 = 1000; + /// A reasonable default value for [`Trait::MaxDepth`]. + pub const DefaultMaxDepth: u32 = 32; + /// A reasonable default value for [`Trait::MaxValueSize`]. pub const DefaultMaxValueSize: u32 = 16_384; - /// A resonable default value for [`Trait::BlockGasLimit`]. + /// A reasonable default value for [`Trait::BlockGasLimit`]. pub const DefaultBlockGasLimit: u32 = 10_000_000; } -pub trait Trait: timestamp::Trait { +pub trait Trait: system::Trait { type Currency: Currency; + type Time: Time; + type Randomness: Randomness; /// The outer call dispatch type. - type Call: Parameter + Dispatchable::Origin>; + type Call: Parameter + Dispatchable::Origin> + IsSubType, Self>; /// The overarching event type. type Event: From> + Into<::Event>; - /// A function type to get the contract address given the creator. + /// A function type to get the contract address given the instantiator. type DetermineContractAddress: ContractAddressFor, Self::AccountId>; /// A function type that computes the fee for dispatching the given `Call`. /// - /// It is recommended (though not required) for this function to return a fee that would be taken - /// by the Executive module for regular dispatch. + /// It is recommended (though not required) for this function to return a fee that would be + /// taken by the Executive module for regular dispatch. type ComputeDispatchFee: ComputeDispatchFee<::Call, BalanceOf>; /// trie id generator @@ -341,6 +355,9 @@ pub trait Trait: timestamp::Trait { /// Handler for the unbalanced reduction when making a gas payment. type GasPayment: OnUnbalanced>; + /// Handler for rent payments. + type RentPayment: OnUnbalanced>; + /// Number of block delay an extrinsic claim surcharge has. /// /// When claim surcharge is called by an extrinsic the rent is checked @@ -350,7 +367,7 @@ pub trait Trait: timestamp::Trait { /// The minimum amount required to generate a tombstone. type TombstoneDeposit: Get>; - /// Size of a contract at the time of creation. This is a simple way to ensure + /// Size of a contract at the time of instantiation. This is a simple way to ensure /// that empty contracts eventually gets deleted. type StorageSizeOffset: Get; @@ -382,16 +399,16 @@ pub trait Trait: timestamp::Trait { /// The fee to be paid for making a transaction; the per-byte portion. type TransactionByteFee: Get>; - /// The fee required to create a contract instance. + /// The fee required to instantiate a contract instance. type ContractFee: Get>; /// The base fee charged for calling into a contract. type CallBaseFee: Get; - /// The base fee charged for creating a contract. - type CreateBaseFee: Get; + /// The base fee charged for instantiating a contract. + type InstantiateBaseFee: Get; - /// The maximum nesting level of a call/create stack. + /// The maximum nesting level of a call/instantiate stack. type MaxDepth: Get; /// The maximum size of a storage value in bytes. @@ -425,7 +442,8 @@ where } /// The default dispatch fee computor computes the fee in the same way that -/// the implementation of `MakePayment` for the Balances module does. +/// the implementation of `ChargeTransactionPayment` for the Balances module does. Note that this only takes a fixed +/// fee based on size. Unlike the balances module, weight-fee is applied. pub struct DefaultDispatchFeeComputor(PhantomData); impl ComputeDispatchFee<::Call, BalanceOf> for DefaultDispatchFeeComputor { fn compute_dispatch_fee(call: &::Call) -> BalanceOf { @@ -448,8 +466,8 @@ decl_module! { /// The minimum amount required to generate a tombstone. const TombstoneDeposit: BalanceOf = T::TombstoneDeposit::get(); - /// Size of a contract at the time of creation. This is a simple way to ensure - /// that empty contracts eventually gets deleted. + /// Size of a contract at the time of instantiaion. This is a simple way to ensure that + /// empty contracts eventually gets deleted. const StorageSizeOffset: u32 = T::StorageSizeOffset::get(); /// Price of a byte of storage per one block interval. Should be greater than 0. @@ -480,7 +498,7 @@ decl_module! { /// The fee to be paid for making a transaction; the per-byte portion. const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); - /// The fee required to create a contract instance. A reasonable default value + /// The fee required to instantiate a contract instance. A reasonable default value /// is 21. const ContractFee: BalanceOf = T::ContractFee::get(); @@ -488,11 +506,11 @@ decl_module! { /// value is 135. const CallBaseFee: Gas = T::CallBaseFee::get(); - /// The base fee charged for creating a contract. A reasonable default value + /// The base fee charged for instantiating a contract. A reasonable default value /// is 175. - const CreateBaseFee: Gas = T::CreateBaseFee::get(); + const InstantiateBaseFee: Gas = T::InstantiateBaseFee::get(); - /// The maximum nesting level of a call/create stack. A reasonable default + /// The maximum nesting level of a call/instantiate stack. A reasonable default /// value is 100. const MaxDepth: u32 = T::MaxDepth::get(); @@ -503,7 +521,7 @@ decl_module! { /// default value is 10_000_000. const BlockGasLimit: Gas = T::BlockGasLimit::get(); - fn deposit_event() = default; + fn deposit_event() = default; /// Updates the schedule for metering contracts. /// @@ -559,14 +577,14 @@ decl_module! { let origin = ensure_signed(origin)?; let dest = T::Lookup::lookup(dest)?; - Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { - ctx.call(dest, value, gas_meter, data) - }) + Self::bare_call(origin, dest, value, gas_limit, data) + .map(|_| ()) + .map_err(|e| e.reason) } - /// Creates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance. + /// Instantiates a new contract from the `codehash` generated by `put_code`, optionally transferring some balance. /// - /// Creation is executed as follows: + /// Instantiation is executed as follows: /// /// - The destination address is computed based on the sender and hash of the code. /// - The smart-contract account is created at the computed address. @@ -574,7 +592,7 @@ decl_module! { /// after the execution is saved as the `code` of the account. That code will be invoked /// upon any call received by this account. /// - The contract is initialized. - pub fn create( + pub fn instantiate( origin, #[compact] endowment: BalanceOf, #[compact] gas_limit: Gas, @@ -587,6 +605,8 @@ decl_module! { ctx.instantiate(endowment, gas_meter, &code_hash, data) .map(|(_address, output)| output) }) + .map(|_| ()) + .map_err(|e| e.reason) } /// Allows block producers to claim a small reward for evicting a contract. If a block producer @@ -596,15 +616,17 @@ decl_module! { /// the sender is not eligible for the reward. fn claim_surcharge(origin, dest: T::AccountId, aux_sender: Option) { let origin = origin.into(); - let (signed, rewarded) = match origin { - Ok(system::RawOrigin::Signed(ref account)) if aux_sender.is_none() => { + let (signed, rewarded) = match (origin, aux_sender) { + (Ok(system::RawOrigin::Signed(account)), None) => { (true, account) }, - Ok(system::RawOrigin::None) if aux_sender.is_some() => { - (false, aux_sender.as_ref().expect("checked above")) + (Ok(system::RawOrigin::None), Some(aux_sender)) => { + (false, aux_sender) }, - _ => return Err("Invalid surcharge claim: origin must be signed or \ - inherent and auxiliary sender only provided on inherent") + _ => return Err( + "Invalid surcharge claim: origin must be signed or \ + inherent and auxiliary sender only provided on inherent" + ), }; // Add some advantage for block producers (who send unsigned extrinsics) by @@ -618,7 +640,7 @@ decl_module! { // If poking the contract has lead to eviction of the contract, give out the rewards. if rent::try_evict::(&dest, handicap) == rent::RentOutcome::Evicted { - T::Currency::deposit_into_existing(rewarded, T::SurchargeReward::get())?; + T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?; } } @@ -628,17 +650,68 @@ decl_module! { } } +/// The possible errors that can happen querying the storage of a contract. +pub enum GetStorageError { + /// The given address doesn't point on a contract. + ContractDoesntExist, + /// The specified contract is a tombstone and thus cannot have any storage. + IsTombstone, +} + +/// Public APIs provided by the contracts module. +impl Module { + /// Perform a call to a specified contract. + /// + /// This function is similar to `Self::call`, but doesn't perform any address lookups and better + /// suitable for calling directly from Rust. + pub fn bare_call( + origin: T::AccountId, + dest: T::AccountId, + value: BalanceOf, + gas_limit: Gas, + input_data: Vec, + ) -> ExecResult { + Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { + ctx.call(dest, value, gas_meter, input_data) + }) + } + + /// Query storage of a specified contract under a specified key. + pub fn get_storage( + address: T::AccountId, + key: [u8; 32], + ) -> rstd::result::Result>, GetStorageError> { + let contract_info = >::get(&address) + .ok_or(GetStorageError::ContractDoesntExist)? + .get_alive() + .ok_or(GetStorageError::IsTombstone)?; + + let maybe_value = AccountDb::::get_storage( + &DirectAccountDb, + &address, + Some(&contract_info.trie_id), + &key, + ); + Ok(maybe_value) + } +} + impl Module { fn execute_wasm( origin: T::AccountId, gas_limit: Gas, func: impl FnOnce(&mut ExecutionContext, &mut GasMeter) -> ExecResult - ) -> Result { + ) -> ExecResult { // Pay for the gas upfront. // // NOTE: it is very important to avoid any state changes before // paying for the gas. - let (mut gas_meter, imbalance) = gas::buy_gas::(&origin, gas_limit)?; + let (mut gas_meter, imbalance) = + try_or_exec_error!( + gas::buy_gas::(&origin, gas_limit), + // We don't have a spare buffer here in the first place, so create a new empty one. + Vec::new() + ); let cfg = Config::preload(); let vm = WasmVm::new(&cfg.schedule); @@ -689,8 +762,6 @@ impl Module { }); result - .map(|_| ()) - .map_err(|e| e.reason) } fn restore_to( @@ -773,7 +844,7 @@ decl_event! { ::AccountId, ::Hash { - /// Transfer happened `from` to `to` with given `value` as part of a `call` or `create`. + /// Transfer happened `from` to `to` with given `value` as part of a `call` or `instantiate`. Transfer(AccountId, AccountId, Balance), /// Contract deployed by address at the specified address. @@ -797,9 +868,9 @@ decl_event! { decl_storage! { trait Store for Module as Contract { /// Gas spent so far in this block. - GasSpent get(gas_spent): Gas; + GasSpent get(fn gas_spent): Gas; /// Current cost schedule for contracts. - CurrentSchedule get(current_schedule) config(): Schedule = Schedule::default(); + CurrentSchedule get(fn current_schedule) config(): Schedule = Schedule::default(); /// A mapping from an original code hash to the original code, untouched by instrumentation. pub PristineCode: map CodeHash => Option>; /// A mapping between an original code hash and instrumented wasm code, ready for execution. @@ -809,7 +880,7 @@ decl_storage! { /// The code associated with a given account. pub ContractInfoOf: map T::AccountId => Option>; /// The price of one unit of gas. - GasPrice get(gas_price) config(): BalanceOf = 1.into(); + GasPrice get(fn gas_price) config(): BalanceOf = 1.into(); } } @@ -850,8 +921,8 @@ impl Config { } /// Definition of the cost schedule and other parameterizations for wasm vm. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Clone, Encode, Decode, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] pub struct Schedule { /// Version of the schedule. pub version: u32, @@ -936,3 +1007,67 @@ impl Default for Schedule { } } } + +/// `SignedExtension` that checks if a transaction would exhausts the block gas limit. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckBlockGasLimit(PhantomData); + +impl Default for CheckBlockGasLimit { + fn default() -> Self { + Self(PhantomData) + } +} + +impl rstd::fmt::Debug for CheckBlockGasLimit { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + write!(f, "CheckBlockGasLimit") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for CheckBlockGasLimit { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + _: &Self::AccountId, + call: &Self::Call, + _: DispatchInfo, + _: usize, + ) -> TransactionValidity { + let call = match call.is_sub_type() { + Some(call) => call, + None => return Ok(ValidTransaction::default()), + }; + + match call { + Call::claim_surcharge(_, _) | Call::update_schedule(_) => + Ok(ValidTransaction::default()), + Call::put_code(gas_limit, _) + | Call::call(_, _, gas_limit, _) + | Call::instantiate(_, gas_limit, _, _) + => { + // Check if the specified amount of gas is available in the current block. + // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. + let gas_available = T::BlockGasLimit::get() - >::gas_spent(); + if *gas_limit > gas_available { + // gas limit reached, revert the transaction and retry again in the future + InvalidTransaction::ExhaustsResources.into() + } else { + Ok(ValidTransaction::default()) + } + }, + Call::__PhantomItem(_, _) => unreachable!("Variant is never constructed"), + } + } +} diff --git a/srml/contracts/src/rent.rs b/srml/contracts/src/rent.rs index fea6cdc7f3969577c3e77fc342f6fe3806868eca..6647f8963165dd174bbf10a8d78c673515a1c1d0 100644 --- a/srml/contracts/src/rent.rs +++ b/srml/contracts/src/rent.rs @@ -17,8 +17,8 @@ use crate::{BalanceOf, ContractInfo, ContractInfoOf, TombstoneContractInfo, Trait, AliveContractInfo}; use sr_primitives::traits::{Bounded, CheckedDiv, CheckedMul, Saturating, Zero, SaturatedConversion}; -use srml_support::traits::{Currency, ExistenceRequirement, Get, WithdrawReason}; -use srml_support::StorageMap; +use support::traits::{Currency, ExistenceRequirement, Get, WithdrawReason, OnUnbalanced}; +use support::StorageMap; #[derive(PartialEq, Eq, Copy, Clone)] #[must_use] @@ -119,17 +119,17 @@ fn try_evict_or_and_pay_rent( let can_withdraw_rent = T::Currency::ensure_can_withdraw( account, dues_limited, - WithdrawReason::Fee, + WithdrawReason::Fee.into(), balance.saturating_sub(dues_limited), ) .is_ok(); if can_withdraw_rent && (insufficient_rent || pay_rent) { // Collect dues. - let _ = T::Currency::withdraw( + let imbalance = T::Currency::withdraw( account, dues_limited, - WithdrawReason::Fee, + WithdrawReason::Fee.into(), ExistenceRequirement::KeepAlive, ) .expect( @@ -137,6 +137,8 @@ fn try_evict_or_and_pay_rent( dues_limited < rent_budget < balance - subsistence < balance - existential_deposit; qed", ); + + T::RentPayment::on_unbalanced(imbalance); } if insufficient_rent || !can_withdraw_rent { diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index 9c338a5abd9ac9068f952859a08e9013ea304eb8..7a13a66de26c7a7c41523bc85f725c885852f887 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -19,37 +19,34 @@ #![allow(unused)] -use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; use crate::{ BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, - Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, - TrieIdGenerator, Schedule, + Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule, + TrieIdGenerator, CheckBlockGasLimit, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}, }; use assert_matches::assert_matches; use hex_literal::*; use codec::{Decode, Encode, KeyedVec}; -use runtime_io; -use runtime_io::with_externalities; -use sr_primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, H256}; -use sr_primitives::traits::{BlakeTwo256, Hash, IdentityLookup}; -use sr_primitives::{Perbill, BuildStorage}; -use srml_support::{ +use sr_primitives::{ + Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction}, + traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension}, + weights::{DispatchInfo, DispatchClass}, + testing::{Digest, DigestItem, Header, UintAuthorityId, H256}, +}; +use support::{ assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, - storage::child, StorageMap, StorageValue, traits::{Currency, Get}, + storage::child, StorageMap, StorageValue, traits::{Currency, Get}, }; -use std::cell::RefCell; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}}; use primitives::storage::well_known_keys; -use primitives::Blake2Hasher; use system::{self, EventRecord, Phase}; -use {balances, wabt}; mod contract { // Re-export contents of the root. This basically // needs to give a name for the current crate. // This hack is required for `impl_outer_event!`. pub use super::super::*; - use srml_support::impl_outer_event; + use support::impl_outer_event; } impl_outer_event! { pub enum MetaEvent for Test { @@ -69,7 +66,7 @@ impl_outer_dispatch! { thread_local! { static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); static TRANSFER_FEE: RefCell = RefCell::new(0); - static CREATION_FEE: RefCell = RefCell::new(0); + static INSTANTIATION_FEE: RefCell = RefCell::new(0); static BLOCK_GAS_LIMIT: RefCell = RefCell::new(0); } @@ -85,7 +82,7 @@ impl Get for TransferFee { pub struct CreationFee; impl Get for CreationFee { - fn get() -> u64 { CREATION_FEE.with(|v| *v.borrow()) } + fn get() -> u64 { INSTANTIATION_FEE.with(|v| *v.borrow()) } } pub struct BlockGasLimit; @@ -99,8 +96,6 @@ parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: u32 = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; - pub const BalancesTransactionBaseFee: u64 = 0; - pub const BalancesTransactionByteFee: u64 = 0; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl system::Trait for Test { @@ -113,27 +108,23 @@ impl system::Trait for Test { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = MetaEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } impl balances::Trait for Test { type Balance = u64; type OnFreeBalanceZero = Contract; type OnNewAccount = (); type Event = MetaEvent; - type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; - type TransactionBaseFee = BalancesTransactionBaseFee; - type TransactionByteFee = BalancesTransactionByteFee; - type WeightToFee = (); } parameter_types! { pub const MinimumPeriod: u64 = 1; @@ -154,18 +145,21 @@ parameter_types! { pub const TransactionByteFee: u64 = 6; pub const ContractFee: u64 = 21; pub const CallBaseFee: u64 = 135; - pub const CreateBaseFee: u64 = 175; + pub const InstantiateBaseFee: u64 = 175; pub const MaxDepth: u32 = 100; pub const MaxValueSize: u32 = 16_384; } impl Trait for Test { type Currency = Balances; + type Time = Timestamp; + type Randomness = Randomness; type Call = Call; type DetermineContractAddress = DummyContractAddressFor; type Event = MetaEvent; type ComputeDispatchFee = DummyComputeDispatchFee; type TrieIdGenerator = DummyTrieIdGenerator; type GasPayment = (); + type RentPayment = (); type SignedClaimHandicap = SignedClaimHandicap; type TombstoneDeposit = TombstoneDeposit; type StorageSizeOffset = StorageSizeOffset; @@ -178,15 +172,17 @@ impl Trait for Test { type TransactionByteFee = TransactionByteFee; type ContractFee = ContractFee; type CallBaseFee = CallBaseFee; - type CreateBaseFee = CreateBaseFee; + type InstantiateBaseFee = InstantiateBaseFee; type MaxDepth = MaxDepth; type MaxValueSize = MaxValueSize; type BlockGasLimit = BlockGasLimit; } type Balances = balances::Module; +type Timestamp = timestamp::Module; type Contract = Module; type System = system::Module; +type Randomness = randomness_collective_flip::Module; pub struct DummyContractAddressFor; impl ContractAddressFor for DummyContractAddressFor { @@ -232,7 +228,7 @@ pub struct ExtBuilder { gas_price: u64, block_gas_limit: u64, transfer_fee: u64, - creation_fee: u64, + instantiation_fee: u64, } impl Default for ExtBuilder { fn default() -> Self { @@ -241,7 +237,7 @@ impl Default for ExtBuilder { gas_price: 2, block_gas_limit: 100_000_000, transfer_fee: 0, - creation_fee: 0, + instantiation_fee: 0, } } } @@ -262,17 +258,17 @@ impl ExtBuilder { self.transfer_fee = transfer_fee; self } - pub fn creation_fee(mut self, creation_fee: u64) -> Self { - self.creation_fee = creation_fee; + pub fn instantiation_fee(mut self, instantiation_fee: u64) -> Self { + self.instantiation_fee = instantiation_fee; self } pub fn set_associated_consts(&self) { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee); - CREATION_FEE.with(|v| *v.borrow_mut() = self.creation_fee); + INSTANTIATION_FEE.with(|v| *v.borrow_mut() = self.instantiation_fee); BLOCK_GAS_LIMIT.with(|v| *v.borrow_mut() = self.block_gas_limit); } - pub fn build(self) -> runtime_io::TestExternalities { + pub fn build(self) -> runtime_io::TestExternalities { self.set_associated_consts(); let mut t = system::GenesisConfig::default().build_storage::().unwrap(); balances::GenesisConfig:: { @@ -304,7 +300,7 @@ fn compile_module(wabt_module: &str) // Then we check that the all unused gas is refunded. #[test] fn refunds_unused_gas() { - with_externalities(&mut ExtBuilder::default().gas_price(2).build(), || { + ExtBuilder::default().gas_price(2).build().execute_with(|| { Balances::deposit_creating(&ALICE, 100_000_000); assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, Vec::new())); @@ -316,70 +312,67 @@ fn refunds_unused_gas() { #[test] fn account_removal_removes_storage() { - with_externalities( - &mut ExtBuilder::default().existential_deposit(100).build(), - || { - let trie_id1 = ::TrieIdGenerator::trie_id(&1); - let trie_id2 = ::TrieIdGenerator::trie_id(&2); - let key1 = &[1; 32]; - let key2 = &[2; 32]; - - // Set up two accounts with free balance above the existential threshold. - { - Balances::deposit_creating(&1, 110); - ContractInfoOf::::insert(1, &ContractInfo::Alive(RawAliveContractInfo { - trie_id: trie_id1.clone(), - storage_size: ::StorageSizeOffset::get(), - deduct_block: System::block_number(), - code_hash: H256::repeat_byte(1), - rent_allowance: 40, - last_write: None, - })); - - let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); - overlay.set_storage(&1, key1.clone(), Some(b"1".to_vec())); - overlay.set_storage(&1, key2.clone(), Some(b"2".to_vec())); - DirectAccountDb.commit(overlay.into_change_set()); - - Balances::deposit_creating(&2, 110); - ContractInfoOf::::insert(2, &ContractInfo::Alive(RawAliveContractInfo { - trie_id: trie_id2.clone(), - storage_size: ::StorageSizeOffset::get(), - deduct_block: System::block_number(), - code_hash: H256::repeat_byte(2), - rent_allowance: 40, - last_write: None, - })); - - let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); - overlay.set_storage(&2, key1.clone(), Some(b"3".to_vec())); - overlay.set_storage(&2, key2.clone(), Some(b"4".to_vec())); - DirectAccountDb.commit(overlay.into_change_set()); - } + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + let trie_id1 = ::TrieIdGenerator::trie_id(&1); + let trie_id2 = ::TrieIdGenerator::trie_id(&2); + let key1 = &[1; 32]; + let key2 = &[2; 32]; + + // Set up two accounts with free balance above the existential threshold. + { + Balances::deposit_creating(&1, 110); + ContractInfoOf::::insert(1, &ContractInfo::Alive(RawAliveContractInfo { + trie_id: trie_id1.clone(), + storage_size: ::StorageSizeOffset::get(), + deduct_block: System::block_number(), + code_hash: H256::repeat_byte(1), + rent_allowance: 40, + last_write: None, + })); + + let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); + overlay.set_storage(&1, key1.clone(), Some(b"1".to_vec())); + overlay.set_storage(&1, key2.clone(), Some(b"2".to_vec())); + DirectAccountDb.commit(overlay.into_change_set()); + + Balances::deposit_creating(&2, 110); + ContractInfoOf::::insert(2, &ContractInfo::Alive(RawAliveContractInfo { + trie_id: trie_id2.clone(), + storage_size: ::StorageSizeOffset::get(), + deduct_block: System::block_number(), + code_hash: H256::repeat_byte(2), + rent_allowance: 40, + last_write: None, + })); + + let mut overlay = OverlayAccountDb::::new(&DirectAccountDb); + overlay.set_storage(&2, key1.clone(), Some(b"3".to_vec())); + overlay.set_storage(&2, key2.clone(), Some(b"4".to_vec())); + DirectAccountDb.commit(overlay.into_change_set()); + } - // Transfer funds from account 1 of such amount that after this transfer - // the balance of account 1 will be below the existential threshold. - // - // This should lead to the removal of all storage associated with this account. - assert_ok!(Balances::transfer(Origin::signed(1), 2, 20)); - - // Verify that all entries from account 1 is removed, while - // entries from account 2 is in place. - { - assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key1).is_none()); - assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key2).is_none()); - - assert_eq!( - >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key1), - Some(b"3".to_vec()) - ); - assert_eq!( - >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key2), - Some(b"4".to_vec()) - ); - } - }, - ); + // Transfer funds from account 1 of such amount that after this transfer + // the balance of account 1 will be below the existential threshold. + // + // This should lead to the removal of all storage associated with this account. + assert_ok!(Balances::transfer(Origin::signed(1), 2, 20)); + + // Verify that all entries from account 1 is removed, while + // entries from account 2 is in place. + { + assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key1).is_none()); + assert!(>::get_storage(&DirectAccountDb, &1, Some(&trie_id1), key2).is_none()); + + assert_eq!( + >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key1), + Some(b"3".to_vec()) + ); + assert_eq!( + >::get_storage(&DirectAccountDb, &2, Some(&trie_id2), key2), + Some(b"4".to_vec()) + ); + } + }); } const CODE_RETURN_FROM_START_FN: &str = r#" @@ -416,61 +409,58 @@ const CODE_RETURN_FROM_START_FN: &str = r#" fn instantiate_and_call_and_deposit_event() { let (wasm, code_hash) = compile_module::(CODE_RETURN_FROM_START_FN).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(100).build(), - || { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Check at the end to get hash on error easily - let creation = Contract::create( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - ); + ExtBuilder::default().existential_deposit(100).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Check at the end to get hash on error easily + let creation = Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + ); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::NewAccount(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Contract(BOB, vec![1, 2, 3, 4])), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + } + ]); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Contract(BOB, vec![1, 2, 3, 4])), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - } - ]); - - assert_ok!(creation); - assert!(ContractInfoOf::::exists(BOB)); - }, - ); + assert_ok!(creation); + assert!(ContractInfoOf::::exists(BOB)); + }); } const CODE_DISPATCH_CALL: &str = r#" @@ -499,98 +489,95 @@ fn dispatch_call() { let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Let's keep this assert even though it's redundant. If you ever need to update the - // wasm source this test will fail and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contract::create( - Origin::signed(ALICE), - 100, - 100_000, - code_hash.into(), - vec![], - )); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, // newly created account - 0, - 100_000, - vec![], - )); - - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, - - // Dispatching the call. - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(CHARLIE, 50) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::Transfer(BOB, CHARLIE, 50, 0) - ), - topics: vec![], - }, - - // Event emited as a result of dispatch. - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Dispatched(BOB, true)), - topics: vec![], - } - ]); - }, - ); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Let's keep this assert even though it's redundant. If you ever need to update the + // wasm source this test will fail and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + )); + + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, // newly created account + 0, + 100_000, + vec![], + )); + + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::NewAccount(BOB, 100) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + }, + + // Dispatching the call. + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::NewAccount(CHARLIE, 50) + ), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::Transfer(BOB, CHARLIE, 50, 0) + ), + topics: vec![], + }, + + // Event emited as a result of dispatch. + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Dispatched(BOB, true)), + topics: vec![], + } + ]); + }); } const CODE_DISPATCH_CALL_THEN_TRAP: &str = r#" @@ -620,80 +607,77 @@ fn dispatch_call_not_dispatched_after_top_level_transaction_failure() { let (wasm, code_hash) = compile_module::(CODE_DISPATCH_CALL_THEN_TRAP).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - Balances::deposit_creating(&ALICE, 1_000_000); - - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // Let's keep this assert even though it's redundant. If you ever need to update the - // wasm source this test will fail and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - - assert_ok!(Contract::create( + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Let's keep this assert even though it's redundant. If you ever need to update the + // wasm source this test will fail and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + )); + + // Call the newly instantiated contract. The contract is expected to dispatch a call + // and then trap. + assert_err!( + Contract::call( Origin::signed(ALICE), - 100, + BOB, // newly created account + 0, 100_000, - code_hash.into(), vec![], - )); - - // Call the newly created contract. The contract is expected to dispatch a call - // and then trap. - assert_err!( - Contract::call( - Origin::signed(ALICE), - BOB, // newly created account - 0, - 100_000, - vec![], + ), + "during execution" + ); + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances( + balances::RawEvent::NewAccount(BOB, 100) ), - "during execution" - ); - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances( - balances::RawEvent::NewAccount(BOB, 100) - ), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), - topics: vec![], - }, - // ABSENCE of events which would be caused by dispatched Balances::transfer call - ]); - }, - ); + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Transfer(ALICE, BOB, 100)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::Instantiated(ALICE, BOB)), + topics: vec![], + }, + // ABSENCE of events which would be caused by dispatched Balances::transfer call + ]); + }); } const CODE_SET_RENT: &str = r#" @@ -823,28 +807,25 @@ fn test_set_rent_code_and_hash() { let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - - // If you ever need to update the wasm source this test will fail - // and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), - topics: vec![], - }, - ]); - } - ); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // If you ever need to update the wasm source this test will fail + // and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(code_hash.into())), + topics: vec![], + }, + ]); + }); } #[test] @@ -852,92 +833,86 @@ fn storage_size() { let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); // Storage size - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 30_000, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); - - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::set_storage_4_byte())); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4 + 4); - - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::remove_storage_4_byte())); - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); - } - ); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); + + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::set_storage_4_byte())); + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4 + 4); + + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::remove_storage_4_byte())); + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); + }); } #[test] fn deduct_blocks() { let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 30_000, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000); - - // Advance 4 blocks - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Check result - let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset - * 4 // rent byte price - * 4; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent); - assert_eq!(bob_contract.deduct_block, 5); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent); - - // Advance 7 blocks more - System::initialize(&12, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Check result - let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset - * 4 // rent byte price - * 7; // blocks to rent - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); - assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); - - // Second call on same block should have no effect on rent - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); - assert_eq!(bob_contract.deduct_block, 12); - assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); - } - ); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000); + + // Advance 4 blocks + System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent through call + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Check result + let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset + * 4 // rent byte price + * 4; // blocks to rent + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent); + assert_eq!(bob_contract.deduct_block, 5); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent); + + // Advance 7 blocks more + System::initialize(&12, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent through call + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Check result + let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset + * 4 // rent byte price + * 7; // blocks to rent + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); + assert_eq!(bob_contract.deduct_block, 12); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + + // Second call on same block should have no effect on rent + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2); + assert_eq!(bob_contract.deduct_block, 12); + assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2); + }); } #[test] @@ -979,32 +954,29 @@ fn claim_surcharge_malus() { fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) { let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); - // Advance blocks - System::initialize(&blocks, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + // Advance blocks + System::initialize(&blocks, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - // Trigger rent through call - assert!(trigger_call()); + // Trigger rent through call + assert!(trigger_call()); - if removes { - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - } else { - assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some()); - } + if removes { + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + } else { + assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some()); } - ); + }); } /// Test for all kind of removals for the given trigger: @@ -1015,123 +987,114 @@ fn removals(trigger_call: impl Fn() -> bool) { let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); // Balance reached and superior to subsistence threshold - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/; - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(&BOB), 100); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); - - // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); - } - ); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/; + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(&BOB), 100); + + // Advance blocks + System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); + + // Advance blocks + System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&BOB), subsistence_threshold); + }); // Allowance exceeded - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 1_000, - 100_000, code_hash.into(), - ::Balance::from(100u32).encode() // rent allowance - )); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100); - assert_eq!(Balances::free_balance(&BOB), 1_000); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - // Balance should be initial balance - initial rent_allowance - assert_eq!(Balances::free_balance(&BOB), 900); - - // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - assert_eq!(Balances::free_balance(&BOB), 900); - } - ); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 1_000, + 100_000, code_hash.into(), + ::Balance::from(100u32).encode() // rent allowance + )); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100); + assert_eq!(Balances::free_balance(&BOB), 1_000); + + // Advance blocks + System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + // Balance should be initial balance - initial rent_allowance + assert_eq!(Balances::free_balance(&BOB), 900); + + // Advance blocks + System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + assert_eq!(Balances::free_balance(&BOB), 900); + }); // Balance reached and inferior to subsistence threshold - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 50+Balances::minimum_balance(), - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(&BOB), 50 + Balances::minimum_balance()); - - // Transfer funds - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::transfer())); - assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); - assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).is_none()); - assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); - - // Advance blocks - System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent must have no effect - assert!(trigger_call()); - assert!(ContractInfoOf::::get(BOB).is_none()); - assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); - } - ); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 50+Balances::minimum_balance(), + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(&BOB), 50 + Balances::minimum_balance()); + + // Transfer funds + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::transfer())); + assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000); + assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); + + // Advance blocks + System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent through call + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).is_none()); + assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); + + // Advance blocks + System::initialize(&20, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent must have no effect + assert!(trigger_call()); + assert!(ContractInfoOf::::get(BOB).is_none()); + assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance()); + }); } #[test] @@ -1139,38 +1102,35 @@ fn call_removed_contract() { let (wasm, code_hash) = compile_module::(CODE_SET_RENT).unwrap(); // Balance reached and superior to subsistence threshold - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 100, - 100_000, code_hash.into(), - ::Balance::from(1_000u32).encode() // rent allowance - )); - - // Calling contract should succeed. - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Advance blocks - System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Calling contract should remove contract and fail. - assert_err!( - Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - - // Subsequent contract calls should also fail. - assert_err!( - Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" - ); - } - ) + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm.clone())); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100, + 100_000, code_hash.into(), + ::Balance::from(1_000u32).encode() // rent allowance + )); + + // Calling contract should succeed. + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Advance blocks + System::initialize(&10, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Calling contract should remove contract and fail. + assert_err!( + Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), + "contract has been evicted" + ); + + // Subsequent contract calls should also fail. + assert_err!( + Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), + "contract has been evicted" + ); + }) } const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#" @@ -1224,38 +1184,35 @@ const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#" "#; #[test] -fn default_rent_allowance_on_create() { +fn default_rent_allowance_on_instantiate() { let (wasm, code_hash) = compile_module::(CODE_CHECK_DEFAULT_RENT_ALLOWANCE).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 30_000, - 100_000, - code_hash.into(), - vec![], - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, >::max_value()); - - // Advance blocks - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Trigger rent through call - assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); - - // Check contract is still alive - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); - assert!(bob_contract.is_some()) - } - ); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, >::max_value()); + + // Advance blocks + System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Trigger rent through call + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Check contract is still alive + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive(); + assert!(bob_contract.is_some()) + }); } const CODE_RESTORATION: &str = r#" @@ -1344,122 +1301,119 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: let (restoration_wasm, restoration_code_hash) = compile_module::(CODE_RESTORATION).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, restoration_wasm)); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, set_rent_wasm)); - - // If you ever need to update the wasm source this test will fail - // and will show you the actual hash. - assert_eq!(System::events(), vec![ - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(restoration_code_hash.into())), - topics: vec![], - }, - EventRecord { - phase: Phase::ApplyExtrinsic(0), - event: MetaEvent::contract(RawEvent::CodeStored(set_rent_code_hash.into())), - topics: vec![], - }, - ]); - - // Create an account with address `BOB` with code `CODE_SET_RENT`. - // The input parameter sets the rent allowance to 0. - assert_ok!(Contract::create( + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, restoration_wasm)); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, set_rent_wasm)); + + // If you ever need to update the wasm source this test will fail + // and will show you the actual hash. + assert_eq!(System::events(), vec![ + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::balances(balances::RawEvent::NewAccount(1, 1_000_000)), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(restoration_code_hash.into())), + topics: vec![], + }, + EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: MetaEvent::contract(RawEvent::CodeStored(set_rent_code_hash.into())), + topics: vec![], + }, + ]); + + // Create an account with address `BOB` with code `CODE_SET_RENT`. + // The input parameter sets the rent allowance to 0. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, + set_rent_code_hash.into(), + ::Balance::from(0u32).encode() + )); + + // Check if `BOB` was created successfully and that the rent allowance is + // set to 0. + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 0); + + if test_different_storage { + assert_ok!(Contract::call( Origin::signed(ALICE), - 30_000, - 100_000, - set_rent_code_hash.into(), - ::Balance::from(0u32).encode() - )); - - // Check if `BOB` was created successfully and that the rent allowance is - // set to 0. - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 0); - - if test_different_storage { - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, 0, 100_000, - call::set_storage_4_byte()) - ); - } - - // Advance 4 blocks, to the 5th. - System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - - // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0 - // we expect that it will get removed leaving tombstone. - assert_err!( - Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), - "contract has been evicted" + BOB, 0, 100_000, + call::set_storage_4_byte()) ); - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - - /// Create another account with the address `DJANGO` with `CODE_RESTORATION`. - /// - /// Note that we can't use `ALICE` for creating `DJANGO` so we create yet another - /// account `CHARLIE` and create `DJANGO` with it. - Balances::deposit_creating(&CHARLIE, 1_000_000); - assert_ok!(Contract::create( - Origin::signed(CHARLIE), - 30_000, - 100_000, - restoration_code_hash.into(), - ::Balance::from(0u32).encode() - )); - - // Before performing a call to `DJANGO` save its original trie id. - let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() - .get_alive().unwrap().trie_id; + } - if !test_restore_to_with_dirty_storage { - // Advance 1 block, to the 6th. - System::initialize(&6, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); - } + // Advance 4 blocks, to the 5th. + System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + + // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0 + // we expect that it will get removed leaving tombstone. + assert_err!( + Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null()), + "contract has been evicted" + ); + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + + /// Create another account with the address `DJANGO` with `CODE_RESTORATION`. + /// + /// Note that we can't use `ALICE` for creating `DJANGO` so we create yet another + /// account `CHARLIE` and create `DJANGO` with it. + Balances::deposit_creating(&CHARLIE, 1_000_000); + assert_ok!(Contract::instantiate( + Origin::signed(CHARLIE), + 30_000, + 100_000, + restoration_code_hash.into(), + ::Balance::from(0u32).encode() + )); + + // Before performing a call to `DJANGO` save its original trie id. + let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap() + .get_alive().unwrap().trie_id; + + if !test_restore_to_with_dirty_storage { + // Advance 1 block, to the 6th. + System::initialize(&6, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + } - // Perform a call to `DJANGO`. This should either perform restoration successfully or - // fail depending on the test parameters. - assert_ok!(Contract::call( - Origin::signed(ALICE), - DJANGO, - 0, - 100_000, - vec![], - )); - - if test_different_storage || test_restore_to_with_dirty_storage { - // Parametrization of the test imply restoration failure. Check that `DJANGO` aka - // restoration contract is still in place and also that `BOB` doesn't exist. - assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); - let django_contract = ContractInfoOf::::get(DJANGO).unwrap() - .get_alive().unwrap(); - assert_eq!(django_contract.storage_size, 16); - assert_eq!(django_contract.trie_id, django_trie_id); - assert_eq!(django_contract.deduct_block, System::block_number()); - } else { - // Here we expect that the restoration is succeeded. Check that the restoration - // contract `DJANGO` ceased to exist and that `BOB` returned back. - println!("{:?}", ContractInfoOf::::get(BOB)); - let bob_contract = ContractInfoOf::::get(BOB).unwrap() - .get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, 50); - assert_eq!(bob_contract.storage_size, 12); - assert_eq!(bob_contract.trie_id, django_trie_id); - assert_eq!(bob_contract.deduct_block, System::block_number()); - assert!(ContractInfoOf::::get(DJANGO).is_none()); - } + // Perform a call to `DJANGO`. This should either perform restoration successfully or + // fail depending on the test parameters. + assert_ok!(Contract::call( + Origin::signed(ALICE), + DJANGO, + 0, + 100_000, + vec![], + )); + + if test_different_storage || test_restore_to_with_dirty_storage { + // Parametrization of the test imply restoration failure. Check that `DJANGO` aka + // restoration contract is still in place and also that `BOB` doesn't exist. + assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some()); + let django_contract = ContractInfoOf::::get(DJANGO).unwrap() + .get_alive().unwrap(); + assert_eq!(django_contract.storage_size, 16); + assert_eq!(django_contract.trie_id, django_trie_id); + assert_eq!(django_contract.deduct_block, System::block_number()); + } else { + // Here we expect that the restoration is succeeded. Check that the restoration + // contract `DJANGO` ceased to exist and that `BOB` returned back. + println!("{:?}", ContractInfoOf::::get(BOB)); + let bob_contract = ContractInfoOf::::get(BOB).unwrap() + .get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, 50); + assert_eq!(bob_contract.storage_size, 12); + assert_eq!(bob_contract.trie_id, django_trie_id); + assert_eq!(bob_contract.deduct_block, System::block_number()); + assert!(ContractInfoOf::::get(DJANGO).is_none()); } - ); + }); } const CODE_STORAGE_SIZE: &str = r#" @@ -1530,46 +1484,43 @@ const CODE_STORAGE_SIZE: &str = r#" fn storage_max_value_limit() { let (wasm, code_hash) = compile_module::(CODE_STORAGE_SIZE).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); - assert_ok!(Contract::create( - Origin::signed(ALICE), - 30_000, - 100_000, - code_hash.into(), - vec![], - )); - - // Check creation - let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.rent_allowance, >::max_value()); - - // Call contract with allowed storage value. - assert_ok!(Contract::call( + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 30_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check creation + let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, >::max_value()); + + // Call contract with allowed storage value. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + Encode::encode(&self::MaxValueSize::get()), + )); + + // Call contract with too large a storage value. + assert_err!( + Contract::call( Origin::signed(ALICE), BOB, 0, 100_000, - Encode::encode(&self::MaxValueSize::get()), - )); - - // Call contract with too large a storage value. - assert_err!( - Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 100_000, - Encode::encode(&(self::MaxValueSize::get() + 1)), - ), - "during execution" - ); - } - ); + Encode::encode(&(self::MaxValueSize::get() + 1)), + ), + "during execution" + ); + }); } const CODE_RETURN_WITH_DATA: &str = r#" @@ -1601,7 +1552,7 @@ const CODE_RETURN_WITH_DATA: &str = r#" ;; Copy all but the first 4 bytes of the input data as the output data. (call $ext_scratch_write - (i32.const 4) ;; Offset from the start of the scratch buffer. + (i32.const 4) ;; Pointer to the data to return. (i32.sub ;; Count of bytes to copy. (get_local $buf_size) (i32.const 4) @@ -1620,7 +1571,7 @@ const CODE_CALLER_CONTRACT: &str = r#" (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) (import "env" "ext_balance" (func $ext_balance)) (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) - (import "env" "ext_create" (func $ext_create (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) (import "env" "ext_println" (func $ext_println (param i32 i32))) (import "env" "memory" (memory 1 1)) @@ -1676,7 +1627,7 @@ const CODE_CALLER_CONTRACT: &str = r#" ;; Fail to deploy the contract since it returns a non-zero exit status. (set_local $exit_code - (call $ext_create + (call $ext_instantiate (i32.const 24) ;; Pointer to the code hash. (i32.const 32) ;; Length of the code hash. (i64.const 0) ;; How much gas to devote for the execution. 0 = all. @@ -1704,7 +1655,7 @@ const CODE_CALLER_CONTRACT: &str = r#" ;; Fail to deploy the contract due to insufficient gas. (set_local $exit_code - (call $ext_create + (call $ext_instantiate (i32.const 24) ;; Pointer to the code hash. (i32.const 32) ;; Length of the code hash. (i64.const 200) ;; How much gas to devote for the execution. @@ -1732,7 +1683,7 @@ const CODE_CALLER_CONTRACT: &str = r#" ;; Deploy the contract successfully. (set_local $exit_code - (call $ext_create + (call $ext_instantiate (i32.const 24) ;; Pointer to the code hash. (i32.const 32) ;; Length of the code hash. (i64.const 0) ;; How much gas to devote for the execution. 0 = all. @@ -1897,31 +1848,496 @@ fn deploy_and_call_other_contract() { let (callee_wasm, callee_code_hash) = compile_module::(CODE_RETURN_WITH_DATA).unwrap(); let (caller_wasm, caller_code_hash) = compile_module::(CODE_CALLER_CONTRACT).unwrap(); - with_externalities( - &mut ExtBuilder::default().existential_deposit(50).build(), - || { - // Create - Balances::deposit_creating(&ALICE, 1_000_000); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); - assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); + + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100_000, + 100_000, + caller_code_hash.into(), + vec![], + )); + + // Call BOB contract, which attempts to instantiate and call the callee contract and + // makes various assertions on the results from those calls. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 200_000, + callee_code_hash.as_ref().to_vec(), + )); + }); +} + +const CODE_SELF_DESTRUCT: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_address" (func $ext_address)) + (import "env" "ext_balance" (func $ext_balance)) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy")) + + (func (export "call") + ;; If the input data is not empty, then recursively call self with empty input data. + ;; This should trap instead of self-destructing since a contract cannot be removed live in + ;; the execution stack cannot be removed. If the recursive call traps, then trap here as + ;; well. + (if (call $ext_scratch_size) + (then + (call $ext_address) + + ;; Expect address to be 8 bytes. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; Read own address into memory. + (call $ext_scratch_read + (i32.const 16) ;; Pointer to write address to + (i32.const 0) ;; Offset into scrach buffer + (i32.const 8) ;; Length of encoded address + ) + + ;; Recursively call self with empty imput data. + (call $assert + (i32.eq + (call $ext_call + (i32.const 16) ;; Pointer to own address + (i32.const 8) ;; Length of own address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) + ) + + ;; Send entire remaining balance to the 0 address. + (call $ext_balance) + + ;; Balance should be encoded as a u64. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; Read balance into memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer to write balance to + (i32.const 0) ;; Offset into scrach buffer + (i32.const 8) ;; Length of encoded balance + ) + + ;; Self-destruct by sending full balance to the 0 address. + (call $assert + (i32.eq + (call $ext_call + (i32.const 0) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) +) +"#; - assert_ok!(Contract::create( +#[test] +fn self_destruct_by_draining_balance() { + let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Instantiate the BOB contract. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB with no input data, forcing it to self-destruct. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + vec![], + )); + + // Check that BOB is now dead. + assert!(ContractInfoOf::::get(BOB).is_none()); + }); +} + +#[test] +fn cannot_self_destruct_while_live() { + let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Instantiate the BOB contract. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 100_000, + 100_000, + code_hash.into(), + vec![], + )); + + // Check that the BOB contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB with input data, forcing it make a recursive call to itself to + // self-destruct, resulting in a trap. + assert_err!( + Contract::call( Origin::signed(ALICE), + BOB, + 0, 100_000, + vec![0], + ), + "during execution" + ); + + // Check that BOB is still alive. + assert_matches!( + ContractInfoOf::::get(BOB), + Some(ContractInfo::Alive(_)) + ); + }); +} + +const CODE_DESTROY_AND_TRANSFER: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_get_storage" (func $ext_get_storage (param i32) (result i32))) + (import "env" "ext_set_storage" (func $ext_set_storage (param i32 i32 i32 i32))) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy") + ;; Input data is the code hash of the contract to be deployed. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 32) + ) + ) + + ;; Copy code hash from scratch buffer into this contract's memory. + (call $ext_scratch_read + (i32.const 48) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 32) ;; Count of bytes to copy. + ) + + ;; Deploy the contract with the provided code hash. + (call $assert + (i32.eq + (call $ext_instantiate + (i32.const 48) ;; Pointer to the code hash. + (i32.const 32) ;; Length of the code hash. + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer. + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + + ;; Read the address of the instantiated contract into memory. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + (call $ext_scratch_read + (i32.const 80) ;; The pointer where to store the scratch buffer contents, + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; Store the return address. + (call $ext_set_storage + (i32.const 16) ;; Pointer to the key + (i32.const 1) ;; Value is not null + (i32.const 80) ;; Pointer to the value + (i32.const 8) ;; Length of the value + ) + ) + + (func (export "call") + ;; Read address of destination contract from storage. + (call $assert + (i32.eq + (call $ext_get_storage + (i32.const 16) ;; Pointer to the key + ) + (i32.const 0) + ) + ) + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + (call $ext_scratch_read + (i32.const 80) ;; The pointer where to store the contract address. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; Calling the destination contract with non-empty input data should fail. + (call $assert + (i32.eq + (call $ext_call + (i32.const 80) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 1) ;; Length of input data buffer + ) + (i32.const 0x0100) + ) + ) + + ;; Call the destination contract regularly, forcing it to self-destruct. + (call $assert + (i32.eq + (call $ext_call + (i32.const 80) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + + ;; Calling the destination address with non-empty input data should now work since the + ;; contract has been removed. Also transfer a balance to the address so we can ensure this + ;; does not keep the contract alive. + (call $assert + (i32.eq + (call $ext_call + (i32.const 80) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 0) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 1) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) + + (data (i32.const 0) "\00\00\01") ;; Endowment to send when creating contract. + (data (i32.const 8) "") ;; Value to send when calling contract. + (data (i32.const 16) "") ;; The key to store the contract address under. +) +"#; + +// This tests that one contract cannot prevent another from self-destructing by sending it +// additional funds after it has been drained. +#[test] +fn destroy_contract_and_transfer_funds() { + let (callee_wasm, callee_code_hash) = compile_module::(CODE_SELF_DESTRUCT).unwrap(); + let (caller_wasm, caller_code_hash) = compile_module::(CODE_DESTROY_AND_TRANSFER).unwrap(); + + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, callee_wasm)); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, caller_wasm)); + + // This deploys the BOB contract, which in turn deploys the CHARLIE contract during + // construction. + assert_ok!(Contract::instantiate( + Origin::signed(ALICE), + 200_000, + 100_000, + caller_code_hash.into(), + callee_code_hash.as_ref().to_vec(), + )); + + // Check that the CHARLIE contract has been instantiated. + assert_matches!( + ContractInfoOf::::get(CHARLIE), + Some(ContractInfo::Alive(_)) + ); + + // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct. + assert_ok!(Contract::call( + Origin::signed(ALICE), + BOB, + 0, + 100_000, + CHARLIE.encode(), + )); + + // Check that CHARLIE has moved on to the great beyond (ie. died). + assert!(ContractInfoOf::::get(CHARLIE).is_none()); + }); +} + +const CODE_SELF_DESTRUCTING_CONSTRUCTOR: &str = r#" +(module + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "ext_balance" (func $ext_balance)) + (import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "deploy") + ;; Send entire remaining balance to the 0 address. + (call $ext_balance) + + ;; Balance should be encoded as a u64. + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; Read balance into memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer to write balance to + (i32.const 0) ;; Offset into scrach buffer + (i32.const 8) ;; Length of encoded balance + ) + + ;; Self-destruct by sending full balance to the 0 address. + (call $assert + (i32.eq + (call $ext_call + (i32.const 0) ;; Pointer to destination address + (i32.const 8) ;; Length of destination address + (i64.const 0) ;; How much gas to devote for the execution. 0 = all. + (i32.const 8) ;; Pointer to the buffer with value to transfer + (i32.const 8) ;; Length of the buffer with value to transfer + (i32.const 0) ;; Pointer to input data buffer address + (i32.const 0) ;; Length of input data buffer + ) + (i32.const 0) + ) + ) + ) + + (func (export "call")) +) +"#; + +#[test] +fn cannot_self_destruct_in_constructor() { + let (wasm, code_hash) = compile_module::(CODE_SELF_DESTRUCTING_CONSTRUCTOR).unwrap(); + ExtBuilder::default().existential_deposit(50).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + + // Fail to instantiate the BOB contract since its final balance is below existential + // deposit. + assert_err!( + Contract::instantiate( + Origin::signed(ALICE), 100_000, - caller_code_hash.into(), + 100_000, + code_hash.into(), vec![], - )); + ), + "insufficient remaining balance" + ); + }); +} - // Call BOB contract, which attempts to instantiate and call the callee contract and - // makes various assertions on the results from those calls. - assert_ok!(Contract::call( - Origin::signed(ALICE), - BOB, - 0, - 200_000, - callee_code_hash.as_ref().to_vec(), - )); - } - ); +#[test] +fn check_block_gas_limit_works() { + ExtBuilder::default().block_gas_limit(50).build().execute_with(|| { + let info = DispatchInfo { weight: 100, class: DispatchClass::Normal }; + let check = CheckBlockGasLimit::(Default::default()); + let call: Call = crate::Call::put_code(1000, vec![]).into(); + + assert_eq!( + check.validate(&0, &call, info, 0), InvalidTransaction::ExhaustsResources.into(), + ); + + let call: Call = crate::Call::update_schedule(Default::default()).into(); + assert_eq!(check.validate(&0, &call, info, 0), Ok(Default::default())); + }); } diff --git a/srml/contracts/src/wasm/code_cache.rs b/srml/contracts/src/wasm/code_cache.rs index 9e8fcab8c257315f1f64abd815be92987279cc5b..e6702d29cf5c71b1fbfa8d1a0026cefc6c48a86e 100644 --- a/srml/contracts/src/wasm/code_cache.rs +++ b/srml/contracts/src/wasm/code_cache.rs @@ -31,7 +31,7 @@ use crate::wasm::{prepare, runtime::Env, PrefabWasmModule}; use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait}; use rstd::prelude::*; use sr_primitives::traits::{Hash, Bounded}; -use srml_support::StorageMap; +use support::StorageMap; /// Gas metering token that used for charging storing code into the code storage. /// @@ -98,7 +98,7 @@ pub fn load( let original_code = >::get(code_hash).ok_or_else(|| "pristine code is not found")?; prefab_module = prepare::prepare_contract::(&original_code, schedule)?; - >::insert(code_hash, prefab_module.clone()); + >::insert(&code_hash, &prefab_module); } Ok(prefab_module) } diff --git a/srml/contracts/src/wasm/mod.rs b/srml/contracts/src/wasm/mod.rs index 99578fee2747f5623cb24e0f515c8d7a6ca4f25b..4fa9412bc1769121c4d5fa06dcf30b384d5acb79 100644 --- a/srml/contracts/src/wasm/mod.rs +++ b/srml/contracts/src/wasm/mod.rs @@ -173,7 +173,7 @@ mod tests { } #[derive(Debug, PartialEq, Eq)] - struct CreateEntry { + struct InstantiateEntry { code_hash: H256, endowment: u64, data: Vec, @@ -192,7 +192,7 @@ mod tests { pub struct MockExt { storage: HashMap>, rent_allowance: u64, - creates: Vec, + instantiates: Vec, transfers: Vec, dispatches: Vec, restores: Vec, @@ -220,7 +220,7 @@ mod tests { gas_meter: &mut GasMeter, data: Vec, ) -> Result<(u64, ExecReturnValue), ExecError> { - self.creates.push(CreateEntry { + self.instantiates.push(InstantiateEntry { code_hash: code_hash.clone(), endowment, data: data.to_vec(), @@ -282,6 +282,10 @@ mod tests { &1111 } + fn minimum_balance(&self) -> u64 { + 666 + } + fn random(&self, subject: &[u8]) -> H256 { H256::from_slice(subject) } @@ -364,6 +368,9 @@ mod tests { fn now(&self) -> &u64 { (**self).now() } + fn minimum_balance(&self) -> u64 { + (**self).minimum_balance() + } fn random(&self, subject: &[u8]) -> H256 { (**self).random(subject) } @@ -464,14 +471,14 @@ mod tests { to: 9, value: 6, data: vec![1, 2, 3, 4], - gas_left: 49970, + gas_left: 49971, }] ); } - const CODE_CREATE: &str = r#" + const CODE_INSTANTIATE: &str = r#" (module - ;; ext_create( + ;; ext_instantiate( ;; code_ptr: u32, ;; code_len: u32, ;; gas: u64, @@ -480,11 +487,11 @@ mod tests { ;; input_data_ptr: u32, ;; input_data_len: u32, ;; ) -> u32 - (import "env" "ext_create" (func $ext_create (param i32 i32 i64 i32 i32 i32 i32) (result i32))) + (import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory 1 1)) (func (export "call") (drop - (call $ext_create + (call $ext_instantiate (i32.const 16) ;; Pointer to `code_hash` (i32.const 32) ;; Length of `code_hash` (i64.const 0) ;; How much gas to devote for the execution. 0 = all. @@ -500,7 +507,7 @@ mod tests { ;; Amount of value to transfer. ;; Represented by u64 (8 bytes long) in little endian. (data (i32.const 4) "\03\00\00\00\00\00\00\00") - ;; Input data to pass to the contract being created. + ;; Input data to pass to the contract being instantiated. (data (i32.const 12) "\01\02\03\04") ;; Hash of code. (data (i32.const 16) @@ -511,22 +518,22 @@ mod tests { "#; #[test] - fn contract_create() { + fn contract_instantiate() { let mut mock_ext = MockExt::default(); let _ = execute( - CODE_CREATE, + CODE_INSTANTIATE, vec![], &mut mock_ext, &mut GasMeter::with_limit(50_000, 1), ).unwrap(); assert_eq!( - &mock_ext.creates, - &[CreateEntry { + &mock_ext.instantiates, + &[InstantiateEntry { code_hash: [0x11; 32].into(), endowment: 3, data: vec![1, 2, 3, 4], - gas_left: 49946, + gas_left: 49947, }] ); } @@ -1176,6 +1183,65 @@ mod tests { ).unwrap(); } + const CODE_MINIMUM_BALANCE: &str = r#" +(module + (import "env" "ext_minimum_balance" (func $ext_minimum_balance)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call") + (call $ext_minimum_balance) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_read + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to the i64 value of 666. + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 666) + ) + ) + ) + (func (export "deploy")) +) +"#; + + #[test] + fn minimum_balance() { + let mut gas_meter = GasMeter::with_limit(50_000, 1); + let _ = execute( + CODE_MINIMUM_BALANCE, + vec![], + MockExt::default(), + &mut gas_meter, + ).unwrap(); + } + const CODE_RANDOM: &str = r#" (module (import "env" "ext_random" (func $ext_random (param i32 i32))) @@ -1293,11 +1359,7 @@ mod tests { vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]) ]); - assert_eq!(gas_meter.gas_left(), 50_000 - - 6 // Explicit - - 13 - 1 - 1 // Deposit event - - (13 + 33) // read memory - ); + assert_eq!(gas_meter.gas_left(), 49934); } const CODE_DEPOSIT_EVENT_MAX_TOPICS: &str = r#" diff --git a/srml/contracts/src/wasm/runtime.rs b/srml/contracts/src/wasm/runtime.rs index ecc4dfc7fb592f40ae5504d654405af65cc9865e..28117eaa7c690d7b25f5d06c99f6a9fee2ea6cb9 100644 --- a/srml/contracts/src/wasm/runtime.rs +++ b/srml/contracts/src/wasm/runtime.rs @@ -29,7 +29,7 @@ use rstd::mem; use codec::{Decode, Encode}; use sr_primitives::traits::{Bounded, SaturatedConversion}; -/// The value returned from ext_call and ext_create contract external functions if the call or +/// The value returned from ext_call and ext_instantiate contract external functions if the call or /// instantiation traps. This value is chosen as if the execution does not trap, the return value /// will always be an 8-bit integer, so 0x0100 is the smallest value that could not be returned. const TRAP_RETURN_CODE: u32 = 0x0100; @@ -70,10 +70,6 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> { special_trap: None, } } - - fn memory(&self) -> &sandbox::Memory { - &self.memory - } } pub(crate) fn to_execution_result( @@ -436,11 +432,12 @@ define_env!(Env, , // by the code hash. // // If the constructor runs to completion, then this returns the status code that the newly - // created contract returns on exit in the bottom 8 bits of the return value. The top 24 bits - // are 0s. A status code of 0 indicates success, and any other code indicates a failure. On - // failure, any state changes made by the called contract are reverted and the contract is not - // instantiated. On a success status, the scratch buffer is filled with the encoded address of - // the newly created contract. In the case of a failure status, the scratch buffer is cleared. + // instantiated contract returns on exit in the bottom 8 bits of the return value. The top 24 + // bits are 0s. A status code of 0 indicates success, and any other code indicates a failure. + // On failure, any state changes made by the called contract are reverted and the contract is + // not instantiated. On a success status, the scratch buffer is filled with the encoded address + // of the newly instantiated contract. In the case of a failure status, the scratch buffer is + // cleared. // // If the contract traps during execution or otherwise fails to complete successfully, then // this function clears the scratch buffer and returns 0x0100. As with a failure status, any @@ -449,8 +446,9 @@ define_env!(Env, , // This function creates an account and executes initializer code. After the execution, // the returned buffer is saved as the code of the created account. // - // Returns 0 on the successful contract creation and puts the address of the created contract - // into the scratch buffer. Otherwise, returns non-zero value and clears the scratch buffer. + // Returns 0 on the successful contract instantiation and puts the address of the instantiated + // contract into the scratch buffer. Otherwise, returns non-zero value and clears the scratch + // buffer. // // - code_hash_ptr: a pointer to the buffer that contains the initializer code. // - code_hash_len: length of the initializer code buffer. @@ -460,7 +458,7 @@ define_env!(Env, , // - value_len: length of the value buffer. // - input_data_ptr: a pointer to a buffer to be used as input data to the initializer code. // - input_data_len: length of the input data buffer. - ext_create( + ext_instantiate( ctx, code_hash_ptr: u32, code_hash_len: u32, @@ -539,9 +537,9 @@ define_env!(Env, , // Stores the address of the caller into the scratch buffer. // - // If this is a top-level call (i.e. initiated by an extrinsic) the origin address of the extrinsic - // will be returned. Otherwise, if this call is initiated by another contract then the address - // of the contract will be returned. + // If this is a top-level call (i.e. initiated by an extrinsic) the origin address of the + // extrinsic will be returned. Otherwise, if this call is initiated by another contract then the + // address of the contract will be returned. ext_caller(ctx) => { ctx.scratch_buf.clear(); ctx.ext.caller().encode_to(&mut ctx.scratch_buf); @@ -615,6 +613,16 @@ define_env!(Env, , Ok(()) }, + // Stores the minimum balance (a.k.a. existential deposit) into the scratch buffer. + // + // The data is encoded as T::Balance. The current contents of the scratch buffer are + // overwritten. + ext_minimum_balance(ctx) => { + ctx.scratch_buf.clear(); + ctx.ext.minimum_balance().encode_to(&mut ctx.scratch_buf); + Ok(()) + }, + // Decodes the given buffer as a `T::Call` and adds it to the list // of to-be-dispatched calls. // @@ -711,8 +719,8 @@ define_env!(Env, , Ok(ctx.scratch_buf.len() as u32) }, - // Copy data from the scratch buffer starting from `offset` with length `len` into the contract memory. - // The region at which the data should be put is specified by `dest_ptr`. + // Copy data from the scratch buffer starting from `offset` with length `len` into the contract + // memory. The region at which the data should be put is specified by `dest_ptr`. // // In order to get size of the scratch buffer use `ext_scratch_size`. At the start of contract // execution, the scratch buffer is filled with the input data. Whenever a contract calls @@ -816,7 +824,7 @@ define_env!(Env, , ext_println(ctx, str_ptr: u32, str_len: u32) => { let data = read_sandbox_memory(ctx, str_ptr, str_len)?; if let Ok(utf8) = core::str::from_utf8(&data) { - runtime_io::print(utf8); + sr_primitives::print(utf8); } Ok(()) }, diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs deleted file mode 100644 index 787abdb0787dd99956ed86cd8f5b38f80fb27639..0000000000000000000000000000000000000000 --- a/srml/council/src/lib.rs +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Council system: Handles the voting in and maintenance of council members. - -#![cfg_attr(not(feature = "std"), no_std)] -#![recursion_limit="128"] - -pub mod motions; -pub mod seats; - -pub use crate::seats::{Trait, Module, RawEvent, Event, VoteIndex}; - -/// Trait for type that can handle incremental changes to a set of account IDs. -pub trait OnMembersChanged { - /// A number of members `new` just joined the set and replaced some `old` ones. - fn on_members_changed(new: &[AccountId], old: &[AccountId]); -} - -impl OnMembersChanged for () { - fn on_members_changed(_new: &[T], _old: &[T]) {} -} - -#[cfg(test)] -mod tests { - // These re-exports are here for a reason, edit with care - pub use super::*; - pub use runtime_io::with_externalities; - use srml_support::{impl_outer_origin, impl_outer_event, impl_outer_dispatch, parameter_types}; - use srml_support::traits::Get; - pub use primitives::{H256, Blake2Hasher, u32_trait::{_1, _2, _3, _4}}; - pub use sr_primitives::traits::{BlakeTwo256, IdentityLookup}; - pub use sr_primitives::testing::{Digest, DigestItem, Header}; - pub use sr_primitives::Perbill; - pub use {seats, motions}; - use std::cell::RefCell; - - impl_outer_origin! { - pub enum Origin for Test { - motions - } - } - - impl_outer_event! { - pub enum Event for Test { - balances, democracy, seats, motions, - } - } - - impl_outer_dispatch! { - pub enum Call for Test where origin: Origin { - balances::Balances, - democracy::Democracy, - } - } - - thread_local! { - static VOTER_BOND: RefCell = RefCell::new(0); - static VOTING_FEE: RefCell = RefCell::new(0); - static PRESENT_SLASH_PER_VOTER: RefCell = RefCell::new(0); - static DECAY_RATIO: RefCell = RefCell::new(0); - } - - pub struct VotingBond; - impl Get for VotingBond { - fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) } - } - - pub struct VotingFee; - impl Get for VotingFee { - fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) } - } - - pub struct PresentSlashPerVoter; - impl Get for PresentSlashPerVoter { - fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) } - } - - pub struct DecayRatio; - impl Get for DecayRatio { - fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) } - } - - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, Eq, PartialEq, Debug)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type WeightMultiplierUpdate = (); - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - pub const TransactionBaseFee: u64 = 1; - pub const TransactionByteFee: u64 = 0; - } - impl balances::Trait for Test { - type Balance = u64; - type OnNewAccount = (); - type OnFreeBalanceZero = (); - type Event = Event; - type TransactionPayment = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = (); - } - parameter_types! { - pub const LaunchPeriod: u64 = 1; - pub const VotingPeriod: u64 = 3; - pub const MinimumDeposit: u64 = 1; - pub const EnactmentPeriod: u64 = 0; - pub const CooloffPeriod: u64 = 2; - } - impl democracy::Trait for Test { - type Proposal = Call; - type Event = Event; - type Currency = balances::Module; - type EnactmentPeriod = EnactmentPeriod; - type LaunchPeriod = LaunchPeriod; - type EmergencyVotingPeriod = VotingPeriod; - type VotingPeriod = VotingPeriod; - type MinimumDeposit = MinimumDeposit; - type ExternalOrigin = motions::EnsureProportionAtLeast<_1, _2, u64>; - type ExternalMajorityOrigin = motions::EnsureProportionAtLeast<_2, _3, u64>; - type EmergencyOrigin = motions::EnsureProportionAtLeast<_1, _1, u64>; - type CancellationOrigin = motions::EnsureProportionAtLeast<_2, _3, u64>; - type VetoOrigin = motions::EnsureMember; - type CooloffPeriod = CooloffPeriod; - } - parameter_types! { - pub const CandidacyBond: u64 = 3; - pub const CarryCount: u32 = 2; - pub const InactiveGracePeriod: u32 = 1; - pub const CouncilVotingPeriod: u64 = 4; - } - impl seats::Trait for Test { - type Event = Event; - type BadPresentation = (); - type BadReaper = (); - type BadVoterIndex = (); - type LoserCandidate = (); - type OnMembersChanged = CouncilMotions; - type CandidacyBond = CandidacyBond; - type VotingBond = VotingBond; - type VotingFee = VotingFee; - type PresentSlashPerVoter = PresentSlashPerVoter; - type CarryCount = CarryCount; - type InactiveGracePeriod = InactiveGracePeriod; - type CouncilVotingPeriod = CouncilVotingPeriod; - type DecayRatio = DecayRatio; - } - impl motions::Trait for Test { - type Origin = Origin; - type Proposal = Call; - type Event = Event; - } - - pub struct ExtBuilder { - balance_factor: u64, - decay_ratio: u32, - voting_fee: u64, - voter_bond: u64, - bad_presentation_punishment: u64, - with_council: bool, - } - - impl Default for ExtBuilder { - fn default() -> Self { - Self { - balance_factor: 1, - decay_ratio: 24, - voting_fee: 0, - voter_bond: 0, - bad_presentation_punishment: 1, - with_council: false, - } - } - } - - impl ExtBuilder { - pub fn with_council(mut self, council: bool) -> Self { - self.with_council = council; - self - } - pub fn balance_factor(mut self, factor: u64) -> Self { - self.balance_factor = factor; - self - } - pub fn decay_ratio(mut self, ratio: u32) -> Self { - self.decay_ratio = ratio; - self - } - pub fn voting_fee(mut self, fee: u64) -> Self { - self.voting_fee = fee; - self - } - pub fn bad_presentation_punishment(mut self, fee: u64) -> Self { - self.bad_presentation_punishment = fee; - self - } - pub fn voter_bond(mut self, fee: u64) -> Self { - self.voter_bond = fee; - self - } - pub fn set_associated_consts(&self) { - VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond); - VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee); - PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment); - DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio); - } - pub fn build(self) -> runtime_io::TestExternalities { - self.set_associated_consts(); - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig::{ - balances: vec![ - (1, 10 * self.balance_factor), - (2, 20 * self.balance_factor), - (3, 30 * self.balance_factor), - (4, 40 * self.balance_factor), - (5, 50 * self.balance_factor), - (6, 60 * self.balance_factor) - ], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - seats::GenesisConfig:: { - active_council: if self.with_council { vec![ - (1, 10), - (2, 10), - (3, 10) - ] } else { vec![] }, - desired_seats: 2, - presentation_duration: 2, - term_duration: 5, - }.assimilate_storage(&mut t).unwrap(); - runtime_io::TestExternalities::new(t) - } - } - - pub type System = system::Module; - pub type Balances = balances::Module; - pub type Democracy = democracy::Module; - pub type Council = seats::Module; - pub type CouncilMotions = motions::Module; -} diff --git a/srml/democracy/Cargo.toml b/srml/democracy/Cargo.toml index b6341a8225638a04342fad4f9d65ab83510fd778..761e56ceda6cb978d1c208126dd076c59eca5d3a 100644 --- a/srml/democracy/Cargo.toml +++ b/srml/democracy/Cargo.toml @@ -5,13 +5,13 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true, features = ["derive"] } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] @@ -25,8 +25,8 @@ std = [ "safe-mix/std", "codec/std", "rstd/std", - "runtime_io/std", - "srml-support/std", + "runtime-io/std", + "support/std", "sr-primitives/std", "system/std", ] diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 5a1c61b8ae24ce47410a350ed7018c2cb8bf86c1..545666e493026202199aff88ef74d717f3c3ab52 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -20,18 +20,21 @@ use rstd::prelude::*; use rstd::{result, convert::TryFrom}; -use sr_primitives::traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash}; -use sr_primitives::weights::SimpleDispatchInfo; -use codec::{Encode, Decode, Input, Output, Error}; -use srml_support::{ +use sr_primitives::{ + RuntimeDebug, + traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash, Dispatchable}, + weights::SimpleDispatchInfo, +}; +use codec::{Ref, Encode, Decode, Input, Output, Error}; +use support::{ decl_module, decl_storage, decl_event, ensure, - StorageValue, StorageMap, Parameter, Dispatchable, EnumerableStorageMap, + Parameter, traits::{ - Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, - OnFreeBalanceZero, Get + Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, + OnFreeBalanceZero } }; -use srml_support::dispatch::Result; +use support::dispatch::Result; use system::{ensure_signed, ensure_root}; mod vote_threshold; @@ -46,8 +49,7 @@ pub type PropIndex = u32; pub type ReferendumIndex = u32; /// A value denoting the strength of conviction of a vote. -#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)] pub enum Conviction { /// 0.1x votes, unlocked. None, @@ -146,8 +148,7 @@ impl Bounded for Conviction { const MAX_RECURSION_LIMIT: u32 = 16; /// A number of lock periods, plus a vote, one way or the other. -#[derive(Copy, Clone, Eq, PartialEq, Default)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug)] pub struct Vote { pub aye: bool, pub conviction: Conviction, @@ -174,13 +175,6 @@ impl Decode for Vote { type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -pub const DEFAULT_ENACTMENT_PERIOD: u32 = 0; -pub const DEFAULT_LAUNCH_PERIOD: u32 = 0; -pub const DEFAULT_VOTING_PERIOD: u32 = 0; -pub const DEFAULT_MINIMUM_DEPOSIT: u32 = 0; -pub const DEFAULT_EMERGENCY_VOTING_PERIOD: u32 = 0; -pub const DEFAULT_COOLOFF_PERIOD: u32 = 0; - pub trait Trait: system::Trait + Sized { type Proposal: Parameter + Dispatchable; type Event: From> + Into<::Event>; @@ -236,8 +230,7 @@ pub trait Trait: system::Trait + Sized { } /// Info regarding an ongoing referendum. -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct ReferendumInfo { /// When voting on this referendum will end. end: BlockNumber, @@ -264,38 +257,38 @@ impl ReferendumInfo as Democracy { /// The number of (public) proposals that have been made so far. - pub PublicPropCount get(public_prop_count) build(|_| 0 as PropIndex) : PropIndex; + pub PublicPropCount get(fn public_prop_count) build(|_| 0 as PropIndex) : PropIndex; /// The public proposals. Unsorted. - pub PublicProps get(public_props): Vec<(PropIndex, T::Proposal, T::AccountId)>; + pub PublicProps get(fn public_props): Vec<(PropIndex, T::Proposal, T::AccountId)>; /// Those who have locked a deposit. - pub DepositOf get(deposit_of): map PropIndex => Option<(BalanceOf, Vec)>; + pub DepositOf get(fn deposit_of): map PropIndex => Option<(BalanceOf, Vec)>; /// The next free referendum index, aka the number of referenda started so far. - pub ReferendumCount get(referendum_count) build(|_| 0 as ReferendumIndex): ReferendumIndex; + pub ReferendumCount get(fn referendum_count) build(|_| 0 as ReferendumIndex): ReferendumIndex; /// The next referendum index that should be tallied. - pub NextTally get(next_tally) build(|_| 0 as ReferendumIndex): ReferendumIndex; + pub NextTally get(fn next_tally) build(|_| 0 as ReferendumIndex): ReferendumIndex; /// Information concerning any given referendum. - pub ReferendumInfoOf get(referendum_info): + pub ReferendumInfoOf get(fn referendum_info): map ReferendumIndex => Option<(ReferendumInfo)>; /// Queue of successful referenda to be dispatched. - pub DispatchQueue get(dispatch_queue): + pub DispatchQueue get(fn dispatch_queue): map T::BlockNumber => Vec>; /// Get the voters for the current proposal. - pub VotersFor get(voters_for): map ReferendumIndex => Vec; + pub VotersFor get(fn voters_for): map ReferendumIndex => Vec; /// Get the vote in a given referendum of a particular voter. The result is meaningful only /// if `voters_for` includes the voter when called with the referendum (you'll get the /// default `Vote` value otherwise). If you don't want to check `voters_for`, then you can /// also check for simple existence with `VoteOf::exists` first. - pub VoteOf get(vote_of): map (ReferendumIndex, T::AccountId) => Vote; + pub VoteOf get(fn vote_of): map (ReferendumIndex, T::AccountId) => Vote; /// Who is able to vote for whom. Value is the fund-holding account, key is the /// vote-transaction-sending account. - pub Proxy get(proxy): map T::AccountId => Option; + pub Proxy get(fn proxy): map T::AccountId => Option; /// Get the account (and lock periods) to which another account is delegating vote. - pub Delegations get(delegations): linked_map T::AccountId => (T::AccountId, Conviction); + pub Delegations get(fn delegations): linked_map T::AccountId => (T::AccountId, Conviction); /// True if the last referendum tabled was submitted externally. False if it was a public /// proposal. @@ -309,7 +302,7 @@ decl_storage! { /// A record of who vetoed what. Maps proposal hash to a possible existent block number /// (until when it may not be resubmitted) and who vetoed it. - pub Blacklist get(blacklist): map T::Hash => Option<(T::BlockNumber, Vec)>; + pub Blacklist get(fn blacklist): map T::Hash => Option<(T::BlockNumber, Vec)>; /// Record of all proposals that have been subject to emergency cancellation. pub Cancellations: map T::Hash => bool; @@ -361,7 +354,7 @@ decl_module! { /// Period in blocks where an external proposal may not be re-submitted after being vetoed. const CooloffPeriod: T::BlockNumber = T::CooloffPeriod::get(); - fn deposit_event() = default; + fn deposit_event() = default; /// Propose a sensitive action to be taken. /// @@ -382,11 +375,10 @@ decl_module! { let index = Self::public_prop_count(); PublicPropCount::put(index + 1); - >::insert(index, (value, vec![who.clone()])); + >::insert(index, (value, &[&who][..])); - let mut props = Self::public_props(); - props.push((index, (*proposal).clone(), who)); - >::put(props); + let new_prop = (index, proposal, who); + >::append_or_put(&[Ref::from(&new_prop)][..]); Self::deposit_event(RawEvent::Proposed(index, value)); } @@ -494,9 +486,10 @@ decl_module! { /// but it is not a majority-carries referendum then it fails. /// /// - `proposal_hash`: The hash of the current external proposal. - /// - `voting_period`: The period that is allowed for voting on this proposal. + /// - `voting_period`: The period that is allowed for voting on this proposal. Increased to + /// `EmergencyVotingPeriod` if too low. /// - `delay`: The number of block after voting has ended in approval and this should be - /// enacted. Increased to `EmergencyVotingPeriod` if too low. + /// enacted. This doesn't have a minimum amount. #[weight = SimpleDispatchInfo::FixedNormal(200_000)] fn fast_track(origin, proposal_hash: T::Hash, @@ -568,7 +561,7 @@ decl_module! { fn on_initialize(n: T::BlockNumber) { if let Err(e) = Self::end_block(n) { - runtime_io::print(e); + sr_primitives::print(e); } } @@ -615,7 +608,7 @@ decl_module! { #[weight = SimpleDispatchInfo::FixedNormal(500_000)] pub fn delegate(origin, to: T::AccountId, conviction: Conviction) { let who = ensure_signed(origin)?; - >::insert(who.clone(), (to.clone(), conviction)); + >::insert(&who, (&to, conviction)); // Currency is locked indefinitely as long as it's delegated. T::Currency::extend_lock( DEMOCRACY_ID, @@ -794,10 +787,10 @@ impl Module { /// Actually enact a vote, if legit. fn do_vote(who: T::AccountId, ref_index: ReferendumIndex, vote: Vote) -> Result { ensure!(Self::is_active_referendum(ref_index), "vote given for invalid referendum."); - if !>::exists(&(ref_index, who.clone())) { - >::mutate(ref_index, |voters| voters.push(who.clone())); + if !>::exists((ref_index, &who)) { + >::append_or_insert(ref_index, &[&who][..]); } - >::insert(&(ref_index, who), vote); + >::insert((ref_index, &who), vote); Ok(()) } @@ -933,9 +926,9 @@ impl Module { if info.delay.is_zero() { Self::enact_proposal(info.proposal, index); } else { - >::mutate( + >::append_or_insert( now + info.delay, - |q| q.push(Some((info.proposal, index))) + &[Some((info.proposal, index))][..] ); } } else { @@ -953,12 +946,12 @@ impl Module { if (now % T::LaunchPeriod::get()).is_zero() { // Errors come from the queue being empty. we don't really care about that, and even if // we did, there is nothing we can do here. - let _ = Self::launch_next(now.clone()); + let _ = Self::launch_next(now); } // tally up votes for any expiring referenda. for (index, info) in Self::maturing_referenda_at(now).into_iter() { - Self::bake_referendum(now.clone(), index, info)?; + Self::bake_referendum(now, index, info)?; } for (proposal, index) in >::take(now).into_iter().filter_map(|x| x) { @@ -977,14 +970,12 @@ impl OnFreeBalanceZero for Module { #[cfg(test)] mod tests { use super::*; - use runtime_io::with_externalities; - use srml_support::{ + use support::{ impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, traits::Contains }; - use primitives::{H256, Blake2Hasher}; - use sr_primitives::{traits::{BlakeTwo256, IdentityLookup, Bounded}, testing::Header}; - use sr_primitives::Perbill; + use primitives::H256; + use sr_primitives::{traits::{BlakeTwo256, IdentityLookup, Bounded}, testing::Header, Perbill}; use balances::BalanceLock; use system::EnsureSignedBy; @@ -1023,34 +1014,28 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } parameter_types! { pub const ExistentialDeposit: u64 = 0; pub const TransferFee: u64 = 0; pub const CreationFee: u64 = 0; - pub const TransactionBaseFee: u64 = 0; - pub const TransactionByteFee: u64 = 0; } impl balances::Trait for Test { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); type Event = (); - type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = (); } parameter_types! { pub const LaunchPeriod: u64 = 2; @@ -1089,7 +1074,7 @@ mod tests { type CooloffPeriod = CooloffPeriod; } - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); balances::GenesisConfig::{ balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)], @@ -1105,7 +1090,7 @@ mod tests { #[test] fn params_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(Democracy::referendum_count(), 0); assert_eq!(Balances::free_balance(&42), 0); assert_eq!(Balances::total_issuance(), 210); @@ -1137,7 +1122,7 @@ mod tests { #[test] fn external_and_public_interleaving_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(Democracy::external_propose( Origin::signed(2), @@ -1250,7 +1235,7 @@ mod tests { #[test] fn emergency_cancel_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); let r = Democracy::inject_referendum( 2, @@ -1279,7 +1264,7 @@ mod tests { #[test] fn veto_external_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(Democracy::external_propose( Origin::signed(2), @@ -1339,7 +1324,7 @@ mod tests { #[test] fn external_referendum_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_noop!(Democracy::external_propose( Origin::signed(1), @@ -1368,7 +1353,7 @@ mod tests { #[test] fn external_majority_referendum_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_noop!(Democracy::external_propose_majority( Origin::signed(1), @@ -1393,7 +1378,7 @@ mod tests { #[test] fn external_default_referendum_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_noop!(Democracy::external_propose_default( Origin::signed(3), @@ -1418,7 +1403,7 @@ mod tests { #[test] fn fast_track_referendum_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); let h = BlakeTwo256::hash_of(&set_balance_proposal(2)); assert_noop!(Democracy::fast_track(Origin::signed(5), h, 3, 2), "no proposal made"); @@ -1442,7 +1427,7 @@ mod tests { #[test] fn fast_track_referendum_fails_when_no_simple_majority() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); let h = BlakeTwo256::hash_of(&set_balance_proposal(2)); assert_ok!(Democracy::external_propose( @@ -1458,7 +1443,7 @@ mod tests { #[test] fn locked_for_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); assert_ok!(propose_set_balance(1, 2, 2)); assert_ok!(propose_set_balance(1, 4, 4)); @@ -1471,7 +1456,7 @@ mod tests { #[test] fn single_proposal_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); assert!(Democracy::referendum_info(0).is_none()); @@ -1518,7 +1503,7 @@ mod tests { #[test] fn cancel_queued_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); @@ -1542,7 +1527,7 @@ mod tests { #[test] fn proxy_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(Democracy::proxy(10), None); assert_ok!(Democracy::set_proxy(Origin::signed(1), 10)); assert_eq!(Democracy::proxy(10), Some(1)); @@ -1572,7 +1557,7 @@ mod tests { #[test] fn single_proposal_should_work_with_proxy() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); @@ -1592,7 +1577,7 @@ mod tests { #[test] fn single_proposal_should_work_with_delegation() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); @@ -1617,7 +1602,7 @@ mod tests { #[test] fn single_proposal_should_work_with_cyclic_delegation() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); @@ -1644,7 +1629,7 @@ mod tests { #[test] /// If transactor already voted, delegated vote is overwriten. fn single_proposal_should_work_with_vote_and_delegation() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); @@ -1670,7 +1655,7 @@ mod tests { #[test] fn single_proposal_should_work_with_undelegation() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); @@ -1699,7 +1684,7 @@ mod tests { #[test] /// If transactor voted, delegated vote is overwriten. fn single_proposal_should_work_with_delegation_and_vote() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 1)); @@ -1730,7 +1715,7 @@ mod tests { #[test] fn deposit_for_proposals_should_be_taken() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); assert_ok!(propose_set_balance(1, 2, 5)); assert_ok!(Democracy::second(Origin::signed(2), 0)); @@ -1745,7 +1730,7 @@ mod tests { #[test] fn deposit_for_proposals_should_be_returned() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); assert_ok!(propose_set_balance(1, 2, 5)); assert_ok!(Democracy::second(Origin::signed(2), 0)); @@ -1761,7 +1746,7 @@ mod tests { #[test] fn proposal_with_deposit_below_minimum_should_not_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); assert_noop!(propose_set_balance(1, 2, 0), "value too low"); }); @@ -1769,7 +1754,7 @@ mod tests { #[test] fn poor_proposer_should_not_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); assert_noop!(propose_set_balance(1, 2, 11), "proposer\'s balance too low"); }); @@ -1777,7 +1762,7 @@ mod tests { #[test] fn poor_seconder_should_not_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); assert_ok!(propose_set_balance(2, 2, 11)); assert_noop!(Democracy::second(Origin::signed(1), 0), "seconder\'s balance too low"); @@ -1786,7 +1771,7 @@ mod tests { #[test] fn runners_up_should_come_after() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); assert_ok!(propose_set_balance(1, 2, 2)); assert_ok!(propose_set_balance(1, 4, 4)); @@ -1802,7 +1787,7 @@ mod tests { #[test] fn simple_passing_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); let r = Democracy::inject_referendum( 1, @@ -1825,7 +1810,7 @@ mod tests { #[test] fn cancel_referendum_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); let r = Democracy::inject_referendum( 1, @@ -1845,7 +1830,7 @@ mod tests { #[test] fn simple_failing_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); let r = Democracy::inject_referendum( 1, @@ -1868,7 +1853,7 @@ mod tests { #[test] fn controversial_voting_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); let r = Democracy::inject_referendum( 1, @@ -1894,7 +1879,7 @@ mod tests { #[test] fn delayed_enactment_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); let r = Democracy::inject_referendum( 1, @@ -1922,7 +1907,7 @@ mod tests { #[test] fn controversial_low_turnout_voting_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); let r = Democracy::inject_referendum( 1, @@ -1944,7 +1929,7 @@ mod tests { #[test] fn passing_low_turnout_voting_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(Balances::free_balance(&42), 0); assert_eq!(Balances::total_issuance(), 210); @@ -1970,7 +1955,7 @@ mod tests { #[test] fn lock_voting_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(0); let r = Democracy::inject_referendum( 1, @@ -2030,7 +2015,7 @@ mod tests { #[test] fn lock_voting_should_work_with_delegation() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); let r = Democracy::inject_referendum( 1, diff --git a/srml/democracy/src/vote_threshold.rs b/srml/democracy/src/vote_threshold.rs index d304c36f32c95d7ba7523c0576f0bad4deed9d09..61e7e6535941ab6d797c6f9bbdcc14eefc63e0f4 100644 --- a/srml/democracy/src/vote_threshold.rs +++ b/srml/democracy/src/vote_threshold.rs @@ -23,8 +23,8 @@ use sr_primitives::traits::{Zero, IntegerSquareRoot}; use rstd::ops::{Add, Mul, Div, Rem}; /// A means of determining if a vote is past pass threshold. -#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] +#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, sr_primitives::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum VoteThreshold { /// A supermajority of approvals is needed to pass this vote. SuperMajorityApprove, diff --git a/srml/elections-phragmen/Cargo.toml b/srml/elections-phragmen/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..85532849ecc00c84729b71c8d4a3445616fccbc7 --- /dev/null +++ b/srml/elections-phragmen/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "srml-elections-phragmen" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +phragmen = { package = "substrate-phragmen", path = "../../core/phragmen", default-features = false } +srml-support = { path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } + +[dev-dependencies] +runtime_io = { package = "sr-io", path = "../../core/sr-io" } +hex-literal = "0.2.1" +balances = { package = "srml-balances", path = "../balances" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +serde = { version = "1.0.101" } + +[features] +default = ["std"] +std = [ + "codec/std", + "srml-support/std", + "sr-primitives/std", + "phragmen/std", + "system/std", + "rstd/std", +] diff --git a/srml/elections-phragmen/src/lib.rs b/srml/elections-phragmen/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b277815f385a8452d5a1b4d1e5200f718e1e9e0 --- /dev/null +++ b/srml/elections-phragmen/src/lib.rs @@ -0,0 +1,1771 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Phragmen Election Module. +//! +//! An election module based on sequential phragmen. +//! +//! ### Term and Round +//! +//! The election happens in _rounds_: every `N` blocks, all previous members are retired and a new +//! set is elected (which may or may not have an intersection with the previous set). Each round +//! lasts for some number of blocks defined by `TermDuration` storage item. The words _term_ and +//! _round_ can be used interchangeably in this context. +//! +//! `TermDuration` might change during a round. This can shorten or extend the length of the round. +//! The next election round's block number is never stored but rather always checked on the fly. +//! Based on the current block number and `TermDuration`, the condition `BlockNumber % TermDuration +//! == 0` being satisfied will always trigger a new election round. +//! +//! ### Voting +//! +//! Voters can vote for any set of the candidates by providing a list of account ids. Invalid votes +//! (voting for non-candidates) are ignored during election. Yet, a voter _might_ vote for a future +//! candidate. Voters reserve a bond as they vote. Each vote defines a `value`. This amount is +//! locked from the account of the voter and indicates the weight of the vote. Voters can update +//! their votes at any time by calling `vote()` again. This keeps the bond untouched but can +//! optionally change the locked `value`. After a round, votes are kept and might still be valid for +//! further rounds. A voter is responsible for calling `remove_voter` once they are done to have +//! their bond back and remove the lock. +//! +//! Voters also report other voters as being defunct to earn their bond. A voter is defunct once all +//! of the candidates that they have voted for are neither a valid candidate anymore nor a member. +//! Upon reporting, if the target voter is actually defunct, the reporter will be rewarded by the +//! voting bond of the target. The target will lose their bond and get removed. If the target is not +//! defunct, the reporter is slashed and removed. To prevent being reported, voters should manually +//! submit a `remove_voter()` as soon as they are in the defunct state. +//! +//! ### Candidacy and Members +//! +//! Candidates also reserve a bond as they submit candidacy. A candidate cannot take their candidacy +//! back. A candidate can end up in one of the below situations: +//! - **Winner**: A winner is kept as a _member_. They must still have a bond in reserve and they +//! are automatically counted as a candidate for the next election. +//! - **Loser**: Any of the candidate who are not a winner are left as losers. A loser might be an +//! _outgoing member_, meaning that they are an active member who failed to keep their spot. In +//! this case, the outgoing member will get their bond back. Otherwise, the bond is slashed from +//! the loser candidate. +//! - **Runner-up**: Runners-up are the best candidates immediately after the winners. The number +//! of runners_up to keep is configurable. Runners-up are used, in order that they are elected, +//! as replacements when a candidate is kicked by `remove_member()`. +//! +//! Note that with the members being the default candidates for the next round and votes persisting +//! in storage, the election system is entirely stable given no further input. This means that if +//! the system has a particular set of candidates `C` and voters `V` that lead to a set of members +//! `M` being elected, as long as `V` and `C` don't remove their candidacy and votes, `M` will keep +//! being re-elected at the end of each round. +//! +//! ### Module Information +//! +//! - [`election_phragmen::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::prelude::*; +use codec::Decode; +use sr_primitives::{print, traits::{Zero, StaticLookup, Bounded, Convert}}; +use sr_primitives::weights::SimpleDispatchInfo; +use srml_support::{ + decl_storage, decl_event, ensure, decl_module, dispatch, + storage::unhashed, + traits::{ + Currency, Get, LockableCurrency, LockIdentifier, ReservableCurrency, WithdrawReasons, + ChangeMembers, OnUnbalanced, WithdrawReason + } +}; +use phragmen::ExtendedBalance; +use system::{self, ensure_signed, ensure_root}; + +const MODULE_ID: LockIdentifier = *b"phrelect"; + +/// The maximum votes allowed per voter. +pub const MAXIMUM_VOTE: usize = 16; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = + <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: system::Trait { + /// The overarching event type.c + type Event: From> + Into<::Event>; + + /// The currency that people are electing with. + type Currency: + LockableCurrency + + ReservableCurrency; + + /// What to do when the members change. + type ChangeMembers: ChangeMembers; + + /// Convert a balance into a number used for election calculation. + /// This must fit into a `u64` but is allowed to be sensibly lossy. + type CurrencyToVote: Convert, u64> + Convert>; + + /// How much should be locked up in order to submit one's candidacy. + type CandidacyBond: Get>; + + /// How much should be locked up in order to be able to submit votes. + type VotingBond: Get>; + + /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner-up) + type LoserCandidate: OnUnbalanced>; + + /// Handler for the unbalanced reduction when a reporter has submitted a bad defunct report. + type BadReport: OnUnbalanced>; + + /// Handler for the unbalanced reduction when a member has been kicked. + type KickedMember: OnUnbalanced>; + + /// Number of members to elect. + type DesiredMembers: Get; + + /// Number of runners_up to keep. + type DesiredRunnersUp: Get; + + /// How long each seat is kept. This defines the next block number at which an election + /// round will happen. If set to zero, no elections are ever triggered and the module will + /// be in passive mode. + type TermDuration: Get; +} + +decl_storage! { + trait Store for Module as PhragmenElection { + // ---- State + /// The current elected membership. Sorted based on account id. + pub Members get(fn members): Vec<(T::AccountId, BalanceOf)>; + /// The current runners_up. Sorted based on low to high merit (worse to best runner). + pub RunnersUp get(fn runners_up): Vec<(T::AccountId, BalanceOf)>; + /// The total number of vote rounds that have happened, excluding the upcoming one. + pub ElectionRounds get(fn election_rounds): u32 = Zero::zero(); + + /// Votes of a particular voter, with the round index of the votes. + pub VotesOf get(fn votes_of): linked_map T::AccountId => Vec; + /// Locked stake of a voter. + pub StakeOf get(fn stake_of): map T::AccountId => BalanceOf; + + /// The present candidate list. Sorted based on account id. A current member can never enter + /// this vector and is always implicitly assumed to be a candidate. + pub Candidates get(fn candidates): Vec; + + /// Has the storage format been updated? + /// NOTE: Only use and set to false if you have used an early version of this module. Should + /// be set to true otherwise. + DidMigrate: bool; + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + const CandidacyBond: BalanceOf = T::CandidacyBond::get(); + const VotingBond: BalanceOf = T::VotingBond::get(); + const DesiredMembers: u32 = T::DesiredMembers::get(); + const DesiredRunnersUp: u32 = T::DesiredRunnersUp::get(); + const TermDuration: T::BlockNumber = T::TermDuration::get(); + + /// Vote for a set of candidates for the upcoming round of election. + /// + /// The `votes` should: + /// - not be empty. + /// - be less than the number of candidates. + /// + /// Upon voting, `value` units of `who`'s balance is locked and a bond amount is reserved. + /// It is the responsibility of the caller to not place all of their balance into the lock + /// and keep some for further transactions. + /// + /// # + /// #### State + /// Reads: O(1) + /// Writes: O(V) given `V` votes. V is bounded by 16. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] + fn vote(origin, votes: Vec, #[compact] value: BalanceOf) { + let who = ensure_signed(origin)?; + + let candidates_count = >::decode_len().unwrap_or(0) as usize; + let members_count = >::decode_len().unwrap_or(0) as usize; + // addition is valid: candidates and members never overlap. + let allowed_votes = candidates_count + members_count; + + ensure!(!allowed_votes.is_zero(), "cannot vote when no candidates or members exist"); + ensure!(votes.len() <= allowed_votes, "cannot vote more than candidates"); + ensure!(votes.len() <= MAXIMUM_VOTE, "cannot vote more than maximum allowed"); + ensure!(!votes.is_empty(), "must vote for at least one candidate."); + + ensure!( + value > T::Currency::minimum_balance(), + "cannot vote with stake less than minimum balance" + ); + + if !Self::is_voter(&who) { + // first time voter. Reserve bond. + T::Currency::reserve(&who, T::VotingBond::get()) + .map_err(|_| "voter can not pay voting bond")?; + } + // Amount to be locked up. + let locked_balance = value.min(T::Currency::total_balance(&who)); + + // lock + T::Currency::set_lock( + MODULE_ID, + &who, + locked_balance, + T::BlockNumber::max_value(), + WithdrawReasons::except(WithdrawReason::TransactionPayment), + ); + >::insert(&who, locked_balance); + >::insert(&who, votes); + } + + /// Remove `origin` as a voter. This removes the lock and returns the bond. + /// + /// # + /// #### State + /// Reads: O(1) + /// Writes: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn remove_voter(origin) { + let who = ensure_signed(origin)?; + + ensure!(Self::is_voter(&who), "must be a voter"); + + Self::do_remove_voter(&who, true); + } + + /// Report `target` for being an defunct voter. In case of a valid report, the reporter is + /// rewarded by the bond amount of `target`. Otherwise, the reporter itself is removed and + /// their bond is slashed. + /// + /// A defunct voter is defined to be: + /// - a voter whose current submitted votes are all invalid. i.e. all of them are no + /// longer a candidate nor an active member. + /// + /// # + /// #### State + /// Reads: O(NLogM) given M current candidates and N votes for `target`. + /// Writes: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] + fn report_defunct_voter(origin, target: ::Source) { + let reporter = ensure_signed(origin)?; + let target = T::Lookup::lookup(target)?; + + ensure!(reporter != target, "cannot report self"); + ensure!(Self::is_voter(&reporter), "reporter must be a voter"); + + // Checking if someone is a candidate and a member here is O(LogN), making the whole + // function O(MLonN) with N candidates in total and M of them being voted by `target`. + // We could easily add another mapping to be able to check if someone is a candidate in + // `O(1)` but that would make the process of removing candidates at the end of each + // round slightly harder. Note that for now we have a bound of number of votes (`N`). + let valid = Self::is_defunct_voter(&target); + if valid { + // reporter will get the voting bond of the target + T::Currency::repatriate_reserved(&target, &reporter, T::VotingBond::get())?; + // remove the target. They are defunct. + Self::do_remove_voter(&target, false); + } else { + // slash the bond of the reporter. + let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; + T::BadReport::on_unbalanced(imbalance); + // remove the reporter. + Self::do_remove_voter(&reporter, false); + } + Self::deposit_event(RawEvent::VoterReported(target, reporter, valid)); + } + + + /// Submit oneself for candidacy. + /// + /// A candidate will either: + /// - Lose at the end of the term and forfeit their deposit. + /// - Win and become a member. Members will eventually get their stash back. + /// - Become a runner-up. Runners-ups are reserved members in case one gets forcefully + /// removed. + /// + /// # + /// #### State + /// Reads: O(LogN) Given N candidates. + /// Writes: O(1) + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] + fn submit_candidacy(origin) { + let who = ensure_signed(origin)?; + + let is_candidate = Self::is_candidate(&who); + ensure!(is_candidate.is_err(), "duplicate candidate submission"); + // assured to be an error, error always contains the index. + let index = is_candidate.unwrap_err(); + + ensure!(!Self::is_member(&who), "member cannot re-submit candidacy"); + + T::Currency::reserve(&who, T::CandidacyBond::get()) + .map_err(|_| "candidate does not have enough funds")?; + + >::mutate(|c| c.insert(index, who)); + } + + /// Remove a particular member from the set. This is effective immediately. + /// + /// If a runner-up is available, then the best runner-up will be removed and replaces the + /// outgoing member. Otherwise, a new phragmen round is started. + /// + /// Note that this does not affect the designated block number of the next election. + /// + /// # + /// #### State + /// Reads: O(do_phragmen) + /// Writes: O(do_phragmen) + /// # + #[weight = SimpleDispatchInfo::FixedOperational(2_000_000)] + fn remove_member(origin, who: ::Source) { + ensure_root(origin)?; + let who = T::Lookup::lookup(who)?; + + let mut members_with_stake = Self::members(); + if let Ok(index) = members_with_stake.binary_search_by(|(ref m, ref _s)| m.cmp(&who)) { + // remove, slash, emit event. + members_with_stake.remove(index); + let (imbalance, _) = T::Currency::slash_reserved(&who, T::CandidacyBond::get()); + T::KickedMember::on_unbalanced(imbalance); + Self::deposit_event(RawEvent::MemberKicked(who.clone())); + + let mut runners_up = Self::runners_up(); + if let Some((replacement, stake)) = runners_up.pop() { + // replace the outgoing with the best runner up. + if let Err(index) = members_with_stake + .binary_search_by(|(ref m, ref _s)| m.cmp(&replacement)) + { + members_with_stake.insert(index, (replacement.clone(), stake)); + ElectionRounds::mutate(|v| *v += 1); + T::ChangeMembers::change_members_sorted( + &[replacement], + &[who], + &members_with_stake + .iter() + .map(|(m, _)| m.clone()) + .collect::>(), + ); + } + // else it would mean that the runner up was already a member. This cannot + // happen. If it does, not much that we can do about it. + + >::put(members_with_stake); + >::put(runners_up); + } else { + // update `Members` storage -- `do_phragmen` adds this to the candidate list. + >::put(members_with_stake); + // trigger a new phragmen. grab a cup of coffee. This might take a while. + Self::do_phragmen(); + } + } + } + + /// What to do at the end of each block. Checks if an election needs to happen or not. + fn on_initialize(n: T::BlockNumber) { + if !DidMigrate::exists() { + DidMigrate::put(true); + Self::do_migrate(); + } + if let Err(e) = Self::end_block(n) { + print("Guru meditation"); + print(e); + } + } + } +} + +decl_event!( + pub enum Event where + Balance = BalanceOf, + ::AccountId, + { + /// A new term with new members. This indicates that enough candidates existed, not that + /// enough have has been elected. The inner value must be examined for this purpose. + NewTerm(Vec<(AccountId, Balance)>), + /// No (or not enough) candidates existed for this round. + EmptyTerm, + /// A member has been removed. This should always be followed by either `NewTerm` ot + /// `EmptyTerm`. + MemberKicked(AccountId), + /// A voter (first element) was reported (byt the second element) with the the report being + /// successful or not (third element). + VoterReported(AccountId, AccountId, bool), + } +); + +impl Module { + /// Check if `who` is a candidate. It returns the insert index if the element does not exists as + /// an error. + /// + /// State: O(LogN) given N candidates. + fn is_candidate(who: &T::AccountId) -> Result<(), usize> { + Self::candidates().binary_search(who).map(|_| ()) + } + + /// Check if `who` is a voter. It may or may not be a _current_ one. + /// + /// State: O(1). + fn is_voter(who: &T::AccountId) -> bool { + >::exists(who) + } + + /// Check if `who` is currently an active member. + /// + /// Limited number of members. Binary search. Constant time factor. O(1) + fn is_member(who: &T::AccountId) -> bool { + Self::members_ids().binary_search(who).is_ok() + } + + /// Returns number of desired members. + fn desired_members() -> u32 { + T::DesiredMembers::get() + } + + /// Returns number of desired runners up. + fn desired_runners_up() -> u32 { + T::DesiredRunnersUp::get() + } + + /// Returns the term duration + fn term_duration() -> T::BlockNumber { + T::TermDuration::get() + } + + /// Get the members' account ids. + fn members_ids() -> Vec { + Self::members().into_iter().map(|(m, _)| m).collect::>() + } + + /// The the runners' up account ids. + fn runners_up_ids() -> Vec { + Self::runners_up().into_iter().map(|(r, _)| r).collect::>() + } + + /// Check if `who` is a defunct voter. + /// + /// Note that false is returned if `who` is not a voter at all. + /// + /// O(NLogM) with M candidates and `who` having voted for `N` of them. + fn is_defunct_voter(who: &T::AccountId) -> bool { + if Self::is_voter(who) { + Self::votes_of(who) + .iter() + .all(|v| !Self::is_member(v) && !Self::is_candidate(v).is_ok()) + } else { + false + } + } + + /// Remove a certain someone as a voter. + /// + /// This will clean always clean the storage associated with the voter, and remove the balance + /// lock. Optionally, it would also return the reserved voting bond if indicated by `unreserve`. + fn do_remove_voter(who: &T::AccountId, unreserve: bool) { + // remove storage and lock. + >::remove(who); + >::remove(who); + T::Currency::remove_lock(MODULE_ID, who); + + if unreserve { + T::Currency::unreserve(who, T::VotingBond::get()); + } + } + + /// The locked stake of a voter. + fn locked_stake_of(who: &T::AccountId) -> BalanceOf { + Self::stake_of(who) + } + + /// Check there's nothing to do this block. + /// + /// Runs phragmen election and cleans all the previous candidate state. The voter state is NOT + /// cleaned and voters must themselves submit a transaction to retract. + fn end_block(block_number: T::BlockNumber) -> dispatch::Result { + if !Self::term_duration().is_zero() { + if (block_number % Self::term_duration()).is_zero() { + Self::do_phragmen(); + } + } + Ok(()) + } + + /// Run the phragmen election with all required side processes and state updates. + /// + /// Calls the appropriate `ChangeMembers` function variant internally. + /// + /// # + /// #### State + /// Reads: O(C + V*E) where C = candidates, V voters and E votes per voter exits. + /// Writes: O(M + R) with M desired members and R runners_up. + /// # + fn do_phragmen() { + let desired_seats = Self::desired_members() as usize; + let desired_runners_up = Self::desired_runners_up() as usize; + let num_to_elect = desired_runners_up + desired_seats; + + let mut candidates = Self::candidates(); + // candidates who explicitly called `submit_candidacy`. Only these folks are at the risk of + // losing their bond. + let mut exposed_candidates = candidates.clone(); + // current members are always a candidate for the next round as well. + // this is guaranteed to not create any duplicates. + candidates.append(&mut Self::members_ids()); + // previous runners_up are also always candidates for the next round. + candidates.append(&mut Self::runners_up_ids()); + // and exposed to being an outgoing in case they are no longer elected. + exposed_candidates.append(&mut Self::runners_up_ids()); + + let voters_and_votes = >::enumerate() + .map(|(v, i)| (v, i)) + .collect::)>>(); + let maybe_phragmen_result = phragmen::elect::<_, _, _, T::CurrencyToVote>( + num_to_elect, + 0, + candidates, + voters_and_votes, + Self::locked_stake_of, + false, + ); + + let mut to_release_bond: Vec = Vec::with_capacity(desired_seats); + let old_members = >::take(); + if let Some(phragmen_result) = maybe_phragmen_result { + // filter out those who had literally no votes at all. + // AUDIT/NOTE: the need to do this is because all candidates, even those who have no + // vote are still considered by phragmen and when good candidates are scarce, then these + // cheap ones might get elected. We might actually want to remove the filter and allow + // zero-voted candidates to also make it to the membership set. + let new_set_with_approval = phragmen_result.winners; + let new_set = new_set_with_approval + .into_iter() + .filter_map(|(m, a)| if a.is_zero() { None } else { Some(m) } ) + .collect::>(); + + let support_map = phragmen::build_support_map::<_, _, _, T::CurrencyToVote>( + &new_set, + &phragmen_result.assignments, + Self::locked_stake_of, + false, + ); + + let to_balance = |e: ExtendedBalance| + >>::convert(e); + let new_set_with_stake = new_set + .into_iter() + .map(|ref m| { + let support = support_map.get(m) + .expect( + "entire new_set was given to build_support_map; en entry must be \ + created for each item; qed" + ); + (m.clone(), to_balance(support.total)) + }) + .collect::)>>(); + + // split new set into winners and runner ups. + let split_point = desired_seats.min(new_set_with_stake.len()); + let mut new_members = (&new_set_with_stake[..split_point]).to_vec(); + let runners_up = &new_set_with_stake[split_point..] + .into_iter() + .cloned() + .rev() + .collect::)>>(); + + // sort and save the members. + new_members.sort(); + >::put(&new_members); + + // save the runners as-is + >::put(runners_up); + + // report member changes. We compute diff because we need the outgoing list. + let (incoming, outgoing) = T::ChangeMembers::compute_members_diff( + &Self::members_ids(), + &old_members.into_iter().map(|(m, _)| m).collect::>(), + ); + T::ChangeMembers::change_members_sorted( + &incoming, + &outgoing.clone(), + &Self::members_ids(), + ); + + // unlike exposed_candidates, these are members who were in the list and no longer + // exist. They must get their bond back. + to_release_bond = outgoing.to_vec(); + + // Burn loser bond. members list is sorted. O(NLogM) (N candidates, M members) + // runner up list is not sorted. O(K*N) given K runner ups. Overall: O(NLogM + N*K) + exposed_candidates.into_iter().for_each(|c| { + // any candidate who is not a member and not a runner up. + if new_members.binary_search_by_key(&c, |(m, _)| m.clone()).is_err() + && !Self::runners_up_ids().contains(&c) + { + let (imbalance, _) = T::Currency::slash_reserved(&c, T::CandidacyBond::get()); + T::LoserCandidate::on_unbalanced(imbalance); + } + }); + Self::deposit_event(RawEvent::NewTerm(new_members.to_vec())); + } else { + Self::deposit_event(RawEvent::EmptyTerm); + } + + // unreserve the bond of all the outgoings. + to_release_bond.iter().for_each(|m| { + T::Currency::unreserve(&m, T::CandidacyBond::get()); + }); + + // clean candidates. + >::kill(); + + ElectionRounds::mutate(|v| *v += 1); + } + + /// Perform the storage update needed to migrate the module from the initial version of the + /// storage. + /// + /// If decoding the old storage fails in any way, the consequence is that we start with an empty + /// set. + fn do_migrate() { + // old storage format. + let old_members: Vec = unhashed::get_raw(&>::hashed_key()) + .and_then(|bytes| Decode::decode(&mut &*bytes).ok()).unwrap_or_default(); + let old_runners: Vec = unhashed::get_raw(&>::hashed_key()) + .and_then(|bytes| Decode::decode(&mut &*bytes).ok()).unwrap_or_default(); + + // new storage format. + let new_runners: Vec<(T::AccountId, BalanceOf)> = old_runners + .into_iter() + .map(|r| (r, Zero::zero())) + .collect(); + let new_members: Vec<(T::AccountId, BalanceOf)> = old_members + .into_iter() + .map(|r| (r, Zero::zero())) + .collect(); + + >::put(new_members); + >::put(new_runners); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::cell::RefCell; + use srml_support::{assert_ok, assert_noop, parameter_types, assert_eq_uvec}; + use primitives::H256; + use sr_primitives::{ + Perbill, testing::Header, BuildStorage, + traits::{OnInitialize, BlakeTwo256, IdentityLookup, Block as BlockT}, + }; + use crate as elections; + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + } + + parameter_types! { + pub const ExistentialDeposit: u64 = 1; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + + impl balances::Trait for Test { + type Balance = u64; + type OnNewAccount = (); + type OnFreeBalanceZero = (); + type Event = Event; + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + + parameter_types! { + pub const CandidacyBond: u64 = 3; + } + + thread_local! { + static VOTING_BOND: RefCell = RefCell::new(2); + static DESIRED_MEMBERS: RefCell = RefCell::new(2); + static DESIRED_RUNNERS_UP: RefCell = RefCell::new(2); + static TERM_DURATION: RefCell = RefCell::new(5); + } + + pub struct VotingBond; + impl Get for VotingBond { + fn get() -> u64 { VOTING_BOND.with(|v| *v.borrow()) } + } + + pub struct DesiredMembers; + impl Get for DesiredMembers { + fn get() -> u32 { DESIRED_MEMBERS.with(|v| *v.borrow()) } + } + + pub struct DesiredRunnersUp; + impl Get for DesiredRunnersUp { + fn get() -> u32 { DESIRED_RUNNERS_UP.with(|v| *v.borrow()) } + } + + pub struct TermDuration; + impl Get for TermDuration { + fn get() -> u64 { TERM_DURATION.with(|v| *v.borrow()) } + } + + pub struct TestChangeMembers; + impl ChangeMembers for TestChangeMembers { + fn change_members_sorted(_: &[u64], _: &[u64], _: &[u64]) {} + } + + /// Simple structure that exposes how u64 currency can be represented as... u64. + pub struct CurrencyToVoteHandler; + impl Convert for CurrencyToVoteHandler { + fn convert(x: u64) -> u64 { x } + } + impl Convert for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { + x as u64 + } + } + + impl Trait for Test { + type Event = Event; + type Currency = Balances; + type CurrencyToVote = CurrencyToVoteHandler; + type ChangeMembers = TestChangeMembers; + type CandidacyBond = CandidacyBond; + type VotingBond = VotingBond; + type TermDuration = TermDuration; + type DesiredMembers = DesiredMembers; + type DesiredRunnersUp = DesiredRunnersUp; + type LoserCandidate = (); + type KickedMember = (); + type BadReport = (); + } + + pub type Block = sr_primitives::generic::Block; + pub type UncheckedExtrinsic = sr_primitives::generic::UncheckedExtrinsic; + + srml_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Balances: balances::{Module, Call, Event, Config}, + Elections: elections::{Module, Call, Event}, + } + ); + + pub struct ExtBuilder { + balance_factor: u64, + voter_bond: u64, + term_duration: u64, + desired_runners_up: u32, + } + + impl Default for ExtBuilder { + fn default() -> Self { + Self { + balance_factor: 1, + voter_bond: 2, + desired_runners_up: 0, + term_duration: 5, + } + } + } + + impl ExtBuilder { + pub fn voter_bond(mut self, fee: u64) -> Self { + self.voter_bond = fee; + self + } + pub fn desired_runners_up(mut self, count: u32) -> Self { + self.desired_runners_up = count; + self + } + pub fn term_duration(mut self, duration: u64) -> Self { + self.term_duration = duration; + self + } + pub fn build(self) -> runtime_io::TestExternalities { + VOTING_BOND.with(|v| *v.borrow_mut() = self.voter_bond); + TERM_DURATION.with(|v| *v.borrow_mut() = self.term_duration); + DESIRED_RUNNERS_UP.with(|v| *v.borrow_mut() = self.desired_runners_up); + GenesisConfig { + balances: Some(balances::GenesisConfig::{ + balances: vec![ + (1, 10 * self.balance_factor), + (2, 20 * self.balance_factor), + (3, 30 * self.balance_factor), + (4, 40 * self.balance_factor), + (5, 50 * self.balance_factor), + (6, 60 * self.balance_factor) + ], + vesting: vec![], + }), + }.build_storage().unwrap().into() + } + } + + fn all_voters() -> Vec { + >::enumerate().map(|(v, _)| v).collect::>() + } + + fn balances(who: &u64) -> (u64, u64) { + (Balances::free_balance(who), Balances::reserved_balance(who)) + } + + fn has_lock(who: &u64) -> u64 { + let lock = Balances::locks(who)[0].clone(); + assert_eq!(lock.id, MODULE_ID); + lock.amount + } + + #[test] + fn temp_migration_works() { + ExtBuilder::default().build().execute_with(|| { + use srml_support::storage::unhashed; + use codec::Encode; + + let old_members = vec![1u64, 2]; + let old_runners = vec![3u64]; + + let members_key = >::hashed_key(); + let runners_key = >::hashed_key(); + + unhashed::put_raw(&members_key, &old_members.encode()[..]); + unhashed::put_raw(&runners_key, &old_runners.encode()[..]); + + assert_eq!(DidMigrate::get(), false); + >::on_initialize(1); + assert_eq!(DidMigrate::get(), true); + + assert_eq!(Elections::members(), vec![(1, 0), (2, 0)]); + assert_eq!(Elections::runners_up(), vec![(3, 0)]); + }); + } + + #[test] + fn params_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::desired_members(), 2); + assert_eq!(Elections::term_duration(), 5); + assert_eq!(Elections::election_rounds(), 0); + + assert_eq!(Elections::members(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(>::decode_len().unwrap(), 0); + assert!(Elections::is_candidate(&1).is_err()); + + assert_eq!(all_voters(), vec![]); + assert_eq!(Elections::votes_of(&1), vec![]); + }); + } + + #[test] + fn term_duration_zero_is_passive() { + ExtBuilder::default() + .term_duration(0) + .build() + .execute_with(|| + { + System::set_block_number(1); + assert_eq!(Elections::term_duration(), 0); + assert_eq!(Elections::desired_members(), 2); + assert_eq!(Elections::election_rounds(), 0); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq!(Elections::candidates(), vec![]); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq!(Elections::candidates(), vec![]); + }); + } + + #[test] + fn simple_candidate_submission_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert!(Elections::is_candidate(&1).is_err()); + assert!(Elections::is_candidate(&2).is_err()); + + assert_eq!(balances(&1), (10, 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_eq!(balances(&1), (7, 3)); + + assert_eq!(Elections::candidates(), vec![1]); + + assert!(Elections::is_candidate(&1).is_ok()); + assert!(Elections::is_candidate(&2).is_err()); + + assert_eq!(balances(&2), (20, 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_eq!(balances(&2), (17, 3)); + + assert_eq!(Elections::candidates(), vec![1, 2]); + + assert!(Elections::is_candidate(&1).is_ok()); + assert!(Elections::is_candidate(&2).is_ok()); + }); + } + + #[test] + fn simple_candidate_submission_with_no_votes_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert!(Elections::is_candidate(&1).is_ok()); + assert!(Elections::is_candidate(&2).is_ok()); + assert_eq!(Elections::candidates(), vec![1, 2]); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert!(Elections::is_candidate(&1).is_err()); + assert!(Elections::is_candidate(&2).is_err()); + assert_eq!(Elections::candidates(), vec![]); + + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::runners_up(), vec![]); + }); + } + + #[test] + fn dupe_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_eq!(Elections::candidates(), vec![1]); + assert_noop!( + Elections::submit_candidacy(Origin::signed(1)), + "duplicate candidate submission" + ); + }); + } + + #[test] + fn member_candidacy_submission_should_not_work() { + // critically important to make sure that outgoing candidates and losers are not mixed up. + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![5]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq!(Elections::candidates(), vec![]); + + assert_noop!( + Elections::submit_candidacy(Origin::signed(5)), + "member cannot re-submit candidacy" + ); + }); + } + + #[test] + fn poor_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_noop!( + Elections::submit_candidacy(Origin::signed(7)), + "candidate does not have enough funds" + ); + }); + } + + #[test] + fn simple_voting_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(balances(&2), (20, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 20); + }); + } + + #[test] + fn can_vote_with_custom_stake() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(balances(&2), (20, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 12)); + + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 12); + }); + } + + #[test] + fn can_update_votes_and_stake() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(balances(&2), (20, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 20); + assert_eq!(Elections::stake_of(2), 20); + + // can update; different stake; different lock and reserve. + assert_ok!(Elections::vote(Origin::signed(2), vec![5, 4], 15)); + assert_eq!(balances(&2), (18, 2)); + assert_eq!(has_lock(&2), 15); + assert_eq!(Elections::stake_of(2), 15); + }); + } + + #[test] + fn cannot_vote_for_no_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + Elections::vote(Origin::signed(2), vec![], 20), + "cannot vote when no candidates or members exist" + ); + }); + } + + #[test] + fn can_vote_for_old_members_even_when_no_new_candidates() { + // let allowed_votes = candidates_count as usize + Self::members().len() + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::candidates(), vec![]); + + assert_ok!(Elections::vote(Origin::signed(3), vec![4, 5], 10)); + }); + } + + #[test] + fn cannot_vote_for_more_than_candidates() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_noop!( + Elections::vote(Origin::signed(2), vec![10, 20, 30], 20), + "cannot vote more than candidates" + ); + }); + } + + #[test] + fn cannot_vote_for_less_than_ed() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_noop!( + Elections::vote(Origin::signed(2), vec![4], 1), + "cannot vote with stake less than minimum balance" + ); + }) + } + + #[test] + fn can_vote_for_more_than_total_balance_but_moot() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 30)); + // you can lie but won't get away with it. + assert_eq!(Elections::stake_of(2), 20); + assert_eq!(has_lock(&2), 20); + }); + } + + #[test] + fn remove_voter_should_work() { + ExtBuilder::default().voter_bond(8).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![5], 30)); + + assert_eq_uvec!(all_voters(), vec![2, 3]); + assert_eq!(Elections::stake_of(2), 20); + assert_eq!(Elections::stake_of(3), 30); + assert_eq!(Elections::votes_of(2), vec![5]); + assert_eq!(Elections::votes_of(3), vec![5]); + + assert_ok!(Elections::remove_voter(Origin::signed(2))); + + assert_eq_uvec!(all_voters(), vec![3]); + assert_eq!(Elections::votes_of(2), vec![]); + assert_eq!(Elections::stake_of(2), 0); + + assert_eq!(balances(&2), (20, 0)); + assert_eq!(Balances::locks(&2).len(), 0); + }); + } + + #[test] + fn non_voter_remove_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!(Elections::remove_voter(Origin::signed(3)), "must be a voter"); + }); + } + + #[test] + fn dupe_remove_should_fail() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + + assert_ok!(Elections::remove_voter(Origin::signed(2))); + assert_eq!(all_voters(), vec![]); + + assert_noop!(Elections::remove_voter(Origin::signed(2)), "must be a voter"); + }); + } + + #[test] + fn removed_voter_should_not_be_counted() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_ok!(Elections::remove_voter(Origin::signed(4))); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![3, 5]); + }); + } + + #[test] + fn reporter_must_be_voter() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + Elections::report_defunct_voter(Origin::signed(1), 2), + "reporter must be a voter", + ); + }); + } + + #[test] + fn can_detect_defunct_voter() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + // will be soon a defunct voter. + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::candidates(), vec![]); + + // all of them have a member that they voted for. + assert_eq!(Elections::is_defunct_voter(&5), false); + assert_eq!(Elections::is_defunct_voter(&4), false); + assert_eq!(Elections::is_defunct_voter(&2), false); + + // defunct + assert_eq!(Elections::is_defunct_voter(&3), true); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); + + // has a candidate voted for. + assert_eq!(Elections::is_defunct_voter(&1), false); + + }); + } + + #[test] + fn report_voter_should_work_and_earn_reward() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(2), vec![4, 5], 20)); + // will be soon a defunct voter. + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::candidates(), vec![]); + + assert_eq!(balances(&3), (28, 2)); + assert_eq!(balances(&5), (45, 5)); + + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 3)); + assert_eq!( + System::events()[1].event, + Event::elections(RawEvent::VoterReported(3, 5, true)) + ); + + assert_eq!(balances(&3), (28, 0)); + assert_eq!(balances(&5), (47, 5)); + }); + } + + #[test] + fn report_voter_should_slash_when_bad_report() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::candidates(), vec![]); + + assert_eq!(balances(&4), (35, 5)); + assert_eq!(balances(&5), (45, 5)); + + assert_ok!(Elections::report_defunct_voter(Origin::signed(5), 4)); + assert_eq!( + System::events()[1].event, + Event::elections(RawEvent::VoterReported(4, 5, false)) + ); + + assert_eq!(balances(&4), (35, 5)); + assert_eq!(balances(&5), (45, 3)); + }); + } + + + #[test] + fn simple_voting_rounds_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![5], 20)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 15)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_eq_uvec!(all_voters(), vec![2, 3, 4]); + + assert_eq!(Elections::votes_of(2), vec![5]); + assert_eq!(Elections::votes_of(3), vec![3]); + assert_eq!(Elections::votes_of(4), vec![4]); + + assert_eq!(Elections::candidates(), vec![3, 4, 5]); + assert_eq!(>::decode_len().unwrap(), 3); + + assert_eq!(Elections::election_rounds(), 0); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(3, 30), (5, 20)]); + assert_eq!(Elections::runners_up(), vec![]); + assert_eq_uvec!(all_voters(), vec![2, 3, 4]); + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(>::decode_len().unwrap(), 0); + + assert_eq!(Elections::election_rounds(), 1); + }); + } + + #[test] + fn defunct_voter_will_be_counted() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + + // This guy's vote is pointless for this round. + assert_ok!(Elections::vote(Origin::signed(3), vec![4], 30)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(5, 50)]); + assert_eq!(Elections::election_rounds(), 1); + + // but now it has a valid target. + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + + // candidate 4 is affected by an old vote. + assert_eq!(Elections::members(), vec![(4, 30), (5, 50)]); + assert_eq!(Elections::election_rounds(), 2); + assert_eq_uvec!(all_voters(), vec![3, 5]); + }); + } + + #[test] + fn only_desired_seats_are_chosen() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::election_rounds(), 1); + assert_eq!(Elections::members_ids(), vec![4, 5]); + }); + } + + #[test] + fn phragmen_should_not_self_vote() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(Elections::election_rounds(), 1); + assert_eq!(Elections::members_ids(), vec![]); + }); + } + + #[test] + fn runners_up_should_be_kept() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![2], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + // sorted based on account id. + assert_eq!(Elections::members_ids(), vec![4, 5]); + // sorted based on merit (least -> most) + assert_eq!(Elections::runners_up_ids(), vec![3, 2]); + + // runner ups are still locked. + assert_eq!(balances(&4), (35, 5)); + assert_eq!(balances(&5), (45, 5)); + assert_eq!(balances(&3), (25, 5)); + }); + } + + #[test] + fn runners_up_should_be_next_candidates() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members(), vec![(4, 40), (5, 50)]); + assert_eq!(Elections::runners_up(), vec![(2, 20), (3, 30)]); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 15)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members(), vec![(3, 30), (4, 40)]); + assert_eq!(Elections::runners_up(), vec![(5, 15), (2, 20)]); + }); + } + + #[test] + fn runners_up_lose_bond_once_outgoing() { + ExtBuilder::default().desired_runners_up(1).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![4, 5]); + + assert_eq!(Elections::runners_up_ids(), vec![2]); + assert_eq!(balances(&2), (15, 5)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![4, 5]); + + assert_eq!(Elections::runners_up_ids(), vec![3]); + assert_eq!(balances(&3), (25, 5)); + assert_eq!(balances(&2), (15, 2)); + }); + } + + #[test] + fn current_members_are_always_implicitly_next_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::election_rounds(), 1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_ok!(Elections::remove_voter(Origin::signed(4))); + + // 5 will persist as candidates despite not being in the list. + assert_eq!(Elections::candidates(), vec![2, 3]); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + + // 4 removed; 5 and 3 are the new best. + assert_eq!(Elections::members_ids(), vec![3, 5]); + }); + } + + #[test] + fn election_state_is_uninterrupted() { + // what I mean by uninterrupted: + // given no input or stimulants the same members are re-elected. + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + + let check_at_block = |b: u32| { + System::set_block_number(b.into()); + assert_ok!(Elections::end_block(System::block_number())); + // we keep re-electing the same folks. + assert_eq!(Elections::members(), vec![(4, 40), (5, 50)]); + assert_eq!(Elections::runners_up(), vec![(2, 20), (3, 30)]); + // no new candidates but old members and runners-up are always added. + assert_eq!(Elections::candidates(), vec![]); + assert_eq!(Elections::election_rounds(), b / 5); + assert_eq_uvec!(all_voters(), vec![2, 3, 4, 5]); + }; + + // this state will always persist when no further input is given. + check_at_block(5); + check_at_block(10); + check_at_block(15); + check_at_block(20); + }); + } + + #[test] + fn remove_members_triggers_election() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![4, 5]); + assert_eq!(Elections::election_rounds(), 1); + + // a new candidate + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + + assert_ok!(Elections::remove_member(Origin::ROOT, 4)); + + assert_eq!(balances(&4), (35, 2)); // slashed + assert_eq!(Elections::election_rounds(), 2); // new election round + assert_eq!(Elections::members_ids(), vec![3, 5]); // new members + }); + } + + #[test] + fn seats_should_be_released_when_no_vote() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + assert_eq!(>::decode_len().unwrap(), 3); + + assert_eq!(Elections::election_rounds(), 0); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![3, 5]); + assert_eq!(Elections::election_rounds(), 1); + + assert_ok!(Elections::remove_voter(Origin::signed(2))); + assert_ok!(Elections::remove_voter(Origin::signed(3))); + assert_ok!(Elections::remove_voter(Origin::signed(4))); + assert_ok!(Elections::remove_voter(Origin::signed(5))); + + // meanwhile, no one cares to become a candidate again. + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![]); + assert_eq!(Elections::election_rounds(), 2); + }); + } + + #[test] + fn outgoing_will_get_the_bond_back() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(balances(&5), (50, 0)); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_eq!(balances(&5), (47, 3)); + + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + assert_eq!(balances(&5), (45, 5)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![5]); + + assert_ok!(Elections::remove_voter(Origin::signed(5))); + assert_eq!(balances(&5), (47, 3)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![]); + + assert_eq!(balances(&5), (50, 0)); + }); + } + + #[test] + fn losers_will_lose_the_bond() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + + assert_eq!(balances(&5), (47, 3)); + assert_eq!(balances(&3), (27, 3)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members_ids(), vec![5]); + + // winner + assert_eq!(balances(&5), (47, 3)); + // loser + assert_eq!(balances(&3), (27, 0)); + }); + } + + #[test] + fn incoming_outgoing_are_reported() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![5], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + assert_eq!(Elections::members_ids(), vec![4, 5]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + // 5 will change their vote and becomes an `outgoing` + assert_ok!(Elections::vote(Origin::signed(5), vec![4], 8)); + // 4 will stay in the set + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + // 3 will become a winner + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + // these two are losers. + assert_ok!(Elections::vote(Origin::signed(2), vec![2], 20)); + assert_ok!(Elections::vote(Origin::signed(1), vec![1], 10)); + + System::set_block_number(10); + assert_ok!(Elections::end_block(System::block_number())); + + // 3, 4 are new members, must still be bonded, nothing slashed. + assert_eq!(Elections::members(), vec![(3, 30), (4, 48)]); + assert_eq!(balances(&3), (25, 5)); + assert_eq!(balances(&4), (35, 5)); + + // 1 is a loser, slashed by 3. + assert_eq!(balances(&1), (5, 2)); + + // 5 is an outgoing loser, it will get their bond back. + assert_eq!(balances(&5), (48, 2)); + + assert_eq!( + System::events()[0].event, + Event::elections(RawEvent::NewTerm(vec![(4, 40), (5, 50)])), + ); + }) + } + + #[test] + fn invalid_votes_are_moot() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + + assert_ok!(Elections::vote(Origin::signed(3), vec![3], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![4], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![10], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq_uvec!(Elections::members_ids(), vec![3, 4]); + assert_eq!(Elections::election_rounds(), 1); + }); + } + + #[test] + fn members_are_sorted_based_on_id_runners_on_merit() { + ExtBuilder::default().desired_runners_up(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5))); + assert_ok!(Elections::submit_candidacy(Origin::signed(4))); + assert_ok!(Elections::submit_candidacy(Origin::signed(3))); + assert_ok!(Elections::submit_candidacy(Origin::signed(2))); + + assert_ok!(Elections::vote(Origin::signed(2), vec![3], 20)); + assert_ok!(Elections::vote(Origin::signed(3), vec![2], 30)); + assert_ok!(Elections::vote(Origin::signed(4), vec![5], 40)); + assert_ok!(Elections::vote(Origin::signed(5), vec![4], 50)); + + System::set_block_number(5); + assert_ok!(Elections::end_block(System::block_number())); + // id: low -> high. + assert_eq!(Elections::members(), vec![(4, 50), (5, 40)]); + // merit: low -> high. + assert_eq!(Elections::runners_up(), vec![(3, 20), (2, 30)]); + }); + } +} diff --git a/srml/elections/Cargo.toml b/srml/elections/Cargo.toml index d6043bb2d02337d2363c91b74348ccdef3ded0ec..88d147ac087aa69cf22e10f545fd333b5f2e63de 100644 --- a/srml/elections/Cargo.toml +++ b/srml/elections/Cargo.toml @@ -5,18 +5,18 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -hex-literal = "0.2.0" +hex-literal = "0.2.1" balances = { package = "srml-balances", path = "../balances" } [features] @@ -27,8 +27,8 @@ std = [ "primitives/std", "rstd/std", "serde", - "runtime_io/std", - "srml-support/std", + "runtime-io/std", + "support/std", "sr-primitives/std", "system/std", ] diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs index a96588e84a3c6b1d44283fd30172a36ce24ff860..1e2349440f1681abff31e6554d662cd4668a8af4 100644 --- a/srml/elections/src/lib.rs +++ b/srml/elections/src/lib.rs @@ -24,11 +24,13 @@ #![recursion_limit="128"] use rstd::prelude::*; -use sr_primitives::traits::{Zero, One, StaticLookup, Bounded, Saturating}; -use sr_primitives::weights::SimpleDispatchInfo; -use runtime_io::print; -use srml_support::{ - StorageValue, StorageMap, +use sr_primitives::{ + RuntimeDebug, + print, + traits::{Zero, One, StaticLookup, Bounded, Saturating}, + weights::SimpleDispatchInfo, +}; +use support::{ dispatch::Result, decl_storage, decl_event, ensure, decl_module, traits::{ Currency, ExistenceRequirement, Get, LockableCurrency, LockIdentifier, @@ -38,6 +40,9 @@ use srml_support::{ use codec::{Encode, Decode}; use system::{self, ensure_signed, ensure_root}; +mod mock; +mod tests; + // no polynomial attacks: // // all unbonded public operations should be constant time. @@ -96,8 +101,7 @@ use system::{self, ensure_signed, ensure_root}; // entries before they increase the capacity. /// The activity status of a voter. -#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Default)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Default, RuntimeDebug)] pub struct VoterInfo { /// Last VoteIndex in which this voter assigned (or initialized) approvals. last_active: VoteIndex, @@ -112,8 +116,7 @@ pub struct VoterInfo { } /// Used to demonstrate the status of a particular index in the global voter list. -#[derive(PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, RuntimeDebug)] pub enum CellStatus { /// Any out of bound index. Means a push a must happen to the chunk pointed by `NextVoterSet`. /// Voting fee is applied in case a new chunk is created. @@ -126,29 +129,23 @@ pub enum CellStatus { const MODULE_ID: LockIdentifier = *b"py/elect"; +/// Number of voters grouped in one chunk. pub const VOTER_SET_SIZE: usize = 64; +/// NUmber of approvals grouped in one chunk. pub const APPROVAL_SET_SIZE: usize = 8; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; +/// Index used to access chunks. type SetIndex = u32; +/// Index used to count voting rounds. pub type VoteIndex = u32; - -// all three must be in sync. +/// Underlying data type of the approvals. type ApprovalFlag = u32; -pub const APPROVAL_FLAG_MASK: ApprovalFlag = 0x8000_0000; -pub const APPROVAL_FLAG_LEN: usize = 32; - -pub const DEFAULT_CANDIDACY_BOND: u32 = 9; -pub const DEFAULT_VOTING_BOND: u32 = 0; -pub const DEFAULT_VOTING_FEE: u32 = 0; -pub const DEFAULT_PRESENT_SLASH_PER_VOTER: u32 = 1; -pub const DEFAULT_CARRY_COUNT: u32 = 2; -pub const DEFAULT_INACTIVE_GRACE_PERIOD: u32 = 1; -pub const DEFAULT_VOTING_PERIOD: u32 = 1000; -pub const DEFAULT_DECAY_RATIO: u32 = 24; +/// Number of approval flags that can fit into [`ApprovalFlag`] type. +const APPROVAL_FLAG_LEN: usize = 32; pub trait Trait: system::Trait { type Event: From> + Into<::Event>; @@ -184,6 +181,9 @@ pub trait Trait: system::Trait { /// _hole_ index and replace it. type VotingFee: Get>; + /// Minimum about that can be used as the locked value for voting. + type MinimumVotingLock: Get>; + /// The punishment, per voter, if you provide an invalid presentation. A /// reasonable default value is 1. type PresentSlashPerVoter: Get>; @@ -212,55 +212,59 @@ pub trait Trait: system::Trait { decl_storage! { trait Store for Module as Council { // ---- parameters + /// How long to give each top candidate to present themselves after the vote ends. - pub PresentationDuration get(presentation_duration) config(): T::BlockNumber; + pub PresentationDuration get(fn presentation_duration) config(): T::BlockNumber; /// How long each position is active for. - pub TermDuration get(term_duration) config(): T::BlockNumber; + pub TermDuration get(fn term_duration) config(): T::BlockNumber; /// Number of accounts that should constitute the collective. - pub DesiredSeats get(desired_seats) config(): u32; + pub DesiredSeats get(fn desired_seats) config(): u32; // ---- permanent state (always relevant, changes only at the finalization of voting) - /// The current membership. When there's a vote going on, this should still be used for executive - /// matters. The block number (second element in the tuple) is the block that their position is - /// active until (calculated by the sum of the block number when the member was elected - /// and their term duration). - pub Members get(members) config(): Vec<(T::AccountId, T::BlockNumber)>; + + /// The current membership. When there's a vote going on, this should still be used for + /// executive matters. The block number (second element in the tuple) is the block that + /// their position is active until (calculated by the sum of the block number when the + /// member was elected and their term duration). + pub Members get(fn members) config(): Vec<(T::AccountId, T::BlockNumber)>; /// The total number of vote rounds that have happened or are in progress. - pub VoteCount get(vote_index): VoteIndex; + pub VoteCount get(fn vote_index): VoteIndex; // ---- persistent state (always relevant, changes constantly) - /// A list of votes for each voter. The votes are stored as numeric values and parsed in a bit-wise manner. - /// - /// In order to get a human-readable representation (`Vec`), use [`all_approvals_of`]. - /// - /// Furthermore, each vector of scalars is chunked with the cap of `APPROVAL_SET_SIZE`. - pub ApprovalsOf get(approvals_of): map (T::AccountId, SetIndex) => Vec; - /// The vote index and list slot that the candidate `who` was registered or `None` if they are not - /// currently registered. - pub RegisterInfoOf get(candidate_reg_info): map T::AccountId => Option<(VoteIndex, u32)>; + + // A list of votes for each voter. The votes are stored as numeric values and parsed in a + // bit-wise manner. In order to get a human-readable representation (`Vec`), use + // [`all_approvals_of`]. Furthermore, each vector of scalars is chunked with the cap of + // `APPROVAL_SET_SIZE`. + pub ApprovalsOf get(fn approvals_of): map (T::AccountId, SetIndex) => Vec; + /// The vote index and list slot that the candidate `who` was registered or `None` if they + /// are not currently registered. + pub RegisterInfoOf get(fn candidate_reg_info): map T::AccountId => Option<(VoteIndex, u32)>; /// Basic information about a voter. - pub VoterInfoOf get(voter_info): map T::AccountId => Option>>; + pub VoterInfoOf get(fn voter_info): map T::AccountId => Option>>; /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). - pub Voters get(voters): map SetIndex => Vec>; + pub Voters get(fn voters): map SetIndex => Vec>; /// the next free set to store a voter in. This will keep growing. - pub NextVoterSet get(next_nonfull_voter_set): SetIndex = 0; + pub NextVoterSet get(fn next_nonfull_voter_set): SetIndex = 0; /// Current number of Voters. - pub VoterCount get(voter_count): SetIndex = 0; + pub VoterCount get(fn voter_count): SetIndex = 0; /// The present candidate list. - pub Candidates get(candidates): Vec; // has holes + pub Candidates get(fn candidates): Vec; // has holes /// Current number of active candidates - pub CandidateCount get(candidate_count): u32; + pub CandidateCount get(fn candidate_count): u32; // ---- temporary state (only relevant during finalization/presentation) + /// The accounts holding the seats that will become free on the next tally. - pub NextFinalize get(next_finalize): Option<(T::BlockNumber, u32, Vec)>; - /// Get the leaderboard if we're in the presentation phase. The first element is the weight of each entry; - /// It may be the direct summed approval stakes, or a weighted version of it. - pub Leaderboard get(leaderboard): Option, T::AccountId)> >; // ORDERED low -> high + pub NextFinalize get(fn next_finalize): Option<(T::BlockNumber, u32, Vec)>; + /// Get the leaderboard if we're in the presentation phase. The first element is the weight + /// of each entry; It may be the direct summed approval stakes, or a weighted version of it. + /// Sorted from low to high. + pub Leaderboard get(fn leaderboard): Option, T::AccountId)> >; /// Who is able to vote for whom. Value is the fund-holding account, key is the /// vote-transaction-sending account. - pub Proxy get(proxy): map T::AccountId => Option; + pub Proxy get(fn proxy): map T::AccountId => Option; } } @@ -294,6 +298,9 @@ decl_module! { /// is 1000. const VotingPeriod: T::BlockNumber = T::VotingPeriod::get(); + /// Minimum about that can be used as the locked value for voting. + const MinimumVotingLock: BalanceOf = T::MinimumVotingLock::get(); + /// Decay factor of weight when being accumulated. It should typically be set to /// __at least__ `membership_size -1` to keep the collective secure. /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight @@ -306,26 +313,26 @@ decl_module! { /// The chunk size of the approval vector. const APPROVAL_SET_SIZE: u32 = APPROVAL_SET_SIZE as u32; - fn deposit_event() = default; + fn deposit_event() = default; /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots /// are registered. /// - /// Locks the total balance of caller indefinitely. - /// Only [`retract_voter`] or [`reap_inactive_voter`] can unlock the balance. + /// Locks `value` from the balance of `origin` indefinitely. Only [`retract_voter`] or + /// [`reap_inactive_voter`] can unlock the balance. /// /// `hint` argument is interpreted differently based on: - /// - if `origin` is setting approvals for the first time: The index will be checked - /// for being a valid _hole_ in the voter list. + /// - if `origin` is setting approvals for the first time: The index will be checked for + /// being a valid _hole_ in the voter list. /// - if the hint is correctly pointing to a hole, no fee is deducted from `origin`. - /// - Otherwise, the call will succeed but the index is ignored and simply a push to the last chunk - /// with free space happens. If the new push causes a new chunk to be created, a fee indicated by - /// [`VotingFee`] is deducted. + /// - Otherwise, the call will succeed but the index is ignored and simply a push to the + /// last chunk with free space happens. If the new push causes a new chunk to be + /// created, a fee indicated by [`VotingFee`] is deducted. /// - if `origin` is already a voter: the index __must__ be valid and point to the correct - /// position of the `origin` in the current voters list. + /// position of the `origin` in the current voters list. /// - /// Note that any trailing `false` votes in `votes` is ignored; In approval voting, not voting for a candidate - /// and voting false, are equal. + /// Note that any trailing `false` votes in `votes` is ignored; In approval voting, not + /// voting for a candidate and voting false, are equal. /// /// # /// - O(1). @@ -333,13 +340,19 @@ decl_module! { /// - Argument `votes` is limited in length to number of candidates. /// # #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] - fn set_approvals(origin, votes: Vec, #[compact] index: VoteIndex, hint: SetIndex) -> Result { + fn set_approvals( + origin, + votes: Vec, + #[compact] index: VoteIndex, + hint: SetIndex, + #[compact] value: BalanceOf + ) -> Result { let who = ensure_signed(origin)?; - Self::do_set_approvals(who, votes, index, hint) + Self::do_set_approvals(who, votes, index, hint, value) } - /// Set candidate approvals from a proxy. Approval slots stay valid as long as candidates in those slots - /// are registered. + /// Set candidate approvals from a proxy. Approval slots stay valid as long as candidates in + /// those slots are registered. /// /// # /// - Same as `set_approvals` with one additional storage read. @@ -348,15 +361,16 @@ decl_module! { fn proxy_set_approvals(origin, votes: Vec, #[compact] index: VoteIndex, - hint: SetIndex + hint: SetIndex, + #[compact] value: BalanceOf ) -> Result { let who = Self::proxy(ensure_signed(origin)?).ok_or("not a proxy")?; - Self::do_set_approvals(who, votes, index, hint) + Self::do_set_approvals(who, votes, index, hint, value) } /// Remove a voter. For it not to be a bond-consuming no-op, all approved candidate indices - /// must now be either unregistered or registered to a candidate that registered the slot after - /// the voter gave their last approval set. + /// must now be either unregistered or registered to a candidate that registered the slot + /// after the voter gave their last approval set. /// /// Both indices must be provided as explained in [`voter_at`] function. /// @@ -380,7 +394,8 @@ decl_module! { ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_info(&reporter).is_some(), "reporter must be a voter"); - let info = Self::voter_info(&who).ok_or("target for inactivity cleanup must be active")?; + let info = Self::voter_info(&who) + .ok_or("target for inactivity cleanup must be active")?; let last_active = info.last_active; ensure!(assumed_vote_index == Self::vote_index(), "vote index not current"); @@ -419,8 +434,8 @@ decl_module! { ); if valid { - // This only fails if `reporter` doesn't exist, which it clearly must do since its the origin. - // Still, it's no more harmful to propagate any error at this point. + // This only fails if `reporter` doesn't exist, which it clearly must do since its + // the origin. Still, it's no more harmful to propagate any error at this point. T::Currency::repatriate_reserved(&who, &reporter, T::VotingBond::get())?; Self::deposit_event(RawEvent::VoterReaped(who, reporter)); } else { @@ -496,9 +511,10 @@ decl_module! { CandidateCount::put(count as u32 + 1); } - /// Claim that `signed` is one of the top Self::carry_count() + current_vote().1 candidates. - /// Only works if the `block_number >= current_vote().0` and `< current_vote().0 + presentation_duration()` - /// `signed` should have at least + /// Claim that `candidate` is one of the top `carry_count + desired_seats` candidates. Only + /// works iff the presentation period is active. `candidate` should have at least collected + /// some non-zero `total` votes and `origin` must have enough funds to pay for a potential + /// slash. /// /// # /// - O(voters) compute. @@ -514,12 +530,13 @@ decl_module! { let who = ensure_signed(origin)?; ensure!( !total.is_zero(), - "stake deposited to present winner and be added to leaderboard should be non-zero" + "stake deposited to present winner and be added to leaderboard should be non-zero", ); let candidate = T::Lookup::lookup(candidate)?; ensure!(index == Self::vote_index(), "index not current"); - let (_, _, expiring) = Self::next_finalize().ok_or("cannot present outside of presentation period")?; + let (_, _, expiring) = Self::next_finalize() + .ok_or("cannot present outside of presentation period")?; let bad_presentation_punishment = T::PresentSlashPerVoter::get() * BalanceOf::::from(Self::voter_count() as u32); @@ -528,11 +545,15 @@ decl_module! { "presenter must have sufficient slashable funds" ); - let mut leaderboard = Self::leaderboard().ok_or("leaderboard must exist while present phase active")?; + let mut leaderboard = Self::leaderboard() + .ok_or("leaderboard must exist while present phase active")?; ensure!(total > leaderboard[0].0, "candidate not worthy of leaderboard"); if let Some(p) = Self::members().iter().position(|&(ref c, _)| c == &candidate) { - ensure!(p < expiring.len(), "candidate must not form a duplicated member if elected"); + ensure!( + p < expiring.len(), + "candidate must not form a duplicated member if elected" + ); } let voters = Self::all_voters(); @@ -681,8 +702,8 @@ impl Module { } else { // next tally begins once enough members expire to bring members below desired. if desired_seats <= coming { - // the entire amount of desired seats is less than those new members - we'll have - // to wait until they expire. + // the entire amount of desired seats is less than those new members - we'll + // have to wait until they expire. Some(next_possible + Self::term_duration()) } else { Some(c[c.len() - (desired_seats - coming) as usize].1) @@ -723,19 +744,33 @@ impl Module { /// Actually do the voting. /// /// The voter index must be provided as explained in [`voter_at`] function. - fn do_set_approvals(who: T::AccountId, votes: Vec, index: VoteIndex, hint: SetIndex) -> Result { - let candidates = Self::candidates(); + fn do_set_approvals( + who: T::AccountId, + votes: Vec, + index: VoteIndex, + hint: SetIndex, + value: BalanceOf, + ) -> Result { + let candidates_len = ::Candidates::decode_len().unwrap_or(0_usize); ensure!(!Self::presentation_active(), "no approval changes during presentation period"); ensure!(index == Self::vote_index(), "incorrect vote index"); - ensure!(!candidates.is_empty(), "amount of candidates to receive approval votes should be non-zero"); - // Prevent a vote from voters that provide a list of votes that exceeds the candidates length - // since otherwise an attacker may be able to submit a very long list of `votes` that far exceeds - // the amount of candidates and waste more computation than a reasonable voting bond would cover. - ensure!(candidates.len() >= votes.len(), "amount of candidate votes cannot exceed amount of candidates"); + ensure!( + !candidates_len.is_zero(), + "amount of candidates to receive approval votes should be non-zero" + ); + // Prevent a vote from voters that provide a list of votes that exceeds the candidates + // length since otherwise an attacker may be able to submit a very long list of `votes` that + // far exceeds the amount of candidates and waste more computation than a reasonable voting + // bond would cover. + ensure!( + candidates_len >= votes.len(), + "amount of candidate votes cannot exceed amount of candidates" + ); + ensure!(value >= T::MinimumVotingLock::get(), "locked value must be more than limit"); // Amount to be locked up. - let mut locked_balance = T::Currency::total_balance(&who); + let mut locked_balance = value.min(T::Currency::total_balance(&who)); let mut pot_to_set = Zero::zero(); let hint = hint as usize; @@ -765,22 +800,24 @@ impl Module { CellStatus::Head | CellStatus::Occupied => { // Either occupied or out-of-range. let next = Self::next_nonfull_voter_set(); - let mut set = Self::voters(next); + let set_len = >::decode_len(next).unwrap_or(0_usize); // Caused a new set to be created. Pay for it. // This is the last potential error. Writes will begin afterwards. - if set.is_empty() { + if set_len == 0 { let imbalance = T::Currency::withdraw( &who, T::VotingFee::get(), - WithdrawReason::Fee, + WithdrawReason::Fee.into(), ExistenceRequirement::KeepAlive, )?; T::BadVoterIndex::on_unbalanced(imbalance); // NOTE: this is safe since the `withdraw()` will check this. locked_balance -= T::VotingFee::get(); } - Self::checked_push_voter(&mut set, who.clone(), next); - >::insert(next, set); + if set_len + 1 == VOTER_SET_SIZE { + NextVoterSet::put(next + 1); + } + >::append_or_insert(next, &[Some(who.clone())][..]) } } @@ -793,7 +830,7 @@ impl Module { &who, locked_balance, T::BlockNumber::max_value(), - WithdrawReasons::except(WithdrawReason::TransactionPayment), + WithdrawReasons::all(), ); >::insert( @@ -815,28 +852,33 @@ impl Module { let members = Self::members(); let desired_seats = Self::desired_seats() as usize; let number = >::block_number(); - let expiring = members.iter().take_while(|i| i.1 <= number).map(|i| i.0.clone()).collect::>(); + let expiring = + members.iter().take_while(|i| i.1 <= number).map(|i| i.0.clone()).collect::>(); let retaining_seats = members.len() - expiring.len(); if retaining_seats < desired_seats { let empty_seats = desired_seats - retaining_seats; - >::put((number + Self::presentation_duration(), empty_seats as u32, expiring)); + >::put( + (number + Self::presentation_duration(), empty_seats as u32, expiring) + ); // initialize leaderboard. let leaderboard_size = empty_seats + T::CarryCount::get() as usize; - >::put(vec![(Zero::zero(), T::AccountId::default()); leaderboard_size]); + >::put(vec![(BalanceOf::::zero(), T::AccountId::default()); leaderboard_size]); Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32)); } } - /// Finalize the vote, removing each of the `removals` and inserting `seats` of the most approved - /// candidates in their place. If the total number of members is less than the desired membership - /// a new vote is started. - /// Clears all presented candidates, returning the bond of the elected ones. + /// Finalize the vote, removing each of the `removals` and inserting `seats` of the most + /// approved candidates in their place. If the total number of members is less than the desired + /// membership a new vote is started. Clears all presented candidates, returning the bond of the + /// elected ones. fn finalize_tally() -> Result { let (_, coming, expiring): (T::BlockNumber, u32, Vec) = - >::take().ok_or("finalize can only be called after a tally is started.")?; - let leaderboard: Vec<(BalanceOf, T::AccountId)> = >::take().unwrap_or_default(); + >::take() + .ok_or("finalize can only be called after a tally is started.")?; + let leaderboard: Vec<(BalanceOf, T::AccountId)> = >::take() + .unwrap_or_default(); let new_expiry = >::block_number() + Self::term_duration(); // return bond to winners. @@ -892,15 +934,25 @@ impl Module { count += 1; } for (old, new) in candidates.iter().zip(new_candidates.iter()) { + // candidate is not a runner up. if old != new { // removed - kill it >::remove(old); + + // and candidate is not a winner. + if incoming.iter().find(|e| *e == old).is_none() { + // slash the bond. + let (imbalance, _) = T::Currency::slash_reserved(&old, T::CandidacyBond::get()); + T::LoserCandidate::on_unbalanced(imbalance); + } } } // discard any superfluous slots. - if let Some(last_index) = new_candidates.iter().rposition(|c| *c != T::AccountId::default()) { - new_candidates.truncate(last_index + 1); - } + if let Some(last_index) = new_candidates + .iter() + .rposition(|c| *c != T::AccountId::default()) { + new_candidates.truncate(last_index + 1); + } Self::deposit_event(RawEvent::TallyFinalized(incoming, outgoing)); @@ -910,18 +962,6 @@ impl Module { Ok(()) } - fn checked_push_voter(set: &mut Vec>, who: T::AccountId, index: u32) { - let len = set.len(); - - // Defensive only: this should never happen. Don't push since it will break more things. - if len == VOTER_SET_SIZE { return; } - - set.push(Some(who)); - if len + 1 == VOTER_SET_SIZE { - NextVoterSet::put(index + 1); - } - } - /// Get the set and vector index of a global voter index. /// /// Note that this function does not take holes into account. @@ -966,8 +1006,8 @@ impl Module { } } - /// A more sophisticated version of `voter_at`. Will be kept separate as most often it is an overdue - /// compared to `voter_at`. Only used when setting approvals. + /// A more sophisticated version of `voter_at`. Will be kept separate as most often it is an + /// overdue compared to `voter_at`. Only used when setting approvals. fn cell_status(set_index: SetIndex, vec_index: usize) -> CellStatus { let set = Self::voters(set_index); if vec_index < set.len() { @@ -987,13 +1027,15 @@ impl Module { approvals_flag_vec .chunks(APPROVAL_SET_SIZE) .enumerate() - .for_each(|(index, slice)| >::insert((who.clone(), index as SetIndex), slice.to_vec())); + .for_each(|(index, slice)| >::insert( + (&who, index as SetIndex), slice) + ); } /// shorthand for fetching a specific approval of a voter at a specific (global) index. /// - /// Using this function to read a vote is preferred as it reads `APPROVAL_SET_SIZE` items of type - /// `ApprovalFlag` from storage at most; not all of them. + /// Using this function to read a vote is preferred as it reads `APPROVAL_SET_SIZE` items of + /// type `ApprovalFlag` from storage at most; not all of them. /// /// Note that false is returned in case of no-vote or an explicit `false`. fn approvals_of_at(who: &T::AccountId, index: usize) -> bool { @@ -1012,7 +1054,6 @@ impl Module { /// Return true of the bit `n` of scalar `x` is set to `1` and false otherwise. fn bit_at(x: ApprovalFlag, n: usize) -> bool { if n < APPROVAL_FLAG_LEN { - // x & ( APPROVAL_FLAG_MASK >> n ) != 0 x & ( 1 << n ) != 0 } else { false @@ -1047,7 +1088,9 @@ impl Module { let mut result = Vec::with_capacity(chunk.len()); if chunk.is_empty() { return vec![] } chunk.into_iter() - .map(|num| (0..APPROVAL_FLAG_LEN).map(|bit| Self::bit_at(num, bit)).collect::>()) + .map(|num| + (0..APPROVAL_FLAG_LEN).map(|bit| Self::bit_at(num, bit)).collect::>() + ) .for_each(|c| { let last_approve = match c.iter().rposition(|n| *n) { Some(index) => index + 1, @@ -1109,1768 +1152,3 @@ impl Module { r } } - -#[cfg(test)] -mod tests { - use super::*; - use std::cell::RefCell; - use srml_support::{assert_ok, assert_err, assert_noop, parameter_types}; - use runtime_io::with_externalities; - use primitives::{H256, Blake2Hasher}; - use sr_primitives::{ - Perbill, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, BuildStorage - }; - use crate as elections; - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type WeightMultiplierUpdate = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - pub const TransactionBaseFee: u64 = 0; - pub const TransactionByteFee: u64 = 0; - } - impl balances::Trait for Test { - type Balance = u64; - type OnNewAccount = (); - type OnFreeBalanceZero = (); - type Event = Event; - type TransactionPayment = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = (); - } - parameter_types! { - pub const CandidacyBond: u64 = 3; - pub const CarryCount: u32 = 2; - pub const InactiveGracePeriod: u32 = 1; - pub const VotingPeriod: u64 = 4; - } - - thread_local! { - static VOTER_BOND: RefCell = RefCell::new(0); - static VOTING_FEE: RefCell = RefCell::new(0); - static PRESENT_SLASH_PER_VOTER: RefCell = RefCell::new(0); - static DECAY_RATIO: RefCell = RefCell::new(0); - static MEMBERS: RefCell> = RefCell::new(vec![]); - } - - pub struct VotingBond; - impl Get for VotingBond { - fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) } - } - - pub struct VotingFee; - impl Get for VotingFee { - fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) } - } - - pub struct PresentSlashPerVoter; - impl Get for PresentSlashPerVoter { - fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) } - } - - pub struct DecayRatio; - impl Get for DecayRatio { - fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) } - } - - pub struct TestChangeMembers; - impl ChangeMembers for TestChangeMembers { - fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { - let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); - old_plus_incoming.extend_from_slice(incoming); - old_plus_incoming.sort(); - let mut new_plus_outgoing = new.to_vec(); - new_plus_outgoing.extend_from_slice(outgoing); - new_plus_outgoing.sort(); - assert_eq!(old_plus_incoming, new_plus_outgoing); - - MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); - } - } - - impl Trait for Test { - type Event = Event; - type Currency = Balances; - type BadPresentation = (); - type BadReaper = (); - type BadVoterIndex = (); - type LoserCandidate = (); - type ChangeMembers = TestChangeMembers; - type CandidacyBond = CandidacyBond; - type VotingBond = VotingBond; - type VotingFee = VotingFee; - type PresentSlashPerVoter = PresentSlashPerVoter; - type CarryCount = CarryCount; - type InactiveGracePeriod = InactiveGracePeriod; - type VotingPeriod = VotingPeriod; - type DecayRatio = DecayRatio; - } - - pub type Block = sr_primitives::generic::Block; - pub type UncheckedExtrinsic = sr_primitives::generic::UncheckedExtrinsic; - - srml_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: system::{Module, Call, Event}, - Balances: balances::{Module, Call, Event, Config}, - Elections: elections::{Module, Call, Event, Config}, - } - ); - - pub struct ExtBuilder { - balance_factor: u64, - decay_ratio: u32, - voting_fee: u64, - voter_bond: u64, - bad_presentation_punishment: u64, - } - - impl Default for ExtBuilder { - fn default() -> Self { - Self { - balance_factor: 1, - decay_ratio: 24, - voting_fee: 0, - voter_bond: 0, - bad_presentation_punishment: 1, - } - } - } - - impl ExtBuilder { - pub fn balance_factor(mut self, factor: u64) -> Self { - self.balance_factor = factor; - self - } - pub fn decay_ratio(mut self, ratio: u32) -> Self { - self.decay_ratio = ratio; - self - } - pub fn voting_fee(mut self, fee: u64) -> Self { - self.voting_fee = fee; - self - } - pub fn bad_presentation_punishment(mut self, fee: u64) -> Self { - self.bad_presentation_punishment = fee; - self - } - pub fn voter_bond(mut self, fee: u64) -> Self { - self.voter_bond = fee; - self - } - pub fn build(self) -> runtime_io::TestExternalities { - VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond); - VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee); - PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment); - DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio); - GenesisConfig { - balances: Some(balances::GenesisConfig::{ - balances: vec![ - (1, 10 * self.balance_factor), - (2, 20 * self.balance_factor), - (3, 30 * self.balance_factor), - (4, 40 * self.balance_factor), - (5, 50 * self.balance_factor), - (6, 60 * self.balance_factor) - ], - vesting: vec![], - }), - elections: Some(elections::GenesisConfig::{ - members: vec![], - desired_seats: 2, - presentation_duration: 2, - term_duration: 5, - }), - }.build_storage().unwrap().into() - } - } - - fn voter_ids() -> Vec { - Elections::all_voters().iter().map(|v| v.unwrap_or(0) ).collect::>() - } - - fn vote(i: u64, l: usize) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!(Elections::set_approvals(Origin::signed(i), (0..l).map(|_| true).collect::>(), 0, 0)); - } - - fn vote_at(i: u64, l: usize, index: VoteIndex) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!(Elections::set_approvals(Origin::signed(i), (0..l).map(|_| true).collect::>(), 0, index)); - } - - fn create_candidate(i: u64, index: u32) { - let _ = Balances::make_free_balance_be(&i, 20); - assert_ok!(Elections::submit_candidacy(Origin::signed(i), index)); - } - - fn bond() -> u64 { - ::VotingBond::get() - } - - #[test] - fn bool_to_flag_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_eq!(Elections::bool_to_flag(vec![]), vec![]); - assert_eq!(Elections::bool_to_flag(vec![false]), vec![0]); - assert_eq!(Elections::bool_to_flag(vec![true]), vec![1]); - assert_eq!(Elections::bool_to_flag(vec![true, true, true, true]), vec![15]); - assert_eq!(Elections::bool_to_flag(vec![true, true, true, true, true]), vec![15 + 16]); - - let set_1 = vec![ - true, false, false, false, // 0x1 - false, true, true, true, // 0xE - ]; - assert_eq!( - Elections::bool_to_flag(set_1.clone()), - vec![0x00_00_00_E1_u32] - ); - assert_eq!( - Elections::flag_to_bool(vec![0x00_00_00_E1_u32]), - set_1 - ); - - let set_2 = vec![ - false, false, false, true, // 0x8 - false, true, false, true, // 0xA - ]; - assert_eq!( - Elections::bool_to_flag(set_2.clone()), - vec![0x00_00_00_A8_u32] - ); - assert_eq!( - Elections::flag_to_bool(vec![0x00_00_00_A8_u32]), - set_2 - ); - - let mut rhs = (0..100/APPROVAL_FLAG_LEN).map(|_| 0xFFFFFFFF_u32).collect::>(); - // NOTE: this might be need change based on `APPROVAL_FLAG_LEN`. - rhs.extend(vec![0x00_00_00_0F]); - assert_eq!( - Elections::bool_to_flag((0..100).map(|_| true).collect()), - rhs - ) - }) - } - - #[test] - fn params_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_eq!(Elections::next_vote_from(1), 4); - assert_eq!(Elections::next_vote_from(4), 4); - assert_eq!(Elections::next_vote_from(5), 8); - assert_eq!(Elections::vote_index(), 0); - assert_eq!(Elections::presentation_duration(), 2); - assert_eq!(Elections::term_duration(), 5); - assert_eq!(Elections::desired_seats(), 2); - - assert_eq!(Elections::members(), vec![]); - assert_eq!(Elections::next_tally(), Some(4)); - assert_eq!(Elections::presentation_active(), false); - assert_eq!(Elections::next_finalize(), None); - - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Elections::is_a_candidate(&1), false); - assert_eq!(Elections::candidate_reg_info(1), None); - - assert_eq!(Elections::voters(0), Vec::>::new()); - assert_eq!(Elections::voter_info(1), None); - assert_eq!(Elections::all_approvals_of(&1), vec![]); - }); - } - - #[test] - fn voter_set_growth_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - // create 65. 64 (set0) + 1 (set1) - (1..=63).for_each(|i| vote(i, 2)); - assert_eq!(Elections::next_nonfull_voter_set(), 0); - vote(64, 2); - assert_eq!(Elections::next_nonfull_voter_set(), 1); - vote(65, 2); - - let set1 = Elections::voters(0); - let set2 = Elections::voters(1); - - assert_eq!(set1.len(), 64); - assert_eq!(set2.len(), 1); - - assert_eq!(set1[0], Some(1)); - assert_eq!(set1[10], Some(11)); - assert_eq!(set2[0], Some(65)); - }) - } - - #[test] - fn voter_set_reclaim_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - (1..=129).for_each(|i| vote(i, 2)); - assert_eq!(Elections::next_nonfull_voter_set(), 2); - - assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); - - assert_ok!(Elections::retract_voter(Origin::signed(66), 65)); - assert_ok!(Elections::retract_voter(Origin::signed(67), 66)); - - // length does not show it but holes do exist. - assert_eq!(Elections::voters(0).len(), 64); - assert_eq!(Elections::voters(1).len(), 64); - assert_eq!(Elections::voters(2).len(), 1); - - assert_eq!(Elections::voters(0)[10], None); - assert_eq!(Elections::voters(1)[1], None); - assert_eq!(Elections::voters(1)[2], None); - // Next set with capacity is 2. - assert_eq!(Elections::next_nonfull_voter_set(), 2); - - // But we can fill a hole. - vote_at(130, 2, 10); - - // Nothing added to set 2. A hole was filled. - assert_eq!(Elections::voters(0).len(), 64); - assert_eq!(Elections::voters(1).len(), 64); - assert_eq!(Elections::voters(2).len(), 1); - - // and the next two (scheduled) to the second set. - assert_eq!(Elections::next_nonfull_voter_set(), 2); - }) - } - - #[test] - fn approvals_set_growth_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - // create candidates and voters. - (1..=250).for_each(|i| create_candidate(i, (i-1) as u32)); - (1..=250).for_each(|i| vote(i, i as usize)); - - // all approvals of should return the exact expected vector. - assert_eq!(Elections::all_approvals_of(&180), (0..180).map(|_| true).collect::>()); - - assert_eq!(Elections::all_approvals_of(&32), (0..32).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&8), (0..8).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&64), (0..64).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&65), (0..65).map(|_| true).collect::>()); - assert_eq!(Elections::all_approvals_of(&63), (0..63).map(|_| true).collect::>()); - - // NOTE: assuming that APPROVAL_SET_SIZE is more or less small-ish. Might fail otherwise. - let full_sets = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; - let left_over = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; - let rem = 180 % APPROVAL_FLAG_LEN; - - // grab and check the last full set, if it exists. - if full_sets > 0 { - assert_eq!( - Elections::approvals_of((180, (full_sets-1) as SetIndex )), - Elections::bool_to_flag((0..APPROVAL_SET_SIZE * APPROVAL_FLAG_LEN).map(|_| true).collect::>()) - ); - } - - // grab and check the last, half-empty, set. - if left_over > 0 { - assert_eq!( - Elections::approvals_of((180, full_sets as SetIndex)), - Elections::bool_to_flag((0..left_over * APPROVAL_FLAG_LEN + rem).map(|_| true).collect::>()) - ); - } - }) - } - - - #[test] - fn cell_status_works() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - (1..=63).for_each(|i| vote(i, 2)); - - assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); - assert_ok!(Elections::retract_voter(Origin::signed(21), 20)); - - assert_eq!(Elections::cell_status(0, 10), CellStatus::Hole); - assert_eq!(Elections::cell_status(0, 0), CellStatus::Occupied); - assert_eq!(Elections::cell_status(0, 20), CellStatus::Hole); - assert_eq!(Elections::cell_status(0, 63), CellStatus::Head); - assert_eq!(Elections::cell_status(1, 0), CellStatus::Head); - assert_eq!(Elections::cell_status(1, 10), CellStatus::Head); - }) - } - - #[test] - fn initial_set_approvals_ignores_voter_index() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - // Last argument is essentially irrelevant. You might get or miss a tip. - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![true], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 5)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 0, 100)); - - // indices are more or less ignored. all is pushed. - assert_eq!(voter_ids(), vec![3, 4, 5]); - }) - } - - #[test] - fn bad_approval_index_slashes_voters_and_bond_reduces_stake() { - with_externalities(&mut ExtBuilder::default().voting_fee(5).voter_bond(2).build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - (1..=63).for_each(|i| vote(i, 2)); - assert_eq!(Balances::free_balance(&1), 20 - 5 - 2); // -5 fee -2 bond - assert_eq!(Balances::free_balance(&10), 20 - 2); - assert_eq!(Balances::free_balance(&60), 20 - 2); - - // still no fee - vote(64, 2); - assert_eq!(Balances::free_balance(&64), 20 - 2); // -2 bond - assert_eq!( - Elections::voter_info(&64).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 20, pot:0 } - ); - - assert_eq!(Elections::next_nonfull_voter_set(), 1); - - // now we charge the next voter. - vote(65, 2); - assert_eq!(Balances::free_balance(&65), 20 - 5 - 2); - assert_eq!( - Elections::voter_info(&65).unwrap(), - VoterInfo { last_win: 0, last_active: 0, stake: 15, pot:0 } - ); - }); - } - - #[test] - fn subsequent_set_approvals_checks_voter_index() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![true], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 5)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 0, 100)); - - // invalid index - assert_noop!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 5), "invalid voter index"); - // wrong index - assert_noop!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 0), "wrong voter index"); - // correct - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1)); - }) - } - - #[test] - fn voter_index_does_not_take_holes_into_account() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - // create 65. 64 (set0) + 1 (set1) - (1..=65).for_each(|i| vote(i, 2)); - - // account 65 has global index 65. - assert_eq!(Elections::voter_at(64).unwrap(), 65); - - assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); - - // still the same. These holes are in some other set. - assert_eq!(Elections::voter_at(64).unwrap(), 65); - // proof: can submit a new approval with the old index. - assert_noop!(Elections::set_approvals(Origin::signed(65), vec![false, true], 0, 64 - 2), "wrong voter index"); - assert_ok!(Elections::set_approvals(Origin::signed(65), vec![false, true], 0, 64)); - }) - } - - #[test] - fn simple_candidate_submission_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Elections::candidate_reg_info(1), None); - assert_eq!(Elections::candidate_reg_info(2), None); - assert_eq!(Elections::is_a_candidate(&1), false); - assert_eq!(Elections::is_a_candidate(&2), false); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); - assert_eq!(Elections::candidate_reg_info(2), None); - assert_eq!(Elections::is_a_candidate(&1), true); - assert_eq!(Elections::is_a_candidate(&2), false); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_eq!(Elections::candidates(), vec![1, 2]); - assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); - assert_eq!(Elections::candidate_reg_info(2), Some((0, 1))); - assert_eq!(Elections::is_a_candidate(&1), true); - assert_eq!(Elections::is_a_candidate(&2), true); - }); - } - - fn new_test_ext_with_candidate_holes() -> runtime_io::TestExternalities { - let mut t = ExtBuilder::default().build(); - with_externalities(&mut t, || { - >::put(vec![0, 0, 1]); - CandidateCount::put(1); - >::insert(1, (0, 2)); - }); - t - } - - #[test] - fn candidate_submission_using_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - with_externalities(&mut t, || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), vec![0, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_eq!(Elections::candidates(), vec![0, 2, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - assert_eq!(Elections::candidates(), vec![3, 2, 1]); - }); - } - - #[test] - fn candidate_submission_using_alternative_free_slot_should_work() { - let mut t = new_test_ext_with_candidate_holes(); - - with_externalities(&mut t, || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), vec![0, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_eq!(Elections::candidates(), vec![2, 0, 1]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - assert_eq!(Elections::candidates(), vec![2, 3, 1]); - }); - } - - #[test] - fn candidate_submission_not_using_free_slot_should_not_work() { - let mut t = new_test_ext_with_candidate_holes(); - - with_externalities(&mut t, || { - System::set_block_number(1); - assert_noop!(Elections::submit_candidacy(Origin::signed(4), 3), "invalid candidate slot"); - }); - } - - #[test] - fn bad_candidate_slot_submission_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_noop!(Elections::submit_candidacy(Origin::signed(1), 1), "invalid candidate slot"); - }); - } - - #[test] - fn non_free_candidate_slot_submission_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_noop!(Elections::submit_candidacy(Origin::signed(2), 0), "invalid candidate slot"); - }); - } - - #[test] - fn dupe_candidate_submission_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_eq!(Elections::candidates(), vec![1]); - assert_noop!(Elections::submit_candidacy(Origin::signed(1), 1), "duplicate candidate submission"); - }); - } - - #[test] - fn poor_candidate_submission_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_noop!(Elections::submit_candidacy(Origin::signed(7), 0), "candidate has not enough funds"); - }); - } - - #[test] - fn balance_should_lock_to_the_maximum() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Balances::free_balance(&2), 20); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - - assert_eq!(Balances::free_balance(&2), 20 - bond() ); - assert_noop!(Balances::reserve(&2, 1), "account liquidity restrictions prevent withdrawal"); // locked. - - // deposit a bit more. - let _ = Balances::deposit_creating(&2, 100); - assert_ok!(Balances::reserve(&2, 1)); // locked but now has enough. - - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_noop!(Balances::reserve(&2, 1), "account liquidity restrictions prevent withdrawal"); // locked. - assert_eq!(Balances::locks(&2).len(), 1); - assert_eq!(Balances::locks(&2)[0].amount, 100 + 20); - - assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); - - assert_eq!(Balances::locks(&2).len(), 0); - assert_eq!(Balances::free_balance(&2), 120 - 1); // 1 ok call to .reserve() happened. - assert_ok!(Balances::reserve(&2, 1)); // unlocked. - }); - } - - #[test] - fn balance_should_lock_on_submit_approvals_unlock_on_retract() { - with_externalities(&mut ExtBuilder::default().voter_bond(8).voting_fee(0).build(), || { - System::set_block_number(1); - assert_eq!(Elections::candidates(), Vec::::new()); - assert_eq!(Balances::free_balance(&2), 20); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - - assert_eq!(Balances::free_balance(&2), 12); // 20 - 8 (bond) - assert_noop!(Balances::reserve(&2, 10), "account liquidity restrictions prevent withdrawal"); // locked. - - assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); - - assert_eq!(Balances::free_balance(&2), 20); - assert_ok!(Balances::reserve(&2, 10)); // unlocked. - }); - } - - #[test] - fn accumulating_weight_and_decaying_should_work() { - with_externalities(&mut ExtBuilder::default().balance_factor(10).build(), || { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); - - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 0)); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - assert_eq!(Elections::voter_info(6).unwrap(), VoterInfo { last_win: 1, last_active: 0, stake: 600, pot: 0}); - assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 1, last_active: 0, stake: 500, pot: 0}); - assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); - - System::set_block_number(12); - // retract needed to unlock approval funds => submit candidacy again. - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 1), 1), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 19), (5, 19)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 2, last_active: 1, stake: 600, pot:0 } - ); - assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 2, last_active: 1, stake: 500, pot:0 }); - assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot:0 }); - - System::set_block_number(20); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 2, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 2, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(22); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 2), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 2), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 2), 2), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 27), (5, 27)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 3, last_active: 2, stake: 600, pot: 0} - ); - assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 3, last_active: 2, stake: 500, pot: 0}); - assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); - - - System::set_block_number(28); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 3, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 3, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(30); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 3), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 3), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 3), 3), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93 + 90, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 35), (5, 35)]); - assert_eq!( - Elections::voter_info(6).unwrap(), - VoterInfo { last_win: 4, last_active: 3, stake: 600, pot: 0} - ); - assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 4, last_active: 3, stake: 500, pot: 0}); - assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); - }) - } - - #[test] - fn winning_resets_accumulated_pot() { - with_externalities(&mut ExtBuilder::default().balance_factor(10).build(), || { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 3)); - - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 0, 1)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true, true], 0, 2)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(300, 2), (300, 3), (400, 4), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (4, 11)]); - - System::set_block_number(12); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(4), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 1, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 1, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300 + Elections::get_offset(300, 1), 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300 + Elections::get_offset(300, 1), 1), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(400, 4), (588, 2), (588, 3), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 19), (3, 19)]); - - System::set_block_number(20); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(22); - // 2 will not get re-elected with 300 + 288, instead just 300. - // because one of 3's candidates (3) won in previous round - // 4 on the other hand will get extra weight since it was unlucky. - assert_eq!(Elections::present_winner(Origin::signed(3), 2, 300, 2), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400 + Elections::get_offset(400, 1), 2), Ok(())); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(4, 27), (2, 27)]); - }) - } - - #[test] - fn resubmitting_approvals_stores_pot() { - with_externalities(&mut ExtBuilder::default() - .voter_bond(0) - .voting_fee(0) - .balance_factor(10) - .build(), - || { System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); - - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 1)); - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 2)); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - - System::set_block_number(12); - assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); - assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1)); - // give 1 some new high balance - let _ = Balances::make_free_balance_be(&1, 997); - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![false, false, true], 1, 2)); - assert_eq!(Elections::voter_info(1).unwrap(), - VoterInfo { - stake: 1000, // 997 + 3 which is candidacy bond. - pot: Elections::get_offset(100, 1), - last_active: 1, - last_win: 1, - } - ); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); - - System::set_block_number(14); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(1), 1, 1000 + 96 /* pot */, 1), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (500, 5), (600, 6), (1096, 1)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(1, 19), (6, 19)]); - }) - } - - #[test] - fn get_offset_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_eq!(Elections::get_offset(100, 0), 0); - assert_eq!(Elections::get_offset(100, 1), 96); - assert_eq!(Elections::get_offset(100, 2), 96 + 93); - assert_eq!(Elections::get_offset(100, 3), 96 + 93 + 90); - assert_eq!(Elections::get_offset(100, 4), 96 + 93 + 90 + 87); - // limit - assert_eq!(Elections::get_offset(100, 1000), 100 * 24); - - assert_eq!(Elections::get_offset(50_000_000_000, 0), 0); - assert_eq!(Elections::get_offset(50_000_000_000, 1), 48_000_000_000); - assert_eq!(Elections::get_offset(50_000_000_000, 2), 48_000_000_000 + 46_080_000_000); - assert_eq!(Elections::get_offset(50_000_000_000, 3), 48_000_000_000 + 46_080_000_000 + 44_236_800_000); - assert_eq!( - Elections::get_offset(50_000_000_000, 4), - 48_000_000_000 + 46_080_000_000 + 44_236_800_000 + 42_467_328_000 - ); - // limit - assert_eq!(Elections::get_offset(50_000_000_000, 1000), 50_000_000_000 * 24); - }) - } - - #[test] - fn get_offset_with_zero_decay() { - with_externalities(&mut ExtBuilder::default().decay_ratio(0).build(), || { - assert_eq!(Elections::get_offset(100, 0), 0); - assert_eq!(Elections::get_offset(100, 1), 0); - assert_eq!(Elections::get_offset(100, 2), 0); - assert_eq!(Elections::get_offset(100, 3), 0); - // limit - assert_eq!(Elections::get_offset(100, 1000), 0); - }) - } - - #[test] - fn voting_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(voter_ids(), vec![1, 4]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true, true], 0, 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, true], 0, 3)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); - - assert_eq!(voter_ids(), vec![1, 4, 2, 3]); - }); - } - - #[test] - fn proxy_voting_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - - >::insert(11, 1); - >::insert(12, 2); - >::insert(13, 3); - >::insert(14, 4); - assert_ok!(Elections::proxy_set_approvals(Origin::signed(11), vec![true], 0, 0)); - assert_ok!(Elections::proxy_set_approvals(Origin::signed(14), vec![true], 0, 1)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(voter_ids(), vec![1, 4]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - - assert_ok!(Elections::proxy_set_approvals(Origin::signed(12), vec![false, true, true], 0, 2)); - assert_ok!(Elections::proxy_set_approvals(Origin::signed(13), vec![false, true, true], 0, 3)); - - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); - - assert_eq!(voter_ids(), vec![1, 4, 2, 3]); - }); - } - - #[test] - fn setting_any_approval_vote_count_without_any_candidate_count_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - - assert_eq!(Elections::candidates().len(), 0); - - assert_noop!( - Elections::set_approvals(Origin::signed(4), vec![], 0, 0), - "amount of candidates to receive approval votes should be non-zero" - ); - }); - } - - #[test] - fn setting_an_approval_vote_count_more_than_candidate_count_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_eq!(Elections::candidates().len(), 1); - - assert_noop!( - Elections::set_approvals(Origin::signed(4),vec![true, true], 0, 0), - "amount of candidate votes cannot exceed amount of candidates" - ); - }); - } - - #[test] - fn resubmitting_voting_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 0)); - - assert_eq!(Elections::all_approvals_of(&4), vec![true]); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_eq!(Elections::candidates().len(), 3); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true, false, true], 0, 0)); - - assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); - }); - } - - #[test] - fn retracting_voter_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_eq!(Elections::candidates().len(), 3); - - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true, true], 0, 1)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, true], 0, 2)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true, false, true], 0, 3)); - - assert_eq!(voter_ids(), vec![1, 2, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), vec![true]); - assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); - - assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); - - assert_eq!(voter_ids(), vec![0, 2, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); - - assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); - - assert_eq!(voter_ids(), vec![0, 0, 3, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); - assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); - - assert_ok!(Elections::retract_voter(Origin::signed(3), 2)); - - assert_eq!(voter_ids(), vec![0, 0, 0, 4]); - assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&3), Vec::::new()); - assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); - }); - } - - #[test] - fn invalid_retraction_index_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_eq!(voter_ids(), vec![1, 2]); - assert_noop!(Elections::retract_voter(Origin::signed(1), 1), "retraction index mismatch"); - }); - } - - #[test] - fn overflow_retraction_index_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0)); - assert_noop!(Elections::retract_voter(Origin::signed(1), 1), "retraction index invalid"); - }); - } - - #[test] - fn non_voter_retraction_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(1); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0)); - assert_noop!(Elections::retract_voter(Origin::signed(2), 0), "cannot retract non-voter"); - }); - } - - #[test] - fn approval_storage_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 0)); - - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - // NOTE: these two are stored in mem differently though. - assert_eq!(Elections::all_approvals_of(&3), vec![]); - assert_eq!(Elections::all_approvals_of(&4), vec![]); - - assert_eq!(Elections::approvals_of((3, 0)), vec![0]); - assert_eq!(Elections::approvals_of((4, 0)), vec![]); - }); - } - - #[test] - fn simple_tally_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0)); - assert_eq!(voter_ids(), vec![2, 5]); - assert_eq!(Elections::all_approvals_of(&2), vec![true]); - assert_eq!(Elections::all_approvals_of(&5), vec![false, true]); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - - assert!(!Elections::is_a_candidate(&2)); - assert!(!Elections::is_a_candidate(&5)); - assert_eq!(Elections::vote_index(), 1); - assert_eq!(Elections::voter_info(2), Some(VoterInfo { last_win: 1, last_active: 0, stake: 20, pot: 0 })); - assert_eq!(Elections::voter_info(5), Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 })); - }); - } - - #[test] - fn seats_should_be_released() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); - assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - let mut current = System::block_number(); - let free_block; - loop { - current += 1; - System::set_block_number(current); - assert_ok!(Elections::end_block(System::block_number())); - if Elections::members().len() == 0 { - free_block = current; - break; - } - } - // 11 + 2 which is the next voting period. - assert_eq!(free_block, 14); - }); - } - - #[test] - fn presentations_with_zero_staked_deposit_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 0, 0), - "stake deposited to present winner and be added to leaderboard should be non-zero" - ); - }); - } - - #[test] - fn double_presentations_should_be_punished() { - with_externalities(&mut ExtBuilder::default().build(), || { - assert!(Balances::can_slash(&4, 10)); - - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Err("duplicate presentation")); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); - assert_eq!(Balances::total_balance(&4), 38); - }); - } - - #[test] - fn retracting_inactive_voter_should_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), - (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![0, 5]); - assert_eq!(Elections::all_approvals_of(&2).len(), 0); - assert_eq!(Balances::total_balance(&2), 20); - assert_eq!(Balances::total_balance(&5), 50); - }); - } - - #[test] - fn presenting_for_double_election_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - // NOTE: This is now mandatory to disable the lock - assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); - assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 1, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_noop!( - Elections::present_winner(Origin::signed(4), 2, 20, 1), - "candidate must not form a duplicated member if elected" - ); - }); - } - - #[test] - fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { - with_externalities(&mut ExtBuilder::default().voter_bond(2).build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(11); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - - assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), - (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![0, 5]); - assert_eq!(Elections::all_approvals_of(&2).len(), 0); - assert_eq!(Balances::total_balance(&2), 18); - assert_eq!(Balances::total_balance(&5), 52); - }); - } - - #[test] - fn retracting_inactive_voter_with_bad_reporter_index_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), - 42, - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - ), "invalid reporter index"); - }); - } - - #[test] - fn retracting_inactive_voter_with_bad_target_index_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2, 42, - 2 - ), "invalid target index"); - }); - } - - #[test] - fn attempting_to_retract_active_voter_should_slash_reporter() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 2)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false, false, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, false, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, true, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20 + Elections::get_offset(20, 1), 1)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1), 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_eq!(Elections::vote_index(), 2); - assert_eq!(::InactiveGracePeriod::get(), 1); - assert_eq!(::VotingPeriod::get(), 4); - assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 1, last_active: 0, stake: 40, pot: 0 })); - - assert_ok!(Elections::reap_inactive_voter(Origin::signed(4), - (voter_ids().iter().position(|&i| i == 4).unwrap() as u32).into(), - 2, - (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - )); - - assert_eq!(voter_ids(), vec![2, 3, 0, 5]); - assert_eq!(Elections::all_approvals_of(&4).len(), 0); - assert_eq!(Balances::total_balance(&4), 40); - }); - } - - #[test] - fn attempting_to_retract_inactive_voter_by_nonvoter_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert_noop!(Elections::reap_inactive_voter(Origin::signed(4), - 0, - 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), - 2 - ), "reporter must be a voter"); - }); - } - - #[test] - fn presenting_loser_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - - assert_eq!(Elections::leaderboard(), Some(vec![ - (30, 3), - (40, 4), - (50, 5), - (60, 1) - ])); - - assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 0), "candidate not worthy of leaderboard"); - }); - } - - #[test] - fn presenting_loser_first_should_not_matter() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - - assert_eq!(Elections::leaderboard(), Some(vec![ - (30, 3), - (40, 4), - (50, 5), - (60, 1) - ])); - }); - } - - #[test] - fn present_outside_of_presentation_period_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - assert_noop!( - Elections::present_winner(Origin::signed(5), 5, 1, 0), - "cannot present outside of presentation period" - ); - }); - } - - #[test] - fn present_with_invalid_vote_index_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 1), "index not current"); - }); - } - - #[test] - fn present_when_presenter_is_poor_should_not_work() { - let test_present = |p| { - with_externalities(&mut ExtBuilder::default() - .voting_fee(5) - .voter_bond(2) - .bad_presentation_punishment(p) - .build(), - || { - System::set_block_number(4); - let _ = Balances::make_free_balance_be(&1, 15); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); // -3 - assert_eq!(Balances::free_balance(&1), 12); - assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0)); // -2 -5 - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_eq!(Balances::free_balance(&1), 5); - assert_eq!(Balances::reserved_balance(&1), 5); - if p > 5 { - assert_noop!(Elections::present_winner( - Origin::signed(1), 1, 10, 0), - "presenter must have sufficient slashable funds" - ); - } else { - assert_ok!(Elections::present_winner(Origin::signed(1), 1, 10, 0)); - } - }); - }; - test_present(4); - test_present(6); - } - - #[test] - fn invalid_present_tally_should_slash() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - assert_eq!(Balances::total_balance(&4), 40); - - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_err!(Elections::present_winner(Origin::signed(4), 2, 80, 0), "incorrect total"); - - assert_eq!(Balances::total_balance(&4), 38); - }); - } - - #[test] - fn runners_up_should_be_kept() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert!(!Elections::presentation_active()); - - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0)); - - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert!(Elections::presentation_active()); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - // leaderboard length is the empty seats plus the carry count (i.e. 5 + 2), where those - // to be carried are the lowest and stored in lowest indices - assert_eq!(Elections::leaderboard(), Some(vec![ - (0, 0), - (0, 0), - (0, 0), - (60, 1) - ])); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_eq!(Elections::leaderboard(), Some(vec![ - (30, 3), - (40, 4), - (50, 5), - (60, 1) - ])); - - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11), (5, 11)]); - - assert!(!Elections::is_a_candidate(&1)); - assert!(!Elections::is_a_candidate(&5)); - assert!(!Elections::is_a_candidate(&2)); - assert!(Elections::is_a_candidate(&3)); - assert!(Elections::is_a_candidate(&4)); - assert_eq!(Elections::vote_index(), 1); - assert_eq!(Elections::voter_info(2), Some(VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0 })); - assert_eq!(Elections::voter_info(3), Some(VoterInfo { last_win: 0, last_active: 0, stake: 30, pot: 0 })); - assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0 })); - assert_eq!(Elections::voter_info(5), Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 })); - assert_eq!(Elections::voter_info(6), Some(VoterInfo { last_win: 1, last_active: 0, stake: 60, pot: 0 })); - assert_eq!(Elections::candidate_reg_info(3), Some((0, 2))); - assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); - }); - } - - #[test] - fn second_tally_should_use_runners_up() { - with_externalities(&mut ExtBuilder::default().build(), || { - System::set_block_number(4); - assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); - assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); - assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); - assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0)); - assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); - assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(6); - assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); - assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(8); - assert_ok!(Elections::set_approvals(Origin::signed(6), vec![false, false, true, false], 1, 0)); - assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); - assert_ok!(Elections::end_block(System::block_number())); - - System::set_block_number(10); - assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1) + 60, 1)); - assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40 + Elections::get_offset(40, 1), 1)); - assert_ok!(Elections::end_block(System::block_number())); - - assert!(!Elections::presentation_active()); - assert_eq!(Elections::members(), vec![(1, 11), (5, 11), (3, 15)]); - - assert!(!Elections::is_a_candidate(&1)); - assert!(!Elections::is_a_candidate(&2)); - assert!(!Elections::is_a_candidate(&3)); - assert!(!Elections::is_a_candidate(&5)); - assert!(Elections::is_a_candidate(&4)); - assert_eq!(Elections::vote_index(), 2); - assert_eq!(Elections::voter_info(2), Some( VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0})); - assert_eq!(Elections::voter_info(3), Some( VoterInfo { last_win: 2, last_active: 0, stake: 30, pot: 0})); - assert_eq!(Elections::voter_info(4), Some( VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0})); - assert_eq!(Elections::voter_info(5), Some( VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0})); - assert_eq!( - Elections::voter_info(6), - Some(VoterInfo { last_win: 2, last_active: 1, stake: 60, pot: 0}) - ); - - assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); - }); - } -} diff --git a/srml/elections/src/mock.rs b/srml/elections/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..77b13d74a139f42d7aab7ad6a76741cdd70c8342 --- /dev/null +++ b/srml/elections/src/mock.rs @@ -0,0 +1,284 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Mock file for election module. + +#![cfg(test)] + +use std::cell::RefCell; +use support::{ + StorageValue, StorageMap, parameter_types, assert_ok, + traits::{Get, ChangeMembers, Currency} +}; +use primitives::H256; +use sr_primitives::{ + Perbill, BuildStorage, testing::Header, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, +}; +use crate as elections; + + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); +} + +parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; +} +impl balances::Trait for Test { + type Balance = u64; + type OnNewAccount = (); + type OnFreeBalanceZero = (); + type Event = Event; + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +parameter_types! { + pub const CandidacyBond: u64 = 3; + pub const CarryCount: u32 = 2; + pub const InactiveGracePeriod: u32 = 1; + pub const VotingPeriod: u64 = 4; + pub const MinimumVotingLock: u64 = 5; +} + +thread_local! { + static VOTER_BOND: RefCell = RefCell::new(0); + static VOTING_FEE: RefCell = RefCell::new(0); + static PRESENT_SLASH_PER_VOTER: RefCell = RefCell::new(0); + static DECAY_RATIO: RefCell = RefCell::new(0); + static MEMBERS: RefCell> = RefCell::new(vec![]); +} + +pub struct VotingBond; +impl Get for VotingBond { + fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) } +} + +pub struct VotingFee; +impl Get for VotingFee { + fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) } +} + +pub struct PresentSlashPerVoter; +impl Get for PresentSlashPerVoter { + fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) } +} + +pub struct DecayRatio; +impl Get for DecayRatio { + fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) } +} + +pub struct TestChangeMembers; +impl ChangeMembers for TestChangeMembers { + fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { + let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); + old_plus_incoming.extend_from_slice(incoming); + old_plus_incoming.sort(); + let mut new_plus_outgoing = new.to_vec(); + new_plus_outgoing.extend_from_slice(outgoing); + new_plus_outgoing.sort(); + assert_eq!(old_plus_incoming, new_plus_outgoing); + + MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); + } +} + +impl elections::Trait for Test { + type Event = Event; + type Currency = Balances; + type BadPresentation = (); + type BadReaper = (); + type BadVoterIndex = (); + type LoserCandidate = (); + type ChangeMembers = TestChangeMembers; + type CandidacyBond = CandidacyBond; + type VotingBond = VotingBond; + type VotingFee = VotingFee; + type MinimumVotingLock = MinimumVotingLock; + type PresentSlashPerVoter = PresentSlashPerVoter; + type CarryCount = CarryCount; + type InactiveGracePeriod = InactiveGracePeriod; + type VotingPeriod = VotingPeriod; + type DecayRatio = DecayRatio; +} + +pub type Block = sr_primitives::generic::Block; +pub type UncheckedExtrinsic = sr_primitives::generic::UncheckedExtrinsic; + +support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: system::{Module, Call, Event}, + Balances: balances::{Module, Call, Event, Config, Error}, + Elections: elections::{Module, Call, Event, Config}, + } +); + +pub struct ExtBuilder { + balance_factor: u64, + decay_ratio: u32, + desired_seats: u32, + voting_fee: u64, + voter_bond: u64, + bad_presentation_punishment: u64, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + balance_factor: 1, + decay_ratio: 24, + desired_seats: 2, + voting_fee: 0, + voter_bond: 0, + bad_presentation_punishment: 1, + } + } +} + +impl ExtBuilder { + pub fn balance_factor(mut self, factor: u64) -> Self { + self.balance_factor = factor; + self + } + pub fn decay_ratio(mut self, ratio: u32) -> Self { + self.decay_ratio = ratio; + self + } + pub fn voting_fee(mut self, fee: u64) -> Self { + self.voting_fee = fee; + self + } + pub fn bad_presentation_punishment(mut self, fee: u64) -> Self { + self.bad_presentation_punishment = fee; + self + } + pub fn voter_bond(mut self, fee: u64) -> Self { + self.voter_bond = fee; + self + } + pub fn desired_seats(mut self, seats: u32) -> Self { + self.desired_seats = seats; + self + } + pub fn build(self) -> runtime_io::TestExternalities { + VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond); + VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee); + PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment); + DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio); + GenesisConfig { + balances: Some(balances::GenesisConfig::{ + balances: vec![ + (1, 10 * self.balance_factor), + (2, 20 * self.balance_factor), + (3, 30 * self.balance_factor), + (4, 40 * self.balance_factor), + (5, 50 * self.balance_factor), + (6, 60 * self.balance_factor) + ], + vesting: vec![], + }), + elections: Some(elections::GenesisConfig::{ + members: vec![], + desired_seats: self.desired_seats, + presentation_duration: 2, + term_duration: 5, + }), + }.build_storage().unwrap().into() + } +} + +pub(crate) fn voter_ids() -> Vec { + Elections::all_voters().iter().map(|v| v.unwrap_or(0) ).collect::>() +} + +pub(crate) fn vote(i: u64, l: usize) { + let _ = Balances::make_free_balance_be(&i, 20); + assert_ok!( + Elections::set_approvals( + Origin::signed(i), + (0..l).map(|_| true).collect::>(), + 0, + 0, + 20, + ) + ); +} + +pub(crate) fn vote_at(i: u64, l: usize, index: elections::VoteIndex) { + let _ = Balances::make_free_balance_be(&i, 20); + assert_ok!( + Elections::set_approvals( + Origin::signed(i), + (0..l).map(|_| true).collect::>(), + 0, + index, + 20, + ) + ); +} + +pub(crate) fn create_candidate(i: u64, index: u32) { + let _ = Balances::make_free_balance_be(&i, 20); + assert_ok!(Elections::submit_candidacy(Origin::signed(i), index)); +} + +pub(crate) fn balances(who: &u64) -> (u64, u64) { + (Balances::free_balance(who), Balances::reserved_balance(who)) +} + +pub(crate) fn locks(who: &u64) -> Vec { + Balances::locks(who).iter().map(|l| l.amount).collect::>() +} + +pub(crate) fn new_test_ext_with_candidate_holes() -> runtime_io::TestExternalities { + let mut t = ExtBuilder::default().build(); + t.execute_with(|| { + >::put(vec![0, 0, 1]); + elections::CandidateCount::put(1); + >::insert(1, (0, 2)); + }); + t +} diff --git a/srml/elections/src/tests.rs b/srml/elections/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..c9bb054ab23538edf62dfbcfb67b648f278c7a96 --- /dev/null +++ b/srml/elections/src/tests.rs @@ -0,0 +1,1681 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for election module. + +#![cfg(test)] + +use crate::mock::*; +use crate::*; + +use support::{assert_ok, assert_err, assert_noop}; + +#[test] +fn params_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::next_vote_from(1), 4); + assert_eq!(Elections::next_vote_from(4), 4); + assert_eq!(Elections::next_vote_from(5), 8); + assert_eq!(Elections::vote_index(), 0); + assert_eq!(Elections::presentation_duration(), 2); + assert_eq!(Elections::term_duration(), 5); + assert_eq!(Elections::desired_seats(), 2); + + assert_eq!(Elections::members(), vec![]); + assert_eq!(Elections::next_tally(), Some(4)); + assert_eq!(Elections::presentation_active(), false); + assert_eq!(Elections::next_finalize(), None); + + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(Elections::is_a_candidate(&1), false); + assert_eq!(Elections::candidate_reg_info(1), None); + + assert_eq!(Elections::voters(0), Vec::>::new()); + assert_eq!(Elections::voter_info(1), None); + assert_eq!(Elections::all_approvals_of(&1), vec![]); + }); +} + +#[test] +fn chunking_bool_to_flag_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::bool_to_flag(vec![]), vec![]); + assert_eq!(Elections::bool_to_flag(vec![false]), vec![0]); + assert_eq!(Elections::bool_to_flag(vec![true]), vec![1]); + assert_eq!(Elections::bool_to_flag(vec![true, true, true, true]), vec![15]); + assert_eq!(Elections::bool_to_flag(vec![true, true, true, true, true]), vec![15 + 16]); + + let set_1 = vec![ + true, false, false, false, // 0x1 + false, true, true, true, // 0xE + ]; + assert_eq!( + Elections::bool_to_flag(set_1.clone()), + vec![0x00_00_00_E1_u32] + ); + assert_eq!( + Elections::flag_to_bool(vec![0x00_00_00_E1_u32]), + set_1 + ); + + let set_2 = vec![ + false, false, false, true, // 0x8 + false, true, false, true, // 0xA + ]; + assert_eq!( + Elections::bool_to_flag(set_2.clone()), + vec![0x00_00_00_A8_u32] + ); + assert_eq!( + Elections::flag_to_bool(vec![0x00_00_00_A8_u32]), + set_2 + ); + + let mut rhs = (0..100/APPROVAL_FLAG_LEN).map(|_| 0xFFFFFFFF_u32).collect::>(); + // NOTE: this might be need change based on `APPROVAL_FLAG_LEN`. + rhs.extend(vec![0x00_00_00_0F]); + assert_eq!( + Elections::bool_to_flag((0..100).map(|_| true).collect()), + rhs + ) + }) +} + +#[test] +fn chunking_voter_set_growth_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + // create 65. 64 (set0) + 1 (set1) + (1..=63).for_each(|i| vote(i, 0)); + assert_eq!(Elections::next_nonfull_voter_set(), 0); + vote(64, 0); + assert_eq!(Elections::next_nonfull_voter_set(), 1); + vote(65, 0); + + let set1 = Elections::voters(0); + let set2 = Elections::voters(1); + + assert_eq!(set1.len(), 64); + assert_eq!(set2.len(), 1); + + assert_eq!(set1[0], Some(1)); + assert_eq!(set1[10], Some(11)); + assert_eq!(set2[0], Some(65)); + }) +} + +#[test] +fn chunking_voter_set_reclaim_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + (1..=129).for_each(|i| vote(i, 0)); + assert_eq!(Elections::next_nonfull_voter_set(), 2); + + assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); + + assert_ok!(Elections::retract_voter(Origin::signed(66), 65)); + assert_ok!(Elections::retract_voter(Origin::signed(67), 66)); + + // length does not show it but holes do exist. + assert_eq!(Elections::voters(0).len(), 64); + assert_eq!(Elections::voters(1).len(), 64); + assert_eq!(Elections::voters(2).len(), 1); + + assert_eq!(Elections::voters(0)[10], None); + assert_eq!(Elections::voters(1)[1], None); + assert_eq!(Elections::voters(1)[2], None); + // Next set with capacity is 2. + assert_eq!(Elections::next_nonfull_voter_set(), 2); + + // But we can fill a hole. + vote_at(130, 0, 10); + + // Nothing added to set 2. A hole was filled. + assert_eq!(Elections::voters(0).len(), 64); + assert_eq!(Elections::voters(1).len(), 64); + assert_eq!(Elections::voters(2).len(), 1); + + // and the next two (scheduled) to the second set. + assert_eq!(Elections::next_nonfull_voter_set(), 2); + }) +} + +#[test] +fn chunking_approvals_set_growth_should_work() { + ExtBuilder::default().build().execute_with(|| { + // create candidates and voters. + (1..=250).for_each(|i| create_candidate(i, (i-1) as u32)); + (1..=250).for_each(|i| vote(i, i as usize)); + + // all approvals of should return the exact expected vector. + assert_eq!( + Elections::all_approvals_of(&180), + (0..180).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&32), + (0..32).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&8), + (0..8).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&64), + (0..64).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&65), + (0..65).map(|_| true).collect::>() + ); + assert_eq!( + Elections::all_approvals_of(&63), + (0..63).map(|_| true).collect::>() + ); + + // NOTE: assuming that APPROVAL_SET_SIZE is more or less small-ish. Might fail otherwise. + let full_sets = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; + let left_over = (180 / APPROVAL_FLAG_LEN) / APPROVAL_SET_SIZE; + let rem = 180 % APPROVAL_FLAG_LEN; + + // grab and check the last full set, if it exists. + if full_sets > 0 { + assert_eq!( + Elections::approvals_of((180, (full_sets-1) as SetIndex )), + Elections::bool_to_flag( + (0..APPROVAL_SET_SIZE * APPROVAL_FLAG_LEN) + .map(|_| true).collect::>() + ) + ); + } + + // grab and check the last, half-empty, set. + if left_over > 0 { + assert_eq!( + Elections::approvals_of((180, full_sets as SetIndex)), + Elections::bool_to_flag( + (0..left_over * APPROVAL_FLAG_LEN + rem) + .map(|_| true).collect::>() + ) + ); + } + }) +} + +#[test] +fn chunking_cell_status_works() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + (1..=63).for_each(|i| vote(i, 0)); + + assert_ok!(Elections::retract_voter(Origin::signed(11), 10)); + assert_ok!(Elections::retract_voter(Origin::signed(21), 20)); + + assert_eq!(Elections::cell_status(0, 10), CellStatus::Hole); + assert_eq!(Elections::cell_status(0, 0), CellStatus::Occupied); + assert_eq!(Elections::cell_status(0, 20), CellStatus::Hole); + assert_eq!(Elections::cell_status(0, 63), CellStatus::Head); + assert_eq!(Elections::cell_status(1, 0), CellStatus::Head); + assert_eq!(Elections::cell_status(1, 10), CellStatus::Head); + }) +} + +#[test] +fn chunking_voter_index_does_not_take_holes_into_account() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + // create 65. 64 (set0) + 1 (set1) + (1..=65).for_each(|i| vote(i, 0)); + + // account 65 has global index 65. + assert_eq!(Elections::voter_at(64).unwrap(), 65); + + assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); + + // still the same. These holes are in some other set. + assert_eq!(Elections::voter_at(64).unwrap(), 65); + // proof: can submit a new approval with the old index. + assert_noop!( + Elections::set_approvals(Origin::signed(65), vec![], 0, 64 - 2, 10), + "wrong voter index" + ); + assert_ok!(Elections::set_approvals(Origin::signed(65), vec![], 0, 64, 10)); + }) +} + +#[test] +fn chunking_approval_storage_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); + + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40)); + + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + // NOTE: these two are stored in mem differently though. + assert_eq!(Elections::all_approvals_of(&3), vec![]); + assert_eq!(Elections::all_approvals_of(&4), vec![]); + + assert_eq!(Elections::approvals_of((3, 0)), vec![0]); + assert_eq!(Elections::approvals_of((4, 0)), vec![]); + }); +} + +#[test] +fn voting_initial_set_approvals_ignores_voter_index() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + // Last argument is essentially irrelevant. You might get or miss a tip. + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); + + // indices are more or less ignored. all is pushed. + assert_eq!(voter_ids(), vec![3, 4, 5]); + }) +} +#[test] +fn voting_bad_approval_index_slashes_voters_and_bond_reduces_stake() { + ExtBuilder::default().voting_fee(5).voter_bond(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + (1..=63).for_each(|i| vote(i, 0)); + assert_eq!(balances(&1), (13, 2)); + assert_eq!(balances(&10), (18, 2)); + assert_eq!(balances(&60), (18, 2)); + + // still no fee + vote(64, 0); + assert_eq!(balances(&64), (18, 2)); + assert_eq!( + Elections::voter_info(&64).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 20, pot:0 } + ); + + assert_eq!(Elections::next_nonfull_voter_set(), 1); + + // now we charge the next voter. + vote(65, 0); + assert_eq!(balances(&65), (13, 2)); + assert_eq!( + Elections::voter_info(&65).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 15, pot:0 } + ); + }); +} + +#[test] +fn voting_subsequent_set_approvals_checks_voter_index() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![], 0, 5, 40)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![], 0, 100, 50)); + + // invalid index + assert_noop!( + Elections::set_approvals(Origin::signed(4), vec![true], 0, 5, 40), + "invalid voter index" + ); + // wrong index + assert_noop!( + Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40), + "wrong voter index" + ); + // correct + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); + }) +} + +#[test] +fn voting_cannot_lock_less_than_limit() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + assert_noop!( + Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 4), + "locked value must be more than limit", + ); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 5)); + }); +} + +#[test] +fn voting_locking_more_than_total_balance_is_moot() { + ExtBuilder::default().voter_bond(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + + assert_eq!(balances(&3), (30, 0)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![], 0, 0, 35)); + + assert_eq!(balances(&3), (28, 2)); + assert_eq!( + Elections::voter_info(&3).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 30, pot:0 } + ); + }); +} + +#[test] +fn voting_locking_stake_and_reserving_bond_works() { + ExtBuilder::default().voter_bond(2).build().execute_with(|| { + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + + assert_eq!(balances(&2), (20, 0)); + assert_eq!(locks(&2), vec![]); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![], 0, 0, 15)); + assert_eq!(balances(&2), (18, 2)); + assert_eq!(locks(&2), vec![15]); + + // deposit a bit more. + let _ = Balances::make_free_balance_be(&2, 100); + + // change vote + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 70)); + assert_eq!(balances(&2), (100, 2)); + assert_eq!(locks(&2), vec![70]); + + assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); + + assert_eq!(balances(&2), (102, 0)); + assert_eq!(locks(&2), vec![]); + }); +} + +#[test] +fn voting_without_any_candidate_count_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_eq!(Elections::candidates().len(), 0); + + assert_noop!( + Elections::set_approvals(Origin::signed(4), vec![], 0, 0, 40), + "amount of candidates to receive approval votes should be non-zero" + ); + }); +} + +#[test] +fn voting_setting_an_approval_vote_count_more_than_candidate_count_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_eq!(Elections::candidates().len(), 1); + + assert_noop!( + Elections::set_approvals(Origin::signed(4),vec![true, true], 0, 0, 40), + "amount of candidate votes cannot exceed amount of candidates" + ); + }); +} + +#[test] +fn voting_resubmitting_approvals_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 0, 40)); + + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_eq!(Elections::candidates().len(), 3); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true, false, true], 0, 0, 40)); + + assert_eq!(Elections::all_approvals_of(&4), vec![true, false, true]); + }); +} + +#[test] +fn voting_retracting_voter_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_eq!(Elections::candidates().len(), 1); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 1, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![true], 0, 2, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 3, 40)); + + assert_eq!(voter_ids(), vec![1, 2, 3, 4]); + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + assert_eq!(Elections::all_approvals_of(&3), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::retract_voter(Origin::signed(1), 0)); + + assert_eq!(voter_ids(), vec![0, 2, 3, 4]); + assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + assert_eq!(Elections::all_approvals_of(&3), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::retract_voter(Origin::signed(2), 1)); + + assert_eq!(voter_ids(), vec![0, 0, 3, 4]); + assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&3), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + + assert_ok!(Elections::retract_voter(Origin::signed(3), 2)); + + assert_eq!(voter_ids(), vec![0, 0, 0, 4]); + assert_eq!(Elections::all_approvals_of(&1), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&2), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&3), Vec::::new()); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + }); +} + +#[test] +fn voting_invalid_retraction_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_eq!(voter_ids(), vec![1, 2]); + assert_noop!(Elections::retract_voter(Origin::signed(1), 1), "retraction index mismatch"); + }); +} + +#[test] +fn voting_overflow_retraction_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_noop!(Elections::retract_voter(Origin::signed(1), 1), "retraction index invalid"); + }); +} + +#[test] +fn voting_non_voter_retraction_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_noop!(Elections::retract_voter(Origin::signed(2), 0), "cannot retract non-voter"); + }); +} + +#[test] +fn retracting_inactive_voter_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), + (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + )); + + assert_eq!(voter_ids(), vec![0, 5]); + assert_eq!(Elections::all_approvals_of(&2).len(), 0); + assert_eq!(Balances::total_balance(&2), 20); + assert_eq!(Balances::total_balance(&5), 50); + }); +} + +#[test] +fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() { + ExtBuilder::default().voter_bond(2).build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(11); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + + assert_ok!(Elections::reap_inactive_voter(Origin::signed(5), + (voter_ids().iter().position(|&i| i == 5).unwrap() as u32).into(), + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + )); + + assert_eq!(voter_ids(), vec![0, 5]); + assert_eq!(Elections::all_approvals_of(&2).len(), 0); + }); +} + +#[test] +fn retracting_inactive_voter_with_bad_reporter_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), + 42, + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + ), "invalid reporter index"); + }); +} + +#[test] +fn retracting_inactive_voter_with_bad_target_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_noop!(Elections::reap_inactive_voter(Origin::signed(2), + (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2, 42, + 2 + ), "invalid target index"); + }); +} + +#[test] +fn retracting_active_voter_should_slash_reporter() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 2)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false, false, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, false, false], 0, 0, 30)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, true, false], 0, 0, 40)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20 + Elections::get_offset(20, 1), 1)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1), 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::vote_index(), 2); + assert_eq!(::InactiveGracePeriod::get(), 1); + assert_eq!(::VotingPeriod::get(), 4); + assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 1, last_active: 0, stake: 40, pot: 0 })); + + assert_ok!(Elections::reap_inactive_voter(Origin::signed(4), + (voter_ids().iter().position(|&i| i == 4).unwrap() as u32).into(), + 2, + (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + )); + + assert_eq!(voter_ids(), vec![2, 3, 0, 5]); + assert_eq!(Elections::all_approvals_of(&4).len(), 0); + assert_eq!(Balances::total_balance(&4), 40); + }); +} + +#[test] +fn retracting_inactive_voter_by_nonvoter_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 1, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert_noop!(Elections::reap_inactive_voter(Origin::signed(4), + 0, + 2, (voter_ids().iter().position(|&i| i == 2).unwrap() as u32).into(), + 2 + ), "reporter must be a voter"); + }); +} + +#[test] +fn candidacy_simple_candidate_submission_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_eq!(Elections::candidate_reg_info(1), None); + assert_eq!(Elections::candidate_reg_info(2), None); + assert_eq!(Elections::is_a_candidate(&1), false); + assert_eq!(Elections::is_a_candidate(&2), false); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Elections::candidates(), vec![1]); + assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); + assert_eq!(Elections::candidate_reg_info(2), None); + assert_eq!(Elections::is_a_candidate(&1), true); + assert_eq!(Elections::is_a_candidate(&2), false); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_eq!(Elections::candidates(), vec![1, 2]); + assert_eq!(Elections::candidate_reg_info(1), Some((0, 0))); + assert_eq!(Elections::candidate_reg_info(2), Some((0, 1))); + assert_eq!(Elections::is_a_candidate(&1), true); + assert_eq!(Elections::is_a_candidate(&2), true); + }); +} + +#[test] +fn candidacy_submission_using_free_slot_should_work() { + let mut t = new_test_ext_with_candidate_holes(); + + t.execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), vec![0, 0, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_eq!(Elections::candidates(), vec![0, 2, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 0)); + assert_eq!(Elections::candidates(), vec![3, 2, 1]); + }); +} + +#[test] +fn candidacy_submission_using_alternative_free_slot_should_work() { + let mut t = new_test_ext_with_candidate_holes(); + + t.execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), vec![0, 0, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_eq!(Elections::candidates(), vec![2, 0, 1]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 1)); + assert_eq!(Elections::candidates(), vec![2, 3, 1]); + }); +} + +#[test] +fn candidacy_submission_not_using_free_slot_should_not_work() { + let mut t = new_test_ext_with_candidate_holes(); + + t.execute_with(|| { + System::set_block_number(1); + assert_noop!( + Elections::submit_candidacy(Origin::signed(4), 3), + "invalid candidate slot" + ); + }); +} + +#[test] +fn candidacy_bad_candidate_slot_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_noop!( + Elections::submit_candidacy(Origin::signed(1), 1), + "invalid candidate slot" + ); + }); +} + +#[test] +fn candidacy_non_free_candidate_slot_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Elections::candidates(), vec![1]); + assert_noop!( + Elections::submit_candidacy(Origin::signed(2), 0), + "invalid candidate slot" + ); + }); +} + +#[test] +fn candidacy_dupe_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Elections::candidates(), vec![1]); + assert_noop!( + Elections::submit_candidacy(Origin::signed(1), 1), + "duplicate candidate submission" + ); + }); +} + +#[test] +fn candidacy_poor_candidate_submission_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + assert_eq!(Elections::candidates(), Vec::::new()); + assert_noop!( + Elections::submit_candidacy(Origin::signed(7), 0), + "candidate has not enough funds" + ); + }); +} + +#[test] +fn election_voting_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 10)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![true], 0, 1, 40)); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(voter_ids(), vec![1, 4]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true, true], 0, 2, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, true, true], 0, 3, 30)); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(Elections::all_approvals_of(&2), vec![false, true, true]); + assert_eq!(Elections::all_approvals_of(&3), vec![false, true, true]); + + assert_eq!(voter_ids(), vec![1, 4, 2, 3]); + }); +} + +#[test] +fn election_proxy_voting_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0)); + + >::insert(11, 1); + >::insert(12, 2); + >::insert(13, 3); + >::insert(14, 4); + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(11), vec![true], 0, 0, 10) + ); + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(14), vec![true], 0, 1, 40) + ); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(voter_ids(), vec![1, 4]); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(12), vec![false, true], 0, 2, 20) + ); + assert_ok!( + Elections::proxy_set_approvals(Origin::signed(13), vec![false, true], 0, 3, 30) + ); + + assert_eq!(Elections::all_approvals_of(&1), vec![true]); + assert_eq!(Elections::all_approvals_of(&4), vec![true]); + assert_eq!(Elections::all_approvals_of(&2), vec![false, true]); + assert_eq!(Elections::all_approvals_of(&3), vec![false, true]); + + assert_eq!(voter_ids(), vec![1, 4, 2, 3]); + }); +} + +#[test] +fn election_simple_tally_should_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_eq!(voter_ids(), vec![2, 5]); + assert_eq!(Elections::all_approvals_of(&2), vec![true]); + assert_eq!(Elections::all_approvals_of(&5), vec![false, true]); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); + + assert!(!Elections::is_a_candidate(&2)); + assert!(!Elections::is_a_candidate(&5)); + assert_eq!(Elections::vote_index(), 1); + assert_eq!( + Elections::voter_info(2), + Some(VoterInfo { last_win: 1, last_active: 0, stake: 20, pot: 0 }) + ); + assert_eq!( + Elections::voter_info(5), + Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 }) + ); + }); +} + +#[test] +fn election_seats_should_be_released() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(4), 2, 20, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (0, 0), (20, 2), (50, 5)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); + let mut current = System::block_number(); + let free_block; + loop { + current += 1; + System::set_block_number(current); + assert_ok!(Elections::end_block(System::block_number())); + if Elections::members().len() == 0 { + free_block = current; + break; + } + } + // 11 + 2 which is the next voting period. + assert_eq!(free_block, 14); + }); +} + +#[test] +fn election_presentations_with_zero_staked_deposit_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_noop!( + Elections::present_winner(Origin::signed(4), 2, 0, 0), + "stake deposited to present winner and be added to leaderboard should be non-zero" + ); + }); +} + +#[test] +fn election_double_presentations_should_be_punished() { + ExtBuilder::default().build().execute_with(|| { + assert!(Balances::can_slash(&4, 10)); + + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_eq!(Elections::present_winner(Origin::signed(4), 5, 50, 0), Err("duplicate presentation")); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(5, 11), (2, 11)]); + assert_eq!(Balances::total_balance(&4), 38); + }); +} + +#[test] +fn election_presenting_for_double_election_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + // NOTE: This is now mandatory to disable the lock + assert_ok!(Elections::retract_voter(Origin::signed(2), 0)); + assert_eq!(Elections::submit_candidacy(Origin::signed(2), 0), Ok(())); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 1, 0, 20)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_noop!( + Elections::present_winner(Origin::signed(4), 2, 20, 1), + "candidate must not form a duplicated member if elected" + ); + }); +} + +#[test] +fn election_presenting_loser_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + + assert_eq!(Elections::leaderboard(), Some(vec![ + (30, 3), + (40, 4), + (50, 5), + (60, 1) + ])); + + assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 0), "candidate not worthy of leaderboard"); + }); +} + +#[test] +fn election_presenting_loser_first_should_not_matter() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 2, 20, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + + assert_eq!(Elections::leaderboard(), Some(vec![ + (30, 3), + (40, 4), + (50, 5), + (60, 1) + ])); + }); +} + +#[test] +fn election_present_outside_of_presentation_period_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + assert_noop!( + Elections::present_winner(Origin::signed(5), 5, 1, 0), + "cannot present outside of presentation period" + ); + }); +} + +#[test] +fn election_present_with_invalid_vote_index_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_noop!(Elections::present_winner(Origin::signed(4), 2, 20, 1), "index not current"); + }); +} + +#[test] +fn election_present_when_presenter_is_poor_should_not_work() { + let test_present = |p| { + ExtBuilder::default() + .voting_fee(5) + .voter_bond(2) + .bad_presentation_punishment(p) + .build() + .execute_with(|| { + System::set_block_number(4); + let _ = Balances::make_free_balance_be(&1, 15); + assert!(!Elections::presentation_active()); + + // -3 + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_eq!(Balances::free_balance(&1), 12); + // -2 -5 + assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 15)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_eq!(Balances::free_balance(&1), 5); + assert_eq!(Balances::reserved_balance(&1), 5); + if p > 5 { + assert_noop!(Elections::present_winner( + Origin::signed(1), 1, 10, 0), + "presenter must have sufficient slashable funds" + ); + } else { + assert_ok!(Elections::present_winner(Origin::signed(1), 1, 10, 0)); + } + }); + }; + test_present(4); + test_present(6); +} + +#[test] +fn election_invalid_present_tally_should_slash() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + assert_eq!(Balances::total_balance(&4), 40); + + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true, false], 0, 0, 20)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_err!(Elections::present_winner(Origin::signed(4), 2, 80, 0), "incorrect total"); + + assert_eq!(Balances::total_balance(&4), 38); + }); +} + +#[test] +fn election_runners_up_should_be_kept() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + // leaderboard length is the empty seats plus the carry count (i.e. 5 + 2), where those + // to be carried are the lowest and stored in lowest indices + assert_eq!(Elections::leaderboard(), Some(vec![ + (0, 0), + (0, 0), + (0, 0), + (60, 1) + ])); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_eq!(Elections::leaderboard(), Some(vec![ + (30, 3), + (40, 4), + (50, 5), + (60, 1) + ])); + + assert_ok!(Elections::end_block(System::block_number())); + + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(1, 11), (5, 11)]); + + assert!(!Elections::is_a_candidate(&1)); + assert!(!Elections::is_a_candidate(&5)); + assert!(!Elections::is_a_candidate(&2)); + assert!(Elections::is_a_candidate(&3)); + assert!(Elections::is_a_candidate(&4)); + assert_eq!(Elections::vote_index(), 1); + assert_eq!(Elections::voter_info(2), Some(VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0 })); + assert_eq!(Elections::voter_info(3), Some(VoterInfo { last_win: 0, last_active: 0, stake: 30, pot: 0 })); + assert_eq!(Elections::voter_info(4), Some(VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0 })); + assert_eq!(Elections::voter_info(5), Some(VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0 })); + assert_eq!(Elections::voter_info(6), Some(VoterInfo { last_win: 1, last_active: 0, stake: 60, pot: 0 })); + assert_eq!(Elections::candidate_reg_info(3), Some((0, 2))); + assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); + }); +} + +#[test] +fn election_second_tally_should_use_runners_up() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(4); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true], 0, 0, 60)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(2), vec![false, true], 0, 0, 20)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true], 0, 0, 30)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, false, false, true], 0, 0, 40)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 4)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, false, false, false, true], 0, 0, 50)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert_ok!(Elections::present_winner(Origin::signed(4), 1, 60, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40, 0)); + assert_ok!(Elections::present_winner(Origin::signed(4), 5, 50, 0)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(8); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![false, false, true, false], 1, 0, 60)); + assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(10); + assert_ok!(Elections::present_winner(Origin::signed(4), 3, 30 + Elections::get_offset(30, 1) + 60, 1)); + assert_ok!(Elections::present_winner(Origin::signed(4), 4, 40 + Elections::get_offset(40, 1), 1)); + assert_ok!(Elections::end_block(System::block_number())); + + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(1, 11), (5, 11), (3, 15)]); + + assert!(!Elections::is_a_candidate(&1)); + assert!(!Elections::is_a_candidate(&2)); + assert!(!Elections::is_a_candidate(&3)); + assert!(!Elections::is_a_candidate(&5)); + assert!(Elections::is_a_candidate(&4)); + assert_eq!(Elections::vote_index(), 2); + assert_eq!(Elections::voter_info(2), Some( VoterInfo { last_win: 0, last_active: 0, stake: 20, pot: 0})); + assert_eq!(Elections::voter_info(3), Some( VoterInfo { last_win: 2, last_active: 0, stake: 30, pot: 0})); + assert_eq!(Elections::voter_info(4), Some( VoterInfo { last_win: 0, last_active: 0, stake: 40, pot: 0})); + assert_eq!(Elections::voter_info(5), Some( VoterInfo { last_win: 1, last_active: 0, stake: 50, pot: 0})); + assert_eq!( + Elections::voter_info(6), + Some(VoterInfo { last_win: 2, last_active: 1, stake: 60, pot: 0}) + ); + + assert_eq!(Elections::candidate_reg_info(4), Some((0, 3))); + }); +} + +#[test] +fn election_loser_candidates_bond_gets_slashed() { + ExtBuilder::default().desired_seats(1).build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 3)); + + assert_eq!(balances(&2), (17, 3)); + + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![true], 0, 0, 50)); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, true, true, true], 0, 0, 10) + ); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 10, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(3), 3, 10, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(2), 2, 10, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 50, 0), Ok(())); + + + // winner + carry + assert_eq!(Elections::leaderboard(), Some(vec![(10, 3), (10, 4), (50, 1)])); + assert_ok!(Elections::end_block(System::block_number())); + assert!(!Elections::presentation_active()); + assert_eq!(Elections::members(), vec![(1, 11)]); + + // account 2 is not a runner up or in leaderboard. + assert_eq!(balances(&2), (17, 0)); + }); +} + +#[test] +fn pot_accumulating_weight_and_decaying_should_work() { + ExtBuilder::default().balance_factor(10).build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); + + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0, 600) + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 0, 500) + ); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 0, 100) + ); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 1, last_active: 0, stake: 600, pot: 0}, + ); + assert_eq!( + Elections::voter_info(5).unwrap(), + VoterInfo { last_win: 1, last_active: 0, stake: 500, pot: 0}, + ); + assert_eq!( + Elections::voter_info(1).unwrap(), + VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}, + ); + + System::set_block_number(12); + // retract needed to unlock approval funds => submit candidacy again. + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0, 600) + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1, 500) + ); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(14); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 1), 1), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 19), (5, 19)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 2, last_active: 1, stake: 600, pot:0 } + ); + assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 2, last_active: 1, stake: 500, pot:0 }); + assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot:0 }); + + System::set_block_number(20); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 2, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 2, 1, 500)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(22); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 2), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 2), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 2), 2), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 27), (5, 27)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 3, last_active: 2, stake: 600, pot: 0} + ); + assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 3, last_active: 2, stake: 500, pot: 0}); + assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); + + + System::set_block_number(28); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false], 3, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(5), vec![false, true, false], 3, 1, 500)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(30); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 3), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 3), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100 + Elections::get_offset(100, 3), 3), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100 + 96 + 93 + 90, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 35), (5, 35)]); + assert_eq!( + Elections::voter_info(6).unwrap(), + VoterInfo { last_win: 4, last_active: 3, stake: 600, pot: 0} + ); + assert_eq!(Elections::voter_info(5).unwrap(), VoterInfo { last_win: 4, last_active: 3, stake: 500, pot: 0}); + assert_eq!(Elections::voter_info(1).unwrap(), VoterInfo { last_win: 0, last_active: 0, stake: 100, pot: 0}); + }) +} + +#[test] +fn pot_winning_resets_accumulated_pot() { + ExtBuilder::default().balance_factor(10).build().execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(3), 2)); + assert_ok!(Elections::submit_candidacy(Origin::signed(2), 3)); + + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 0, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 0, 1, 400)); + assert_ok!(Elections::set_approvals(Origin::signed(3), vec![false, false, true, true], 0, 2, 300)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(300, 2), (300, 3), (400, 4), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (4, 11)]); + + System::set_block_number(12); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(4), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(4), 1)); + assert_ok!(Elections::set_approvals(Origin::signed(6), vec![true, false, false, false], 1, 0, 600)); + assert_ok!(Elections::set_approvals(Origin::signed(4), vec![false, true, false, false], 1, 1, 400)); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(14); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(3), 3, 300 + Elections::get_offset(300, 1), 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(2), 2, 300 + Elections::get_offset(300, 1), 1), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(400, 4), (588, 2), (588, 3), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 19), (3, 19)]); + + System::set_block_number(20); + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(22); + // 2 will not get re-elected with 300 + 288, instead just 300. + // because one of 3's candidates (3) won in previous round + // 4 on the other hand will get extra weight since it was unlucky. + assert_eq!(Elections::present_winner(Origin::signed(3), 2, 300, 2), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(4), 4, 400 + Elections::get_offset(400, 1), 2), Ok(())); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(4, 27), (2, 27)]); + }) +} + +#[test] +fn pot_resubmitting_approvals_stores_pot() { + ExtBuilder::default() + .voter_bond(0) + .voting_fee(0) + .balance_factor(10) + .build() + .execute_with(|| { + System::set_block_number(4); + assert!(!Elections::presentation_active()); + + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(1), 2)); + + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 0, 0, 600), + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 0, 1, 500), + ); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, false, true], 0, 2, 100), + ); + + assert_ok!(Elections::end_block(System::block_number())); + + System::set_block_number(6); + assert!(Elections::presentation_active()); + + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 0), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(1), 1, 100, 0), Ok(())); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (100, 1), (500, 5), (600, 6)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); + + System::set_block_number(12); + assert_ok!(Elections::retract_voter(Origin::signed(6), 0)); + assert_ok!(Elections::retract_voter(Origin::signed(5), 1)); + assert_ok!(Elections::submit_candidacy(Origin::signed(6), 0)); + assert_ok!(Elections::submit_candidacy(Origin::signed(5), 1)); + assert_ok!( + Elections::set_approvals(Origin::signed(6), vec![true, false, false], 1, 0, 600), + ); + assert_ok!( + Elections::set_approvals(Origin::signed(5), vec![false, true, false], 1, 1, 500), + ); + // give 1 some new high balance + let _ = Balances::make_free_balance_be(&1, 997); + assert_ok!( + Elections::set_approvals(Origin::signed(1), vec![false, false, true], 1, 2, 1000), + ); + assert_eq!(Elections::voter_info(1).unwrap(), + VoterInfo { + stake: 1000, // 997 + 3 which is candidacy bond. + pot: Elections::get_offset(100, 1), + last_active: 1, + last_win: 1, + } + ); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(6, 11), (5, 11)]); + + System::set_block_number(14); + assert!(Elections::presentation_active()); + assert_eq!(Elections::present_winner(Origin::signed(6), 6, 600, 1), Ok(())); + assert_eq!(Elections::present_winner(Origin::signed(5), 5, 500, 1), Ok(())); + assert_eq!( + Elections::present_winner(Origin::signed(1), 1, 1000 + 96 /* pot */, 1), + Ok(()), + ); + assert_eq!(Elections::leaderboard(), Some(vec![(0, 0), (500, 5), (600, 6), (1096, 1)])); + assert_ok!(Elections::end_block(System::block_number())); + + assert_eq!(Elections::members(), vec![(1, 19), (6, 19)]); + }) +} + +#[test] +fn pot_get_offset_should_work() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Elections::get_offset(100, 0), 0); + assert_eq!(Elections::get_offset(100, 1), 96); + assert_eq!(Elections::get_offset(100, 2), 96 + 93); + assert_eq!(Elections::get_offset(100, 3), 96 + 93 + 90); + assert_eq!(Elections::get_offset(100, 4), 96 + 93 + 90 + 87); + // limit + assert_eq!(Elections::get_offset(100, 1000), 100 * 24); + + assert_eq!(Elections::get_offset(50_000_000_000, 0), 0); + assert_eq!(Elections::get_offset(50_000_000_000, 1), 48_000_000_000); + assert_eq!(Elections::get_offset(50_000_000_000, 2), 48_000_000_000 + 46_080_000_000); + assert_eq!(Elections::get_offset(50_000_000_000, 3), 48_000_000_000 + 46_080_000_000 + 44_236_800_000); + assert_eq!( + Elections::get_offset(50_000_000_000, 4), + 48_000_000_000 + 46_080_000_000 + 44_236_800_000 + 42_467_328_000 + ); + // limit + assert_eq!(Elections::get_offset(50_000_000_000, 1000), 50_000_000_000 * 24); + }) +} + +#[test] +fn pot_get_offset_with_zero_decay() { + ExtBuilder::default().decay_ratio(0).build().execute_with(|| { + assert_eq!(Elections::get_offset(100, 0), 0); + assert_eq!(Elections::get_offset(100, 1), 0); + assert_eq!(Elections::get_offset(100, 2), 0); + assert_eq!(Elections::get_offset(100, 3), 0); + // limit + assert_eq!(Elections::get_offset(100, 1000), 0); + }) +} diff --git a/srml/evm/Cargo.toml b/srml/evm/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..f0bad3e793ce878d003a60a08402b39be9afd9e8 --- /dev/null +++ b/srml/evm/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "srml-evm" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } +balances = { package = "srml-balances", path = "../balances", default-features = false } +primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +primitive-types = { version = "0.6", default-features = false, features = ["rlp"] } +rlp = { version = "0.4", default-features = false } +evm = { version = "0.14", default-features = false } +sha3 = { version = "0.8", default-features = false } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "primitives/std", + "sr-primitives/std", + "support/std", + "system/std", + "balances/std", + "runtime-io/std", + "rstd/std", + "sha3/std", + "rlp/std", + "primitive-types/std", + "evm/std", + "timestamp/std", +] diff --git a/srml/evm/src/backend.rs b/srml/evm/src/backend.rs new file mode 100644 index 0000000000000000000000000000000000000000..6de5429dde478e7289fe700e632a76fcfeaf2c0d --- /dev/null +++ b/srml/evm/src/backend.rs @@ -0,0 +1,187 @@ +use rstd::marker::PhantomData; +use rstd::vec::Vec; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +use codec::{Encode, Decode}; +use primitives::{U256, H256, H160}; +use sr_primitives::traits::UniqueSaturatedInto; +use support::storage::{StorageMap, StorageDoubleMap}; +use sha3::{Keccak256, Digest}; +use evm::Config; +use evm::backend::{Backend as BackendT, ApplyBackend, Apply}; +use crate::{Trait, Accounts, AccountStorages, AccountCodes, Module, Event}; + +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +/// Ethereum account nonce, balance and code. Used by storage. +pub struct Account { + /// Account nonce. + pub nonce: U256, + /// Account balance. + pub balance: U256, +} + +#[derive(Clone, Eq, PartialEq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +/// Ethereum log. Used for `deposit_event`. +pub struct Log { + /// Source address of the log. + pub address: H160, + /// Topics of the log. + pub topics: Vec, + /// Bytearray data of the log. + pub data: Vec, +} + +#[derive(Clone, Eq, PartialEq, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +/// External input from the transaction. +pub struct Vicinity { + /// Current transaction gas price. + pub gas_price: U256, + /// Origin of the transaction. + pub origin: H160, +} + +/// Gasometer config used for executor. Currently this is hard-coded to +/// Istanbul hard fork. +pub static GASOMETER_CONFIG: Config = Config::istanbul(); + +/// Substrate backend for EVM. +pub struct Backend<'vicinity, T> { + vicinity: &'vicinity Vicinity, + _marker: PhantomData, +} + +impl<'vicinity, T> Backend<'vicinity, T> { + /// Create a new backend with given vicinity. + pub fn new(vicinity: &'vicinity Vicinity) -> Self { + Self { vicinity, _marker: PhantomData } + } +} + +impl<'vicinity, T: Trait> BackendT for Backend<'vicinity, T> { + fn gas_price(&self) -> U256 { self.vicinity.gas_price } + fn origin(&self) -> H160 { self.vicinity.origin } + + fn block_hash(&self, number: U256) -> H256 { + if number > U256::from(u32::max_value()) { + H256::default() + } else { + let number = T::BlockNumber::from(number.as_u32()); + H256::from_slice(system::Module::::block_hash(number).as_ref()) + } + } + + fn block_number(&self) -> U256 { + let number: u128 = system::Module::::block_number().unique_saturated_into(); + U256::from(number) + } + + fn block_coinbase(&self) -> H160 { + H160::default() + } + + fn block_timestamp(&self) -> U256 { + let now: u128 = timestamp::Module::::get().unique_saturated_into(); + U256::from(now) + } + + fn block_difficulty(&self) -> U256 { + U256::zero() + } + + fn block_gas_limit(&self) -> U256 { + U256::zero() + } + + fn chain_id(&self) -> U256 { + U256::from(runtime_io::chain_id()) + } + + fn exists(&self, _address: H160) -> bool { + true + } + + fn basic(&self, address: H160) -> evm::backend::Basic { + let account = Accounts::get(&address); + + evm::backend::Basic { + balance: account.balance, + nonce: account.nonce, + } + } + + fn code_size(&self, address: H160) -> usize { + AccountCodes::decode_len(&address).unwrap_or(0) + } + + fn code_hash(&self, address: H160) -> H256 { + H256::from_slice(Keccak256::digest(&AccountCodes::get(&address)).as_slice()) + } + + fn code(&self, address: H160) -> Vec { + AccountCodes::get(&address) + } + + fn storage(&self, address: H160, index: H256) -> H256 { + AccountStorages::get(address, index) + } +} + +impl<'vicinity, T: Trait> ApplyBackend for Backend<'vicinity, T> { + fn apply( + &mut self, + values: A, + logs: L, + delete_empty: bool, + ) where + A: IntoIterator>, + I: IntoIterator, + L: IntoIterator, + { + for apply in values { + match apply { + Apply::Modify { + address, basic, code, storage, reset_storage, + } => { + Accounts::mutate(&address, |account| { + account.balance = basic.balance; + account.nonce = basic.nonce; + }); + + if let Some(code) = code { + AccountCodes::insert(address, code); + } + + if reset_storage { + AccountStorages::remove_prefix(address); + } + + for (index, value) in storage { + if value == H256::default() { + AccountStorages::remove(address, index); + } else { + AccountStorages::insert(address, index, value); + } + } + + if delete_empty { + Module::::remove_account_if_empty(&address); + } + }, + Apply::Delete { address } => { + Module::::remove_account(&address) + }, + } + } + + for log in logs { + Module::::deposit_event(Event::Log(Log { + address: log.address, + topics: log.topics, + data: log.data, + })); + } + } +} diff --git a/srml/evm/src/lib.rs b/srml/evm/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..37e09eb26436225fb3ef36598bef81c59c80856c --- /dev/null +++ b/srml/evm/src/lib.rs @@ -0,0 +1,282 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! EVM execution module for Substrate + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod backend; + +pub use crate::backend::{Account, Log, Vicinity, Backend}; + +use rstd::vec::Vec; +use support::{dispatch::Result, decl_module, decl_storage, decl_event}; +use support::traits::{Currency, WithdrawReason, ExistenceRequirement}; +use system::ensure_signed; +use sr_primitives::weights::SimpleDispatchInfo; +use sr_primitives::traits::UniqueSaturatedInto; +use primitives::{U256, H256, H160}; +use evm::{ExitReason, ExitSucceed, ExitError}; +use evm::executor::StackExecutor; +use evm::backend::ApplyBackend; + +/// Type alias for currency balance. +pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + +/// Trait that outputs the current transaction gas price. +pub trait FeeCalculator { + /// Return the current gas price. + fn gas_price() -> U256; +} + +/// Trait for converting account ids of `balances` module into +/// `H160` for EVM module. +/// +/// Accounts and contracts of this module are stored in its own +/// storage, in an Ethereum-compatible format. In order to communicate +/// with the rest of Substrate module, we require an one-to-one +/// mapping of Substrate account to Ethereum address. +pub trait ConvertAccountId { + /// Given a Substrate address, return the corresponding Ethereum address. + fn convert_account_id(account_id: &A) -> H160; +} + +/// Custom precompiles to be used by EVM engine. +pub trait Precompiles { + /// Try to execute the code address as precompile. If the code address is not + /// a precompile or the precompile is not yet available, return `None`. + /// Otherwise, calculate the amount of gas needed with given `input` and + /// `target_gas`. Return `Some(Ok(status, output, gas_used))` if the execution + /// is successful. Otherwise return `Some(Err(_))`. + fn execute( + address: H160, + input: &[u8], + target_gas: Option + ) -> Option, usize), ExitError>>; +} + +impl Precompiles for () { + fn execute( + _address: H160, + _input: &[u8], + _target_gas: Option + ) -> Option, usize), ExitError>> { + None + } +} + +/// EVM module trait +pub trait Trait: system::Trait + timestamp::Trait { + /// Calculator for current gas price. + type FeeCalculator: FeeCalculator; + /// Convert account ID to H160; + type ConvertAccountId: ConvertAccountId; + /// Currency type for deposit and withdraw. + type Currency: Currency; + /// The overarching event type. + type Event: From + Into<::Event>; + /// Precompiles associated with this EVM engine. + type Precompiles: Precompiles; +} + +decl_storage! { + trait Store for Module as Example { + Accounts get(fn accounts) config(): map H160 => Account; + AccountCodes: map H160 => Vec; + AccountStorages: double_map H160, blake2_256(H256) => H256; + } +} + +decl_event!( + /// EVM events + pub enum Event { + /// Ethereum events from contracts. + Log(Log), + } +); + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn deposit_balance(origin, value: BalanceOf) -> Result { + let sender = ensure_signed(origin)?; + + T::Currency::withdraw( + &sender, + value, + WithdrawReason::Reserve.into(), + ExistenceRequirement::KeepAlive, + )?; + + let bvalue = U256::from(UniqueSaturatedInto::::unique_saturated_into(value)); + let address = T::ConvertAccountId::convert_account_id(&sender); + Accounts::mutate(&address, |account| { + account.balance += bvalue; + }); + + Ok(()) + } + + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn withdraw_balance(origin, value: BalanceOf) -> Result { + let sender = ensure_signed(origin)?; + let address = T::ConvertAccountId::convert_account_id(&sender); + let bvalue = U256::from(UniqueSaturatedInto::::unique_saturated_into(value)); + + if Accounts::get(&address).balance < bvalue { + return Err("Not enough balance to withdraw") + } + + Accounts::mutate(&address, |account| { + account.balance -= bvalue; + }); + + T::Currency::deposit_creating(&sender, value); + + Ok(()) + } + + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn call(origin, target: H160, input: Vec, value: U256, gas_limit: u32) -> Result { + let sender = ensure_signed(origin)?; + let source = T::ConvertAccountId::convert_account_id(&sender); + let gas_price = T::FeeCalculator::gas_price(); + + let vicinity = Vicinity { + gas_price, + origin: source, + }; + + let mut backend = Backend::::new(&vicinity); + let mut executor = StackExecutor::new_with_precompile( + &backend, + gas_limit as usize, + &backend::GASOMETER_CONFIG, + T::Precompiles::execute, + ); + + let total_fee = gas_price.checked_mul(U256::from(gas_limit)) + .ok_or("Calculating total fee overflowed")?; + if Accounts::get(&source).balance < + value.checked_add(total_fee).ok_or("Calculating total payment overflowed")? + { + return Err("Not enough balance to pay transaction fee") + } + executor.withdraw(source, total_fee).map_err(|_| "Withdraw fee failed")?; + + let reason = executor.transact_call( + source, + target, + value, + input, + gas_limit as usize, + ); + + let ret = match reason { + ExitReason::Succeed(_) => Ok(()), + ExitReason::Error(_) => Err("Execute message call failed"), + ExitReason::Revert(_) => Err("Execute message call reverted"), + ExitReason::Fatal(_) => Err("Execute message call returned VM fatal error"), + }; + let actual_fee = executor.fee(gas_price); + executor.deposit(source, total_fee.saturating_sub(actual_fee)); + + let (values, logs) = executor.deconstruct(); + backend.apply(values, logs, true); + + ret + } + + #[weight = SimpleDispatchInfo::FixedNormal(10_000)] + fn create(origin, init: Vec, value: U256, gas_limit: u32) -> Result { + let sender = ensure_signed(origin)?; + let source = T::ConvertAccountId::convert_account_id(&sender); + let gas_price = T::FeeCalculator::gas_price(); + + let vicinity = Vicinity { + gas_price, + origin: source, + }; + + let mut backend = Backend::::new(&vicinity); + let mut executor = StackExecutor::new_with_precompile( + &backend, + gas_limit as usize, + &backend::GASOMETER_CONFIG, + T::Precompiles::execute, + ); + + let total_fee = gas_price.checked_mul(U256::from(gas_limit)) + .ok_or("Calculating total fee overflowed")?; + if Accounts::get(&source).balance < + value.checked_add(total_fee).ok_or("Calculating total payment overflowed")? + { + return Err("Not enough balance to pay transaction fee") + } + executor.withdraw(source, total_fee).map_err(|_| "Withdraw fee failed")?; + + let reason = executor.transact_create( + source, + value, + init, + gas_limit as usize, + ); + + let ret = match reason { + ExitReason::Succeed(_) => Ok(()), + ExitReason::Error(_) => Err("Execute contract creation failed"), + ExitReason::Revert(_) => Err("Execute contract creation reverted"), + ExitReason::Fatal(_) => Err("Execute contract creation returned VM fatal error"), + }; + let actual_fee = executor.fee(gas_price); + executor.deposit(source, total_fee.saturating_sub(actual_fee)); + + let (values, logs) = executor.deconstruct(); + backend.apply(values, logs, true); + + ret + } + } +} + +impl Module { + /// Check whether an account is empty. + pub fn is_account_empty(address: &H160) -> bool { + let account = Accounts::get(address); + let code_len = AccountCodes::decode_len(address).unwrap_or(0); + + account.nonce == U256::zero() && + account.balance == U256::zero() && + code_len == 0 + } + + /// Remove an account if its empty. + pub fn remove_account_if_empty(address: &H160) { + if Self::is_account_empty(address) { + Self::remove_account(address) + } + } + + /// Remove an account from state. + fn remove_account(address: &H160) { + Accounts::remove(address); + AccountCodes::remove(address); + AccountStorages::remove_prefix(address); + } +} diff --git a/srml/example/Cargo.toml b/srml/example/Cargo.toml index 87069a487a19a617f31fd08b9e3fcf05c2951516..695e0602fb32757b203213c7ad7a18d89c5dcdfd 100644 --- a/srml/example/Cargo.toml +++ b/srml/example/Cargo.toml @@ -5,15 +5,16 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } balances = { package = "srml-balances", path = "../balances", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } [dev-dependencies] -sr-io = { path = "../../core/sr-io" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } [features] @@ -22,7 +23,9 @@ std = [ "serde", "codec/std", "sr-primitives/std", - "srml-support/std", + "support/std", "system/std", "balances/std", + "runtime-io/std", + "rstd/std" ] diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index 0cfad989b156c7920c55c5aa9efdc9d38911de75..fb05e731bdd4dd9428f6199f315149a898495dbe 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -253,11 +253,56 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use srml_support::{StorageValue, dispatch::Result, decl_module, decl_storage, decl_event}; +use rstd::marker::PhantomData; +use support::{dispatch::Result, decl_module, decl_storage, decl_event}; use system::{ensure_signed, ensure_root}; -use sr_primitives::weights::SimpleDispatchInfo; +use codec::{Encode, Decode}; +use sr_primitives::{ + traits::{SignedExtension, Bounded, SaturatedConversion}, + weights::{SimpleDispatchInfo, DispatchInfo, DispatchClass, ClassifyDispatch, WeighData, Weight}, + transaction_validity::{ + ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, + }, +}; + +// A custom weight calculator tailored for the dispatch call `set_dummy()`. This actually examines +// the arguments and makes a decision based upon them. +// +// The `WeightData` trait has access to the arguments of the dispatch that it wants to assign a +// weight to. Nonetheless, the trait itself can not make any assumptions about what the generic type +// of the arguments (`T`) is. Based on our needs, we could replace `T` with a more concrete type +// while implementing the trait. The `decl_module!` expects whatever implements `WeighData` to +// replace `T` with a tuple of the dispatch arguments. This is exactly how we will craft the +// implementation below. +// +// The rules of `WeightForSetDummy` are as follows: +// - The final weight of each dispatch is calculated as the argument of the call multiplied by the +// parameter given to the `WeightForSetDummy`'s constructor. +// - assigns a dispatch class `operational` if the argument of the call is more than 1000. +struct WeightForSetDummy(BalanceOf); + +impl WeighData<(&BalanceOf,)> for WeightForSetDummy +{ + fn weigh_data(&self, target: (&BalanceOf,)) -> Weight { + let multiplier = self.0; + (*target.0 * multiplier).saturated_into::() + } +} + +impl ClassifyDispatch<(&BalanceOf,)> for WeightForSetDummy { + fn classify_dispatch(&self, target: (&BalanceOf,)) -> DispatchClass { + if *target.0 > >::from(1000u32) { + DispatchClass::Operational + } else { + DispatchClass::Normal + } + } +} -/// Our module's configuration trait. All our types and consts go in here. If the +/// A type alias for the balance type from this module's point of view. +type BalanceOf = ::Balance; + +/// Our module's configuration trait. All our types and constants go in here. If the /// module is dependent on specific other modules, then their configuration traits /// should be added to our implied traits list. /// @@ -273,7 +318,7 @@ decl_storage! { // keep things around between blocks. trait Store for Module as Example { // Any storage declarations of the form: - // `pub? Name get(getter_name)? [config()|config(myname)] [build(|_| {...})] : (= )?;` + // `pub? Name get(fn getter_name)? [config()|config(myname)] [build(|_| {...})] : (= )?;` // where `` is either: // - `Type` (a basic value item); or // - `map KeyType => ValueType` (a map item). @@ -286,7 +331,7 @@ decl_storage! { // - `Foo::put(1); Foo::get()` returns `1`; // - `Foo::kill(); Foo::get()` returns `0` (u32::default()). // e.g. Foo: u32; - // e.g. pub Bar get(bar): map T::AccountId => Vec<(T::Balance, u64)>; + // e.g. pub Bar get(fn bar): map T::AccountId => Vec<(T::Balance, u64)>; // // For basic value items, you'll get a type which implements // `support::StorageValue`. For map items, you'll get a type which @@ -295,13 +340,13 @@ decl_storage! { // If they have a getter (`get(getter_name)`), then your module will come // equipped with `fn getter_name() -> Type` for basic value items or // `fn getter_name(key: KeyType) -> ValueType` for map items. - Dummy get(dummy) config(): Option; + Dummy get(fn dummy) config(): Option; // A map that has enumerable entries. - Bar get(bar) config(): linked_map T::AccountId => T::Balance; + Bar get(fn bar) config(): linked_map T::AccountId => T::Balance; // this one uses the default, we'll demonstrate the usage of 'mutate' API. - Foo get(foo) config(): T::Balance; + Foo get(fn foo) config(): T::Balance; } } @@ -357,7 +402,7 @@ decl_module! { /// It is also possible to provide a custom implementation. /// For non-generic events, the generic parameter just needs to be dropped, so that it /// looks like: `fn deposit_event() = default;`. - fn deposit_event() = default; + fn deposit_event() = default; /// This is your public interface. Be extremely careful. /// This is just a simple example of how to interact with the module from the external /// world. @@ -404,9 +449,8 @@ decl_module! { // The _right-hand-side_ value of the `#[weight]` attribute can be any type that implements // a set of traits, namely [`WeighData`] and [`ClassifyDispatch`]. The former conveys the // weight (a numeric representation of pure execution time and difficulty) of the - // transaction and the latter demonstrates the `DispatchClass` of the call. A higher weight - // means a larger transaction (less of which can be placed in a single block). See the - // `CheckWeight` signed extension struct in the `system` module for more information. + // transaction and the latter demonstrates the [`DispatchClass`] of the call. A higher + // weight means a larger transaction (less of which can be placed in a single block). #[weight = SimpleDispatchInfo::FixedNormal(10_000)] fn accumulate_dummy(origin, increase_by: T::Balance) -> Result { // This is a public call, so we ensure that the origin is some signed account. @@ -447,6 +491,7 @@ decl_module! { // without worrying about gameability or attack scenarios. // If you not specify `Result` explicitly as return value, it will be added automatically // for you and `Ok(())` will be returned. + #[weight = WeightForSetDummy::(>::from(100u32))] fn set_dummy(origin, #[compact] new_value: T::Balance) { ensure_root(origin)?; // Put the new value into storage. @@ -500,17 +545,99 @@ impl Module { } } +// Similar to other SRML modules, your module can also define a signed extension and perform some +// checks and [pre/post]processing [before/after] the transaction. A signed extension can be any +// decodable type that implements `SignedExtension`. See the trait definition for the full list of +// bounds. As a convention, you can follow this approach to create an extension for your module: +// - If the extension does not carry any data, then use a tuple struct with just a `marker` +// (needed for the compiler to accept `T: Trait`) will suffice. +// - Otherwise, create a tuple struct which contains the external data. Of course, for the entire +// struct to be decodable, each individual item also needs to be decodable. +// +// Note that a signed extension can also indicate that a particular data must be present in the +// _signing payload_ of a transaction by providing an implementation for the `additional_signed` +// method. This example will not cover this type of extension. See `CheckRuntime` in system module +// for an example. +// +// Using the extension, you can add some hooks to the lifecycle of each transaction. Note that by +// default, an extension is applied to all `Call` functions (i.e. all transactions). the `Call` enum +// variant is given to each function of `SignedExtension`. Hence, you can filter based on module or +// a particular call if needed. +// +// Some extra information, such as encoded length, some static dispatch info like weight and the +// sender of the transaction (if signed) are also provided. +// +// The full list of hooks that can be added to a signed extension can be found +// [here](https://crates.parity.io/sr_primitives/traits/trait.SignedExtension.html). +// +// The signed extensions are aggregated in the runtime file of a substrate chain. All extensions +// should be aggregated in a tuple and passed to the `CheckedExtrinsic` and `UncheckedExtrinsic` +// types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and +// `node-template` for an example of this. + +/// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the +/// priority and prints some log. +/// +/// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No +/// particular reason why, just to demonstrate the power of signed extensions. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct WatchDummy(PhantomData); + +impl rstd::fmt::Debug for WatchDummy { + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + write!(f, "WatchDummy") + } +} + +impl SignedExtension for WatchDummy { + type AccountId = T::AccountId; + // Note that this could also be assigned to the top-level call enum. It is passed into the + // balances module directly and since `Trait: balances::Trait`, you could also use `T::Call`. + // In that case, you would have had access to all call variants and could match on variants from + // other modules. + type Call = Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: DispatchInfo, + len: usize, + ) -> TransactionValidity { + // if the transaction is too big, just drop it. + if len > 200 { + return InvalidTransaction::ExhaustsResources.into() + } + + // check for `set_dummy` + match call { + Call::set_dummy(..) => { + sr_primitives::print("set_dummy was received."); + + let mut valid_tx = ValidTransaction::default(); + valid_tx.priority = Bounded::max_value(); + Ok(valid_tx) + } + _ => Ok(Default::default()), + } + } +} + #[cfg(test)] mod tests { use super::*; - use srml_support::{assert_ok, impl_outer_origin, parameter_types}; - use sr_io::with_externalities; - use primitives::{H256, Blake2Hasher}; + use support::{assert_ok, impl_outer_origin, parameter_types}; + use primitives::H256; // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sr_primitives::{ - Perbill, traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup}, testing::Header + Perbill, weights::GetDispatchInfo, testing::Header, + traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup}, }; impl_outer_origin! { @@ -538,34 +665,28 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } parameter_types! { pub const ExistentialDeposit: u64 = 0; pub const TransferFee: u64 = 0; pub const CreationFee: u64 = 0; - pub const TransactionBaseFee: u64 = 0; - pub const TransactionByteFee: u64 = 0; } impl balances::Trait for Test { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); type Event = (); - type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = (); } impl Trait for Test { type Event = (); @@ -574,7 +695,7 @@ mod tests { // This function basically just builds a genesis storage key/value store according to // our desired mockup. - fn new_test_ext() -> sr_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); // We use default for brevity, but you can configure as desired if needed. balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); @@ -589,7 +710,7 @@ mod tests { #[test] fn it_works_for_optional_value() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { // Check that GenesisBuilder works properly. assert_eq!(Example::dummy(), Some(42)); @@ -610,10 +731,43 @@ mod tests { #[test] fn it_works_for_default_value() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(Example::foo(), 24); assert_ok!(Example::accumulate_foo(Origin::signed(1), 1)); assert_eq!(Example::foo(), 25); }); } + + #[test] + fn signed_ext_watch_dummy_works() { + new_test_ext().execute_with(|| { + let call = >::set_dummy(10); + let info = DispatchInfo::default(); + + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, info, 150) + .unwrap() + .priority, + Bounded::max_value(), + ); + assert_eq!( + WatchDummy::(PhantomData).validate(&1, &call, info, 250), + InvalidTransaction::ExhaustsResources.into(), + ); + }) + } + + #[test] + fn weights_work() { + // must have a default weight. + let default_call = >::accumulate_dummy(10); + let info = default_call.get_dispatch_info(); + // aka. `let info = as GetDispatchInfo>::get_dispatch_info(&default_call);` + assert_eq!(info.weight, 10_000); + + // must have a custom weight of `100 * arg = 2000` + let custom_call = >::set_dummy(20); + let info = custom_call.get_dispatch_info(); + assert_eq!(info.weight, 2000); + } } diff --git a/srml/executive/Cargo.toml b/srml/executive/Cargo.toml index e398a951896ea6e59767981a72d2316040ae1c65..92191a7aac4db28dc3577a1379a0642afb8c2b00 100644 --- a/srml/executive/Cargo.toml +++ b/srml/executive/Cargo.toml @@ -5,28 +5,29 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -hex-literal = "0.2.0" +hex-literal = "0.2.1" primitives = { package = "substrate-primitives", path = "../../core/primitives" } srml-indices = { path = "../indices" } balances = { package = "srml-balances", path = "../balances" } +transaction-payment = { package = "srml-transaction-payment", path = "../transaction-payment" } [features] default = ["std"] std = [ "rstd/std", - "srml-support/std", + "support/std", "serde", "codec/std", "sr-primitives/std", - "runtime_io/std", + "runtime-io/std", "system/std", ] diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 9c29c95f1082de13e07d254cd5aef3665e1542fa..146e0ebcadcd8cb82019a845c94b54f0c52aa38c 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -59,13 +59,15 @@ //! # pub type Balances = u64; //! # pub type AllModules = u64; //! # pub enum Runtime {}; -//! # use sr_primitives::transaction_validity::TransactionValidity; +//! # use sr_primitives::transaction_validity::{TransactionValidity, UnknownTransaction}; +//! # #[allow(deprecated)] //! # use sr_primitives::traits::ValidateUnsigned; +//! # #[allow(deprecated)] //! # impl ValidateUnsigned for Runtime { //! # type Call = (); //! # //! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity { -//! # TransactionValidity::Invalid(0) +//! # UnknownTransaction::NoUnsignedValidator.into() //! # } //! # } //! /// Executive: handles dispatch to the various modules. @@ -74,50 +76,19 @@ #![cfg_attr(not(feature = "std"), no_std)] -use rstd::prelude::*; -use rstd::marker::PhantomData; -use rstd::result; -use sr_primitives::{generic::Digest, traits::{ - self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, - OnInitialize, NumberFor, Block as BlockT, OffchainWorker, ValidateUnsigned -}}; -use srml_support::Dispatchable; +use rstd::{prelude::*, marker::PhantomData}; +use sr_primitives::{ + generic::Digest, ApplyResult, weights::GetDispatchInfo, + traits::{ + self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, + NumberFor, Block as BlockT, OffchainWorker, Dispatchable, + }, + transaction_validity::TransactionValidity, +}; +#[allow(deprecated)] +use sr_primitives::traits::ValidateUnsigned; use codec::{Codec, Encode}; use system::{extrinsics_root, DigestOf}; -use sr_primitives::{ApplyOutcome, ApplyError}; -use sr_primitives::transaction_validity::TransactionValidity; -use sr_primitives::weights::GetDispatchInfo; - -mod internal { - use sr_primitives::traits::DispatchError; - - pub enum ApplyError { - BadSignature(&'static str), - Stale, - Future, - CantPay, - FullBlock, - } - - pub enum ApplyOutcome { - Success, - Fail(&'static str), - } - - impl From for ApplyError { - fn from(d: DispatchError) -> Self { - match d { - DispatchError::Payment => ApplyError::CantPay, - DispatchError::Exhausted => ApplyError::FullBlock, - DispatchError::NoPermission => ApplyError::CantPay, - DispatchError::BadState => ApplyError::CantPay, - DispatchError::Stale => ApplyError::Stale, - DispatchError::Future => ApplyError::Future, - DispatchError::BadProof => ApplyError::BadSignature(""), - } - } - } -} /// Trait that can be used to execute a block. pub trait ExecuteBlock { @@ -133,6 +104,7 @@ pub struct Executive( PhantomData<(System, Block, Context, UnsignedValidator, AllModules)> ); +#[allow(deprecated)] // Allow ValidateUnsigned, remove the attribute when the trait is removed. impl< System: system::Trait, Block: traits::Block, @@ -152,6 +124,7 @@ where } } +#[allow(deprecated)] // Allow ValidateUnsigned, remove the attribute when the trait is removed. impl< System: system::Trait, Block: traits::Block, @@ -239,30 +212,19 @@ where /// Apply extrinsic outside of the block execution function. /// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt /// hashes. - pub fn apply_extrinsic(uxt: Block::Extrinsic) -> result::Result { + pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyResult { let encoded = uxt.encode(); let encoded_len = encoded.len(); - match Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded)) { - Ok(internal::ApplyOutcome::Success) => Ok(ApplyOutcome::Success), - Ok(internal::ApplyOutcome::Fail(_)) => Ok(ApplyOutcome::Fail), - Err(internal::ApplyError::CantPay) => Err(ApplyError::CantPay), - Err(internal::ApplyError::BadSignature(_)) => Err(ApplyError::BadSignature), - Err(internal::ApplyError::Stale) => Err(ApplyError::Stale), - Err(internal::ApplyError::Future) => Err(ApplyError::Future), - Err(internal::ApplyError::FullBlock) => Err(ApplyError::FullBlock), - } + Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded)) } /// Apply an extrinsic inside the block execution function. fn apply_extrinsic_no_note(uxt: Block::Extrinsic) { let l = uxt.encode().len(); match Self::apply_extrinsic_with_len(uxt, l, None) { - Ok(internal::ApplyOutcome::Success) => (), - Ok(internal::ApplyOutcome::Fail(e)) => runtime_io::print(e), - Err(internal::ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), - Err(internal::ApplyError::BadSignature(_)) => panic!("All extrinsics should be properly signed"), - Err(internal::ApplyError::Stale) | Err(internal::ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), - Err(internal::ApplyError::FullBlock) => panic!("Extrinsics should not exceed block limit"), + Ok(Ok(())) => (), + Ok(Err(e)) => sr_primitives::print(e), + Err(e) => { let err: &'static str = e.into(); panic!(err) }, } } @@ -271,9 +233,9 @@ where uxt: Block::Extrinsic, encoded_len: usize, to_note: Option>, - ) -> result::Result { + ) -> ApplyResult { // Verify that the signature is good. - let xt = uxt.check(&Default::default()).map_err(internal::ApplyError::BadSignature)?; + let xt = uxt.check(&Default::default())?; // We don't need to make sure to `note_extrinsic` only after we know it's going to be // executed to prevent it from leaking in storage since at this point, it will either @@ -286,15 +248,11 @@ where // Decode parameters and dispatch let dispatch_info = xt.get_dispatch_info(); - let r = Applyable::dispatch(xt, dispatch_info, encoded_len) - .map_err(internal::ApplyError::from)?; + let r = Applyable::apply::(xt, dispatch_info, encoded_len)?; >::note_applied_extrinsic(&r, encoded_len as u32); - r.map(|_| internal::ApplyOutcome::Success).or_else(|e| match e { - sr_primitives::BLOCK_FULL => Err(internal::ApplyError::FullBlock), - e => Ok(internal::ApplyOutcome::Fail(e)) - }) + Ok(r) } fn final_checks(header: &System::Header) { @@ -324,21 +282,8 @@ where /// /// Changes made to storage should be discarded. pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity { - // Note errors > 0 are from ApplyError - const UNKNOWN_ERROR: i8 = -127; - const INVALID_INDEX: i8 = -10; - let encoded_len = uxt.using_encoded(|d| d.len()); - let xt = match uxt.check(&Default::default()) { - // Checks out. Carry on. - Ok(xt) => xt, - // An unknown account index implies that the transaction may yet become valid. - Err("invalid account index") => return TransactionValidity::Unknown(INVALID_INDEX), - // Technically a bad signature could also imply an out-of-date account index, but - // that's more of an edge case. - Err(sr_primitives::BAD_SIGNATURE) => return TransactionValidity::Invalid(ApplyError::BadSignature as i8), - Err(_) => return TransactionValidity::Invalid(UNKNOWN_ERROR), - }; + let xt = uxt.check(&Default::default())?; let dispatch_info = xt.get_dispatch_info(); xt.validate::(dispatch_info, encoded_len) @@ -354,19 +299,23 @@ where #[cfg(test)] mod tests { use super::*; - use balances::Call; - use runtime_io::with_externalities; - use primitives::{H256, Blake2Hasher}; - use sr_primitives::generic::Era; - use sr_primitives::Perbill; - use sr_primitives::weights::Weight; - use sr_primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}; - use sr_primitives::testing::{Digest, Header, Block}; - use srml_support::{impl_outer_event, impl_outer_origin, parameter_types}; - use srml_support::traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}; - use system; + use primitives::H256; + use sr_primitives::{ + generic::Era, Perbill, DispatchError, weights::Weight, testing::{Digest, Header, Block}, + traits::{Bounded, Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}, + transaction_validity::{InvalidTransaction, UnknownTransaction}, ApplyError, + }; + use support::{ + impl_outer_event, impl_outer_origin, parameter_types, impl_outer_dispatch, + traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}, + }; + use system::Call as SystemCall; + use balances::Call as BalancesCall; use hex_literal::hex; + type System = system::Module; + type Balances = balances::Module; + impl_outer_origin! { pub enum Origin for Runtime { } } @@ -376,8 +325,13 @@ mod tests { balances, } } + impl_outer_dispatch! { + pub enum Call for Runtime where origin: Origin { + system::System, + balances::Balances, + } + } - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Eq, PartialEq)] pub struct Runtime; parameter_types! { @@ -389,7 +343,7 @@ mod tests { impl system::Trait for Runtime { type Origin = Origin; type Index = u64; - type Call = Call; + type Call = Call; type BlockNumber = u64; type Hash = primitives::H256; type Hashing = BlakeTwo256; @@ -398,41 +352,53 @@ mod tests { type Header = Header; type Event = MetaEvent; type BlockHashCount = BlockHashCount; - type WeightMultiplierUpdate = (); type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } parameter_types! { pub const ExistentialDeposit: u64 = 0; pub const TransferFee: u64 = 0; pub const CreationFee: u64 = 0; - pub const TransactionBaseFee: u64 = 10; - pub const TransactionByteFee: u64 = 0; } impl balances::Trait for Runtime { type Balance = u64; type OnFreeBalanceZero = (); type OnNewAccount = (); type Event = MetaEvent; - type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; + } + + parameter_types! { + pub const TransactionBaseFee: u64 = 10; + pub const TransactionByteFee: u64 = 0; + } + impl transaction_payment::Trait for Runtime { + type Currency = Balances; + type OnTransactionPayment = (); type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; type WeightToFee = ConvertInto; + type FeeMultiplierUpdate = (); } + #[allow(deprecated)] impl ValidateUnsigned for Runtime { - type Call = Call; + type Call = Call; + + fn pre_dispatch(_call: &Self::Call) -> Result<(), ApplyError> { + Ok(()) + } fn validate_unsigned(call: &Self::Call) -> TransactionValidity { match call { - Call::set_balance(_, _, _) => TransactionValidity::Valid(Default::default()), - _ => TransactionValidity::Invalid(0), + Call::Balances(BalancesCall::set_balance(_, _, _)) => Ok(Default::default()), + _ => UnknownTransaction::NoUnsignedValidator.into(), } } } @@ -441,9 +407,9 @@ mod tests { system::CheckEra, system::CheckNonce, system::CheckWeight, - balances::TakeFees + transaction_payment::ChargeTransactionPayment ); - type TestXt = sr_primitives::testing::TestXt, SignedExtra>; + type TestXt = sr_primitives::testing::TestXt; type Executive = super::Executive, system::ChainContext, Runtime, ()>; fn extra(nonce: u64, fee: u64) -> SignedExtra { @@ -451,7 +417,7 @@ mod tests { system::CheckEra::from(Era::Immortal), system::CheckNonce::from(nonce), system::CheckWeight::new(), - balances::TakeFees::from(fee) + transaction_payment::ChargeTransactionPayment::from(fee) ) } @@ -466,10 +432,10 @@ mod tests { balances: vec![(1, 211)], vesting: vec![], }.assimilate_storage(&mut t).unwrap(); - let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::transfer(2, 69)); + let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(2, 69))); let weight = xt.get_dispatch_info().weight as u64; - let mut t = runtime_io::TestExternalities::::new(t); - with_externalities(&mut t, || { + let mut t = runtime_io::TestExternalities::new(t); + t.execute_with(|| { Executive::initialize_block(&Header::new( 1, H256::default(), @@ -478,13 +444,13 @@ mod tests { Digest::default(), )); let r = Executive::apply_extrinsic(xt); - assert_eq!(r, Ok(ApplyOutcome::Success)); + assert!(r.is_ok()); assert_eq!(>::total_balance(&1), 142 - 10 - weight); assert_eq!(>::total_balance(&2), 69); }); } - fn new_test_ext(balance_factor: u64) -> runtime_io::TestExternalities { + fn new_test_ext(balance_factor: u64) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)], @@ -495,12 +461,12 @@ mod tests { #[test] fn block_import_works() { - with_externalities(&mut new_test_ext(1), || { + new_test_ext(1).execute_with(|| { Executive::execute_block(Block { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("3e51b47b6cc8449eece93eee4b01f03b00a0ca7981c0b6c0447b6e0d50ca886d").into(), + state_root: hex!("f0d1d66255c2e5b40580eb8b93ddbe732491478487f85e358e1d167d369e398e").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, @@ -512,7 +478,7 @@ mod tests { #[test] #[should_panic] fn block_import_of_bad_state_root_fails() { - with_externalities(&mut new_test_ext(1), || { + new_test_ext(1).execute_with(|| { Executive::execute_block(Block { header: Header { parent_hash: [69u8; 32].into(), @@ -529,7 +495,7 @@ mod tests { #[test] #[should_panic] fn block_import_of_bad_extrinsic_root_fails() { - with_externalities(&mut new_test_ext(1), || { + new_test_ext(1).execute_with(|| { Executive::execute_block(Block { header: Header { parent_hash: [69u8; 32].into(), @@ -547,8 +513,8 @@ mod tests { fn bad_extrinsic_not_inserted() { let mut t = new_test_ext(1); // bad nonce check! - let xt = sr_primitives::testing::TestXt(sign_extra(1, 30, 0), Call::transfer(33, 69)); - with_externalities(&mut t, || { + let xt = sr_primitives::testing::TestXt(sign_extra(1, 30, 0), Call::Balances(BalancesCall::transfer(33, 69))); + t.execute_with(|| { Executive::initialize_block(&Header::new( 1, H256::default(), @@ -565,12 +531,12 @@ mod tests { fn block_weight_limit_enforced() { let mut t = new_test_ext(10000); // given: TestXt uses the encoded len as fixed Len: - let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::transfer::(33, 0)); + let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0))); let encoded = xt.encode(); let encoded_len = encoded.len() as Weight; let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get(); let num_to_exhaust_block = limit / encoded_len; - with_externalities(&mut t, || { + t.execute_with(|| { Executive::initialize_block(&Header::new( 1, H256::default(), @@ -581,14 +547,19 @@ mod tests { assert_eq!(>::all_extrinsics_weight(), 0); for nonce in 0..=num_to_exhaust_block { - let xt = sr_primitives::testing::TestXt(sign_extra(1, nonce.into(), 0), Call::transfer::(33, 0)); + let xt = sr_primitives::testing::TestXt( + sign_extra(1, nonce.into(), 0), Call::Balances(BalancesCall::transfer(33, 0)), + ); let res = Executive::apply_extrinsic(xt); if nonce != num_to_exhaust_block { - assert_eq!(res.unwrap(), ApplyOutcome::Success); - assert_eq!(>::all_extrinsics_weight(), encoded_len * (nonce + 1)); + assert!(res.is_ok()); + assert_eq!( + >::all_extrinsics_weight(), + encoded_len * (nonce + 1), + ); assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); } else { - assert_eq!(res, Err(ApplyError::FullBlock)); + assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); } } }); @@ -596,21 +567,21 @@ mod tests { #[test] fn block_weight_and_size_is_stored_per_tx() { - let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::transfer(33, 0)); - let x1 = sr_primitives::testing::TestXt(sign_extra(1, 1, 0), Call::transfer(33, 0)); - let x2 = sr_primitives::testing::TestXt(sign_extra(1, 2, 0), Call::transfer(33, 0)); + let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0))); + let x1 = sr_primitives::testing::TestXt(sign_extra(1, 1, 0), Call::Balances(BalancesCall::transfer(33, 0))); + let x2 = sr_primitives::testing::TestXt(sign_extra(1, 2, 0), Call::Balances(BalancesCall::transfer(33, 0))); let len = xt.clone().encode().len() as u32; let mut t = new_test_ext(1); - with_externalities(&mut t, || { + t.execute_with(|| { assert_eq!(>::all_extrinsics_weight(), 0); assert_eq!(>::all_extrinsics_weight(), 0); - assert_eq!(Executive::apply_extrinsic(xt.clone()).unwrap(), ApplyOutcome::Success); - assert_eq!(Executive::apply_extrinsic(x1.clone()).unwrap(), ApplyOutcome::Success); - assert_eq!(Executive::apply_extrinsic(x2.clone()).unwrap(), ApplyOutcome::Success); + assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); // default weight for `TestXt` == encoded length. - assert_eq!(>::all_extrinsics_weight(), (3 * len).into()); + assert_eq!(>::all_extrinsics_weight(), (3 * len) as u32); assert_eq!(>::all_extrinsics_len(), 3 * len); let _ = >::finalize(); @@ -622,13 +593,19 @@ mod tests { #[test] fn validate_unsigned() { - let xt = sr_primitives::testing::TestXt(None, Call::set_balance(33, 69, 69)); - let valid = TransactionValidity::Valid(Default::default()); + let xt = sr_primitives::testing::TestXt(None, Call::Balances(BalancesCall::set_balance(33, 69, 69))); let mut t = new_test_ext(1); - with_externalities(&mut t, || { - assert_eq!(Executive::validate_transaction(xt.clone()), valid); - assert_eq!(Executive::apply_extrinsic(xt), Ok(ApplyOutcome::Fail)); + t.execute_with(|| { + assert_eq!(Executive::validate_transaction(xt.clone()), Ok(Default::default())); + assert_eq!( + Executive::apply_extrinsic(xt), + Ok( + Err( + DispatchError { module: Some(1), error: 0, message: Some("RequireRootOrigin") } + ) + ) + ); }); } @@ -637,15 +614,18 @@ mod tests { let id: LockIdentifier = *b"0 "; let execute_with_lock = |lock: WithdrawReasons| { let mut t = new_test_ext(1); - with_externalities(&mut t, || { + t.execute_with(|| { as LockableCurrency>::set_lock( id, &1, 110, - 10, + Bounded::max_value(), lock, ); - let xt = sr_primitives::testing::TestXt(sign_extra(1, 0, 0), Call::transfer(2, 10)); + let xt = sr_primitives::testing::TestXt( + sign_extra(1, 0, 0), + Call::System(SystemCall::remark(vec![1u8])), + ); let weight = xt.get_dispatch_info().weight as u64; Executive::initialize_block(&Header::new( 1, @@ -656,11 +636,14 @@ mod tests { )); if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { - assert_eq!(Executive::apply_extrinsic(xt).unwrap(), ApplyOutcome::Fail); - // but tx fee has been deducted. the transaction failed on transfer, not on fee. + assert!(Executive::apply_extrinsic(xt).unwrap().is_ok()); + // tx fee has been deducted. assert_eq!(>::total_balance(&1), 111 - 10 - weight); } else { - assert_eq!(Executive::apply_extrinsic(xt), Err(ApplyError::CantPay)); + assert_eq!( + Executive::apply_extrinsic(xt), + Err(ApplyError::Validity(InvalidTransaction::Payment.into())), + ); assert_eq!(>::total_balance(&1), 111); } }); diff --git a/srml/finality-tracker/Cargo.toml b/srml/finality-tracker/Cargo.toml index 65ac540b6bcaee5e586bca231c47ab12c23c6644..a881b2906f0458cce7de49342012a5b80497f7d2 100644 --- a/srml/finality-tracker/Cargo.toml +++ b/srml/finality-tracker/Cargo.toml @@ -5,17 +5,18 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } srml-system = { path = "../system", default-features = false } +impl-trait-for-tuples = "0.1.3" [dev-dependencies] primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } [features] default = ["std"] @@ -23,7 +24,7 @@ std = [ "serde/std", "codec/std", "rstd/std", - "srml-support/std", + "support/std", "sr-primitives/std", "srml-system/std", "inherents/std", diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs index 26a0e0d4151214bae51eeb88f705508a00859c95..5e973cd43235d3002e89b8badfe1c7cee38e5bd3 100644 --- a/srml/finality-tracker/src/lib.rs +++ b/srml/finality-tracker/src/lib.rs @@ -22,12 +22,11 @@ use inherents::{ RuntimeString, InherentIdentifier, ProvideInherent, InherentData, MakeFatalError, }; -use srml_support::StorageValue; use sr_primitives::traits::{One, Zero, SaturatedConversion}; use rstd::{prelude::*, result, cmp, vec}; use codec::Decode; -use srml_support::{decl_module, decl_storage, for_each_tuple}; -use srml_support::traits::Get; +use support::{decl_module, decl_storage}; +use support::traits::Get; use srml_system::{ensure_none, Trait as SystemTrait}; #[cfg(feature = "std")] @@ -97,17 +96,17 @@ pub trait Trait: SystemTrait { decl_storage! { trait Store for Module as Timestamp { /// Recent hints. - RecentHints get(recent_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; + RecentHints get(fn recent_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; /// Ordered recent hints. - OrderedHints get(ordered_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; + OrderedHints get(fn ordered_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; /// The median. - Median get(median) build(|_| T::BlockNumber::zero()): T::BlockNumber; + Median get(fn median) build(|_| T::BlockNumber::zero()): T::BlockNumber; /// Final hint to apply in the block. `None` means "same as parent". Update: Option; // when initialized through config this is set in the beginning. - Initialized get(initialized) build(|_| false): bool; + Initialized get(fn initialized) build(|_| false): bool; } } @@ -214,30 +213,13 @@ impl Module { } /// Called when finalization stalled at a given number. +#[impl_trait_for_tuples::impl_for_tuples(30)] pub trait OnFinalizationStalled { /// The parameter here is how many more blocks to wait before applying /// changes triggered by finality stalling. fn on_stalled(further_wait: N, median: N); } -macro_rules! impl_on_stalled { - () => ( - impl OnFinalizationStalled for () { - fn on_stalled(_: N, _: N) {} - } - ); - - ( $($t:ident)* ) => { - impl),*> OnFinalizationStalled for ($($t,)*) { - fn on_stalled(further_wait: NUM, median: NUM) { - $($t::on_stalled(further_wait.clone(), median.clone());)* - } - } - } -} - -for_each_tuple!(impl_on_stalled); - impl ProvideInherent for Module { type Call = Call; type Error = MakeFatalError<()>; @@ -265,12 +247,13 @@ impl ProvideInherent for Module { mod tests { use super::*; - use sr_io::{with_externalities, TestExternalities}; + use runtime_io::TestExternalities; use primitives::H256; - use sr_primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}; - use sr_primitives::testing::Header; - use sr_primitives::Perbill; - use srml_support::{assert_ok, impl_outer_origin, parameter_types}; + use sr_primitives::{ + testing::Header, Perbill, + traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}, + }; + use support::{assert_ok, impl_outer_origin, parameter_types}; use srml_system as system; use std::cell::RefCell; @@ -315,12 +298,12 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } parameter_types! { pub const WindowSize: u64 = 11; @@ -338,7 +321,7 @@ mod tests { #[test] fn median_works() { let t = system::GenesisConfig::default().build_storage::().unwrap(); - with_externalities(&mut TestExternalities::new(t), || { + TestExternalities::new(t).execute_with(|| { FinalityTracker::update_hint(Some(500)); assert_eq!(FinalityTracker::median(), 250); assert!(NOTIFICATIONS.with(|n| n.borrow().is_empty())); @@ -348,7 +331,7 @@ mod tests { #[test] fn notifies_when_stalled() { let t = system::GenesisConfig::default().build_storage::().unwrap(); - with_externalities(&mut TestExternalities::new(t), || { + TestExternalities::new(t).execute_with(|| { let mut parent_hash = System::parent_hash(); for i in 2..106 { System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); @@ -367,7 +350,7 @@ mod tests { #[test] fn recent_notifications_prevent_stalling() { let t = system::GenesisConfig::default().build_storage::().unwrap(); - with_externalities(&mut TestExternalities::new(t), || { + TestExternalities::new(t).execute_with(|| { let mut parent_hash = System::parent_hash(); for i in 2..106 { System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); diff --git a/srml/generic-asset/Cargo.toml b/srml/generic-asset/Cargo.toml index 65e21c3b11fbe8eb4b947a8521423fe2b5c3aa28..49a9db4c0ecd8962f81bdf0a1df1ebed83dfedeb 100644 --- a/srml/generic-asset/Cargo.toml +++ b/srml/generic-asset/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Centrality Developers "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } @@ -13,7 +13,7 @@ support = { package = "srml-support", path = "../support", default-features = fa system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -runtime_io = { package = "sr-io", path = "../../core/sr-io" } +runtime-io ={ package = "sr-io", path = "../../core/sr-io" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } [features] diff --git a/srml/generic-asset/src/lib.rs b/srml/generic-asset/src/lib.rs index c93df7c0be8118fd01b5a061a1404a0c62cb2eb3..fda3b6ae048f40e984c2d4c0133bd7295d80566f 100644 --- a/srml/generic-asset/src/lib.rs +++ b/srml/generic-asset/src/lib.rs @@ -128,7 +128,7 @@ //! T::Currency::withdraw( //! transactor, //! amount, -//! WithdrawReason::TransactionPayment, +//! WithdrawReason::TransactionPayment.into(), //! ExistenceRequirement::KeepAlive, //! )?; //! // ... @@ -153,12 +153,13 @@ use codec::{Decode, Encode, HasCompact, Input, Output, Error}; +use sr_primitives::RuntimeDebug; use sr_primitives::traits::{ - CheckedAdd, CheckedSub, MaybeSerializeDebug, Member, One, Saturating, SimpleArithmetic, Zero, Bounded + CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic, Zero, Bounded }; use rstd::prelude::*; -use rstd::{cmp, result}; +use rstd::{cmp, result, fmt::Debug}; use support::dispatch::Result; use support::{ decl_event, decl_module, decl_storage, ensure, @@ -166,7 +167,7 @@ use support::{ Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency, ReservableCurrency, SignedImbalance, UpdateBalanceOutcome, WithdrawReason, WithdrawReasons, }, - Parameter, StorageDoubleMap, StorageMap, StorageValue, + Parameter, StorageMap, }; use system::{ensure_signed, ensure_root}; @@ -181,7 +182,8 @@ pub trait Trait: system::Trait { + SimpleArithmetic + Default + Copy - + MaybeSerializeDebug; + + MaybeSerializeDeserialize + + Debug; type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy; type Event: From> + Into<::Event>; } @@ -192,7 +194,8 @@ pub trait Subtrait: system::Trait { + SimpleArithmetic + Default + Copy - + MaybeSerializeDebug; + + MaybeSerializeDeserialize + + Debug; type AssetId: Parameter + Member + SimpleArithmetic + Default + Copy; } @@ -202,8 +205,7 @@ impl Subtrait for T { } /// Asset creation options. -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Clone, Encode, Decode, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] pub struct AssetOptions { /// Initial issuance of this asset. All deposit to the creater of the asset. #[codec(compact)] @@ -213,8 +215,7 @@ pub struct AssetOptions { } /// Owner of an asset. -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Clone, Encode, Decode, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] pub enum Owner { /// No owner. None, @@ -229,8 +230,7 @@ impl Default for Owner { } /// Asset permissions -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Clone, Encode, Decode, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] pub struct PermissionsV1 { /// Who have permission to update asset permission pub update: Owner, @@ -240,27 +240,25 @@ pub struct PermissionsV1 { pub burn: Owner, } -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Clone, Encode, Decode, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] #[repr(u8)] enum PermissionVersionNumber { V1 = 0, } /// Versioned asset permission -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, RuntimeDebug)] pub enum PermissionVersions { V1(PermissionsV1), } /// Asset permission types pub enum PermissionType { - /// Permission to update asset permission + /// Permission to burn asset permission Burn, /// Permission to mint new asset Mint, - /// Permission to burn asset + /// Permission to update asset Update, } @@ -324,7 +322,7 @@ impl Into> for PermissionLatest for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Create a new kind of asset. fn create(origin, options: AssetOptions) -> Result { @@ -435,8 +433,7 @@ decl_module! { } } -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct BalanceLock { pub id: LockIdentifier, pub amount: Balance, @@ -447,7 +444,7 @@ pub struct BalanceLock { decl_storage! { trait Store for Module as GenericAsset { /// Total issuance of a given asset. - pub TotalIssuance get(total_issuance) build(|config: &GenesisConfig| { + pub TotalIssuance get(fn total_issuance) build(|config: &GenesisConfig| { let issuance = config.initial_balance * (config.endowed_accounts.len() as u32).into(); config.assets.iter().map(|id| (id.clone(), issuance)).collect::>() }): map T::AssetId => T::Balance; @@ -459,34 +456,29 @@ decl_storage! { pub ReservedBalance: double_map T::AssetId, twox_128(T::AccountId) => T::Balance; /// Next available ID for user-created asset. - pub NextAssetId get(next_asset_id) config(): T::AssetId; + pub NextAssetId get(fn next_asset_id) config(): T::AssetId; /// Permission options for a given asset. - pub Permissions get(get_permission): map T::AssetId => PermissionVersions; + pub Permissions get(fn get_permission): map T::AssetId => PermissionVersions; /// Any liquidity locks on some account balances. - pub Locks get(locks): map T::AccountId => Vec>; + pub Locks get(fn locks): map T::AccountId => Vec>; /// The identity of the asset which is the one that is designated for the chain's staking system. - pub StakingAssetId get(staking_asset_id) config(): T::AssetId; + pub StakingAssetId get(fn staking_asset_id) config(): T::AssetId; /// The identity of the asset which is the one that is designated for paying the chain's transaction fee. - pub SpendingAssetId get(spending_asset_id) config(): T::AssetId; + pub SpendingAssetId get(fn spending_asset_id) config(): T::AssetId; } add_extra_genesis { config(assets): Vec; config(initial_balance): T::Balance; config(endowed_accounts): Vec; - build(| - storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), - config: &GenesisConfig| { + build(|config: &GenesisConfig| { config.assets.iter().for_each(|asset_id| { config.endowed_accounts.iter().for_each(|account_id| { - storage.0.insert( - >::key_for(asset_id, account_id), - ::encode(&config.initial_balance) - ); + >::insert(asset_id, account_id, &config.initial_balance); }); }); }); @@ -571,11 +563,16 @@ impl Module { /// Transfer some liquid free balance from one account to another. /// This will not emit the `Transferred` event. - pub fn make_transfer(asset_id: &T::AssetId, from: &T::AccountId, to: &T::AccountId, amount: T::Balance) -> Result { + pub fn make_transfer( + asset_id: &T::AssetId, + from: &T::AccountId, + to: &T::AccountId, + amount: T::Balance + ) -> Result { let new_balance = Self::free_balance(asset_id, from) .checked_sub(&amount) .ok_or_else(|| "balance too low to send amount")?; - Self::ensure_can_withdraw(asset_id, from, amount, WithdrawReason::Transfer, new_balance)?; + Self::ensure_can_withdraw(asset_id, from, amount, WithdrawReason::Transfer.into(), new_balance)?; if from != to { >::mutate(asset_id, from, |balance| *balance -= amount); @@ -742,7 +739,7 @@ impl Module { asset_id: &T::AssetId, who: &T::AccountId, _amount: T::Balance, - reason: WithdrawReason, + reasons: WithdrawReasons, new_balance: T::Balance, ) -> Result { if asset_id != &Self::staking_asset_id() { @@ -756,7 +753,7 @@ impl Module { let now = >::block_number(); if Self::locks(who) .into_iter() - .all(|l| now >= l.until || new_balance >= l.amount || !l.reasons.contains(reason)) + .all(|l| now >= l.until || new_balance >= l.amount || !l.reasons.intersects(reasons)) { Ok(()) } else { @@ -1061,8 +1058,8 @@ impl system::Trait for ElevatedTrait { type MaximumBlockWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; type AvailableBlockRatio = T::AvailableBlockRatio; - type WeightMultiplierUpdate = (); type BlockHashCount = T::BlockHashCount; + type Version = T::Version; } impl Trait for ElevatedTrait { type Balance = T::Balance; @@ -1070,8 +1067,7 @@ impl Trait for ElevatedTrait { type Event = (); } -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct AssetCurrency(rstd::marker::PhantomData, rstd::marker::PhantomData); impl Currency for AssetCurrency @@ -1100,29 +1096,34 @@ where Zero::zero() } - fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { + fn transfer( + transactor: &T::AccountId, + dest: &T::AccountId, + value: Self::Balance, + _: ExistenceRequirement, // no existential deposit policy for generic asset + ) -> Result { >::make_transfer(&U::asset_id(), transactor, dest, value) } fn ensure_can_withdraw( who: &T::AccountId, amount: Self::Balance, - reason: WithdrawReason, + reasons: WithdrawReasons, new_balance: Self::Balance, ) -> Result { - >::ensure_can_withdraw(&U::asset_id(), who, amount, reason, new_balance) + >::ensure_can_withdraw(&U::asset_id(), who, amount, reasons, new_balance) } fn withdraw( who: &T::AccountId, value: Self::Balance, - reason: WithdrawReason, + reasons: WithdrawReasons, _: ExistenceRequirement, // no existential deposit policy for generic asset ) -> result::Result { let new_balance = Self::free_balance(who) .checked_sub(&value) .ok_or_else(|| "account has too few funds")?; - Self::ensure_can_withdraw(who, value, reason, new_balance)?; + Self::ensure_can_withdraw(who, value, reasons, new_balance)?; >::set_free_balance(&U::asset_id(), who, new_balance); Ok(NegativeImbalance::new(value)) } @@ -1205,7 +1206,9 @@ where Self::free_balance(who) .checked_sub(&value) .map_or(false, |new_balance| - >::ensure_can_withdraw(&U::asset_id(), who, value, WithdrawReason::Reserve, new_balance).is_ok() + >::ensure_can_withdraw( + &U::asset_id(), who, value, WithdrawReason::Reserve.into(), new_balance + ).is_ok() ) } @@ -1259,7 +1262,7 @@ impl AssetIdProvider for SpendingAssetIdProvider { impl LockableCurrency for AssetCurrency> where T: Trait, - T::Balance: MaybeSerializeDebug, + T::Balance: MaybeSerializeDeserialize + Debug, { type Moment = T::BlockNumber; diff --git a/srml/generic-asset/src/mock.rs b/srml/generic-asset/src/mock.rs index 2c348a0175c4f3c46ab8d9691a67d9d3ff0cc9cb..57b13760fa03d2ed90d59dd8a33dfb9abbc62b77 100644 --- a/srml/generic-asset/src/mock.rs +++ b/srml/generic-asset/src/mock.rs @@ -25,7 +25,7 @@ use sr_primitives::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; -use primitives::{Blake2Hasher, H256}; +use primitives::H256; use support::{parameter_types, impl_outer_event, impl_outer_origin}; use super::*; @@ -56,11 +56,11 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; - type WeightMultiplierUpdate = (); type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type BlockHashCount = BlockHashCount; + type Version = (); } impl Trait for Test { @@ -117,7 +117,7 @@ impl ExtBuilder { } // builds genesis config - pub fn build(self) -> runtime_io::TestExternalities { + pub fn build(self) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig:: { @@ -136,7 +136,7 @@ impl ExtBuilder { // This function basically just builds a genesis storage key/value store according to // our desired mockup. -pub fn new_test_ext() -> runtime_io::TestExternalities { +pub fn new_test_ext() -> runtime_io::TestExternalities { system::GenesisConfig::default() .build_storage::() .unwrap() diff --git a/srml/generic-asset/src/tests.rs b/srml/generic-asset/src/tests.rs index 685e553c1c14d03687a3595ece8032746f273fea..165936d0215a6e86133f59b2ce652fb830b55f33 100644 --- a/srml/generic-asset/src/tests.rs +++ b/srml/generic-asset/src/tests.rs @@ -22,14 +22,13 @@ use super::*; use crate::mock::{new_test_ext, ExtBuilder, GenericAsset, Origin, System, Test, TestEvent}; -use runtime_io::with_externalities; use support::{assert_noop, assert_ok}; #[test] fn issuing_asset_units_to_issuer_should_work() { let balance = 100; - with_externalities(&mut ExtBuilder::default().free_balance((16000, 1, 100)).build(), || { + ExtBuilder::default().free_balance((16000, 1, 100)).build().execute_with(|| { let default_permission = PermissionLatest { update: Owner::Address(1), mint: Owner::Address(1), @@ -51,61 +50,55 @@ fn issuing_asset_units_to_issuer_should_work() { #[test] fn issuing_with_next_asset_id_overflow_should_not_work() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - NextAssetId::::put(u32::max_value()); - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_noop!( - GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 1, - permissions: default_permission - } - ), - "No new assets id available." - ); - assert_eq!(GenericAsset::next_asset_id(), u32::max_value()); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + NextAssetId::::put(u32::max_value()); + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_noop!( + GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 1, + permissions: default_permission + } + ), + "No new assets id available." + ); + assert_eq!(GenericAsset::next_asset_id(), u32::max_value()); + }); } #[test] fn querying_total_supply_should_work() { let asset_id = 1000; - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 50)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); - assert_eq!(GenericAsset::free_balance(&asset_id, &2), 50); - assert_ok!(GenericAsset::transfer(Origin::signed(2), asset_id, 3, 31)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); - assert_eq!(GenericAsset::free_balance(&asset_id, &2), 19); - assert_eq!(GenericAsset::free_balance(&asset_id, &3), 31); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 1)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 50)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); + assert_eq!(GenericAsset::free_balance(&asset_id, &2), 50); + assert_ok!(GenericAsset::transfer(Origin::signed(2), asset_id, 3, 31)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); + assert_eq!(GenericAsset::free_balance(&asset_id, &2), 19); + assert_eq!(GenericAsset::free_balance(&asset_id, &3), 31); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 1)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 50); + }); } // Given @@ -127,27 +120,24 @@ fn querying_total_supply_should_work() { fn transferring_amount_should_work() { let asset_id = 1000; let free_balance = 100; - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: free_balance, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), free_balance); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 40)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 60); - assert_eq!(GenericAsset::free_balance(&asset_id, &2), 40); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: free_balance, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), free_balance); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 2, 40)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 60); + assert_eq!(GenericAsset::free_balance(&asset_id, &2), 40); + }); } // Given @@ -168,55 +158,49 @@ fn transferring_amount_should_work() { #[test] fn transferring_amount_should_fail_when_transferring_more_than_free_balance() { let asset_id = 1000; - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_noop!( - GenericAsset::transfer(Origin::signed(1), asset_id, 2, 2000), - "balance too low to send amount" - ); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_noop!( + GenericAsset::transfer(Origin::signed(1), asset_id, 2, 2000), + "balance too low to send amount" + ); + }); } #[test] fn transferring_less_than_one_unit_should_not_work() { let asset_id = 1000; - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); - assert_noop!( - GenericAsset::transfer(Origin::signed(1), asset_id, 2, 0), - "cannot transfer zero amount" - ); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); + assert_noop!( + GenericAsset::transfer(Origin::signed(1), asset_id, 2, 0), + "cannot transfer zero amount" + ); + }); } // Given @@ -233,60 +217,54 @@ fn self_transfer_should_fail() { let asset_id = 1000; let balance = 100; - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: balance, - permissions: default_permission - } - )); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: balance, + permissions: default_permission + } + )); - let initial_free_balance = GenericAsset::free_balance(&asset_id, &1); - assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 10)); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), initial_free_balance); - }, - ); + let initial_free_balance = GenericAsset::free_balance(&asset_id, &1); + assert_ok!(GenericAsset::transfer(Origin::signed(1), asset_id, 1, 10)); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), initial_free_balance); + }); } #[test] fn transferring_more_units_than_total_supply_should_not_work() { let asset_id = 1000; - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let default_permission = PermissionLatest { - update: Owner::Address(1), - mint: Owner::Address(1), - burn: Owner::Address(1), - }; - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); - assert_noop!( - GenericAsset::transfer(Origin::signed(1), asset_id, 2, 101), - "balance too low to send amount" - ); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let default_permission = PermissionLatest { + update: Owner::Address(1), + mint: Owner::Address(1), + burn: Owner::Address(1), + }; + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &1), 100); + assert_noop!( + GenericAsset::transfer(Origin::signed(1), asset_id, 2, 101), + "balance too low to send amount" + ); + }); } // Ensures it uses fake money for staking asset id. #[test] fn staking_asset_id_should_return_0() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { assert_eq!(GenericAsset::staking_asset_id(), 16000); }); } @@ -294,7 +272,7 @@ fn staking_asset_id_should_return_0() { // Ensures it uses fake money for spending asset id. #[test] fn spending_asset_id_should_return_10() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { assert_eq!(GenericAsset::spending_asset_id(), 16001); }); } @@ -305,7 +283,7 @@ fn spending_asset_id_should_return_10() { // -Â total_balance should return 0 #[test] fn total_balance_should_be_zero() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(GenericAsset::total_balance(&0, &0), 0); }); } @@ -323,19 +301,16 @@ fn total_balance_should_be_equal_to_account_balance() { mint: Owner::Address(1), burn: Owner::Address(1), }; - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - assert_ok!(GenericAsset::create( - Origin::signed(1), - AssetOptions { - initial_issuance: 100, - permissions: default_permission - } - )); - assert_eq!(GenericAsset::total_balance(&1000, &1), 100); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + assert_ok!(GenericAsset::create( + Origin::signed(1), + AssetOptions { + initial_issuance: 100, + permissions: default_permission + } + )); + assert_eq!(GenericAsset::total_balance(&1000, &1), 100); + }); } // Given @@ -348,7 +323,7 @@ fn total_balance_should_be_equal_to_account_balance() { // -Â free_balance should return 50. #[test] fn free_balance_should_only_return_account_free_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 50)).build(), || { + ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 70); assert_eq!(GenericAsset::free_balance(&1, &0), 50); }); @@ -363,7 +338,7 @@ fn free_balance_should_only_return_account_free_balance() { // -Â total_balance should equals to account balance + free balance. #[test] fn total_balance_should_be_equal_to_sum_of_account_balance_and_free_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 50)).build(), || { + ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 70); assert_eq!(GenericAsset::total_balance(&1, &0), 120); }); @@ -378,7 +353,7 @@ fn total_balance_should_be_equal_to_sum_of_account_balance_and_free_balance() { // - reserved_balance should return 70. #[test] fn reserved_balance_should_only_return_account_reserved_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 50)).build(), || { + ExtBuilder::default().free_balance((1, 0, 50)).build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 70); assert_eq!(GenericAsset::reserved_balance(&1, &0), 70); }); @@ -394,7 +369,7 @@ fn reserved_balance_should_only_return_account_reserved_balance() { // - reserved_balance = amount #[test] fn set_reserved_balance_should_add_balance_as_reserved() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 50); assert_eq!(GenericAsset::reserved_balance(&1, &0), 50); }); @@ -410,7 +385,7 @@ fn set_reserved_balance_should_add_balance_as_reserved() { // - New free_balance should replace older free_balance. #[test] fn set_free_balance_should_add_amount_as_free_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { GenericAsset::set_free_balance(&1, &0, 50); assert_eq!(GenericAsset::free_balance(&1, &0), 50); }); @@ -429,7 +404,7 @@ fn set_free_balance_should_add_amount_as_free_balance() { // - new reserved_balance = original free balance + reserved amount #[test] fn reserve_should_moves_amount_from_balance_to_reserved_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { assert_ok!(GenericAsset::reserve(&1, &0, 70)); assert_eq!(GenericAsset::free_balance(&1, &0), 30); assert_eq!(GenericAsset::reserved_balance(&1, &0), 70); @@ -448,7 +423,7 @@ fn reserve_should_moves_amount_from_balance_to_reserved_balance() { // - Should throw an error. #[test] fn reserve_should_not_moves_amount_from_balance_to_reserved_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { assert_noop!(GenericAsset::reserve(&1, &0, 120), "not enough free funds"); assert_eq!(GenericAsset::free_balance(&1, &0), 100); assert_eq!(GenericAsset::reserved_balance(&1, &0), 0); @@ -466,7 +441,7 @@ fn reserve_should_not_moves_amount_from_balance_to_reserved_balance() { // - unreserved should return 20. #[test] fn unreserve_should_return_substratced_value_from_unreserved_amount_by_actual_acount_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); assert_eq!(GenericAsset::unreserve(&1, &0, 120), 20); }); @@ -483,7 +458,7 @@ fn unreserve_should_return_substratced_value_from_unreserved_amount_by_actual_ac // - unreserved should return None. #[test] fn unreserve_should_return_none() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); assert_eq!(GenericAsset::unreserve(&1, &0, 50), 0); }); @@ -500,7 +475,7 @@ fn unreserve_should_return_none() { // - free_balance should be 200. #[test] fn unreserve_should_increase_free_balance_by_reserved_balance() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); GenericAsset::unreserve(&1, &0, 120); assert_eq!(GenericAsset::free_balance(&1, &0), 200); @@ -518,7 +493,7 @@ fn unreserve_should_increase_free_balance_by_reserved_balance() { // - reserved_balance should be 0. #[test] fn unreserve_should_deduct_reserved_balance_by_reserved_amount() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { GenericAsset::set_free_balance(&1, &0, 100); GenericAsset::unreserve(&1, &0, 120); assert_eq!(GenericAsset::reserved_balance(&1, &0), 0); @@ -536,7 +511,7 @@ fn unreserve_should_deduct_reserved_balance_by_reserved_amount() { // - slash should return None. #[test] fn slash_should_return_slash_reserved_amount() { - with_externalities(&mut ExtBuilder::default().free_balance((1, 0, 100)).build(), || { + ExtBuilder::default().free_balance((1, 0, 100)).build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); assert_eq!(GenericAsset::slash(&1, &0, 70), None); }); @@ -550,7 +525,7 @@ fn slash_should_return_slash_reserved_amount() { // - Should return slashed_reserved - reserved_balance. #[test] fn slash_reserved_should_deducts_up_to_amount_from_reserved_balance() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); assert_eq!(GenericAsset::slash_reserved(&1, &0, 150), Some(50)); }); @@ -564,7 +539,7 @@ fn slash_reserved_should_deducts_up_to_amount_from_reserved_balance() { // - Should return None. #[test] fn slash_reserved_should_return_none() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); assert_eq!(GenericAsset::slash_reserved(&1, &0, 100), None); }); @@ -579,7 +554,7 @@ fn slash_reserved_should_return_none() { // - Should not return None. #[test] fn repatriate_reserved_return_amount_substracted_by_slash_amount() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); assert_eq!(GenericAsset::repatriate_reserved(&1, &0, &1, 130), 30); }); @@ -594,7 +569,7 @@ fn repatriate_reserved_return_amount_substracted_by_slash_amount() { // - Should return None. #[test] fn repatriate_reserved_return_none() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { GenericAsset::set_reserved_balance(&1, &0, 100); assert_eq!(GenericAsset::repatriate_reserved(&1, &0, &1, 90), 0); }); @@ -608,7 +583,7 @@ fn repatriate_reserved_return_none() { // - Should create a new reserved asset. #[test] fn create_reserved_should_create_a_default_account_with_the_balance_given() { - with_externalities(&mut ExtBuilder::default().next_asset_id(10).build(), || { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { let default_permission = PermissionLatest { update: Owner::Address(1), mint: Owner::Address(1), @@ -643,7 +618,7 @@ fn create_reserved_should_create_a_default_account_with_the_balance_given() { // - Should throw a permission error #[test] fn mint_should_throw_permission_error() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { let origin = 1; let asset_id = 4; let to_account = 2; @@ -666,36 +641,33 @@ fn mint_should_throw_permission_error() { // - Should not change `origins` free_balance. #[test] fn mint_should_increase_asset() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let origin = 1; - let asset_id = 1000; - let to_account = 2; - let amount = 500; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let to_account = 2; + let amount = 500; + let initial_issuance = 100; - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; - assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); - assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), amount); + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); - // Origin's free_balance should not change. - assert_eq!(GenericAsset::free_balance(&asset_id, &origin), initial_issuance); - }, - ); + assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); + assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), amount); + + // Origin's free_balance should not change. + assert_eq!(GenericAsset::free_balance(&asset_id, &origin), initial_issuance); + }); } // Given @@ -707,20 +679,17 @@ fn mint_should_increase_asset() { // - Should throw a permission error. #[test] fn burn_should_throw_permission_error() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let origin = 1; - let asset_id = 4; - let to_account = 2; - let amount = 10; - - assert_noop!( - GenericAsset::burn(Origin::signed(origin), asset_id, to_account, amount), - "The origin does not have permission to burn an asset." - ); - }, - ); + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 4; + let to_account = 2; + let amount = 10; + + assert_noop!( + GenericAsset::burn(Origin::signed(origin), asset_id, to_account, amount), + "The origin does not have permission to burn an asset." + ); + }); } // Given @@ -733,41 +702,38 @@ fn burn_should_throw_permission_error() { // - Should not change `origin`'s free_balance. #[test] fn burn_should_burn_an_asset() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let origin = 1; - let asset_id = 1000; - let to_account = 2; - let amount = 1000; - let initial_issuance = 100; - let burn_amount = 400; - let expected_amount = 600; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let to_account = 2; + let amount = 1000; + let initial_issuance = 100; + let burn_amount = 400; + let expected_amount = 600; - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); - assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; - assert_ok!(GenericAsset::burn( - Origin::signed(origin), - asset_id, - to_account, - burn_amount - )); - assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), expected_amount); - }, - ); + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to_account, amount)); + + assert_ok!(GenericAsset::burn( + Origin::signed(origin), + asset_id, + to_account, + burn_amount + )); + assert_eq!(GenericAsset::free_balance(&asset_id, &to_account), expected_amount); + }); } // Given @@ -779,41 +745,29 @@ fn burn_should_burn_an_asset() { // - The account origin should have burn, mint and update permissions. #[test] fn check_permission_should_return_correct_permission() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::Address(origin), - }; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::Address(origin), + }; - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn), - true - ); - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint), - true - ); - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update), - true - ); - }, - ); + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + }, + )); + + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update)); + }); } // Given @@ -825,41 +779,29 @@ fn check_permission_should_return_correct_permission() { // - The account origin should not have burn, mint and update permissions. #[test] fn check_permission_should_return_false_for_no_permission() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::None, - mint: Owner::None, - burn: Owner::None, - }; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); + let default_permission = PermissionLatest { + update: Owner::None, + mint: Owner::None, + burn: Owner::None, + }; - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn), - false - ); - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint), - false - ); - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update), - false - ); - }, - ); + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Update)); + }); } // Given @@ -871,48 +813,39 @@ fn check_permission_should_return_false_for_no_permission() { // - The account origin should have update and mint permissions. #[test] fn update_permission_should_change_permission() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::None, - burn: Owner::None, - }; - - let new_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::None, - }; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); + let default_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::None, + burn: Owner::None, + }; - assert_ok!(GenericAsset::update_permission( - Origin::signed(origin), - asset_id, - new_permission - )); - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint), - true - ); - assert_eq!( - GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn), - false - ); - }, - ); + let new_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::None, + }; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + } + )); + + assert_ok!(GenericAsset::update_permission( + Origin::signed(origin), + asset_id, + new_permission, + )); + assert!(GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Mint)); + assert!(!GenericAsset::check_permission(&asset_id, &origin, &PermissionType::Burn)); + }); } // Given @@ -923,41 +856,38 @@ fn update_permission_should_change_permission() { // - Should throw an error stating "Origin does not have enough permission to update permissions." #[test] fn update_permission_should_throw_error_when_lack_of_permissions() { - with_externalities( - &mut ExtBuilder::default().free_balance((16000, 1, 100000)).build(), - || { - let origin = 1; - let asset_id = 1000; - let initial_issuance = 100; - - let default_permission = PermissionLatest { - update: Owner::None, - mint: Owner::None, - burn: Owner::None, - }; - - let new_permission = PermissionLatest { - update: Owner::Address(origin), - mint: Owner::Address(origin), - burn: Owner::None, - }; - - let expected_error_message = "Origin does not have enough permission to update permissions."; + ExtBuilder::default().free_balance((16000, 1, 100000)).build().execute_with(|| { + let origin = 1; + let asset_id = 1000; + let initial_issuance = 100; - assert_ok!(GenericAsset::create( - Origin::signed(origin), - AssetOptions { - initial_issuance: initial_issuance, - permissions: default_permission - } - )); + let default_permission = PermissionLatest { + update: Owner::None, + mint: Owner::None, + burn: Owner::None, + }; - assert_noop!( - GenericAsset::update_permission(Origin::signed(origin), asset_id, new_permission), - expected_error_message - ); - }, - ); + let new_permission = PermissionLatest { + update: Owner::Address(origin), + mint: Owner::Address(origin), + burn: Owner::None, + }; + + let expected_error_message = "Origin does not have enough permission to update permissions."; + + assert_ok!(GenericAsset::create( + Origin::signed(origin), + AssetOptions { + initial_issuance: initial_issuance, + permissions: default_permission + }, + )); + + assert_noop!( + GenericAsset::update_permission(Origin::signed(origin), asset_id, new_permission), + expected_error_message, + ); + }); } // Given @@ -974,7 +904,7 @@ fn update_permission_should_throw_error_when_lack_of_permissions() { // - Permissions must have burn, mint and updatePermission for the given asset_id. #[test] fn create_asset_works_with_given_asset_id_and_from_account() { - with_externalities(&mut ExtBuilder::default().next_asset_id(10).build(), || { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { let origin = 1; let from_account: Option<::AccountId> = Some(1); @@ -1011,7 +941,7 @@ fn create_asset_works_with_given_asset_id_and_from_account() { // - `create_asset` should not work. #[test] fn create_asset_with_non_reserved_asset_id_should_not_work() { - with_externalities(&mut ExtBuilder::default().next_asset_id(10).build(), || { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { let origin = 1; let from_account: Option<::AccountId> = Some(1); @@ -1045,7 +975,7 @@ fn create_asset_with_non_reserved_asset_id_should_not_work() { // - `create_asset` should not work. #[test] fn create_asset_with_a_taken_asset_id_should_not_work() { - with_externalities(&mut ExtBuilder::default().next_asset_id(10).build(), || { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { let origin = 1; let from_account: Option<::AccountId> = Some(1); @@ -1090,7 +1020,7 @@ fn create_asset_with_a_taken_asset_id_should_not_work() { // - Should create a reserved token. #[test] fn create_asset_should_create_a_reserved_asset_when_from_account_is_none() { - with_externalities(&mut ExtBuilder::default().next_asset_id(10).build(), || { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { let origin = 1; let from_account: Option<::AccountId> = None; @@ -1133,7 +1063,7 @@ fn create_asset_should_create_a_reserved_asset_when_from_account_is_none() { // - Should not create a `reserved_asset`. #[test] fn create_asset_should_create_a_user_asset() { - with_externalities(&mut ExtBuilder::default().next_asset_id(10).build(), || { + ExtBuilder::default().next_asset_id(10).build().execute_with(|| { let origin = 1; let from_account: Option<::AccountId> = None; @@ -1180,12 +1110,11 @@ fn update_permission_should_raise_event() { burn: Owner::Address(origin), }; - with_externalities( - &mut ExtBuilder::default() - .next_asset_id(asset_id) - .free_balance((staking_asset_id, origin, initial_balance)) - .build(), - || { + ExtBuilder::default() + .next_asset_id(asset_id) + .free_balance((staking_asset_id, origin, initial_balance)) + .build() + .execute_with(|| { assert_ok!(GenericAsset::create( Origin::signed(origin), AssetOptions { @@ -1201,9 +1130,11 @@ fn update_permission_should_raise_event() { permissions.clone() )); + let expected_event = TestEvent::generic_asset( + RawEvent::PermissionUpdated(asset_id, permissions.clone()), + ); // Assert - assert!(System::events().iter().any(|record| record.event - == TestEvent::generic_asset(RawEvent::PermissionUpdated(asset_id, permissions.clone())))); + assert!(System::events().iter().any(|record| record.event == expected_event)); }, ); } @@ -1223,27 +1154,26 @@ fn mint_should_raise_event() { let to = 2; let amount = 100; - with_externalities( - &mut ExtBuilder::default() - .next_asset_id(asset_id) - .free_balance((staking_asset_id, origin, initial_balance)) - .build(), - || { + ExtBuilder::default() + .next_asset_id(asset_id) + .free_balance((staking_asset_id, origin, initial_balance)) + .build() + .execute_with(|| { assert_ok!(GenericAsset::create( Origin::signed(origin), AssetOptions { initial_issuance: 0, permissions: permissions.clone(), - } + }, )); // Act assert_ok!(GenericAsset::mint(Origin::signed(origin), asset_id, to, amount)); + let expected_event = TestEvent::generic_asset(RawEvent::Minted(asset_id, to, amount)); + // Assert - assert!(System::events() - .iter() - .any(|record| record.event == TestEvent::generic_asset(RawEvent::Minted(asset_id, to, amount)))); + assert!(System::events().iter().any(|record| record.event == expected_event)); }, ); } @@ -1262,27 +1192,26 @@ fn burn_should_raise_event() { }; let amount = 100; - with_externalities( - &mut ExtBuilder::default() - .next_asset_id(asset_id) - .free_balance((staking_asset_id, origin, initial_balance)) - .build(), - || { + ExtBuilder::default() + .next_asset_id(asset_id) + .free_balance((staking_asset_id, origin, initial_balance)) + .build() + .execute_with(|| { assert_ok!(GenericAsset::create( Origin::signed(origin), AssetOptions { initial_issuance: amount, permissions: permissions.clone(), - } + }, )); // Act assert_ok!(GenericAsset::burn(Origin::signed(origin), asset_id, origin, amount)); + let expected_event = TestEvent::generic_asset(RawEvent::Burned(asset_id, origin, amount)); + // Assert - assert!(System::events() - .iter() - .any(|record| record.event == TestEvent::generic_asset(RawEvent::Burned(asset_id, origin, amount)))); + assert!(System::events().iter().any(|record| record.event == expected_event)); }, ); } diff --git a/srml/grandpa/Cargo.toml b/srml/grandpa/Cargo.toml index 2466b8e012ec538238fa38bc241cf7668dc58acc..4b494cfeff8d11979116deb598d03dc5920f690e 100644 --- a/srml/grandpa/Cargo.toml +++ b/srml/grandpa/Cargo.toml @@ -5,19 +5,20 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } substrate-finality-grandpa-primitives = { path = "../../core/finality-grandpa/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } session = { package = "srml-session", path = "../session", default-features = false } finality-tracker = { package = "srml-finality-tracker", path = "../finality-tracker", default-features = false } [dev-dependencies] -runtime_io = { package = "sr-io", path = "../../core/sr-io" } +runtime-io ={ package = "sr-io", path = "../../core/sr-io" } [features] default = ["std"] @@ -27,8 +28,9 @@ std = [ "primitives/std", "substrate-finality-grandpa-primitives/std", "rstd/std", - "srml-support/std", + "support/std", "sr-primitives/std", + "sr-staking-primitives/std", "system/std", "session/std", "finality-tracker/std", diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs index 3f4b26c17d74cf6debd807072b04018f4fe0d352..f3e876f2c4e0e681cac3cc06b0ce5df3c12d48f8 100644 --- a/srml/grandpa/src/lib.rs +++ b/srml/grandpa/src/lib.rs @@ -32,13 +32,17 @@ pub use substrate_finality_grandpa_primitives as fg_primitives; use rstd::prelude::*; use codec::{self as codec, Encode, Decode, Error}; -use srml_support::{ - decl_event, decl_storage, decl_module, dispatch::Result, storage::StorageValue +use support::{ + decl_event, decl_storage, decl_module, dispatch::Result, }; use sr_primitives::{ - generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, + generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, Perbill, }; -use fg_primitives::{ScheduledChange, ConsensusLog, GRANDPA_ENGINE_ID}; +use sr_staking_primitives::{ + SessionIndex, + offence::{Offence, Kind}, +}; +use fg_primitives::{GRANDPA_ENGINE_ID, ScheduledChange, ConsensusLog, SetId, RoundNumber}; pub use fg_primitives::{AuthorityId, AuthorityWeight}; use system::{ensure_signed, DigestOf}; @@ -60,7 +64,7 @@ pub struct OldStoredPendingChange { /// The delay in blocks until it will be applied. pub delay: N, /// The next authority set. - pub next_authorities: Vec<(AuthorityId, u64)>, + pub next_authorities: Vec<(AuthorityId, AuthorityWeight)>, } /// A stored pending change. @@ -71,7 +75,7 @@ pub struct StoredPendingChange { /// The delay in blocks until it will be applied. pub delay: N, /// The next authority set. - pub next_authorities: Vec<(AuthorityId, u64)>, + pub next_authorities: Vec<(AuthorityId, AuthorityWeight)>, /// If defined it means the change was forced and the given block number /// indicates the median last finalized block when the change was signaled. pub forced: Option, @@ -122,7 +126,7 @@ pub enum StoredState { decl_event!( pub enum Event { /// New authority set has been applied. - NewAuthorities(Vec<(AuthorityId, u64)>), + NewAuthorities(Vec<(AuthorityId, AuthorityWeight)>), /// Current authority set has been paused. Paused, /// Current authority set has been resumed. @@ -133,19 +137,30 @@ decl_event!( decl_storage! { trait Store for Module as GrandpaFinality { /// The current authority set. - Authorities get(authorities) config(): Vec<(AuthorityId, AuthorityWeight)>; + Authorities get(fn authorities): Vec<(AuthorityId, AuthorityWeight)>; /// State of the current authority set. - State get(state): StoredState = StoredState::Live; + State get(fn state): StoredState = StoredState::Live; /// Pending change: (signaled at, scheduled change). PendingChange: Option>; /// next block number where we can force a change. - NextForced get(next_forced): Option; + NextForced get(fn next_forced): Option; /// `true` if we are currently stalled. - Stalled get(stalled): Option<(T::BlockNumber, T::BlockNumber)>; + Stalled get(fn stalled): Option<(T::BlockNumber, T::BlockNumber)>; + + /// The number of changes (both in terms of keys and underlying economic responsibilities) + /// in the "set" of Grandpa validators from genesis. + CurrentSetId get(fn current_set_id) build(|_| fg_primitives::SetId::default()): SetId; + + /// A mapping from grandpa set ID to the index of the *most recent* session for which its members were responsible. + SetIdSession get(fn session_for_set): map SetId => Option; + } + add_extra_genesis { + config(authorities): Vec<(AuthorityId, AuthorityWeight)>; + build(|config| Module::::initialize_authorities(&config.authorities)) } } @@ -226,10 +241,12 @@ decl_module! { impl Module { /// Get the current set of authorities, along with their respective weights. - pub fn grandpa_authorities() -> Vec<(AuthorityId, u64)> { + pub fn grandpa_authorities() -> Vec<(AuthorityId, AuthorityWeight)> { Authorities::get() } + /// Schedule GRANDPA to pause starting in the given number of blocks. + /// Cannot be done when already paused. pub fn schedule_pause(in_blocks: T::BlockNumber) -> Result { if let StoredState::Live = >::get() { let scheduled_at = >::block_number(); @@ -245,6 +262,7 @@ impl Module { } } + /// Schedule a resume of GRANDPA after pausing. pub fn schedule_resume(in_blocks: T::BlockNumber) -> Result { if let StoredState::Paused = >::get() { let scheduled_at = >::block_number(); @@ -275,7 +293,7 @@ impl Module { /// No change should be signaled while any change is pending. Returns /// an error if a change is already pending. pub fn schedule_change( - next_authorities: Vec<(AuthorityId, u64)>, + next_authorities: Vec<(AuthorityId, AuthorityWeight)>, in_blocks: T::BlockNumber, forced: Option, ) -> Result { @@ -310,32 +328,44 @@ impl Module { let log: DigestItem = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()); >::deposit_log(log.into()); } + + fn initialize_authorities(authorities: &[(AuthorityId, AuthorityWeight)]) { + if !authorities.is_empty() { + assert!(Authorities::get().is_empty(), "Authorities are already initialized!"); + Authorities::put(authorities); + } + } } impl Module { + /// Attempt to extract a GRANDPA log from a generic digest. pub fn grandpa_log(digest: &DigestOf) -> Option> { let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); digest.convert_first(|l| l.try_to::>(id)) } + /// Attempt to extract a pending set-change signal from a digest. pub fn pending_change(digest: &DigestOf) -> Option> { Self::grandpa_log(digest).and_then(|signal| signal.try_into_change()) } + /// Attempt to extract a forced set-change signal from a digest. pub fn forced_change(digest: &DigestOf) -> Option<(T::BlockNumber, ScheduledChange)> { Self::grandpa_log(digest).and_then(|signal| signal.try_into_forced_change()) } + /// Attempt to extract a pause signal from a digest. pub fn pending_pause(digest: &DigestOf) -> Option { Self::grandpa_log(digest).and_then(|signal| signal.try_into_pause()) } + /// Attempt to extract a resume signal from a digest. pub fn pending_resume(digest: &DigestOf) -> Option { @@ -343,24 +373,46 @@ impl Module { } } -impl session::OneSessionHandler for Module { +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = AuthorityId; +} + +impl session::OneSessionHandler for Module + where T: session::Trait +{ type Key = AuthorityId; + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + Self::initialize_authorities(&authorities); + } + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) where I: Iterator { - // instant changes - if changed { - let next_authorities = validators.map(|(_, k)| (k, 1u64)).collect::>(); - let last_authorities = >::grandpa_authorities(); - if next_authorities != last_authorities { - if let Some((further_wait, median)) = >::take() { - let _ = Self::schedule_change(next_authorities, further_wait, Some(median)); - } else { - let _ = Self::schedule_change(next_authorities, Zero::zero(), None); - } + // Always issue a change if `session` says that the validators have changed. + // Even if their session keys are the same as before, the underyling economic + // identities have changed. + let current_set_id = if changed { + let next_authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + if let Some((further_wait, median)) = >::take() { + let _ = Self::schedule_change(next_authorities, further_wait, Some(median)); + } else { + let _ = Self::schedule_change(next_authorities, Zero::zero(), None); } - } + CurrentSetId::mutate(|s| { *s += 1; *s }) + } else { + // nothing's changed, neither economic conditions nor session keys. update the pointer + // of the current set. + Self::current_set_id() + }; + + // if we didn't issue a change, we update the mapping to note that the current + // set corresponds to the latest equivalent session (i.e. now). + let session_index = >::current_index(); + SetIdSession::insert(current_set_id, &session_index); } fn on_disabled(i: usize) { @@ -376,3 +428,56 @@ impl finality_tracker::OnFinalizationStalled for Modul >::put((further_wait, median)); } } + +/// A round number and set id which point on the time of an offence. +#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Encode, Decode)] +struct GrandpaTimeSlot { + // The order of these matters for `derive(Ord)`. + set_id: SetId, + round: RoundNumber, +} + +// TODO [slashing]: Integrate this. +/// A grandpa equivocation offence report. +#[allow(dead_code)] +struct GrandpaEquivocationOffence { + /// Time slot at which this incident happened. + time_slot: GrandpaTimeSlot, + /// The session index in which the incident happened. + session_index: SessionIndex, + /// The size of the validator set at the time of the offence. + validator_set_count: u32, + /// The authority which produced this equivocation. + offender: FullIdentification, +} + +impl Offence for GrandpaEquivocationOffence { + const ID: Kind = *b"grandpa:equivoca"; + type TimeSlot = GrandpaTimeSlot; + + fn offenders(&self) -> Vec { + vec![self.offender.clone()] + } + + fn session_index(&self) -> SessionIndex { + self.session_index + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> Self::TimeSlot { + self.time_slot + } + + fn slash_fraction( + offenders_count: u32, + validator_set_count: u32, + ) -> Perbill { + // the formula is min((3k / n)^2, 1) + let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count); + // _ ^ 2 + x.square() + } +} diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs index e3c53510deae48f900c078208732ae76ee36a3bc..fcacbade20490e19c961ddcfa7d94ba1b216322a 100644 --- a/srml/grandpa/src/mock.rs +++ b/srml/grandpa/src/mock.rs @@ -20,8 +20,8 @@ use sr_primitives::{Perbill, DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; use runtime_io; -use srml_support::{impl_outer_origin, impl_outer_event, parameter_types}; -use primitives::{H256, Blake2Hasher}; +use support::{impl_outer_origin, impl_outer_event, parameter_types}; +use primitives::H256; use codec::{Encode, Decode}; use crate::{AuthorityId, GenesisConfig, Trait, Module, ConsensusLog}; use substrate_finality_grandpa_primitives::GRANDPA_ENGINE_ID; @@ -37,9 +37,9 @@ pub fn grandpa_log(log: ConsensusLog) -> DigestItem { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Decode, Encode)] pub struct Test; + impl Trait for Test { type Event = TestEvent; - } parameter_types! { pub const BlockHashCount: u64 = 250; @@ -53,16 +53,16 @@ impl system::Trait for Test { type BlockNumber = u64; type Call = (); type Hash = H256; - type Hashing = ::sr_primitives::traits::BlakeTwo256; + type Hashing = sr_primitives::traits::BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = TestEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } mod grandpa { @@ -81,11 +81,11 @@ pub fn to_authorities(vec: Vec<(u64, u64)>) -> Vec<(AuthorityId, u64)> { .collect() } -pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> runtime_io::TestExternalities { +pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig { authorities: to_authorities(authorities), - }.assimilate_storage(&mut t).unwrap(); + }.assimilate_storage::(&mut t).unwrap(); t.into() } diff --git a/srml/grandpa/src/tests.rs b/srml/grandpa/src/tests.rs index adef602ce6f185ff4e0cdaef3ef929a9c57cd0e6..2efeb4b5bf3cfc87f69763ef1e07b5a56b3421f2 100644 --- a/srml/grandpa/src/tests.rs +++ b/srml/grandpa/src/tests.rs @@ -18,9 +18,7 @@ #![cfg(test)] -use sr_primitives::testing::Digest; -use sr_primitives::traits::{Header, OnFinalize}; -use runtime_io::with_externalities; +use sr_primitives::{testing::Digest, traits::{Header, OnFinalize}}; use crate::mock::*; use system::{EventRecord, Phase}; use codec::{Decode, Encode}; @@ -29,7 +27,7 @@ use super::*; #[test] fn authorities_change_logged() { - with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 0, None).unwrap(); @@ -57,7 +55,7 @@ fn authorities_change_logged() { #[test] fn authorities_change_logged_after_delay() { - with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap(); Grandpa::on_finalize(1); @@ -90,7 +88,7 @@ fn authorities_change_logged_after_delay() { #[test] fn cannot_schedule_change_when_one_pending() { - with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap(); assert!(>::exists()); @@ -133,7 +131,7 @@ fn new_decodes_from_old() { #[test] fn dispatch_forced_change() { - with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_change( to_authorities(vec![(4, 1), (5, 1), (6, 1)]), @@ -205,7 +203,7 @@ fn dispatch_forced_change() { #[test] fn schedule_pause_only_when_live() { - with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { // we schedule a pause at block 1 with delay of 1 System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); Grandpa::schedule_pause(1).unwrap(); @@ -240,7 +238,7 @@ fn schedule_pause_only_when_live() { #[test] fn schedule_resume_only_when_paused() { - with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || { + new_test_ext(vec![(1, 1), (2, 1), (3, 1)]).execute_with(|| { System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); // the set is currently live, resuming it is an error @@ -282,3 +280,31 @@ fn schedule_resume_only_when_paused() { ); }); } + +#[test] +fn time_slot_have_sane_ord() { + // Ensure that `Ord` implementation is sane. + const FIXTURE: &[GrandpaTimeSlot] = &[ + GrandpaTimeSlot { + set_id: 0, + round: 0, + }, + GrandpaTimeSlot { + set_id: 0, + round: 1, + }, + GrandpaTimeSlot { + set_id: 1, + round: 0, + }, + GrandpaTimeSlot { + set_id: 1, + round: 1, + }, + GrandpaTimeSlot { + set_id: 1, + round: 2, + } + ]; + assert!(FIXTURE.windows(2).all(|f| f[0] < f[1])); +} diff --git a/srml/im-online/Cargo.toml b/srml/im-online/Cargo.toml index 8f0e4cc39fa825a6dd85bbcb9b17e76cff612059..4c7ccf1487d9b853495b4339ce1d9c471c310850 100644 --- a/srml/im-online/Cargo.toml +++ b/srml/im-online/Cargo.toml @@ -5,27 +5,35 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sr-primitives = { path = "../../core/sr-primitives", default-features = false } -primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } +authorship = { package = "srml-authorship", path = "../authorship", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +primitives = { package="substrate-primitives", path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } session = { package = "srml-session", path = "../session", default-features = false } -srml-support = { path = "../support", default-features = false } -sr-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } +[dev-dependencies] +offchain = { package = "substrate-offchain", path = "../../core/offchain" } + [features] -default = ["std"] +default = ["std", "session/historical"] std = [ + "app-crypto/std", + "authorship/std", "codec/std", - "sr-primitives/std", + "primitives/std", "rstd/std", "serde", "session/std", - "srml-support/std", - "sr-io/std", + "runtime-io/std", + "sr-primitives/std", + "sr-staking-primitives/std", + "support/std", "system/std", - "app-crypto/std", ] diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index eff811d6cacf386ec680e41b21484521bebc35f4..3d8cf99bc5fca0c17aa0291fff7423d2321549b6 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -37,12 +37,12 @@ //! //! ### Public Functions //! -//! - `is_online_in_current_session` - True if the validator sent a heartbeat in the current session. +//! - `is_online` - True if the validator sent a heartbeat in the current session. //! //! ## Usage //! //! ``` -//! use srml_support::{decl_module, dispatch::Result}; +//! use support::{decl_module, dispatch::Result}; //! use system::ensure_signed; //! use srml_im_online::{self as im_online}; //! @@ -52,7 +52,7 @@ //! pub struct Module for enum Call where origin: T::Origin { //! pub fn is_online(origin, authority_index: u32) -> Result { //! let _sender = ensure_signed(origin)?; -//! let _is_online = >::is_online_in_current_session(authority_index); +//! let _is_online = >::is_online(authority_index); //! Ok(()) //! } //! } @@ -67,70 +67,96 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use primitives::offchain::{OpaqueNetworkState, StorageKind}; +mod mock; +mod tests; + +use app_crypto::RuntimeAppPublic; use codec::{Encode, Decode}; +use primitives::offchain::{OpaqueNetworkState, StorageKind}; +use rstd::prelude::*; +use rstd::convert::TryInto; +use session::historical::IdentificationTuple; use sr_primitives::{ - ApplyError, traits::{Extrinsic as ExtrinsicT}, - transaction_validity::{TransactionValidity, TransactionLongevity, ValidTransaction}, + RuntimeDebug, + traits::{Convert, Member, Printable, Saturating}, Perbill, + transaction_validity::{ + TransactionValidity, ValidTransaction, InvalidTransaction, + TransactionPriority, + }, }; -use rstd::prelude::*; -use session::SessionIndex; -use sr_io::Printable; -use srml_support::{ - StorageValue, decl_module, decl_event, decl_storage, StorageDoubleMap, print, +use sr_staking_primitives::{ + SessionIndex, + offence::{ReportOffence, Offence, Kind}, +}; +use support::{ + decl_module, decl_event, decl_storage, print, Parameter, debug, + traits::Get, }; use system::ensure_none; -use app_crypto::RuntimeAppPublic; +use system::offchain::SubmitUnsignedTransaction; + +pub mod sr25519 { + mod app_sr25519 { + use app_crypto::{app_crypto, key_types::IM_ONLINE, sr25519}; + app_crypto!(sr25519, IM_ONLINE); + } -mod app { - pub use app_crypto::sr25519 as crypto; - use app_crypto::{app_crypto, key_types::IM_ONLINE, sr25519}; + /// An i'm online keypair using sr25519 as its crypto. + #[cfg(feature = "std")] + pub type AuthorityPair = app_sr25519::Pair; - app_crypto!(sr25519, IM_ONLINE); + /// An i'm online signature using sr25519 as its crypto. + pub type AuthoritySignature = app_sr25519::Signature; + + /// An i'm online identifier using sr25519 as its crypto. + pub type AuthorityId = app_sr25519::Public; } -/// A Babe authority keypair. Necessarily equivalent to the schnorrkel public key used in -/// the main Babe module. If that ever changes, then this must, too. -#[cfg(feature = "std")] -pub type AuthorityPair = app::Pair; +pub mod ed25519 { + mod app_ed25519 { + use app_crypto::{app_crypto, key_types::IM_ONLINE, ed25519}; + app_crypto!(ed25519, IM_ONLINE); + } -/// A Babe authority signature. -pub type AuthoritySignature = app::Signature; + /// An i'm online keypair using ed25519 as its crypto. + #[cfg(feature = "std")] + pub type AuthorityPair = app_ed25519::Pair; -/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in -/// the main Babe module. If that ever changes, then this must, too. -pub type AuthorityId = app::Public; + /// An i'm online signature using ed25519 as its crypto. + pub type AuthoritySignature = app_ed25519::Signature; -// The local storage database key under which the worker progress status -// is tracked. + /// An i'm online identifier using ed25519 as its crypto. + pub type AuthorityId = app_ed25519::Public; +} + +/// The local storage database key under which the worker progress status +/// is tracked. const DB_KEY: &[u8] = b"srml/im-online-worker-status"; -// It's important to persist the worker state, since e.g. the -// server could be restarted while starting the gossip process, but before -// finishing it. With every execution of the off-chain worker we check -// if we need to recover and resume gossipping or if there is already -// another off-chain worker in the process of gossipping. -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +/// It's important to persist the worker state, since e.g. the +/// server could be restarted while starting the gossip process, but before +/// finishing it. With every execution of the off-chain worker we check +/// if we need to recover and resume gossipping or if there is already +/// another off-chain worker in the process of gossipping. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] struct WorkerStatus { done: bool, gossipping_at: BlockNumber, } -// Error which may occur while executing the off-chain code. +/// Error which may occur while executing the off-chain code. +#[derive(RuntimeDebug)] enum OffchainErr { DecodeWorkerStatus, - ExtrinsicCreation, FailedSigning, NetworkState, SubmitTransaction, } impl Printable for OffchainErr { - fn print(self) { + fn print(&self) { match self { OffchainErr::DecodeWorkerStatus => print("Offchain error: decoding WorkerStatus failed!"), - OffchainErr::ExtrinsicCreation => print("Offchain error: extrinsic creation failed!"), OffchainErr::FailedSigning => print("Offchain error: signing failed!"), OffchainErr::NetworkState => print("Offchain error: fetching network state failed!"), OffchainErr::SubmitTransaction => print("Offchain error: submitting transaction failed!"), @@ -141,8 +167,7 @@ impl Printable for OffchainErr { pub type AuthIndex = u32; /// Heartbeat which is sent/received. -#[derive(Encode, Decode, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct Heartbeat where BlockNumber: PartialEq + Eq + Decode + Encode, { @@ -152,37 +177,69 @@ pub struct Heartbeat authority_index: AuthIndex, } -pub trait Trait: system::Trait + session::Trait { +pub trait Trait: system::Trait + session::historical::Trait { + /// The identifier type for an authority. + type AuthorityId: Member + Parameter + RuntimeAppPublic + Default + Ord; + /// The overarching event type. - type Event: From + Into<::Event>; + type Event: From> + Into<::Event>; - /// The function call. + /// A dispatchable call type. type Call: From>; - /// A extrinsic right from the external world. This is unchecked and so - /// can contain a signature. - type UncheckedExtrinsic: ExtrinsicT::Call> + Encode + Decode; + /// A transaction submitter. + type SubmitTransaction: SubmitUnsignedTransaction::Call>; + + /// An expected duration of the session. + /// + /// This parameter is used to determine the longevity of `heartbeat` transaction + /// and a rough time when the heartbeat should be sent. + type SessionDuration: Get; + + /// A type that gives us the ability to submit unresponsiveness offence reports. + type ReportUnresponsiveness: + ReportOffence< + Self::AccountId, + IdentificationTuple, + UnresponsivenessOffence>, + >; } decl_event!( - pub enum Event { + pub enum Event where + ::AuthorityId, + IdentificationTuple = IdentificationTuple, + { /// A new heartbeat was received from `AuthorityId` HeartbeatReceived(AuthorityId), + /// At the end of the session, no offence was committed. + AllGood, + /// At the end of the session, at least once validator was found to be offline. + SomeOffline(Vec), } ); decl_storage! { trait Store for Module as ImOnline { /// The block number when we should gossip. - GossipAt get(gossip_at) config(): T::BlockNumber; + GossipAt get(fn gossip_at): T::BlockNumber; /// The current set of keys that may issue a heartbeat. - Keys get(keys) config(): Vec; + Keys get(fn keys): Vec; - /// For each session index we keep a mapping of `AuthorityId` + /// For each session index, we keep a mapping of `AuthIndex` /// to `offchain::OpaqueNetworkState`. - ReceivedHeartbeats get(received_heartbeats): double_map SessionIndex, - blake2_256(AuthIndex) => Vec; + ReceivedHeartbeats get(fn received_heartbeats): double_map SessionIndex, + blake2_256(AuthIndex) => Option>; + + /// For each session index, we keep a mapping of `T::ValidatorId` to the + /// number of blocks authored by the given authority. + AuthoredBlocks get(fn authored_blocks): double_map SessionIndex, + blake2_256(T::ValidatorId) => u32; + } + add_extra_genesis { + config(keys): Vec; + build(|config| Module::::initialize_keys(&config.keys)) } } @@ -194,7 +251,9 @@ decl_module! { fn heartbeat( origin, heartbeat: Heartbeat, - _signature: AuthoritySignature + // since signature verification is done in `validate_unsigned` + // we can skip doing it here again. + _signature: ::Signature ) { ensure_none(origin)?; @@ -203,10 +262,10 @@ decl_module! { ¤t_session, &heartbeat.authority_index ); - let keys = Keys::get(); + let keys = Keys::::get(); let public = keys.get(heartbeat.authority_index as usize); - if let (true, Some(public)) = (!exists, public) { - Self::deposit_event(Event::HeartbeatReceived(public.clone())); + if let (false, Some(public)) = (exists, public) { + Self::deposit_event(Event::::HeartbeatReceived(public.clone())); let network_state = heartbeat.network_state.encode(); ::insert( @@ -214,28 +273,83 @@ decl_module! { &heartbeat.authority_index, &network_state ); + } else if exists { + Err("Duplicated heartbeat.")? + } else { + Err("Non existent public key.")? } } // Runs after every block. fn offchain_worker(now: T::BlockNumber) { + debug::RuntimeLogger::init(); + // Only send messages if we are a potential validator. - if sr_io::is_validator() { + if runtime_io::is_validator() { Self::offchain(now); } } } } +/// Keep track of number of authored blocks per authority, uncles are counted as +/// well since they're a valid proof of onlineness. +impl authorship::EventHandler for Module { + fn note_author(author: T::ValidatorId) { + Self::note_authorship(author); + } + + fn note_uncle(author: T::ValidatorId, _age: T::BlockNumber) { + Self::note_authorship(author); + } +} + impl Module { + /// Returns `true` if a heartbeat has been received for the authority at + /// `authority_index` in the authorities series or if the authority has + /// authored at least one block, during the current session. Otherwise + /// `false`. + pub fn is_online(authority_index: AuthIndex) -> bool { + let current_validators = >::validators(); + + if authority_index >= current_validators.len() as u32 { + return false; + } + + let authority = ¤t_validators[authority_index as usize]; + + Self::is_online_aux(authority_index, authority) + } + + fn is_online_aux(authority_index: AuthIndex, authority: &T::ValidatorId) -> bool { + let current_session = >::current_index(); + + ::exists(¤t_session, &authority_index) || + >::get( + ¤t_session, + authority, + ) != 0 + } + /// Returns `true` if a heartbeat has been received for the authority at `authority_index` in /// the authorities series, during the current session. Otherwise `false`. - pub fn is_online_in_current_session(authority_index: AuthIndex) -> bool { + pub fn received_heartbeat_in_current_session(authority_index: AuthIndex) -> bool { let current_session = >::current_index(); ::exists(¤t_session, &authority_index) } - fn offchain(now: T::BlockNumber) { + /// Note that the given authority has authored a block in the current session. + fn note_authorship(author: T::ValidatorId) { + let current_session = >::current_index(); + + >::mutate( + ¤t_session, + author, + |authored| *authored += 1, + ); + } + + pub(crate) fn offchain(now: T::BlockNumber) { let next_gossip = >::get(); let check = Self::check_not_yet_gossipped(now, next_gossip); let (curr_worker_status, not_yet_gossipped) = match check { @@ -258,13 +372,22 @@ impl Module { Ok(_) => {}, Err(err) => print(err), } + } else { + debug::native::debug!( + target: "imonline", + "Skipping gossip at: {:?} >= {:?} || {:?}", + next_gossip, + now, + if not_yet_gossipped { "not gossipped" } else { "gossipped" } + ); } } fn do_gossip_at(block_number: T::BlockNumber) -> Result<(), OffchainErr> { // we run only when a local authority key is configured - let authorities = Keys::get(); - let mut local_keys = app::Public::all(); + let authorities = Keys::::get(); + let mut results = Vec::new(); + let mut local_keys = T::AuthorityId::all(); local_keys.sort(); for (authority_index, key) in authorities.into_iter() @@ -275,7 +398,17 @@ impl Module { .map(|location| (index as u32, &local_keys[location])) }) { - let network_state = sr_io::network_state().map_err(|_| OffchainErr::NetworkState)?; + if Self::is_online(authority_index) { + debug::native::info!( + target: "imonline", + "[index: {:?}] Skipping sending heartbeat at block: {:?}. Already online.", + authority_index, + block_number + ); + continue; + } + + let network_state = runtime_io::network_state().map_err(|_| OffchainErr::NetworkState)?; let heartbeat_data = Heartbeat { block_number, network_state, @@ -285,15 +418,28 @@ impl Module { let signature = key.sign(&heartbeat_data.encode()).ok_or(OffchainErr::FailedSigning)?; let call = Call::heartbeat(heartbeat_data, signature); - let ex = T::UncheckedExtrinsic::new_unsigned(call.into()) - .ok_or(OffchainErr::ExtrinsicCreation)?; - sr_io::submit_transaction(&ex).map_err(|_| OffchainErr::SubmitTransaction)?; - - // once finished we set the worker status without comparing - // if the existing value changed in the meantime. this is - // because at this point the heartbeat was definitely submitted. - Self::set_worker_status(block_number, true); + + debug::info!( + target: "imonline", + "[index: {:?}] Reporting im-online at block: {:?}", + authority_index, + block_number + ); + + results.push( + T::SubmitTransaction::submit_unsigned(call) + .map_err(|_| OffchainErr::SubmitTransaction) + ); } + + // fail only after trying all keys. + results.into_iter().collect::, OffchainErr>>()?; + + // once finished we set the worker status without comparing + // if the existing value changed in the meantime. this is + // because at this point the heartbeat was definitely submitted. + Self::set_worker_status(block_number, true); + Ok(()) } @@ -306,7 +452,7 @@ impl Module { done, gossipping_at, }; - sr_io::local_storage_compare_and_set( + runtime_io::local_storage_compare_and_set( StorageKind::PERSISTENT, DB_KEY, curr_worker_status.as_ref().map(Vec::as_slice), @@ -322,7 +468,7 @@ impl Module { done, gossipping_at, }; - sr_io::local_storage_set( + runtime_io::local_storage_set( StorageKind::PERSISTENT, DB_KEY, &enc.encode()); } @@ -333,7 +479,7 @@ impl Module { now: T::BlockNumber, next_gossip: T::BlockNumber, ) -> Result<(Option>, bool), OffchainErr> { - let last_gossip = sr_io::local_storage_get(StorageKind::PERSISTENT, DB_KEY); + let last_gossip = runtime_io::local_storage_get(StorageKind::PERSISTENT, DB_KEY); match last_gossip { Some(last) => { let worker_status: WorkerStatus = Decode::decode(&mut &last[..]) @@ -355,22 +501,69 @@ impl Module { } } + fn initialize_keys(keys: &[T::AuthorityId]) { + if !keys.is_empty() { + assert!(Keys::::get().is_empty(), "Keys are already initialized!"); + Keys::::put(keys); + } + } +} + +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; } impl session::OneSessionHandler for Module { - type Key = AuthorityId; + type Key = T::AuthorityId; - fn on_new_session<'a, I: 'a>(_changed: bool, _validators: I, next_validators: I) - where I: Iterator + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator { - // Reset heartbeats - ::remove_prefix(&>::current_index()); + let keys = validators.map(|x| x.1).collect::>(); + Self::initialize_keys(&keys); + } + fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, _queued_validators: I) + where I: Iterator + { // Tell the offchain worker to start making the next session's heartbeats. - >::put(>::block_number()); + // Since we consider producing blocks as being online, + // the hearbeat is defered a bit to prevent spaming. + let block_number = >::block_number(); + let half_session = T::SessionDuration::get() / 2.into(); + >::put(block_number + half_session); // Remember who the authorities are for the new session. - Keys::put(next_validators.map(|x| x.1).collect::>()); + Keys::::put(validators.map(|x| x.1).collect::>()); + } + + fn on_before_session_ending() { + let session_index = >::current_index(); + let keys = Keys::::get(); + let current_validators = >::validators(); + + let offenders = current_validators.into_iter().enumerate() + .filter(|(index, id)| + !Self::is_online_aux(*index as u32, id) + ).filter_map(|(_, id)| + T::FullIdentificationOf::convert(id.clone()).map(|full_id| (id, full_id)) + ).collect::>>(); + + // Remove all received heartbeats and number of authored blocks from the + // current session, they have already been processed and won't be needed + // anymore. + ::remove_prefix(&>::current_index()); + >::remove_prefix(&>::current_index()); + + if offenders.is_empty() { + Self::deposit_event(RawEvent::AllGood); + } else { + Self::deposit_event(RawEvent::SomeOffline(offenders.clone())); + + let validator_set_count = keys.len() as u32; + let offence = UnresponsivenessOffence { session_index, validator_set_count, offenders }; + T::ReportUnresponsiveness::report_offence(vec![], offence); + } } fn on_disabled(_i: usize) { @@ -378,27 +571,28 @@ impl session::OneSessionHandler for Module { } } -impl srml_support::unsigned::ValidateUnsigned for Module { +#[allow(deprecated)] +impl support::unsigned::ValidateUnsigned for Module { type Call = Call; - fn validate_unsigned(call: &Self::Call) -> srml_support::unsigned::TransactionValidity { + fn validate_unsigned(call: &Self::Call) -> TransactionValidity { if let Call::heartbeat(heartbeat, signature) = call { - if >::is_online_in_current_session(heartbeat.authority_index) { + if >::is_online(heartbeat.authority_index) { // we already received a heartbeat for this authority - return TransactionValidity::Invalid(ApplyError::Stale as i8); + return InvalidTransaction::Stale.into(); } // check if session index from heartbeat is recent let current_session = >::current_index(); if heartbeat.session_index != current_session { - return TransactionValidity::Invalid(ApplyError::Stale as i8); + return InvalidTransaction::Stale.into(); } // verify that the incoming (unverified) pubkey is actually an authority id - let keys = Keys::get(); + let keys = Keys::::get(); let authority_id = match keys.get(heartbeat.authority_index as usize) { Some(id) => id, - None => return TransactionValidity::Invalid(ApplyError::BadSignature as i8), + None => return InvalidTransaction::BadProof.into(), }; // check signature (this is expensive so we do it last). @@ -407,18 +601,60 @@ impl srml_support::unsigned::ValidateUnsigned for Module { }); if !signature_valid { - return TransactionValidity::Invalid(ApplyError::BadSignature as i8); + return InvalidTransaction::BadProof.into(); } - return TransactionValidity::Valid(ValidTransaction { - priority: 0, + Ok(ValidTransaction { + priority: TransactionPriority::max_value(), requires: vec![], provides: vec![(current_session, authority_id).encode()], - longevity: TransactionLongevity::max_value(), + longevity: TryInto::::try_into(T::SessionDuration::get() / 2.into()).unwrap_or(64_u64), propagate: true, }) + } else { + InvalidTransaction::Call.into() } + } +} + +/// An offence that is filed if a validator didn't send a heartbeat message. +#[derive(RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Clone, PartialEq, Eq))] +pub struct UnresponsivenessOffence { + /// The current session index in which we report the unresponsive validators. + /// + /// It acts as a time measure for unresponsiveness reports and effectively will always point + /// at the end of the session. + session_index: SessionIndex, + /// The size of the validator set in current session/era. + validator_set_count: u32, + /// Authorities that were unresponsive during the current era. + offenders: Vec, +} + +impl Offence for UnresponsivenessOffence { + const ID: Kind = *b"im-online:offlin"; + type TimeSlot = SessionIndex; + + fn offenders(&self) -> Vec { + self.offenders.clone() + } + + fn session_index(&self) -> SessionIndex { + self.session_index + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> Self::TimeSlot { + self.session_index + } - TransactionValidity::Invalid(0) + fn slash_fraction(offenders: u32, validator_set_count: u32) -> Perbill { + // the formula is min((3 * (k - 1)) / n, 1) * 0.05 + let x = Perbill::from_rational_approximation(3 * (offenders - 1), validator_set_count); + x.saturating_mul(Perbill::from_percent(5)) } } diff --git a/srml/im-online/src/mock.rs b/srml/im-online/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..4be33c44ed59e61b4ca3a8299c5ce0e2d44879f9 --- /dev/null +++ b/srml/im-online/src/mock.rs @@ -0,0 +1,178 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use std::cell::RefCell; + +use crate::{Module, Trait}; +use sr_primitives::Perbill; +use sr_staking_primitives::{SessionIndex, offence::ReportOffence}; +use sr_primitives::testing::{Header, UintAuthorityId, TestXt}; +use sr_primitives::traits::{IdentityLookup, BlakeTwo256, ConvertInto}; +use primitives::H256; +use support::{impl_outer_origin, impl_outer_dispatch, parameter_types}; +use {runtime_io, system}; + +impl_outer_origin!{ + pub enum Origin for Runtime {} +} + +impl_outer_dispatch! { + pub enum Call for Runtime where origin: Origin { + imonline::ImOnline, + } +} + +thread_local! { + pub static VALIDATORS: RefCell>> = RefCell::new(Some(vec![1, 2, 3])); +} + +pub struct TestOnSessionEnding; +impl session::OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) + -> Option> + { + VALIDATORS.with(|l| l.borrow_mut().take()) + } +} + +impl session::historical::OnSessionEnding for TestOnSessionEnding { + fn on_session_ending(_ending_index: SessionIndex, _will_apply_at: SessionIndex) + -> Option<(Vec, Vec<(u64, u64)>)> + { + VALIDATORS.with(|l| l + .borrow_mut() + .take() + .map(|validators| { + let full_identification = validators.iter().map(|v| (*v, *v)).collect(); + (validators, full_identification) + }) + ) + } +} + +/// An extrinsic type used for tests. +pub type Extrinsic = TestXt; +type SubmitTransaction = system::offchain::TransactionSubmitter<(), Call, Extrinsic>; +type IdentificationTuple = (u64, u64); +type Offence = crate::UnresponsivenessOffence; + +thread_local! { + pub static OFFENCES: RefCell, Offence)>> = RefCell::new(vec![]); +} + +/// A mock offence report handler. +pub struct OffenceHandler; +impl ReportOffence for OffenceHandler { + fn report_offence(reporters: Vec, offence: Offence) { + OFFENCES.with(|l| l.borrow_mut().push((reporters, offence))); + } +} + +pub fn new_test_ext() -> runtime_io::TestExternalities { + let t = system::GenesisConfig::default().build_storage::().unwrap(); + t.into() +} + + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Runtime; + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); +} + +parameter_types! { + pub const Period: u64 = 1; + pub const Offset: u64 = 0; +} + +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); +} + +impl session::Trait for Runtime { + type ShouldEndSession = session::PeriodicSessions; + type OnSessionEnding = session::historical::NoteHistoricalRoot; + type SessionHandler = (ImOnline, ); + type ValidatorId = u64; + type ValidatorIdOf = ConvertInto; + type Keys = UintAuthorityId; + type Event = (); + type SelectInitialValidators = (); + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +impl session::historical::Trait for Runtime { + type FullIdentification = u64; + type FullIdentificationOf = ConvertInto; +} + +parameter_types! { + pub const UncleGenerations: u32 = 5; +} + +impl authorship::Trait for Runtime { + type FindAuthor = (); + type UncleGenerations = UncleGenerations; + type FilterUncle = (); + type EventHandler = ImOnline; +} + +impl Trait for Runtime { + type AuthorityId = UintAuthorityId; + type Event = (); + type Call = Call; + type SubmitTransaction = SubmitTransaction; + type ReportUnresponsiveness = OffenceHandler; + type SessionDuration = Period; +} + +/// Im Online module. +pub type ImOnline = Module; +pub type System = system::Module; +pub type Session = session::Module; + +pub fn advance_session() { + let now = System::block_number(); + System::set_block_number(now + 1); + Session::rotate_session(); + assert_eq!(Session::current_index(), (now / Period::get()) as u32); +} diff --git a/srml/im-online/src/tests.rs b/srml/im-online/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..f3a0895d5fce6c3ef1debfd7a755ead5e9e5fb12 --- /dev/null +++ b/srml/im-online/src/tests.rs @@ -0,0 +1,324 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the im-online module. + +#![cfg(test)] + +use super::*; +use crate::mock::*; +use offchain::testing::TestOffchainExt; +use primitives::offchain::{OpaquePeerId, OffchainExt}; +use support::{dispatch, assert_noop}; +use sr_primitives::testing::UintAuthorityId; + +#[test] +fn test_unresponsiveness_slash_fraction() { + // A single case of unresponsiveness is not slashed. + assert_eq!( + UnresponsivenessOffence::<()>::slash_fraction(1, 50), + Perbill::zero(), + ); + + assert_eq!( + UnresponsivenessOffence::<()>::slash_fraction(3, 50), + Perbill::from_parts(6000000), // 0.6% + ); + + // One third offline should be punished around 5%. + assert_eq!( + UnresponsivenessOffence::<()>::slash_fraction(17, 50), + Perbill::from_parts(48000000), // 4.8% + ); +} + +#[test] +fn should_report_offline_validators() { + new_test_ext().execute_with(|| { + // given + let block = 1; + System::set_block_number(block); + // buffer new validators + Session::rotate_session(); + // enact the change and buffer another one + let validators = vec![1, 2, 3, 4, 5, 6]; + VALIDATORS.with(|l| *l.borrow_mut() = Some(validators.clone())); + Session::rotate_session(); + + // when + // we end current session and start the next one + Session::rotate_session(); + + // then + let offences = OFFENCES.with(|l| l.replace(vec![])); + assert_eq!(offences, vec![ + (vec![], UnresponsivenessOffence { + session_index: 2, + validator_set_count: 3, + offenders: vec![ + (1, 1), + (2, 2), + (3, 3), + ], + }) + ]); + + // should not report when heartbeat is sent + for (idx, v) in validators.into_iter().take(4).enumerate() { + let _ = heartbeat(block, 3, idx as u32, v.into()).unwrap(); + } + Session::rotate_session(); + + // then + let offences = OFFENCES.with(|l| l.replace(vec![])); + assert_eq!(offences, vec![ + (vec![], UnresponsivenessOffence { + session_index: 3, + validator_set_count: 6, + offenders: vec![ + (5, 5), + (6, 6), + ], + }) + ]); + }); +} + +fn heartbeat( + block_number: u64, + session_index: u32, + authority_index: u32, + id: UintAuthorityId, +) -> dispatch::Result { + #[allow(deprecated)] + use support::unsigned::ValidateUnsigned; + + let heartbeat = Heartbeat { + block_number, + network_state: OpaqueNetworkState { + peer_id: OpaquePeerId(vec![1]), + external_addresses: vec![], + }, + session_index, + authority_index, + }; + let signature = id.sign(&heartbeat.encode()).unwrap(); + + #[allow(deprecated)] // Allow ValidateUnsigned + ImOnline::pre_dispatch(&crate::Call::heartbeat(heartbeat.clone(), signature.clone()))?; + ImOnline::heartbeat( + Origin::system(system::RawOrigin::None), + heartbeat, + signature + ) +} + +#[test] +fn should_mark_online_validator_when_heartbeat_is_received() { + new_test_ext().execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + assert!(!ImOnline::is_online(0)); + assert!(!ImOnline::is_online(1)); + assert!(!ImOnline::is_online(2)); + + // when + let _ = heartbeat(1, 2, 0, 1.into()).unwrap(); + + // then + assert!(ImOnline::is_online(0)); + assert!(!ImOnline::is_online(1)); + assert!(!ImOnline::is_online(2)); + + // and when + let _ = heartbeat(1, 2, 2, 3.into()).unwrap(); + + // then + assert!(ImOnline::is_online(0)); + assert!(!ImOnline::is_online(1)); + assert!(ImOnline::is_online(2)); + }); +} + +#[test] +fn late_heartbeat_should_fail() { + new_test_ext().execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 4, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + // when + assert_noop!(heartbeat(1, 3, 0, 1.into()), "Transaction is outdated"); + assert_noop!(heartbeat(1, 1, 0, 1.into()), "Transaction is outdated"); + }); +} + +#[test] +fn should_generate_heartbeats() { + let mut ext = new_test_ext(); + let (offchain, state) = TestOffchainExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + + ext.execute_with(|| { + // given + let block = 1; + System::set_block_number(block); + // buffer new validators + Session::rotate_session(); + // enact the change and buffer another one + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + Session::rotate_session(); + + // when + UintAuthorityId::set_all_keys(vec![0, 1, 2]); + ImOnline::offchain(2); + + // then + let transaction = state.write().transactions.pop().unwrap(); + // All validators have `0` as their session key, so we generate 3 transactions. + assert_eq!(state.read().transactions.len(), 2); + // check stuff about the transaction. + let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); + let heartbeat = match ex.1 { + crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h, + e => panic!("Unexpected call: {:?}", e), + }; + + assert_eq!(heartbeat, Heartbeat { + block_number: 2, + network_state: runtime_io::network_state().unwrap(), + session_index: 2, + authority_index: 2, + }); + }); +} + +#[test] +fn should_cleanup_received_heartbeats_on_session_end() { + new_test_ext().execute_with(|| { + advance_session(); + + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3])); + assert_eq!(Session::validators(), Vec::::new()); + + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + // send an heartbeat from authority id 0 at session 2 + let _ = heartbeat(1, 2, 0, 1.into()).unwrap(); + + // the heartbeat is stored + assert!(!ImOnline::received_heartbeats(&2, &0).is_none()); + + advance_session(); + + // after the session has ended we have already processed the heartbeat + // message, so any messages received on the previous session should have + // been pruned. + assert!(ImOnline::received_heartbeats(&2, &0).is_none()); + }); +} + +#[test] +fn should_mark_online_validator_when_block_is_authored() { + use authorship::EventHandler; + + new_test_ext().execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + + for i in 0..3 { + assert!(!ImOnline::is_online(i)); + } + + // when + ImOnline::note_author(1); + ImOnline::note_uncle(2, 0); + + // then + assert!(ImOnline::is_online(0)); + assert!(ImOnline::is_online(1)); + assert!(!ImOnline::is_online(2)); + }); +} + +#[test] +fn should_not_send_a_report_if_already_online() { + use authorship::EventHandler; + + let mut ext = new_test_ext(); + let (offchain, state) = TestOffchainExt::new(); + ext.register_extension(OffchainExt::new(offchain)); + + ext.execute_with(|| { + advance_session(); + // given + VALIDATORS.with(|l| *l.borrow_mut() = Some(vec![1, 2, 3, 4, 5, 6])); + assert_eq!(Session::validators(), Vec::::new()); + // enact the change and buffer another one + advance_session(); + assert_eq!(Session::current_index(), 2); + assert_eq!(Session::validators(), vec![1, 2, 3]); + ImOnline::note_author(2); + ImOnline::note_uncle(3, 0); + + // when + UintAuthorityId::set_all_keys(vec![0]); // all authorities use session key 0 + ImOnline::offchain(4); + + // then + let transaction = state.write().transactions.pop().unwrap(); + // All validators have `0` as their session key, but we should only produce 1 hearbeat. + assert_eq!(state.read().transactions.len(), 0); + // check stuff about the transaction. + let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap(); + let heartbeat = match ex.1 { + crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h, + e => panic!("Unexpected call: {:?}", e), + }; + + assert_eq!(heartbeat, Heartbeat { + block_number: 4, + network_state: runtime_io::network_state().unwrap(), + session_index: 2, + authority_index: 0, + }); + }); +} diff --git a/srml/indices/Cargo.toml b/srml/indices/Cargo.toml index 3cbf1d88dec9f1e8c88c43b2249519f4336e5fee..b8b560c3f9b4d4b34a178582e4dcc7f695f540ef 100644 --- a/srml/indices/Cargo.toml +++ b/srml/indices/Cargo.toml @@ -5,19 +5,19 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } substrate-keyring = { path = "../../core/keyring", optional = true } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -ref_thread_local = "0.0" +ref_thread_local = "0.0.0" [features] default = ["std"] @@ -29,7 +29,7 @@ std = [ "primitives/std", "rstd/std", "runtime-io/std", - "srml-support/std", + "support/std", "sr-primitives/std", "system/std", ] diff --git a/srml/indices/src/address.rs b/srml/indices/src/address.rs index caef4728fbf3fdb245fd5e099708604c31889bed..21ee654cf2e3f362182a99f12bb8ca8f4cc60f10 100644 --- a/srml/indices/src/address.rs +++ b/srml/indices/src/address.rs @@ -24,8 +24,8 @@ use codec::{Encode, Decode, Input, Output, Error}; /// An indices-aware address, which can be either a direct `AccountId` or /// an index. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Hash))] +#[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Hash))] pub enum Address where AccountId: Member, AccountIndex: Member, diff --git a/srml/indices/src/lib.rs b/srml/indices/src/lib.rs index 5bf838f32112dfc56c63fce28ff272218cb23a90..31aa57276bde95444d9320a09639480b560da3ec 100644 --- a/srml/indices/src/lib.rs +++ b/srml/indices/src/lib.rs @@ -19,10 +19,10 @@ #![cfg_attr(not(feature = "std"), no_std)] -use rstd::{prelude::*, result, marker::PhantomData, convert::TryInto}; +use rstd::{prelude::*, marker::PhantomData, convert::TryInto}; use codec::{Encode, Codec}; -use srml_support::{StorageValue, StorageMap, Parameter, decl_module, decl_event, decl_storage}; -use sr_primitives::traits::{One, SimpleArithmetic, StaticLookup, Member}; +use support::{Parameter, decl_module, decl_event, decl_storage}; +use sr_primitives::traits::{One, SimpleArithmetic, StaticLookup, Member, LookupError}; use system::{IsDeadAccount, OnNewAccount}; use self::address::Address as RawAddress; @@ -73,7 +73,7 @@ pub trait Trait: system::Trait { decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; } } @@ -93,12 +93,12 @@ decl_event!( decl_storage! { trait Store for Module as Indices { /// The next free enumeration set. - pub NextEnumSet get(next_enum_set) build(|config: &GenesisConfig| { + pub NextEnumSet get(fn next_enum_set) build(|config: &GenesisConfig| { (config.ids.len() as u32 / ENUM_SET_SIZE).into() }): T::AccountIndex; /// The enumeration sets. - pub EnumSet get(enum_set) build(|config: &GenesisConfig| { + pub EnumSet get(fn enum_set) build(|config: &GenesisConfig| { (0..((config.ids.len() as u32) + ENUM_SET_SIZE - 1) / ENUM_SET_SIZE) .map(|i| ( i.into(), @@ -224,9 +224,11 @@ impl OnNewAccount for Module { impl StaticLookup for Module { type Source = address::Address; type Target = T::AccountId; - fn lookup(a: Self::Source) -> result::Result { - Self::lookup_address(a).ok_or("invalid account index") + + fn lookup(a: Self::Source) -> Result { + Self::lookup_address(a).ok_or(LookupError) } + fn unlookup(a: Self::Target) -> Self::Source { address::Address::Id(a) } diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs index 50b38eae28f91b5992c67a4159509fb211f9363c..427fd87c47e7d14d9383e9708ea96f8869891649 100644 --- a/srml/indices/src/mock.rs +++ b/srml/indices/src/mock.rs @@ -22,8 +22,8 @@ use std::collections::HashSet; use ref_thread_local::{ref_thread_local, RefThreadLocal}; use sr_primitives::testing::Header; use sr_primitives::Perbill; -use primitives::{H256, Blake2Hasher}; -use srml_support::{impl_outer_origin, parameter_types}; +use primitives::H256; +use support::{impl_outer_origin, parameter_types}; use {runtime_io, system}; use crate::{GenesisConfig, Module, Trait, IsDeadAccount, OnNewAccount, ResolveHint}; @@ -81,12 +81,12 @@ impl system::Trait for Runtime { type AccountId = u64; type Lookup = Indices; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } impl Trait for Runtime { type AccountIndex = u64; @@ -95,7 +95,7 @@ impl Trait for Runtime { type Event = (); } -pub fn new_test_ext() -> runtime_io::TestExternalities { +pub fn new_test_ext() -> runtime_io::TestExternalities { { let mut h = ALIVE.borrow_mut(); h.clear(); diff --git a/srml/indices/src/tests.rs b/srml/indices/src/tests.rs index 7b60e305278c58be97d156b0bbffc892afe7b750..3bcf0157130ce9ad10a5ed0fd8396359bb658814 100644 --- a/srml/indices/src/tests.rs +++ b/srml/indices/src/tests.rs @@ -20,61 +20,48 @@ use super::*; use crate::mock::{Indices, new_test_ext, make_account, kill_account, TestIsDeadAccount}; -use runtime_io::with_externalities; #[test] fn indexing_lookup_should_work() { - with_externalities( - &mut new_test_ext(), - || { - assert_eq!(Indices::lookup_index(0), Some(1)); - assert_eq!(Indices::lookup_index(1), Some(2)); - assert_eq!(Indices::lookup_index(2), Some(3)); - assert_eq!(Indices::lookup_index(3), Some(4)); - assert_eq!(Indices::lookup_index(4), None); - }, - ); + new_test_ext().execute_with(|| { + assert_eq!(Indices::lookup_index(0), Some(1)); + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(2), Some(3)); + assert_eq!(Indices::lookup_index(3), Some(4)); + assert_eq!(Indices::lookup_index(4), None); + }); } #[test] fn default_indexing_on_new_accounts_should_work() { - with_externalities( - &mut new_test_ext(), - || { - assert_eq!(Indices::lookup_index(4), None); - make_account(5); - assert_eq!(Indices::lookup_index(4), Some(5)); - }, - ); + new_test_ext().execute_with(|| { + assert_eq!(Indices::lookup_index(4), None); + make_account(5); + assert_eq!(Indices::lookup_index(4), Some(5)); + }); } #[test] fn reclaim_indexing_on_new_accounts_should_work() { - with_externalities( - &mut new_test_ext(), - || { - assert_eq!(Indices::lookup_index(1), Some(2)); - assert_eq!(Indices::lookup_index(4), None); + new_test_ext().execute_with(|| { + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(4), None); - kill_account(2); // index 1 no longer locked to id 2 + kill_account(2); // index 1 no longer locked to id 2 - make_account(1 + 256); // id 257 takes index 1. - assert_eq!(Indices::lookup_index(1), Some(257)); - }, - ); + make_account(1 + 256); // id 257 takes index 1. + assert_eq!(Indices::lookup_index(1), Some(257)); + }); } #[test] fn alive_account_should_prevent_reclaim() { - with_externalities( - &mut new_test_ext(), - || { - assert!(!TestIsDeadAccount::is_dead_account(&2)); - assert_eq!(Indices::lookup_index(1), Some(2)); - assert_eq!(Indices::lookup_index(4), None); + new_test_ext().execute_with(|| { + assert!(!TestIsDeadAccount::is_dead_account(&2)); + assert_eq!(Indices::lookup_index(1), Some(2)); + assert_eq!(Indices::lookup_index(4), None); - make_account(1 + 256); // id 257 takes index 1. - assert_eq!(Indices::lookup_index(4), Some(257)); - }, - ); + make_account(1 + 256); // id 257 takes index 1. + assert_eq!(Indices::lookup_index(4), Some(257)); + }); } diff --git a/srml/membership/Cargo.toml b/srml/membership/Cargo.toml index 5126f41f8929aa52fbda89f8b8ce78ee056fd729..a8cb73055563ec5fa82ec40e9d2d0f20031f6c7c 100644 --- a/srml/membership/Cargo.toml +++ b/srml/membership/Cargo.toml @@ -5,11 +5,11 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } -srml-support = { path = "../support", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } @@ -22,8 +22,8 @@ std = [ "serde", "codec/std", "sr-primitives/std", - "sr-std/std", - "sr-io/std", - "srml-support/std", + "rstd/std", + "runtime-io/std", + "support/std", "system/std", ] diff --git a/srml/membership/src/lib.rs b/srml/membership/src/lib.rs index f56a0ca0420a4febee1be3f7ba5196c875d4e9aa..6cd2a914e6bffea346b79ad1b3c33b763b0c1e48 100644 --- a/srml/membership/src/lib.rs +++ b/srml/membership/src/lib.rs @@ -22,10 +22,9 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use sr_std::prelude::*; -use srml_support::{ - StorageValue, decl_module, decl_storage, decl_event, - traits::{ChangeMembers} +use rstd::prelude::*; +use support::{ + decl_module, decl_storage, decl_event, traits::{ChangeMembers, InitializeMembers}, }; use system::ensure_root; use sr_primitives::{traits::EnsureOrigin, weights::SimpleDispatchInfo}; @@ -49,7 +48,7 @@ pub trait Trait: system::Trait { /// The receiver of the signal for when the membership has been initialized. This happens pre- /// genesis and will usually be the same as `MembershipChanged`. If you need to do something /// different on initialization, then you can change this accordingly. - type MembershipInitialized: ChangeMembers; + type MembershipInitialized: InitializeMembers; /// The receiver of the signal for when the membership has changed. type MembershipChanged: ChangeMembers; @@ -58,21 +57,16 @@ pub trait Trait: system::Trait { decl_storage! { trait Store for Module, I: Instance=DefaultInstance> as Membership { /// The current membership, stored as an ordered Vec. - Members get(members): Vec; + Members get(fn members): Vec; } add_extra_genesis { config(members): Vec; - config(phantom): sr_std::marker::PhantomData; - build(| - storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), - config: &GenesisConfig - | { - sr_io::with_storage(storage, || { - let mut members = config.members.clone(); - members.sort(); - T::MembershipInitialized::set_members_sorted(&members[..], &[]); - >::put(members); - }); + config(phantom): rstd::marker::PhantomData; + build(|config: &Self| { + let mut members = config.members.clone(); + members.sort(); + T::MembershipInitialized::initialize_members(&members); + >::put(members); }) } } @@ -91,7 +85,7 @@ decl_event!( /// The membership was reset; see the transaction for who the new set is. MembersReset, /// Phantom member, never used. - Dummy(sr_std::marker::PhantomData<(AccountId, Event)>), + Dummy(rstd::marker::PhantomData<(AccountId, Event)>), } ); @@ -100,7 +94,7 @@ decl_module! { for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Add a member `who` to the set. /// @@ -198,14 +192,11 @@ mod tests { use super::*; use std::cell::RefCell; - use srml_support::{assert_ok, assert_noop, impl_outer_origin, parameter_types}; - use sr_io::with_externalities; - use primitives::{H256, Blake2Hasher}; + use support::{assert_ok, assert_noop, impl_outer_origin, parameter_types}; + use primitives::H256; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. - use sr_primitives::{ - Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header - }; + use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; use system::EnsureSignedBy; impl_outer_origin! { @@ -233,12 +224,12 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } parameter_types! { pub const One: u64 = 1; @@ -266,6 +257,11 @@ mod tests { MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); } } + impl InitializeMembers for TestChangeMembers { + fn initialize_members(members: &[u64]) { + MEMBERS.with(|m| *m.borrow_mut() = members.to_vec()); + } + } impl Trait for Test { type Event = (); @@ -281,7 +277,7 @@ mod tests { // This function basically just builds a genesis storage key/value store according to // our desired mockup. - fn new_test_ext() -> sr_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); // We use default for brevity, but you can configure as desired if needed. GenesisConfig::{ @@ -293,7 +289,7 @@ mod tests { #[test] fn query_membership_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(Membership::members(), vec![10, 20, 30]); assert_eq!(MEMBERS.with(|m| m.borrow().clone()), vec![10, 20, 30]); }); @@ -301,7 +297,7 @@ mod tests { #[test] fn add_member_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_noop!(Membership::add_member(Origin::signed(5), 15), "bad origin"); assert_noop!(Membership::add_member(Origin::signed(1), 10), "already a member"); assert_ok!(Membership::add_member(Origin::signed(1), 15)); @@ -312,7 +308,7 @@ mod tests { #[test] fn remove_member_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_noop!(Membership::remove_member(Origin::signed(5), 20), "bad origin"); assert_noop!(Membership::remove_member(Origin::signed(2), 15), "not a member"); assert_ok!(Membership::remove_member(Origin::signed(2), 20)); @@ -323,7 +319,7 @@ mod tests { #[test] fn swap_member_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_noop!(Membership::swap_member(Origin::signed(5), 10, 25), "bad origin"); assert_noop!(Membership::swap_member(Origin::signed(3), 15, 25), "not a member"); assert_noop!(Membership::swap_member(Origin::signed(3), 10, 30), "already a member"); @@ -337,7 +333,7 @@ mod tests { #[test] fn reset_members_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_noop!(Membership::reset_members(Origin::signed(1), vec![20, 40, 30]), "bad origin"); assert_ok!(Membership::reset_members(Origin::signed(4), vec![20, 40, 30])); assert_eq!(Membership::members(), vec![20, 30, 40]); diff --git a/srml/metadata/Cargo.toml b/srml/metadata/Cargo.toml index 9fc9c6e46d5dbfaa1dbbf4a1a350a2d3d0ef9825..e9381f68bbbf967f24c3a168cca47d1f4116e626 100644 --- a/srml/metadata/Cargo.toml +++ b/srml/metadata/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } diff --git a/srml/metadata/src/lib.rs b/srml/metadata/src/lib.rs index bf7c379000d760cffb39c950c0fc6eace93e2934..d85a6837fc6e015d7d1c2068a685e1eaa9283fea 100644 --- a/srml/metadata/src/lib.rs +++ b/srml/metadata/src/lib.rs @@ -28,6 +28,7 @@ use serde::Serialize; use codec::{Decode, Input, Error}; use codec::{Encode, Output}; use rstd::vec::Vec; +use primitives::RuntimeDebug; #[cfg(feature = "std")] type StringBuf = String; @@ -84,13 +85,12 @@ impl Eq for DecodeDifferent where B: Encode + Eq + PartialEq + 'static, O: Encode + Eq + PartialEq + 'static {} -#[cfg(feature = "std")] -impl std::fmt::Debug for DecodeDifferent +impl rstd::fmt::Debug for DecodeDifferent where - B: std::fmt::Debug + Eq + 'static, - O: std::fmt::Debug + Eq + 'static, + B: rstd::fmt::Debug + Eq + 'static, + O: rstd::fmt::Debug + Eq + 'static, { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { match self { DecodeDifferent::Encode(b) => b.fmt(f), DecodeDifferent::Decoded(o) => o.fmt(f), @@ -114,14 +114,11 @@ impl serde::Serialize for DecodeDifferent pub type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; -#[cfg(feature = "std")] -type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; -#[cfg(not(feature = "std"))] type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; /// All the metadata about a function. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct FunctionMetadata { pub name: DecodeDifferentStr, pub arguments: DecodeDifferentArray, @@ -129,8 +126,8 @@ pub struct FunctionMetadata { } /// All the metadata about a function argument. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct FunctionArgumentMetadata { pub name: DecodeDifferentStr, pub ty: DecodeDifferentStr, @@ -154,9 +151,8 @@ impl PartialEq for FnEncode { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for FnEncode { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl rstd::fmt::Debug for FnEncode { + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { self.0().fmt(f) } } @@ -169,8 +165,8 @@ impl serde::Serialize for FnEncode { } /// All the metadata about an outer event. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct OuterEventMetadata { pub name: DecodeDifferentStr, pub events: DecodeDifferentArray< @@ -179,9 +175,9 @@ pub struct OuterEventMetadata { >, } -/// All the metadata about a event. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +/// All the metadata about an event. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct EventMetadata { pub name: DecodeDifferentStr, pub arguments: DecodeDifferentArray<&'static str, StringBuf>, @@ -189,8 +185,8 @@ pub struct EventMetadata { } /// All the metadata about one storage entry. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct StorageEntryMetadata { pub name: DecodeDifferentStr, pub modifier: StorageEntryModifier, @@ -200,8 +196,8 @@ pub struct StorageEntryMetadata { } /// All the metadata about one module constant. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct ModuleConstantMetadata { pub name: DecodeDifferentStr, pub ty: DecodeDifferentStr, @@ -209,6 +205,25 @@ pub struct ModuleConstantMetadata { pub documentation: DecodeDifferentArray<&'static str, StringBuf>, } +/// All the metadata about a module error. +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct ErrorMetadata { + pub name: DecodeDifferentStr, + pub documentation: DecodeDifferentArray<&'static str, StringBuf>, +} + +/// All the metadata about errors in a module. +pub trait ModuleErrorMetadata { + fn metadata() -> &'static [ErrorMetadata]; +} + +impl ModuleErrorMetadata for &'static str { + fn metadata() -> &'static [ErrorMetadata] { + &[] + } +} + /// A technical trait to store lazy initiated vec value as static dyn pointer. pub trait DefaultByte: Send + Sync { fn default_byte(&self) -> Vec; @@ -246,16 +261,15 @@ impl serde::Serialize for DefaultByteGetter { } } -#[cfg(feature = "std")] -impl std::fmt::Debug for DefaultByteGetter { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl rstd::fmt::Debug for DefaultByteGetter { + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { self.0.default_byte().fmt(f) } } /// Hasher used by storage maps -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub enum StorageHasher { Blake2_128, Blake2_256, @@ -265,8 +279,8 @@ pub enum StorageHasher { } /// A storage entry type. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub enum StorageEntryType { Plain(DecodeDifferentStr), Map { @@ -285,32 +299,32 @@ pub enum StorageEntryType { } /// A storage entry modifier. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub enum StorageEntryModifier { Optional, Default, } /// All metadata of the storage. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct StorageMetadata { /// The common prefix used by all storage entries. pub prefix: DecodeDifferent<&'static str, StringBuf>, pub entries: DecodeDifferent<&'static [StorageEntryMetadata], Vec>, } -#[derive(Eq, Encode, PartialEq)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Eq, Encode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] /// Metadata prefixed by a u32 for reserved usage pub struct RuntimeMetadataPrefixed(pub u32, pub RuntimeMetadata); /// The metadata of a runtime. /// The version ID encoded/decoded through /// the enum nature of `RuntimeMetadata`. -#[derive(Eq, Encode, PartialEq)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Eq, Encode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub enum RuntimeMetadata { /// Unused; enum filler. V0(RuntimeMetadataDeprecated), @@ -326,13 +340,15 @@ pub enum RuntimeMetadata { V5(RuntimeMetadataDeprecated), /// Version 6 for runtime metadata. No longer used. V6(RuntimeMetadataDeprecated), - /// Version 7 for runtime metadata. - V7(RuntimeMetadataV7), + /// Version 7 for runtime metadata. No longer used. + V7(RuntimeMetadataDeprecated), + /// Version 8 for runtime metadata. + V8(RuntimeMetadataV8), } /// Enum that should fail. -#[derive(Eq, PartialEq)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[derive(Eq, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize))] pub enum RuntimeMetadataDeprecated { } impl Encode for RuntimeMetadataDeprecated { @@ -349,24 +365,25 @@ impl Decode for RuntimeMetadataDeprecated { } /// The metadata of a runtime. -#[derive(Eq, Encode, PartialEq)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] -pub struct RuntimeMetadataV7 { +#[derive(Eq, Encode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] +pub struct RuntimeMetadataV8 { pub modules: DecodeDifferentArray, } /// The latest version of the metadata. -pub type RuntimeMetadataLastVersion = RuntimeMetadataV7; +pub type RuntimeMetadataLastVersion = RuntimeMetadataV8; /// All metadata about an runtime module. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Decode, Debug, Serialize))] +#[derive(Clone, PartialEq, Eq, Encode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode, Serialize))] pub struct ModuleMetadata { pub name: DecodeDifferentStr, pub storage: Option, StorageMetadata>>, pub calls: ODFnA, pub event: ODFnA, pub constants: DFnA, + pub errors: DFnA, } type ODFnA = Option>; @@ -380,6 +397,6 @@ impl Into for RuntimeMetadataPrefixed { impl Into for RuntimeMetadataLastVersion { fn into(self) -> RuntimeMetadataPrefixed { - RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V7(self)) + RuntimeMetadataPrefixed(META_RESERVED, RuntimeMetadata::V8(self)) } } diff --git a/srml/nicks/Cargo.toml b/srml/nicks/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4b8fabe9effe55febc9dff3b0360e44f95b03705 --- /dev/null +++ b/srml/nicks/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "srml-nicks" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +balances = { package = "srml-balances", path = "../balances", default-features = false } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "rstd/std", + "runtime-io/std", + "sr-primitives/std", + "support/std", + "system/std", +] diff --git a/srml/nicks/src/lib.rs b/srml/nicks/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..6b914ca5dc220c27ea7139a231a4d2d0b2046cf1 --- /dev/null +++ b/srml/nicks/src/lib.rs @@ -0,0 +1,385 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Nicks Module +//! +//! - [`nicks::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! Nicks is a trivial module for keeping track of account names on-chain. It makes no effort to +//! create a name hierarchy, be a DNS replacement or provide reverse lookups. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! * `set_name` - Set the associated name of an account; a small deposit is reserved if not already +//! taken. +//! * `clear_name` - Remove an account's associated name; the deposit is returned. +//! * `kill_name` - Forcibly remove the associated name; the deposit is lost. +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::prelude::*; +use sr_primitives::{ + traits::{StaticLookup, EnsureOrigin, Zero}, weights::SimpleDispatchInfo +}; +use support::{ + decl_module, decl_event, decl_storage, ensure, traits::{ + Currency, ReservableCurrency, OnUnbalanced, Get + }, +}; +use system::{ensure_signed, ensure_root}; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The currency trait. + type Currency: ReservableCurrency; + + /// Reservation fee. + type ReservationFee: Get>; + + /// What to do with slashed funds. + type Slashed: OnUnbalanced>; + + /// The origin which may forcibly set or remove a name. Root can always do this. + type ForceOrigin: EnsureOrigin; + + /// The minimum length a name may be. + type MinLength: Get; + + /// The maximum length a name may be. + type MaxLength: Get; +} + +decl_storage! { + trait Store for Module as Sudo { + /// The lookup table for names. + NameOf: map T::AccountId => Option<(Vec, BalanceOf)>; + } +} + +decl_event!( + pub enum Event where AccountId = ::AccountId, Balance = BalanceOf { + /// A name was set. + NameSet(AccountId), + /// A name was forcibly set. + NameForced(AccountId), + /// A name was changed. + NameChanged(AccountId), + /// A name was cleared, and the given balance returned. + NameCleared(AccountId, Balance), + /// A name was removed and the given balance slashed. + NameKilled(AccountId, Balance), + } +); + +decl_module! { + // Simple declaration of the `Module` type. Lets the macro know what it's working on. + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + /// Reservation fee. + const ReservationFee: BalanceOf = T::ReservationFee::get(); + + /// The minimum length a name may be. + const MinLength: u32 = T::MinLength::get() as u32; + + /// The maximum length a name may be. + const MaxLength: u32 = T::MaxLength::get() as u32; + + /// Set an account's name. The name should be a UTF-8-encoded string by convention, though + /// we don't check it. + /// + /// The name may not be more than `T::MaxLength` bytes, nor less than `T::MinLength` bytes. + /// + /// If the account doesn't already have a name, then a fee of `ReservationFee` is reserved + /// in the account. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - At most one balance operation. + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_name(origin, name: Vec) { + let sender = ensure_signed(origin)?; + + ensure!(name.len() >= T::MinLength::get(), "Name too short"); + ensure!(name.len() <= T::MaxLength::get(), "Name too long"); + + let deposit = if let Some((_, deposit)) = >::get(&sender) { + Self::deposit_event(RawEvent::NameSet(sender.clone())); + deposit + } else { + let deposit = T::ReservationFee::get(); + T::Currency::reserve(&sender, deposit.clone())?; + Self::deposit_event(RawEvent::NameChanged(sender.clone())); + deposit + }; + + >::insert(&sender, (name, deposit)); + } + + /// Clear an account's name and return the deposit. Fails if the account was not named. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - One balance operation. + /// - One storage read/write. + /// - One event. + /// # + fn clear_name(origin) { + let sender = ensure_signed(origin)?; + + let deposit = >::take(&sender).ok_or("Not named")?.1; + + let _ = T::Currency::unreserve(&sender, deposit.clone()); + + Self::deposit_event(RawEvent::NameCleared(sender, deposit)); + } + + /// Remove an account's name and take charge of the deposit. + /// + /// Fails if `who` has not been named. The deposit is dealt with through `T::Slashed` + /// imbalance handler. + /// + /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// + /// # + /// - O(1). + /// - One unbalanced handler (probably a balance transfer) + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn kill_name(origin, target: ::Source) { + T::ForceOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root) + .map_err(|_| "bad origin")?; + + // Figure out who we're meant to be clearing. + let target = T::Lookup::lookup(target)?; + // Grab their deposit (and check that they have one). + let deposit = >::take(&target).ok_or("Not named")?.1; + // Slash their deposit from them. + T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit.clone()).0); + + Self::deposit_event(RawEvent::NameKilled(target, deposit)); + } + + /// Set a third-party account's name with no deposit. + /// + /// No length checking is done on the name. + /// + /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// + /// # + /// - O(1). + /// - At most one balance operation. + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_name(origin, target: ::Source, name: Vec) { + T::ForceOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root) + .map_err(|_| "bad origin")?; + + let target = T::Lookup::lookup(target)?; + let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); + >::insert(&target, (name, deposit)); + + Self::deposit_event(RawEvent::NameForced(target)); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use support::{assert_ok, assert_noop, impl_outer_origin, parameter_types}; + use primitives::H256; + use system::EnsureSignedBy; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. + use sr_primitives::{ + Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, + }; + + impl_outer_origin! { + pub enum Origin for Test {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + parameter_types! { + pub const ReservationFee: u64 = 2; + pub const MinLength: usize = 3; + pub const MaxLength: usize = 16; + pub const One: u64 = 1; + } + impl Trait for Test { + type Event = (); + type Currency = Balances; + type ReservationFee = ReservationFee; + type Slashed = (); + type ForceOrigin = EnsureSignedBy; + type MinLength = MinLength; + type MaxLength = MaxLength; + } + type Balances = balances::Module; + type Nicks = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + balances::GenesisConfig:: { + balances: vec![ + (1, 10), + (2, 10), + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn kill_name_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); + assert_eq!(Balances::total_balance(&2), 10); + assert_ok!(Nicks::kill_name(Origin::signed(1), 2)); + assert_eq!(Balances::total_balance(&2), 8); + assert_eq!(>::get(2), None); + }); + } + + #[test] + fn force_name_should_work() { + new_test_ext().execute_with(|| { + assert_noop!( + Nicks::set_name(Origin::signed(2), b"Dr. David Brubeck, III".to_vec()), + "Name too long" + ); + + assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); + assert_eq!(Balances::reserved_balance(&2), 2); + assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec())); + assert_eq!(Balances::reserved_balance(&2), 2); + assert_eq!(>::get(2).unwrap(), (b"Dr. David Brubeck, III".to_vec(), 2)); + }); + } + + #[test] + fn normal_operation_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Nicks::set_name(Origin::signed(1), b"Gav".to_vec())); + assert_eq!(Balances::reserved_balance(&1), 2); + assert_eq!(Balances::free_balance(&1), 8); + assert_eq!(>::get(1).unwrap().0, b"Gav".to_vec()); + + assert_ok!(Nicks::set_name(Origin::signed(1), b"Gavin".to_vec())); + assert_eq!(Balances::reserved_balance(&1), 2); + assert_eq!(Balances::free_balance(&1), 8); + assert_eq!(>::get(1).unwrap().0, b"Gavin".to_vec()); + + assert_ok!(Nicks::clear_name(Origin::signed(1))); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 10); + }); + } + + #[test] + fn error_catching_should_work() { + new_test_ext().execute_with(|| { + assert_noop!(Nicks::clear_name(Origin::signed(1)), "Not named"); + + assert_noop!(Nicks::set_name(Origin::signed(3), b"Dave".to_vec()), "not enough free funds"); + + assert_noop!(Nicks::set_name(Origin::signed(1), b"Ga".to_vec()), "Name too short"); + assert_noop!( + Nicks::set_name(Origin::signed(1), b"Gavin James Wood, Esquire".to_vec()), + "Name too long" + ); + assert_ok!(Nicks::set_name(Origin::signed(1), b"Dave".to_vec())); + assert_noop!(Nicks::kill_name(Origin::signed(2), 1), "bad origin"); + assert_noop!(Nicks::force_name(Origin::signed(2), 1, b"Whatever".to_vec()), "bad origin"); + }); + } +} diff --git a/srml/offences/Cargo.toml b/srml/offences/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..90a3396d112280285dfa1b55fcdcf1071e613cc9 --- /dev/null +++ b/srml/offences/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "srml-offences" +version = "1.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +balances = { package = "srml-balances", path = "../balances", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +serde = { version = "1.0.101", optional = true } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +runtime-io = { package = "sr-io", path = "../../core/sr-io" } +substrate-primitives = { path = "../../core/primitives" } + +[features] +default = ["std"] +std = [ + "balances/std", + "codec/std", + "rstd/std", + "serde", + "sr-primitives/std", + "sr-staking-primitives/std", + "support/std", + "system/std", +] diff --git a/srml/offences/src/lib.rs b/srml/offences/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..a6cf4d795646771e2dc424d2f5cd2190be6eef70 --- /dev/null +++ b/srml/offences/src/lib.rs @@ -0,0 +1,279 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Offences Module +//! +//! Tracks reported offences + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod mock; +mod tests; + +use rstd::{ + vec::Vec, + collections::btree_set::BTreeSet, +}; +use support::{ + decl_module, decl_event, decl_storage, Parameter, +}; +use sr_primitives::{ + Perbill, + traits::{Hash, Saturating}, +}; +use sr_staking_primitives::{ + offence::{Offence, ReportOffence, Kind, OnOffenceHandler, OffenceDetails}, +}; +use codec::{Encode, Decode}; + +/// A binary blob which represents a SCALE codec-encoded `O::TimeSlot`. +type OpaqueTimeSlot = Vec; + +/// A type alias for a report identifier. +type ReportIdOf = ::Hash; + +/// Offences trait +pub trait Trait: system::Trait { + /// The overarching event type. + type Event: From + Into<::Event>; + /// Full identification of the validator. + type IdentificationTuple: Parameter + Ord; + /// A handler called for every offence report. + type OnOffenceHandler: OnOffenceHandler; +} + +decl_storage! { + trait Store for Module as Offences { + /// The primary structure that holds all offence records keyed by report identifiers. + Reports get(fn reports): map ReportIdOf => Option>; + + /// A vector of reports of the same kind that happened at the same time slot. + ConcurrentReportsIndex: double_map Kind, blake2_256(OpaqueTimeSlot) => Vec>; + + /// Enumerates all reports of a kind along with the time they happened. + /// + /// All reports are sorted by the time of offence. + /// + /// Note that the actual type of this mapping is `Vec`, this is because values of + /// different types are not supported at the moment so we are doing the manual serialization. + ReportsByKindIndex: map Kind => Vec; // (O::TimeSlot, ReportIdOf) + } +} + +decl_event!( + pub enum Event { + /// There is an offence reported of the given `kind` happened at the `session_index` and + /// (kind-specific) time slot. This event is not deposited for duplicate slashes. + Offence(Kind, OpaqueTimeSlot), + } +); + +decl_module! { + /// Offences module, currently just responsible for taking offence reports. + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + } +} +impl> + ReportOffence for Module +where + T::IdentificationTuple: Clone, +{ + fn report_offence(reporters: Vec, offence: O) { + let offenders = offence.offenders(); + let time_slot = offence.time_slot(); + let validator_set_count = offence.validator_set_count(); + + // Go through all offenders in the offence report and find all offenders that was spotted + // in unique reports. + let TriageOutcome { + new_offenders, + concurrent_offenders, + } = match Self::triage_offence_report::(reporters, &time_slot, offenders) { + Some(triage) => triage, + // The report contained only duplicates, so there is no need to slash again. + None => return, + }; + + // Deposit the event. + Self::deposit_event(Event::Offence(O::ID, time_slot.encode())); + + let offenders_count = concurrent_offenders.len() as u32; + let previous_offenders_count = offenders_count - new_offenders.len() as u32; + + // The amount new offenders are slashed + let new_fraction = O::slash_fraction(offenders_count, validator_set_count); + + // The amount previous offenders are slashed additionally. + // + // Since they were slashed in the past, we slash by: + // x = (new - prev) / (1 - prev) + // because: + // Y = X * (1 - prev) + // Z = Y * (1 - x) + // Z = X * (1 - new) + let old_fraction = if previous_offenders_count > 0 { + let previous_fraction = O::slash_fraction( + offenders_count.saturating_sub(previous_offenders_count), + validator_set_count, + ); + let numerator = new_fraction.saturating_sub(previous_fraction); + let denominator = Perbill::one().saturating_sub(previous_fraction); + denominator.saturating_mul(numerator) + } else { + new_fraction.clone() + }; + + // calculate how much to slash + let slash_perbill = concurrent_offenders + .iter() + .map(|details| { + if previous_offenders_count > 0 && new_offenders.contains(&details.offender) { + new_fraction.clone() + } else { + old_fraction.clone() + } + }) + .collect::>(); + + T::OnOffenceHandler::on_offence(&concurrent_offenders, &slash_perbill); + } +} + +impl Module { + /// Compute the ID for the given report properties. + /// + /// The report id depends on the offence kind, time slot and the id of offender. + fn report_id>( + time_slot: &O::TimeSlot, + offender: &T::IdentificationTuple, + ) -> ReportIdOf { + (O::ID, time_slot.encode(), offender).using_encoded(T::Hashing::hash) + } + + /// Triages the offence report and returns the set of offenders that was involved in unique + /// reports along with the list of the concurrent offences. + fn triage_offence_report>( + reporters: Vec, + time_slot: &O::TimeSlot, + offenders: Vec, + ) -> Option> { + let mut storage = ReportIndexStorage::::load(time_slot); + let mut new_offenders = BTreeSet::new(); + + for offender in offenders { + let report_id = Self::report_id::(time_slot, &offender); + + if !>::exists(&report_id) { + new_offenders.insert(offender.clone()); + >::insert( + &report_id, + OffenceDetails { + offender, + reporters: reporters.clone(), + }, + ); + + storage.insert(time_slot, report_id); + } + } + + if !new_offenders.is_empty() { + // Load report details for the all reports happened at the same time. + let concurrent_offenders = storage.concurrent_reports + .iter() + .filter_map(|report_id| >::get(report_id)) + .collect::>(); + + storage.save(); + + Some(TriageOutcome { + new_offenders, + concurrent_offenders, + }) + } else { + None + } + } +} + +struct TriageOutcome { + /// Offenders that was spotted in the unique reports. + new_offenders: BTreeSet, + /// Other reports for the same report kinds. + concurrent_offenders: Vec>, +} + +/// An auxilary struct for working with storage of indexes localized for a specific offence +/// kind (specified by the `O` type parameter). +/// +/// This struct is responsible for aggregating storage writes and the underlying storage should not +/// accessed directly meanwhile. +#[must_use = "The changes are not saved without called `save`"] +struct ReportIndexStorage> { + opaque_time_slot: OpaqueTimeSlot, + concurrent_reports: Vec>, + same_kind_reports: Vec<(O::TimeSlot, ReportIdOf)>, +} + +impl> ReportIndexStorage { + /// Preload indexes from the storage for the specific `time_slot` and the kind of the offence. + fn load(time_slot: &O::TimeSlot) -> Self { + let opaque_time_slot = time_slot.encode(); + + let same_kind_reports = ::get(&O::ID); + let same_kind_reports = + Vec::<(O::TimeSlot, ReportIdOf)>::decode(&mut &same_kind_reports[..]) + .unwrap_or_default(); + + let concurrent_reports = >::get(&O::ID, &opaque_time_slot); + + Self { + opaque_time_slot, + concurrent_reports, + same_kind_reports, + } + } + + /// Insert a new report to the index. + fn insert(&mut self, time_slot: &O::TimeSlot, report_id: ReportIdOf) { + // Insert the report id into the list while maintaining the ordering by the time + // slot. + let pos = match self + .same_kind_reports + .binary_search_by_key(&time_slot, |&(ref when, _)| when) + { + Ok(pos) => pos, + Err(pos) => pos, + }; + self.same_kind_reports + .insert(pos, (time_slot.clone(), report_id)); + + // Update the list of concurrent reports. + self.concurrent_reports.push(report_id); + } + + /// Dump the indexes to the storage. + fn save(self) { + ::insert(&O::ID, self.same_kind_reports.encode()); + >::insert( + &O::ID, + &self.opaque_time_slot, + &self.concurrent_reports, + ); + } +} diff --git a/srml/offences/src/mock.rs b/srml/offences/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..f9c79390819e0e83e4cfb48618c271a6150467ea --- /dev/null +++ b/srml/offences/src/mock.rs @@ -0,0 +1,162 @@ +// Copyright 2018-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +#![cfg(test)] + +use std::cell::RefCell; +use crate::{Module, Trait}; +use codec::Encode; +use sr_primitives::Perbill; +use sr_staking_primitives::{ + SessionIndex, + offence::{self, Kind, OffenceDetails}, +}; +use sr_primitives::testing::Header; +use sr_primitives::traits::{IdentityLookup, BlakeTwo256}; +use substrate_primitives::H256; +use support::{impl_outer_origin, impl_outer_event, parameter_types, StorageMap, StorageDoubleMap}; +use {runtime_io, system}; + +impl_outer_origin!{ + pub enum Origin for Runtime {} +} + +pub struct OnOffenceHandler; + +thread_local! { + pub static ON_OFFENCE_PERBILL: RefCell> = RefCell::new(Default::default()); +} + +impl offence::OnOffenceHandler for OnOffenceHandler { + fn on_offence( + _offenders: &[OffenceDetails], + slash_fraction: &[Perbill], + ) { + ON_OFFENCE_PERBILL.with(|f| { + *f.borrow_mut() = slash_fraction.to_vec(); + }); + } +} + +pub fn with_on_offence_fractions) -> R>(f: F) -> R { + ON_OFFENCE_PERBILL.with(|fractions| { + f(&mut *fractions.borrow_mut()) + }) +} + +// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Runtime; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); +} + +impl Trait for Runtime { + type Event = TestEvent; + type IdentificationTuple = u64; + type OnOffenceHandler = OnOffenceHandler; +} + +mod offences { + pub use crate::Event; +} + +impl_outer_event! { + pub enum TestEvent for Runtime { + offences, + } +} + +pub fn new_test_ext() -> runtime_io::TestExternalities { + let t = system::GenesisConfig::default().build_storage::().unwrap(); + t.into() +} + +/// Offences module. +pub type Offences = Module; +pub type System = system::Module; + +pub const KIND: [u8; 16] = *b"test_report_1234"; + +/// Returns all offence details for the specific `kind` happened at the specific time slot. +pub fn offence_reports(kind: Kind, time_slot: u128) -> Vec> { + >::get(&kind, &time_slot.encode()) + .into_iter() + .map(|report_id| { + >::get(&report_id) + .expect("dangling report id is found in ConcurrentReportsIndex") + }) + .collect() +} + +#[derive(Clone)] +pub struct Offence { + pub validator_set_count: u32, + pub offenders: Vec, + pub time_slot: u128, +} + +impl offence::Offence for Offence { + const ID: offence::Kind = KIND; + type TimeSlot = u128; + + fn offenders(&self) -> Vec { + self.offenders.clone() + } + + fn validator_set_count(&self) -> u32 { + self.validator_set_count + } + + fn time_slot(&self) -> u128 { + self.time_slot + } + + fn session_index(&self) -> SessionIndex { + // session index is not used by the srml-offences directly, but rather it exists only for + // filtering historical reports. + unimplemented!() + } + + fn slash_fraction( + offenders_count: u32, + validator_set_count: u32, + ) -> Perbill { + Perbill::from_percent(5 + offenders_count * 100 / validator_set_count) + } +} diff --git a/srml/offences/src/tests.rs b/srml/offences/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..28e655d16bfdd2e93fa69ce211adca389f65bccb --- /dev/null +++ b/srml/offences/src/tests.rs @@ -0,0 +1,245 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the offences module. + +#![cfg(test)] + +use super::*; +use crate::mock::{ + Offences, System, Offence, TestEvent, KIND, new_test_ext, with_on_offence_fractions, + offence_reports, +}; +use system::{EventRecord, Phase}; + +#[test] +fn should_report_an_authority_and_trigger_on_offence() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + + // when + Offences::report_offence(vec![], offence); + + // then + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + }); + }); +} + +#[test] +fn should_calculate_the_fraction_correctly() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + let offence1 = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + let offence2 = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![4], + }; + + // when + Offences::report_offence(vec![], offence1); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + }); + + Offences::report_offence(vec![], offence2); + + // then + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(15), Perbill::from_percent(45)]); + }); + }); +} + +#[test] +fn should_not_report_the_same_authority_twice_in_the_same_slot() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence.clone()); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // report for the second time + Offences::report_offence(vec![], offence); + + // then + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![]); + }); + }); +} + + +#[test] +fn should_report_in_different_time_slot() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let mut offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence.clone()); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // reportfor the second time + offence.time_slot += 1; + Offences::report_offence(vec![], offence); + + // then + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + }); + }); +} + +#[test] +fn should_deposit_event() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + + // when + Offences::report_offence(vec![], offence); + + // then + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: TestEvent::offences(crate::Event::Offence(KIND, time_slot.encode())), + topics: vec![], + }] + ); + }); +} + +#[test] +fn doesnt_deposit_event_for_dups() { + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + Offences::report_offence(vec![], offence.clone()); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // report for the second time + Offences::report_offence(vec![], offence); + + // then + // there is only one event. + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::ApplyExtrinsic(0), + event: TestEvent::offences(crate::Event::Offence(KIND, time_slot.encode())), + topics: vec![], + }] + ); + }); +} + +#[test] +fn should_properly_count_offences() { + // We report two different authorities for the same issue. Ultimately, the 1st authority + // should have `count` equal 2 and the count of the 2nd one should be equal to 1. + new_test_ext().execute_with(|| { + // given + let time_slot = 42; + assert_eq!(offence_reports(KIND, time_slot), vec![]); + + let offence1 = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![5], + }; + let offence2 = Offence { + validator_set_count: 5, + time_slot, + offenders: vec![4], + }; + Offences::report_offence(vec![], offence1); + with_on_offence_fractions(|f| { + assert_eq!(f.clone(), vec![Perbill::from_percent(25)]); + f.clear(); + }); + + // when + // report for the second time + Offences::report_offence(vec![], offence2); + + // then + // the 1st authority should have count 2 and the 2nd one should be reported only once. + assert_eq!( + offence_reports(KIND, time_slot), + vec![ + OffenceDetails { offender: 5, reporters: vec![] }, + OffenceDetails { offender: 4, reporters: vec![] }, + ] + ); + }); +} diff --git a/srml/randomness-collective-flip/Cargo.toml b/srml/randomness-collective-flip/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..5be9aad50f0b3003f82265d725e97fdb5cba8a2c --- /dev/null +++ b/srml/randomness-collective-flip/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "srml-randomness-collective-flip" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +safe-mix = { version = "1.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } + +[dev-dependencies] +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +runtime-io = { package = "sr-io", path = "../../core/sr-io" } + +[features] +default = ["std"] +std = [ + "safe-mix/std", + "system/std", + "codec/std", + "support/std", + "sr-primitives/std", + "rstd/std", +] diff --git a/srml/randomness-collective-flip/src/lib.rs b/srml/randomness-collective-flip/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..3644b8898c2ab3ebd8646078f39001c75737ec0c --- /dev/null +++ b/srml/randomness-collective-flip/src/lib.rs @@ -0,0 +1,280 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Randomness Module +//! +//! The Randomness Collective Flip module provides a [`random`](./struct.Module.html#method.random) +//! function that generates low-influence random values based on the block hashes from the previous +//! `81` blocks. Low-influence randomness can be useful when defending against relatively weak +//! adversaries. +//! +//! ## Public Functions +//! +//! See the [`Module`](./struct.Module.html) struct for details of publicly available functions. +//! +//! ## Usage +//! +//! ### Prerequisites +//! +//! Import the Randomness Collective Flip module and derive your module's configuration trait from +//! the system trait. +//! +//! ### Example - Get random seed for the current block +//! +//! ``` +//! use support::{decl_module, dispatch::Result, traits::Randomness}; +//! +//! pub trait Trait: system::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn random_module_example(origin) -> Result { +//! let _random_seed = >::random_seed(); +//! Ok(()) +//! } +//! } +//! } +//! # fn main() { } +//! ``` + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::{prelude::*, convert::TryInto}; +use sr_primitives::traits::Hash; +use support::{decl_module, decl_storage, traits::Randomness}; +use safe_mix::TripletMix; +use codec::Encode; +use system::Trait; + +const RANDOM_MATERIAL_LEN: u32 = 81; + +fn block_number_to_index(block_number: T::BlockNumber) -> usize { + // on_initialize is called on the first block after genesis + let index = (block_number - 1.into()) % RANDOM_MATERIAL_LEN.into(); + index.try_into().ok().expect("Something % 81 is always smaller than usize; qed") +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn on_initialize(block_number: T::BlockNumber) { + let parent_hash = >::parent_hash(); + + >::mutate(|ref mut values| if values.len() < RANDOM_MATERIAL_LEN as usize { + values.push(parent_hash) + } else { + let index = block_number_to_index::(block_number); + values[index] = parent_hash; + }); + } + } +} + +decl_storage! { + trait Store for Module as RandomnessCollectiveFlip { + /// Series of block headers from the last 81 blocks that acts as random seed material. This + /// is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of + /// the oldest hash. + RandomMaterial get(fn random_material): Vec; + } +} + +impl Randomness for Module { + /// Get a low-influence "random" value. + /// + /// Being a deterministic block chain, real randomness is difficult to come by. This gives you + /// something that approximates it. `subject` is a context identifier and allows you to get a + /// different result to other callers of this function; use it like + /// `random(&b"my context"[..])`. This is initially implemented through a low-influence + /// "triplet mix" convolution of previous block hash values. In the future it will be generated + /// from a secure verifiable random function (VRF). + /// + /// ### Security Notes + /// + /// This randomness uses a low-influence function, drawing upon the block hashes from the + /// previous 81 blocks. Its result for any given subject will be known far in advance by anyone + /// observing the chain. Any block producer has significant influence over their block hashes + /// bounded only by their computational resources. Our low-influence function reduces the actual + /// block producer's influence over the randomness, but increases the influence of small + /// colluding groups of recent block producers. + /// + /// Some BABE blocks have VRF outputs where the block producer has exactly one bit of influence, + /// either they make the block or they do not make the block and thus someone else makes the + /// next block. Yet, this randomness is not fresh in all BABE blocks. + /// + /// If that is an insufficient security guarantee then two things can be used to improve this + /// randomness: + /// + /// - Name, in advance, the block number whose random value will be used; ensure your module + /// retains a buffer of previous random values for its subject and then index into these in + /// order to obviate the ability of your user to look up the parent hash and choose when to + /// transact based upon it. + /// - Require your user to first commit to an additional value by first posting its hash. + /// Require them to reveal the value to determine the final result, hashing it with the + /// output of this random function. This reduces the ability of a cabal of block producers + /// from conspiring against individuals. + /// + /// WARNING: Hashing the result of this function will remove any low-influence properties it has + /// and mean that all bits of the resulting value are entirely manipulatable by the author of + /// the parent block, who can determine the value of `parent_hash`. + fn random(subject: &[u8]) -> T::Hash { + let block_number = >::block_number(); + let index = block_number_to_index::(block_number); + + let hash_series = >::get(); + if !hash_series.is_empty() { + // Always the case after block 1 is initialised. + hash_series.iter() + .cycle() + .skip(index) + .take(RANDOM_MATERIAL_LEN as usize) + .enumerate() + .map(|(i, h)| (i as i8, subject, h).using_encoded(T::Hashing::hash)) + .triplet_mix() + } else { + T::Hash::default() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use primitives::H256; + use sr_primitives::{ + Perbill, traits::{BlakeTwo256, OnInitialize, Header as _, IdentityLookup}, testing::Header, + }; + use support::{impl_outer_origin, parameter_types, traits::Randomness}; + + #[derive(Clone, PartialEq, Eq)] + pub struct Test; + + impl_outer_origin! { + pub enum Origin for Test {} + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + } + + type System = system::Module; + type CollectiveFlip = Module; + + fn new_test_ext() -> runtime_io::TestExternalities { + let t = system::GenesisConfig::default().build_storage::().unwrap(); + t.into() + } + + #[test] + fn test_block_number_to_index() { + for i in 1 .. 1000 { + assert_eq!((i - 1) as usize % 81, block_number_to_index::(i)); + } + } + + fn setup_blocks(blocks: u64) { + let mut parent_hash = System::parent_hash(); + + for i in 1 .. (blocks + 1) { + System::initialize(&i, &parent_hash, &Default::default(), &Default::default()); + CollectiveFlip::on_initialize(i); + + let header = System::finalize(); + parent_hash = header.hash(); + System::set_block_number(*header.number()); + } + } + + #[test] + fn test_random_material_parital() { + new_test_ext().execute_with(|| { + let genesis_hash = System::parent_hash(); + + setup_blocks(38); + + let random_material = CollectiveFlip::random_material(); + + assert_eq!(random_material.len(), 38); + assert_eq!(random_material[0], genesis_hash); + }); + } + + #[test] + fn test_random_material_filled() { + new_test_ext().execute_with(|| { + let genesis_hash = System::parent_hash(); + + setup_blocks(81); + + let random_material = CollectiveFlip::random_material(); + + assert_eq!(random_material.len(), 81); + assert_ne!(random_material[0], random_material[1]); + assert_eq!(random_material[0], genesis_hash); + }); + } + + #[test] + fn test_random_material_filled_twice() { + new_test_ext().execute_with(|| { + let genesis_hash = System::parent_hash(); + + setup_blocks(162); + + let random_material = CollectiveFlip::random_material(); + + assert_eq!(random_material.len(), 81); + assert_ne!(random_material[0], random_material[1]); + assert_ne!(random_material[0], genesis_hash); + }); + } + + #[test] + fn test_random() { + new_test_ext().execute_with(|| { + setup_blocks(162); + + assert_eq!(System::block_number(), 162); + assert_eq!(CollectiveFlip::random_seed(), CollectiveFlip::random_seed()); + assert_ne!(CollectiveFlip::random(b"random_1"), CollectiveFlip::random(b"random_2")); + + let random = CollectiveFlip::random_seed(); + + assert_ne!(random, H256::zero()); + assert!(!CollectiveFlip::random_material().contains(&random)); + }); + } +} diff --git a/srml/scored-pool/Cargo.toml b/srml/scored-pool/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e65f71a10d13ed24cadfe957ca7732df661d5291 --- /dev/null +++ b/srml/scored-pool/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "srml-scored-pool" +version = "1.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } + +[dev-dependencies] +balances = { package = "srml-balances", path = "../balances" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } + +[features] +default = ["std"] +std = [ + "codec/std", + "serde", + "runtime-io/std", + "sr-primitives/std", + "rstd/std", + "support/std", + "system/std", +] diff --git a/srml/scored-pool/src/lib.rs b/srml/scored-pool/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..5fde1e9c450cf986decd23accb2e47643bd4091a --- /dev/null +++ b/srml/scored-pool/src/lib.rs @@ -0,0 +1,456 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Scored Pool Module +//! +//! The module maintains a scored membership pool. Each entity in the +//! pool can be attributed a `Score`. From this pool a set `Members` +//! is constructed. This set contains the `MemberCount` highest +//! scoring entities. Unscored entities are never part of `Members`. +//! +//! If an entity wants to be part of the pool a deposit is required. +//! The deposit is returned when the entity withdraws or when it +//! is removed by an entity with the appropriate authority. +//! +//! Every `Period` blocks the set of `Members` is refreshed from the +//! highest scoring members in the pool and, no matter if changes +//! occurred, `T::MembershipChanged::set_members_sorted` is invoked. +//! On first load `T::MembershipInitialized::initialize_members` is +//! invoked with the initial `Members` set. +//! +//! It is possible to withdraw candidacy/resign your membership at any +//! time. If an entity is currently a member, this results in removal +//! from the `Pool` and `Members`; the entity is immediately replaced +//! by the next highest scoring candidate in the pool, if available. +//! +//! - [`scored_pool::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! - [`Module`](./struct.Module.html) +//! +//! ## Interface +//! +//! ### Public Functions +//! +//! - `submit_candidacy` - Submit candidacy to become a member. Requires a deposit. +//! - `withdraw_candidacy` - Withdraw candidacy. Deposit is returned. +//! - `score` - Attribute a quantitative score to an entity. +//! - `kick` - Remove an entity from the pool and members. Deposit is returned. +//! - `change_member_count` - Changes the amount of candidates taken into `Members`. +//! +//! ## Usage +//! +//! ``` +//! use support::{decl_module, dispatch::Result}; +//! use system::ensure_signed; +//! use srml_scored_pool::{self as scored_pool}; +//! +//! pub trait Trait: scored_pool::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn candidate(origin) -> Result { +//! let who = ensure_signed(origin)?; +//! +//! let _ = >::submit_candidacy( +//! T::Origin::from(Some(who.clone()).into()) +//! ); +//! Ok(()) +//! } +//! } +//! } +//! +//! # fn main() { } +//! ``` +//! +//! ## Dependencies +//! +//! This module depends on the [System module](../srml_system/index.html). + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +use codec::FullCodec; +use rstd::{ + fmt::Debug, + prelude::*, +}; +use support::{ + decl_module, decl_storage, decl_event, ensure, + traits::{ChangeMembers, InitializeMembers, Currency, Get, ReservableCurrency}, +}; +use system::{self, ensure_root, ensure_signed}; +use sr_primitives::{ + traits::{EnsureOrigin, SimpleArithmetic, MaybeSerializeDeserialize, Zero, StaticLookup}, +}; + +type BalanceOf = <>::Currency as Currency<::AccountId>>::Balance; +type PoolT = Vec<(::AccountId, Option<>::Score>)>; + +/// The enum is supplied when refreshing the members set. +/// Depending on the enum variant the corresponding associated +/// type function will be invoked. +enum ChangeReceiver { + /// Should call `T::MembershipInitialized`. + MembershipInitialized, + /// Should call `T::MembershipChanged`. + MembershipChanged, +} + +pub trait Trait: system::Trait { + /// The currency used for deposits. + type Currency: Currency + ReservableCurrency; + + /// The score attributed to a member or candidate. + type Score: + SimpleArithmetic + Clone + Copy + Default + FullCodec + MaybeSerializeDeserialize + Debug; + + /// The overarching event type. + type Event: From> + Into<::Event>; + + // The deposit which is reserved from candidates if they want to + // start a candidacy. The deposit gets returned when the candidacy is + // withdrawn or when the candidate is kicked. + type CandidateDeposit: Get>; + + /// Every `Period` blocks the `Members` are filled with the highest scoring + /// members in the `Pool`. + type Period: Get; + + /// The receiver of the signal for when the membership has been initialized. + /// This happens pre-genesis and will usually be the same as `MembershipChanged`. + /// If you need to do something different on initialization, then you can change + /// this accordingly. + type MembershipInitialized: InitializeMembers; + + /// The receiver of the signal for when the members have changed. + type MembershipChanged: ChangeMembers; + + /// Allows a configurable origin type to set a score to a candidate in the pool. + type ScoreOrigin: EnsureOrigin; + + /// Required origin for removing a member (though can always be Root). + /// Configurable origin which enables removing an entity. If the entity + /// is part of the `Members` it is immediately replaced by the next + /// highest scoring candidate, if available. + type KickOrigin: EnsureOrigin; +} + +decl_storage! { + trait Store for Module, I: Instance=DefaultInstance> as ScoredPool { + /// The current pool of candidates, stored as an ordered Vec + /// (ordered descending by score, `None` last, highest first). + Pool get(fn pool) config(): PoolT; + + /// A Map of the candidates. The information in this Map is redundant + /// to the information in the `Pool`. But the Map enables us to easily + /// check if a candidate is already in the pool, without having to + /// iterate over the entire pool (the `Pool` is not sorted by + /// `T::AccountId`, but by `T::Score` instead). + CandidateExists get(fn candidate_exists): map T::AccountId => bool; + + /// The current membership, stored as an ordered Vec. + Members get(fn members): Vec; + + /// Size of the `Members` set. + MemberCount get(fn member_count) config(): u32; + } + add_extra_genesis { + config(members): Vec; + config(phantom): rstd::marker::PhantomData; + build(|config| { + let mut pool = config.pool.clone(); + + // reserve balance for each candidate in the pool. + // panicking here is ok, since this just happens one time, pre-genesis. + pool + .iter() + .for_each(|(who, _)| { + T::Currency::reserve(&who, T::CandidateDeposit::get()) + .expect("balance too low to create candidacy"); + >::insert(who, true); + }); + + /// Sorts the `Pool` by score in a descending order. Entities which + /// have a score of `None` are sorted to the beginning of the vec. + pool.sort_by_key(|(_, maybe_score)| + Reverse(maybe_score.unwrap_or_default()) + ); + + >::put(&pool); + >::refresh_members(pool, ChangeReceiver::MembershipInitialized); + }) + } +} + +decl_event!( + pub enum Event where + ::AccountId, + { + /// The given member was removed. See the transaction for who. + MemberRemoved, + /// An entity has issued a candidacy. See the transaction for who. + CandidateAdded, + /// An entity withdrew candidacy. See the transaction for who. + CandidateWithdrew, + /// The candidacy was forcefully removed for an entity. + /// See the transaction for who. + CandidateKicked, + /// A score was attributed to the candidate. + /// See the transaction for who. + CandidateScored, + /// Phantom member, never used. + Dummy(rstd::marker::PhantomData<(AccountId, I)>), + } +); + +decl_module! { + pub struct Module, I: Instance=DefaultInstance> + for enum Call + where origin: T::Origin + { + fn deposit_event() = default; + + /// Every `Period` blocks the `Members` set is refreshed from the + /// highest scoring members in the pool. + fn on_initialize(n: T::BlockNumber) { + if n % T::Period::get() == Zero::zero() { + let pool = >::get(); + >::refresh_members(pool, ChangeReceiver::MembershipChanged); + } + } + + /// Add `origin` to the pool of candidates. + /// + /// This results in `CandidateDeposit` being reserved from + /// the `origin` account. The deposit is returned once + /// candidacy is withdrawn by the candidate or the entity + /// is kicked by `KickOrigin`. + /// + /// The dispatch origin of this function must be signed. + /// + /// The `index` parameter of this function must be set to + /// the index of the transactor in the `Pool`. + pub fn submit_candidacy(origin) { + let who = ensure_signed(origin)?; + ensure!(!>::exists(&who), "already a member"); + + let deposit = T::CandidateDeposit::get(); + T::Currency::reserve(&who, deposit) + .map_err(|_| "balance too low to submit candidacy")?; + + // can be inserted as last element in pool, since entities with + // `None` are always sorted to the end. + if let Err(e) = >::append(&[(who.clone(), None)]) { + T::Currency::unreserve(&who, deposit); + return Err(e); + } + + >::insert(&who, true); + + Self::deposit_event(RawEvent::CandidateAdded); + } + + /// An entity withdraws candidacy and gets its deposit back. + /// + /// If the entity is part of the `Members`, then the highest member + /// of the `Pool` that is not currently in `Members` is immediately + /// placed in the set instead. + /// + /// The dispatch origin of this function must be signed. + /// + /// The `index` parameter of this function must be set to + /// the index of the transactor in the `Pool`. + pub fn withdraw_candidacy( + origin, + index: u32 + ) { + let who = ensure_signed(origin)?; + + let pool = >::get(); + Self::ensure_index(&pool, &who, index)?; + + Self::remove_member(pool, who, index)?; + Self::deposit_event(RawEvent::CandidateWithdrew); + } + + /// Kick a member `who` from the set. + /// + /// May only be called from `KickOrigin` or root. + /// + /// The `index` parameter of this function must be set to + /// the index of `dest` in the `Pool`. + pub fn kick( + origin, + dest: ::Source, + index: u32 + ) { + T::KickOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root) + .map_err(|_| "bad origin")?; + + let who = T::Lookup::lookup(dest)?; + + let pool = >::get(); + Self::ensure_index(&pool, &who, index)?; + + Self::remove_member(pool, who, index)?; + Self::deposit_event(RawEvent::CandidateKicked); + } + + /// Score a member `who` with `score`. + /// + /// May only be called from `ScoreOrigin` or root. + /// + /// The `index` parameter of this function must be set to + /// the index of the `dest` in the `Pool`. + pub fn score( + origin, + dest: ::Source, + index: u32, + score: T::Score + ) { + T::ScoreOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root) + .map_err(|_| "bad origin")?; + + let who = T::Lookup::lookup(dest)?; + + let mut pool = >::get(); + Self::ensure_index(&pool, &who, index)?; + + pool.remove(index as usize); + + // we binary search the pool (which is sorted descending by score). + // if there is already an element with `score`, we insert + // right before that. if not, the search returns a location + // where we can insert while maintaining order. + let item = (who.clone(), Some(score.clone())); + let location = pool + .binary_search_by_key( + &Reverse(score), + |(_, maybe_score)| Reverse(maybe_score.unwrap_or_default()) + ) + .unwrap_or_else(|l| l); + pool.insert(location, item); + + >::put(&pool); + Self::deposit_event(RawEvent::CandidateScored); + } + + /// Dispatchable call to change `MemberCount`. + /// + /// This will only have an effect the next time a refresh happens + /// (this happens each `Period`). + /// + /// May only be called from root. + pub fn change_member_count(origin, count: u32) { + ensure_root(origin)?; + >::put(&count); + } + } +} + +impl, I: Instance> Module { + + /// Fetches the `MemberCount` highest scoring members from + /// `Pool` and puts them into `Members`. + /// + /// The `notify` parameter is used to deduct which associated + /// type function to invoke at the end of the method. + fn refresh_members( + pool: PoolT, + notify: ChangeReceiver + ) { + let count = >::get(); + + let mut new_members: Vec = pool + .into_iter() + .filter(|(_, score)| score.is_some()) + .take(count as usize) + .map(|(account_id, _)| account_id) + .collect(); + new_members.sort(); + + let old_members = >::get(); + >::put(&new_members); + + match notify { + ChangeReceiver::MembershipInitialized => + T::MembershipInitialized::initialize_members(&new_members), + ChangeReceiver::MembershipChanged => + T::MembershipChanged::set_members_sorted( + &new_members[..], + &old_members[..], + ), + } + } + + /// Removes an entity `remove` at `index` from the `Pool`. + /// + /// If the entity is a member it is also removed from `Members` and + /// the deposit is returned. + fn remove_member( + mut pool: PoolT, + remove: T::AccountId, + index: u32 + ) -> Result<(), &'static str> { + // all callers of this function in this module also check + // the index for validity before calling this function. + // nevertheless we check again here, to assert that there was + // no mistake when invoking this sensible function. + Self::ensure_index(&pool, &remove, index)?; + + pool.remove(index as usize); + >::put(&pool); + + // remove from set, if it was in there + let members = >::get(); + if members.binary_search(&remove).is_ok() { + Self::refresh_members(pool, ChangeReceiver::MembershipChanged); + } + + >::remove(&remove); + + T::Currency::unreserve(&remove, T::CandidateDeposit::get()); + + Self::deposit_event(RawEvent::MemberRemoved); + Ok(()) + } + + /// Checks if `index` is a valid number and if the element found + /// at `index` in `Pool` is equal to `who`. + fn ensure_index( + pool: &PoolT, + who: &T::AccountId, + index: u32 + ) -> Result<(), &'static str> { + ensure!(index < pool.len() as u32, "index out of bounds"); + + let (index_who, _index_score) = &pool[index as usize]; + ensure!(index_who == who, "index does not match requested account"); + + Ok(()) + } +} + diff --git a/srml/scored-pool/src/mock.rs b/srml/scored-pool/src/mock.rs new file mode 100644 index 0000000000000000000000000000000000000000..394f486a8bec383bf28e52eef7a0a1c4c7a47aec --- /dev/null +++ b/srml/scored-pool/src/mock.rs @@ -0,0 +1,170 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test utilities + +use super::*; + +use std::cell::RefCell; +use support::{impl_outer_origin, parameter_types}; +use primitives::H256; +// The testing primitives are very useful for avoiding having to work with signatures +// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. +use sr_primitives::{ + Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header, +}; +use system::EnsureSignedBy; + +impl_outer_origin! { + pub enum Origin for Test {} +} + +// For testing the module, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of modules we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const CandidateDeposit: u64 = 25; + pub const Period: u64 = 4; + + pub const KickOrigin: u64 = 2; + pub const ScoreOrigin: u64 = 3; + + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; +} + +impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); +} + +impl balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +thread_local! { + pub static MEMBERS: RefCell> = RefCell::new(vec![]); +} + +pub struct TestChangeMembers; +impl ChangeMembers for TestChangeMembers { + fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) { + let mut old_plus_incoming = MEMBERS.with(|m| m.borrow().to_vec()); + old_plus_incoming.extend_from_slice(incoming); + old_plus_incoming.sort(); + + let mut new_plus_outgoing = new.to_vec(); + new_plus_outgoing.extend_from_slice(outgoing); + new_plus_outgoing.sort(); + + assert_eq!(old_plus_incoming, new_plus_outgoing); + + MEMBERS.with(|m| *m.borrow_mut() = new.to_vec()); + } +} + +impl InitializeMembers for TestChangeMembers { + fn initialize_members(new_members: &[u64]) { + MEMBERS.with(|m| *m.borrow_mut() = new_members.to_vec()); + } +} + +impl Trait for Test { + type Event = (); + type KickOrigin = EnsureSignedBy; + type MembershipInitialized = TestChangeMembers; + type MembershipChanged = TestChangeMembers; + type Currency = balances::Module; + type CandidateDeposit = CandidateDeposit; + type Period = Period; + type Score = u64; + type ScoreOrigin = EnsureSignedBy; +} + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext() -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + balances::GenesisConfig:: { + balances: vec![ + (5, 500_000), + (10, 500_000), + (15, 500_000), + (20, 500_000), + (31, 500_000), + (40, 500_000), + (99, 1), + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + GenesisConfig::{ + pool: vec![ + (5, None), + (10, Some(1)), + (20, Some(2)), + (31, Some(2)), + (40, Some(3)), + ], + member_count: 2, + .. Default::default() + }.assimilate_storage(&mut t).unwrap(); + t.into() +} + +/// Fetch an entity from the pool, if existent. +pub fn fetch_from_pool(who: u64) -> Option<(u64, Option)> { + >::pool() + .into_iter() + .find(|item| item.0 == who) +} + +/// Find an entity in the pool. +/// Returns its position in the `Pool` vec, if existent. +pub fn find_in_pool(who: u64) -> Option { + >::pool() + .into_iter() + .position(|item| item.0 == who) +} diff --git a/srml/scored-pool/src/tests.rs b/srml/scored-pool/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..2f47b5da6fe26c5a8c0443155b370fd38e2aa5b9 --- /dev/null +++ b/srml/scored-pool/src/tests.rs @@ -0,0 +1,282 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Tests for the module. + +use super::*; +use mock::*; + +use support::{assert_ok, assert_noop}; +use sr_primitives::traits::OnInitialize; + +type ScoredPool = Module; +type System = system::Module; +type Balances = balances::Module; + +const OOB_ERR: &str = "index out of bounds"; +const INDEX_ERR: &str = "index does not match requested account"; + +#[test] +fn query_membership_works() { + new_test_ext().execute_with(|| { + assert_eq!(ScoredPool::members(), vec![20, 40]); + assert_eq!(Balances::reserved_balance(&31), CandidateDeposit::get()); + assert_eq!(Balances::reserved_balance(&40), CandidateDeposit::get()); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), vec![20, 40]); + }); +} + +#[test] +fn submit_candidacy_must_not_work() { + new_test_ext().execute_with(|| { + assert_noop!( + ScoredPool::submit_candidacy(Origin::signed(99)), + "balance too low to submit candidacy" + ); + assert_noop!( + ScoredPool::submit_candidacy(Origin::signed(40)), + "already a member" + ); + }); +} + +#[test] +fn submit_candidacy_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + + // when + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + assert_eq!(fetch_from_pool(15), Some((who, None))); + + // then + assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); + }); +} + +#[test] +fn scoring_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + let score = 99; + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, score)); + + // then + assert_eq!(fetch_from_pool(who), Some((who, Some(score)))); + assert_eq!(find_in_pool(who), Some(0)); // must be first element, since highest scored + }); +} + +#[test] +fn scoring_same_element_with_same_score_works() { + new_test_ext().execute_with(|| { + // given + let who = 31; + let index = find_in_pool(who).expect("entity must be in pool") as u32; + let score = 2; + + // when + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, score)); + + // then + assert_eq!(fetch_from_pool(who), Some((who, Some(score)))); + + // must have been inserted right before the `20` element which is + // of the same score as `31`. so sort order is maintained. + assert_eq!(find_in_pool(who), Some(1)); + }); +} + +#[test] +fn kicking_works_only_for_authorized() { + new_test_ext().execute_with(|| { + let who = 40; + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_noop!(ScoredPool::kick(Origin::signed(99), who, index), "bad origin"); + }); +} + +#[test] +fn kicking_works() { + new_test_ext().execute_with(|| { + // given + let who = 40; + assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); + assert_eq!(find_in_pool(who), Some(0)); + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index)); + + // then + assert_eq!(find_in_pool(who), None); + assert_eq!(ScoredPool::members(), vec![20, 31]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + assert_eq!(Balances::reserved_balance(&who), 0); // deposit must have been returned + }); +} + +#[test] +fn unscored_entities_must_not_be_used_for_filling_members() { + new_test_ext().execute_with(|| { + // given + // we submit a candidacy, score will be `None` + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(15))); + + // when + // we remove every scored member + ScoredPool::pool() + .into_iter() + .for_each(|(who, score)| { + if let Some(_) = score { + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index)); + } + }); + + // then + // the `None` candidates should not have been filled in + assert_eq!(ScoredPool::members(), vec![]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + }); +} + +#[test] +fn refreshing_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, 99)); + + // when + ScoredPool::refresh_members(ScoredPool::pool(), ChangeReceiver::MembershipChanged); + + // then + assert_eq!(ScoredPool::members(), vec![15, 40]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + }); +} + +#[test] +fn refreshing_happens_every_period() { + new_test_ext().execute_with(|| { + // given + System::set_block_number(1); + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(15))); + let index = find_in_pool(15).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), 15, index, 99)); + assert_eq!(ScoredPool::members(), vec![20, 40]); + + // when + System::set_block_number(4); + ScoredPool::on_initialize(4); + + // then + assert_eq!(ScoredPool::members(), vec![15, 40]); + assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members()); + }); +} + +#[test] +fn withdraw_candidacy_must_only_work_for_members() { + new_test_ext().execute_with(|| { + let who = 77; + let index = 0; + assert_noop!( ScoredPool::withdraw_candidacy(Origin::signed(who), index), INDEX_ERR); + }); +} + +#[test] +fn oob_index_should_abort() { + new_test_ext().execute_with(|| { + let who = 40; + let oob_index = ScoredPool::pool().len() as u32; + assert_noop!(ScoredPool::withdraw_candidacy(Origin::signed(who), oob_index), OOB_ERR); + assert_noop!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, oob_index, 99), OOB_ERR); + assert_noop!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, oob_index), OOB_ERR); + }); +} + +#[test] +fn index_mismatches_should_abort() { + new_test_ext().execute_with(|| { + let who = 40; + let index = 3; + assert_noop!(ScoredPool::withdraw_candidacy(Origin::signed(who), index), INDEX_ERR); + assert_noop!(ScoredPool::score(Origin::signed(ScoreOrigin::get()), who, index, 99), INDEX_ERR); + assert_noop!(ScoredPool::kick(Origin::signed(KickOrigin::get()), who, index), INDEX_ERR); + }); +} + +#[test] +fn withdraw_unscored_candidacy_must_work() { + new_test_ext().execute_with(|| { + // given + let who = 5; + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); + + // then + assert_eq!(fetch_from_pool(5), None); + }); +} + +#[test] +fn withdraw_scored_candidacy_must_work() { + new_test_ext().execute_with(|| { + // given + let who = 40; + assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get()); + + // when + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); + + // then + assert_eq!(fetch_from_pool(who), None); + assert_eq!(ScoredPool::members(), vec![20, 31]); + assert_eq!(Balances::reserved_balance(&who), 0); + }); +} + +#[test] +fn candidacy_resubmitting_works() { + new_test_ext().execute_with(|| { + // given + let who = 15; + + // when + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + assert_eq!(ScoredPool::candidate_exists(who), true); + let index = find_in_pool(who).expect("entity must be in pool") as u32; + assert_ok!(ScoredPool::withdraw_candidacy(Origin::signed(who), index)); + assert_eq!(ScoredPool::candidate_exists(who), false); + assert_ok!(ScoredPool::submit_candidacy(Origin::signed(who))); + + // then + assert_eq!(ScoredPool::candidate_exists(who), true); + }); +} diff --git a/srml/session/Cargo.toml b/srml/session/Cargo.toml index d084ab4261b3cbd977872191589173d72c12573b..134686791031376c22fd2c80a703717cbfd63a32 100644 --- a/srml/session/Cargo.toml +++ b/srml/session/Cargo.toml @@ -5,21 +5,23 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } substrate-trie = { path = "../../core/trie", default-features = false, optional = true } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } +impl-trait-for-tuples = "0.1.3" [dev-dependencies] primitives = { package = "substrate-primitives", path = "../../core/primitives" } app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto" } -lazy_static = "1.0" +lazy_static = "1.4.0" [features] default = ["std", "historical"] @@ -29,8 +31,10 @@ std = [ "safe-mix/std", "codec/std", "rstd/std", - "srml-support/std", + "support/std", "sr-primitives/std", + "sr-staking-primitives/std", "timestamp/std", - "substrate-trie/std" + "substrate-trie/std", + "runtime-io/std", ] diff --git a/srml/session/src/historical.rs b/srml/session/src/historical.rs index c0ffdeb464eb390f725a95fe3152efc4761b9a6e..7975da49983249041edc78b667cb249e4535527a 100644 --- a/srml/session/src/historical.rs +++ b/srml/session/src/historical.rs @@ -29,14 +29,14 @@ use rstd::prelude::*; use codec::{Encode, Decode}; use sr_primitives::KeyTypeId; use sr_primitives::traits::{Convert, OpaqueKeys, Hash as HashT}; -use srml_support::{ - StorageValue, StorageMap, decl_module, decl_storage, -}; -use srml_support::{Parameter, print}; +use support::{decl_module, decl_storage}; +use support::{Parameter, print}; use substrate_trie::{MemoryDB, Trie, TrieMut, Recorder, EMPTY_PREFIX}; use substrate_trie::trie_types::{TrieDBMut, TrieDB}; use super::{SessionIndex, Module as SessionModule}; +type ValidatorCount = u32; + /// Trait necessary for the historical module. pub trait Trait: super::Trait { /// Full identification of the validator. @@ -55,10 +55,10 @@ pub trait Trait: super::Trait { decl_storage! { trait Store for Module as Session { - /// Mapping from historical session indices to session-data root hash. - HistoricalSessions get(historical_root): map SessionIndex => Option; + /// Mapping from historical session indices to session-data root hash and validator count. + HistoricalSessions get(fn historical_root): map SessionIndex => Option<(T::Hash, ValidatorCount)>; /// Queued full identifications for queued sessions whose validators have become obsolete. - CachedObsolete get(cached_obsolete): map SessionIndex + CachedObsolete get(fn cached_obsolete): map SessionIndex => Option>; /// The range of historical sessions we store. [first, last) StoredRange: Option<(SessionIndex, SessionIndex)>; @@ -121,8 +121,9 @@ impl crate::OnSessionEnding for NoteHistoricalRoot< // do all of this _before_ calling the other `on_session_ending` impl // so that we have e.g. correct exposures from the _current_. + let count = >::validators().len() as u32; match ProvingTrie::::generate_for(ending) { - Ok(trie) => >::insert(ending, &trie.root), + Ok(trie) => >::insert(ending, &(trie.root, count)), Err(reason) => { print("Failed to generate historical ancestry-inclusion proof."); print(reason); @@ -181,11 +182,9 @@ impl ProvingTrie { // map each key to the owner index. for key_id in T::Keys::key_ids() { - let key = keys.get_raw(key_id); + let key = keys.get_raw(*key_id); let res = (key_id, key).using_encoded(|k| - i.using_encoded(|v| - trie.insert(k, v) - ) + i.using_encoded(|v| trie.insert(k, v)) ); let _ = res.map_err(|_| "failed to insert into trie")?; @@ -274,11 +273,11 @@ pub struct Proof { trie_nodes: Vec>, } -impl> srml_support::traits::KeyOwnerProofSystem<(KeyTypeId, D)> +impl> support::traits::KeyOwnerProofSystem<(KeyTypeId, D)> for Module { type Proof = Proof; - type FullIdentification = IdentificationTuple; + type IdentificationTuple = IdentificationTuple; fn prove(key: (KeyTypeId, D)) -> Option { let session = >::current_index(); @@ -300,7 +299,7 @@ impl> srml_support::traits::KeyOwnerProofSystem<(KeyTyp T::FullIdentificationOf::convert(owner.clone()).map(move |id| (owner, id)) ) } else { - let root = >::get(&proof.session)?; + let (root, _) = >::get(&proof.session)?; let trie = ProvingTrie::::from_nodes(root, &proof.trie_nodes); trie.query(id, data.as_ref()) @@ -311,18 +310,17 @@ impl> srml_support::traits::KeyOwnerProofSystem<(KeyTyp #[cfg(test)] mod tests { use super::*; - use runtime_io::with_externalities; - use primitives::{Blake2Hasher, crypto::key_types::DUMMY}; + use primitives::crypto::key_types::DUMMY; use sr_primitives::{traits::OnInitialize, testing::UintAuthorityId}; use crate::mock::{ NEXT_VALIDATORS, force_new_session, set_next_validators, Test, System, Session, }; - use srml_support::traits::KeyOwnerProofSystem; + use support::traits::KeyOwnerProofSystem; type Historical = Module; - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); crate::GenesisConfig:: { keys: NEXT_VALIDATORS.with(|l| @@ -334,7 +332,7 @@ mod tests { #[test] fn generated_proof_is_good() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { set_next_validators(vec![1, 2]); force_new_session(); @@ -375,7 +373,7 @@ mod tests { #[test] fn prune_up_to_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { for i in 1..101u64 { set_next_validators(vec![i]); force_new_session(); diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index 53c5c9b394f8b39e4c0b65bbc356bc2222eaac5d..42324d387f69e2e73ba1a48c356f9e45b2b98db2 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -121,14 +121,15 @@ use rstd::{prelude::*, marker::PhantomData, ops::{Sub, Rem}}; use codec::Decode; -use sr_primitives::{KeyTypeId, AppKey}; +use sr_primitives::{KeyTypeId, Perbill, RuntimeAppPublic, BoundToRuntimeAppPublic}; use sr_primitives::weights::SimpleDispatchInfo; use sr_primitives::traits::{Convert, Zero, Member, OpaqueKeys}; -use srml_support::{ - dispatch::Result, ConsensusEngineId, StorageValue, StorageDoubleMap, for_each_tuple, - decl_module, decl_event, decl_storage, +use sr_staking_primitives::SessionIndex; +use support::{ + dispatch::Result, ConsensusEngineId, decl_module, decl_event, + decl_storage, }; -use srml_support::{ensure, traits::{OnFreeBalanceZero, Get, FindAuthor}, Parameter}; +use support::{ensure, traits::{OnFreeBalanceZero, Get, FindAuthor}, Parameter}; use system::{self, ensure_signed}; #[cfg(test)] @@ -137,9 +138,6 @@ mod mock; #[cfg(feature = "historical")] pub mod historical; -/// Simple index type with which we can count sessions. -pub type SessionIndex = u32; - /// Decides whether the session should be ended. pub trait ShouldEndSession { /// Return `true` if the session should be ended. @@ -168,9 +166,16 @@ impl< } /// An event handler for when the session is ending. +/// TODO [slashing] consider renaming to OnSessionStarting pub trait OnSessionEnding { /// Handle the fact that the session is ending, and optionally provide the new validator set. /// + /// Even if the validator-set is the same as before, if any underlying economic + /// conditions have changed (i.e. stake-weights), the new validator set must be returned. + /// This is necessary for consensus engines making use of the session module to + /// issue a validator-set change so misbehavior can be provably associated with the new + /// economic conditions as opposed to the old. + /// /// `ending_index` is the index of the currently ending session. /// The returned validator set, if any, will not be applied until `will_apply_at`. /// `will_apply_at` is guaranteed to be at least `ending_index + 1`, since session indices don't @@ -185,64 +190,136 @@ impl OnSessionEnding for () { fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { None } } -/// Handler for when a session keys set changes. +/// Handler for session lifecycle events. pub trait SessionHandler { - /// Session set has changed; act appropriately. + /// All the key type ids this session handler can process. + /// + /// The order must be the same as it expects them in + /// [`on_new_session`](Self::on_new_session) and [`on_genesis_session`](Self::on_genesis_session). + const KEY_TYPE_IDS: &'static [KeyTypeId]; + + /// The given validator set will be used for the genesis session. + /// It is guaranteed that the given validator set will also be used + /// for the second session, therefore the first call to `on_new_session` + /// should provide the same validator set. + fn on_genesis_session(validators: &[(ValidatorId, Ks)]); + + /// Session set has changed; act appropriately. Note that this can be called + /// before initialization of your module. + /// + /// `changed` is true whenever any of the session keys or underlying economic + /// identities or weightings behind those keys has changed. fn on_new_session( changed: bool, validators: &[(ValidatorId, Ks)], queued_validators: &[(ValidatorId, Ks)], ); + /// A notification for end of the session. + /// + /// Note it is triggered before any `OnSessionEnding` handlers, + /// so we can still affect the validator set. + fn on_before_session_ending() {} + /// A validator got disabled. Act accordingly until a new session begins. fn on_disabled(validator_index: usize); } -/// One session-key type handler. -pub trait OneSessionHandler { +/// A session handler for specific key type. +pub trait OneSessionHandler: BoundToRuntimeAppPublic { /// The key type expected. - type Key: Decode + Default + AppKey; + type Key: Decode + Default + RuntimeAppPublic; - fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued_validators: I) + fn on_genesis_session<'a, I: 'a>(validators: I) where I: Iterator, ValidatorId: 'a; - fn on_disabled(i: usize); + + /// Session set has changed; act appropriately. Note that this can be called + /// before initialization of your module. + /// + /// `changed` is true when at least one of the session keys + /// or the underlying economic identities/distribution behind one the + /// session keys has changed, false otherwise. + /// + /// The `validators` are the validators of the incoming session, and `queued_validators` + /// will follow. + fn on_new_session<'a, I: 'a>( + changed: bool, + validators: I, + queued_validators: I, + ) where I: Iterator, ValidatorId: 'a; + + + /// A notification for end of the session. + /// + /// Note it is triggered before any `OnSessionEnding` handlers, + /// so we can still affect the validator set. + fn on_before_session_ending() {} + + /// A validator got disabled. Act accordingly until a new session begins. + fn on_disabled(_validator_index: usize); } -macro_rules! impl_session_handlers { - () => ( - impl SessionHandler for () { - fn on_new_session(_: bool, _: &[(AId, Ks)], _: &[(AId, Ks)]) {} - fn on_disabled(_: usize) {} - } +#[impl_trait_for_tuples::impl_for_tuples(1, 30)] +#[tuple_types_no_default_trait_bound] +impl SessionHandler for Tuple { + for_tuples!( where #( Tuple: OneSessionHandler )* ); + + for_tuples!( + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[ #( ::ID ),* ]; ); - ( $($t:ident)* ) => { - impl ),*> SessionHandler for ( $( $t , )* ) { - fn on_new_session( - changed: bool, - validators: &[(AId, Ks)], - queued_validators: &[(AId, Ks)], - ) { - $( - let our_keys: Box> = Box::new(validators.iter() - .map(|k| (&k.0, k.1.get::<$t::Key>(<$t::Key as AppKey>::ID) - .unwrap_or_default()))); - let queued_keys: Box> = Box::new(queued_validators.iter() - .map(|k| (&k.0, k.1.get::<$t::Key>(<$t::Key as AppKey>::ID) - .unwrap_or_default()))); - $t::on_new_session(changed, our_keys, queued_keys); - )* - } - fn on_disabled(i: usize) { - $( - $t::on_disabled(i); - )* - } - } + fn on_genesis_session(validators: &[(AId, Ks)]) { + for_tuples!( + #( + let our_keys: Box> = Box::new(validators.iter() + .map(|k| (&k.0, k.1.get::(::ID) + .unwrap_or_default()))); + + Tuple::on_genesis_session(our_keys); + )* + ) + } + + fn on_new_session( + changed: bool, + validators: &[(AId, Ks)], + queued_validators: &[(AId, Ks)], + ) { + for_tuples!( + #( + let our_keys: Box> = Box::new(validators.iter() + .map(|k| (&k.0, k.1.get::(::ID) + .unwrap_or_default()))); + let queued_keys: Box> = Box::new(queued_validators.iter() + .map(|k| (&k.0, k.1.get::(::ID) + .unwrap_or_default()))); + Tuple::on_new_session(changed, our_keys, queued_keys); + )* + ) + } + + fn on_before_session_ending() { + for_tuples!( #( Tuple::on_before_session_ending(); )* ) + } + + fn on_disabled(i: usize) { + for_tuples!( #( Tuple::on_disabled(i); )* ) } } -for_each_tuple!(impl_session_handlers); +/// `SessionHandler` for tests that use `UintAuthorityId` as `Keys`. +pub struct TestSessionHandler; +impl SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[sr_primitives::key_types::DUMMY]; + + fn on_genesis_session(_: &[(AId, Ks)]) {} + + fn on_new_session(_: bool, _: &[(AId, Ks)], _: &[(AId, Ks)]) {} + + fn on_before_session_ending() {} + + fn on_disabled(_: usize) {} +} /// Handler for selecting the genesis validator set. pub trait SelectInitialValidators { @@ -281,6 +358,12 @@ pub trait Trait: system::Trait { /// The keys. type Keys: OpaqueKeys + Member + Parameter + Default; + /// The fraction of validators set that is safe to be disabled. + /// + /// After the threshold is reached `disabled` method starts to return true, + /// which in combination with `srml_staking` forces a new era. + type DisabledValidatorsThreshold: Get; + /// Select initial validators. type SelectInitialValidators: SelectInitialValidators; } @@ -290,20 +373,23 @@ const DEDUP_KEY_PREFIX: &[u8] = b":session:keys"; decl_storage! { trait Store for Module as Session { /// The current set of validators. - Validators get(validators): Vec; + Validators get(fn validators): Vec; /// Current index of the session. - CurrentIndex get(current_index): SessionIndex; - - /// True if anything has changed in this session. - Changed: bool; + CurrentIndex get(fn current_index): SessionIndex; - /// Queued keys changed. + /// True if the underlying economic identities or weighting behind the validators + /// has changed in the queued validator set. QueuedChanged: bool; /// The queued keys for the next session. When the next session begins, these keys /// will be used to determine the validator's session keys. - QueuedKeys get(queued_keys): Vec<(T::ValidatorId, T::Keys)>; + QueuedKeys get(fn queued_keys): Vec<(T::ValidatorId, T::Keys)>; + + /// Indices of disabled validators. + /// + /// The set is cleared when `on_session_ending` returns a new set of identities. + DisabledValidators get(fn disabled_validators): Vec; /// The next session keys for a validator. /// @@ -319,38 +405,50 @@ decl_storage! { } add_extra_genesis { config(keys): Vec<(T::ValidatorId, T::Keys)>; - build(| - storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), - config: &GenesisConfig - | { - runtime_io::with_storage(storage, || { - for (who, keys) in config.keys.iter().cloned() { - assert!( - >::load_keys(&who).is_none(), - "genesis config contained duplicate validator {:?}", who, - ); - - >::do_set_keys(&who, keys) - .expect("genesis config must not contain duplicates; qed"); - } + build(|config: &GenesisConfig| { + if T::SessionHandler::KEY_TYPE_IDS.len() != T::Keys::key_ids().len() { + panic!("Number of keys in session handler and session keys does not match"); + } + + T::SessionHandler::KEY_TYPE_IDS.iter().zip(T::Keys::key_ids()).enumerate() + .for_each(|(i, (sk, kk))| { + if sk != kk { + panic!( + "Session handler and session key expect different key type at index: {}", + i, + ); + } + }); + + for (who, keys) in config.keys.iter().cloned() { + assert!( + >::load_keys(&who).is_none(), + "genesis config contained duplicate validator {:?}", who, + ); + + >::do_set_keys(&who, keys) + .expect("genesis config must not contain duplicates; qed"); + } + + let initial_validators = T::SelectInitialValidators::select_initial_validators() + .unwrap_or_else(|| config.keys.iter().map(|(ref v, _)| v.clone()).collect()); - let initial_validators = T::SelectInitialValidators::select_initial_validators() - .unwrap_or_else(|| config.keys.iter().map(|(ref v, _)| v.clone()).collect()); + assert!(!initial_validators.is_empty(), "Empty validator set in genesis block!"); - assert!(!initial_validators.is_empty(), "Empty validator set in genesis block!"); + let queued_keys: Vec<_> = initial_validators + .iter() + .cloned() + .map(|v| ( + v.clone(), + >::load_keys(&v).unwrap_or_default(), + )) + .collect(); - let queued_keys: Vec<_> = initial_validators - .iter() - .cloned() - .map(|v| ( - v.clone(), - >::load_keys(&v).unwrap_or_default(), - )) - .collect(); + // Tell everyone about the genesis session keys + T::SessionHandler::on_genesis_session::(&queued_keys); - >::put(initial_validators); - >::put(queued_keys); - }); + >::put(initial_validators); + >::put(queued_keys); }); } } @@ -394,13 +492,10 @@ decl_module! { Self::do_set_keys(&who, keys)?; - // Something changed. - Changed::put(true); - Ok(()) } - /// Called when a block is finalized. Will rotate session if it is the last + /// Called when a block is initialized. Will rotate session if it is the last /// block of the current session. fn on_initialize(n: T::BlockNumber) { if T::ShouldEndSession::should_end_session(n) { @@ -418,7 +513,9 @@ impl Module { let session_index = CurrentIndex::get(); let changed = QueuedChanged::get(); - let mut next_changed = Changed::take(); + + // Inform the session handlers that a session is going to end. + T::SessionHandler::on_before_session_ending(); // Get queued session keys and validators. let session_keys = >::get(); @@ -427,15 +524,24 @@ impl Module { .collect::>(); >::put(&validators); + if changed { + // reset disabled validators + DisabledValidators::take(); + } + let applied_at = session_index + 2; // Get next validator set. - let maybe_validators = T::OnSessionEnding::on_session_ending(session_index, applied_at); - let next_validators = if let Some(validators) = maybe_validators { - next_changed = true; - validators + let maybe_next_validators = T::OnSessionEnding::on_session_ending(session_index, applied_at); + let (next_validators, next_identities_changed) + = if let Some(validators) = maybe_next_validators + { + // NOTE: as per the documentation on `OnSessionEnding`, we consider + // the validator set as having changed even if the validators are the + // same as before, as underlying economic conditions may have changed. + (validators, true) } else { - >::get() + (>::get(), false) }; // Increment session index. @@ -443,9 +549,34 @@ impl Module { CurrentIndex::put(session_index); // Queue next session keys. - let queued_amalgamated = next_validators.into_iter() - .map(|a| { let k = Self::load_keys(&a).unwrap_or_default(); (a, k) }) - .collect::>(); + let (queued_amalgamated, next_changed) = { + // until we are certain there has been a change, iterate the prior + // validators along with the current and check for changes + let mut changed = next_identities_changed; + + let mut now_session_keys = session_keys.iter(); + let mut check_next_changed = |keys: &T::Keys| { + if changed { return } + // since a new validator set always leads to `changed` starting + // as true, we can ensure that `now_session_keys` and `next_validators` + // have the same length. this function is called once per iteration. + if let Some(&(_, ref old_keys)) = now_session_keys.next() { + if old_keys != keys { + changed = true; + return + } + } + }; + let queued_amalgamated = next_validators.into_iter() + .map(|a| { + let k = Self::load_keys(&a).unwrap_or_default(); + check_next_changed(&k); + (a, k) + }) + .collect::>(); + + (queued_amalgamated, changed) + }; >::put(queued_amalgamated.clone()); QueuedChanged::put(next_changed); @@ -454,18 +585,44 @@ impl Module { Self::deposit_event(Event::NewSession(session_index)); // Tell everyone about the new session keys. - T::SessionHandler::on_new_session::(changed, &session_keys, &queued_amalgamated); + T::SessionHandler::on_new_session::( + changed, + &session_keys, + &queued_amalgamated, + ); } /// Disable the validator of index `i`. - pub fn disable_index(i: usize) { - T::SessionHandler::on_disabled(i); - Changed::put(true); + /// + /// Returns `true` if this causes a `DisabledValidatorsThreshold` of validators + /// to be already disabled. + pub fn disable_index(i: usize) -> bool { + let (fire_event, threshold_reached) = DisabledValidators::mutate(|disabled| { + let i = i as u32; + if let Err(index) = disabled.binary_search(&i) { + let count = >::decode_len().unwrap_or(0) as u32; + let threshold = T::DisabledValidatorsThreshold::get() * count; + disabled.insert(index, i); + (true, disabled.len() as u32 > threshold) + } else { + (false, false) + } + }); + + if fire_event { + T::SessionHandler::on_disabled(i); + } + + threshold_reached } - /// Disable the validator identified by `c`. (If using with the staking module, this would be - /// their *stash* account.) - pub fn disable(c: &T::ValidatorId) -> rstd::result::Result<(), ()> { + /// Disable the validator identified by `c`. (If using with the staking module, + /// this would be their *stash* account.) + /// + /// Returns `Ok(true)` if more than `DisabledValidatorsThreshold` validators in current + /// session is already disabled. + /// If used with the staking module it allows to force a new era in such case. + pub fn disable(c: &T::ValidatorId) -> rstd::result::Result { Self::validators().iter().position(|i| i == c).map(Self::disable_index).ok_or(()) } @@ -475,23 +632,23 @@ impl Module { let old_keys = Self::load_keys(&who); for id in T::Keys::key_ids() { - let key = keys.get_raw(id); + let key = keys.get_raw(*id); // ensure keys are without duplication. ensure!( - Self::key_owner(id, key).map_or(true, |owner| &owner == who), + Self::key_owner(*id, key).map_or(true, |owner| &owner == who), "registered duplicate key" ); - if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(id)) { + if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(*id)) { if key == old { continue; } - Self::clear_key_owner(id, old); + Self::clear_key_owner(*id, old); } - Self::put_key_owner(id, key, &who); + Self::put_key_owner(*id, key, &who); } Self::put_keys(&who, &keys); @@ -502,11 +659,9 @@ impl Module { fn prune_dead_keys(who: &T::ValidatorId) { if let Some(old_keys) = Self::take_keys(who) { for id in T::Keys::key_ids() { - let key_data = old_keys.get_raw(id); - Self::clear_key_owner(id, key_data); + let key_data = old_keys.get_raw(*id); + Self::clear_key_owner(*id, key_data); } - - Changed::put(true); } } @@ -523,15 +678,15 @@ impl Module { } fn key_owner(id: KeyTypeId, key_data: &[u8]) -> Option { - >::get(DEDUP_KEY_PREFIX, &(id, key_data.to_vec())) + >::get(DEDUP_KEY_PREFIX, (id, key_data)) } fn put_key_owner(id: KeyTypeId, key_data: &[u8], v: &T::ValidatorId) { - >::insert(DEDUP_KEY_PREFIX, &(id, key_data.to_vec()), v) + >::insert(DEDUP_KEY_PREFIX, (id, key_data), v) } fn clear_key_owner(id: KeyTypeId, key_data: &[u8]) { - >::remove(DEDUP_KEY_PREFIX, &(id, key_data.to_vec())); + >::remove(DEDUP_KEY_PREFIX, (id, key_data)); } } @@ -562,19 +717,16 @@ impl> FindAuthor #[cfg(test)] mod tests { use super::*; - use srml_support::assert_ok; - use runtime_io::with_externalities; - use primitives::{Blake2Hasher, crypto::key_types::DUMMY}; - use sr_primitives::{ - traits::OnInitialize, - testing::UintAuthorityId, - }; + use support::assert_ok; + use primitives::crypto::key_types::DUMMY; + use sr_primitives::{traits::OnInitialize, testing::UintAuthorityId}; use mock::{ NEXT_VALIDATORS, SESSION_CHANGED, TEST_SESSION_CHANGED, authorities, force_new_session, set_next_validators, set_session_length, session_changed, Test, Origin, System, Session, + reset_before_session_end_called, before_session_end_called, }; - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig:: { keys: NEXT_VALIDATORS.with(|l| @@ -592,7 +744,7 @@ mod tests { #[test] fn simple_setup_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); assert_eq!(Session::validators(), vec![1, 2, 3]); }); @@ -600,7 +752,7 @@ mod tests { #[test] fn put_get_keys() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { Session::put_keys(&10, &UintAuthorityId(10).into()); assert_eq!(Session::load_keys(&10), Some(UintAuthorityId(10).into())); }) @@ -609,7 +761,7 @@ mod tests { #[test] fn keys_cleared_on_kill() { let mut ext = new_test_ext(); - with_externalities(&mut ext, || { + ext.execute_with(|| { assert_eq!(Session::validators(), vec![1, 2, 3]); assert_eq!(Session::load_keys(&1), Some(UintAuthorityId(1).into())); @@ -619,14 +771,14 @@ mod tests { Session::on_free_balance_zero(&1); assert_eq!(Session::load_keys(&1), None); assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), None); - - assert!(Changed::get()); }) } #[test] fn authorities_should_track_validators() { - with_externalities(&mut new_test_ext(), || { + reset_before_session_end_called(); + + new_test_ext().execute_with(|| { set_next_validators(vec![1, 2]); force_new_session(); initialize_block(1); @@ -636,6 +788,8 @@ mod tests { ]); assert_eq!(Session::validators(), vec![1, 2, 3]); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + assert!(before_session_end_called()); + reset_before_session_end_called(); force_new_session(); initialize_block(2); @@ -645,6 +799,8 @@ mod tests { ]); assert_eq!(Session::validators(), vec![1, 2]); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); + assert!(before_session_end_called()); + reset_before_session_end_called(); set_next_validators(vec![1, 2, 4]); assert_ok!(Session::set_keys(Origin::signed(4), UintAuthorityId(4).into(), vec![])); @@ -657,6 +813,7 @@ mod tests { ]); assert_eq!(Session::validators(), vec![1, 2]); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); + assert!(before_session_end_called()); force_new_session(); initialize_block(4); @@ -672,7 +829,7 @@ mod tests { #[test] fn should_work_with_early_exit() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { set_session_length(10); initialize_block(1); @@ -695,7 +852,7 @@ mod tests { #[test] fn session_change_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { // Block 1: No change initialize_block(1); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); @@ -725,7 +882,7 @@ mod tests { #[test] fn duplicates_are_not_allowed() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::set_block_number(1); Session::on_initialize(1); assert!(Session::set_keys(Origin::signed(4), UintAuthorityId(1).into(), vec![]).is_err()); @@ -738,38 +895,63 @@ mod tests { #[test] fn session_changed_flag_works() { - with_externalities(&mut new_test_ext(), || { + reset_before_session_end_called(); + + new_test_ext().execute_with(|| { TEST_SESSION_CHANGED.with(|l| *l.borrow_mut() = true); force_new_session(); initialize_block(1); assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); force_new_session(); initialize_block(2); assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); Session::disable_index(0); force_new_session(); initialize_block(3); assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); force_new_session(); initialize_block(4); assert!(session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); force_new_session(); initialize_block(5); assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); assert_ok!(Session::set_keys(Origin::signed(2), UintAuthorityId(5).into(), vec![])); force_new_session(); initialize_block(6); assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + // changing the keys of a validator leads to change. + assert_ok!(Session::set_keys(Origin::signed(69), UintAuthorityId(69).into(), vec![])); force_new_session(); initialize_block(7); assert!(session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); + + // while changing the keys of a non-validator does not. + force_new_session(); + initialize_block(7); + assert!(!session_changed()); + assert!(before_session_end_called()); + reset_before_session_end_called(); }); } @@ -804,7 +986,7 @@ mod tests { #[test] fn session_keys_generate_output_works_as_set_keys_input() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let new_keys = mock::MockSessionKeys::generate(None); assert_ok!( Session::set_keys( @@ -815,4 +997,21 @@ mod tests { ); }); } + + #[test] + fn return_true_if_more_than_third_is_disabled() { + new_test_ext().execute_with(|| { + set_next_validators(vec![1, 2, 3, 4, 5, 6, 7]); + force_new_session(); + initialize_block(1); + // apply the new validator set + force_new_session(); + initialize_block(2); + + assert_eq!(Session::disable_index(0), false); + assert_eq!(Session::disable_index(1), false); + assert_eq!(Session::disable_index(2), true); + assert_eq!(Session::disable_index(3), true); + }); + } } diff --git a/srml/session/src/mock.rs b/srml/session/src/mock.rs index 66bf93032d29f5ed41dd5f657645699d6f163af7..cb95a35570bc1e37455446fff6404e825f83c32c 100644 --- a/srml/session/src/mock.rs +++ b/srml/session/src/mock.rs @@ -18,16 +18,16 @@ use super::*; use std::cell::RefCell; -use srml_support::{impl_outer_origin, parameter_types}; +use support::{impl_outer_origin, parameter_types}; use primitives::{crypto::key_types::DUMMY, H256}; use sr_primitives::{ Perbill, impl_opaque_keys, traits::{BlakeTwo256, IdentityLookup, ConvertInto}, testing::{Header, UintAuthorityId} }; +use sr_staking_primitives::SessionIndex; impl_opaque_keys! { pub struct MockSessionKeys { - #[id(DUMMY)] pub dummy: UintAuthorityId, } } @@ -43,6 +43,7 @@ impl_outer_origin! { } thread_local! { + pub static VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); pub static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); pub static AUTHORITIES: RefCell> = RefCell::new(vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); @@ -50,6 +51,9 @@ thread_local! { pub static SESSION_LENGTH: RefCell = RefCell::new(2); pub static SESSION_CHANGED: RefCell = RefCell::new(false); pub static TEST_SESSION_CHANGED: RefCell = RefCell::new(false); + pub static DISABLED: RefCell = RefCell::new(false); + // Stores if `on_before_session_end` was called + pub static BEFORE_SESSION_END_CALLED: RefCell = RefCell::new(false); } pub struct TestShouldEndSession; @@ -62,6 +66,8 @@ impl ShouldEndSession for TestShouldEndSession { pub struct TestSessionHandler; impl SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [sr_primitives::KeyTypeId] = &[UintAuthorityId::ID]; + fn on_genesis_session(_validators: &[(u64, T)]) {} fn on_new_session( changed: bool, validators: &[(u64, T)], @@ -74,14 +80,27 @@ impl SessionHandler for TestSessionHandler { .collect() ); } - fn on_disabled(_validator_index: usize) {} + fn on_disabled(_validator_index: usize) { + DISABLED.with(|l| *l.borrow_mut() = true) + } + fn on_before_session_ending() { + BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = true); + } } pub struct TestOnSessionEnding; impl OnSessionEnding for TestOnSessionEnding { fn on_session_ending(_: SessionIndex, _: SessionIndex) -> Option> { if !TEST_SESSION_CHANGED.with(|l| *l.borrow()) { - Some(NEXT_VALIDATORS.with(|l| l.borrow().clone())) + VALIDATORS.with(|v| { + let mut v = v.borrow_mut(); + *v = NEXT_VALIDATORS.with(|l| l.borrow().clone()); + Some(v.clone()) + }) + } else if DISABLED.with(|l| std::mem::replace(&mut *l.borrow_mut(), false)) { + // If there was a disabled validator, underlying conditions have changed + // so we return `Some`. + Some(VALIDATORS.with(|v| v.borrow().clone())) } else { None } @@ -90,16 +109,13 @@ impl OnSessionEnding for TestOnSessionEnding { #[cfg(feature = "historical")] impl crate::historical::OnSessionEnding for TestOnSessionEnding { - fn on_session_ending(_: SessionIndex, _: SessionIndex) + fn on_session_ending(ending_index: SessionIndex, will_apply_at: SessionIndex) -> Option<(Vec, Vec<(u64, u64)>)> { - if !TEST_SESSION_CHANGED.with(|l| *l.borrow()) { - let last_validators = Session::validators(); - let last_identifications = last_validators.into_iter().map(|v| (v, v)).collect(); - Some((NEXT_VALIDATORS.with(|l| l.borrow().clone()), last_identifications)) - } else { - None - } + let pair_with_ids = |vals: &[u64]| vals.iter().map(|&v| (v, v)).collect::>(); + >::on_session_ending(ending_index, will_apply_at) + .map(|vals| (pair_with_ids(&vals), vals)) + .map(|(ids, vals)| (vals, ids)) } } @@ -123,8 +139,17 @@ pub fn set_next_validators(next: Vec) { NEXT_VALIDATORS.with(|v| *v.borrow_mut() = next); } +pub fn before_session_end_called() -> bool { + BEFORE_SESSION_END_CALLED.with(|b| *b.borrow()) +} + +pub fn reset_before_session_end_called() { + BEFORE_SESSION_END_CALLED.with(|b| *b.borrow_mut() = false); +} + #[derive(Clone, Eq, PartialEq)] pub struct Test; + parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: u32 = 1024; @@ -143,12 +168,12 @@ impl system::Trait for Test { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } impl timestamp::Trait for Test { @@ -157,6 +182,10 @@ impl timestamp::Trait for Test { type MinimumPeriod = MinimumPeriod; } +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(33); +} + impl Trait for Test { type ShouldEndSession = TestShouldEndSession; #[cfg(feature = "historical")] @@ -169,6 +198,7 @@ impl Trait for Test { type Keys = MockSessionKeys; type Event = (); type SelectInitialValidators = (); + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; } #[cfg(feature = "historical")] diff --git a/srml/staking/Cargo.toml b/srml/staking/Cargo.toml index 5428d663f3f44cc7b0ab3c2d8f217dcf1717820d..67f3ab41d6583f73deb70ff2e6b01539e73182c6 100644 --- a/srml/staking/Cargo.toml +++ b/srml/staking/Cargo.toml @@ -5,14 +5,16 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } substrate-keyring = { path = "../../core/keyring", optional = true } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +phragmen = { package = "substrate-phragmen", path = "../../core/phragmen", default-features = false } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +sr-staking-primitives = { path = "../../core/sr-staking-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } session = { package = "srml-session", path = "../session", default-features = false, features = ["historical"] } authorship = { package = "srml-authorship", path = "../authorship", default-features = false } @@ -21,11 +23,10 @@ authorship = { package = "srml-authorship", path = "../authorship", default-feat primitives = { package = "substrate-primitives", path = "../../core/primitives" } balances = { package = "srml-balances", path = "../balances" } timestamp = { package = "srml-timestamp", path = "../timestamp" } -rand = "0.6.5" +srml-staking-reward-curve = { path = "../staking/reward-curve"} [features] equalize = [] -bench = [] default = ["std", "equalize"] std = [ "serde", @@ -33,9 +34,11 @@ std = [ "substrate-keyring", "codec/std", "rstd/std", - "runtime_io/std", - "srml-support/std", + "phragmen/std", + "runtime-io/std", + "support/std", "sr-primitives/std", + "sr-staking-primitives/std", "session/std", "system/std", "authorship/std", diff --git a/srml/staking/reward-curve/Cargo.toml b/srml/staking/reward-curve/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b33323a5e319073c2c1a2534e02dba3527e5bfc2 --- /dev/null +++ b/srml/staking/reward-curve/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "srml-staking-reward-curve" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "1.0.7", features = [ "full", "visit" ] } +quote = "1.0" +proc-macro2 = "1.0.6" +proc-macro-crate = "0.1.4" + +[dev-dependencies] +sr-primitives = { path = "../../../core/sr-primitives" } diff --git a/srml/staking/reward-curve/src/lib.rs b/srml/staking/reward-curve/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7e1f1e6aa945f1b9a961c7b8da547c5248dca6cd --- /dev/null +++ b/srml/staking/reward-curve/src/lib.rs @@ -0,0 +1,416 @@ +extern crate proc_macro; + +mod log; + +use log::log2; +use proc_macro::TokenStream; +use proc_macro2::{TokenStream as TokenStream2, Span}; +use proc_macro_crate::crate_name; +use quote::{quote, ToTokens}; +use std::convert::TryInto; +use syn::parse::{Parse, ParseStream}; + +/// Accepts a number of expressions to create a instance of PiecewiseLinear which represents the +/// NPoS curve (as detailed +/// [here](http://research.web3.foundation/en/latest/polkadot/Token%20Economics/#inflation-model)) +/// for those parameters. Parameters are: +/// - `min_inflation`: the minimal amount to be rewarded between validators, expressed as a fraction +/// of total issuance. Known as `I_0` in the literature. +/// Expressed in millionth, must be between 0 and 1_000_000. +/// +/// - `max_inflation`: the maximum amount to be rewarded between validators, expressed as a fraction +/// of total issuance. This is attained only when `ideal_stake` is achieved. +/// Expressed in millionth, must be between min_inflation and 1_000_000. +/// +/// - `ideal_stake`: the fraction of total issued tokens that should be actively staked behind +/// validators. Known as `x_ideal` in the literature. +/// Expressed in millionth, must be between 0_100_000 and 0_900_000. +/// +/// - `falloff`: Known as `decay_rate` in the literature. A co-efficient dictating the strength of +/// the global incentivisation to get the `ideal_stake`. A higher number results in less typical +/// inflation at the cost of greater volatility for validators. +/// Expressed in millionth, must be between 0 and 1_000_000. +/// +/// - `max_piece_count`: The maximum number of pieces in the curve. A greater number uses more +/// resources but results in higher accuracy. +/// Must be between 2 and 1_000. +/// +/// - `test_precision`: The maximum error allowed in the generated test. +/// Expressed in millionth, must be between 0 and 1_000_000. +/// +/// # Example +/// +/// ``` +/// # fn main() {} +/// use sr_primitives::curve::PiecewiseLinear; +/// +/// srml_staking_reward_curve::build! { +/// const I_NPOS: PiecewiseLinear<'static> = curve!( +/// min_inflation: 0_025_000, +/// max_inflation: 0_100_000, +/// ideal_stake: 0_500_000, +/// falloff: 0_050_000, +/// max_piece_count: 40, +/// test_precision: 0_005_000, +/// ); +/// } +/// ``` +#[proc_macro] +pub fn build(input: TokenStream) -> TokenStream { + let input = syn::parse_macro_input!(input as INposInput); + + let points = compute_points(&input); + + let declaration = generate_piecewise_linear(points); + let test_module = generate_test_module(&input); + + let imports = match crate_name("sr-primitives") { + Ok(sr_primitives) => { + let ident = syn::Ident::new(&sr_primitives, Span::call_site()); + quote!( extern crate #ident as _sr_primitives; ) + }, + Err(e) => syn::Error::new(Span::call_site(), &e).to_compile_error(), + }; + + let const_name = input.ident; + let const_type = input.typ; + + quote!( + const #const_name: #const_type = { + #imports + #declaration + }; + #test_module + ).into() +} + +const MILLION: u32 = 1_000_000; + +mod keyword { + syn::custom_keyword!(curve); + syn::custom_keyword!(min_inflation); + syn::custom_keyword!(max_inflation); + syn::custom_keyword!(ideal_stake); + syn::custom_keyword!(falloff); + syn::custom_keyword!(max_piece_count); + syn::custom_keyword!(test_precision); +} + +struct INposInput { + ident: syn::Ident, + typ: syn::Type, + min_inflation: u32, + ideal_stake: u32, + max_inflation: u32, + falloff: u32, + max_piece_count: u32, + test_precision: u32, +} + +struct Bounds { + min: u32, + min_strict: bool, + max: u32, + max_strict: bool, +} + +impl Bounds { + fn check(&self, value: u32) -> bool { + let wrong = (self.min_strict && value <= self.min) + || (!self.min_strict && value < self.min) + || (self.max_strict && value >= self.max) + || (!self.max_strict && value > self.max); + + !wrong + } +} + +impl core::fmt::Display for Bounds { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!( + f, + "{}{:07}; {:07}{}", + if self.min_strict { "]" } else { "[" }, + self.min, + self.max, + if self.max_strict { "[" } else { "]" }, + ) + } +} + +fn parse_field(input: ParseStream, bounds: Bounds) + -> syn::Result +{ + ::parse(&input)?; + ::parse(&input)?; + let value_lit = syn::LitInt::parse(&input)?; + let value: u32 = value_lit.base10_parse()?; + if !bounds.check(value) { + return Err(syn::Error::new(value_lit.span(), format!( + "Invalid {}: {}, must be in {}", Token::default().to_token_stream(), value, bounds, + ))); + } + + Ok(value) +} + +impl Parse for INposInput { + fn parse(input: ParseStream) -> syn::Result { + let args_input; + + ::parse(&input)?; + let ident = ::parse(&input)?; + ::parse(&input)?; + let typ = ::parse(&input)?; + ::parse(&input)?; + ::parse(&input)?; + ::parse(&input)?; + syn::parenthesized!(args_input in input); + ::parse(&input)?; + + if !input.is_empty() { + return Err(input.error("expected end of input stream, no token expected")); + } + + let min_inflation = parse_field::(&args_input, Bounds { + min: 0, + min_strict: true, + max: 1_000_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let max_inflation = parse_field::(&args_input, Bounds { + min: min_inflation, + min_strict: true, + max: 1_000_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let ideal_stake = parse_field::(&args_input, Bounds { + min: 0_100_000, + min_strict: false, + max: 0_900_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let falloff = parse_field::(&args_input, Bounds { + min: 0_010_000, + min_strict: false, + max: 1_000_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let max_piece_count = parse_field::(&args_input, Bounds { + min: 2, + min_strict: false, + max: 1_000, + max_strict: false, + })?; + ::parse(&args_input)?; + let test_precision = parse_field::(&args_input, Bounds { + min: 0, + min_strict: false, + max: 1_000_000, + max_strict: false, + })?; + >::parse(&args_input)?; + + if !args_input.is_empty() { + return Err(args_input.error("expected end of input stream, no token expected")); + } + + Ok(Self { + ident, + typ, + min_inflation, + ideal_stake, + max_inflation, + falloff, + max_piece_count, + test_precision, + }) + } +} + +struct INPoS { + i_0: u32, + i_ideal_times_x_ideal: u32, + i_ideal: u32, + x_ideal: u32, + d: u32, +} + +impl INPoS { + fn from_input(input: &INposInput) -> Self { + INPoS { + i_0: input.min_inflation, + i_ideal: (input.max_inflation as u64 * MILLION as u64 / input.ideal_stake as u64) + .try_into().unwrap(), + i_ideal_times_x_ideal: input.max_inflation, + x_ideal: input.ideal_stake, + d: input.falloff, + } + } + + fn compute_opposite_after_x_ideal(&self, y: u32) -> u32 { + if y == self.i_0 { + return u32::max_value(); + } + let log = log2(self.i_ideal_times_x_ideal - self.i_0, y - self.i_0); + + let term: u32 = ((self.d as u64 * log as u64) / 1_000_000).try_into().unwrap(); + + self.x_ideal + term + } +} + +fn compute_points(input: &INposInput) -> Vec<(u32, u32)> { + let inpos = INPoS::from_input(input); + + let mut points = vec![]; + points.push((0, inpos.i_0)); + points.push((inpos.x_ideal, inpos.i_ideal_times_x_ideal)); + + // For each point p: (next_p.0 - p.0) < segment_lenght && (next_p.1 - p.1) < segment_lenght. + // This ensures that the total number of segment doesn't overflow max_piece_count. + let max_length = (input.max_inflation - input.min_inflation + 1_000_000 - inpos.x_ideal) + / (input.max_piece_count - 1); + + let mut delta_y = max_length; + let mut y = input.max_inflation; + + // The algorithm divide the curve in segment with vertical len and horizontal len less + // than `max_length`. This is not very accurate in case of very consequent steep. + while delta_y != 0 { + let next_y = y - delta_y; + + if next_y <= input.min_inflation { + delta_y = delta_y.saturating_sub(1); + continue + } + + let next_x = inpos.compute_opposite_after_x_ideal(next_y); + + if (next_x - points.last().unwrap().0) > max_length { + delta_y = delta_y.saturating_sub(1); + continue + } + + if next_x >= 1_000_000 { + let prev = points.last().unwrap(); + // Compute the y corresponding to x=1_000_000 using the this point and the previous one. + + let delta_y: u32 = ( + (next_x - 1_000_000) as u64 + * (prev.1 - next_y) as u64 + / (next_x - prev.0) as u64 + ).try_into().unwrap(); + + let y = next_y + delta_y; + + points.push((1_000_000, y)); + return points; + } + points.push((next_x, next_y)); + y = next_y; + } + + points.push((1_000_000, inpos.i_0)); + + points +} + +fn generate_piecewise_linear(points: Vec<(u32, u32)>) -> TokenStream2 { + let mut points_tokens = quote!(); + + for (x, y) in points { + let error = || panic!(format!( + "Generated reward curve approximation doesn't fit into [0, 1] -> [0, 1] \ + because of point: + x = {:07} per million + y = {:07} per million", + x, y + )); + + let x_perbill = x.checked_mul(1_000).unwrap_or_else(error); + let y_perbill = y.checked_mul(1_000).unwrap_or_else(error); + + points_tokens.extend(quote!( + ( + _sr_primitives::Perbill::from_parts(#x_perbill), + _sr_primitives::Perbill::from_parts(#y_perbill), + ), + )); + } + + quote!( + _sr_primitives::curve::PiecewiseLinear::<'static> { + points: & [ #points_tokens ], + } + ) +} + +fn generate_test_module(input: &INposInput) -> TokenStream2 { + let inpos = INPoS::from_input(input); + + let ident = &input.ident; + let precision = input.test_precision; + let i_0 = inpos.i_0 as f64/ MILLION as f64; + let i_ideal_times_x_ideal = inpos.i_ideal_times_x_ideal as f64 / MILLION as f64; + let i_ideal = inpos.i_ideal as f64 / MILLION as f64; + let x_ideal = inpos.x_ideal as f64 / MILLION as f64; + let d = inpos.d as f64 / MILLION as f64; + let max_piece_count = input.max_piece_count; + + quote!( + #[cfg(test)] + mod __srml_staking_reward_curve_test_module { + fn i_npos(x: f64) -> f64 { + if x <= #x_ideal { + #i_0 + x * (#i_ideal - #i_0 / #x_ideal) + } else { + #i_0 + (#i_ideal_times_x_ideal - #i_0) * 2_f64.powf((#x_ideal - x) / #d) + } + } + + const MILLION: u32 = 1_000_000; + + #[test] + fn reward_curve_precision() { + for &base in [MILLION, u32::max_value()].into_iter() { + let number_of_check = 100_000.min(base); + for check_index in 0..=number_of_check { + let i = (check_index as u64 * base as u64 / number_of_check as u64) as u32; + let x = i as f64 / base as f64; + let float_res = (i_npos(x) * base as f64).round() as u32; + let int_res = super::#ident.calculate_for_fraction_times_denominator(i, base); + let err = ( + (float_res.max(int_res) - float_res.min(int_res)) as u64 + * MILLION as u64 + / float_res as u64 + ) as u32; + if err > #precision { + panic!(format!("\n\ + Generated reward curve approximation differ from real one:\n\t\ + for i = {} and base = {}, f(i/base) * base = {},\n\t\ + but approximation = {},\n\t\ + err = {:07} millionth,\n\t\ + try increase the number of segment: {} or the test_error: {}.\n", + i, base, float_res, int_res, err, #max_piece_count, #precision + )); + } + } + } + } + + #[test] + fn reward_curve_piece_count() { + assert!( + super::#ident.points.len() as u32 - 1 <= #max_piece_count, + "Generated reward curve approximation is invalid: \ + has more points than specified, please fill an issue." + ); + } + } + ).into() +} diff --git a/srml/staking/reward-curve/src/log.rs b/srml/staking/reward-curve/src/log.rs new file mode 100644 index 0000000000000000000000000000000000000000..1a25dbb98628bd1b526fea508158490945d2a6da --- /dev/null +++ b/srml/staking/reward-curve/src/log.rs @@ -0,0 +1,70 @@ +use std::convert::TryInto; + +/// Return Per-million value. +pub fn log2(p: u32, q: u32) -> u32 { + assert!(p >= q); + assert!(p <= u32::max_value()/2); + + // This restriction should not be mandatory. But function is only tested and used for this. + assert!(p <= 1_000_000); + assert!(q <= 1_000_000); + + if p == q { + return 0 + } + + let mut n = 0u32; + while !(p >= 2u32.pow(n)*q) || !(p < 2u32.pow(n+1)*q) { + n += 1; + } + assert!(p < 2u32.pow(n+1) * q); + + let y_num: u32 = (p - 2u32.pow(n) * q).try_into().unwrap(); + let y_den: u32 = (p + 2u32.pow(n) * q).try_into().unwrap(); + + let _2_div_ln_2 = 2_885_390u32; + + let taylor_term = |k: u32| -> u32 { + if k == 0 { + (_2_div_ln_2 as u128 * (y_num as u128).pow(1) / (y_den as u128).pow(1)) + .try_into().unwrap() + } else { + let mut res = _2_div_ln_2 as u128 * (y_num as u128).pow(3) / (y_den as u128).pow(3); + for _ in 1..k { + res = res * (y_num as u128).pow(2) / (y_den as u128).pow(2); + } + res /= 2 * k as u128 + 1; + + res.try_into().unwrap() + } + }; + + let mut res = n * 1_000_000u32; + let mut k = 0; + loop { + let term = taylor_term(k); + if term == 0 { + break + } + + res += term; + k += 1; + } + + res +} + +#[test] +fn test_log() { + let div = 1_000; + for p in 0..=div { + for q in 1..=p { + let p: u32 = (1_000_000 as u64 * p as u64 / div as u64).try_into().unwrap(); + let q: u32 = (1_000_000 as u64 * q as u64 / div as u64).try_into().unwrap(); + + let res = - (log2(p, q) as i64); + let expected = ((q as f64 / p as f64).log(2.0) * 1_000_000 as f64).round() as i64; + assert!((res - expected).abs() <= 6); + } + } +} diff --git a/srml/staking/reward-curve/tests/test.rs b/srml/staking/reward-curve/tests/test.rs new file mode 100644 index 0000000000000000000000000000000000000000..55a3b7d383e9e618bcce18ee00106f015bee7b3a --- /dev/null +++ b/srml/staking/reward-curve/tests/test.rs @@ -0,0 +1,44 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test crate for srml-staking-reward-curve. Allows to test for procedural macro. +//! See tests directory. + +mod test_small_falloff { + srml_staking_reward_curve::build! { + const REWARD_CURVE: sr_primitives::curve::PiecewiseLinear<'static> = curve!( + min_inflation: 0_020_000, + max_inflation: 0_200_000, + ideal_stake: 0_600_000, + falloff: 0_010_000, + max_piece_count: 200, + test_precision: 0_005_000, + ); + } +} + +mod test_big_falloff { + srml_staking_reward_curve::build! { + const REWARD_CURVE: sr_primitives::curve::PiecewiseLinear<'static> = curve!( + min_inflation: 0_100_000, + max_inflation: 0_400_000, + ideal_stake: 0_400_000, + falloff: 1_000_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); + } +} diff --git a/srml/staking/src/benches.rs b/srml/staking/src/benches.rs deleted file mode 100644 index 6e79ee70a47a26dedd201494e5e92adfb8943293..0000000000000000000000000000000000000000 --- a/srml/staking/src/benches.rs +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2019 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Benchmarks of the phragmen election algorithm. -//! Note that execution times will not be accurate in an absolute scale, since -//! - Everything is executed in the context of `TestExternalities` -//! - Everything is executed in native environment. -//! -//! Run using: -//! -//! ```zsh -//! cargo bench --features bench --color always -//! ``` - -use test::Bencher; -use runtime_io::with_externalities; -use mock::*; -use super::*; -use rand::{self, Rng}; - -const VALIDATORS: u64 = 1000; -const NOMINATORS: u64 = 10_000; -const EDGES: u64 = 2; -const TO_ELECT: usize = 100; -const STAKE: u64 = 1000; - -fn do_phragmen( - b: &mut Bencher, - num_vals: u64, - num_noms: u64, - count: usize, - votes_per: u64, - eq_iters: usize, - eq_tolerance: u128, -) { - with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { - assert!(num_vals > votes_per); - let rr = |a, b| rand::thread_rng().gen_range(a as usize, b as usize) as u64; - - // prefix to distinguish the validator and nominator account ranges. - let np = 10_000; - - (1 ..= 2*num_vals) - .step_by(2) - .for_each(|acc| bond_validator(acc, STAKE + rr(10, 50))); - - (np ..= (np + 2*num_noms)) - .step_by(2) - .for_each(|acc| { - let mut stashes_to_vote = (1 ..= 2*num_vals) - .step_by(2) - .map(|ctrl| ctrl + 1) - .collect::>(); - let votes = (0 .. votes_per) - .map(|_| { - stashes_to_vote.remove(rr(0, stashes_to_vote.len()) as usize) - }) - .collect::>(); - bond_nominator(acc, STAKE + rr(10, 50), votes); - }); - - b.iter(|| { - let r = phragmen::elect::( - count, - 1_usize, - >::enumerate(), - >::enumerate(), - Staking::slashable_balance_of - ).unwrap(); - - // Do the benchmarking with equalize. - if eq_iters > 0 { - let elected_stashes = r.0; - let assignments = r.1; - - let to_balance = |b: ExtendedBalance| - <::CurrencyToVote as Convert>::convert(b); - let to_votes = |b: Balance| - <::CurrencyToVote as Convert>::convert(b) as ExtendedBalance; - let ratio_of = |b, p| (p as ExtendedBalance).saturating_mul(to_votes(b)) / ACCURACY; - - let assignments_with_stakes = assignments.into_iter().map(|(n, a)|( - n, - Staking::slashable_balance_of(&n), - a.into_iter().map(|(acc, r)| ( - acc.clone(), - r, - to_balance(ratio_of(Staking::slashable_balance_of(&n), r)), - )) - .collect::>>() - )).collect::>)>>(); - - let mut exposures = >::new(); - elected_stashes - .into_iter() - .map(|e| (e, Staking::slashable_balance_of(&e))) - .for_each(|(e, s)| { - let item = Exposure { own: s, total: s, ..Default::default() }; - exposures.insert(e, item); - }); - - for (n, _, assignment) in &assignments_with_stakes { - for (c, _, s) in assignment { - if let Some(expo) = exposures.get_mut(c) { - expo.total = expo.total.saturating_add(*s); - expo.others.push( IndividualExposure { who: n.clone(), value: *s } ); - } - } - } - - let mut assignments_with_votes = assignments_with_stakes.into_iter() - .map(|a| ( - a.0, a.1, - a.2.into_iter() - .map(|e| (e.0, e.1, to_votes(e.2))) - .collect::>() - )) - .collect:: - )>>(); - equalize::(&mut assignments_with_votes, &mut exposures, eq_tolerance, eq_iters); - } - }) - }) -} - -macro_rules! phragmen_benches { - ($($name:ident: $tup:expr,)*) => { - $( - #[bench] - fn $name(b: &mut Bencher) { - let (v, n, t, e, eq_iter, eq_tol) = $tup; - println!(""); - println!( - r#" -++ Benchmark: {} Validators // {} Nominators // {} Edges-per-nominator // {} total edges // -electing {} // Equalize: {} iterations -- {} tolerance"#, - v, n, e, e * n, t, eq_iter, eq_tol, - ); - do_phragmen(b, v, n, t, e, eq_iter, eq_tol); - } - )* - } -} - -phragmen_benches! { - bench_1_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0), - bench_1_2: (VALIDATORS*2, NOMINATORS, TO_ELECT, EDGES, 0, 0), - bench_1_3: (VALIDATORS*4, NOMINATORS, TO_ELECT, EDGES, 0, 0), - bench_1_4: (VALIDATORS*8, NOMINATORS, TO_ELECT, EDGES, 0, 0), - bench_1_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), - bench_1_2_eq: (VALIDATORS*2, NOMINATORS, TO_ELECT, EDGES, 2, 0), - bench_1_3_eq: (VALIDATORS*4, NOMINATORS, TO_ELECT, EDGES, 2, 0), - bench_1_4_eq: (VALIDATORS*8, NOMINATORS, TO_ELECT, EDGES, 2, 0), - - bench_0_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0), - bench_0_2: (VALIDATORS, NOMINATORS, TO_ELECT * 4, EDGES, 0, 0), - bench_0_3: (VALIDATORS, NOMINATORS, TO_ELECT * 8, EDGES, 0, 0), - bench_0_4: (VALIDATORS, NOMINATORS, TO_ELECT * 16, EDGES , 0, 0), - bench_0_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), - bench_0_2_eq: (VALIDATORS, NOMINATORS, TO_ELECT * 4, EDGES, 2, 0), - bench_0_3_eq: (VALIDATORS, NOMINATORS, TO_ELECT * 8, EDGES, 2, 0), - bench_0_4_eq: (VALIDATORS, NOMINATORS, TO_ELECT * 16, EDGES , 2, 0), - - bench_2_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0), - bench_2_2: (VALIDATORS, NOMINATORS*2, TO_ELECT, EDGES, 0, 0), - bench_2_3: (VALIDATORS, NOMINATORS*4, TO_ELECT, EDGES, 0, 0), - bench_2_4: (VALIDATORS, NOMINATORS*8, TO_ELECT, EDGES, 0, 0), - bench_2_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), - bench_2_2_eq: (VALIDATORS, NOMINATORS*2, TO_ELECT, EDGES, 2, 0), - bench_2_3_eq: (VALIDATORS, NOMINATORS*4, TO_ELECT, EDGES, 2, 0), - bench_2_4_eq: (VALIDATORS, NOMINATORS*8, TO_ELECT, EDGES, 2, 0), - - bench_3_1: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 0, 0 ), - bench_3_2: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*2, 0, 0), - bench_3_3: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*4, 0, 0), - bench_3_4: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*8, 0, 0), - bench_3_1_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES, 2, 0), - bench_3_2_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*2, 2, 0), - bench_3_3_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*4, 2, 0), - bench_3_4_eq: (VALIDATORS, NOMINATORS, TO_ELECT, EDGES*8, 2, 0), -} diff --git a/srml/staking/src/inflation.rs b/srml/staking/src/inflation.rs index 80065886d7cac6a545a33391db4e4c41087e716f..89326b92c0fd11359963b04067c9d741b98a5295 100644 --- a/srml/staking/src/inflation.rs +++ b/srml/staking/src/inflation.rs @@ -18,369 +18,77 @@ //! the total payout for the era given the era duration and the staking rate in NPoS. //! The staking rate in NPoS is the total amount of tokens staked by nominators and validators, //! divided by the total token supply. -//! -//! This payout is computed from the desired yearly inflation `I_NPoS`. -//! -//! `I_NPoS` is defined as such: -//! -//! let's introduce some constant: -//! * `I0` represents a tight upper-bound on our estimate of the operational costs of all -//! validators, expressed as a fraction of the total token supply. I_NPoS must be always -//! superior or equal to this value. -//! * `x_ideal` the ideal staking rate in NPoS. -//! * `i_ideal` the ideal yearly interest rate: the ideal total yearly amount of tokens minted to -//! pay all validators and nominators for NPoS, divided by the total amount of tokens staked by -//! them. `i(x) = I(x)/x` and `i(x_ideal) = i_deal` -//! * `d` decay rate. -//! -//! We define I_NPoS as a linear function from 0 to `x_ideal` and an exponential decrease after -//! `x_ideal` to 1. We choose exponential decrease for `I_NPoS` because this implies an exponential -//! decrease for the yearly interest rate as well, and we want the interest rate to fall sharply -//! beyond `x_ideal` to avoid illiquidity. -//! -//! Function is defined as such: -//! ```nocompile -//! for 0 < x < x_ideal: I_NPoS(x) = I0 + x*(i_ideal - I0/x_ideal) -//! for x_ideal < x < 1: I_NPoS(x) = I0 + (i_ideal*x_ideal - I0)*2^((x_ideal-x)/d) -//! ``` -//! -//! Thus we have the following properties: -//! * `I_NPoS > I0` -//! * `I_NPoS(0) = I0` -//! * `I_NPoS(x_ideal) = max(I_NPoS) = x_ideal*i_ideal` -//! * `i(x)` is monotone decreasing -//! -//! More details can be found [here](http://research.web3.foundation/en/latest/polkadot/Token%20Eco -//! nomics/#inflation-model) - -use sr_primitives::{Perbill, traits::SimpleArithmetic}; - -/// Linear function truncated to positive part `y = max(0, b [+ or -] a*x)` for `P_NPoS` usage. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -struct Linear { - // Negate the `a*x` term. - negative_a: bool, - // Per-billion representation of `a`, the x coefficient. - a: u32, - // Per-billion representation of `b`, the intercept. - b: u32, -} - -impl Linear { - /// Compute `f(n/d)*d`. This is useful to avoid loss of precision. - fn calculate_for_fraction_times_denominator(&self, n: N, d: N) -> N - where - N: SimpleArithmetic + Clone - { - if self.negative_a { - (Perbill::from_parts(self.b) * d).saturating_sub(Perbill::from_parts(self.a) * n) - } else { - (Perbill::from_parts(self.b) * d).saturating_add(Perbill::from_parts(self.a) * n) - } - } -} - -/// Piecewise Linear function for `P_NPoS` usage -#[derive(Debug, PartialEq, Eq)] -struct PiecewiseLinear { - /// Array of tuples of an abscissa in a per-billion representation and a linear function. - /// - /// Abscissas in the array must be in order from the lowest to the highest. - /// - /// The array defines a piecewise linear function as such: - /// * the n-th segment starts at the abscissa of the n-th element until the abscissa of the - /// n-th + 1 element, and is defined by the linear function of the n-th element - /// * last segment doesn't end - pieces: [(u32, Linear); 20], -} - -impl PiecewiseLinear { - /// Compute `f(n/d)*d`. This is useful to avoid loss of precision. - fn calculate_for_fraction_times_denominator(&self, n: N, d: N) -> N - where - N: SimpleArithmetic + Clone - { - let part = self.pieces.iter() - .take_while(|(abscissa, _)| n > Perbill::from_parts(*abscissa) * d.clone()) - .last() - .unwrap_or(&self.pieces[0]); - - part.1.calculate_for_fraction_times_denominator(n, d) - } -} - -/// Piecewise linear approximation of `I_NPoS`. -/// -/// Using the constants: -/// * `I_0` = 0.025; -/// * `i_ideal` = 0.2; -/// * `x_ideal` = 0.5; -/// * `d` = 0.05; -/// -/// This approximation is tested to be close to real one by an error less than 1% see -/// `i_npos_precision` test. -const I_NPOS: PiecewiseLinear = PiecewiseLinear { - pieces: [ - (0, Linear { negative_a: false, a: 150000000, b: 25000000 }), - (500000000, Linear { negative_a: true, a: 986493987, b: 593246993 }), - (507648979, Linear { negative_a: true, a: 884661327, b: 541551747 }), - (515726279, Linear { negative_a: true, a: 788373842, b: 491893761 }), - (524282719, Linear { negative_a: true, a: 697631517, b: 444319128 }), - (533378749, Linear { negative_a: true, a: 612434341, b: 398876765 }), - (543087019, Linear { negative_a: true, a: 532782338, b: 355618796 }), - (553495919, Linear { negative_a: true, a: 458675508, b: 314600968 }), - (564714479, Linear { negative_a: true, a: 390113843, b: 275883203 }), - (576879339, Linear { negative_a: true, a: 327097341, b: 239530285 }), - (590164929, Linear { negative_a: true, a: 269626004, b: 205612717 }), - (604798839, Linear { negative_a: true, a: 217699848, b: 174207838 }), - (621085859, Linear { negative_a: true, a: 171318873, b: 145401271 }), - (639447429, Linear { negative_a: true, a: 130483080, b: 119288928 }), - (660489879, Linear { negative_a: true, a: 95192479, b: 95979842 }), - (685131379, Linear { negative_a: true, a: 65447076, b: 75600334 }), - (714860569, Linear { negative_a: true, a: 41246910, b: 58300589 }), - (752334749, Linear { negative_a: true, a: 22592084, b: 44265915 }), - (803047659, Linear { negative_a: true, a: 9482996, b: 33738693 }), - (881691659, Linear { negative_a: true, a: 2572702, b: 27645944 }) - ] -}; - -/// Second per year for the Julian year (365.25 days). -const SECOND_PER_YEAR: u32 = 3600*24*36525/100; +use sr_primitives::{Perbill, traits::SimpleArithmetic, curve::PiecewiseLinear}; /// The total payout to all validators (and their nominators) per era. /// -/// Named P_NPoS in the [paper](http://research.web3.foundation/en/latest/polkadot/Token%20Ec -/// onomics/#inflation-model). -/// -/// For x the staking rate in NPoS: `P_NPoS(x) = I_NPoS(x) * current_total_token / era_per_year` -/// i.e. `P_NPoS(x) = I_NPoS(x) * current_total_token * era_duration / year_duration` +/// Defined as such: +/// `payout = yearly_inflation(npos_token_staked / total_tokens) * total_tokans / era_per_year` /// -/// I_NPoS is the desired yearly inflation rate for nominated proof of stake. -pub fn compute_total_payout(npos_token_staked: N, total_tokens: N, era_duration: N) -> N -where - N: SimpleArithmetic + Clone +/// `era_duration` is expressed in millisecond. +pub fn compute_total_payout( + yearly_inflation: &PiecewiseLinear<'static>, + npos_token_staked: N, + total_tokens: N, + era_duration: u64 +) -> N where N: SimpleArithmetic + Clone { - let year_duration: N = SECOND_PER_YEAR.into(); - I_NPOS.calculate_for_fraction_times_denominator(npos_token_staked, total_tokens) - * era_duration / year_duration + // Milliseconds per year for the Julian year (365.25 days). + const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; + + Perbill::from_rational_approximation(era_duration as u64, MILLISECONDS_PER_YEAR) + * yearly_inflation.calculate_for_fraction_times_denominator(npos_token_staked, total_tokens) } -#[allow(non_upper_case_globals, non_snake_case)] // To stick with paper notations #[cfg(test)] -mod test_inflation { - use std::convert::TryInto; - - // Function `y = a*x + b` using float used for testing precision of Linear - #[derive(Debug)] - struct LinearFloat { - a: f64, - b: f64, - } - - impl LinearFloat { - fn new(x0: f64, y0: f64, x1: f64, y1: f64) -> Self { - LinearFloat { - a: (y1 - y0) / (x1 - x0), - b: (x0*y1 - x1*y0) / (x0 - x1), - } - } - - fn compute(&self, x: f64) -> f64 { - self.a*x + self.b - } - } - - #[test] - fn linear_float_works() { - assert_eq!(LinearFloat::new(1.0, 2.0, 4.0, 3.0).compute(7.0), 4.0); - } - - // Constants defined in paper - const I_0: f64 = 0.025; - const i_ideal: f64 = 0.2; - const x_ideal: f64 = 0.5; - const d: f64 = 0.05; - - // Left part from `x_ideal` - fn I_left(x: f64) -> f64 { - I_0 + x * (i_ideal - I_0/x_ideal) - } - - // Right part from `x_ideal` - fn I_right(x: f64) -> f64 { - I_0 + (i_ideal*x_ideal - I_0) * 2_f64.powf((x_ideal-x)/d) - } - - // Definition of I_NPoS in float - fn I_full(x: f64) -> f64 { - if x <= x_ideal { - I_left(x) - } else { - I_right(x) - } - } - - // Compute approximation of I_NPoS into piecewise linear function - fn I_NPoS_points() -> super::PiecewiseLinear { - let mut points = vec![]; - - // Points for left part - points.push((0.0, I_0)); - points.push((x_ideal, I_left(x_ideal))); - - // Approximation for right part. - // - // We start from x_ideal (x0) and we try to find the next point (x1) for which the linear - // approximation of (x0, x1) doesn't deviate from float definition by an error of - // GEN_ERROR. - - // When computing deviation between linear approximation and float definition we iterate - // over all points with this step precision. - const STEP_PRECISION: f64 = 0.000_000_1; - // Max error used for generating points. - const GEN_ERROR: f64 = 0.000_1; - - let mut x0: f64 = x_ideal; - let mut x1: f64 = x0; - - // This is just a step used to find next x1: - // if x1 + step result in a not enought precise approximation we reduce step and try again. - // we stop as soon as step is less than STEP_PRECISION. - let mut step: f64 = 0.1; - - loop { - let next_x1 = x1 + step; - - if next_x1 >= 1.0 { - points.push((1.0, I_right(1.0))); - break; - } - - let y0 = I_right(x0); - let next_y1 = I_right(next_x1); - - let mut error_overflowed = false; - - // Test error is not overflowed - - // Quick test on one point - if (I_right((x0 + next_x1)/2.0) - (y0 + next_y1)/2.0).abs() > GEN_ERROR { - error_overflowed = true; - } - - // Long test on all points - if !error_overflowed { - let linear = LinearFloat::new(x0, y0, next_x1, next_y1); - let mut cursor = x0; - while cursor < x1 { - if (I_right(cursor) - linear.compute(cursor)).abs() > GEN_ERROR { - error_overflowed = true; - } - cursor += STEP_PRECISION; - } - } - - if error_overflowed { - if step <= STEP_PRECISION { - points.push((x1, I_right(x1))); - x0 = x1; - step = 0.1; - } else { - step /= 10.0; - } - } else { - x1 = next_x1; - } - } - - // Convert points to piecewise linear definition - let pieces: Vec<(u32, super::Linear)> = (0..points.len()-1) - .map(|i| { - let p0 = points[i]; - let p1 = points[i+1]; - - let linear = LinearFloat::new(p0.0, p0.1, p1.0, p1.1); - - // Needed if we want to use a Perbill later - assert!(linear.a.abs() <= 1.0); - // Needed if we want to use a Perbill later - assert!(linear.b.abs() <= 1.0); - // Needed to stick with our restrictive definition of linear - assert!(linear.b.signum() == 1.0); - - ( - (p0.0 * 1_000_000_000.0) as u32, - super::Linear { - negative_a: linear.a.signum() < 0.0, - a: (linear.a.abs() * 1_000_000_000.0) as u32, - b: (linear.b.abs() * 1_000_000_000.0) as u32, - } - ) - }) - .collect(); - - println!("Generated pieces: {:?}", pieces); - assert_eq!(pieces.len(), 20); - - super::PiecewiseLinear { pieces: (&pieces[..]).try_into().unwrap() } - } - - /// This test is only useful to generate a new set of points for the definition of I_NPoS. - #[test] - fn generate_I_NPOS() { - assert_eq!(super::I_NPOS, I_NPoS_points()); +mod test { + use sr_primitives::curve::PiecewiseLinear; + + srml_staking_reward_curve::build! { + const I_NPOS: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); } - /// This test ensure that i_npos piecewise linear approximation is close to the actual function. - /// It does compare the result from a computation in integer of different capcity and in f64. #[test] - fn i_npos_precision() { - const STEP_PRECISION: f64 = 0.000_001; - const ERROR: f64 = 0.000_2; - - macro_rules! test_for_value { - ($($total_token:expr => $type:ty,)*) => { - let mut x = 0.1; - while x <= 1.0 { - let expected = I_full(x); - $({ - let result = super::I_NPOS.calculate_for_fraction_times_denominator( - (x * $total_token as f64) as $type, - $total_token, - ) as f64; - let expected = expected * $total_token as f64; - let error = (ERROR * $total_token as f64).max(2.0); - - let diff = (result - expected).abs(); - if diff >= error { - println!("total_token: {}", $total_token); - println!("x: {}", x); - println!("diff: {}", diff); - println!("error: {}", error); - panic!("error overflowed"); - } - })* - x += STEP_PRECISION - } - } - } - - test_for_value!( - 1_000u32 => u32, - 1_000_000u32 => u32, - 1_000_000_000u32 => u32, - 1_000_000_000_000u64 => u64, - 1_000_000_000_000_000u64 => u64, - 1_000_000_000_000_000_000u64 => u64, - 1_000_000_000_000_000_000_000u128 => u128, - 1_000_000_000_000_000_000_000_000u128 => u128, - 1_000_000_000_000_000_000_000_000_000u128 => u128, - 1_000_000_000_000_000_000_000_000_000_000u128 => u128, - 1_000_000_000_000_000_000_000_000_000_000_000_000u128 => u128, - u32::max_value() => u32, - u64::max_value() => u64, - u128::max_value() => u128, + fn npos_curve_is_sensible() { + const YEAR: u64 = 365 * 24 * 60 * 60 * 1000; + //super::I_NPOS.calculate_for_fraction_times_denominator(25, 100) + assert_eq!(super::compute_total_payout(&I_NPOS, 0, 100_000u64, YEAR), 2_498); + assert_eq!(super::compute_total_payout(&I_NPOS, 5_000, 100_000u64, YEAR), 3_248); + assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, YEAR), 6_246); + assert_eq!(super::compute_total_payout(&I_NPOS, 40_000, 100_000u64, YEAR), 8_494); + assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, YEAR), 9_993); + assert_eq!(super::compute_total_payout(&I_NPOS, 60_000, 100_000u64, YEAR), 4_379); + assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, YEAR), 2_733); + assert_eq!(super::compute_total_payout(&I_NPOS, 95_000, 100_000u64, YEAR), 2_513); + assert_eq!(super::compute_total_payout(&I_NPOS, 100_000, 100_000u64, YEAR), 2_505); + + const DAY: u64 = 24 * 60 * 60 * 1000; + assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, DAY), 17); + assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, DAY), 27); + assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, DAY), 7); + + const SIX_HOURS: u64 = 6 * 60 * 60 * 1000; + assert_eq!(super::compute_total_payout(&I_NPOS, 25_000, 100_000u64, SIX_HOURS), 4); + assert_eq!(super::compute_total_payout(&I_NPOS, 50_000, 100_000u64, SIX_HOURS), 7); + assert_eq!(super::compute_total_payout(&I_NPOS, 75_000, 100_000u64, SIX_HOURS), 2); + + const HOUR: u64 = 60 * 60 * 1000; + assert_eq!( + super::compute_total_payout( + &I_NPOS, + 2_500_000_000_000_000_000_000_000_000u128, + 5_000_000_000_000_000_000_000_000_000u128, + HOUR + ), + 57_038_500_000_000_000_000_000 ); } } diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 5a04ae5c5e36c02fb715d5c7b2aa482515ec94ef..1cbdfbc8c0438e55611279bd0e71a863fdc6e540 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -133,10 +133,10 @@ //! //! ## Usage //! -//! ### Example: Reporting Misbehavior +//! ### Example: Rewarding a validator by id. //! //! ``` -//! use srml_support::{decl_module, dispatch::Result}; +//! use support::{decl_module, dispatch::Result}; //! use system::ensure_signed; //! use srml_staking::{self as staking}; //! @@ -144,10 +144,10 @@ //! //! decl_module! { //! pub struct Module for enum Call where origin: T::Origin { -//! /// Report whoever calls this function as offline once. -//! pub fn report_sender(origin) -> Result { +//! /// Reward a validator. +//! pub fn reward_myself(origin) -> Result { //! let reported = ensure_signed(origin)?; -//! >::on_offline_validator(reported, 1); +//! >::reward_by_ids(vec![(reported, 10)]); //! Ok(()) //! } //! } @@ -203,28 +203,6 @@ //! - Stash account, not increasing the staked value. //! - Stash account, also increasing the staked value. //! -//! ### Slashing details -//! -//! A validator can be _reported_ to be offline at any point via the public function -//! [`on_offline_validator`](enum.Call.html#variant.on_offline_validator). Each validator declares -//! how many times it can be _reported_ before it actually gets slashed via its -//! [`ValidatorPrefs::unstake_threshold`](./struct.ValidatorPrefs.html#structfield.unstake_threshold). -//! -//! On top of this, the Staking module also introduces an -//! [`OfflineSlashGrace`](./struct.Module.html#method.offline_slash_grace), which applies -//! to all validators and prevents them from getting immediately slashed. -//! -//! Essentially, a validator gets slashed once they have been reported more than -//! [`OfflineSlashGrace`] + [`ValidatorPrefs::unstake_threshold`] times. Getting slashed due to -//! offline report always leads to being _unstaked_ (_i.e._ removed as a validator candidate) as -//! the consequence. -//! -//! The base slash value is computed _per slash-event_ by multiplying -//! [`OfflineSlash`](./struct.Module.html#method.offline_slash) and the `total` `Exposure`. This -//! value is then multiplied by `2.pow(unstake_threshold)` to obtain the final slash value. All -//! individual accounts' punishments are capped at their total stake (NOTE: This cap should never -//! come into force in a correctly implemented, non-corrupted, well-configured system). -//! //! ### Additional Fund Management Operations //! //! Any funds already placed into stash can be the target of the following operations: @@ -265,81 +243,79 @@ #![recursion_limit="128"] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(all(feature = "bench", test), feature(test))] - -#[cfg(all(feature = "bench", test))] -extern crate test; -#[cfg(any(feature = "bench", test))] +#[cfg(test)] mod mock; - #[cfg(test)] mod tests; -mod phragmen; -mod inflation; +pub mod inflation; -#[cfg(all(feature = "bench", test))] -mod benches; - -#[cfg(feature = "std")] -use runtime_io::with_storage; -use rstd::{prelude::*, result, collections::btree_map::BTreeMap}; +use rstd::{prelude::*, result}; use codec::{HasCompact, Encode, Decode}; -use srml_support::{ - StorageValue, StorageMap, EnumerableStorageMap, decl_module, decl_event, - decl_storage, ensure, traits::{ - Currency, OnFreeBalanceZero, OnDilution, LockIdentifier, LockableCurrency, - WithdrawReasons, WithdrawReason, OnUnbalanced, Imbalance, Get, Time +use support::{ + decl_module, decl_event, decl_storage, ensure, + traits::{ + Currency, OnFreeBalanceZero, LockIdentifier, LockableCurrency, + WithdrawReasons, OnUnbalanced, Imbalance, Get, Time + } +}; +use session::{historical::OnSessionEnding, SelectInitialValidators}; +use sr_primitives::{ + Perbill, + RuntimeDebug, + curve::PiecewiseLinear, + weights::SimpleDispatchInfo, + traits::{ + Convert, Zero, One, StaticLookup, CheckedSub, Saturating, Bounded, SaturatedConversion, } }; -use session::{historical::OnSessionEnding, SelectInitialValidators, SessionIndex}; -use sr_primitives::Perbill; -use sr_primitives::weights::SimpleDispatchInfo; -use sr_primitives::traits::{ - Convert, Zero, One, StaticLookup, CheckedSub, CheckedShl, Saturating, Bounded, - SaturatedConversion, SimpleArithmetic +use sr_staking_primitives::{ + SessionIndex, + offence::{OnOffenceHandler, OffenceDetails, Offence, ReportOffence}, }; #[cfg(feature = "std")] use sr_primitives::{Serialize, Deserialize}; use system::{ensure_signed, ensure_root}; -use phragmen::{elect, ACCURACY, ExtendedBalance, equalize}; +use phragmen::{elect, equalize, build_support_map, ExtendedBalance, PhragmenStakedAssignment}; -const RECENT_OFFLINE_COUNT: usize = 32; const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4; const MAX_NOMINATIONS: usize = 16; -const MAX_UNSTAKE_THRESHOLD: u32 = 10; const MAX_UNLOCKING_CHUNKS: usize = 32; const STAKING_ID: LockIdentifier = *b"staking "; /// Counter for the number of eras that have passed. pub type EraIndex = u32; +/// Counter for the number of "reward" points earned by a given validator. +pub type Points = u32; + /// Reward points of an era. Used to split era total payout between validators. #[derive(Encode, Decode, Default)] -pub struct EraRewards { +pub struct EraPoints { /// Total number of points. Equals the sum of reward points for each validator. - total: u32, - /// Reward at one index correspond to reward for validator in current_elected of this index. - /// Thus this reward vec is only valid for one elected set. - rewards: Vec, + total: Points, + /// The reward points earned by a given validator. The index of this vec corresponds to the + /// index into the current validator set. + individual: Vec, } -impl EraRewards { +impl EraPoints { /// Add the reward to the validator at the given index. Index must be valid /// (i.e. `index < current_elected.len()`). fn add_points_to_index(&mut self, index: u32, points: u32) { if let Some(new_total) = self.total.checked_add(points) { self.total = new_total; - self.rewards.resize((index as usize + 1).max(self.rewards.len()), 0); - self.rewards[index as usize] += points; // Addition is less than total + self.individual.resize((index as usize + 1).max(self.individual.len()), 0); + self.individual[index as usize] += points; // Addition is less than total } } } /// Indicates the initial status of the staker. -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum StakerStatus { /// Chilling. Idle, @@ -350,8 +326,7 @@ pub enum StakerStatus { } /// A destination account for payment. -#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, RuntimeDebug)] pub enum RewardDestination { /// Pay into the stash account, increasing the amount at stake accordingly. Staked, @@ -368,12 +343,8 @@ impl Default for RewardDestination { } /// Preference of what happens on a slash event. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] pub struct ValidatorPrefs { - /// Validator should ensure this many more slashes than is necessary before being unstaked. - #[codec(compact)] - pub unstake_threshold: u32, /// Reward that validator takes up-front; only the rest is split between themselves and /// nominators. #[codec(compact)] @@ -383,15 +354,13 @@ pub struct ValidatorPrefs { impl Default for ValidatorPrefs { fn default() -> Self { ValidatorPrefs { - unstake_threshold: 3, validator_payment: Default::default(), } } } /// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] pub struct UnlockChunk { /// Amount of funds to be unlocked. #[codec(compact)] @@ -402,8 +371,7 @@ pub struct UnlockChunk { } /// The ledger of a (bonded) stash. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] pub struct StakingLedger { /// The stash account whose balance is actually locked and at stake. pub stash: AccountId, @@ -441,8 +409,7 @@ impl< } /// The amount of exposure (to slashing) than an individual nominator has. -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, RuntimeDebug)] pub struct IndividualExposure { /// The stash account of the nominator in question. who: AccountId, @@ -452,8 +419,7 @@ pub struct IndividualExposure { } /// A snapshot of the stake backing a single validator in the system. -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default, RuntimeDebug)] pub struct Exposure { /// The total balance backing this validator. #[codec(compact)] @@ -465,6 +431,14 @@ pub struct Exposure { pub others: Vec>, } +/// A slashing event occurred, slashing a validator for a given amount of balance. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default, RuntimeDebug)] +pub struct SlashJournalEntry { + who: AccountId, + amount: Balance, + own_slash: Balance, // the amount of `who`'s own exposure that was slashed +} + pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type PositiveImbalanceOf = @@ -473,26 +447,20 @@ type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; type MomentOf= <::Time as Time>::Moment; -type RawAssignment = (::AccountId, ExtendedBalance); -type Assignment = (::AccountId, ExtendedBalance, BalanceOf); -type ExpoMap = BTreeMap< - ::AccountId, - Exposure<::AccountId, BalanceOf> ->; - -pub const DEFAULT_SESSIONS_PER_ERA: u32 = 3; -pub const DEFAULT_BONDING_DURATION: u32 = 1; - /// Means for interacting with a specialized version of the `session` trait. /// /// This is needed because `Staking` sets the `ValidatorIdOf` of the `session::Trait` pub trait SessionInterface: system::Trait { /// Disable a given validator by stash ID. - fn disable_validator(validator: &AccountId) -> Result<(), ()>; + /// + /// Returns `true` if new era should be forced at the end of this session. + /// This allows preventing a situation where there is too many validators + /// disabled and block production stalls. + fn disable_validator(validator: &AccountId) -> Result; /// Get the validators from session. fn validators() -> Vec; /// Prune historical session tries up to but not including the given index. - fn prune_historical_up_to(up_to: session::SessionIndex); + fn prune_historical_up_to(up_to: SessionIndex); } impl SessionInterface<::AccountId> for T where @@ -506,7 +474,7 @@ impl SessionInterface<::AccountId> for T where T::SelectInitialValidators: session::SelectInitialValidators<::AccountId>, T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> { - fn disable_validator(validator: &::AccountId) -> Result<(), ()> { + fn disable_validator(validator: &::AccountId) -> Result { >::disable(validator) } @@ -514,7 +482,7 @@ impl SessionInterface<::AccountId> for T where >::validators() } - fn prune_historical_up_to(up_to: session::SessionIndex) { + fn prune_historical_up_to(up_to: SessionIndex) { >::prune_up_to(up_to); } } @@ -530,11 +498,11 @@ pub trait Trait: system::Trait { /// This must fit into a `u64` but is allowed to be sensibly lossy. /// TODO: #1377 /// The backward convert should be removed as the new Phragmen API returns ratio. - /// The post-processing needs it but will be moved to off-chain. + /// The post-processing needs it but will be moved to off-chain. TODO: #2908 type CurrencyToVote: Convert, u64> + Convert>; - /// Some tokens minted. - type OnRewardMinted: OnDilution>; + /// Tokens have been minted and are unused for validator-reward. + type RewardRemainder: OnUnbalanced>; /// The overarching event type. type Event: From> + Into<::Event>; @@ -553,11 +521,18 @@ pub trait Trait: system::Trait { /// Interface for interacting with a session module. type SessionInterface: self::SessionInterface; + + /// The NPoS reward curve to use. + type RewardCurve: Get<&'static PiecewiseLinear<'static>>; + + /// The maximum possible reward (in proportion of total issued tokens) that can be paid in one + /// reward cycle. + type MaxPossibleReward: Get; } /// Mode of era-forcing. -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Forcing { /// Not forcing anything - just let whatever happen. NotForcing, @@ -565,6 +540,8 @@ pub enum Forcing { ForceNew, /// Avoid a new era indefinitely. ForceNone, + /// Force a new era at the end of all sessions indefinitely. + ForceAlways, } impl Default for Forcing { @@ -575,124 +552,118 @@ decl_storage! { trait Store for Module as Staking { /// The ideal number of staking participants. - pub ValidatorCount get(validator_count) config(): u32; + pub ValidatorCount get(fn validator_count) config(): u32; /// Minimum number of staking participants before emergency conditions are imposed. - pub MinimumValidatorCount get(minimum_validator_count) config(): + pub MinimumValidatorCount get(fn minimum_validator_count) config(): u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT; - /// Slash, per validator that is taken for the first time they are found to be offline. - pub OfflineSlash get(offline_slash) config(): Perbill = Perbill::from_millionths(1000); - /// Number of instances of offline reports before slashing begins for validators. - pub OfflineSlashGrace get(offline_slash_grace) config(): u32; /// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're /// easy to initialize and the performance hit is minimal (we expect no more than four /// invulnerables) and restricted to testnets. - pub Invulnerables get(invulnerables) config(): Vec; + pub Invulnerables get(fn invulnerables) config(): Vec; /// Map from all locked "stash" accounts to the controller account. - pub Bonded get(bonded): map T::AccountId => Option; + pub Bonded get(fn bonded): map T::AccountId => Option; /// Map from all (unlocked) "controller" accounts to the info regarding the staking. - pub Ledger get(ledger): + pub Ledger get(fn ledger): map T::AccountId => Option>>; /// Where the reward payment should be made. Keyed by stash. - pub Payee get(payee): map T::AccountId => RewardDestination; + pub Payee get(fn payee): map T::AccountId => RewardDestination; /// The map from (wannabe) validator stash key to the preferences of that validator. - pub Validators get(validators): linked_map T::AccountId => ValidatorPrefs>; + pub Validators get(fn validators): linked_map T::AccountId => ValidatorPrefs>; /// The map from nominator stash key to the set of stash keys of all validators to nominate. - pub Nominators get(nominators): linked_map T::AccountId => Vec; + pub Nominators get(fn nominators): linked_map T::AccountId => Vec; /// Nominators for a particular account that is in action right now. You can't iterate /// through validators here, but you can find them in the Session module. /// /// This is keyed by the stash account. - pub Stakers get(stakers): map T::AccountId => Exposure>; + pub Stakers get(fn stakers): map T::AccountId => Exposure>; /// The currently elected validator set keyed by stash account ID. - pub CurrentElected get(current_elected): Vec; + pub CurrentElected get(fn current_elected): Vec; /// The current era index. - pub CurrentEra get(current_era) config(): EraIndex; + pub CurrentEra get(fn current_era) config(): EraIndex; /// The start of the current era. - pub CurrentEraStart get(current_era_start): MomentOf; + pub CurrentEraStart get(fn current_era_start): MomentOf; /// The session index at which the current era started. - pub CurrentEraStartSessionIndex get(current_era_start_session_index): SessionIndex; + pub CurrentEraStartSessionIndex get(fn current_era_start_session_index): SessionIndex; /// Rewards for the current era. Using indices of current elected set. - CurrentEraRewards get(current_era_reward): EraRewards; + CurrentEraPointsEarned get(fn current_era_reward): EraPoints; /// The amount of balance actively at stake for each validator slot, currently. /// /// This is used to derive rewards and punishments. - pub SlotStake get(slot_stake) build(|config: &GenesisConfig| { + pub SlotStake get(fn slot_stake) build(|config: &GenesisConfig| { config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() }): BalanceOf; - /// The number of times a given validator has been reported offline. This gets decremented - /// by one each era that passes. - pub SlashCount get(slash_count): map T::AccountId => u32; - - /// Most recent `RECENT_OFFLINE_COUNT` instances. (Who it was, when it was reported, how - /// many instances they were offline for). - pub RecentlyOffline get(recently_offline): Vec<(T::AccountId, T::BlockNumber, u32)>; - /// True if the next session change will be a new era regardless of index. - pub ForceEra get(force_era) config(): Forcing; + pub ForceEra get(fn force_era) config(): Forcing; + + /// The percentage of the slash that is distributed to reporters. + /// + /// The rest of the slashed value is handled by the `Slash`. + pub SlashRewardFraction get(fn slash_reward_fraction) config(): Perbill; /// A mapping from still-bonded eras to the first session index of that era. BondedEras: Vec<(EraIndex, SessionIndex)>; + + /// All slashes that have occurred in a given era. + EraSlashJournal get(fn era_slash_journal): + map EraIndex => Vec>>; } add_extra_genesis { config(stakers): Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; - build(| - storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), - config: &GenesisConfig - | { - with_storage(storage, || { - for &(ref stash, ref controller, balance, ref status) in &config.stakers { - assert!( - T::Currency::free_balance(&stash) >= balance, - "Stash does not have enough balance to bond." - ); - let _ = >::bond( - T::Origin::from(Some(stash.clone()).into()), - T::Lookup::unlookup(controller.clone()), - balance, - RewardDestination::Staked - ); - let _ = match status { - StakerStatus::Validator => { - >::validate( - T::Origin::from(Some(controller.clone()).into()), - Default::default() - ) - }, StakerStatus::Nominator(votes) => { - >::nominate( - T::Origin::from(Some(controller.clone()).into()), - votes.iter().map(|l| {T::Lookup::unlookup(l.clone())}).collect() - ) - }, _ => Ok(()) - }; - } - }); + build(|config: &GenesisConfig| { + for &(ref stash, ref controller, balance, ref status) in &config.stakers { + assert!( + T::Currency::free_balance(&stash) >= balance, + "Stash does not have enough balance to bond." + ); + let _ = >::bond( + T::Origin::from(Some(stash.clone()).into()), + T::Lookup::unlookup(controller.clone()), + balance, + RewardDestination::Staked, + ); + let _ = match status { + StakerStatus::Validator => { + >::validate( + T::Origin::from(Some(controller.clone()).into()), + Default::default(), + ) + }, + StakerStatus::Nominator(votes) => { + >::nominate( + T::Origin::from(Some(controller.clone()).into()), + votes.iter().map(|l| T::Lookup::unlookup(l.clone())).collect(), + ) + }, _ => Ok(()) + }; + } }); } } decl_event!( pub enum Event where Balance = BalanceOf, ::AccountId { - /// All validators have been rewarded by the given balance. - Reward(Balance), - /// One validator (and its nominators) has been given an offline-warning (it is still - /// within its grace). The accrued number of slashes is recorded, too. - OfflineWarning(AccountId, u32), + /// All validators have been rewarded by the first balance; the second is the remainder + /// from the maximum amount of reward. + Reward(Balance, Balance), /// One validator (and its nominators) has been slashed by the given amount. - OfflineSlash(AccountId, Balance), + Slash(AccountId, Balance), + /// An old slashing report from a prior era was discarded because it could + /// not be processed. + OldSlashingReportDiscarded(SessionIndex), } ); @@ -704,7 +675,7 @@ decl_module! { /// Number of eras that staked funds must remain bonded for. const BondingDuration: EraIndex = T::BondingDuration::get(); - fn deposit_event() = default; + fn deposit_event() = default; fn on_finalize() { // Set the start of the first era. @@ -716,7 +687,7 @@ decl_module! { /// Take the origin account as a stash and lock up `value` of its balance. `controller` will /// be the account that controls it. /// - /// `value` must be more than the `existential_deposit` defined in the Balances module. + /// `value` must be more than the `minimum_balance` specified by `T::Currency`. /// /// The dispatch origin for this call must be _Signed_ by the stash account. /// @@ -753,7 +724,7 @@ decl_module! { // You're auto-bonded forever, here. We might improve this by only bonding when // you actually validate/nominate and remove once you unbond __everything__. - >::insert(&stash, controller.clone()); + >::insert(&stash, &controller); >::insert(&stash, payee); let stash_balance = T::Currency::free_balance(&stash); @@ -795,7 +766,7 @@ decl_module! { /// Schedule a portion of the stash to be unlocked ready for transfer out after the bond /// period ends. If this leaves an amount actively bonded less than - /// T::Currency::existential_deposit(), then it is increased to the full amount. + /// T::Currency::minimum_balance(), then it is increased to the full amount. /// /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move /// the funds out of management ready for transfer. @@ -895,10 +866,6 @@ decl_module! { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or("not a controller")?; let stash = &ledger.stash; - ensure!( - prefs.unstake_threshold <= MAX_UNSTAKE_THRESHOLD, - "unstake threshold too large" - ); >::remove(stash); >::insert(stash, prefs); } @@ -922,8 +889,8 @@ decl_module! { ensure!(!targets.is_empty(), "targets cannot be empty"); let targets = targets.into_iter() .take(MAX_NOMINATIONS) - .map(T::Lookup::lookup) - .collect::, &'static str>>()?; + .map(|t| T::Lookup::lookup(t)) + .collect::, _>>()?; >::remove(stash); >::insert(stash, targets); @@ -996,7 +963,7 @@ decl_module! { } /// The ideal number of validators. - #[weight = SimpleDispatchInfo::FixedOperational(150_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn set_validator_count(origin, #[compact] new: u32) { ensure_root(origin)?; ValidatorCount::put(new); @@ -1009,7 +976,7 @@ decl_module! { /// # /// - No arguments. /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn force_no_eras(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNone); @@ -1021,25 +988,40 @@ decl_module! { /// # /// - No arguments. /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn force_new_era(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNew); } - /// Set the offline slash grace period. - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] - fn set_offline_slash_grace(origin, #[compact] new: u32) { - ensure_root(origin)?; - OfflineSlashGrace::put(new); - } - /// Set the validators who cannot be slashed (if any). - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn set_invulnerables(origin, validators: Vec) { ensure_root(origin)?; >::put(validators); } + + /// Force a current staker to become completely unstaked, immediately. + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_unstake(origin, stash: T::AccountId) { + ensure_root(origin)?; + + // remove the lock. + T::Currency::remove_lock(STAKING_ID, &stash); + // remove all staking-related information. + Self::kill_stash(&stash); + } + + /// Force there to be a new era at the end of sessions indefinitely. + /// + /// # + /// - One storage write + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_new_era_always(origin) { + ensure_root(origin)?; + ForceEra::put(Forcing::ForceAlways); + } } } @@ -1048,8 +1030,8 @@ impl Module { /// The total balance that can be slashed from a validator controller account as of /// right now. - pub fn slashable_balance(who: &T::AccountId) -> BalanceOf { - Self::stakers(who).total + pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { + Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() } // MUTABLES (DANGEROUS) @@ -1065,25 +1047,47 @@ impl Module { &ledger.stash, ledger.total, T::BlockNumber::max_value(), - WithdrawReasons::except(WithdrawReason::TransactionPayment), + WithdrawReasons::all(), ); >::insert(controller, ledger); } - /// Slash a given validator by a specific amount. Removes the slash from the validator's - /// balance by preference, and reduces the nominators' balance if needed. - fn slash_validator(stash: &T::AccountId, slash: BalanceOf) { - // The exposure (backing stake) information of the validator to be slashed. - let exposure = Self::stakers(stash); + /// Slash a given validator by a specific amount with given (historical) exposure. + /// + /// Removes the slash from the validator's balance by preference, + /// and reduces the nominators' balance if needed. + /// + /// Returns the resulting `NegativeImbalance` to allow distributing the slashed amount and + /// pushes an entry onto the slash journal. + fn slash_validator( + stash: &T::AccountId, + slash: BalanceOf, + exposure: &Exposure>, + journal: &mut Vec>>, + ) -> NegativeImbalanceOf { // The amount we are actually going to slash (can't be bigger than the validator's total // exposure) let slash = slash.min(exposure.total); + + // limit what we'll slash of the stash's own to only what's in + // the exposure. + // + // note: this is fine only because we limit reports of the current era. + // otherwise, these funds may have already been slashed due to something + // reported from a prior era. + let already_slashed_own = journal.iter() + .filter(|entry| &entry.who == stash) + .map(|entry| entry.own_slash) + .fold(>::zero(), |a, c| a.saturating_add(c)); + + let own_remaining = exposure.own.saturating_sub(already_slashed_own); + // The amount we'll slash from the validator's stash directly. - let own_slash = exposure.own.min(slash); + let own_slash = own_remaining.min(slash); let (mut imbalance, missing) = T::Currency::slash(stash, own_slash); let own_slash = own_slash - missing; - // The amount remaining that we can't slash from the validator, that must be taken from the - // nominators. + // The amount remaining that we can't slash from the validator, + // that must be taken from the nominators. let rest_slash = slash - own_slash; if !rest_slash.is_zero() { // The total to be slashed from the nominators. @@ -1096,7 +1100,19 @@ impl Module { } } } - T::Slash::on_unbalanced(imbalance); + + journal.push(SlashJournalEntry { + who: stash.clone(), + own_slash: own_slash.clone(), + amount: slash, + }); + + // trigger the event + Self::deposit_event( + RawEvent::Slash(stash.clone(), slash) + ); + + imbalance } /// Actually make a payment to a staker. This uses the currency's reward function @@ -1154,9 +1170,11 @@ impl Module { fn new_session(session_index: SessionIndex) -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> { + let era_length = session_index.checked_sub(Self::current_era_start_session_index()).unwrap_or(0); match ForceEra::get() { Forcing::ForceNew => ForceEra::kill(), - Forcing::NotForcing if session_index % T::SessionsPerEra::get() == 0 => (), + Forcing::ForceAlways => (), + Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), _ => return None, } let validators = T::SessionInterface::validators(); @@ -1173,10 +1191,10 @@ impl Module { /// get a chance to set their session keys. fn new_era(start_session_index: SessionIndex) -> Option> { // Payout - let rewards = CurrentEraRewards::take(); + let points = CurrentEraPointsEarned::take(); let now = T::Time::now(); let previous_era_start = >::mutate(|v| { - rstd::mem::replace(v, now.clone()) + rstd::mem::replace(v, now) }); let era_duration = now - previous_era_start; if !era_duration.is_zero() { @@ -1186,30 +1204,40 @@ impl Module { let total_rewarded_stake = Self::slot_stake() * validator_len; let total_payout = inflation::compute_total_payout( + &T::RewardCurve::get(), total_rewarded_stake.clone(), T::Currency::total_issuance(), - // Era of duration more than u32::MAX is rewarded as u32::MAX. - >::from(era_duration.saturated_into::()), + // Duration of era; more than u64::MAX is rewarded as u64::MAX. + era_duration.saturated_into::(), ); let mut total_imbalance = >::zero(); - let total_points = rewards.total; - for (v, points) in validators.iter().zip(rewards.rewards.into_iter()) { - if points != 0 { - let reward = multiply_by_rational(total_payout, points, total_points); + for (v, p) in validators.iter().zip(points.individual.into_iter()) { + if p != 0 { + let reward = Perbill::from_rational_approximation(p, points.total) * total_payout; total_imbalance.subsume(Self::reward_validator(v, reward)); } } let total_reward = total_imbalance.peek(); - Self::deposit_event(RawEvent::Reward(total_reward)); + // assert!(total_reward <= total_payout) + + let max_reward = T::MaxPossibleReward::get() * T::Currency::total_issuance(); + let rest_reward = max_reward.saturating_sub(total_reward); + + Self::deposit_event(RawEvent::Reward(total_reward, rest_reward)); + T::Reward::on_unbalanced(total_imbalance); - T::OnRewardMinted::on_dilution(total_reward, total_rewarded_stake); + T::RewardRemainder::on_unbalanced(T::Currency::issue(rest_reward)); } // Increment current era. let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); + + // prune journal for last era. + >::remove(current_era - 1); + CurrentEraStartSessionIndex::mutate(|v| { *v = start_session_index; }); @@ -1239,108 +1267,89 @@ impl Module { maybe_new_validators } - fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { - Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() - } - /// Select a new validator set from the assembled stakers and their role preferences. /// /// Returns the new `SlotStake` value and a set of newly selected _stash_ IDs. fn select_validators() -> (BalanceOf, Option>) { - let maybe_elected_set = elect::( + let maybe_phragmen_result = elect::<_, _, _, T::CurrencyToVote>( Self::validator_count() as usize, Self::minimum_validator_count().max(1) as usize, - >::enumerate(), - >::enumerate(), + >::enumerate().map(|(who, _)| who).collect::>(), + >::enumerate().collect(), Self::slashable_balance_of, + true, ); - if let Some(elected_set) = maybe_elected_set { - let elected_stashes = elected_set.0; - let assignments = elected_set.1; + if let Some(phragmen_result) = maybe_phragmen_result { + let elected_stashes = phragmen_result.winners.iter() + .map(|(s, _)| s.clone()) + .collect::>(); + let assignments = phragmen_result.assignments; - // helper closure. - let to_balance = |b: ExtendedBalance| - >>::convert(b); let to_votes = |b: BalanceOf| , u64>>::convert(b) as ExtendedBalance; + let to_balance = |e: ExtendedBalance| + >>::convert(e); + + let mut supports = build_support_map::<_, _, _, T::CurrencyToVote>( + &elected_stashes, + &assignments, + Self::slashable_balance_of, + true, + ); - // The return value of this is safe to be converted to u64. - // The original balance, `b` is within the scope of u64. It is just extended to u128 - // to be properly multiplied by a ratio, which will lead to another value - // less than u64 for sure. The result can then be safely passed to `to_balance`. - // For now the backward convert is used. A simple `TryFrom` is also safe. - let ratio_of = |b, p| (p as ExtendedBalance).saturating_mul(to_votes(b)) / ACCURACY; - - // Compute the actual stake from nominator's ratio. - let assignments_with_stakes = assignments.iter().map(|(n, a)|( - n.clone(), - Self::slashable_balance_of(n), - a.iter().map(|(acc, r)| ( - acc.clone(), - *r, - to_balance(ratio_of(Self::slashable_balance_of(n), *r)), - )) - .collect::>>() - )).collect::, Vec>)>>(); - - // update elected candidate exposures. - let mut exposures = >::new(); - elected_stashes - .iter() - .map(|e| (e, Self::slashable_balance_of(e))) - .for_each(|(e, s)| { - let item = Exposure { own: s, total: s, ..Default::default() }; - exposures.insert(e.clone(), item); - }); - - for (n, _, assignment) in &assignments_with_stakes { - for (c, _, s) in assignment { - if let Some(expo) = exposures.get_mut(c) { - // NOTE: simple example where this saturates: - // candidate with max_value stake. 1 nominator with max_value stake. - // Nuked. Sadly there is not much that we can do about this. - // See this test: phragmen_should_not_overflow_xxx() - expo.total = expo.total.saturating_add(*s); - expo.others.push( IndividualExposure { who: n.clone(), value: *s } ); + if cfg!(feature = "equalize") { + let mut staked_assignments + : Vec<(T::AccountId, Vec>)> + = Vec::with_capacity(assignments.len()); + for (n, assignment) in assignments.iter() { + let mut staked_assignment + : Vec> + = Vec::with_capacity(assignment.len()); + for (c, per_thing) in assignment.iter() { + let nominator_stake = to_votes(Self::slashable_balance_of(n)); + let other_stake = *per_thing * nominator_stake; + staked_assignment.push((c.clone(), other_stake)); } + staked_assignments.push((n.clone(), staked_assignment)); } - } - if cfg!(feature = "equalize") { let tolerance = 0_u128; let iterations = 2_usize; - let mut assignments_with_votes = assignments_with_stakes.iter() - .map(|a| ( - a.0.clone(), a.1, - a.2.iter() - .map(|e| (e.0.clone(), e.1, to_votes(e.2))) - .collect::>() - )) - .collect::, - Vec<(T::AccountId, ExtendedBalance, ExtendedBalance)> - )>>(); - equalize::(&mut assignments_with_votes, &mut exposures, tolerance, iterations); + equalize::<_, _, T::CurrencyToVote, _>( + staked_assignments, + &mut supports, + tolerance, + iterations, + Self::slashable_balance_of, + ); } - // Clear Stakers and reduce their slash_count. + // Clear Stakers. for v in Self::current_elected().iter() { >::remove(v); - let slash_count = >::take(v); - if slash_count > 1 { - >::insert(v, slash_count - 1); - } } // Populate Stakers and figure out the minimum stake behind a slot. let mut slot_stake = BalanceOf::::max_value(); - for (c, e) in exposures.iter() { - if e.total < slot_stake { - slot_stake = e.total; + for (c, s) in supports.into_iter() { + // build `struct exposure` from `support` + let exposure = Exposure { + own: to_balance(s.own), + // This might reasonably saturate and we cannot do much about it. The sum of + // someone's stake might exceed the balance type if they have the maximum amount + // of balance and receive some support. This is super unlikely to happen, yet + // we simulate it in some tests. + total: to_balance(s.total), + others: s.others + .into_iter() + .map(|(who, value)| IndividualExposure { who, value: to_balance(value) }) + .collect::>>(), + }; + if exposure.total < slot_stake { + slot_stake = exposure.total; } - >::insert(c.clone(), e.clone()); + >::insert(&c, exposure.clone()); } // Update slot stake. @@ -1349,6 +1358,10 @@ impl Module { // Set the new validator set in sessions. >::put(&elected_stashes); + // In order to keep the property required by `n_session_ending` + // that we must return the new validator set even if it's the same as the old, + // as long as any underlying economic conditions have changed, we don't attempt + // to do any optimization where we compare against the prior set. (slot_stake, Some(elected_stashes)) } else { // There were not enough candidates for even our minimal level of functionality. @@ -1371,68 +1384,10 @@ impl Module { >::remove(&controller); } >::remove(stash); - >::remove(stash); >::remove(stash); >::remove(stash); } - /// Call when a validator is determined to be offline. `count` is the - /// number of offenses the validator has committed. - /// - /// NOTE: This is called with the controller (not the stash) account id. - pub fn on_offline_validator(controller: T::AccountId, count: usize) { - if let Some(l) = Self::ledger(&controller) { - let stash = l.stash; - - // Early exit if validator is invulnerable. - if Self::invulnerables().contains(&stash) { - return - } - - let slash_count = Self::slash_count(&stash); - let new_slash_count = slash_count + count as u32; - >::insert(&stash, new_slash_count); - let grace = Self::offline_slash_grace(); - - if RECENT_OFFLINE_COUNT > 0 { - let item = (stash.clone(), >::block_number(), count as u32); - >::mutate(|v| if v.len() >= RECENT_OFFLINE_COUNT { - let index = v.iter() - .enumerate() - .min_by_key(|(_, (_, block, _))| block) - .expect("v is non-empty; qed") - .0; - v[index] = item; - } else { - v.push(item); - }); - } - - let prefs = Self::validators(&stash); - let unstake_threshold = prefs.unstake_threshold.min(MAX_UNSTAKE_THRESHOLD); - let max_slashes = grace + unstake_threshold; - - let event = if new_slash_count > max_slashes { - let slash_exposure = Self::stakers(&stash).total; - let offline_slash_base = Self::offline_slash() * slash_exposure; - // They're bailing. - let slash = offline_slash_base - // Multiply slash_mantissa by 2^(unstake_threshold with upper bound) - .checked_shl(unstake_threshold) - .map(|x| x.min(slash_exposure)) - .unwrap_or(slash_exposure); - let _ = Self::slash_validator(&stash, slash); - let _ = T::SessionInterface::disable_validator(&stash); - - RawEvent::OfflineSlash(stash.clone(), slash) - } else { - RawEvent::OfflineWarning(stash.clone(), slash_count) - }; - - Self::deposit_event(event); - } - } - /// Add reward points to validators using their stash account ID. /// /// Validators are keyed by stash account ID and must be in the current elected set. @@ -1446,7 +1401,7 @@ impl Module { /// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`. /// If you need to reward lots of validator consider using `reward_by_indices`. pub fn reward_by_ids(validators_points: impl IntoIterator) { - CurrentEraRewards::mutate(|rewards| { + CurrentEraPointsEarned::mutate(|rewards| { let current_elected = >::current_elected(); for (validator, points) in validators_points.into_iter() { if let Some(index) = current_elected.iter() @@ -1466,7 +1421,7 @@ impl Module { // TODO: This can be optimised once #3302 is implemented. let current_elected_len = >::current_elected().len() as u32; - CurrentEraRewards::mutate(|rewards| { + CurrentEraPointsEarned::mutate(|rewards| { for (validator_index, points) in validators_points.into_iter() { if validator_index < current_elected_len { rewards.add_points_to_index(validator_index, points); @@ -1474,6 +1429,14 @@ impl Module { } }); } + + /// Ensures that at the end of the current session there will be a new era. + fn ensure_new_era() { + match ForceEra::get() { + Forcing::ForceAlways | Forcing::ForceNew => (), + _ => ForceEra::put(Forcing::ForceNew), + } + } } impl session::OnSessionEnding for Module { @@ -1512,31 +1475,6 @@ impl authorship::EventHandler(value: N, num: u32, den: u32) -> N - where N: SimpleArithmetic + Clone -{ - let num = num.min(den); - - let result_divisor_part = value.clone() / den.into() * num.into(); - - let result_remainder_part = { - let rem = value % den.into(); - - // Fits into u32 because den is u32 and remainder < den - let rem_u32 = rem.saturated_into::(); - - // Multiplication fits into u64 as both term are u32 - let rem_part = rem_u32 as u64 * num as u64 / den as u64; - - // Result fits into u32 as num < total_points - (rem_part as u32).into() - }; - - result_divisor_part + result_remainder_part -} - /// A `Convert` implementation that finds the stash of the given controller account, /// if any. pub struct StashOf(rstd::marker::PhantomData); @@ -1564,3 +1502,107 @@ impl SelectInitialValidators for Module { >::select_validators().1 } } + +/// This is intended to be used with `FilterHistoricalOffences`. +impl OnOffenceHandler> for Module where + T: session::Trait::AccountId>, + T: session::historical::Trait< + FullIdentification = Exposure<::AccountId, BalanceOf>, + FullIdentificationOf = ExposureOf, + >, + T::SessionHandler: session::SessionHandler<::AccountId>, + T::OnSessionEnding: session::OnSessionEnding<::AccountId>, + T::SelectInitialValidators: session::SelectInitialValidators<::AccountId>, + T::ValidatorIdOf: Convert<::AccountId, Option<::AccountId>> +{ + fn on_offence( + offenders: &[OffenceDetails>], + slash_fraction: &[Perbill], + ) { + let mut remaining_imbalance = >::zero(); + let slash_reward_fraction = SlashRewardFraction::get(); + + let era_now = Self::current_era(); + let mut journal = Self::era_slash_journal(era_now); + for (details, slash_fraction) in offenders.iter().zip(slash_fraction) { + let stash = &details.offender.0; + let exposure = &details.offender.1; + + // Skip if the validator is invulnerable. + if Self::invulnerables().contains(stash) { + continue + } + + // Auto deselect validator on any offence and force a new era if they haven't previously + // been deselected. + if >::exists(stash) { + >::remove(stash); + Self::ensure_new_era(); + } + + // calculate the amount to slash + let slash_exposure = exposure.total; + let amount = *slash_fraction * slash_exposure; + // in some cases `slash_fraction` can be just `0`, + // which means we are not slashing this time. + if amount.is_zero() { + continue; + } + + // make sure to disable validator till the end of this session + if T::SessionInterface::disable_validator(stash).unwrap_or(false) { + // force a new era, to select a new validator set + Self::ensure_new_era(); + } + // actually slash the validator + let slashed_amount = Self::slash_validator(stash, amount, exposure, &mut journal); + + // distribute the rewards according to the slash + let slash_reward = slash_reward_fraction * slashed_amount.peek(); + if !slash_reward.is_zero() && !details.reporters.is_empty() { + let (mut reward, rest) = slashed_amount.split(slash_reward); + // split the reward between reporters equally. Division cannot fail because + // we guarded against it in the enclosing if. + let per_reporter = reward.peek() / (details.reporters.len() as u32).into(); + for reporter in &details.reporters { + let (reporter_reward, rest) = reward.split(per_reporter); + reward = rest; + T::Currency::resolve_creating(reporter, reporter_reward); + } + // The rest goes to the treasury. + remaining_imbalance.subsume(reward); + remaining_imbalance.subsume(rest); + } else { + remaining_imbalance.subsume(slashed_amount); + } + } + >::insert(era_now, journal); + + // Handle the rest of imbalances + T::Slash::on_unbalanced(remaining_imbalance); + } +} + +/// Filter historical offences out and only allow those from the current era. +pub struct FilterHistoricalOffences { + _inner: rstd::marker::PhantomData<(T, R)>, +} + +impl ReportOffence + for FilterHistoricalOffences, R> where + T: Trait, + R: ReportOffence, + O: Offence, +{ + fn report_offence(reporters: Vec, offence: O) { + // disallow any slashing from before the current era. + let offence_session = offence.session_index(); + if offence_session >= >::current_era_start_session_index() { + R::report_offence(reporters, offence) + } else { + >::deposit_event( + RawEvent::OldSlashingReportDiscarded(offence_session) + ) + } + } +} diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index d8233e5f45dfa585300d6c9e8cf3dc19c0aa4e83..5929be59086112b89062b0a587aa57838970fcb5 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -17,13 +17,15 @@ //! Test utilities use std::{collections::HashSet, cell::RefCell}; -use sr_primitives::Perbill; -use sr_primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize}; +use sr_primitives::{Perbill, KeyTypeId}; +use sr_primitives::curve::PiecewiseLinear; +use sr_primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize, SaturatedConversion}; use sr_primitives::testing::{Header, UintAuthorityId}; -use primitives::{H256, Blake2Hasher}; +use sr_staking_primitives::SessionIndex; +use primitives::{H256, crypto::key_types}; use runtime_io; -use srml_support::{assert_ok, impl_outer_origin, parameter_types, EnumerableStorageMap}; -use srml_support::traits::{Currency, Get, FindAuthor}; +use support::{assert_ok, impl_outer_origin, parameter_types, StorageLinkedMap}; +use support::traits::{Currency, Get, FindAuthor}; use crate::{ EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination, Nominators, inflation @@ -40,9 +42,7 @@ impl Convert for CurrencyToVoteHandler { fn convert(x: u64) -> u64 { x } } impl Convert for CurrencyToVoteHandler { - fn convert(x: u128) -> u64 { - x as u64 - } + fn convert(x: u128) -> u64 { x.saturated_into() } } thread_local! { @@ -52,6 +52,10 @@ thread_local! { pub struct TestSessionHandler; impl session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[key_types::DUMMY]; + + fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} + fn on_new_session( _changed: bool, validators: &[(AccountId, Ks)], @@ -71,8 +75,8 @@ impl session::SessionHandler for TestSessionHandler { } } -pub fn is_disabled(validator: AccountId) -> bool { - let stash = Staking::ledger(&validator).unwrap().stash; +pub fn is_disabled(controller: AccountId) -> bool { + let stash = Staking::ledger(&controller).unwrap().stash; SESSION.with(|d| d.borrow().1.contains(&stash)) } @@ -91,7 +95,7 @@ impl_outer_origin!{ pub struct Author11; impl FindAuthor for Author11 { fn find_author<'a, I>(_digests: I) -> Option - where I: 'a + IntoIterator + where I: 'a + IntoIterator { Some(11) } @@ -116,38 +120,33 @@ impl system::Trait for Test { type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } parameter_types! { pub const TransferFee: Balance = 0; pub const CreationFee: Balance = 0; - pub const TransactionBaseFee: u64 = 0; - pub const TransactionByteFee: u64 = 0; } impl balances::Trait for Test { type Balance = Balance; type OnFreeBalanceZero = Staking; type OnNewAccount = (); type Event = (); - type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = (); } parameter_types! { pub const Period: BlockNumber = 1; pub const Offset: BlockNumber = 0; pub const UncleGenerations: u64 = 0; + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(25); } impl session::Trait for Test { type OnSessionEnding = session::historical::NoteHistoricalRoot; @@ -158,6 +157,7 @@ impl session::Trait for Test { type ValidatorId = AccountId; type ValidatorIdOf = crate::StashOf; type SelectInitialValidators = Staking; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; } impl session::historical::Trait for Test { @@ -178,21 +178,35 @@ impl timestamp::Trait for Test { type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; } +srml_staking_reward_curve::build! { + const I_NPOS: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} parameter_types! { - pub const SessionsPerEra: session::SessionIndex = 3; + pub const SessionsPerEra: SessionIndex = 3; pub const BondingDuration: EraIndex = 3; + pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; + pub const MaxReward: Perbill = Perbill::from_percent(10); } impl Trait for Test { type Currency = balances::Module; type Time = timestamp::Module; type CurrencyToVote = CurrencyToVoteHandler; - type OnRewardMinted = (); + type RewardRemainder = (); type Event = (); type Slash = (); type Reward = (); type SessionsPerEra = SessionsPerEra; type BondingDuration = BondingDuration; type SessionInterface = Self; + type RewardCurve = RewardCurve; + type MaxPossibleReward = MaxReward; } pub struct ExtBuilder { @@ -203,6 +217,7 @@ pub struct ExtBuilder { minimum_validator_count: u32, fair: bool, num_validators: Option, + invulnerables: Vec, } impl Default for ExtBuilder { @@ -215,6 +230,7 @@ impl Default for ExtBuilder { minimum_validator_count: 0, fair: true, num_validators: None, + invulnerables: vec![], } } } @@ -248,10 +264,14 @@ impl ExtBuilder { self.num_validators = Some(num_validators); self } + pub fn invulnerables(mut self, invulnerables: Vec) -> Self { + self.invulnerables = invulnerables; + self + } pub fn set_associated_consts(&self) { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); } - pub fn build(self) -> runtime_io::TestExternalities { + pub fn build(self) -> runtime_io::TestExternalities { self.set_associated_consts(); let mut storage = system::GenesisConfig::default().build_storage::().unwrap(); let balance_factor = if self.existential_deposit > 0 { @@ -298,6 +318,7 @@ impl ExtBuilder { let _ = GenesisConfig::{ current_era: 0, stakers: vec![ + // (stash, controller, staked_amount, status) (11, 10, balance_factor * 1000, StakerStatus::::Validator), (21, 20, stake_21, StakerStatus::::Validator), (31, 30, stake_31, StakerStatus::::Validator), @@ -307,18 +328,17 @@ impl ExtBuilder { ], validator_count: self.validator_count, minimum_validator_count: self.minimum_validator_count, - offline_slash: Perbill::from_percent(5), - offline_slash_grace: 0, - invulnerables: vec![], - .. Default::default() + invulnerables: self.invulnerables, + slash_reward_fraction: Perbill::from_percent(10), + ..Default::default() }.assimilate_storage(&mut storage); let _ = session::GenesisConfig:: { keys: validators.iter().map(|x| (*x, UintAuthorityId(*x))).collect(), }.assimilate_storage(&mut storage); - let mut ext = storage.into(); - runtime_io::with_externalities(&mut ext, || { + let mut ext = runtime_io::TestExternalities::from(storage); + ext.execute_with(|| { let validators = Session::validators(); SESSION.with(|x| *x.borrow_mut() = (validators.clone(), HashSet::new()) @@ -371,11 +391,6 @@ pub fn check_nominator_exposure(stash: u64) { ); } -pub fn assert_total_expo(stash: u64, val: u64) { - let expo = Staking::stakers(&stash); - assert_eq!(expo.total, val); -} - pub fn assert_is_stash(acc: u64) { assert!(Staking::bonded(&acc).is_some(), "Not a stash."); } @@ -383,25 +398,30 @@ pub fn assert_is_stash(acc: u64) { pub fn bond_validator(acc: u64, val: u64) { // a = controller // a + 1 = stash - let _ = Balances::make_free_balance_be(&(acc+1), val); - assert_ok!(Staking::bond(Origin::signed(acc+1), acc, val, RewardDestination::Controller)); + let _ = Balances::make_free_balance_be(&(acc + 1), val); + assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(acc), ValidatorPrefs::default())); } pub fn bond_nominator(acc: u64, val: u64, target: Vec) { // a = controller // a + 1 = stash - let _ = Balances::make_free_balance_be(&(acc+1), val); - assert_ok!(Staking::bond(Origin::signed(acc+1), acc, val, RewardDestination::Controller)); + let _ = Balances::make_free_balance_be(&(acc + 1), val); + assert_ok!(Staking::bond(Origin::signed(acc + 1), acc, val, RewardDestination::Controller)); assert_ok!(Staking::nominate(Origin::signed(acc), target)); } -pub fn start_session(session_index: session::SessionIndex) { +pub fn advance_session() { + let current_index = Session::current_index(); + start_session(current_index + 1); +} + +pub fn start_session(session_index: SessionIndex) { // Compensate for session delay let session_index = session_index + 1; for i in Session::current_index()..session_index { System::set_block_number((i + 1).into()); - Timestamp::set_timestamp(System::block_number()); + Timestamp::set_timestamp(System::block_number() * 1000); Session::on_initialize(System::block_number()); } @@ -415,7 +435,8 @@ pub fn start_era(era_index: EraIndex) { pub fn current_total_payout_for_duration(duration: u64) -> u64 { let res = inflation::compute_total_payout( - >::slot_stake()*2, + ::RewardCurve::get(), + >::slot_stake() * 2, Balances::total_issuance(), duration, ); diff --git a/srml/staking/src/phragmen.rs b/srml/staking/src/phragmen.rs deleted file mode 100644 index 14b8a3845f2c497e570c9404272a8d4698d3eaf2..0000000000000000000000000000000000000000 --- a/srml/staking/src/phragmen.rs +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Rust implementation of the Phragmén election algorithm. - -use rstd::{prelude::*, collections::btree_map::BTreeMap}; -use sr_primitives::{PerU128}; -use sr_primitives::traits::{Zero, Convert, Saturating}; -use crate::{BalanceOf, RawAssignment, ExpoMap, Trait, ValidatorPrefs, IndividualExposure}; - -type Fraction = PerU128; -/// Wrapper around the type used as the _safe_ wrapper around a `balance`. -pub type ExtendedBalance = u128; - -// this is only used while creating the candidate score. Due to reasons explained below -// The more accurate this is, the less likely we choose a wrong candidate. -const SCALE_FACTOR: ExtendedBalance = u32::max_value() as ExtendedBalance + 1; -/// These are used to expose a fixed accuracy to the caller function. The bigger they are, -/// the more accurate we get, but the more likely it is for us to overflow. The case of overflow -/// is handled but accuracy will be lost. 32 or 16 are reasonable values. -pub const ACCURACY: ExtendedBalance = u32::max_value() as ExtendedBalance + 1; - -/// Wrapper around validation candidates some metadata. -#[derive(Clone, Default)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct Candidate { - /// The validator's account - pub who: AccountId, - /// Intermediary value used to sort candidates. - pub score: Fraction, - /// Accumulator of the stake of this candidate based on received votes. - approval_stake: ExtendedBalance, - /// Flag for being elected. - elected: bool, -} - -/// Wrapper around the nomination info of a single nominator for a group of validators. -#[derive(Clone, Default)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct Nominator { - /// The nominator's account. - who: AccountId, - /// List of validators proposed by this nominator. - edges: Vec>, - /// the stake amount proposed by the nominator as a part of the vote. - budget: ExtendedBalance, - /// Incremented each time a nominee that this nominator voted for has been elected. - load: Fraction, -} - -/// Wrapper around a nominator vote and the load of that vote. -#[derive(Clone, Default)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct Edge { - /// Account being voted for - who: AccountId, - /// Load of this vote. - load: Fraction, - /// Equal to `edge.load / nom.load`. Stored only to be used with post-processing. - ratio: ExtendedBalance, - /// Index of the candidate stored in the 'candidates' vector. - candidate_index: usize, -} - -/// Perform election based on Phragmén algorithm. -/// -/// Reference implementation: https://github.com/w3f/consensus -/// -/// Returns an Option of elected candidates, if election is performed. -/// Returns None if not enough candidates exist. -/// -/// The returned Option is a tuple consisting of: -/// - The list of elected candidates. -/// - The list of nominators and their associated vote weights. -pub fn elect( - validator_count: usize, - minimum_validator_count: usize, - validator_iter: FV, - nominator_iter: FN, - slashable_balance_of: FS, -) -> Option<(Vec, Vec<(T::AccountId, Vec>)>)> where - FV: Iterator>)>, - FN: Iterator)>, - for <'r> FS: Fn(&'r T::AccountId) -> BalanceOf, -{ - let to_votes = |b: BalanceOf| , u64>>::convert(b) as ExtendedBalance; - - // return structures - let mut elected_candidates: Vec; - let mut assigned: Vec<(T::AccountId, Vec>)>; - let mut c_idx_cache = BTreeMap::::new(); - - // 1- Pre-process candidates and place them in a container, optimisation and add phantom votes. - // Candidates who have 0 stake => have no votes or all null-votes. Kick them out not. - let mut nominators: Vec> = - Vec::with_capacity(validator_iter.size_hint().0 + nominator_iter.size_hint().0); - let mut candidates = validator_iter.map(|(who, _)| { - let stash_balance = slashable_balance_of(&who); - (Candidate { who, ..Default::default() }, stash_balance) - }) - .filter_map(|(mut c, s)| { - c.approval_stake += to_votes(s); - if c.approval_stake.is_zero() { - None - } else { - Some((c, s)) - } - }) - .enumerate() - .map(|(idx, (c, s))| { - nominators.push(Nominator { - who: c.who.clone(), - edges: vec![ Edge { who: c.who.clone(), candidate_index: idx, ..Default::default() }], - budget: to_votes(s), - load: Fraction::zero(), - }); - c_idx_cache.insert(c.who.clone(), idx); - c - }) - .collect::>>(); - - // 2- Collect the nominators with the associated votes. - // Also collect approval stake along the way. - nominators.extend(nominator_iter.map(|(who, nominees)| { - let nominator_stake = slashable_balance_of(&who); - let mut edges: Vec> = Vec::with_capacity(nominees.len()); - for n in &nominees { - if let Some(idx) = c_idx_cache.get(n) { - // This candidate is valid + already cached. - candidates[*idx].approval_stake = candidates[*idx].approval_stake - .saturating_add(to_votes(nominator_stake)); - edges.push(Edge { who: n.clone(), candidate_index: *idx, ..Default::default() }); - } // else {} would be wrong votes. We don't really care about it. - } - Nominator { - who, - edges: edges, - budget: to_votes(nominator_stake), - load: Fraction::zero(), - } - })); - - // 4- If we have more candidates then needed, run Phragmén. - if candidates.len() >= minimum_validator_count { - let validator_count = validator_count.min(candidates.len()); - - elected_candidates = Vec::with_capacity(validator_count); - assigned = Vec::with_capacity(validator_count); - // Main election loop - for _round in 0..validator_count { - // Loop 1: initialize score - for c in &mut candidates { - if !c.elected { - c.score = Fraction::from_xth(c.approval_stake); - } - } - // Loop 2: increment score. - for n in &nominators { - for e in &n.edges { - let c = &mut candidates[e.candidate_index]; - if !c.elected && !c.approval_stake.is_zero() { - // Basic fixed-point shifting by 32. - // `n.budget.saturating_mul(SCALE_FACTOR)` will never saturate - // since n.budget cannot exceed u64,despite being stored in u128. yet, - // `*n.load / SCALE_FACTOR` might collapse to zero. Hence, 32 or 16 bits are better scale factors. - // Note that left-associativity in operators precedence is crucially important here. - let temp = - n.budget.saturating_mul(SCALE_FACTOR) / c.approval_stake - * (*n.load / SCALE_FACTOR); - c.score = Fraction::from_parts((*c.score).saturating_add(temp)); - } - } - } - - // Find the best - if let Some(winner) = candidates - .iter_mut() - .filter(|c| !c.elected) - .min_by_key(|c| *c.score) - { - // loop 3: update nominator and edge load - winner.elected = true; - for n in &mut nominators { - for e in &mut n.edges { - if e.who == winner.who { - e.load = Fraction::from_parts(*winner.score - *n.load); - n.load = winner.score; - } - } - } - - elected_candidates.push(winner.who.clone()); - } else { - break - } - } // end of all rounds - - // 4.1- Update backing stake of candidates and nominators - for n in &mut nominators { - let mut assignment = (n.who.clone(), vec![]); - for e in &mut n.edges { - if let Some(c) = elected_candidates.iter().find(|c| **c == e.who) { - if *c != n.who { - let ratio = { - // Full support. No need to calculate. - if *n.load == *e.load { ACCURACY } - else { - // This should not saturate. Safest is to just check - if let Some(r) = ACCURACY.checked_mul(*e.load) { - r / n.load.max(1) - } else { - // Just a simple trick. - *e.load / (n.load.max(1) / ACCURACY) - } - } - }; - e.ratio = ratio; - assignment.1.push((e.who.clone(), ratio)); - } - } - } - - if assignment.1.len() > 0 { - // To ensure an assertion indicating: no stake from the nominator going to waste, - // we add a minimal post-processing to equally assign all of the leftover stake ratios. - let vote_count = assignment.1.len() as ExtendedBalance; - let l = assignment.1.len(); - let sum = assignment.1.iter().map(|a| a.1).sum::(); - let diff = ACCURACY.checked_sub(sum).unwrap_or(0); - let diff_per_vote= diff / vote_count; - - if diff_per_vote > 0 { - for i in 0..l { - assignment.1[i%l].1 = - assignment.1[i%l].1 - .saturating_add(diff_per_vote); - } - } - - // `remainder` is set to be less than maximum votes of a nominator (currently 16). - // safe to cast it to usize. - let remainder = diff - diff_per_vote * vote_count; - for i in 0..remainder as usize { - assignment.1[i%l].1 = - assignment.1[i%l].1 - .saturating_add(1); - } - assigned.push(assignment); - } - } - - } else { - // if we have less than minimum, use the previous validator set. - return None - } - Some((elected_candidates, assigned)) -} - -/// Performs equalize post-processing to the output of the election algorithm -/// This function mutates the input parameters, most noticeably it updates the exposure of -/// the elected candidates. -/// -/// No value is returned from the function and the `expo_map` parameter is updated. -pub fn equalize( - assignments: &mut Vec<(T::AccountId, BalanceOf, Vec<(T::AccountId, ExtendedBalance, ExtendedBalance)>)>, - expo_map: &mut ExpoMap, - tolerance: ExtendedBalance, - iterations: usize, -) { - for _i in 0..iterations { - let mut max_diff = 0; - assignments.iter_mut().for_each(|(n, budget, assignment)| { - let diff = do_equalize::(&n, *budget, assignment, expo_map, tolerance); - if diff > max_diff { - max_diff = diff; - } - }); - if max_diff < tolerance { - break; - } - } -} - -fn do_equalize( - nominator: &T::AccountId, - budget_balance: BalanceOf, - elected_edges: &mut Vec<(T::AccountId, ExtendedBalance, ExtendedBalance)>, - expo_map: &mut ExpoMap, - tolerance: ExtendedBalance -) -> ExtendedBalance { - let to_votes = |b: BalanceOf| - , u64>>::convert(b) as ExtendedBalance; - let to_balance = |v: ExtendedBalance| - >>::convert(v); - let budget = to_votes(budget_balance); - - // Nothing to do. This nominator had nothing useful. - // Defensive only. Assignment list should always be populated. - if elected_edges.is_empty() { return 0; } - - let stake_used = elected_edges - .iter() - .fold(0 as ExtendedBalance, |s, e| s.saturating_add(e.2)); - - let backed_stakes_iter = elected_edges - .iter() - .filter_map(|e| expo_map.get(&e.0)) - .map(|e| to_votes(e.total)); - - let backing_backed_stake = elected_edges - .iter() - .filter(|e| e.2 > 0) - .filter_map(|e| expo_map.get(&e.0)) - .map(|e| to_votes(e.total)) - .collect::>(); - - let mut difference; - if backing_backed_stake.len() > 0 { - let max_stake = backing_backed_stake - .iter() - .max() - .expect("vector with positive length will have a max; qed"); - let min_stake = backed_stakes_iter - .min() - .expect("iterator with positive length will have a min; qed"); - - difference = max_stake.saturating_sub(min_stake); - difference = difference.saturating_add(budget.saturating_sub(stake_used)); - if difference < tolerance { - return difference; - } - } else { - difference = budget; - } - - // Undo updates to exposure - elected_edges.iter_mut().for_each(|e| { - if let Some(expo) = expo_map.get_mut(&e.0) { - expo.total = expo.total.saturating_sub(to_balance(e.2)); - expo.others.retain(|i_expo| i_expo.who != *nominator); - } - e.2 = 0; - }); - - elected_edges.sort_unstable_by_key(|e| - if let Some(e) = expo_map.get(&e.0) { e.total } else { Zero::zero() } - ); - - let mut cumulative_stake: ExtendedBalance = 0; - let mut last_index = elected_edges.len() - 1; - elected_edges.iter_mut().enumerate().for_each(|(idx, e)| { - if let Some(expo) = expo_map.get_mut(&e.0) { - let stake: ExtendedBalance = to_votes(expo.total); - let stake_mul = stake.saturating_mul(idx as ExtendedBalance); - let stake_sub = stake_mul.saturating_sub(cumulative_stake); - if stake_sub > budget { - last_index = idx.checked_sub(1).unwrap_or(0); - return - } - cumulative_stake = cumulative_stake.saturating_add(stake); - } - }); - - let last_stake = elected_edges[last_index].2; - let split_ways = last_index + 1; - let excess = budget - .saturating_add(cumulative_stake) - .saturating_sub(last_stake.saturating_mul(split_ways as ExtendedBalance)); - elected_edges.iter_mut().take(split_ways).for_each(|e| { - if let Some(expo) = expo_map.get_mut(&e.0) { - e.2 = (excess / split_ways as ExtendedBalance) - .saturating_add(last_stake) - .saturating_sub(to_votes(expo.total)); - expo.total = expo.total.saturating_add(to_balance(e.2)); - expo.others.push(IndividualExposure { who: nominator.clone(), value: to_balance(e.2)}); - } - }); - - difference -} diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index de473dd9902fc0cb114700cb090693ade80de5d6..aef5a26a04537828b4a0ed62fa855e107507d7de 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -17,39 +17,68 @@ //! Tests for the module. use super::*; -use runtime_io::with_externalities; -use phragmen; -use sr_primitives::traits::OnInitialize; -use srml_support::{assert_ok, assert_noop, assert_eq_uvec, EnumerableStorageMap}; use mock::*; -use srml_support::traits::{Currency, ReservableCurrency}; +use sr_primitives::{assert_eq_error_rate, traits::OnInitialize}; +use sr_staking_primitives::offence::{OffenceDetails, OnOffenceHandler}; +use support::{assert_ok, assert_noop, assert_eq_uvec, traits::{Currency, ReservableCurrency}}; + +#[test] +fn force_unstake_works() { + // Verifies initial conditions of mock + ExtBuilder::default().build().execute_with(|| { + // Account 11 is stashed and locked, and account 10 is the controller + assert_eq!(Staking::bonded(&11), Some(10)); + // Cant transfer + assert_noop!( + Balances::transfer(Origin::signed(11), 1, 10), + "account liquidity restrictions prevent withdrawal" + ); + // Force unstake requires root. + assert_noop!(Staking::force_unstake(Origin::signed(11), 11), "RequireRootOrigin"); + // We now force them to unstake + assert_ok!(Staking::force_unstake(Origin::ROOT, 11)); + // No longer bonded. + assert_eq!(Staking::bonded(&11), None); + // Transfer works. + assert_ok!(Balances::transfer(Origin::signed(11), 1, 10)); + }); +} #[test] fn basic_setup_works() { // Verifies initial conditions of mock - with_externalities(&mut ExtBuilder::default() - .build(), - || { - assert_eq!(Staking::bonded(&11), Some(10)); // Account 11 is stashed and locked, and account 10 is the controller - assert_eq!(Staking::bonded(&21), Some(20)); // Account 21 is stashed and locked, and account 20 is the controller - assert_eq!(Staking::bonded(&1), None); // Account 1 is not a stashed + ExtBuilder::default().build().execute_with(|| { + // Account 11 is stashed and locked, and account 10 is the controller + assert_eq!(Staking::bonded(&11), Some(10)); + // Account 21 is stashed and locked, and account 20 is the controller + assert_eq!(Staking::bonded(&21), Some(20)); + // Account 1 is not a stashed + assert_eq!(Staking::bonded(&1), None); // Account 10 controls the stash from account 11, which is 100 * balance_factor units - assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] })); + assert_eq!( + Staking::ledger(&10), + Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] }) + ); // Account 20 controls the stash from account 21, which is 200 * balance_factor units - assert_eq!(Staking::ledger(&20), Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![] })); + assert_eq!( + Staking::ledger(&20), + Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![] }) + ); // Account 1 does not control any stash assert_eq!(Staking::ledger(&1), None); - // ValidatorPrefs are default, thus unstake_threshold is 3, other values are default for their type + // ValidatorPrefs are default assert_eq!(>::enumerate().collect::>(), vec![ - (31, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }), - (21, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }), - (11, ValidatorPrefs { unstake_threshold: 3, validator_payment: 0 }) + (31, ValidatorPrefs::default()), + (21, ValidatorPrefs::default()), + (11, ValidatorPrefs::default()) ]); - // Account 100 is the default nominator - assert_eq!(Staking::ledger(100), Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![] })); + assert_eq!( + Staking::ledger(100), + Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![] }) + ); assert_eq!(Staking::nominators(101), vec![11, 21]); if cfg!(feature = "equalize") { @@ -83,39 +112,22 @@ fn basic_setup_works() { // Initial Era and session assert_eq!(Staking::current_era(), 0); - // initial slash_count of validators - assert_eq!(Staking::slash_count(&11), 0); - assert_eq!(Staking::slash_count(&21), 0); - - // All exposures must be correct. - check_exposure_all(); - check_nominator_all(); - }); -} - -#[test] -fn no_offline_should_work() { - // Test the staking module works when no validators are offline - with_externalities(&mut ExtBuilder::default().build(), - || { - // Slashing begins for validators immediately if found offline - assert_eq!(Staking::offline_slash_grace(), 0); - // Account 10 has not been reported offline - assert_eq!(Staking::slash_count(&10), 0); // Account 10 has `balance_factor` free balance assert_eq!(Balances::free_balance(&10), 1); - // Nothing happens to Account 10, as expected - assert_eq!(Staking::slash_count(&10), 0); assert_eq!(Balances::free_balance(&10), 1); + // New era is not being forced assert_eq!(Staking::force_era(), Forcing::NotForcing); + + // All exposures must be correct. + check_exposure_all(); + check_nominator_all(); }); } #[test] fn change_controller_works() { - with_externalities(&mut ExtBuilder::default().build(), - || { + ExtBuilder::default().build().execute_with(|| { assert_eq!(Staking::bonded(&11), Some(10)); assert!(>::enumerate().map(|(c, _)| c).collect::>().contains(&11)); @@ -135,197 +147,17 @@ fn change_controller_works() { }) } -#[test] -fn invulnerability_should_work() { - // Test that users can be invulnerable from slashing and being kicked - with_externalities(&mut ExtBuilder::default().build(), - || { - // Make account 11 invulnerable - assert_ok!(Staking::set_invulnerables(Origin::ROOT, vec![11])); - // Give account 11 some funds - let _ = Balances::make_free_balance_be(&11, 70); - // There is no slash grace -- slash immediately. - assert_eq!(Staking::offline_slash_grace(), 0); - // Account 11 has not been slashed - assert_eq!(Staking::slash_count(&11), 0); - // Account 11 has the 70 funds we gave it above - assert_eq!(Balances::free_balance(&11), 70); - // Account 11 should be a validator - assert!(>::exists(&11)); - - // Set account 11 as an offline validator with a large number of reports - // Should exit early if invulnerable - Staking::on_offline_validator(10, 100); - - // Show that account 11 has not been touched - assert_eq!(Staking::slash_count(&11), 0); - assert_eq!(Balances::free_balance(&11), 70); - assert!(>::exists(&11)); - // New era not being forced - // NOTE: new era is always forced once slashing happens -> new validators need to be chosen. - assert_eq!(Staking::force_era(), Forcing::NotForcing); - }); -} - -#[test] -fn offline_should_slash_and_disable() { - // Test that an offline validator gets slashed and kicked - with_externalities(&mut ExtBuilder::default().build(), || { - // Give account 10 some balance - let _ = Balances::make_free_balance_be(&11, 1000); - // Confirm account 10 is a validator - assert!(>::exists(&11)); - // Validators get slashed immediately - assert_eq!(Staking::offline_slash_grace(), 0); - // Unstake threshold is 3 - assert_eq!(Staking::validators(&11).unstake_threshold, 3); - // Account 10 has not been slashed before - assert_eq!(Staking::slash_count(&11), 0); - // Account 10 has the funds we just gave it - assert_eq!(Balances::free_balance(&11), 1000); - // Account 10 is not yet disabled. - assert!(!is_disabled(10)); - // Report account 10 as offline, one greater than unstake threshold - Staking::on_offline_validator(10, 4); - // Confirm user has been reported - assert_eq!(Staking::slash_count(&11), 4); - // Confirm balance has been reduced by 2^unstake_threshold * offline_slash() * amount_at_stake. - let slash_base = Staking::offline_slash() * Staking::stakers(11).total; - assert_eq!(Balances::free_balance(&11), 1000 - 2_u64.pow(3) * slash_base); - // Confirm account 10 has been disabled. - assert!(is_disabled(10)); - }); -} - -#[test] -fn offline_grace_should_delay_slashing() { - // Tests that with grace, slashing is delayed - with_externalities(&mut ExtBuilder::default().build(), || { - // Initialize account 10 with balance - let _ = Balances::make_free_balance_be(&11, 70); - // Verify account 11 has balance - assert_eq!(Balances::free_balance(&11), 70); - - // Set offline slash grace - let offline_slash_grace = 1; - assert_ok!(Staking::set_offline_slash_grace(Origin::ROOT, offline_slash_grace)); - assert_eq!(Staking::offline_slash_grace(), 1); - - // Check unstake_threshold is 3 (default) - let default_unstake_threshold = 3; - assert_eq!( - Staking::validators(&11), - ValidatorPrefs { unstake_threshold: default_unstake_threshold, validator_payment: 0 } - ); - - // Check slash count is zero - assert_eq!(Staking::slash_count(&11), 0); - - // Report account 10 up to the threshold - Staking::on_offline_validator(10, default_unstake_threshold as usize + offline_slash_grace as usize); - // Confirm slash count - assert_eq!(Staking::slash_count(&11), 4); - - // Nothing should happen - assert_eq!(Balances::free_balance(&11), 70); - - // Report account 10 one more time - Staking::on_offline_validator(10, 1); - assert_eq!(Staking::slash_count(&11), 5); - // User gets slashed - assert!(Balances::free_balance(&11) < 70); - // New era is forced - assert!(is_disabled(10)); - }); -} - - -#[test] -fn max_unstake_threshold_works() { - // Tests that max_unstake_threshold gets used when prefs.unstake_threshold is large - with_externalities(&mut ExtBuilder::default().build(), || { - const MAX_UNSTAKE_THRESHOLD: u32 = 10; - // Two users with maximum possible balance - let _ = Balances::make_free_balance_be(&11, u64::max_value()); - let _ = Balances::make_free_balance_be(&21, u64::max_value()); - - // Give them full exposure as a staker - >::insert(&11, Exposure { total: 1000000, own: 1000000, others: vec![]}); - >::insert(&21, Exposure { total: 2000000, own: 2000000, others: vec![]}); - - // Check things are initialized correctly - assert_eq!(Balances::free_balance(&11), u64::max_value()); - assert_eq!(Balances::free_balance(&21), u64::max_value()); - assert_eq!(Staking::offline_slash_grace(), 0); - // Account 10 will have max unstake_threshold - assert_ok!(Staking::validate(Origin::signed(10), ValidatorPrefs { - unstake_threshold: MAX_UNSTAKE_THRESHOLD, - validator_payment: 0, - })); - // Account 20 could not set their unstake_threshold past 10 - assert_noop!(Staking::validate(Origin::signed(20), ValidatorPrefs { - unstake_threshold: MAX_UNSTAKE_THRESHOLD + 1, - validator_payment: 0}), - "unstake threshold too large" - ); - // Give Account 20 unstake_threshold 11 anyway, should still be limited to 10 - >::insert(21, ValidatorPrefs { - unstake_threshold: MAX_UNSTAKE_THRESHOLD + 1, - validator_payment: 0, - }); - - OfflineSlash::put(Perbill::from_fraction(0.0001)); - - // Report each user 1 more than the max_unstake_threshold - Staking::on_offline_validator(10, MAX_UNSTAKE_THRESHOLD as usize + 1); - Staking::on_offline_validator(20, MAX_UNSTAKE_THRESHOLD as usize + 1); - - // Show that each balance only gets reduced by 2^max_unstake_threshold times 10% - // of their total stake. - assert_eq!(Balances::free_balance(&11), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 100); - assert_eq!(Balances::free_balance(&21), u64::max_value() - 2_u64.pow(MAX_UNSTAKE_THRESHOLD) * 200); - }); -} - -#[test] -fn slashing_does_not_cause_underflow() { - // Tests that slashing more than a user has does not underflow - with_externalities(&mut ExtBuilder::default().build(), || { - // Verify initial conditions - assert_eq!(Balances::free_balance(&11), 1000); - assert_eq!(Staking::offline_slash_grace(), 0); - - // Set validator preference so that 2^unstake_threshold would cause overflow (greater than 64) - // FIXME: that doesn't overflow. - >::insert(11, ValidatorPrefs { - unstake_threshold: 10, - validator_payment: 0, - }); - - System::set_block_number(1); - Session::on_initialize(System::block_number()); - - // Should not panic - Staking::on_offline_validator(10, 100); - // Confirm that underflow has not occurred, and account balance is set to zero - assert_eq!(Balances::free_balance(&11), 0); - }); -} - #[test] fn rewards_should_work() { // should check that: // * rewards get recorded per session // * rewards get paid per Era // * Check that nominators are also rewarded - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { + ExtBuilder::default().nominate(false).build().execute_with(|| { // Init some balances let _ = Balances::make_free_balance_be(&2, 500); - let delay = 1; + let delay = 1000; let init_balance_2 = Balances::total_balance(&2); let init_balance_10 = Balances::total_balance(&10); let init_balance_11 = Balances::total_balance(&11); @@ -353,7 +185,7 @@ fn rewards_should_work() { let mut block = 3; // Block 3 => Session 1 => Era 0 System::set_block_number(block); - Timestamp::set_timestamp(block*5); // on time. + Timestamp::set_timestamp(block * 5000); // on time. Session::on_initialize(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 1); @@ -365,7 +197,7 @@ fn rewards_should_work() { >::reward_by_ids(vec![(1001, 10_000)]); // Compute total payout now for whole duration as other parameter won't change - let total_payout = current_total_payout_for_duration(9 * 5); + let total_payout = current_total_payout_for_duration(9 * 5 * 1000); assert!(total_payout > 10); // Test is meaningful if reward something // No reward yet @@ -375,21 +207,21 @@ fn rewards_should_work() { block = 6; // Block 6 => Session 2 => Era 0 System::set_block_number(block); - Timestamp::set_timestamp(block*5 + delay); // a little late. + Timestamp::set_timestamp(block * 5000 + delay); // a little late. Session::on_initialize(System::block_number()); assert_eq!(Staking::current_era(), 0); assert_eq!(Session::current_index(), 2); block = 9; // Block 9 => Session 3 => Era 1 System::set_block_number(block); - Timestamp::set_timestamp(block*5); // back to being on time. no delays + Timestamp::set_timestamp(block * 5000); // back to being on time. no delays Session::on_initialize(System::block_number()); assert_eq!(Staking::current_era(), 1); assert_eq!(Session::current_index(), 3); // 11 validator has 2/3 of the total rewards and half half for it and its nominator - assert_eq!(Balances::total_balance(&2), init_balance_2 + total_payout/3); - assert_eq!(Balances::total_balance(&10), init_balance_10 + total_payout/3); + assert_eq_error_rate!(Balances::total_balance(&2), init_balance_2 + total_payout / 3, 1); + assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + total_payout / 3, 1); assert_eq!(Balances::total_balance(&11), init_balance_11); }); } @@ -399,19 +231,15 @@ fn multi_era_reward_should_work() { // Should check that: // The value of current_session_reward is set at the end of each era, based on // slot_stake and session_reward. - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { + ExtBuilder::default().nominate(false).build().execute_with(|| { let init_balance_10 = Balances::total_balance(&10); // Set payee to controller assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); // Compute now as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3); + let total_payout_0 = current_total_payout_for_duration(3000); assert!(total_payout_0 > 10); // Test is meaningfull if reward something - dbg!(>::slot_stake()); >::reward_by_ids(vec![(11, 1)]); start_session(0); @@ -424,7 +252,7 @@ fn multi_era_reward_should_work() { start_session(4); - let total_payout_1 = current_total_payout_for_duration(3); + let total_payout_1 = current_total_payout_for_duration(3000); assert!(total_payout_1 > 10); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 101)]); @@ -442,131 +270,128 @@ fn staking_should_work() { // * new validators can be added to the default set // * new ones will be chosen per era // * either one can unlock the stash and back-down from being a validator via `chill`ing. - with_externalities(&mut ExtBuilder::default() + ExtBuilder::default() .nominate(false) .fair(false) // to give 20 more staked value - .build(), - || { - Timestamp::set_timestamp(1); // Initialize time. + .build() + .execute_with(|| { + Timestamp::set_timestamp(1); // Initialize time. - // remember + compare this along with the test. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); + // remember + compare this along with the test. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); - // put some money in account that we'll use. - for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); } + // put some money in account that we'll use. + for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); } - // --- Block 1: - start_session(1); - // add a new candidate for being a validator. account 3 controlled by 4. - assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); - assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); + // --- Block 1: + start_session(1); + // add a new candidate for being a validator. account 3 controlled by 4. + assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); - // No effects will be seen so far. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); + // No effects will be seen so far. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); - // --- Block 2: - start_session(2); + // --- Block 2: + start_session(2); - // No effects will be seen so far. Era has not been yet triggered. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); + // No effects will be seen so far. Era has not been yet triggered. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); - // --- Block 3: the validators will now be queued. - start_session(3); - assert_eq!(Staking::current_era(), 1); + // --- Block 3: the validators will now be queued. + start_session(3); + assert_eq!(Staking::current_era(), 1); - // --- Block 4: the validators will now be changed. - start_session(4); + // --- Block 4: the validators will now be changed. + start_session(4); - assert_eq_uvec!(validator_controllers(), vec![20, 4]); - // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 - // 4 will chill - Staking::chill(Origin::signed(4)).unwrap(); + assert_eq_uvec!(validator_controllers(), vec![20, 4]); + // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 + // 4 will chill + Staking::chill(Origin::signed(4)).unwrap(); - // --- Block 5: nothing. 4 is still there. - start_session(5); - assert_eq_uvec!(validator_controllers(), vec![20, 4]); + // --- Block 5: nothing. 4 is still there. + start_session(5); + assert_eq_uvec!(validator_controllers(), vec![20, 4]); - // --- Block 6: 4 will not be a validator. - start_session(7); - assert_eq_uvec!(validator_controllers(), vec![20, 10]); + // --- Block 6: 4 will not be a validator. + start_session(7); + assert_eq_uvec!(validator_controllers(), vec![20, 10]); - // Note: the stashed value of 4 is still lock - assert_eq!( - Staking::ledger(&4), - Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![] }) - ); - // e.g. it cannot spend more than 500 that it has free from the total 2000 - assert_noop!(Balances::reserve(&3, 501), "account liquidity restrictions prevent withdrawal"); - assert_ok!(Balances::reserve(&3, 409)); - }); + // Note: the stashed value of 4 is still lock + assert_eq!( + Staking::ledger(&4), + Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![] }) + ); + // e.g. it cannot spend more than 500 that it has free from the total 2000 + assert_noop!(Balances::reserve(&3, 501), "account liquidity restrictions prevent withdrawal"); + assert_ok!(Balances::reserve(&3, 409)); + }); } #[test] fn less_than_needed_candidates_works() { - with_externalities(&mut ExtBuilder::default() + ExtBuilder::default() .minimum_validator_count(1) .validator_count(4) .nominate(false) .num_validators(3) - .build(), - || { - assert_eq!(Staking::validator_count(), 4); - assert_eq!(Staking::minimum_validator_count(), 1); - assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); - - start_era(1); - - // Previous set is selected. NO election algorithm is even executed. - assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); - - // But the exposure is updated in a simple way. No external votes exists. This is purely self-vote. - assert_eq!(Staking::stakers(10).others.len(), 0); - assert_eq!(Staking::stakers(20).others.len(), 0); - assert_eq!(Staking::stakers(30).others.len(), 0); - check_exposure_all(); - check_nominator_all(); - }); + .build() + .execute_with(|| { + assert_eq!(Staking::validator_count(), 4); + assert_eq!(Staking::minimum_validator_count(), 1); + assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); + + start_era(1); + + // Previous set is selected. NO election algorithm is even executed. + assert_eq_uvec!(validator_controllers(), vec![30, 20, 10]); + + // But the exposure is updated in a simple way. No external votes exists. + // This is purely self-vote. + assert_eq!(Staking::stakers(10).others.len(), 0); + assert_eq!(Staking::stakers(20).others.len(), 0); + assert_eq!(Staking::stakers(30).others.len(), 0); + check_exposure_all(); + check_nominator_all(); + }); } #[test] fn no_candidate_emergency_condition() { - // Test the situation where the number of validators are less than `ValidatorCount` and less than - // The expected behavior is to choose all candidates from the previous era. - with_externalities(&mut ExtBuilder::default() + ExtBuilder::default() .minimum_validator_count(10) .validator_count(15) .num_validators(4) .validator_pool(true) .nominate(false) - .build(), - || { + .build() + .execute_with(|| { + // initial validators + assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); - // initial validators - assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); + // set the minimum validator count. + ::MinimumValidatorCount::put(10); + ::ValidatorCount::put(15); + assert_eq!(Staking::validator_count(), 15); - // set the minimum validator count. - ::MinimumValidatorCount::put(10); - ::ValidatorCount::put(15); - assert_eq!(Staking::validator_count(), 15); + let _ = Staking::chill(Origin::signed(10)); - let _ = Staking::chill(Origin::signed(10)); - - // trigger era - System::set_block_number(1); - Session::on_initialize(System::block_number()); + // trigger era + System::set_block_number(1); + Session::on_initialize(System::block_number()); - // Previous ones are elected. chill is invalidates. TODO: #2494 - assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); - assert_eq!(Staking::current_elected().len(), 0); - }); + // Previous ones are elected. chill is invalidates. TODO: #2494 + assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); + assert_eq!(Staking::current_elected().len(), 0); + }); } #[test] fn nominating_and_rewards_should_work() { // PHRAGMEN OUTPUT: running this test with the reference impl gives: // - // Votes [('10', 1000, ['10']), ('20', 1000, ['20']), ('30', 1000, ['30']), ('40', 1000, ['40']), ('2', 1000, ['10', '20', '30']), ('4', 1000, ['10', '20', '40'])] // Sequential Phragmén gives // 10 is elected with stake 2200.0 and score 0.0003333333333333333 // 20 is elected with stake 1800.0 and score 0.0005555555555555556 @@ -600,161 +425,192 @@ fn nominating_and_rewards_should_work() { // 10 with stake 400.0 20 with stake 600.0 30 with stake 0 // 4 has load 0.0005555555555555556 and supported // 10 with stake 600.0 20 with stake 400.0 40 with stake 0.0 - with_externalities(&mut ExtBuilder::default() + ExtBuilder::default() .nominate(false) .validator_pool(true) - .build(), - || { - // initial validators -- everyone is actually even. - assert_eq_uvec!(validator_controllers(), vec![40, 30]); - - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(30), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(40), RewardDestination::Controller)); - - // give the man some money - let initial_balance = 1000; - for i in [1, 2, 3, 4, 5, 10, 11, 20, 21].iter() { - let _ = Balances::make_free_balance_be(i, initial_balance); - } - - // bond two account pairs and state interest in nomination. - // 2 will nominate for 10, 20, 30 - assert_ok!(Staking::bond(Origin::signed(1), 2, 1000, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21, 31])); - // 4 will nominate for 10, 20, 40 - assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::Controller)); - assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41])); - - // the total reward for era 0 - let total_payout_0 = current_total_payout_for_duration(3); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(41, 1)]); - >::reward_by_ids(vec![(31, 1)]); - >::reward_by_ids(vec![(21, 10)]); // must be no-op - >::reward_by_ids(vec![(11, 10)]); // must be no-op - - start_era(1); - - // 10 and 20 have more votes, they will be chosen by phragmen. - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // OLD validators must have already received some rewards. - assert_eq!(Balances::total_balance(&40), 1 + total_payout_0/2); - assert_eq!(Balances::total_balance(&30), 1 + total_payout_0/2); - - // ------ check the staked value of all parties. - - if cfg!(feature = "equalize") { - // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(11).own, 1000); - assert_eq!(Staking::stakers(11).total, 1000 + 999); - // 2 and 4 supported 10, each with stake 600, according to phragmen. - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![599, 400] - ); - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - // total expo of 20, with 500 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(21).own, 1000); - assert_eq!(Staking::stakers(21).total, 1000 + 999); - // 2 and 4 supported 20, each with stake 250, according to phragmen. - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![400, 599] - ); - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - } else { - // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(11).own, 1000); - assert_eq!(Staking::stakers(11).total, 1000 + 800); - // 2 and 4 supported 10, each with stake 600, according to phragmen. - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![400, 400] - ); - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - // total expo of 20, with 500 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(21).own, 1000); - assert_eq!(Staking::stakers(21).total, 1000 + 1198); - // 2 and 4 supported 20, each with stake 250, according to phragmen. - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![599, 599] - ); - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - } - - // They are not chosen anymore - assert_eq!(Staking::stakers(31).total, 0); - assert_eq!(Staking::stakers(41).total, 0); - - // the total reward for era 1 - let total_payout_1 = current_total_payout_for_duration(3); - assert!(total_payout_1 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(41, 10)]); // must be no-op - >::reward_by_ids(vec![(31, 10)]); // must be no-op - >::reward_by_ids(vec![(21, 2)]); - >::reward_by_ids(vec![(11, 1)]); - - start_era(2); - - // nothing else will happen, era ends and rewards are paid again, - // it is expected that nominators will also be paid. See below - - let payout_for_10 = total_payout_1/3; - let payout_for_20 = 2*total_payout_1/3; - if cfg!(feature = "equalize") { - // Nominator 2: has [400/2000 ~ 1/5 from 10] + [600/2000 ~ 3/10 from 20]'s reward. - assert_eq!(Balances::total_balance(&2), initial_balance + payout_for_10/5 + payout_for_20*3/10 - 1); - // Nominator 4: has [400/2000 ~ 1/5 from 20] + [600/2000 ~ 3/10 from 10]'s reward. - assert_eq!(Balances::total_balance(&4), initial_balance + payout_for_20/5 + payout_for_10*3/10); - - // Validator 10: got 1000 / 2000 external stake. - assert_eq!(Balances::total_balance(&10), initial_balance + payout_for_10/2); - // Validator 20: got 1000 / 2000 external stake. - assert_eq!(Balances::total_balance(&20), initial_balance + payout_for_20/2); - } else { - // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 - assert_eq!(Balances::total_balance(&2), initial_balance + (2*payout_for_10/9 + 3*payout_for_20/11) - 2); - // Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 - assert_eq!(Balances::total_balance(&4), initial_balance + (2*payout_for_10/9 + 3*payout_for_20/11) - 2); - - // Validator 10: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 - assert_eq!(Balances::total_balance(&10), initial_balance + 5*payout_for_10/9 - 1); - // Validator 20: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11 - assert_eq!(Balances::total_balance(&20), initial_balance + 5*payout_for_20/11); - } - - check_exposure_all(); - check_nominator_all(); - }); + .build() + .execute_with(|| { + // initial validators -- everyone is actually even. + assert_eq_uvec!(validator_controllers(), vec![40, 30]); + + // Set payee to controller + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(30), RewardDestination::Controller)); + assert_ok!(Staking::set_payee(Origin::signed(40), RewardDestination::Controller)); + + // give the man some money + let initial_balance = 1000; + for i in [1, 2, 3, 4, 5, 10, 11, 20, 21].iter() { + let _ = Balances::make_free_balance_be(i, initial_balance); + } + + // bond two account pairs and state interest in nomination. + // 2 will nominate for 10, 20, 30 + assert_ok!(Staking::bond(Origin::signed(1), 2, 1000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21, 31])); + // 4 will nominate for 10, 20, 40 + assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::Controller)); + assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41])); + + // the total reward for era 0 + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(41, 1)]); + >::reward_by_ids(vec![(31, 1)]); + >::reward_by_ids(vec![(21, 10)]); // must be no-op + >::reward_by_ids(vec![(11, 10)]); // must be no-op + + start_era(1); + + // 10 and 20 have more votes, they will be chosen by phragmen. + assert_eq_uvec!(validator_controllers(), vec![20, 10]); + + // OLD validators must have already received some rewards. + assert_eq!(Balances::total_balance(&40), 1 + total_payout_0 / 2); + assert_eq!(Balances::total_balance(&30), 1 + total_payout_0 / 2); + + // ------ check the staked value of all parties. + + if cfg!(feature = "equalize") { + // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(11).own, 1000); + assert_eq_error_rate!(Staking::stakers(11).total, 1000 + 1000, 2); + // 2 and 4 supported 10, each with stake 600, according to phragmen. + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), + vec![600, 400] + ); + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + // total expo of 20, with 500 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(21).own, 1000); + assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1000, 2); + // 2 and 4 supported 20, each with stake 250, according to phragmen. + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), + vec![400, 600] + ); + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + } else { + // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(11).own, 1000); + assert_eq!(Staking::stakers(11).total, 1000 + 800); + // 2 and 4 supported 10, each with stake 600, according to phragmen. + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), + vec![400, 400] + ); + assert_eq!( + Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + // total expo of 20, with 500 coming from nominators (externals), according to phragmen. + assert_eq!(Staking::stakers(21).own, 1000); + assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1200, 2); + // 2 and 4 supported 20, each with stake 250, according to phragmen. + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), + vec![600, 600] + ); + assert_eq!( + Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), + vec![3, 1] + ); + } + + // They are not chosen anymore + assert_eq!(Staking::stakers(31).total, 0); + assert_eq!(Staking::stakers(41).total, 0); + + // the total reward for era 1 + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(41, 10)]); // must be no-op + >::reward_by_ids(vec![(31, 10)]); // must be no-op + >::reward_by_ids(vec![(21, 2)]); + >::reward_by_ids(vec![(11, 1)]); + + start_era(2); + + // nothing else will happen, era ends and rewards are paid again, + // it is expected that nominators will also be paid. See below + + let payout_for_10 = total_payout_1 / 3; + let payout_for_20 = 2 * total_payout_1 / 3; + if cfg!(feature = "equalize") { + // Nominator 2: has [400 / 2000 ~ 1 / 5 from 10] + [600 / 2000 ~ 3 / 10 from 20]'s reward. + assert_eq_error_rate!( + Balances::total_balance(&2), + initial_balance + payout_for_10 / 5 + payout_for_20 * 3 / 10, + 2, + ); + // Nominator 4: has [400 / 2000 ~ 1 / 5 from 20] + [600 / 2000 ~ 3 / 10 from 10]'s reward. + assert_eq_error_rate!( + Balances::total_balance(&4), + initial_balance + payout_for_20 / 5 + payout_for_10 * 3 / 10, + 2, + ); + + // Validator 10: got 1000 / 2000 external stake. + assert_eq_error_rate!( + Balances::total_balance(&10), + initial_balance + payout_for_10 / 2, + 1, + ); + // Validator 20: got 1000 / 2000 external stake. + assert_eq_error_rate!( + Balances::total_balance(&20), + initial_balance + payout_for_20 / 2, + 1, + ); + } else { + // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq_error_rate!( + Balances::total_balance(&2), + initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), + 1, + ); + // Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq_error_rate!( + Balances::total_balance(&4), + initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), + 1, + ); + + // Validator 10: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 + assert_eq_error_rate!( + Balances::total_balance(&10), + initial_balance + 5 * payout_for_10 / 9, + 1, + ); + // Validator 20: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11 + assert_eq_error_rate!( + Balances::total_balance(&20), + initial_balance + 5 * payout_for_20 / 11, + 1, + ); + } + + check_exposure_all(); + check_nominator_all(); + }); } #[test] fn nominators_also_get_slashed() { // A nominator should be slashed if the validator they nominated is slashed - with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + // Here is the breakdown of roles: + // 10 - is the controller of 11 + // 11 - is the stash. + // 2 - is the nominator of 20, 10 + ExtBuilder::default().nominate(false).build().execute_with(|| { assert_eq!(Staking::validator_count(), 2); - // slash happens immediately. - assert_eq!(Staking::offline_slash_grace(), 0); - // Account 10 has not been reported offline - assert_eq!(Staking::slash_count(&10), 0); - OfflineSlash::put(Perbill::from_percent(12)); // Set payee to controller assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); @@ -765,12 +621,12 @@ fn nominators_also_get_slashed() { let _ = Balances::make_free_balance_be(i, initial_balance); } - // 2 will nominate for 10 + // 2 will nominate for 10, 20 let nominator_stake = 500; assert_ok!(Staking::bond(Origin::signed(1), 2, nominator_stake, RewardDestination::default())); assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10])); - let total_payout = current_total_payout_for_duration(3); + let total_payout = current_total_payout_for_duration(3000); assert!(total_payout > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); @@ -781,15 +637,24 @@ fn nominators_also_get_slashed() { assert_eq!(Balances::total_balance(&2), initial_balance); // 10 goes offline - Staking::on_offline_validator(10, 4); - let expo = Staking::stakers(10); - let slash_value = Staking::offline_slash() * expo.total * 2_u64.pow(3); + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(5)], + ); + let expo = Staking::stakers(11); + let slash_value = 50; let total_slash = expo.total.min(slash_value); let validator_slash = expo.own.min(total_slash); let nominator_slash = nominator_stake.min(total_slash - validator_slash); // initial + first era reward + slash - assert_eq!(Balances::total_balance(&10), initial_balance + total_payout - validator_slash); + assert_eq!(Balances::total_balance(&11), initial_balance - validator_slash); assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); check_exposure_all(); check_nominator_all(); @@ -804,47 +669,49 @@ fn double_staking_should_fail() { // * an account already bonded as stash cannot be be stashed again. // * an account already bonded as stash cannot nominate. // * an account already bonded as controller can nominate. - with_externalities(&mut ExtBuilder::default() - .build(), - || { - let arbitrary_value = 5; - // 2 = controller, 1 stashed => ok - assert_ok!( - Staking::bond(Origin::signed(1), 2, arbitrary_value, - RewardDestination::default()) - ); - // 4 = not used so far, 1 stashed => not allowed. - assert_noop!( - Staking::bond(Origin::signed(1), 4, arbitrary_value, - RewardDestination::default()), "stash already bonded" - ); - // 1 = stashed => attempting to nominate should fail. - assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller"); - // 2 = controller => nominating should work. - assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); - }); + ExtBuilder::default().build().execute_with(|| { + let arbitrary_value = 5; + // 2 = controller, 1 stashed => ok + assert_ok!( + Staking::bond(Origin::signed(1), 2, arbitrary_value, + RewardDestination::default()) + ); + // 4 = not used so far, 1 stashed => not allowed. + assert_noop!( + Staking::bond(Origin::signed(1), 4, arbitrary_value, + RewardDestination::default()), "stash already bonded" + ); + // 1 = stashed => attempting to nominate should fail. + assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller"); + // 2 = controller => nominating should work. + assert_ok!(Staking::nominate(Origin::signed(2), vec![1])); + }); } #[test] fn double_controlling_should_fail() { // should test (in the same order): // * an account already bonded as controller CANNOT be reused as the controller of another account. - with_externalities(&mut ExtBuilder::default() - .build(), - || { - let arbitrary_value = 5; - // 2 = controller, 1 stashed => ok - assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default())); - // 2 = controller, 3 stashed (Note that 2 is reused.) => no-op - assert_noop!(Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default()), "controller already paired"); - }); + ExtBuilder::default().build().execute_with(|| { + let arbitrary_value = 5; + // 2 = controller, 1 stashed => ok + assert_ok!(Staking::bond( + Origin::signed(1), + 2, + arbitrary_value, + RewardDestination::default(), + )); + // 2 = controller, 3 stashed (Note that 2 is reused.) => no-op + assert_noop!( + Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default()), + "controller already paired", + ); + }); } #[test] fn session_and_eras_work() { - with_externalities(&mut ExtBuilder::default() - .build(), - || { + ExtBuilder::default().build().execute_with(|| { assert_eq!(Staking::current_era(), 0); // Block 1: No change. @@ -886,7 +753,7 @@ fn session_and_eras_work() { #[test] fn forcing_new_era_works() { - with_externalities(&mut ExtBuilder::default().build(),|| { + ExtBuilder::default().build().execute_with(|| { // normal flow of session. assert_eq!(Staking::current_era(), 0); start_session(0); @@ -907,24 +774,39 @@ fn forcing_new_era_works() { start_session(6); assert_eq!(Staking::current_era(), 1); - // back to normal + // back to normal. + // this immediately starts a new session. ForceEra::put(Forcing::NotForcing); start_session(7); - assert_eq!(Staking::current_era(), 1); + assert_eq!(Staking::current_era(), 2); start_session(8); assert_eq!(Staking::current_era(), 2); // forceful change - ForceEra::put(Forcing::ForceNew); + ForceEra::put(Forcing::ForceAlways); start_session(9); assert_eq!(Staking::current_era(), 3); + start_session(10); + assert_eq!(Staking::current_era(), 4); + start_session(11); + assert_eq!(Staking::current_era(), 5); + + // just one forceful change + ForceEra::put(Forcing::ForceNew); + start_session(12); + assert_eq!(Staking::current_era(), 6); + + assert_eq!(ForceEra::get(), Forcing::NotForcing); + start_session(13); + assert_eq!(Staking::current_era(), 6); + }); } #[test] fn cannot_transfer_staked_balance() { // Tests that a stash account cannot transfer funds - with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + ExtBuilder::default().nominate(false).build().execute_with(|| { // Confirm account 11 is stashed assert_eq!(Staking::bonded(&11), Some(10)); // Confirm account 11 has some free balance @@ -932,7 +814,10 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 (via controller 10) is totally staked assert_eq!(Staking::stakers(&11).total, 1000); // Confirm account 11 cannot transfer as a result - assert_noop!(Balances::transfer(Origin::signed(11), 20, 1), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + Balances::transfer(Origin::signed(11), 20, 1), + "account liquidity restrictions prevent withdrawal", + ); // Give account 11 extra free balance let _ = Balances::make_free_balance_be(&11, 10000); @@ -946,11 +831,7 @@ fn cannot_transfer_staked_balance_2() { // Tests that a stash account cannot transfer funds // Same test as above but with 20, and more accurate. // 21 has 2000 free balance but 1000 at stake - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .fair(true) - .build(), - || { + ExtBuilder::default().nominate(false).fair(true).build().execute_with(|| { // Confirm account 21 is stashed assert_eq!(Staking::bonded(&21), Some(20)); // Confirm account 21 has some free balance @@ -958,7 +839,10 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 (via controller 20) is totally staked assert_eq!(Staking::stakers(&21).total, 1000); // Confirm account 21 can transfer at most 1000 - assert_noop!(Balances::transfer(Origin::signed(21), 20, 1001), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + Balances::transfer(Origin::signed(21), 20, 1001), + "account liquidity restrictions prevent withdrawal", + ); assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); }); } @@ -966,7 +850,7 @@ fn cannot_transfer_staked_balance_2() { #[test] fn cannot_reserve_staked_balance() { // Checks that a bonded account cannot reserve balance from free balance - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { // Confirm account 11 is stashed assert_eq!(Staking::bonded(&11), Some(10)); // Confirm account 11 has some free balance @@ -986,7 +870,7 @@ fn cannot_reserve_staked_balance() { #[test] fn reward_destination_works() { // Rewards go to the correct destination as determined in Payee - with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { + ExtBuilder::default().nominate(false).build().execute_with(|| { // Check that account 11 is a validator assert!(Staking::current_elected().contains(&11)); // Check the balance of the validator account @@ -1002,7 +886,7 @@ fn reward_destination_works() { })); // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3); + let total_payout_0 = current_total_payout_for_duration(3000); assert!(total_payout_0 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); @@ -1024,7 +908,7 @@ fn reward_destination_works() { >::insert(&11, RewardDestination::Stash); // Compute total payout now for whole duration as other parameter won't change - let total_payout_1 = current_total_payout_for_duration(3); + let total_payout_1 = current_total_payout_for_duration(3000); assert!(total_payout_1 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); @@ -1051,7 +935,7 @@ fn reward_destination_works() { assert_eq!(Balances::free_balance(&10), 1); // Compute total payout now for whole duration as other parameter won't change - let total_payout_2 = current_total_payout_for_duration(3); + let total_payout_2 = current_total_payout_for_duration(3000); assert!(total_payout_2 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); @@ -1078,9 +962,7 @@ fn validator_payment_prefs_work() { // Test that validator preferences are correctly honored // Note: unstake threshold is being directly tested in slashing tests. // This test will focus on validator payment. - with_externalities(&mut ExtBuilder::default() - .build(), - || { + ExtBuilder::default().build().execute_with(|| { // Initial config let validator_cut = 5; let stash_initial_balance = Balances::total_balance(&11); @@ -1100,12 +982,11 @@ fn validator_payment_prefs_work() { }); >::insert(&2, RewardDestination::Stash); >::insert(&11, ValidatorPrefs { - unstake_threshold: 3, validator_payment: validator_cut }); // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3); + let total_payout_0 = current_total_payout_for_duration(3000); assert!(total_payout_0 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); @@ -1114,11 +995,11 @@ fn validator_payment_prefs_work() { // whats left to be shared is the sum of 3 rounds minus the validator's cut. let shared_cut = total_payout_0 - validator_cut; // Validator's payee is Staked account, 11, reward will be paid here. - assert_eq!(Balances::total_balance(&11), stash_initial_balance + shared_cut/2 + validator_cut); + assert_eq!(Balances::total_balance(&11), stash_initial_balance + shared_cut / 2 + validator_cut); // Controller account will not get any reward. assert_eq!(Balances::total_balance(&10), 1); // Rest of the reward will be shared and paid to the nominator in stake. - assert_eq!(Balances::total_balance(&2), 500 + shared_cut/2); + assert_eq!(Balances::total_balance(&2), 500 + shared_cut / 2); check_exposure_all(); check_nominator_all(); @@ -1131,8 +1012,7 @@ fn bond_extra_works() { // Tests that extra `free_balance` in the stash can be added to stake // NOTE: this tests only verifies `StakingLedger` for correct updates // See `bond_extra_and_withdraw_unbonded_works` for more details and updates on `Exposure`. - with_externalities(&mut ExtBuilder::default().build(), - || { + ExtBuilder::default().build().execute_with(|| { // Check that account 10 is a validator assert!(>::exists(11)); // Check that account 10 is bonded to account 11 @@ -1177,10 +1057,7 @@ fn bond_extra_and_withdraw_unbonded_works() { // * It can add extra funds to the bonded account. // * it can unbond a portion of its funds from the stash account. // * Once the unbonding period is done, it can actually take the funds out of the stash. - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { + ExtBuilder::default().nominate(false).build().execute_with(|| { // Set payee to controller. avoids confusion assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); @@ -1264,7 +1141,7 @@ fn bond_extra_and_withdraw_unbonded_works() { #[test] fn too_many_unbond_calls_should_not_work() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { // locked at era 0 until 3 for _ in 0..MAX_UNLOCKING_CHUNKS-1 { assert_ok!(Staking::unbond(Origin::signed(10), 1)); @@ -1293,11 +1170,7 @@ fn too_many_unbond_calls_should_not_work() { fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment() { // Test that slot_stake is determined by the least staked validator // Test that slot_stake is the maximum punishment that can happen to a validator - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .fair(false) - .build(), - || { + ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { // Confirm validator count is 2 assert_eq!(Staking::validator_count(), 2); // Confirm account 10 and 20 are validators @@ -1319,7 +1192,7 @@ fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment( >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![] }); // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3); + let total_payout_0 = current_total_payout_for_duration(3000); assert!(total_payout_0 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); >::reward_by_ids(vec![(21, 1)]); @@ -1328,21 +1201,14 @@ fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment( start_era(1); // -- new balances + reward - assert_eq!(Staking::stakers(&11).total, 1000 + total_payout_0/2); - assert_eq!(Staking::stakers(&21).total, 69 + total_payout_0/2); + assert_eq!(Staking::stakers(&11).total, 1000 + total_payout_0 / 2); + assert_eq!(Staking::stakers(&21).total, 69 + total_payout_0 / 2); let _11_balance = Balances::free_balance(&11); - assert_eq!(_11_balance, 1000 + total_payout_0/2); + assert_eq!(_11_balance, 1000 + total_payout_0 / 2); // -- slot stake should also be updated. - assert_eq!(Staking::slot_stake(), 69 + total_payout_0/2); - - // If 10 gets slashed now, it will be slashed by 5% of exposure.total * 2.pow(unstake_thresh) - Staking::on_offline_validator(10, 4); - // Confirm user has been reported - assert_eq!(Staking::slash_count(&11), 4); - // check the balance of 10 (slash will be deducted from free balance.) - assert_eq!(Balances::free_balance(&11), _11_balance - _11_balance*5/100 * 2u64.pow(3)); + assert_eq!(Staking::slot_stake(), 69 + total_payout_0 / 2); check_exposure_all(); check_nominator_all(); @@ -1353,10 +1219,7 @@ fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment( fn on_free_balance_zero_stash_removes_validator() { // Tests that validator storage items are cleaned up when stash is empty // Tests that storage items are untouched when controller is empty - with_externalities(&mut ExtBuilder::default() - .existential_deposit(10) - .build(), - || { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { // Check the balance of the validator account assert_eq!(Balances::free_balance(&10), 256); // Check the balance of the stash account @@ -1365,8 +1228,6 @@ fn on_free_balance_zero_stash_removes_validator() { assert_eq!(Staking::bonded(&11), Some(10)); // Set some storage items which we expect to be cleaned up - // Initiate slash count storage item - Staking::on_offline_validator(10, 1); // Set payee information assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash)); @@ -1374,7 +1235,6 @@ fn on_free_balance_zero_stash_removes_validator() { assert!(>::exists(&10)); assert!(>::exists(&11)); assert!(>::exists(&11)); - assert!(>::exists(&11)); assert!(>::exists(&11)); // Reduce free_balance of controller to 0 @@ -1389,7 +1249,6 @@ fn on_free_balance_zero_stash_removes_validator() { assert!(>::exists(&10)); assert!(>::exists(&11)); assert!(>::exists(&11)); - assert!(>::exists(&11)); assert!(>::exists(&11)); // Reduce free_balance of stash to 0 @@ -1402,7 +1261,6 @@ fn on_free_balance_zero_stash_removes_validator() { assert!(!>::exists(&11)); assert!(!>::exists(&11)); assert!(!>::exists(&11)); - assert!(!>::exists(&11)); assert!(!>::exists(&11)); }); } @@ -1411,10 +1269,7 @@ fn on_free_balance_zero_stash_removes_validator() { fn on_free_balance_zero_stash_removes_nominator() { // Tests that nominator storage items are cleaned up when stash is empty // Tests that storage items are untouched when controller is empty - with_externalities(&mut ExtBuilder::default() - .existential_deposit(10) - .build(), - || { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { // Make 10 a nominator assert_ok!(Staking::nominate(Origin::signed(10), vec![20])); // Check that account 10 is a nominator @@ -1459,201 +1314,15 @@ fn on_free_balance_zero_stash_removes_nominator() { assert!(!>::exists(&11)); assert!(!>::exists(&11)); assert!(!>::exists(&11)); - assert!(!>::exists(&11)); assert!(!>::exists(&11)); }); } -#[test] -fn phragmen_poc_works() { - // Tests the POC test of the phragmen, mentioned in the paper and reference implementation. - // Initial votes: - // Votes [ - // ('2', 500, ['10', '20', '30']), - // ('4', 500, ['10', '20', '40']), - // ('10', 1000, ['10']), - // ('20', 1000, ['20']), - // ('30', 1000, ['30']), - // ('40', 1000, ['40'])] - // - // Sequential Phragmén gives - // 10 is elected with stake 1666.6666666666665 and score 0.0005 - // 20 is elected with stake 1333.3333333333333 and score 0.00075 - - // 2 has load 0.00075 and supported - // 10 with stake 333.3333333333333 20 with stake 166.66666666666666 30 with stake 0.0 - // 4 has load 0.00075 and supported - // 10 with stake 333.3333333333333 20 with stake 166.66666666666666 40 with stake 0.0 - // 10 has load 0.0005 and supported - // 10 with stake 1000.0 - // 20 has load 0.00075 and supported - // 20 with stake 1000.0 - // 30 has load 0 and supported - // 30 with stake 0 - // 40 has load 0 and supported - // 40 with stake 0 - - // Sequential Phragmén with post processing gives - // 10 is elected with stake 1500.0 and score 0.0005 - // 20 is elected with stake 1500.0 and score 0.00075 - // - // 10 has load 0.0005 and supported - // 10 with stake 1000.0 - // 20 has load 0.00075 and supported - // 20 with stake 1000.0 - // 30 has load 0 and supported - // 30 with stake 0 - // 40 has load 0 and supported - // 40 with stake 0 - // 2 has load 0.00075 and supported - // 10 with stake 166.66666666666674 20 with stake 333.33333333333326 30 with stake 0 - // 4 has load 0.00075 and supported - // 10 with stake 333.3333333333333 20 with stake 166.66666666666666 40 with stake 0.0 - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .validator_pool(true) - .build(), - || { - // We don't really care about this. At this point everything is even. - assert_eq_uvec!(validator_controllers(), vec![40, 30]); - - // Set payees to Controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(20), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(30), RewardDestination::Controller)); - assert_ok!(Staking::set_payee(Origin::signed(40), RewardDestination::Controller)); - - // no one is a nominator - assert_eq!(>::enumerate().count(), 0 as usize); - - // bond [2,1] / [4,3] a nominator - let _ = Balances::deposit_creating(&1, 1000); - let _ = Balances::deposit_creating(&3, 1000); - - assert_ok!(Staking::bond(Origin::signed(1), 2, 500, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21, 31])); - - assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41])); - - // New era => election algorithm will trigger - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - assert_eq!(Staking::stakers(11).own, 1000); - assert_eq!(Staking::stakers(21).own, 1000); - - if cfg!(feature = "equalize") { - assert_eq!(Staking::stakers(11).total, 1000 + 499); - assert_eq!(Staking::stakers(21).total, 1000 + 499); - } else { - assert_eq!(Staking::stakers(11).total, 1000 + 332); - assert_eq!(Staking::stakers(21).total, 1000 + 666); - } - - // Nominator's stake distribution. - assert_eq!(Staking::stakers(11).others.iter().map(|e| e.who).collect::>>(), vec![3, 1]); - assert_eq!(Staking::stakers(21).others.iter().map(|e| e.who).collect::>>(), vec![3, 1]); - - if cfg!(feature = "equalize") { - assert_eq_uvec!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![333, 166] - ); - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).sum::>(), - 499 - ); - assert_eq_uvec!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![333, 166] - ); - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).sum::>(), - 499 - ); - } else { - assert_eq_uvec!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![166, 166] - ); - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).sum::>(), - 332 - ); - assert_eq_uvec!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![333, 333] - ); - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).sum::>(), - 666 - ); - } - check_exposure_all(); - check_nominator_all(); - }); -} - -#[test] -fn phragmen_poc_2_works() { - // tests the encapsulated phragmen::elect function. - // Votes [ - // ('10', 1000, ['10']), - // ('20', 1000, ['20']), - // ('30', 1000, ['30']), - // ('2', 50, ['10', '20']), - // ('4', 1000, ['10', '30']) - // ] - // Sequential Phragmén gives - // 10 is elected with stake 1705.7377049180327 and score 0.0004878048780487805 - // 30 is elected with stake 1344.2622950819673 and score 0.0007439024390243903 - with_externalities(&mut ExtBuilder::default().nominate(false).build(), || { - // initial setup of 10 and 20, both validators - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // Bond [30, 31] as the third validator - assert_ok!(Staking::bond_extra(Origin::signed(31), 999)); - assert_ok!(Staking::validate(Origin::signed(30), ValidatorPrefs::default())); - - // bond [2,1](A), [4,3](B), as 2 nominators - for i in &[1, 3] { let _ = Balances::deposit_creating(i, 2000); } - - assert_ok!(Staking::bond(Origin::signed(1), 2, 50, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(2), vec![11, 21])); - - assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::default())); - assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 31])); - - let winners = phragmen::elect::( - 2, - Staking::minimum_validator_count() as usize, - >::enumerate(), - >::enumerate(), - Staking::slashable_balance_of, - ); - - let (winners, assignment) = winners.unwrap(); - - // 10 and 30 must be the winners - assert_eq!(winners, vec![11, 31]); - assert_eq!(assignment, vec![ - (3, vec![(11, 2816371998), (31, 1478595298)]), - (1, vec![(11, 4294967296)]), - ]); - check_exposure_all(); - check_nominator_all(); - }) -} #[test] fn switching_roles() { // Test that it should be possible to switch between roles (nominator, validator, idle) with minimal overhead. - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { + ExtBuilder::default().nominate(false).build().execute_with(|| { Timestamp::set_timestamp(1); // Initialize time. // Reset reward destination @@ -1719,11 +1388,7 @@ fn switching_roles() { #[test] fn wrong_vote_is_null() { - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .validator_pool(true) - .build(), - || { + ExtBuilder::default().nominate(false).validator_pool(true).build().execute_with(|| { assert_eq_uvec!(validator_controllers(), vec![40, 30]); // put some money in account that we'll use. @@ -1747,202 +1412,181 @@ fn wrong_vote_is_null() { fn bond_with_no_staked_value() { // Behavior when someone bonds with no staked value. // Particularly when she votes and the candidate is elected. - with_externalities(&mut ExtBuilder::default() - .validator_count(3) - .existential_deposit(5) - .nominate(false) - .minimum_validator_count(1) - .build(), || { - // Can't bond with 1 - assert_noop!( - Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller), - "can not bond with value less than minimum balance" - ); - // bonded with absolute minimum value possible. - assert_ok!(Staking::bond(Origin::signed(1), 2, 5, RewardDestination::Controller)); - assert_eq!(Balances::locks(&1)[0].amount, 5); + ExtBuilder::default() + .validator_count(3) + .existential_deposit(5) + .nominate(false) + .minimum_validator_count(1) + .build() + .execute_with(|| { + // Can't bond with 1 + assert_noop!( + Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller), + "can not bond with value less than minimum balance", + ); + // bonded with absolute minimum value possible. + assert_ok!(Staking::bond(Origin::signed(1), 2, 5, RewardDestination::Controller)); + assert_eq!(Balances::locks(&1)[0].amount, 5); - // unbonding even 1 will cause all to be unbonded. - assert_ok!(Staking::unbond(Origin::signed(2), 1)); - assert_eq!( - Staking::ledger(2), - Some(StakingLedger { - stash: 1, - active: 0, - total: 5, - unlocking: vec![UnlockChunk {value: 5, era: 3}] - }) - ); + // unbonding even 1 will cause all to be unbonded. + assert_ok!(Staking::unbond(Origin::signed(2), 1)); + assert_eq!( + Staking::ledger(2), + Some(StakingLedger { + stash: 1, + active: 0, + total: 5, + unlocking: vec![UnlockChunk {value: 5, era: 3}] + }) + ); - start_era(1); - start_era(2); + start_era(1); + start_era(2); - // not yet removed. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); - assert!(Staking::ledger(2).is_some()); - assert_eq!(Balances::locks(&1)[0].amount, 5); + // not yet removed. + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert!(Staking::ledger(2).is_some()); + assert_eq!(Balances::locks(&1)[0].amount, 5); - start_era(3); + start_era(3); - // poof. Account 1 is removed from the staking system. - assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); - assert!(Staking::ledger(2).is_none()); - assert_eq!(Balances::locks(&1).len(), 0); - }); + // poof. Account 1 is removed from the staking system. + assert_ok!(Staking::withdraw_unbonded(Origin::signed(2))); + assert!(Staking::ledger(2).is_none()); + assert_eq!(Balances::locks(&1).len(), 0); + }); } #[test] fn bond_with_little_staked_value_bounded_by_slot_stake() { // Behavior when someone bonds with little staked value. // Particularly when she votes and the candidate is elected. - with_externalities(&mut ExtBuilder::default() + ExtBuilder::default() .validator_count(3) .nominate(false) .minimum_validator_count(1) - .build(), - || { - - // setup - assert_ok!(Staking::chill(Origin::signed(30))); - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - let init_balance_2 = Balances::free_balance(&2); - let init_balance_10 = Balances::free_balance(&10); - - // Stingy validator. - assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); - assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); - - let total_payout_0 = current_total_payout_for_duration(3); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - reward_all_elected(); - start_era(1); - - // 2 is elected. - // and fucks up the slot stake. - assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::slot_stake(), 1); - - // Old ones are rewarded. - assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0/3); - // no rewards paid to 2. This was initial election. - assert_eq!(Balances::free_balance(&2), init_balance_2); - - let total_payout_1 = current_total_payout_for_duration(3); - assert!(total_payout_1 > 100); // Test is meaningfull if reward something - reward_all_elected(); - start_era(2); - - assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::slot_stake(), 1); - - assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1/3); - assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0/3 + total_payout_1/3); - check_exposure_all(); - check_nominator_all(); - }); + .build() + .execute_with(|| { + // setup + assert_ok!(Staking::chill(Origin::signed(30))); + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + let init_balance_2 = Balances::free_balance(&2); + let init_balance_10 = Balances::free_balance(&10); + + // Stingy validator. + assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + reward_all_elected(); + start_era(1); + + // 2 is elected. + // and fucks up the slot stake. + assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); + assert_eq!(Staking::slot_stake(), 1); + + // Old ones are rewarded. + assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3); + // no rewards paid to 2. This was initial election. + assert_eq!(Balances::free_balance(&2), init_balance_2); + + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something + reward_all_elected(); + start_era(2); + + assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); + assert_eq!(Staking::slot_stake(), 1); + + assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1 / 3); + assert_eq!( + Balances::free_balance(&10), + init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, + ); + check_exposure_all(); + check_nominator_all(); + }); } #[cfg(feature = "equalize")] #[test] fn phragmen_linear_worse_case_equalize() { - with_externalities(&mut ExtBuilder::default() + ExtBuilder::default() .nominate(false) .validator_pool(true) .fair(true) - .build(), - || { - - bond_validator(50, 1000); - bond_validator(60, 1000); - bond_validator(70, 1000); - - bond_nominator(2, 2000, vec![11]); - bond_nominator(4, 1000, vec![11, 21]); - bond_nominator(6, 1000, vec![21, 31]); - bond_nominator(8, 1000, vec![31, 41]); - bond_nominator(110, 1000, vec![41, 51]); - bond_nominator(120, 1000, vec![51, 61]); - bond_nominator(130, 1000, vec![61, 71]); - - for i in &[10, 20, 30, 40, 50, 60, 70] { - assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); - } - - assert_eq_uvec!(validator_controllers(), vec![40, 30]); - assert_ok!(Staking::set_validator_count(Origin::ROOT, 7)); - - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![10, 60, 40, 20, 50, 30, 70]); - - assert_eq!(Staking::stakers(11).total, 3000); - assert_eq!(Staking::stakers(21).total, 2254); - assert_eq!(Staking::stakers(31).total, 2254); - assert_eq!(Staking::stakers(41).total, 1926); - assert_eq!(Staking::stakers(51).total, 1871); - assert_eq!(Staking::stakers(61).total, 1892); - assert_eq!(Staking::stakers(71).total, 1799); - - check_exposure_all(); - check_nominator_all(); - }) + .build() + .execute_with(|| { + bond_validator(50, 1000); + bond_validator(60, 1000); + bond_validator(70, 1000); + + bond_nominator(2, 2000, vec![11]); + bond_nominator(4, 1000, vec![11, 21]); + bond_nominator(6, 1000, vec![21, 31]); + bond_nominator(8, 1000, vec![31, 41]); + bond_nominator(110, 1000, vec![41, 51]); + bond_nominator(120, 1000, vec![51, 61]); + bond_nominator(130, 1000, vec![61, 71]); + + for i in &[10, 20, 30, 40, 50, 60, 70] { + assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); + } + + assert_eq_uvec!(validator_controllers(), vec![40, 30]); + assert_ok!(Staking::set_validator_count(Origin::ROOT, 7)); + + start_era(1); + + assert_eq_uvec!(validator_controllers(), vec![10, 60, 40, 20, 50, 30, 70]); + + assert_eq_error_rate!(Staking::stakers(11).total, 3000, 2); + assert_eq_error_rate!(Staking::stakers(21).total, 2255, 2); + assert_eq_error_rate!(Staking::stakers(31).total, 2255, 2); + assert_eq_error_rate!(Staking::stakers(41).total, 1925, 2); + assert_eq_error_rate!(Staking::stakers(51).total, 1870, 2); + assert_eq_error_rate!(Staking::stakers(61).total, 1890, 2); + assert_eq_error_rate!(Staking::stakers(71).total, 1800, 2); + + check_exposure_all(); + check_nominator_all(); + }) } #[test] -fn phragmen_chooses_correct_number_of_validators() { - with_externalities(&mut ExtBuilder::default() +fn new_era_elects_correct_number_of_validators() { + ExtBuilder::default() .nominate(true) .validator_pool(true) .fair(true) .validator_count(1) - .build(), - || { - assert_eq!(Staking::validator_count(), 1); - assert_eq!(validator_controllers().len(), 1); - - System::set_block_number(1); - Session::on_initialize(System::block_number()); - - assert_eq!(validator_controllers().len(), 1); - check_exposure_all(); - check_nominator_all(); - }) -} - - -#[test] -fn phragmen_score_should_be_accurate_on_large_stakes() { - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { - bond_validator(2, u64::max_value()); - bond_validator(4, u64::max_value()); - bond_validator(6, u64::max_value()-1); - bond_validator(8, u64::max_value()-2); - - start_era(1); - - assert_eq!(validator_controllers(), vec![4, 2]); - check_exposure_all(); - check_nominator_all(); - }) + .build() + .execute_with(|| { + assert_eq!(Staking::validator_count(), 1); + assert_eq!(validator_controllers().len(), 1); + + System::set_block_number(1); + Session::on_initialize(System::block_number()); + + assert_eq!(validator_controllers().len(), 1); + check_exposure_all(); + check_nominator_all(); + }) } #[test] fn phragmen_should_not_overflow_validators() { - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { + ExtBuilder::default().nominate(false).build().execute_with(|| { let _ = Staking::chill(Origin::signed(10)); let _ = Staking::chill(Origin::signed(20)); bond_validator(2, u64::max_value()); bond_validator(4, u64::max_value()); - bond_nominator(6, u64::max_value()/2, vec![3, 5]); - bond_nominator(8, u64::max_value()/2, vec![3, 5]); + bond_nominator(6, u64::max_value() / 2, vec![3, 5]); + bond_nominator(8, u64::max_value() / 2, vec![3, 5]); start_era(1); @@ -1957,15 +1601,12 @@ fn phragmen_should_not_overflow_validators() { #[test] fn phragmen_should_not_overflow_nominators() { - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { + ExtBuilder::default().nominate(false).build().execute_with(|| { let _ = Staking::chill(Origin::signed(10)); let _ = Staking::chill(Origin::signed(20)); - bond_validator(2, u64::max_value()/2); - bond_validator(4, u64::max_value()/2); + bond_validator(2, u64::max_value() / 2); + bond_validator(4, u64::max_value() / 2); bond_nominator(6, u64::max_value(), vec![3, 5]); bond_nominator(8, u64::max_value(), vec![3, 5]); @@ -1982,10 +1623,7 @@ fn phragmen_should_not_overflow_nominators() { #[test] fn phragmen_should_not_overflow_ultimate() { - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .build(), - || { + ExtBuilder::default().nominate(false).build().execute_with(|| { bond_validator(2, u64::max_value()); bond_validator(4, u64::max_value()); @@ -2002,89 +1640,9 @@ fn phragmen_should_not_overflow_ultimate() { }) } - -#[test] -fn phragmen_large_scale_test() { - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .minimum_validator_count(1) - .validator_count(20) - .build(), - || { - let _ = Staking::chill(Origin::signed(10)); - let _ = Staking::chill(Origin::signed(20)); - let _ = Staking::chill(Origin::signed(30)); - let prefix = 200; - - bond_validator(prefix + 2, 1); - bond_validator(prefix + 4, 100); - bond_validator(prefix + 6, 1000000); - bond_validator(prefix + 8, 100000000001000); - bond_validator(prefix + 10, 100000000002000); - bond_validator(prefix + 12, 100000000003000); - bond_validator(prefix + 14, 400000000000000); - bond_validator(prefix + 16, 400000000001000); - bond_validator(prefix + 18, 18000000000000000); - bond_validator(prefix + 20, 20000000000000000); - bond_validator(prefix + 22, 500000000000100000); - bond_validator(prefix + 24, 500000000000200000); - - bond_nominator(50, 990000000000000000, vec![ - prefix + 3, - prefix + 5, - prefix + 7, - prefix + 9, - prefix + 11, - prefix + 13, - prefix + 15, - prefix + 17, - prefix + 19, - prefix + 21, - prefix + 23, - prefix + 25] - ); - - start_era(1); - - check_exposure_all(); - check_nominator_all(); - }) -} - -#[test] -fn phragmen_large_scale_test_2() { - with_externalities(&mut ExtBuilder::default() - .nominate(false) - .minimum_validator_count(1) - .validator_count(2) - .build(), - || { - let _ = Staking::chill(Origin::signed(10)); - let _ = Staking::chill(Origin::signed(20)); - let nom_budget: u64 = 1_000_000_000_000_000_000; - let c_budget: u64 = 4_000_000; - - bond_validator(2, c_budget as u64); - bond_validator(4, c_budget as u64); - - bond_nominator(50, nom_budget, vec![3, 5]); - - start_era(1); - - // Each exposure => total == own + sum(others) - check_exposure_all(); - check_nominator_all(); - - assert_total_expo(3, nom_budget / 2 + c_budget); - assert_total_expo(5, nom_budget / 2 + c_budget); - }) -} - #[test] fn reward_validator_slashing_validator_doesnt_overflow() { - with_externalities(&mut ExtBuilder::default() - .build(), - || { + ExtBuilder::default().build().execute_with(|| { let stake = u32::max_value() as u64 * 2; let reward_slash = u32::max_value() as u64 * 2; @@ -2107,7 +1665,7 @@ fn reward_validator_slashing_validator_doesnt_overflow() { ]}); // Check slashing - Staking::slash_validator(&11, reward_slash); + let _ = Staking::slash_validator(&11, reward_slash, &Staking::stakers(&11), &mut Vec::new()); assert_eq!(Balances::total_balance(&11), stake - 1); assert_eq!(Balances::total_balance(&2), 1); }) @@ -2115,9 +1673,7 @@ fn reward_validator_slashing_validator_doesnt_overflow() { #[test] fn reward_from_authorship_event_handler_works() { - with_externalities(&mut ExtBuilder::default() - .build(), - || { + ExtBuilder::default().build().execute_with(|| { use authorship::EventHandler; assert_eq!(>::author(), 11); @@ -2134,17 +1690,15 @@ fn reward_from_authorship_event_handler_works() { assert_eq!(>::get(), vec![21, 11]); // 21 is rewarded as an uncle producer - // 11 is rewarded as a block procuder and uncle referencer and uncle producer - assert_eq!(CurrentEraRewards::get().rewards, vec![1, 20+2*3 + 1]); - assert_eq!(CurrentEraRewards::get().total, 28); + // 11 is rewarded as a block producer and uncle referencer and uncle producer + assert_eq!(CurrentEraPointsEarned::get().individual, vec![1, 20 + 2 * 3 + 1]); + assert_eq!(CurrentEraPointsEarned::get().total, 28); }) } #[test] fn add_reward_points_fns_works() { - with_externalities(&mut ExtBuilder::default() - .build(), - || { + ExtBuilder::default().build().execute_with(|| { let validators = >::current_elected(); // Not mandatory but must be coherent with rewards assert_eq!(validators, vec![21, 11]); @@ -2163,14 +1717,14 @@ fn add_reward_points_fns_works() { (11, 1), ]); - assert_eq!(CurrentEraRewards::get().rewards, vec![2, 4]); - assert_eq!(CurrentEraRewards::get().total, 6); + assert_eq!(CurrentEraPointsEarned::get().individual, vec![2, 4]); + assert_eq!(CurrentEraPointsEarned::get().total, 6); }) } #[test] fn unbonded_balance_is_not_slashable() { - with_externalities(&mut ExtBuilder::default().build(), || { + ExtBuilder::default().build().execute_with(|| { // total amount staked is slashable. assert_eq!(Staking::slashable_balance_of(&11), 1000); @@ -2180,3 +1734,197 @@ fn unbonded_balance_is_not_slashable() { assert_eq!(Staking::slashable_balance_of(&11), 200); }) } + +#[test] +fn era_is_always_same_length() { + // This ensures that the sessions is always of the same length if there is no forcing no + // session changes. + ExtBuilder::default().build().execute_with(|| { + start_era(1); + assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get()); + + start_era(2); + assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get() * 2); + + let session = Session::current_index(); + ForceEra::put(Forcing::ForceNew); + advance_session(); + assert_eq!(Staking::current_era(), 3); + assert_eq!(Staking::current_era_start_session_index(), session + 1); + + start_era(4); + assert_eq!(Staking::current_era_start_session_index(), session + SessionsPerEra::get() + 1); + }); +} + +#[test] +fn offence_forces_new_era() { + ExtBuilder::default().build().execute_with(|| { + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(5)], + ); + + assert_eq!(Staking::force_era(), Forcing::ForceNew); + }); +} + +#[test] +fn offence_ensures_new_era_without_clobbering() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Staking::force_new_era_always(Origin::ROOT)); + + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(5)], + ); + + assert_eq!(Staking::force_era(), Forcing::ForceAlways); + }); +} + +#[test] +fn offence_deselects_validator_when_slash_is_zero() { + ExtBuilder::default().build().execute_with(|| { + assert!(>::exists(11)); + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(0)], + ); + assert_eq!(Staking::force_era(), Forcing::ForceNew); + assert!(!>::exists(11)); + }); +} + +#[test] +fn slashing_performed_according_exposure() { + // This test checks that slashing is performed according the exposure (or more precisely, + // historical exposure), not the current balance. + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Staking::stakers(&11).own, 1000); + + // Handle an offence with a historical exposure. + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Exposure { + total: 500, + own: 500, + others: vec![], + }, + ), + reporters: vec![], + }], + &[Perbill::from_percent(50)], + ); + + // The stash account should be slashed for 250 (50% of 500). + assert_eq!(Balances::free_balance(&11), 1000 - 250); + }); +} + +#[test] +fn reporters_receive_their_slice() { + // This test verifies that the reporters of the offence receive their slice from the slashed + // amount. + ExtBuilder::default().build().execute_with(|| { + // The reporters' reward is calculated from the total exposure. + #[cfg(feature = "equalize")] + let initial_balance = 1250; + #[cfg(not(feature = "equalize"))] + let initial_balance = 1125; + + assert_eq!(Staking::stakers(&11).total, initial_balance); + + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![1, 2], + }], + &[Perbill::from_percent(50)], + ); + + // initial_balance x 50% (slash fraction) x 10% (rewards slice) + let reward = initial_balance / 20 / 2; + assert_eq!(Balances::free_balance(&1), 10 + reward); + assert_eq!(Balances::free_balance(&2), 20 + reward); + }); +} + +#[test] +fn invulnerables_are_not_slashed() { + // For invulnerable validators no slashing is performed. + ExtBuilder::default().invulnerables(vec![11]).build().execute_with(|| { + #[cfg(feature = "equalize")] + let initial_balance = 1250; + #[cfg(not(feature = "equalize"))] + let initial_balance = 1375; + + assert_eq!(Balances::free_balance(&11), 1000); + assert_eq!(Balances::free_balance(&21), 2000); + assert_eq!(Staking::stakers(&21).total, initial_balance); + + Staking::on_offence( + &[ + OffenceDetails { + offender: (11, Staking::stakers(&11)), + reporters: vec![], + }, + OffenceDetails { + offender: (21, Staking::stakers(&21)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(50), Perbill::from_percent(20)], + ); + + // The validator 11 hasn't been slashed, but 21 has been. + assert_eq!(Balances::free_balance(&11), 1000); + // 2000 - (0.2 * initial_balance) + assert_eq!(Balances::free_balance(&21), 2000 - (2 * initial_balance / 10)); + }); +} + +#[test] +fn dont_slash_if_fraction_is_zero() { + // Don't slash if the fraction is zero. + ExtBuilder::default().build().execute_with(|| { + assert_eq!(Balances::free_balance(&11), 1000); + + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(0)], + ); + + // The validator hasn't been slashed. The new era is not forced. + assert_eq!(Balances::free_balance(&11), 1000); + }); +} diff --git a/srml/sudo/Cargo.toml b/srml/sudo/Cargo.toml index d0e2d5dbc55e494afbdb5a99b495622b613ad775..152f32ab89363364e41483dbb3cd99c85021dff9 100644 --- a/srml/sudo/Cargo.toml +++ b/srml/sudo/Cargo.toml @@ -5,17 +5,15 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sr-std = { path = "../../core/sr-std", default-features = false } -sr-io = { path = "../../core/sr-io", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } -srml-support-procedural = { path = "../support/procedural" } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } [dev-dependencies] -sr-io = { path = "../../core/sr-io", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives" } [features] @@ -23,9 +21,9 @@ default = ["std"] std = [ "serde", "codec/std", - "sr-std/std", - "sr-io/std", + "rstd/std", + "runtime-io/std", "sr-primitives/std", - "srml-support/std", + "support/std", "system/std", ] diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index 65a15b4abfb0342f76999fe5c9b5c43fbdfcdcfb..7801384abcc2fe7b3f3e7e4fb2102e3d6a41221e 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -51,7 +51,7 @@ //! This is an example of a module that exposes a privileged function: //! //! ``` -//! use srml_support::{decl_module, dispatch::Result}; +//! use support::{decl_module, dispatch::Result}; //! use system::ensure_root; //! //! pub trait Trait: system::Trait {} @@ -86,13 +86,11 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sr_std::prelude::*; -use sr_primitives::traits::StaticLookup; -use sr_primitives::weights::SimpleDispatchInfo; -use srml_support::{ - StorageValue, Parameter, Dispatchable, decl_module, decl_event, - decl_storage, ensure +use rstd::prelude::*; +use sr_primitives::{ + traits::{StaticLookup, Dispatchable}, weights::SimpleDispatchInfo, DispatchError, }; +use support::{Parameter, decl_module, decl_event, decl_storage, ensure}; use system::ensure_signed; pub trait Trait: system::Trait { @@ -106,7 +104,7 @@ pub trait Trait: system::Trait { decl_module! { // Simple declaration of the `Module` type. Lets the macro know what it's working on. pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; + fn deposit_event() = default; /// Authenticates the sudo key and dispatches a function call with `Root` origin. /// @@ -115,9 +113,10 @@ decl_module! { /// # /// - O(1). /// - Limited storage reads. - /// - No DB writes. + /// - One DB write (event). + /// - Unknown weight of derivative `proposal` execution. /// # - #[weight = SimpleDispatchInfo::FixedOperational(1_000_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn sudo(origin, proposal: Box) { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; @@ -126,7 +125,8 @@ decl_module! { let res = match proposal.dispatch(system::RawOrigin::Root.into()) { Ok(_) => true, Err(e) => { - sr_io::print(e); + let e: DispatchError = e.into(); + sr_primitives::print(e); false } }; @@ -152,6 +152,37 @@ decl_module! { Self::deposit_event(RawEvent::KeyChanged(Self::key())); >::put(new); } + + /// Authenticates the sudo key and dispatches a function call with `Signed` origin from + /// a given account. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB write (event). + /// - Unknown weight of derivative `proposal` execution. + /// # + #[weight = SimpleDispatchInfo::FixedOperational(0)] + fn sudo_as(origin, who: ::Source, proposal: Box) { + // This is a public call, so we ensure that the origin is some signed account. + let sender = ensure_signed(origin)?; + ensure!(sender == Self::key(), "only the current sudo key can sudo"); + + let who = T::Lookup::lookup(who)?; + + let res = match proposal.dispatch(system::RawOrigin::Signed(who).into()) { + Ok(_) => true, + Err(e) => { + let e: DispatchError = e.into(); + sr_primitives::print(e); + false + } + }; + + Self::deposit_event(RawEvent::SudoAsDone(res)); + } } } @@ -161,12 +192,14 @@ decl_event!( Sudid(bool), /// The sudoer just switched identity; the old key is supplied. KeyChanged(AccountId), + /// A sudo just took place. + SudoAsDone(bool), } ); decl_storage! { trait Store for Module as Sudo { /// The `AccountId` of the sudo key. - Key get(key) config(): T::AccountId; + Key get(fn key) config(): T::AccountId; } } diff --git a/srml/support/Cargo.toml b/srml/support/Cargo.toml index 2befc11b19538def8b23f695cdea80925c50ae0e..46ebebc7d3bf4190f7fed44959d471eda745fe26 100644 --- a/srml/support/Cargo.toml +++ b/srml/support/Cargo.toml @@ -5,18 +5,20 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +log = "0.4" +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } srml-metadata = { path = "../metadata", default-features = false } -sr-std = { path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -srml-support-procedural = { path = "./procedural" } -paste = "0.1" -once_cell = { version = "0.1.6", default-features = false, optional = true } -bitmask = { version = "0.5", default-features = false } +srml-support-procedural = { package = "srml-support-procedural", path = "./procedural" } +paste = "0.1.6" +once_cell = { version = "0.2.4", default-features = false, optional = true } +bitmask = { version = "0.5.0", default-features = false } +impl-trait-for-tuples = "0.1.3" [dev-dependencies] pretty_assertions = "0.6.1" @@ -28,9 +30,9 @@ std = [ "once_cell", "bitmask/std", "serde", - "runtime_io/std", + "runtime-io/std", "codec/std", - "sr-std/std", + "rstd/std", "sr-primitives/std", "srml-metadata/std", "inherents/std", diff --git a/srml/support/procedural/Cargo.toml b/srml/support/procedural/Cargo.toml index fba706c17e890bccf203cc8171b0e904cd529cfe..b891e7b46ff7f14dd69f7bc3b1013aaf320fac7f 100644 --- a/srml/support/procedural/Cargo.toml +++ b/srml/support/procedural/Cargo.toml @@ -8,9 +8,9 @@ edition = "2018" proc-macro = true [dependencies] -srml-support-procedural-tools = { path = "./tools" } +srml-support-procedural-tools = { package = "srml-support-procedural-tools", path = "./tools" } sr-api-macros = { path = "../../../core/sr-api-macros" } -proc-macro2 = "0.4.27" -quote = { version = "0.6.12" } -syn = { version = "0.15.32", features = ["full"] } +proc-macro2 = "1.0.6" +quote = "1.0.2" +syn = { version = "1.0.7", features = ["full"] } diff --git a/srml/support/procedural/src/lib.rs b/srml/support/procedural/src/lib.rs index 78051ee8f2735e4fe72b8482bf9dfcdf139bbd42..792f739f1c35761c6bc370fd0cfb112f5e403a3a 100644 --- a/srml/support/procedural/src/lib.rs +++ b/srml/support/procedural/src/lib.rs @@ -33,7 +33,7 @@ use proc_macro::TokenStream; /// ```nocompile /// decl_storage! { /// trait Store for Module as Example { -/// Foo get(foo) config(): u32=12; +/// Foo get(fn foo) config(): u32=12; /// Bar: map u32 => u32; /// pub Zed build(|config| vec![(0, 0)]): linked_map u32 => u32; /// } @@ -44,38 +44,60 @@ use proc_macro::TokenStream; /// with `Store` a (pub) trait generated associating each storage item to the `Module` and /// `as Example` setting the prefix used for storage items of this module. `Example` must be unique: /// another module with the same name and the same inner storage item name will conflict. +/// `Example` is called the module prefix. +/// +/// note: For instantiable modules the module prefix is prepended with instance +/// prefix. Instance prefix is "" for default instance and "Instance$n" for instance number $n. +/// Thus, instance 3 of module Example has a module prefix of `Instance3Example` /// /// Basic storage consists of a name and a type; supported types are: /// -/// * Value: `Foo: type`: Implements the [`StorageValue`](../srml_support/storage/trait.StorageValue.html) trait. +/// * Value: `Foo: type`: Implements the +/// [`StorageValue`](../srml_support/storage/trait.StorageValue.html) trait using the +/// [`StorageValue generator`](../srml_support/storage/generator/trait.StorageValue.html). +/// The generator `unhashed_key` is `$module_prefix ++ " " ++ $storage_name` +/// /// * Map: `Foo: map hasher($hash) type => type`: Implements the -/// [`StorageMap`](../srml_support/storage/trait.StorageMap.html) trait -/// with `$hash` representing a choice of hashing algorithms available in the +/// [`StorageMap`](../srml_support/storage/trait.StorageMap.html) trait using the +/// [`StorageMap generator`](../srml_support/storage/generator/trait.StorageMap.html). +/// +/// `$hash` representing a choice of hashing algorithms available in the /// [`Hashable`](../srml_support/trait.Hashable.html) trait. /// -/// `hasher($hash)` is optional and its default is `blake2_256`. +/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher +/// with care, see generator documentation. /// -/// /!\ Be careful with each key in the map that is inserted in the trie -/// `$hash(module_name ++ " " ++ storage_name ++ encoding(key))`. -/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as -/// `blake2_256` must be used. Otherwise, other values in storage can be compromised. +/// The generator is implemented with: +/// * `prefix`: `$module_prefix ++ " " ++ $storage_name` +/// * `Hasher`: $hash /// -/// * Linked map: `Foo: linked_map hasher($hash) type => type`: Same as `Map` but also implements -/// the [`EnumerableStorageMap`](../srml_support/storage/trait.EnumerableStorageMap.html) trait. +/// * Linked map: `Foo: linked_map hasher($hash) type => type`: Implements the +/// [`StorageLinkedMap`](../srml_support/storage/trait.StorageLinkedMap.html) trait using the +/// [`StorageLinkedMap generator`](../srml_support/storage/generator/trait.StorageLinkedMap.html). /// -/// * Double map: `Foo: double_map hasher($hash) u32, $hash2(u32) => u32`: Implements the -/// [`StorageDoubleMap`](../srml_support/storage/trait.StorageDoubleMap.html) trait with -/// `$hash` and `$hash2` representing choices of hashing algorithms available in the +/// `$hash` representing a choice of hashing algorithms available in the /// [`Hashable`](../srml_support/trait.Hashable.html) trait. /// -/// `hasher($hash)` is optional and its default is `blake2_256`. +/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher +/// with care, see generator documentation. +/// +/// The generator is implemented with: +/// * `prefix`: `$module_prefix ++ " " ++ $storage_name` +/// * `head_key`: `"head of " ++ $module_prefix ++ " " ++ $storage_name` +/// * `Hasher`: $hash /// -/// /!\ Be careful with each key pair in the double map that is inserted in the trie. -/// The final key is calculated as follows: +/// * Double map: `Foo: double_map hasher($hash1) u32, $hash2(u32) => u32`: Implements the +/// [`StorageDoubleMap`](../srml_support/storage/trait.StorageDoubleMap.html) trait using the +/// [`StorageDoubleMap generator`](../srml_support/storage/generator/trait.StorageDoubleMap.html). /// -/// ```nocompile -/// $hash(module_name ++ " " ++ storage_name ++ encoding(first_key)) ++ $hash2(encoding(second_key)) -/// ``` +/// `$hash1` and `$hash2` representing choices of hashing algorithms available in the +/// [`Hashable`](../srml_support/trait.Hashable.html) trait. They must be choosen with care, see +/// generator documentation. +/// +/// `hasher($hash)` is optional and its default is `blake2_256`. +/// +/// `hasher($hash)` is optional and its default is `blake2_256`. One should use another hasher +/// with care, see generator documentation. /// /// If the first key is untrusted, a cryptographic `hasher` such as `blake2_256` must be used. /// Otherwise, other values of all storage items can be compromised. @@ -83,6 +105,11 @@ use proc_macro::TokenStream; /// If the second key is untrusted, a cryptographic `hasher` such as `blake2_256` must be used. /// Otherwise, other items in storage with the same first key can be compromised. /// +/// The generator is implemented with: +/// * `key1_prefix`: `$module_prefix ++ " " ++ $storage_name` +/// * `Hasher1`: $hash1 +/// * `Hasher2`: $hash2 +/// /// Supported hashers (ordered from least to best security): /// /// * `twox_64_concat` - TwoX with 64bit + key concatenated. @@ -93,11 +120,11 @@ use proc_macro::TokenStream; /// /// Basic storage can be extended as such: /// -/// `#vis #name get(#getter) config(#field_name) build(#closure): #type = #default;` +/// `#vis #name get(fn #getter) config(#field_name) build(#closure): #type = #default;` /// /// * `#vis`: Set the visibility of the structure. `pub` or nothing. /// * `#name`: Name of the storage item, used as a prefix in storage. -/// * [optional] `get(#getter)`: Implements the function #getter to `Module`. +/// * [optional] `get(fn #getter)`: Implements the function #getter to `Module`. /// * [optional] `config(#field_name)`: `field_name` is optional if get is set. /// Will include the item in `GenesisConfig`. /// * [optional] `build(#closure)`: Closure called with storage overlays. @@ -126,14 +153,24 @@ use proc_macro::TokenStream; /// config(genesis_field): GenesisFieldType; /// config(genesis_field2): GenesisFieldType; /// ... -/// build(|_: &mut StorageOverlay, _: &mut ChildrenStorageOverlay, _: &GenesisConfig| { +/// build(|_: &Self| { /// // Modification of storage /// }) /// } /// } /// ``` /// -/// This struct can be exposed as `Config` by the `decl_runtime!` macro. +/// This struct can be exposed as `ExampleConfig` by the `construct_runtime!` macro like follows: +/// +/// ```nocompile +/// construct_runtime!( +/// pub enum Runtume with ... { +/// ..., +/// Example: example::{Module, Storage, ..., Config}, +/// ..., +/// } +/// ); +/// ``` /// /// ### Module with Instances /// @@ -176,5 +213,5 @@ use proc_macro::TokenStream; /// #[proc_macro] pub fn decl_storage(input: TokenStream) -> TokenStream { - storage::transformation::decl_storage_impl(input) + storage::decl_storage_impl(input) } diff --git a/srml/support/procedural/src/storage/genesis_config/builder_def.rs b/srml/support/procedural/src/storage/genesis_config/builder_def.rs new file mode 100644 index 0000000000000000000000000000000000000000..fc425e4a6d53261fb5f9868127be0ce90ddff5e1 --- /dev/null +++ b/srml/support/procedural/src/storage/genesis_config/builder_def.rs @@ -0,0 +1,111 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Builder logic definition used to build genesis storage. + +use srml_support_procedural_tools::syn_ext as ext; +use proc_macro2::TokenStream; +use syn::spanned::Spanned; +use quote::{quote, quote_spanned}; +use super::super::{DeclStorageDefExt, StorageLineTypeDef}; + +/// Definition of builder blocks, each block insert some value in the storage. +/// They must be called inside externalities, and with `self` being the genesis config. +pub struct BuilderDef { + /// Contains: + /// * build block for storage with build attribute. + /// * build block for storage with config attribute and no build attribute. + /// * build block for extra genesis build expression. + pub blocks: Vec, + /// The build blocks requires generic traits. + pub is_generic: bool, +} + +impl BuilderDef { + pub fn from_def(scrate: &TokenStream, def: &DeclStorageDefExt) -> Self { + let mut blocks = Vec::new(); + let mut is_generic = false; + + for line in def.storage_lines.iter() { + let storage_struct = &line.storage_struct; + let storage_trait = &line.storage_trait; + let value_type = &line.value_type; + + // Contains the data to inset at genesis either from build or config. + let mut data = None; + + if let Some(builder) = &line.build { + is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic); + is_generic |= line.is_generic; + + data = Some(quote_spanned!(builder.span() => &(#builder)(self))); + } else if let Some(config) = &line.config { + is_generic |= line.is_generic; + + data = Some(quote!(&self.#config;)); + }; + + if let Some(data) = data { + blocks.push(match &line.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!{{ + let v: &#value_type = #data; + <#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v); + }} + }, + StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => { + let key = &map.key; + quote!{{ + let data: &#scrate::rstd::vec::Vec<(#key, #value_type)> = #data; + data.iter().for_each(|(k, v)| { + <#storage_struct as #scrate::#storage_trait>::insert::< + &#key, &#value_type + >(k, v); + }); + }} + }, + StorageLineTypeDef::DoubleMap(map) => { + let key1 = &map.key1; + let key2 = &map.key2; + quote!{{ + let data: &#scrate::rstd::vec::Vec<(#key1, #key2, #value_type)> = #data; + data.iter().for_each(|(k1, k2, v)| { + <#storage_struct as #scrate::#storage_trait>::insert::< + &#key1, &#key2, &#value_type + >(k1, k2, v); + }); + }} + }, + }); + } + } + + if let Some(builder) = def.extra_genesis_build.as_ref() { + is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic); + + blocks.push(quote_spanned! { builder.span() => + let extra_genesis_builder: fn(&Self) = #builder; + extra_genesis_builder(self); + }); + } + + + Self { + blocks, + is_generic, + } + } +} diff --git a/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs b/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs new file mode 100644 index 0000000000000000000000000000000000000000..8944a924724a9969b5fdff575bd3bf7e5b88d4fe --- /dev/null +++ b/srml/support/procedural/src/storage/genesis_config/genesis_config_def.rs @@ -0,0 +1,144 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Genesis config defintion. + +use srml_support_procedural_tools::syn_ext as ext; +use proc_macro2::TokenStream; +use syn::parse_quote; +use quote::quote; +use super::super::{DeclStorageDefExt, StorageLineTypeDef}; + +pub struct GenesisConfigFieldDef { + pub doc: Vec, + pub name: syn::Ident, + pub typ: syn::Type, + pub default: TokenStream, +} + +pub struct GenesisConfigDef { + pub is_generic: bool, + pub fields: Vec, + /// For example: `, I: Instance=DefaultInstance>`. + pub genesis_struct_decl: TokenStream, + /// For example: ``. + pub genesis_struct: TokenStream, + /// For example: `, I: Instance>`. + pub genesis_impl: TokenStream, + /// The where clause to use to constrain generics if genesis config is generic. + pub genesis_where_clause: Option, +} + +impl GenesisConfigDef { + pub fn from_def(def: &DeclStorageDefExt) -> Self { + let fields = Self::get_genesis_config_field_defs(def); + + let is_generic = fields.iter() + .any(|field| ext::type_contains_ident(&field.typ, &def.module_runtime_generic)); + + let ( + genesis_struct_decl, + genesis_impl, + genesis_struct, + genesis_where_clause + ) = if is_generic { + let runtime_generic = &def.module_runtime_generic; + let runtime_trait = &def.module_runtime_trait; + let optional_instance = &def.optional_instance; + let optional_instance_bound = &def.optional_instance_bound; + let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default; + let where_clause = &def.where_clause; + ( + quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound_optional_default>), + quote!(<#runtime_generic: #runtime_trait, #optional_instance_bound>), + quote!(<#runtime_generic, #optional_instance>), + where_clause.clone(), + ) + } else { + (quote!(), quote!(), quote!(), None) + }; + + Self { + is_generic, + fields, + genesis_struct_decl, + genesis_struct, + genesis_impl, + genesis_where_clause, + } + } + + fn get_genesis_config_field_defs(def: &DeclStorageDefExt) -> Vec { + let mut config_field_defs = Vec::new(); + + for (config_field, line) in def.storage_lines.iter() + .filter_map(|line| line.config.as_ref().map(|config_field| (config_field.clone(), line))) + { + let value_type = &line.value_type; + + let typ = match &line.storage_type { + StorageLineTypeDef::Simple(_) => (*value_type).clone(), + StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => { + let key = &map.key; + parse_quote!( Vec<(#key, #value_type)> ) + }, + StorageLineTypeDef::DoubleMap(map) => { + let key1 = &map.key1; + let key2 = &map.key2; + + parse_quote!( Vec<(#key1, #key2, #value_type)> ) + }, + }; + + let default = line.default_value.as_ref() + .map(|d| { + if line.is_option { + quote!( #d.unwrap_or_default() ) + } else { + quote!( #d ) + } + }) + .unwrap_or_else(|| quote!( Default::default() )); + + config_field_defs.push(GenesisConfigFieldDef { + doc: line.doc_attrs.clone(), + name: config_field, + typ, + default, + }); + } + + for line in &def.extra_genesis_config_lines { + let doc = line.attrs.iter() + .filter_map(|a| a.parse_meta().ok()) + .filter(|m| m.path().is_ident("doc")) + .collect(); + + let default = line.default.as_ref().map(|e| quote!( #e )) + .unwrap_or_else(|| quote!( Default::default() )); + + + config_field_defs.push(GenesisConfigFieldDef { + doc, + name: line.name.clone(), + typ: line.typ.clone(), + default, + }); + } + + config_field_defs + } +} diff --git a/srml/support/procedural/src/storage/genesis_config/mod.rs b/srml/support/procedural/src/storage/genesis_config/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..2d4d4af3861ed56c186f15de4352b0aa0a9ca372 --- /dev/null +++ b/srml/support/procedural/src/storage/genesis_config/mod.rs @@ -0,0 +1,203 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Declaration of genesis config structure and implementation of build storage trait and +//! functions. + +use proc_macro2::{TokenStream, Span}; +use quote::quote; +use super::{DeclStorageDefExt, instance_trait::DEFAULT_INSTANTIABLE_TRAIT_NAME}; +use genesis_config_def::GenesisConfigDef; +use builder_def::BuilderDef; + +mod genesis_config_def; +mod builder_def; + +const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance"; + +fn decl_genesis_config_and_impl_default( + scrate: &TokenStream, + genesis_config: &GenesisConfigDef, +) -> TokenStream { + let config_fields = genesis_config.fields.iter().map(|field| { + let (name, typ, doc) = (&field.name, &field.typ, &field.doc); + quote!( #( #[ #doc] )* pub #name: #typ, ) + }); + + let config_field_defaults = genesis_config.fields.iter().map(|field| { + let (name, default, doc) = (&field.name, &field.default, &field.doc); + quote!( #( #[ #doc] )* #name: #default, ) + }); + + let serde_bug_bound = if !genesis_config.fields.is_empty() { + let mut b_ser = String::new(); + let mut b_dser = String::new(); + + for typ in genesis_config.fields.iter().map(|c| &c.typ) { + let typ = quote!( #typ ); + b_ser.push_str(&format!("{} : {}::serde::Serialize, ", typ, scrate)); + b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", typ, scrate)); + } + + quote! { + #[serde(bound(serialize = #b_ser))] + #[serde(bound(deserialize = #b_dser))] + } + } else { + quote!() + }; + + let genesis_struct_decl = &genesis_config.genesis_struct_decl; + let genesis_struct = &genesis_config.genesis_struct; + let genesis_impl = &genesis_config.genesis_impl; + let genesis_where_clause = &genesis_config.genesis_where_clause; + + quote!( + #[derive(#scrate::Serialize, #scrate::Deserialize)] + #[cfg(feature = "std")] + #[serde(rename_all = "camelCase")] + #[serde(deny_unknown_fields)] + #serde_bug_bound + pub struct GenesisConfig#genesis_struct_decl #genesis_where_clause { + #( #config_fields )* + } + + #[cfg(feature = "std")] + impl#genesis_impl Default for GenesisConfig#genesis_struct #genesis_where_clause { + fn default() -> Self { + GenesisConfig { + #( #config_field_defaults )* + } + } + } + ) +} + +fn impl_build_storage( + scrate: &TokenStream, + def: &DeclStorageDefExt, + genesis_config: &GenesisConfigDef, + builders: &BuilderDef, +) -> TokenStream { + let runtime_generic = &def.module_runtime_generic; + let runtime_trait = &def.module_runtime_trait; + let optional_instance = &def.optional_instance; + let optional_instance_bound = &def.optional_instance_bound; + let where_clause = &def.where_clause; + + let inherent_instance = def.optional_instance.clone().unwrap_or_else(|| { + let name = syn::Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site()); + quote!( #name ) + }); + let inherent_instance_bound = def.optional_instance_bound.clone().unwrap_or_else(|| { + let bound = syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site()); + quote!( #inherent_instance: #bound ) + }); + + let build_storage_impl = quote!( + <#runtime_generic: #runtime_trait, #inherent_instance_bound> + ); + + let genesis_struct = &genesis_config.genesis_struct; + let genesis_impl = &genesis_config.genesis_impl; + let genesis_where_clause = &genesis_config.genesis_where_clause; + + let ( + fn_generic, + fn_traitinstance, + fn_where_clause + ) = if !genesis_config.is_generic && builders.is_generic { + ( + quote!( <#runtime_generic: #runtime_trait, #optional_instance_bound> ), + quote!( #runtime_generic, #optional_instance ), + Some(&def.where_clause), + ) + } else { + (quote!(), quote!(), None) + }; + + let builder_blocks = &builders.blocks; + + let build_storage_impl_trait = quote!( + #scrate::sr_primitives::BuildModuleGenesisStorage<#runtime_generic, #inherent_instance> + ); + + quote!{ + #[cfg(feature = "std")] + impl#genesis_impl GenesisConfig#genesis_struct #genesis_where_clause { + pub fn build_storage #fn_generic (&self) -> std::result::Result< + ( + #scrate::sr_primitives::StorageOverlay, + #scrate::sr_primitives::ChildrenStorageOverlay, + ), + String + > #fn_where_clause { + let mut storage = (Default::default(), Default::default()); + self.assimilate_storage::<#fn_traitinstance>(&mut storage)?; + Ok(storage) + } + + /// Assimilate the storage for this module into pre-existing overlays. + pub fn assimilate_storage #fn_generic ( + &self, + tuple_storage: &mut ( + #scrate::sr_primitives::StorageOverlay, + #scrate::sr_primitives::ChildrenStorageOverlay, + ), + ) -> std::result::Result<(), String> #fn_where_clause { + #scrate::with_storage(tuple_storage, || { + #( #builder_blocks )* + Ok(()) + }) + } + } + + #[cfg(feature = "std")] + impl#build_storage_impl #build_storage_impl_trait for GenesisConfig#genesis_struct + #where_clause + { + fn build_module_genesis_storage( + &self, + storage: &mut ( + #scrate::sr_primitives::StorageOverlay, + #scrate::sr_primitives::ChildrenStorageOverlay, + ), + ) -> std::result::Result<(), String> { + self.assimilate_storage::<#fn_traitinstance> (storage) + } + } + } +} + +pub fn genesis_config_and_build_storage( + scrate: &TokenStream, + def: &DeclStorageDefExt, +) -> TokenStream { + let builders = BuilderDef::from_def(scrate, def); + if !builders.blocks.is_empty() { + let genesis_config = &GenesisConfigDef::from_def(def); + let decl_genesis_config_and_impl_default = + decl_genesis_config_and_impl_default(scrate, genesis_config); + let impl_build_storage = impl_build_storage(scrate, def, genesis_config, &builders); + + quote!{ + #decl_genesis_config_and_impl_default + #impl_build_storage + } + } else { + quote!() + } +} diff --git a/srml/support/procedural/src/storage/getters.rs b/srml/support/procedural/src/storage/getters.rs new file mode 100644 index 0000000000000000000000000000000000000000..f30e489eb58bc7907bcce3fed2bae031ae12e893 --- /dev/null +++ b/srml/support/procedural/src/storage/getters.rs @@ -0,0 +1,80 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of getters on module structure. + +use proc_macro2::TokenStream; +use quote::quote; +use super::{DeclStorageDefExt, StorageLineTypeDef}; + +pub fn impl_getters(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + let mut getters = TokenStream::new(); + + for (get_fn, line) in def.storage_lines.iter() + .filter_map(|line| line.getter.as_ref().map(|get_fn| (get_fn, line))) + { + let attrs = &line.doc_attrs; + + let storage_struct = &line.storage_struct; + let storage_trait = &line.storage_trait; + + let getter = match &line.storage_type { + StorageLineTypeDef::Simple(value) => { + quote!{ + #( #[ #attrs ] )* + pub fn #get_fn() -> #value { + <#storage_struct as #scrate::#storage_trait>::get() + } + } + }, + StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => { + let key = &map.key; + let value = &map.value; + quote!{ + #( #[ #attrs ] )* + pub fn #get_fn>(key: K) -> #value { + <#storage_struct as #scrate::#storage_trait>::get(key) + } + } + }, + StorageLineTypeDef::DoubleMap(map) => { + let key1 = &map.key1; + let key2 = &map.key2; + let value = &map.value; + quote!{ + pub fn #get_fn(k1: KArg1, k2: KArg2) -> #value + where + KArg1: #scrate::codec::EncodeLike<#key1>, + KArg2: #scrate::codec::EncodeLike<#key2>, + { + <#storage_struct as #scrate::#storage_trait>::get(k1, k2) + } + } + }, + }; + getters.extend(getter); + } + + let module_struct = &def.module_struct; + let module_impl = &def.module_impl; + let where_clause = &def.where_clause; + + quote!( + impl#module_impl #module_struct #where_clause { + #getters + } + ) +} diff --git a/srml/support/procedural/src/storage/impls.rs b/srml/support/procedural/src/storage/impls.rs deleted file mode 100644 index dd936636735141231ee6352e14c4032a00ad35df..0000000000000000000000000000000000000000 --- a/srml/support/procedural/src/storage/impls.rs +++ /dev/null @@ -1,873 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::storage::transformation::{DeclStorageTypeInfos, InstanceOpts}; - -use srml_support_procedural_tools::syn_ext as ext; -use proc_macro2::TokenStream as TokenStream2; -use syn::Ident; -use quote::quote; - -pub fn option_unwrap(is_option: bool) -> TokenStream2 { - if !is_option { - // raw type case - quote!( unwrap_or_else ) - } else { - // Option<> type case - quote!( or_else ) - } -} - -// prefix for consts in trait Instance -pub(crate) const PREFIX_FOR: &str = "PREFIX_FOR_"; -pub(crate) const HEAD_KEY_FOR: &str = "HEAD_KEY_FOR_"; - -pub(crate) struct Impls<'a, I: Iterator> { - pub scrate: &'a TokenStream2, - pub visibility: &'a syn::Visibility, - pub traitinstance: &'a syn::Ident, - pub traittype: &'a syn::TypeParamBound, - pub instance_opts: &'a InstanceOpts, - pub type_infos: DeclStorageTypeInfos<'a>, - pub fielddefault: TokenStream2, - pub prefix: String, - pub cratename: &'a syn::Ident, - pub name: &'a syn::Ident, - pub attrs: I, - pub where_clause: &'a Option, -} - -impl<'a, I: Iterator> Impls<'a, I> { - pub fn simple_value(self) -> TokenStream2 { - let Self { - scrate, - visibility, - traitinstance, - traittype, - instance_opts, - type_infos, - fielddefault, - prefix, - name, - attrs, - where_clause, - .. - } = self; - let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; - let option_simple_1 = option_unwrap(is_option); - - let mutate_impl = if !is_option { - quote!{ - >::put(&val, storage) - } - } else { - quote!{ - match val { - Some(ref val) => >::put(&val, storage), - None => >::kill(storage), - } - } - }; - - let InstanceOpts { - equal_default_instance, - bound_instantiable, - instance, - .. - } = instance_opts; - - let final_prefix = if let Some(instance) = instance { - let const_name = Ident::new(&format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site()); - quote!{ #instance::#const_name.as_bytes() } - } else { - quote!{ #prefix.as_bytes() } - }; - - let (struct_trait, impl_trait, trait_and_instance, where_clause) = if ext::type_contains_ident( - value_type, traitinstance - ) { - ( - quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), - quote!(#traitinstance: #traittype, #instance #bound_instantiable), - quote!(#traitinstance, #instance), - where_clause.clone(), - ) - } else { - ( - quote!(#instance #bound_instantiable #equal_default_instance), - quote!(#instance #bound_instantiable), - quote!(#instance), - None, - ) - }; - - // generator for value - quote! { - #( #[ #attrs ] )* - #visibility struct #name<#struct_trait>( - #scrate::rstd::marker::PhantomData<(#trait_and_instance)> - ) #where_clause; - - impl<#impl_trait> #scrate::storage::hashed::generator::StorageValue<#typ> - for #name<#trait_and_instance> #where_clause - { - type Query = #value_type; - - /// Get the storage key. - fn key() -> &'static [u8] { - #final_prefix - } - - /// Load the value from the provided storage instance. - fn get>(storage: &S) -> Self::Query { - storage.get(>::key()) - .#option_simple_1(|| #fielddefault) - } - - /// Take a value from storage, removing it afterwards. - fn take>(storage: &mut S) -> Self::Query { - storage.take(>::key()) - .#option_simple_1(|| #fielddefault) - } - - /// Mutate the value under a key. - fn mutate(f: F, storage: &mut S) -> R - where - F: FnOnce(&mut Self::Query) -> R, - S: #scrate::HashedStorage<#scrate::Twox128>, - { - let mut val = >::get(storage); - - let ret = f(&mut val); - #mutate_impl ; - ret - } - } - } - } - - pub fn map(self, hasher: TokenStream2, kty: &syn::Type) -> TokenStream2 { - let Self { - scrate, - visibility, - traitinstance, - traittype, - instance_opts, - type_infos, - fielddefault, - prefix, - name, - attrs, - where_clause, - .. - } = self; - let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; - let option_simple_1 = option_unwrap(is_option); - - let as_map = quote!{ > }; - - let mutate_impl = if !is_option { - quote!{ - #as_map::insert(key, &val, storage) - } - } else { - quote!{ - match val { - Some(ref val) => #as_map::insert(key, &val, storage), - None => #as_map::remove(key, storage), - } - } - }; - - let InstanceOpts { - equal_default_instance, - bound_instantiable, - instance, - .. - } = instance_opts; - - let final_prefix = if let Some(instance) = instance { - let const_name = syn::Ident::new( - &format!("{}{}", PREFIX_FOR, name.to_string()), - proc_macro2::Span::call_site(), - ); - quote! { #instance::#const_name.as_bytes() } - } else { - quote! { #prefix.as_bytes() } - }; - - let trait_required = ext::type_contains_ident(value_type, traitinstance) - || ext::type_contains_ident(kty, traitinstance); - - let (struct_trait, impl_trait, trait_and_instance, where_clause) = if trait_required { - ( - quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), - quote!(#traitinstance: #traittype, #instance #bound_instantiable), - quote!(#traitinstance, #instance), - where_clause.clone(), - ) - } else { - ( - quote!(#instance #bound_instantiable #equal_default_instance), - quote!(#instance #bound_instantiable), - quote!(#instance), - None, - ) - }; - - // generator for map - quote!{ - #( #[ #attrs ] )* - #visibility struct #name<#struct_trait>( - #scrate::rstd::marker::PhantomData<(#trait_and_instance)> - ) #where_clause; - - impl<#impl_trait> #scrate::storage::hashed::generator::StorageMap<#kty, #typ> - for #name<#trait_and_instance> #where_clause - { - type Query = #value_type; - - type Hasher = #scrate::#hasher; - - /// Get the prefix key in storage. - fn prefix() -> &'static [u8] { - #final_prefix - } - - /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for(x: &#kty) -> #scrate::rstd::vec::Vec { - let mut key = #as_map::prefix().to_vec(); - #scrate::codec::Encode::encode_to(x, &mut key); - key - } - - /// Load the value associated with the given key from the map. - fn get>(key: &#kty, storage: &S) -> Self::Query { - let key = #as_map::key_for(key); - storage.get(&key[..]).#option_simple_1(|| #fielddefault) - } - - /// Take the value, reading and removing it. - fn take>(key: &#kty, storage: &mut S) -> Self::Query { - let key = #as_map::key_for(key); - storage.take(&key[..]).#option_simple_1(|| #fielddefault) - } - - /// Mutate the value under a key - fn mutate(key: &#kty, f: F, storage: &mut S) -> R - where - F: FnOnce(&mut Self::Query) -> R, - S: #scrate::HashedStorage<#scrate::#hasher>, - { - let mut val = #as_map::get(key, storage); - - let ret = f(&mut val); - #mutate_impl ; - ret - } - } - - impl<#impl_trait> #scrate::storage::hashed::generator::AppendableStorageMap<#kty, #typ> - for #name<#trait_and_instance> #where_clause - {} - } - } - - pub fn linked_map(self, hasher: TokenStream2, kty: &syn::Type) -> TokenStream2 { - let Self { - scrate, - visibility, - traitinstance, - traittype, - instance_opts, - type_infos, - fielddefault, - prefix, - name, - attrs, - where_clause, - .. - } = self; - - let InstanceOpts { - equal_default_instance, - bound_instantiable, - instance, - .. - } = instance_opts; - - let final_prefix = if let Some(instance) = instance { - let const_name = Ident::new( - &format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site() - ); - quote!{ #instance::#const_name.as_bytes() } - } else { - quote!{ #prefix.as_bytes() } - }; - - // make sure to use different prefix for head and elements. - let final_head_key = if let Some(instance) = instance { - let const_name = Ident::new( - &format!("{}{}", HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site() - ); - quote!{ #instance::#const_name.as_bytes() } - } else { - let final_head_key = format!("head of {}", prefix); - quote!{ #final_head_key.as_bytes() } - }; - - let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; - let option_simple_1 = option_unwrap(is_option); - let name_lowercase = name.to_string().to_lowercase(); - let inner_module = Ident::new( - &format!("__linked_map_details_for_{}_do_not_use", name_lowercase), name.span() - ); - let linkage = Ident::new(&format!("__LinkageFor{}DoNotUse", name), name.span()); - let phantom_data = quote! { #scrate::rstd::marker::PhantomData }; - let as_map = quote!{ > }; - let put_or_insert = quote! { - match linkage { - Some(linkage) => storage.put(key_for, &(val, linkage)), - None => #as_map::insert(key, &val, storage), - } - }; - let mutate_impl = if !type_infos.is_option { - put_or_insert - } else { - quote! { - match val { - Some(ref val) => #put_or_insert, - None => #as_map::remove(key, storage), - } - } - }; - - let mutate_map = if type_infos.is_option { - quote! { .map(|(data, linkage)| (Some(data), Some(linkage))) } - } else { - quote! { .map(|(data, linkage)| (data, Some(linkage))) } - }; - - let trait_required = ext::type_contains_ident(value_type, traitinstance) - || ext::type_contains_ident(kty, traitinstance); - - let (struct_trait, impl_trait, trait_and_instance) = if trait_required { - ( - quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), - quote!(#traitinstance: #traittype, #instance #bound_instantiable), - quote!(#traitinstance, #instance), - ) - } else { - ( - quote!(#instance #bound_instantiable #equal_default_instance), - quote!(#instance #bound_instantiable), - quote!(#instance), - ) - }; - - let (where_clause, trait_where_clause) = if trait_required { - ( - where_clause.clone(), - where_clause.clone().map(|mut wc| { - wc.predicates.push(syn::parse_quote!(#traitinstance: 'static)); - wc - }).or_else(|| syn::parse_quote!(where #traitinstance: 'static)), - ) - } else { - ( - None, - None, - ) - }; - - // generator for linked map - let helpers = quote! { - /// Linkage data of an element (it's successor and predecessor) - #[derive(#scrate::codec::Encode, #scrate::codec::Decode)] - pub(crate) struct #linkage { - /// Previous element key in storage (None for the first element) - pub previous: Option, - /// Next element key in storage (None for the last element) - pub next: Option, - } - - mod #inner_module { - use super::*; - - /// Re-exported version of linkage to overcome proc-macro derivation issue. - pub(crate) use super::#linkage as Linkage; - - impl Default for Linkage { - fn default() -> Self { - Self { - previous: None, - next: None, - } - } - } - - /// A key-value pair iterator for enumerable map. - pub(crate) struct Enumerator<'a, S, K, V> { - pub storage: &'a S, - pub next: Option, - pub _data: #phantom_data, - } - - impl<'a, S: #scrate::HashedStorage<#scrate::#hasher>, #impl_trait> Iterator - for Enumerator<'a, S, #kty, (#typ, #trait_and_instance)> #where_clause - { - type Item = (#kty, #typ); - - fn next(&mut self) -> Option { - let next = self.next.take()?; - let key_for = - as #scrate::storage::hashed::generator::StorageMap<#kty, #typ>>::key_for(&next); - - let (val, linkage): (#typ, Linkage<#kty>) = self.storage.get(&*key_for) - .expect("previous/next only contain existing entires; we enumerate using next; entry exists; qed"); - self.next = linkage.next; - Some((next, val)) - } - } - - pub(crate) trait Utils<#struct_trait> { - /// Update linkage when this element is removed. - /// - /// Takes care of updating previous and next elements points - /// as well as updates head if the element is first or last. - fn remove_linkage>(linkage: Linkage<#kty>, storage: &mut S); - - /// Read the contained data and it's linkage. - fn read_with_linkage(storage: &S, key: &[u8]) -> Option<(#typ, Linkage<#kty>)> - where - S: #scrate::HashedStorage<#scrate::#hasher>; - - /// Generate linkage for newly inserted element. - /// - /// Takes care of updating head and previous head's pointer. - fn new_head_linkage>( - storage: &mut S, - key: &#kty, - ) -> Linkage<#kty>; - - /// Read current head pointer. - fn read_head>(storage: &S) -> Option<#kty>; - - /// Overwrite current head pointer. - /// - /// If `None` is given head is removed from storage. - fn write_head>(storage: &mut S, head: Option<&#kty>); - } - } - }; - - let structure = quote! { - #( #[ #attrs ] )* - #visibility struct #name<#struct_trait>(#phantom_data<(#trait_and_instance)>); - - impl<#impl_trait> self::#inner_module::Utils<#trait_and_instance> - for #name<#trait_and_instance> #where_clause - { - fn remove_linkage>( - linkage: self::#inner_module::Linkage<#kty>, - storage: &mut S, - ) { - use self::#inner_module::Utils; - - let next_key = linkage.next.as_ref().map(|x| #as_map::key_for(x)); - let prev_key = linkage.previous.as_ref().map(|x| #as_map::key_for(x)); - - if let Some(prev_key) = prev_key { - // Retrieve previous element and update `next` - let mut res = Self::read_with_linkage(storage, &*prev_key) - .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); - res.1.next = linkage.next; - storage.put(&*prev_key, &res); - } else { - // we were first so let's update the head - Self::write_head(storage, linkage.next.as_ref()); - } - - if let Some(next_key) = next_key { - // Update previous of next element - let mut res = Self::read_with_linkage(storage, &*next_key) - .expect("Linkage is updated in case entry is removed; it always points to existing keys; qed"); - res.1.previous = linkage.previous; - storage.put(&*next_key, &res); - } - } - - fn read_with_linkage>( - storage: &S, - key: &[u8], - ) -> Option<(#typ, self::#inner_module::Linkage<#kty>)> { - storage.get(key) - } - - fn new_head_linkage>( - storage: &mut S, - key: &#kty, - ) -> self::#inner_module::Linkage<#kty> { - use self::#inner_module::Utils; - - if let Some(head) = Self::read_head(storage) { - // update previous head predecessor - { - let head_key = #as_map::key_for(&head); - let (data, linkage) = Self::read_with_linkage(storage, &*head_key).expect(r#" - head is set when first element is inserted and unset when last element is removed; - if head is Some then it points to existing key; qed - "#); - storage.put(&*head_key, &(data, self::#inner_module::Linkage { - next: linkage.next.as_ref(), - previous: Some(key), - })); - } - // update to current head - Self::write_head(storage, Some(key)); - // return linkage with pointer to previous head - let mut linkage = self::#inner_module::Linkage::default(); - linkage.next = Some(head); - linkage - } else { - // we are first - update the head and produce empty linkage - Self::write_head(storage, Some(key)); - self::#inner_module::Linkage::default() - } - } - - fn read_head>(storage: &S) -> Option<#kty> { - storage.get(#final_head_key) - } - - fn write_head>(storage: &mut S, head: Option<&#kty>) { - match head { - Some(head) => storage.put(#final_head_key, head), - None => storage.kill(#final_head_key), - } - } - } - }; - - quote! { - #helpers - - #structure - - impl<#impl_trait> #scrate::storage::hashed::generator::StorageMap<#kty, #typ> - for #name<#trait_and_instance> #where_clause - { - type Query = #value_type; - - type Hasher = #scrate::#hasher; - - /// Get the prefix key in storage. - fn prefix() -> &'static [u8] { - #final_prefix - } - - /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for(key: &#kty) -> #scrate::rstd::vec::Vec { - let mut key_for = #as_map::prefix().to_vec(); - #scrate::codec::Encode::encode_to(&key, &mut key_for); - key_for - } - - /// Load the value associated with the given key from the map. - fn get>(key: &#kty, storage: &S) -> Self::Query { - storage.get(&*#as_map::key_for(key)).#option_simple_1(|| #fielddefault) - } - - /// Take the value, reading and removing it. - fn take>(key: &#kty, storage: &mut S) -> Self::Query { - use self::#inner_module::Utils; - - let res: Option<(#typ, self::#inner_module::Linkage<#kty>)> = storage.take(&*#as_map::key_for(key)); - - res.map(|(d, l)| { - Self::remove_linkage(l, storage); - d - }).#option_simple_1(|| #fielddefault) - } - - /// Remove the value under a key. - fn remove>(key: &#kty, storage: &mut S) { - #as_map::take(key, storage); - } - - /// Store a value to be associated with the given key from the map. - fn insert>( - key: &#kty, - val: &#typ, - storage: &mut S, - ) { - use self::#inner_module::Utils; - - let key_for = &*#as_map::key_for(key); - let linkage = match Self::read_with_linkage(storage, key_for) { - // overwrite but reuse existing linkage - Some((_data, linkage)) => linkage, - // create new linkage - None => Self::new_head_linkage(storage, key), - }; - - storage.put(key_for, &(val, linkage)) - } - - /// Store a value under this key into the provided storage instance; this can take any reference - /// type that derefs to `T` (and has `Encode` implemented). - /// Store a value under this key into the provided storage instance. - fn insert_ref(key: &#kty, val: &Arg, storage: &mut S) - where - #typ: AsRef, - Arg: ?Sized + #scrate::codec::Encode, - S: #scrate::HashedStorage<#scrate::#hasher> - { - use self::#inner_module::Utils; - - let key_for = &*#as_map::key_for(key); - let linkage = match Self::read_with_linkage(storage, key_for) { - // overwrite but reuse existing linkage - Some((_data, linkage)) => linkage, - // create new linkage - None => Self::new_head_linkage(storage, key), - }; - - storage.put(key_for, &(val, linkage)) - } - - /// Mutate the value under a key - fn mutate(key: &#kty, f: F, storage: &mut S) -> R - where - F: FnOnce(&mut Self::Query) -> R, - S: #scrate::HashedStorage<#scrate::#hasher>, - { - use self::#inner_module::Utils; - - let key_for = &*#as_map::key_for(key); - let (mut val, linkage) = Self::read_with_linkage(storage, key_for) - #mutate_map - .unwrap_or_else(|| (#fielddefault, None)); - - let ret = f(&mut val); - #mutate_impl; - ret - } - } - - impl<#impl_trait> #scrate::storage::hashed::generator::EnumerableStorageMap<#kty, #typ> - for #name<#trait_and_instance> #trait_where_clause - { - fn head>(storage: &S) -> Option<#kty> { - use self::#inner_module::Utils; - - Self::read_head(storage) - } - - fn enumerate<'a, S>( - storage: &'a S - ) -> #scrate::rstd::boxed::Box + 'a> - where - S: #scrate::HashedStorage<#scrate::#hasher>, - #kty: 'a, - #typ: 'a, - { - use self::#inner_module::{Utils, Enumerator}; - - #scrate::rstd::boxed::Box::new(Enumerator { - next: Self::read_head(storage), - storage, - _data: #phantom_data::<(#typ, #trait_and_instance)>::default(), - }) - } - } - } - } - - pub fn double_map( - self, - hasher: TokenStream2, - k1ty: &syn::Type, - k2ty: &syn::Type, - k2_hasher: TokenStream2, - ) -> TokenStream2 { - let Self { - scrate, - visibility, - traitinstance, - traittype, - type_infos, - fielddefault, - prefix, - name, - attrs, - instance_opts, - where_clause, - .. - } = self; - - let DeclStorageTypeInfos { typ, value_type, is_option, .. } = type_infos; - let option_simple_1 = option_unwrap(is_option); - - let as_double_map = quote!{ - > - }; - - let mutate_impl = if !is_option { - quote!{ - #as_double_map::insert(k1, k2, &val, storage) - } - } else { - quote!{ - match val { - Some(ref val) => #as_double_map::insert::( - k1, - k2, - val, - storage, - ), - None => #as_double_map::remove(k1, k2, storage), - } - } - }; - - let InstanceOpts { - equal_default_instance, - bound_instantiable, - instance, - .. - } = instance_opts; - - let final_prefix = if let Some(instance) = instance { - let const_name = Ident::new( - &format!("{}{}", PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site() - ); - quote!{ #instance::#const_name.as_bytes() } - } else { - quote!{ #prefix.as_bytes() } - }; - - let (struct_trait, impl_trait, trait_and_instance, where_clause) = if ext::type_contains_ident( - value_type, traitinstance - ) || ext::type_contains_ident(k1ty, traitinstance) || ext::type_contains_ident(k2ty, traitinstance) - { - ( - quote!(#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance), - quote!(#traitinstance: #traittype, #instance #bound_instantiable), - quote!(#traitinstance, #instance), - where_clause.clone(), - ) - } else { - ( - quote!(#instance #bound_instantiable #equal_default_instance), - quote!(#instance #bound_instantiable), - quote!(#instance), - None, - ) - }; - - // generator for double map - quote!{ - #( #[ #attrs ] )* - #visibility struct #name<#struct_trait> - (#scrate::rstd::marker::PhantomData<(#trait_and_instance)>); - - impl<#impl_trait> #scrate::storage::unhashed::generator::StorageDoubleMap<#k1ty, #k2ty, #typ> - for #name<#trait_and_instance> #where_clause - { - type Query = #value_type; - - fn prefix_for(k1: &KArg1) -> #scrate::rstd::vec::Vec where - KArg1: ?Sized + #scrate::codec::Encode, - #k1ty: #scrate::rstd::borrow::Borrow, - { - use #scrate::storage::hashed::generator::StorageHasher; - - let mut key = #as_double_map::prefix().to_vec(); - #scrate::codec::Encode::encode_to(k1, &mut key); - #scrate::#hasher::hash(&key[..]).to_vec() - } - - fn prefix() -> &'static [u8] { - #final_prefix - } - - fn key_for( - k1: &KArg1, - k2: &KArg2, - ) -> #scrate::rstd::vec::Vec where - #k1ty: #scrate::rstd::borrow::Borrow, - #k2ty: #scrate::rstd::borrow::Borrow, - KArg1: ?Sized + #scrate::codec::Encode, - KArg2: ?Sized + #scrate::codec::Encode, - { - use #scrate::storage::hashed::generator::StorageHasher; - - let mut key = #as_double_map::prefix_for(k1); - #scrate::codec::Encode::using_encoded(k2, |e| key.extend(&#scrate::#k2_hasher::hash(e))); - key - } - - fn get( - k1: &KArg1, - k2: &KArg2, - storage: &S, - ) -> Self::Query where - #k1ty: #scrate::rstd::borrow::Borrow, - #k2ty: #scrate::rstd::borrow::Borrow, - KArg1: ?Sized + #scrate::codec::Encode, - KArg2: ?Sized + #scrate::codec::Encode, - { - let key = #as_double_map::key_for(k1, k2); - storage.get(&key).#option_simple_1(|| #fielddefault) - } - - fn take( - k1: &KArg1, - k2: &KArg2, - storage: &mut S, - ) -> Self::Query where - #k1ty: #scrate::rstd::borrow::Borrow, - #k2ty: #scrate::rstd::borrow::Borrow, - KArg1: ?Sized + #scrate::codec::Encode, - KArg2: ?Sized + #scrate::codec::Encode, - { - let key = #as_double_map::key_for(k1, k2); - storage.take(&key).#option_simple_1(|| #fielddefault) - } - - fn mutate( - k1: &KArg1, - k2: &KArg2, - f: F, - storage: &mut S, - ) -> R where - #k1ty: #scrate::rstd::borrow::Borrow, - #k2ty: #scrate::rstd::borrow::Borrow, - KArg1: ?Sized + #scrate::codec::Encode, - KArg2: ?Sized + #scrate::codec::Encode, - F: FnOnce(&mut Self::Query) -> R, - { - let mut val = #as_double_map::get(k1, k2, storage); - - let ret = f(&mut val); - #mutate_impl; - ret - } - } - } - } -} diff --git a/srml/support/procedural/src/storage/instance_trait.rs b/srml/support/procedural/src/storage/instance_trait.rs new file mode 100644 index 0000000000000000000000000000000000000000..1a7add89a4b80024f35f512176db7eba61655fd2 --- /dev/null +++ b/srml/support/procedural/src/storage/instance_trait.rs @@ -0,0 +1,200 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of the trait instance and the instance structures implementing it. +//! (For not instantiable traits there is still the inherent instance implemented). + +use proc_macro2::{TokenStream, Span}; +use quote::quote; +use super::{DeclStorageDefExt, StorageLineTypeDef}; + +const NUMBER_OF_INSTANCE: usize = 16; +const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; +pub(crate) const DEFAULT_INSTANTIABLE_TRAIT_NAME: &str = "__GeneratedInstantiable"; + +// prefix for consts in trait Instance +pub(crate) const PREFIX_FOR: &str = "PREFIX_FOR_"; +pub(crate) const HEAD_KEY_FOR: &str = "HEAD_KEY_FOR_"; + +// Used to generate the const: +// `const $name: &'static str = $value_prefix ++ instance_prefix ++ $value_suffix` +struct InstanceConstDef { + name: syn::Ident, + value_prefix: String, + value_suffix: String, +} + +// Used to generate an instance implementation. +struct InstanceDef { + prefix: String, + instance_struct: syn::Ident, + doc: TokenStream, +} + +pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + let mut impls = TokenStream::new(); + + let mut const_defs = vec![]; + + for line in def.storage_lines.iter() { + let storage_prefix = format!("{} {}", def.crate_name, line.name); + + let const_name = syn::Ident::new( + &format!("{}{}", PREFIX_FOR, line.name.to_string()), proc_macro2::Span::call_site() + ); + const_defs.push(InstanceConstDef { + name: const_name, + value_prefix: String::new(), + value_suffix: storage_prefix.clone(), + }); + + if let StorageLineTypeDef::LinkedMap(_) = line.storage_type { + let const_name = syn::Ident::new( + &format!("{}{}", HEAD_KEY_FOR, line.name.to_string()), proc_macro2::Span::call_site() + ); + const_defs.push(InstanceConstDef { + name: const_name, + value_prefix: "head of ".into(), + value_suffix: storage_prefix, + }); + } + } + + impls.extend(create_instance_trait(&const_defs, def)); + + // Implementation of instances. + if let Some(module_instance) = &def.module_instance { + let instance_defs = (0..NUMBER_OF_INSTANCE) + .map(|i| { + let name = format!("Instance{}", i); + InstanceDef { + instance_struct: syn::Ident::new(&name, proc_macro2::Span::call_site()), + prefix: name, + doc: quote!(#[doc=r"Module instance"]), + } + }) + .chain( + module_instance.instance_default.as_ref().map(|ident| InstanceDef { + prefix: String::new(), + instance_struct: ident.clone(), + doc: quote!(#[doc=r"Default module instance"]), + }) + ); + + for instance_def in instance_defs { + impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, def)); + } + } + + // The name of the inherently available instance. + let inherent_instance = syn::Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()); + + // Implementation of inherent instance. + if let Some(default_instance) = def.module_instance.as_ref() + .and_then(|i| i.instance_default.as_ref()) + { + impls.extend(quote! { + #[doc(hidden)] + pub type #inherent_instance = #default_instance; + }); + } else { + let instance_def = InstanceDef { + prefix: String::new(), + instance_struct: inherent_instance, + doc: quote!(#[doc(hidden)]), + }; + impls.extend(create_and_impl_instance_struct(scrate, &instance_def, &const_defs, def)); + } + + impls +} + +fn create_instance_trait( + const_defs: &[InstanceConstDef], + def: &DeclStorageDefExt, +) -> TokenStream { + let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) + .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); + + let mut const_impls = TokenStream::new(); + for const_def in const_defs { + let const_name = &const_def.name; + const_impls.extend(quote! { + const #const_name: &'static str; + }); + } + + let optional_hide = if def.module_instance.is_some() { + quote!() + } else { + quote!(#[doc(hidden)]) + }; + + quote! { + /// Tag a type as an instance of a module. + /// + /// Defines storage prefixes, they must be unique. + #optional_hide + pub trait #instance_trait: 'static { + /// The prefix used by any storage entry of an instance. + const PREFIX: &'static str; + #const_impls + } + } +} + +fn create_and_impl_instance_struct( + scrate: &TokenStream, + instance_def: &InstanceDef, + const_defs: &[InstanceConstDef], + def: &DeclStorageDefExt, +) -> TokenStream { + let mut const_impls = TokenStream::new(); + + for const_def in const_defs { + let const_value = format!( + "{}{}{}", const_def.value_prefix, instance_def.prefix, const_def.value_suffix + ); + let const_name = &const_def.name; + + const_impls.extend(quote! { + const #const_name: &'static str = #const_value; + }); + } + + let instance_trait = def.module_instance.as_ref().map(|i| i.instance_trait.clone()) + .unwrap_or_else(|| syn::Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); + + let instance_struct = &instance_def.instance_struct; + let prefix = format!("{}{}", instance_def.prefix, def.crate_name.to_string()); + let doc = &instance_def.doc; + + quote! { + // Those trait are derived because of wrong bounds for generics + #[derive( + Clone, Eq, PartialEq, + #scrate::codec::Encode, + #scrate::codec::Decode, + #scrate::RuntimeDebug, + )] + #doc + pub struct #instance_struct; + impl #instance_trait for #instance_struct { + const PREFIX: &'static str = #prefix; + #const_impls + } + } +} diff --git a/srml/support/procedural/src/storage/metadata.rs b/srml/support/procedural/src/storage/metadata.rs new file mode 100644 index 0000000000000000000000000000000000000000..f81da84c74c6694604e325453802d0a24129200a --- /dev/null +++ b/srml/support/procedural/src/storage/metadata.rs @@ -0,0 +1,230 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of `storage_metadata` on module structure, used by construct_runtime. + +use srml_support_procedural_tools::clean_type_string; +use proc_macro2::TokenStream; +use quote::quote; +use super::{DeclStorageDefExt, StorageLineDefExt, StorageLineTypeDef}; + +fn storage_line_metadata_type(scrate: &TokenStream, line: &StorageLineDefExt) -> TokenStream { + let value_type = &line.value_type; + let value_type = clean_type_string("e!( #value_type ).to_string()); + match &line.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!{ + #scrate::metadata::StorageEntryType::Plain( + #scrate::metadata::DecodeDifferent::Encode(#value_type), + ) + } + }, + StorageLineTypeDef::Map(map) => { + let hasher = map.hasher.into_metadata(); + let key = &map.key; + let key = clean_type_string("e!(#key).to_string()); + quote!{ + #scrate::metadata::StorageEntryType::Map { + hasher: #scrate::metadata::#hasher, + key: #scrate::metadata::DecodeDifferent::Encode(#key), + value: #scrate::metadata::DecodeDifferent::Encode(#value_type), + is_linked: false, + } + } + }, + StorageLineTypeDef::LinkedMap(map) => { + let hasher = map.hasher.into_metadata(); + let key = &map.key; + let key = clean_type_string("e!(#key).to_string()); + quote!{ + #scrate::metadata::StorageEntryType::Map { + hasher: #scrate::metadata::#hasher, + key: #scrate::metadata::DecodeDifferent::Encode(#key), + value: #scrate::metadata::DecodeDifferent::Encode(#value_type), + is_linked: true, + } + } + }, + StorageLineTypeDef::DoubleMap(map) => { + let hasher1 = map.hasher1.into_metadata(); + let hasher2 = map.hasher2.into_metadata(); + let key1 = &map.key1; + let key1 = clean_type_string("e!(#key1).to_string()); + let key2 = &map.key2; + let key2 = clean_type_string("e!(#key2).to_string()); + quote!{ + #scrate::metadata::StorageEntryType::DoubleMap { + hasher: #scrate::metadata::#hasher1, + key1: #scrate::metadata::DecodeDifferent::Encode(#key1), + key2: #scrate::metadata::DecodeDifferent::Encode(#key2), + value: #scrate::metadata::DecodeDifferent::Encode(#value_type), + key2_hasher: #scrate::metadata::#hasher2, + } + } + }, + } +} + +fn default_byte_getter( + scrate: &TokenStream, + line: &StorageLineDefExt, + def: &DeclStorageDefExt, +) -> (TokenStream, TokenStream) { + let default = line.default_value.as_ref().map(|d| quote!( #d )) + .unwrap_or_else(|| quote!( Default::default() )); + + let str_name = line.name.to_string(); + let struct_name = syn::Ident::new(&("__GetByteStruct".to_string() + &str_name), line.name.span()); + let cache_name = syn::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), line.name.span()); + + let runtime_generic = &def.module_runtime_generic; + let runtime_trait = &def.module_runtime_trait; + let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default; + let optional_instance_bound = &def.optional_instance_bound; + let optional_instance = &def.optional_instance; + let optional_comma_instance = optional_instance.as_ref().map(|i| quote!(, #i)); + let where_clause = &def.where_clause; + + let query_type = &line.query_type; + + let struct_def = quote! { + #[doc(hidden)] + pub struct #struct_name< + #runtime_generic, #optional_instance_bound_optional_default + >(pub #scrate::rstd::marker::PhantomData<(#runtime_generic #optional_comma_instance)>); + + #[cfg(feature = "std")] + #[allow(non_upper_case_globals)] + static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec> = + #scrate::once_cell::sync::OnceCell::new(); + + #[cfg(feature = "std")] + impl<#runtime_generic: #runtime_trait, #optional_instance_bound> + #scrate::metadata::DefaultByte + for #struct_name<#runtime_generic, #optional_instance> + #where_clause + { + fn default_byte(&self) -> #scrate::rstd::vec::Vec { + use #scrate::codec::Encode; + #cache_name.get_or_init(|| { + let def_val: #query_type = #default; + <#query_type as Encode>::encode(&def_val) + }).clone() + } + } + + unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Send + for #struct_name<#runtime_generic, #optional_instance> #where_clause {} + + unsafe impl<#runtime_generic: #runtime_trait, #optional_instance_bound> Sync + for #struct_name<#runtime_generic, #optional_instance> #where_clause {} + + #[cfg(not(feature = "std"))] + impl<#runtime_generic: #runtime_trait, #optional_instance_bound> + #scrate::metadata::DefaultByte + for #struct_name<#runtime_generic, #optional_instance> + #where_clause + { + fn default_byte(&self) -> #scrate::rstd::vec::Vec { + use #scrate::codec::Encode; + let def_val: #query_type = #default; + <#query_type as Encode>::encode(&def_val) + } + } + }; + let struct_instance = quote!( + #struct_name::<#runtime_generic, #optional_instance>(#scrate::rstd::marker::PhantomData) + ); + + (struct_def, struct_instance) +} + +pub fn impl_metadata(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + let mut entries = TokenStream::new(); + let mut default_byte_getter_struct_defs = TokenStream::new(); + + for line in def.storage_lines.iter() { + let str_name = line.name.to_string(); + + let modifier = if line.is_option { + quote!(#scrate::metadata::StorageEntryModifier::Optional) + } else { + quote!(#scrate::metadata::StorageEntryModifier::Default) + }; + + let ty = storage_line_metadata_type(scrate, line); + + let ( + default_byte_getter_struct_def, + default_byte_getter_struct_instance, + ) = default_byte_getter(scrate, line, def); + + let mut docs = TokenStream::new(); + for attr in line.attrs.iter().filter_map(|v| v.parse_meta().ok()) { + if let syn::Meta::NameValue(meta) = attr { + if meta.path.is_ident("doc") { + let lit = meta.lit; + docs.extend(quote!(#lit,)); + } + } + } + + let entry = quote! { + #scrate::metadata::StorageEntryMetadata { + name: #scrate::metadata::DecodeDifferent::Encode(#str_name), + modifier: #modifier, + ty: #ty, + default: #scrate::metadata::DecodeDifferent::Encode( + #scrate::metadata::DefaultByteGetter(&#default_byte_getter_struct_instance) + ), + documentation: #scrate::metadata::DecodeDifferent::Encode(&[ #docs ]), + }, + }; + + default_byte_getter_struct_defs.extend(default_byte_getter_struct_def); + entries.extend(entry); + } + + let prefix = if let Some(instance) = &def.module_instance { + let instance_generic = &instance.instance_generic; + quote!(#instance_generic::PREFIX) + } else { + let prefix = def.crate_name.to_string(); + quote!(#prefix) + }; + + let store_metadata = quote!( + #scrate::metadata::StorageMetadata { + prefix: #scrate::metadata::DecodeDifferent::Encode(#prefix), + entries: #scrate::metadata::DecodeDifferent::Encode(&[ #entries ][..]), + } + ); + + let module_struct = &def.module_struct; + let module_impl = &def.module_impl; + let where_clause = &def.where_clause; + + quote!( + #default_byte_getter_struct_defs + + impl#module_impl #module_struct #where_clause { + #[doc(hidden)] + pub fn storage_metadata() -> #scrate::metadata::StorageMetadata { + #store_metadata + } + } + ) +} diff --git a/srml/support/procedural/src/storage/mod.rs b/srml/support/procedural/src/storage/mod.rs index 4253206f44da064d5903362c3ed72aedbb51a0c7..bdbef49d2776ab80a3021fb9bdde9440d8f0d99e 100644 --- a/srml/support/procedural/src/storage/mod.rs +++ b/srml/support/procedural/src/storage/mod.rs @@ -14,191 +14,358 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -// tag::description[] -//! `decl_storage` macro -// end::description[] +//! `decl_storage` input definition and expansion. + +mod storage_struct; +mod parse; +mod store_trait; +mod getters; +mod metadata; +mod instance_trait; +mod genesis_config; -use srml_support_procedural_tools::{ToTokens, Parse, syn_ext as ext}; -use syn::{Ident, Token}; -use proc_macro2::TokenStream as TokenStream2; use quote::quote; +use srml_support_procedural_tools::{ + generate_crate_access, generate_hidden_includes, syn_ext as ext +}; -mod impls; - -pub mod transformation; - -mod keyword { - syn::custom_keyword!(hiddencrate); - syn::custom_keyword!(add_extra_genesis); - syn::custom_keyword!(extra_genesis_skip_phantom_data_field); - syn::custom_keyword!(config); - syn::custom_keyword!(build); - syn::custom_keyword!(get); - syn::custom_keyword!(map); - syn::custom_keyword!(linked_map); - syn::custom_keyword!(double_map); - syn::custom_keyword!(blake2_256); - syn::custom_keyword!(blake2_128); - syn::custom_keyword!(twox_256); - syn::custom_keyword!(twox_128); - syn::custom_keyword!(twox_64_concat); - syn::custom_keyword!(hasher); +/// All informations contained in input of decl_storage +pub struct DeclStorageDef { + /// Name of the module used to import hidden imports. + hidden_crate: Option, + /// Visibility of store trait. + visibility: syn::Visibility, + /// Name of store trait: usually `Store`. + store_trait: syn::Ident, + /// Module name used by construct_runtime: usually `Module`. + module_name: syn::Ident, + /// Usually `T`. + module_runtime_generic: syn::Ident, + /// Usually `Trait` + module_runtime_trait: syn::Path, + /// For instantiable module: usually `I: Instance=DefaultInstance`. + module_instance: Option, + /// Where claused used to constrain T and I even more. + where_clause: Option, + /// The extra build function used to build storage at genesis. + extra_genesis_build: Option, + /// The extra genesis config fields. + extra_genesis_config_lines: Vec, + /// Definition of storages. + storage_lines: Vec, + /// Name of the crate, used for storage prefixes. + crate_name: syn::Ident, } -/// Parsing usage only -#[derive(Parse, ToTokens, Debug)] -struct StorageDefinition { - pub hidden_crate: ext::Opt, - pub visibility: syn::Visibility, - pub trait_token: Token![trait], - pub ident: Ident, - pub for_token: Token![for], - pub module_ident: Ident, - pub mod_lt_token: Token![<], - pub mod_param: syn::GenericParam, - pub mod_instance_param_token: Option, - pub mod_instance: Option, - pub mod_instantiable_token: Option, - pub mod_instantiable: Option, - pub mod_default_instance_token: Option, - pub mod_default_instance: Option, - pub mod_gt_token: Token![>], - pub as_token: Token![as], - pub crate_ident: Ident, - pub where_clause: Option, - pub content: ext::Braces>, - pub extra_genesis: ext::Opt, +impl syn::parse::Parse for DeclStorageDef { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + parse::parse(input) + } } -#[derive(Parse, ToTokens, Debug)] -struct SpecificHiddenCrate { - pub keyword: keyword::hiddencrate, - pub ident: ext::Parens, +/// Extended version of `DeclStorageDef` with useful precomputed value. +pub struct DeclStorageDefExt { + /// Name of the module used to import hidden imports. + hidden_crate: Option, + /// Visibility of store trait. + visibility: syn::Visibility, + /// Name of store trait: usually `Store`. + store_trait: syn::Ident, + /// Module name used by construct_runtime: usually `Module`. + #[allow(unused)] + module_name: syn::Ident, + /// Usually `T`. + module_runtime_generic: syn::Ident, + /// Usually `Trait`. + module_runtime_trait: syn::Path, + /// For instantiable module: usually `I: Instance=DefaultInstance`. + module_instance: Option, + /// Where claused used to constrain T and I even more. + where_clause: Option, + /// The extra build function used to build storage at genesis. + extra_genesis_build: Option, + /// The extra genesis config fields. + extra_genesis_config_lines: Vec, + /// Definition of storages. + storage_lines: Vec, + /// Name of the crate, used for storage prefixes. + crate_name: syn::Ident, + /// Full struct expansion: `Module`. + module_struct: proc_macro2::TokenStream, + /// Impl block for module: ``. + module_impl: proc_macro2::TokenStream, + /// For instantiable: `I`. + optional_instance: Option, + /// For instantiable: `I: Instance`. + optional_instance_bound: Option, + /// For instantiable: `I: Instance = DefaultInstance`. + optional_instance_bound_optional_default: Option, } -#[derive(Parse, ToTokens, Debug)] -struct AddExtraGenesis { - pub extragenesis_keyword: keyword::add_extra_genesis, - pub content: ext::Braces, -} +impl From for DeclStorageDefExt { + fn from(mut def: DeclStorageDef) -> Self { + let storage_lines = def.storage_lines.drain(..).collect::>(); + let storage_lines = storage_lines.into_iter() + .map(|line| StorageLineDefExt::from_def(line, &def)) + .collect(); + + let ( + optional_instance, + optional_instance_bound, + optional_instance_bound_optional_default, + ) = if let Some(instance) = def.module_instance.as_ref() { + let instance_generic = &instance.instance_generic; + let instance_trait= &instance.instance_trait; + let optional_equal_instance_default = instance.instance_default.as_ref() + .map(|d| quote!( = #d )); + ( + Some(quote!(#instance_generic)), + Some(quote!(#instance_generic: #instance_trait)), + Some(quote!(#instance_generic: #instance_trait #optional_equal_instance_default)), + ) + } else { + (None, None, None) + }; + + let module_runtime_generic = &def.module_runtime_generic; + let module_runtime_trait = &def.module_runtime_trait; + let module_name = &def.module_name; -#[derive(Parse, ToTokens, Debug)] -struct AddExtraGenesisContent { - pub lines: ext::Punctuated, + let module_struct = quote!( + #module_name<#module_runtime_generic, #optional_instance> + ); + + let module_impl = quote!( + <#module_runtime_generic: #module_runtime_trait + 'static, #optional_instance_bound> + ); + + Self { + hidden_crate: def.hidden_crate, + visibility: def.visibility, + store_trait: def.store_trait, + module_name: def.module_name, + module_runtime_generic: def.module_runtime_generic, + module_runtime_trait: def.module_runtime_trait, + module_instance: def.module_instance, + where_clause: def.where_clause, + extra_genesis_build: def.extra_genesis_build, + extra_genesis_config_lines: def.extra_genesis_config_lines, + crate_name: def.crate_name, + storage_lines, + module_struct, + module_impl, + optional_instance, + optional_instance_bound, + optional_instance_bound_optional_default, + } + } } -#[derive(Parse, ToTokens, Debug)] -enum AddExtraGenesisLineEnum { - AddExtraGenesisLine(AddExtraGenesisLine), - AddExtraGenesisBuild(DeclStorageBuild), +/// Usually `I: Instance=DefaultInstance`. +pub struct ModuleInstanceDef { + /// Usually: `I`. + instance_generic: syn::Ident, + /// Usually: `Instance`. + instance_trait: syn::Ident, + /// Usually: `DefaultInstance`. + instance_default: Option, } -#[derive(Parse, ToTokens, Debug)] -struct AddExtraGenesisLine { - pub attrs: ext::OuterAttributes, - pub config_keyword: keyword::config, - pub extra_field: ext::Parens, - pub coldot_token: Token![:], - pub extra_type: syn::Type, - pub default_value: ext::Opt, +pub struct StorageLineDef { + attrs: Vec, + /// Visibility of the storage struct. + visibility: syn::Visibility, + name: syn::Ident, + /// The name of getter function to be implemented on Module struct. + getter: Option, + /// The name of the field to be used in genesis config if any. + config: Option, + /// The build function of the storage if any. + build: Option, + /// Default value of genesis config field and also for storage when no value available. + default_value: Option, + storage_type: StorageLineTypeDef, } -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageLine { - // attrs (main use case is doc) - pub attrs: ext::OuterAttributes, - // visibility (no need to make optional - pub visibility: syn::Visibility, - // name - pub name: Ident, - pub getter: ext::Opt, - pub config: ext::Opt, - pub build: ext::Opt, - pub coldot_token: Token![:], - pub storage_type: DeclStorageType, - pub default_value: ext::Opt, +pub struct StorageLineDefExt { + #[allow(unused)] + attrs: Vec, + /// Visibility of the storage struct. + visibility: syn::Visibility, + name: syn::Ident, + /// The name of getter function to be implemented on Module struct. + getter: Option, + /// The name of the field to be used in genesis config if any. + config: Option, + /// The build function of the storage if any. + build: Option, + /// Default value of genesis config field and also for storage when no value available. + default_value: Option, + storage_type: StorageLineTypeDef, + doc_attrs: Vec, + /// Either the type stored in storage or wrapped in an Option. + query_type: syn::Type, + /// The type stored in storage. + value_type: syn::Type, + /// Full struct, for example: `StorageName`. + storage_struct: proc_macro2::TokenStream, + /// If storage is generic over runtime then `T`. + optional_storage_runtime_comma: Option, + /// If storage is generic over runtime then `T: Trait`. + optional_storage_runtime_bound_comma: Option, + /// The where clause to use to constrain generics if storage is generic over runtime. + optional_storage_where_clause: Option, + /// Full trait, for example: `storage::StorageMap`. + storage_trait: proc_macro2::TokenStream, + /// Full trait, for example: `storage::generator::StorageMap`. + storage_generator_trait: proc_macro2::TokenStream, + /// Weither the storage is generic. + is_generic: bool, + /// Weither the storage value is an option. + is_option: bool, } +impl StorageLineDefExt { + fn from_def(storage_def: StorageLineDef, def: &DeclStorageDef) -> Self { + let is_generic = match &storage_def.storage_type { + StorageLineTypeDef::Simple(value) => { + ext::type_contains_ident(&value, &def.module_runtime_generic) + }, + StorageLineTypeDef::Map(map) => { + ext::type_contains_ident(&map.key, &def.module_runtime_generic) + || ext::type_contains_ident(&map.value, &def.module_runtime_generic) + } + StorageLineTypeDef::LinkedMap(map) => { + ext::type_contains_ident(&map.key, &def.module_runtime_generic) + || ext::type_contains_ident(&map.value, &def.module_runtime_generic) + } + StorageLineTypeDef::DoubleMap(map) => { + ext::type_contains_ident(&map.key1, &def.module_runtime_generic) + || ext::type_contains_ident(&map.key2, &def.module_runtime_generic) + || ext::type_contains_ident(&map.value, &def.module_runtime_generic) + } + }; -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageGetter { - pub getter_keyword: keyword::get, - pub getfn: ext::Parens, -} + let query_type = match &storage_def.storage_type { + StorageLineTypeDef::Simple(value) => value.clone(), + StorageLineTypeDef::Map(map) => map.value.clone(), + StorageLineTypeDef::LinkedMap(map) => map.value.clone(), + StorageLineTypeDef::DoubleMap(map) => map.value.clone(), + }; + let is_option = ext::extract_type_option(&query_type).is_some(); + let value_type = ext::extract_type_option(&query_type).unwrap_or(query_type.clone()); -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageConfig { - pub config_keyword: keyword::config, - pub expr: ext::Parens>, -} + let module_runtime_generic = &def.module_runtime_generic; + let module_runtime_trait = &def.module_runtime_trait; + let optional_storage_runtime_comma = if is_generic { + Some(quote!( #module_runtime_generic, )) + } else { + None + }; + let optional_storage_runtime_bound_comma = if is_generic { + Some(quote!( #module_runtime_generic: #module_runtime_trait, )) + } else { + None + }; -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageBuild { - pub build_keyword: keyword::build, - pub expr: ext::Parens, -} + let storage_name = &storage_def.name; + let optional_instance_generic = def.module_instance.as_ref().map(|i| { + let instance_generic = &i.instance_generic; + quote!( #instance_generic ) + }); + let storage_struct = quote!( + #storage_name<#optional_storage_runtime_comma #optional_instance_generic> + ); -#[derive(Parse, ToTokens, Debug)] -enum DeclStorageType { - Map(DeclStorageMap), - LinkedMap(DeclStorageLinkedMap), - DoubleMap(DeclStorageDoubleMap), - Simple(syn::Type), + let optional_storage_where_clause = if is_generic { + def.where_clause.as_ref().map(|w| quote!( #w )) + } else { + None + }; + + let storage_trait_trunkated = match &storage_def.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!( StorageValue<#value_type> ) + }, + StorageLineTypeDef::Map(map) => { + let key = &map.key; + quote!( StorageMap<#key, #value_type> ) + }, + StorageLineTypeDef::LinkedMap(map) => { + let key = &map.key; + quote!( StorageLinkedMap<#key, #value_type> ) + }, + StorageLineTypeDef::DoubleMap(map) => { + let key1 = &map.key1; + let key2 = &map.key2; + quote!( StorageDoubleMap<#key1, #key2, #value_type> ) + }, + }; + + let storage_trait = quote!( storage::#storage_trait_trunkated ); + let storage_generator_trait = quote!( storage::generator::#storage_trait_trunkated ); + + let doc_attrs = storage_def.attrs.iter() + .filter_map(|a| a.parse_meta().ok()) + .filter(|m| m.path().is_ident("doc")) + .collect(); + + Self { + attrs: storage_def.attrs, + visibility: storage_def.visibility, + name: storage_def.name, + getter: storage_def.getter, + config: storage_def.config, + build: storage_def.build, + default_value: storage_def.default_value, + storage_type: storage_def.storage_type, + doc_attrs, + query_type, + value_type, + storage_struct, + optional_storage_runtime_comma, + optional_storage_runtime_bound_comma, + optional_storage_where_clause, + storage_trait, + storage_generator_trait, + is_generic, + is_option, + } + } } -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageMap { - pub map_keyword: keyword::map, - pub hasher: ext::Opt, - pub key: syn::Type, - pub ass_keyword: Token![=>], - pub value: syn::Type, +pub enum StorageLineTypeDef { + Map(MapDef), + LinkedMap(MapDef), + DoubleMap(DoubleMapDef), + Simple(syn::Type), } -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageLinkedMap { - pub map_keyword: keyword::linked_map, - pub hasher: ext::Opt, +pub struct MapDef { + pub hasher: HasherKind, pub key: syn::Type, - pub ass_keyword: Token![=>], + /// This is the query value not the inner value used in storage trait implementation. pub value: syn::Type, } -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageDoubleMap { - pub map_keyword: keyword::double_map, - pub hasher: ext::Opt, +pub struct DoubleMapDef { + pub hasher1: HasherKind, + pub hasher2: HasherKind, pub key1: syn::Type, - pub comma_keyword: Token![,], - pub key2_hasher: Hasher, - pub key2: ext::Parens, - pub ass_keyword: Token![=>], + pub key2: syn::Type, + /// This is the query value not the inner value used in storage trait implementation. pub value: syn::Type, } -#[derive(Parse, ToTokens, Debug)] -enum Hasher { - Blake2_256(keyword::blake2_256), - Blake2_128(keyword::blake2_128), - Twox256(keyword::twox_256), - Twox128(keyword::twox_128), - Twox64Concat(keyword::twox_64_concat), -} - -#[derive(Parse, ToTokens, Debug)] -struct DeclStorageDefault { - pub equal_token: Token![=], - pub expr: syn::Expr, -} - -#[derive(Parse, ToTokens, Debug)] -struct SetHasher { - pub hasher_keyword: keyword::hasher, - pub inner: ext::Parens, +pub struct ExtraGenesisLineDef { + attrs: Vec, + name: syn::Ident, + typ: syn::Type, + default: Option, } #[derive(Debug, Clone)] -enum HasherKind { +pub enum HasherKind { Blake2_256, Blake2_128, Twox256, @@ -206,26 +373,8 @@ enum HasherKind { Twox64Concat, } -impl From<&SetHasher> for HasherKind { - fn from(set_hasher: &SetHasher) -> Self { - (&set_hasher.inner.content).into() - } -} - -impl From<&Hasher> for HasherKind { - fn from(hasher: &Hasher) -> Self { - match hasher { - Hasher::Blake2_256(_) => HasherKind::Blake2_256, - Hasher::Blake2_128(_) => HasherKind::Blake2_128, - Hasher::Twox256(_) => HasherKind::Twox256, - Hasher::Twox128(_) => HasherKind::Twox128, - Hasher::Twox64Concat(_) => HasherKind::Twox64Concat, - } - } -} - impl HasherKind { - fn into_storage_hasher_struct(&self) -> TokenStream2 { + fn to_storage_hasher_struct(&self) -> proc_macro2::TokenStream { match self { HasherKind::Blake2_256 => quote!( Blake2_256 ), HasherKind::Blake2_128 => quote!( Blake2_128 ), @@ -235,7 +384,7 @@ impl HasherKind { } } - fn into_metadata(&self) -> TokenStream2 { + fn into_metadata(&self) -> proc_macro2::TokenStream { match self { HasherKind::Blake2_256 => quote!( StorageHasher::Blake2_256 ), HasherKind::Blake2_128 => quote!( StorageHasher::Blake2_128 ), @@ -245,3 +394,39 @@ impl HasherKind { } } } + +/// Full implementation of decl_storage. +pub fn decl_storage_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let def = syn::parse_macro_input!(input as DeclStorageDef); + let def_ext = DeclStorageDefExt::from(def); + + let hidden_crate_name = def_ext.hidden_crate.as_ref().map(|i| i.to_string()) + .unwrap_or_else(|| "decl_storage".to_string()); + + let scrate = generate_crate_access(&hidden_crate_name, "srml-support"); + let scrate_decl = generate_hidden_includes(&hidden_crate_name, "srml-support"); + + let store_trait = store_trait::decl_and_impl(&def_ext); + let getters = getters::impl_getters(&scrate, &def_ext); + let metadata = metadata::impl_metadata(&scrate, &def_ext); + let instance_trait = instance_trait::decl_and_impl(&scrate, &def_ext); + let genesis_config = genesis_config::genesis_config_and_build_storage(&scrate, &def_ext); + let storage_struct = storage_struct::decl_and_impl(&scrate, &def_ext); + + quote!( + use #scrate::{ + StorageValue as _, + StorageMap as _, + StorageLinkedMap as _, + StorageDoubleMap as _ + }; + + #scrate_decl + #store_trait + #getters + #metadata + #instance_trait + #genesis_config + #storage_struct + ).into() +} diff --git a/srml/support/procedural/src/storage/parse.rs b/srml/support/procedural/src/storage/parse.rs new file mode 100644 index 0000000000000000000000000000000000000000..e428fbe24f2951483636f213fc95188e7031bd4e --- /dev/null +++ b/srml/support/procedural/src/storage/parse.rs @@ -0,0 +1,404 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Parsing of decl_storage input. + +use srml_support_procedural_tools::{ToTokens, Parse, syn_ext as ext}; +use syn::{Ident, Token, spanned::Spanned}; + +mod keyword { + syn::custom_keyword!(hiddencrate); + syn::custom_keyword!(add_extra_genesis); + syn::custom_keyword!(extra_genesis_skip_phantom_data_field); + syn::custom_keyword!(config); + syn::custom_keyword!(build); + syn::custom_keyword!(get); + syn::custom_keyword!(map); + syn::custom_keyword!(linked_map); + syn::custom_keyword!(double_map); + syn::custom_keyword!(blake2_256); + syn::custom_keyword!(blake2_128); + syn::custom_keyword!(twox_256); + syn::custom_keyword!(twox_128); + syn::custom_keyword!(twox_64_concat); + syn::custom_keyword!(hasher); +} + +/// Parsing usage only +#[derive(Parse, ToTokens, Debug)] +struct StorageDefinition { + pub hidden_crate: ext::Opt, + pub visibility: syn::Visibility, + pub trait_token: Token![trait], + pub ident: Ident, + pub for_token: Token![for], + pub module_ident: Ident, + pub mod_lt_token: Token![<], + pub mod_param_generic: syn::Ident, + pub mod_param_bound_token: Option, + pub mod_param_bound: syn::Path, + pub mod_instance_param_token: Option, + pub mod_instance: Option, + pub mod_instantiable_token: Option, + pub mod_instantiable: Option, + pub mod_default_instance_token: Option, + pub mod_default_instance: Option, + pub mod_gt_token: Token![>], + pub as_token: Token![as], + pub crate_ident: Ident, + pub where_clause: Option, + pub content: ext::Braces>, + pub extra_genesis: ext::Opt, +} + +#[derive(Parse, ToTokens, Debug)] +struct SpecificHiddenCrate { + pub keyword: keyword::hiddencrate, + pub ident: ext::Parens, +} + +#[derive(Parse, ToTokens, Debug)] +struct AddExtraGenesis { + pub extragenesis_keyword: keyword::add_extra_genesis, + pub content: ext::Braces, +} + +#[derive(Parse, ToTokens, Debug)] +struct AddExtraGenesisContent { + pub lines: ext::Punctuated, +} + +#[derive(Parse, ToTokens, Debug)] +enum AddExtraGenesisLineEnum { + AddExtraGenesisLine(AddExtraGenesisLine), + AddExtraGenesisBuild(DeclStorageBuild), +} + +#[derive(Parse, ToTokens, Debug)] +struct AddExtraGenesisLine { + pub attrs: ext::OuterAttributes, + pub config_keyword: keyword::config, + pub extra_field: ext::Parens, + pub coldot_token: Token![:], + pub extra_type: syn::Type, + pub default_value: ext::Opt, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageLine { + // attrs (main use case is doc) + pub attrs: ext::OuterAttributes, + // visibility (no need to make optional + pub visibility: syn::Visibility, + // name + pub name: Ident, + pub getter: ext::Opt, + pub config: ext::Opt, + pub build: ext::Opt, + pub coldot_token: Token![:], + pub storage_type: DeclStorageType, + pub default_value: ext::Opt, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageGetterBody { + fn_keyword: Option, + ident: Ident, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageGetter { + pub getter_keyword: keyword::get, + pub getfn: ext::Parens, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageConfig { + pub config_keyword: keyword::config, + pub expr: ext::Parens>, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageBuild { + pub build_keyword: keyword::build, + pub expr: ext::Parens, +} + +#[derive(Parse, ToTokens, Debug)] +enum DeclStorageType { + Map(DeclStorageMap), + LinkedMap(DeclStorageLinkedMap), + DoubleMap(DeclStorageDoubleMap), + Simple(syn::Type), +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageMap { + pub map_keyword: keyword::map, + pub hasher: ext::Opt, + pub key: syn::Type, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageLinkedMap { + pub map_keyword: keyword::linked_map, + pub hasher: ext::Opt, + pub key: syn::Type, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageDoubleMap { + pub map_keyword: keyword::double_map, + pub hasher: ext::Opt, + pub key1: syn::Type, + pub comma_keyword: Token![,], + pub key2_hasher: Hasher, + pub key2: ext::Parens, + pub ass_keyword: Token![=>], + pub value: syn::Type, +} + +#[derive(Parse, ToTokens, Debug)] +enum Hasher { + Blake2_256(keyword::blake2_256), + Blake2_128(keyword::blake2_128), + Twox256(keyword::twox_256), + Twox128(keyword::twox_128), + Twox64Concat(keyword::twox_64_concat), +} + +#[derive(Parse, ToTokens, Debug)] +struct DeclStorageDefault { + pub equal_token: Token![=], + pub expr: syn::Expr, +} + +#[derive(Parse, ToTokens, Debug)] +struct SetHasher { + pub hasher_keyword: keyword::hasher, + pub inner: ext::Parens, +} + +impl From for super::HasherKind { + fn from(set_hasher: SetHasher) -> Self { + set_hasher.inner.content.into() + } +} + +impl From for super::HasherKind { + fn from(hasher: Hasher) -> Self { + match hasher { + Hasher::Blake2_256(_) => super::HasherKind::Blake2_256, + Hasher::Blake2_128(_) => super::HasherKind::Blake2_128, + Hasher::Twox256(_) => super::HasherKind::Twox256, + Hasher::Twox128(_) => super::HasherKind::Twox128, + Hasher::Twox64Concat(_) => super::HasherKind::Twox64Concat, + } + } +} + +fn get_module_instance( + instance: Option, + instantiable: Option, + default_instance: Option, +) -> syn::Result> { + let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance"; + + match (instance, instantiable, default_instance) { + (Some(instance), Some(instantiable), default_instance) => { + Ok(Some(super::ModuleInstanceDef { + instance_generic: instance, + instance_trait: instantiable, + instance_default: default_instance, + })) + }, + (None, None, None) => Ok(None), + (Some(instance), None, _) => Err( + syn::Error::new( + instance.span(), + format!( + "Expect instantiable trait bound for instance: {}. {}", + instance, + right_syntax, + ) + ) + ), + (None, Some(instantiable), _) => Err( + syn::Error::new( + instantiable.span(), + format!( + "Expect instance generic for bound instantiable: {}. {}", + instantiable, + right_syntax, + ) + ) + ), + (None, _, Some(default_instance)) => Err( + syn::Error::new( + default_instance.span(), + format!( + "Expect instance generic for default instance: {}. {}", + default_instance, + right_syntax, + ) + ) + ), + } +} + +pub fn parse(input: syn::parse::ParseStream) -> syn::Result { + use syn::parse::Parse; + + let def = StorageDefinition::parse(input)?; + + let module_instance = get_module_instance( + def.mod_instance, + def.mod_instantiable, + def.mod_default_instance, + )?; + + let mut extra_genesis_config_lines = vec![]; + let mut extra_genesis_build = None; + + for line in def.extra_genesis.inner.into_iter() + .flat_map(|o| o.content.content.lines.inner.into_iter()) + { + match line { + AddExtraGenesisLineEnum::AddExtraGenesisLine(def) => { + extra_genesis_config_lines.push(super::ExtraGenesisLineDef{ + attrs: def.attrs.inner, + name: def.extra_field.content, + typ: def.extra_type, + default: def.default_value.inner.map(|o| o.expr), + }); + } + AddExtraGenesisLineEnum::AddExtraGenesisBuild(def) => { + if extra_genesis_build.is_some() { + return Err(syn::Error::new( + def.span(), + "Only one build expression allowed for extra genesis" + )) + } + + extra_genesis_build = Some(def.expr.content); + } + } + } + + let storage_lines = parse_storage_line_defs(def.content.content.inner.into_iter())?; + + Ok(super::DeclStorageDef { + hidden_crate: def.hidden_crate.inner.map(|i| i.ident.content), + visibility: def.visibility, + module_name: def.module_ident, + store_trait: def.ident, + module_runtime_generic: def.mod_param_generic, + module_runtime_trait: def.mod_param_bound, + where_clause: def.where_clause, + crate_name: def.crate_ident, + module_instance, + extra_genesis_build, + extra_genesis_config_lines, + storage_lines, + }) +} + +/// Parse the `DeclStorageLine` into `StorageLineDef`. +fn parse_storage_line_defs( + defs: impl Iterator, +) -> syn::Result> { + let mut storage_lines = Vec::::new(); + + for line in defs { + let getter = line.getter.inner.map(|o| o.getfn.content.ident); + let config = if let Some(config) = line.config.inner { + if let Some(ident) = config.expr.content { + Some(ident) + } else if let Some(ref ident) = getter { + Some(ident.clone()) + } else { + return Err(syn::Error::new( + config.span(), + "Invalid storage definition, couldn't find config identifier: storage must \ + either have a get identifier `get(fn ident)` or a defined config identifier \ + `config(ident)`", + )) + } + } else { + None + }; + + if let Some(ref config) = config { + storage_lines.iter().filter_map(|sl| sl.config.as_ref()).try_for_each(|other_config| { + if other_config == config { + Err(syn::Error::new( + config.span(), + "`config()`/`get()` with the same name already defined.", + )) + } else { + Ok(()) + } + })?; + } + + let storage_type = match line.storage_type { + DeclStorageType::Map(map) => super::StorageLineTypeDef::Map( + super::MapDef { + hasher: map.hasher.inner.map(Into::into) + .unwrap_or(super::HasherKind::Blake2_256), + key: map.key, + value: map.value, + } + ), + DeclStorageType::LinkedMap(map) => super::StorageLineTypeDef::LinkedMap( + super::MapDef { + hasher: map.hasher.inner.map(Into::into) + .unwrap_or(super::HasherKind::Blake2_256), + key: map.key, + value: map.value, + } + ), + DeclStorageType::DoubleMap(map) => super::StorageLineTypeDef::DoubleMap( + super::DoubleMapDef { + hasher1: map.hasher.inner.map(Into::into) + .unwrap_or(super::HasherKind::Blake2_256), + hasher2: map.key2_hasher.into(), + key1: map.key1, + key2: map.key2.content, + value: map.value, + } + ), + DeclStorageType::Simple(expr) => super::StorageLineTypeDef::Simple(expr), + }; + + storage_lines.push(super::StorageLineDef { + attrs: line.attrs.inner, + visibility: line.visibility, + name: line.name, + getter, + config, + build: line.build.inner.map(|o| o.expr.content), + default_value: line.default_value.inner.map(|o| o.expr), + storage_type, + }) + } + + Ok(storage_lines) +} diff --git a/srml/support/procedural/src/storage/storage_struct.rs b/srml/support/procedural/src/storage/storage_struct.rs new file mode 100644 index 0000000000000000000000000000000000000000..e195fb53e8a2c3a28e773f6fcb845f0bdc2dffc8 --- /dev/null +++ b/srml/support/procedural/src/storage/storage_struct.rs @@ -0,0 +1,220 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Implementation of storage structures and implementation of storage traits on them. + +use proc_macro2::TokenStream; +use quote::quote; +use super::{ + DeclStorageDefExt, StorageLineTypeDef, + instance_trait::{PREFIX_FOR, HEAD_KEY_FOR}, +}; + +fn from_optional_value_to_query(is_option: bool, default: &Option) -> TokenStream { + let default = default.as_ref().map(|d| quote!( #d )) + .unwrap_or_else(|| quote!( Default::default() )); + + if !is_option { + // raw type case + quote!( v.unwrap_or_else(|| #default ) ) + } else { + // Option<> type case + quote!( v.or_else(|| #default ) ) + } +} + +fn from_query_to_optional_value(is_option: bool) -> TokenStream { + if !is_option { + // raw type case + quote!( Some(v) ) + } else { + // Option<> type case + quote!( v ) + } +} + +pub fn decl_and_impl(scrate: &TokenStream, def: &DeclStorageDefExt) -> TokenStream { + let mut impls = TokenStream::new(); + + for line in &def.storage_lines { + + // Propagate doc attributes. + let attrs = &line.doc_attrs; + + let visibility = &line.visibility; + let optional_storage_runtime_comma = &line.optional_storage_runtime_comma; + let optional_storage_runtime_bound_comma = &line.optional_storage_runtime_bound_comma; + let optional_storage_where_clause = &line.optional_storage_where_clause; + let optional_instance_bound_optional_default = &def.optional_instance_bound_optional_default; + let optional_instance_bound = &def.optional_instance_bound; + let optional_instance = &def.optional_instance; + let name = &line.name; + + let struct_decl = quote!( + #( #[ #attrs ] )* + #visibility struct #name< + #optional_storage_runtime_bound_comma #optional_instance_bound_optional_default + >( + #scrate::rstd::marker::PhantomData< + (#optional_storage_runtime_comma #optional_instance) + > + ) #optional_storage_where_clause; + ); + + let from_query_to_optional_value = from_query_to_optional_value(line.is_option); + let from_optional_value_to_query = + from_optional_value_to_query(line.is_option, &line.default_value); + + let final_prefix = if let Some(instance) = def.module_instance.as_ref() { + let instance = &instance.instance_generic; + let const_name = syn::Ident::new( + &format!("{}{}", PREFIX_FOR, line.name.to_string()), proc_macro2::Span::call_site() + ); + quote!( #instance::#const_name.as_bytes() ) + } else { + let prefix = format!("{} {}", def.crate_name, line.name); + quote!( #prefix.as_bytes() ) + }; + + + let storage_generator_trait = &line.storage_generator_trait; + let storage_struct = &line.storage_struct; + let impl_trait = quote!( #optional_storage_runtime_bound_comma #optional_instance_bound ); + let value_type = &line.value_type; + let query_type = &line.query_type; + + let struct_impl = match &line.storage_type { + StorageLineTypeDef::Simple(_) => { + quote!( + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + + fn unhashed_key() -> &'static [u8] { + #final_prefix + } + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + ) + }, + StorageLineTypeDef::Map(map) => { + let hasher = map.hasher.to_storage_hasher_struct(); + quote!( + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + type Hasher = #scrate::#hasher; + + fn prefix() -> &'static [u8] { + #final_prefix + } + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + ) + }, + StorageLineTypeDef::LinkedMap(map) => { + let hasher = map.hasher.to_storage_hasher_struct(); + + // make sure to use different prefix for head and elements. + let head_key = if let Some(instance) = def.module_instance.as_ref() { + let instance = &instance.instance_generic; + let const_name = syn::Ident::new( + &format!("{}{}", HEAD_KEY_FOR, line.name.to_string()), proc_macro2::Span::call_site() + ); + quote!( #instance::#const_name.as_bytes() ) + } else { + let prefix = format!("head of {} {}", def.crate_name, line.name); + quote!( #prefix.as_bytes() ) + }; + + quote!( + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + type Hasher = #scrate::#hasher; + + fn prefix() -> &'static [u8] { + #final_prefix + } + + fn head_key() -> &'static [u8] { + #head_key + } + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + ) + }, + StorageLineTypeDef::DoubleMap(map) => { + let hasher1 = map.hasher1.to_storage_hasher_struct(); + let hasher2 = map.hasher2.to_storage_hasher_struct(); + quote!( + impl<#impl_trait> #scrate::#storage_generator_trait for #storage_struct + #optional_storage_where_clause + { + type Query = #query_type; + + type Hasher1 = #scrate::#hasher1; + + type Hasher2 = #scrate::#hasher2; + + fn key1_prefix() -> &'static [u8] { + #final_prefix + } + + fn from_optional_value_to_query(v: Option<#value_type>) -> Self::Query { + #from_optional_value_to_query + } + + fn from_query_to_optional_value(v: Self::Query) -> Option<#value_type> { + #from_query_to_optional_value + } + } + ) + } + }; + + impls.extend(quote!( + #struct_decl + #struct_impl + )) + } + + impls +} diff --git a/srml/support/procedural/src/storage/store_trait.rs b/srml/support/procedural/src/storage/store_trait.rs new file mode 100644 index 0000000000000000000000000000000000000000..4c9d96b6bb27a9ba644f5f559df9408a46139eb2 --- /dev/null +++ b/srml/support/procedural/src/storage/store_trait.rs @@ -0,0 +1,54 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Declaration of store trait and implementation on module structure. + +use proc_macro2::TokenStream; +use quote::quote; +use super::DeclStorageDefExt; + +pub fn decl_and_impl(def: &DeclStorageDefExt) -> TokenStream { + let decl_store_items = def.storage_lines.iter() + .map(|sline| &sline.name) + .fold(TokenStream::new(), |mut items, name| { + items.extend(quote!(type #name;)); + items + }); + + let impl_store_items = def.storage_lines.iter() + .fold(TokenStream::new(), |mut items, line| { + let name = &line.name; + let storage_struct = &line.storage_struct; + + items.extend(quote!(type #name = #storage_struct;)); + items + }); + + let visibility = &def.visibility; + let store_trait = &def.store_trait; + let module_struct = &def.module_struct; + let module_impl = &def.module_impl; + let where_clause = &def.where_clause; + + quote!( + #visibility trait #store_trait { + #decl_store_items + } + impl#module_impl #store_trait for #module_struct #where_clause { + #impl_store_items + } + ) +} diff --git a/srml/support/procedural/src/storage/transformation.rs b/srml/support/procedural/src/storage/transformation.rs deleted file mode 100644 index d378907cb1e72fbc2af14dc66beac2340b477af9..0000000000000000000000000000000000000000 --- a/srml/support/procedural/src/storage/transformation.rs +++ /dev/null @@ -1,1232 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! `decl_storage` macro transformation - -use srml_support_procedural_tools::syn_ext as ext; -use srml_support_procedural_tools::{ - generate_crate_access, generate_hidden_includes, clean_type_string -}; - -use proc_macro::TokenStream; -use proc_macro2::{TokenStream as TokenStream2, Span}; - -use syn::{ - Ident, - GenericParam, - WhereClause, - spanned::Spanned, - parse::{ - Error, - Result, - }, - parse_macro_input, -}; -use quote::quote; - -use super::*; - -const NUMBER_OF_INSTANCE: usize = 16; -const DEFAULT_INSTANTIABLE_TRAIT_NAME: &str = "__GeneratedInstantiable"; -const DEFAULT_INSTANCE_NAME: &str = "__GeneratedInstance"; -const INHERENT_INSTANCE_NAME: &str = "__InherentHiddenInstance"; - -// try macro but returning tokenized error -macro_rules! try_tok(( $expre : expr ) => { - match $expre { - Ok(r) => r, - Err (err) => { - return err.to_compile_error().into() - } - } -}); - -pub fn decl_storage_impl(input: TokenStream) -> TokenStream { - let def = parse_macro_input!(input as StorageDefinition); - - let StorageDefinition { - hidden_crate, - visibility, - ident: storetype, - module_ident, - mod_param: strait, - mod_instance, - mod_instantiable, - mod_default_instance, - crate_ident: cratename, - content: ext::Braces { content: storage_lines, ..}, - extra_genesis, - where_clause, - .. - } = def; - - let instance_opts = match get_instance_opts( - mod_instance, - mod_instantiable, - mod_default_instance - ) { - Ok(opts) => opts, - Err(err) => return err.to_compile_error().into(), - }; - - let hidden_crate_name = hidden_crate.inner.map(|rc| rc.ident.content).map(|i| i.to_string()) - .unwrap_or_else(|| "decl_storage".to_string()); - let scrate = generate_crate_access(&hidden_crate_name, "srml-support"); - let scrate_decl = generate_hidden_includes( - &hidden_crate_name, - "srml-support", - ); - - let ( - traitinstance, - traittypes, - ) = if let GenericParam::Type(syn::TypeParam {ident, bounds, ..}) = strait { - (ident, bounds) - } else { - return try_tok!(Err(Error::new(strait.span(), "Missing declare store generic params"))); - }; - - let traittype = if let Some(traittype) = traittypes.first() { - traittype.into_value() - } else { - return try_tok!(Err(Error::new(traittypes.span(), "Trait bound expected"))); - }; - - let extra_genesis = try_tok!(decl_store_extra_genesis( - &scrate, - &traitinstance, - &traittype, - &instance_opts, - &storage_lines, - &extra_genesis.inner, - &where_clause, - )); - let decl_storage_items = decl_storage_items( - &scrate, - &traitinstance, - &traittype, - &instance_opts, - &cratename, - &storage_lines, - &where_clause, - ); - - let decl_store_items = decl_store_items( - &storage_lines, - ); - let impl_store_items = impl_store_items( - &traitinstance, - &instance_opts.instance, - &storage_lines, - ); - let impl_store_fns = impl_store_fns( - &scrate, - &traitinstance, - &instance_opts.instance, - &storage_lines, - ); - let (store_default_struct, store_metadata) = store_functions_to_metadata( - &scrate, - &traitinstance, - &traittype, - &instance_opts, - &storage_lines, - &where_clause, - &cratename, - ); - - let InstanceOpts { - instance, - bound_instantiable, - .. - } = instance_opts; - - let expanded = quote! { - #scrate_decl - #decl_storage_items - #visibility trait #storetype { - #decl_store_items - } - #store_default_struct - impl<#traitinstance: #traittype, #instance #bound_instantiable> #storetype - for #module_ident<#traitinstance, #instance> #where_clause - { - #impl_store_items - } - impl<#traitinstance: 'static + #traittype, #instance #bound_instantiable> - #module_ident<#traitinstance, #instance> #where_clause - { - #impl_store_fns - #[doc(hidden)] - pub fn storage_metadata() -> #scrate::metadata::StorageMetadata { - #store_metadata - } - } - - #extra_genesis - }; - - expanded.into() -} - -fn decl_store_extra_genesis( - scrate: &TokenStream2, - traitinstance: &Ident, - traittype: &syn::TypeParamBound, - instance_opts: &InstanceOpts, - storage_lines: &ext::Punctuated, - extra_genesis: &Option, - where_clause: &Option, -) -> Result { - - let InstanceOpts { - equal_default_instance, - bound_instantiable, - instance, - .. - } = instance_opts; - - let mut is_trait_needed = false; - let mut serde_complete_bound = Vec::new(); - let mut config_field = TokenStream2::new(); - let mut config_field_default = TokenStream2::new(); - let mut builders = TokenStream2::new(); - let mut assimilate_require_generic = instance.is_some(); - let mut builders_clone_bound = Vec::new(); - - for sline in storage_lines.inner.iter() { - let DeclStorageLine { - attrs, - name, - getter, - config, - build, - storage_type, - default_value, - .. - } = sline; - - let type_infos = get_type_infos(storage_type); - - let opt_build = build - .inner - .as_ref() - .map(|b| { - assimilate_require_generic |= ext::expr_contains_ident(&b.expr.content, traitinstance); - &b.expr.content - }) - .map(|b| quote!( #b )); - - // need build line - let builder = if let Some(ref config) = config.inner { - let ident = if let Some(ident) = config.expr.content.as_ref() { - quote!( #ident ) - } else if let Some(ref getter) = getter.inner { - let ident = &getter.getfn.content; - quote!( #ident ) - } else { - return Err( - Error::new_spanned( - name, - "Invalid storage definiton, couldn't find config identifier: storage must either have a get identifier \ - `get(ident)` or a defined config identifier `config(ident)`" - ) - ); - }; - - if ext::type_contains_ident(type_infos.value_type, traitinstance) { - is_trait_needed = true; - } - - if opt_build.is_none() { - builders_clone_bound.push(type_infos.value_type.clone()); - } - - let value_type = &type_infos.value_type; - serde_complete_bound.push(quote!( #value_type )); - match type_infos.kind { - DeclStorageTypeInfosKind::Map { key_type, .. } => { - serde_complete_bound.push(quote!( #key_type )); - is_trait_needed = is_trait_needed - || ext::type_contains_ident(key_type, traitinstance); - - if opt_build.is_none() { - builders_clone_bound.push(key_type.clone()); - } - }, - DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => { - serde_complete_bound.push(quote!( #key1_type )); - serde_complete_bound.push(quote!( #key2_type )); - is_trait_needed = is_trait_needed - || ext::type_contains_ident(key1_type, traitinstance) - || ext::type_contains_ident(key2_type, traitinstance); - if opt_build.is_none() { - builders_clone_bound.push(key1_type.clone()); - builders_clone_bound.push(key2_type.clone()); - } - }, - _ => {}, - } - - if type_infos.is_option { - serde_complete_bound.push(type_infos.typ.clone()); - } - - // Propagate doc attributes. - let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); - - let storage_type = type_infos.typ.clone(); - config_field.extend(match type_infos.kind { - DeclStorageTypeInfosKind::Simple => { - quote!( #( #[ #attrs ] )* pub #ident: #storage_type, ) - }, - DeclStorageTypeInfosKind::Map {key_type, .. } => { - quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key_type, #storage_type)>, ) - }, - DeclStorageTypeInfosKind::DoubleMap {key1_type, key2_type, .. } => { - quote!( #( #[ #attrs ] )* pub #ident: Vec<(#key1_type, #key2_type, #storage_type)>, ) - }, - }); - - let fielddefault = default_value.inner.as_ref().map(|d| &d.expr).map(|d| - if type_infos.is_option { - quote!( #d.unwrap_or_default() ) - } else { - quote!( #d ) - }).unwrap_or_else(|| quote!( Default::default() )); - - config_field_default.extend(quote!( #ident: #fielddefault, )); - - opt_build.or_else(|| Some(quote!( (|config: &Self| config.#ident.clone()) ))) - } else { - opt_build - }; - - let typ = type_infos.typ; - if let Some(builder) = builder { - builders.extend(match type_infos.kind { - DeclStorageTypeInfosKind::Simple => { - let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) { - assimilate_require_generic = true; - quote!(#traitinstance,) - } else { - quote!() - }; - - quote!{{ - let v = (#builder)(&self); - < - #name<#struct_trait #instance> as - #scrate::storage::hashed::generator::StorageValue<#typ> - >::put(&v, storage); - }} - }, - DeclStorageTypeInfosKind::Map { key_type, .. } => { - let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) - || ext::type_contains_ident(key_type, traitinstance) - { - assimilate_require_generic = true; - quote!(#traitinstance,) - } else { - quote!() - }; - - quote!{{ - let data = (#builder)(&self); - data.into_iter().for_each(|(k, v)| { - < - #name<#struct_trait #instance> as - #scrate::storage::hashed::generator::StorageMap<#key_type, #typ> - >::insert(&k, &v, storage); - }); - }} - }, - DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => { - let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) - || ext::type_contains_ident(key1_type, traitinstance) - || ext::type_contains_ident(key2_type, traitinstance) - { - assimilate_require_generic = true; - quote!(#traitinstance,) - } else { - quote!() - }; - - quote!{{ - let data = (#builder)(&self); - data.into_iter().for_each(|(k1, k2, v)| { - < - #name<#struct_trait #instance> as - #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ> - >::insert(&k1, &k2, &v, storage); - }); - }} - }, - }); - } - } - - let mut has_scall = false; - let mut scall = quote!{ ( |_, _| {} ) }; - let mut genesis_extrafields = TokenStream2::new(); - let mut genesis_extrafields_default = TokenStream2::new(); - - // extra genesis - if let Some(eg) = extra_genesis { - for ex_content in eg.content.content.lines.inner.iter() { - match ex_content { - AddExtraGenesisLineEnum::AddExtraGenesisLine(AddExtraGenesisLine { - attrs, - extra_field, - extra_type, - default_value, - .. - }) => { - if ext::type_contains_ident(&extra_type, traitinstance) { - is_trait_needed = true; - } - - serde_complete_bound.push(quote!( #extra_type )); - - let extrafield = &extra_field.content; - genesis_extrafields.extend(quote!{ - #attrs pub #extrafield: #extra_type, - }); - let extra_default = default_value.inner.as_ref().map(|d| &d.expr).map(|e| quote!{ #e }) - .unwrap_or_else(|| quote!( Default::default() )); - genesis_extrafields_default.extend(quote!{ - #extrafield: #extra_default, - }); - }, - AddExtraGenesisLineEnum::AddExtraGenesisBuild(DeclStorageBuild{ expr, .. }) => { - if has_scall { - return Err(Error::new(expr.span(), "Only one build expression allowed for extra genesis")); - } - assimilate_require_generic |= ext::expr_contains_ident(&expr.content, traitinstance); - let content = &expr.content; - scall = quote!( ( #content ) ); - has_scall = true; - }, - } - } - } - - let serde_bug_bound = if !serde_complete_bound.is_empty() { - let mut b_ser = String::new(); - let mut b_dser = String::new(); - - serde_complete_bound.into_iter().for_each(|bound| { - let stype = quote!(#bound); - b_ser.push_str(&format!("{} : {}::serde::Serialize, ", stype, scrate)); - b_dser.push_str(&format!("{} : {}::serde::de::DeserializeOwned, ", stype, scrate)); - }); - - quote! { - #[serde(bound(serialize = #b_ser))] - #[serde(bound(deserialize = #b_dser))] - } - } else { - quote!() - }; - - let is_extra_genesis_needed = has_scall - || !config_field.is_empty() - || !genesis_extrafields.is_empty() - || !builders.is_empty(); - if is_extra_genesis_needed { - let (inherent_instance, inherent_bound_instantiable) = if instance.is_some() { - (instance.clone(), bound_instantiable.clone()) - } else { - let instantiable = Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site()); - ( - Some(Ident::new(DEFAULT_INSTANCE_NAME, Span::call_site())), - quote!(: #instantiable), - ) - }; - - let (fparam_struct, fparam_impl, sparam, build_storage_impl) = if is_trait_needed { - ( - quote!(<#traitinstance: #traittype, #instance #bound_instantiable #equal_default_instance>), - quote!(<#traitinstance: #traittype, #instance #bound_instantiable>), - quote!(<#traitinstance, #instance>), - quote!(<#traitinstance: #traittype, #inherent_instance #inherent_bound_instantiable>), - ) - } else { - // do not even need type parameter - ( - quote!(), - quote!(), - quote!(), - quote!(<#traitinstance: #traittype, #inherent_instance #inherent_bound_instantiable>), - ) - }; - - let (fn_generic, fn_traitinstance) = if !is_trait_needed && assimilate_require_generic { - ( - quote!( <#traitinstance: #traittype, #instance #bound_instantiable> ), - quote!( #traitinstance, #instance ) - ) - } else { - (quote!(), quote!()) - }; - - let impl_trait = quote!(BuildModuleGenesisStorage<#traitinstance, #inherent_instance>); - - let extend_where_clause = |to_extend: &mut WhereClause| { - if let Some(where_clause) = where_clause { - to_extend.predicates.extend(where_clause.predicates.iter().cloned()); - } - }; - - let mut genesis_where_clause: WhereClause = syn::parse_quote!( - where #( #builders_clone_bound: Clone ),* - ); - let mut fn_where_clause = genesis_where_clause.clone(); - - - let mut build_storage_where_clause = genesis_where_clause.clone(); - extend_where_clause(&mut build_storage_where_clause); - - if is_trait_needed { - extend_where_clause(&mut genesis_where_clause); - } else if assimilate_require_generic { - extend_where_clause(&mut fn_where_clause); - } - - let res = quote!{ - #[derive(#scrate::Serialize, #scrate::Deserialize)] - #[cfg(feature = "std")] - #[serde(rename_all = "camelCase")] - #[serde(deny_unknown_fields)] - #serde_bug_bound - pub struct GenesisConfig#fparam_struct #genesis_where_clause { - #config_field - #genesis_extrafields - } - - #[cfg(feature = "std")] - impl#fparam_impl Default for GenesisConfig#sparam #genesis_where_clause { - fn default() -> Self { - GenesisConfig { - #config_field_default - #genesis_extrafields_default - } - } - } - - #[cfg(feature = "std")] - impl#fparam_impl GenesisConfig#sparam #genesis_where_clause { - pub fn build_storage #fn_generic (self) -> std::result::Result< - ( - #scrate::sr_primitives::StorageOverlay, - #scrate::sr_primitives::ChildrenStorageOverlay, - ), - String - > #fn_where_clause { - let mut storage = (Default::default(), Default::default()); - self.assimilate_storage::<#fn_traitinstance>(&mut storage)?; - Ok(storage) - } - - /// Assimilate the storage for this module into pre-existing overlays. - pub fn assimilate_storage #fn_generic ( - self, - tuple_storage: &mut ( - #scrate::sr_primitives::StorageOverlay, - #scrate::sr_primitives::ChildrenStorageOverlay, - ), - ) -> std::result::Result<(), String> #fn_where_clause { - let storage = &mut tuple_storage.0; - - #builders - - #scall(tuple_storage, &self); - - Ok(()) - } - } - - #[cfg(feature = "std")] - impl#build_storage_impl #scrate::sr_primitives::#impl_trait - for GenesisConfig#sparam #build_storage_where_clause - { - fn build_module_genesis_storage( - self, - storage: &mut ( - #scrate::sr_primitives::StorageOverlay, - #scrate::sr_primitives::ChildrenStorageOverlay, - ), - ) -> std::result::Result<(), String> { - self.assimilate_storage::<#fn_traitinstance> (storage) - } - } - }; - - Ok(res) - } else { - Ok(quote!()) - } -} - -fn create_and_impl_instance( - instance_prefix: &str, - ident: &Ident, - doc: &TokenStream2, - const_names: &[(Ident, String)], - scrate: &TokenStream2, - instantiable: &Ident, - cratename: &Ident, -) -> TokenStream2 { - let mut const_impls = TokenStream2::new(); - - for (const_name, partial_const_value) in const_names { - let const_value = format!("{}{}", instance_prefix, partial_const_value); - const_impls.extend(quote! { - const #const_name: &'static str = #const_value; - }); - } - - let prefix = format!("{}{}", instance_prefix, cratename.to_string()); - - quote! { - // Those trait are derived because of wrong bounds for generics - #[cfg_attr(feature = "std", derive(Debug))] - #[derive(Clone, Eq, PartialEq, #scrate::codec::Encode, #scrate::codec::Decode)] - #doc - pub struct #ident; - impl #instantiable for #ident { - const PREFIX: &'static str = #prefix; - #const_impls - } - } -} - -fn decl_storage_items( - scrate: &TokenStream2, - traitinstance: &Ident, - traittype: &syn::TypeParamBound, - instance_opts: &InstanceOpts, - cratename: &Ident, - storage_lines: &ext::Punctuated, - where_clause: &Option, -) -> TokenStream2 { - let mut impls = TokenStream2::new(); - - let InstanceOpts { - instance, - default_instance, - instantiable, - .. - } = instance_opts; - - let build_prefix = |cratename, name| format!("{} {}", cratename, name); - - // Build Instantiable trait - let mut const_names = vec![]; - - for sline in storage_lines.inner.iter() { - let DeclStorageLine { - storage_type, - name, - .. - } = sline; - - let prefix = build_prefix(cratename, name); - - let type_infos = get_type_infos(storage_type); - - let const_name = syn::Ident::new( - &format!("{}{}", impls::PREFIX_FOR, name.to_string()), proc_macro2::Span::call_site() - ); - let partial_const_value = prefix.clone(); - const_names.push((const_name, partial_const_value)); - - if let DeclStorageTypeInfosKind::Map { is_linked: true, .. } = type_infos.kind { - let const_name = syn::Ident::new( - &format!("{}{}", impls::HEAD_KEY_FOR, name.to_string()), proc_macro2::Span::call_site() - ); - let partial_const_value = format!("head of {}", prefix); - const_names.push((const_name, partial_const_value)); - } - } - - let instantiable = instantiable - .clone() - .unwrap_or_else(|| Ident::new(DEFAULT_INSTANTIABLE_TRAIT_NAME, Span::call_site())); - - // Declare Instance trait - { - let mut const_impls = TokenStream2::new(); - for (const_name, _) in &const_names { - const_impls.extend(quote! { - const #const_name: &'static str; - }); - } - - let hide = if instance.is_some() { - quote!() - } else { - quote!(#[doc(hidden)]) - }; - - impls.extend(quote! { - /// Tag a type as an instance of a module. - /// - /// Defines storage prefixes, they must be unique. - #hide - pub trait #instantiable: 'static { - /// The prefix used by any storage entry of an instance. - const PREFIX: &'static str; - #const_impls - } - }); - } - - if instance.is_some() { - let instances = (0..NUMBER_OF_INSTANCE) - .map(|i| { - let name = format!("Instance{}", i); - let ident = Ident::new(&name, proc_macro2::Span::call_site()); - (name, ident, quote! {#[doc=r"Module instance"]}) - }) - .chain( - default_instance - .clone() - .map(|ident| - (String::new(), ident, quote! {#[doc=r"Default module instance"]}) - ) - ); - - // Impl Instance trait for instances - for (instance_prefix, ident, doc) in instances { - impls.extend( - create_and_impl_instance( - &instance_prefix, &ident, &doc, &const_names, scrate, &instantiable, cratename - ) - ); - } - } - - // The name of the inherently available instance. - let inherent_instance = Ident::new(INHERENT_INSTANCE_NAME, Span::call_site()); - - if default_instance.is_some() { - impls.extend(quote! { - #[doc(hidden)] - pub type #inherent_instance = #default_instance; - }); - } else { - impls.extend( - create_and_impl_instance( - "", - &inherent_instance, - "e!(#[doc(hidden)]), - &const_names, - scrate, - &instantiable, - cratename, - ) - ); - } - - for sline in storage_lines.inner.iter() { - let DeclStorageLine { - attrs, - name, - storage_type, - default_value, - visibility, - .. - } = sline; - - let type_infos = get_type_infos(storage_type); - let kind = type_infos.kind.clone(); - // Propagate doc attributes. - let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); - - let i = impls::Impls { - scrate, - visibility, - cratename, - traitinstance, - traittype, - instance_opts, - type_infos, - fielddefault: default_value.inner.as_ref().map(|d| &d.expr).map(|d| quote!( #d )) - .unwrap_or_else(|| quote!{ Default::default() }), - prefix: build_prefix(cratename, name), - name, - attrs, - where_clause, - }; - - let implementation = match kind { - DeclStorageTypeInfosKind::Simple => { - i.simple_value() - }, - DeclStorageTypeInfosKind::Map { key_type, is_linked: false, hasher } => { - i.map(hasher.into_storage_hasher_struct(), key_type) - }, - DeclStorageTypeInfosKind::Map { key_type, is_linked: true, hasher } => { - i.linked_map(hasher.into_storage_hasher_struct(), key_type) - }, - DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, key2_hasher, hasher } => { - i.double_map(hasher.into_storage_hasher_struct(), key1_type, key2_type, key2_hasher.into_storage_hasher_struct()) - }, - }; - impls.extend(implementation) - } - impls -} - -fn decl_store_items(storage_lines: &ext::Punctuated) -> TokenStream2 { - storage_lines.inner.iter().map(|sline| &sline.name) - .fold(TokenStream2::new(), |mut items, name| { - items.extend(quote!(type #name;)); - items - }) -} - -fn impl_store_items( - traitinstance: &Ident, - instance: &Option, - storage_lines: &ext::Punctuated, -) -> TokenStream2 { - storage_lines.inner - .iter() - .fold(TokenStream2::new(), |mut items, line| { - let name = &line.name; - let type_infos = get_type_infos(&line.storage_type); - let requires_trait = match type_infos.kind { - DeclStorageTypeInfosKind::Simple => { - ext::type_contains_ident(&type_infos.value_type, traitinstance) - }, - DeclStorageTypeInfosKind::Map { key_type, .. } => { - ext::type_contains_ident(&type_infos.value_type, traitinstance) - || ext::type_contains_ident(key_type, traitinstance) - } - DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => { - ext::type_contains_ident(&type_infos.value_type, traitinstance) - || ext::type_contains_ident(key1_type, traitinstance) - || ext::type_contains_ident(key2_type, traitinstance) - } - }; - - let struct_trait = if requires_trait { - quote!(#traitinstance,) - } else { - quote!() - }; - - items.extend( - quote!( - type #name = #name<#struct_trait #instance>; - ) - ); - items - }) -} - -fn impl_store_fns( - scrate: &TokenStream2, - traitinstance: &Ident, - instance: &Option, - storage_lines: &ext::Punctuated, -) -> TokenStream2 { - let mut items = TokenStream2::new(); - for sline in storage_lines.inner.iter() { - let DeclStorageLine { - attrs, - name, - getter, - storage_type, - .. - } = sline; - - if let Some(getter) = getter.inner.as_ref() { - let get_fn = &getter.getfn.content; - - let type_infos = get_type_infos(storage_type); - let value_type = type_infos.value_type; - - // Propagate doc attributes. - let attrs = attrs.inner.iter().filter_map(|a| a.parse_meta().ok()).filter(|m| m.name() == "doc"); - - let typ = type_infos.typ; - let item = match type_infos.kind { - DeclStorageTypeInfosKind::Simple => { - let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) { - quote!(#traitinstance,) - } else { - quote!() - }; - - quote!{ - #( #[ #attrs ] )* - pub fn #get_fn() -> #value_type { - <#name<#struct_trait #instance> as - #scrate::storage::hashed::generator::StorageValue<#typ>> :: get( - &#scrate::storage::RuntimeStorage - ) - } - } - }, - DeclStorageTypeInfosKind::Map { key_type, .. } => { - let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) - || ext::type_contains_ident(key_type, traitinstance) - { - quote!(#traitinstance,) - } else { - quote!() - }; - - quote!{ - #( #[ #attrs ] )* - pub fn #get_fn>(key: K) -> #value_type { - < - #name<#struct_trait #instance> as - #scrate::storage::hashed::generator::StorageMap<#key_type, #typ> - >::get(key.borrow(), &#scrate::storage::RuntimeStorage) - } - } - } - DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, .. } => { - let struct_trait = if ext::type_contains_ident(&type_infos.value_type, traitinstance) - || ext::type_contains_ident(key1_type, traitinstance) - || ext::type_contains_ident(key2_type, traitinstance) - { - quote!(#traitinstance,) - } else { - quote!() - }; - - quote!{ - pub fn #get_fn(k1: &KArg1, k2: &KArg2) -> #value_type - where - #key1_type: #scrate::rstd::borrow::Borrow, - #key2_type: #scrate::rstd::borrow::Borrow, - KArg1: ?Sized + #scrate::codec::Encode, - KArg2: ?Sized + #scrate::codec::Encode, - { - < - #name<#struct_trait #instance> as - #scrate::storage::unhashed::generator::StorageDoubleMap<#key1_type, #key2_type, #typ> - >::get(k1, k2, &#scrate::storage::RuntimeStorage) - } - } - } - }; - items.extend(item); - } - } - items -} - -fn store_functions_to_metadata ( - scrate: &TokenStream2, - traitinstance: &Ident, - traittype: &syn::TypeParamBound, - instance_opts: &InstanceOpts, - storage_lines: &ext::Punctuated, - where_clause: &Option, - cratename: &Ident, -) -> (TokenStream2, TokenStream2) { - let InstanceOpts { - comma_instance, - equal_default_instance, - bound_instantiable, - instance, - .. - } = instance_opts; - - let mut items = TokenStream2::new(); - let mut default_getter_struct_def = TokenStream2::new(); - for sline in storage_lines.inner.iter() { - let DeclStorageLine { - attrs, - name, - storage_type, - default_value, - .. - } = sline; - - let type_infos = get_type_infos(storage_type); - let value_type = type_infos.value_type; - - let typ = type_infos.typ; - let styp = clean_type_string(&typ.to_string()); - let stype = match type_infos.kind { - DeclStorageTypeInfosKind::Simple => { - quote!{ - #scrate::metadata::StorageEntryType::Plain( - #scrate::metadata::DecodeDifferent::Encode(#styp), - ) - } - }, - DeclStorageTypeInfosKind::Map { key_type, is_linked, hasher } => { - let hasher = hasher.into_metadata(); - let kty = clean_type_string("e!(#key_type).to_string()); - quote!{ - #scrate::metadata::StorageEntryType::Map { - hasher: #scrate::metadata::#hasher, - key: #scrate::metadata::DecodeDifferent::Encode(#kty), - value: #scrate::metadata::DecodeDifferent::Encode(#styp), - is_linked: #is_linked, - } - } - }, - DeclStorageTypeInfosKind::DoubleMap { key1_type, key2_type, key2_hasher, hasher } => { - let hasher = hasher.into_metadata(); - let k1ty = clean_type_string("e!(#key1_type).to_string()); - let k2ty = clean_type_string("e!(#key2_type).to_string()); - let k2_hasher = key2_hasher.into_metadata(); - quote!{ - #scrate::metadata::StorageEntryType::DoubleMap { - hasher: #scrate::metadata::#hasher, - key1: #scrate::metadata::DecodeDifferent::Encode(#k1ty), - key2: #scrate::metadata::DecodeDifferent::Encode(#k2ty), - value: #scrate::metadata::DecodeDifferent::Encode(#styp), - key2_hasher: #scrate::metadata::#k2_hasher, - } - } - }, - }; - let modifier = if type_infos.is_option { - quote!{ - #scrate::metadata::StorageEntryModifier::Optional - } - } else { - quote!{ - #scrate::metadata::StorageEntryModifier::Default - } - }; - let default = default_value.inner.as_ref().map(|d| &d.expr) - .map(|d| { - quote!( #d ) - }) - .unwrap_or_else(|| quote!( Default::default() )); - let mut docs = TokenStream2::new(); - for attr in attrs.inner.iter().filter_map(|v| v.parse_meta().ok()) { - if let syn::Meta::NameValue(syn::MetaNameValue{ - ref ident, - ref lit, - .. - }) = attr { - if ident == "doc" { - docs.extend(quote!(#lit,)); - } - } - } - let str_name = name.to_string(); - let struct_name = proc_macro2::Ident::new(&("__GetByteStruct".to_string() + &str_name), name.span()); - let cache_name = proc_macro2::Ident::new(&("__CACHE_GET_BYTE_STRUCT_".to_string() + &str_name), name.span()); - - let item = quote! { - #scrate::metadata::StorageEntryMetadata { - name: #scrate::metadata::DecodeDifferent::Encode(#str_name), - modifier: #modifier, - ty: #stype, - default: #scrate::metadata::DecodeDifferent::Encode( - #scrate::metadata::DefaultByteGetter( - &#struct_name::<#traitinstance, #instance>(#scrate::rstd::marker::PhantomData) - ) - ), - documentation: #scrate::metadata::DecodeDifferent::Encode(&[ #docs ]), - }, - }; - items.extend(item); - - let def_get = quote! { - #[doc(hidden)] - pub struct #struct_name< - #traitinstance, #instance #bound_instantiable #equal_default_instance - >(pub #scrate::rstd::marker::PhantomData<(#traitinstance #comma_instance)>); - - #[cfg(feature = "std")] - #[allow(non_upper_case_globals)] - static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec> = #scrate::once_cell::sync::OnceCell::INIT; - - #[cfg(feature = "std")] - impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::metadata::DefaultByte - for #struct_name<#traitinstance, #instance> #where_clause - { - fn default_byte(&self) -> #scrate::rstd::vec::Vec { - use #scrate::codec::Encode; - #cache_name.get_or_init(|| { - let def_val: #value_type = #default; - <#value_type as Encode>::encode(&def_val) - }).clone() - } - } - - unsafe impl<#traitinstance: #traittype, #instance #bound_instantiable> Send - for #struct_name<#traitinstance, #instance> #where_clause {} - - unsafe impl<#traitinstance: #traittype, #instance #bound_instantiable> Sync - for #struct_name<#traitinstance, #instance> #where_clause {} - - #[cfg(not(feature = "std"))] - impl<#traitinstance: #traittype, #instance #bound_instantiable> #scrate::metadata::DefaultByte - for #struct_name<#traitinstance, #instance> #where_clause - { - fn default_byte(&self) -> #scrate::rstd::vec::Vec { - use #scrate::codec::Encode; - let def_val: #value_type = #default; - <#value_type as Encode>::encode(&def_val) - } - } - }; - - default_getter_struct_def.extend(def_get); - } - - let prefix = cratename.to_string(); - let prefix = instance.as_ref().map_or_else(|| quote!(#prefix), |i| quote!(#i::PREFIX)); - - (default_getter_struct_def, quote!{ - #scrate::metadata::StorageMetadata { - prefix: #scrate::metadata::DecodeDifferent::Encode(#prefix), - entries: #scrate::metadata::DecodeDifferent::Encode(&[ #items ][..]), - } - }) -} - - -#[derive(Debug, Clone)] -pub(crate) struct DeclStorageTypeInfos<'a> { - pub is_option: bool, - pub typ: TokenStream2, - pub value_type: &'a syn::Type, - kind: DeclStorageTypeInfosKind<'a>, -} - -#[derive(Debug, Clone)] -enum DeclStorageTypeInfosKind<'a> { - Simple, - Map { - hasher: HasherKind, - key_type: &'a syn::Type, - is_linked: bool, - }, - DoubleMap { - hasher: HasherKind, - key1_type: &'a syn::Type, - key2_type: &'a syn::Type, - key2_hasher: HasherKind, - } -} - -fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos { - let (value_type, kind) = match storage_type { - DeclStorageType::Simple(ref st) => (st, DeclStorageTypeInfosKind::Simple), - DeclStorageType::Map(ref map) => (&map.value, DeclStorageTypeInfosKind::Map { - hasher: map.hasher.inner.as_ref().map(|h| h.into()).unwrap_or(HasherKind::Blake2_256), - key_type: &map.key, - is_linked: false, - }), - DeclStorageType::LinkedMap(ref map) => (&map.value, DeclStorageTypeInfosKind::Map { - hasher: map.hasher.inner.as_ref().map(|h| h.into()).unwrap_or(HasherKind::Blake2_256), - key_type: &map.key, - is_linked: true, - }), - DeclStorageType::DoubleMap(ref map) => (&map.value, DeclStorageTypeInfosKind::DoubleMap { - hasher: map.hasher.inner.as_ref().map(|h| h.into()).unwrap_or(HasherKind::Blake2_256), - key1_type: &map.key1, - key2_type: &map.key2.content, - key2_hasher: (&map.key2_hasher).into(), - }), - }; - - let extracted_type = ext::extract_type_option(value_type); - let is_option = extracted_type.is_some(); - let typ = extracted_type.unwrap_or(quote!( #value_type )); - - DeclStorageTypeInfos { - is_option, - typ, - value_type, - kind, - } - -} - -#[derive(Default)] -pub(crate) struct InstanceOpts { - pub instance: Option, - pub default_instance: Option, - pub instantiable: Option, - pub comma_instance: TokenStream2, - pub equal_default_instance: TokenStream2, - pub bound_instantiable: TokenStream2, -} - -fn get_instance_opts( - instance: Option, - instantiable: Option, - default_instance: Option, -) -> Result { - let right_syntax = "Should be $Instance: $Instantiable = $DefaultInstance"; - - match (instance, instantiable, default_instance) { - (Some(instance), Some(instantiable), default_instance) => { - let (equal_default_instance, default_instance) = if let Some(def) = default_instance { - (quote!{= #def}, Some(def)) - } else { - (quote!(), None) - }; - - Ok(InstanceOpts { - comma_instance: quote!{, #instance}, - equal_default_instance, - bound_instantiable: quote!{: #instantiable}, - instance: Some(instance), - default_instance, - instantiable: Some(instantiable), - }) - }, - (None, None, None) => Ok(Default::default()), - (Some(instance), None, _) => Err( - Error::new( - instance.span(), - format!( - "Expect instantiable trait bound for instance: {}. {}", - instance, - right_syntax, - ) - ) - ), - (None, Some(instantiable), _) => Err( - Error::new( - instantiable.span(), - format!( - "Expect instance generic for bound instantiable: {}. {}", - instantiable, - right_syntax, - ) - ) - ), - (None, _, Some(default_instance)) => Err( - Error::new( - default_instance.span(), - format!( - "Expect instance generic for default instance: {}. {}", - default_instance, - right_syntax, - ) - ) - ), - } -} diff --git a/srml/support/procedural/tools/Cargo.toml b/srml/support/procedural/tools/Cargo.toml index bb6d24def2da8c933fc1881e3bf4c53f39063dd0..4c5726c202521f52096dbd7d494ad40ea7f46a20 100644 --- a/srml/support/procedural/tools/Cargo.toml +++ b/srml/support/procedural/tools/Cargo.toml @@ -5,8 +5,8 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -srml-support-procedural-tools-derive = { path = "./derive" } -proc-macro2 = "0.4.27" -quote = { version = "0.6.12" } -syn = { version = "0.15.30", features = ["full"] } -proc-macro-crate = "0.1.3" +srml-support-procedural-tools-derive = { package = "srml-support-procedural-tools-derive", path = "./derive" } +proc-macro2 = "1.0.6" +quote = "1.0.2" +syn = { version = "1.0.7", features = ["full"] } +proc-macro-crate = "0.1.4" diff --git a/srml/support/procedural/tools/derive/Cargo.toml b/srml/support/procedural/tools/derive/Cargo.toml index 2f7f35ff4a70228423ec451aaf9c641c30e38699..acc0c1b1d336780deb4970649c6b26095e93612c 100644 --- a/srml/support/procedural/tools/derive/Cargo.toml +++ b/srml/support/procedural/tools/derive/Cargo.toml @@ -8,6 +8,6 @@ edition = "2018" proc-macro = true [dependencies] -proc-macro2 = "0.4.27" -quote = { version = "0.6.12", features = ["proc-macro"] } -syn = { version = "0.15.30", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } +proc-macro2 = "1.0.6" +quote = { version = "1.0.2", features = ["proc-macro"] } +syn = { version = "1.0.7", features = ["proc-macro" ,"full", "extra-traits", "parsing"] } diff --git a/srml/support/procedural/tools/src/syn_ext.rs b/srml/support/procedural/tools/src/syn_ext.rs index 1033ebcce2de5b7da84e3d7ebc21bc0220ae4bfe..39cfb0ee1cf2f8f42f67faf4b125087d21b510ee 100644 --- a/srml/support/procedural/tools/src/syn_ext.rs +++ b/srml/support/procedural/tools/src/syn_ext.rs @@ -20,7 +20,7 @@ use syn::{visit::{Visit, self}, parse::{Parse, ParseStream, Result}, Ident}; use proc_macro2::{TokenStream, TokenTree}; -use quote::{ToTokens, quote}; +use quote::ToTokens; use std::iter::once; use srml_support_procedural_tools_derive::{ToTokens, Parse}; @@ -124,13 +124,7 @@ impl Parse for Meta { impl ToTokens for Meta { fn to_tokens(&self, tokens: &mut TokenStream) { match self.inner { - syn::Meta::Word(ref ident) => { - let ident = ident.clone(); - let toks = quote!{ - #[#ident] - }; - tokens.extend(toks); - }, + syn::Meta::Path(ref path) => path.to_tokens(tokens), syn::Meta::List(ref l) => l.to_tokens(tokens), syn::Meta::NameValue(ref n) => n.to_tokens(tokens), } @@ -184,13 +178,15 @@ impl ToTokens for Opt

, +} + +impl TransactionPayment { + /// Create new `TransactionPayment` with the given reference to the client. + pub fn new(client: Arc) -> Self { + TransactionPayment { client, _marker: Default::default() } + } +} + +/// Error type of this RPC api. +pub enum Error { + /// The transaction was not decodable. + DecodeError, + /// The call to runtime failed. + RuntimeError, +} + +impl From for i64 { + fn from(e: Error) -> i64 { + match e { + Error::RuntimeError => 1, + Error::DecodeError => 2, + } + } +} + +impl TransactionPaymentApi<::Hash, Balance> + for TransactionPayment +where + Block: BlockT, + C: Send + Sync + 'static, + C: ProvideRuntimeApi, + C: HeaderBackend, + C::Api: TransactionPaymentRuntimeApi, + Balance: Codec, + Extrinsic: Codec + Send + Sync + 'static, +{ + fn query_info( + &self, + encoded_xt: Bytes, + at: Option<::Hash> + ) -> Result> { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| + // If the block hash is not supplied assume the best block. + self.client.info().best_hash + )); + + let encoded_len = encoded_xt.len() as u32; + + let uxt: Extrinsic = Decode::decode(&mut &*encoded_xt).map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::DecodeError.into()), + message: "Unable to query dispatch info.".into(), + data: Some(format!("{:?}", e).into()), + })?; + api.query_info(&at, uxt, encoded_len).map_err(|e| RpcError { + code: ErrorCode::ServerError(Error::RuntimeError.into()), + message: "Unable to query dispatch info.".into(), + data: Some(format!("{:?}", e).into()), + }) + } +} diff --git a/srml/transaction-payment/src/lib.rs b/srml/transaction-payment/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..2314edf053958537e9be6e5afe5652ba99e2a222 --- /dev/null +++ b/srml/transaction-payment/src/lib.rs @@ -0,0 +1,534 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Transaction Payment Module +//! +//! This module provides the basic logic needed to pay the absolute minimum amount needed for a +//! transaction to be included. This includes: +//! - _weight fee_: A fee proportional to amount of weight a transaction consumes. +//! - _length fee_: A fee proportional to the encoded length of the transaction. +//! - _tip_: An optional tip. Tip increases the priority of the transaction, giving it a higher +//! chance to be included by the transaction queue. +//! +//! Additionally, this module allows one to configure: +//! - The mapping between one unit of weight to one unit of fee via [`WeightToFee`]. +//! - A means of updating the fee for the next block, via defining a multiplier, based on the +//! final state of the chain at the end of the previous block. This can be configured via +//! [`FeeMultiplierUpdate`] + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::prelude::*; +use codec::{Encode, Decode}; +use support::{ + decl_storage, decl_module, + traits::{Currency, Get, OnUnbalanced, ExistenceRequirement, WithdrawReason}, +}; +use sr_primitives::{ + Fixed64, + transaction_validity::{ + TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, + TransactionValidity, + }, + traits::{Zero, Saturating, SignedExtension, SaturatedConversion, Convert}, + weights::{Weight, DispatchInfo, GetDispatchInfo}, +}; +use transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; + +type Multiplier = Fixed64; +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = + <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Trait: system::Trait { + /// The currency type in which fees will be paid. + type Currency: Currency; + + /// Handler for the unbalanced reduction when taking transaction fees. + type OnTransactionPayment: OnUnbalanced>; + + /// The fee to be paid for making a transaction; the base. + type TransactionBaseFee: Get>; + + /// The fee to be paid for making a transaction; the per-byte portion. + type TransactionByteFee: Get>; + + /// Convert a weight value into a deductible fee based on the currency type. + type WeightToFee: Convert>; + + /// Update the multiplier of the next block, based on the previous block's weight. + type FeeMultiplierUpdate: Convert; +} + +decl_storage! { + trait Store for Module as Balances { + NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_parts(0); + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// The fee to be paid for making a transaction; the base. + const TransactionBaseFee: BalanceOf = T::TransactionBaseFee::get(); + + /// The fee to be paid for making a transaction; the per-byte portion. + const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); + + fn on_finalize() { + NextFeeMultiplier::mutate(|fm| { + *fm = T::FeeMultiplierUpdate::convert(*fm) + }); + } + } +} + +impl Module { + /// Query the data that we know about the fee of a given `call`. + /// + /// As this module is not and cannot be aware of the internals of a signed extension, it only + /// interprets them as some encoded value and takes their length into account. + /// + /// All dispatchables must be annotated with weight and will have some fee info. This function + /// always returns. + // NOTE: we can actually make it understand `ChargeTransactionPayment`, but would be some hassle + // for sure. We have to make it aware of the index of `ChargeTransactionPayment` in `Extra`. + // Alternatively, we could actually execute the tx's per-dispatch and record the balance of the + // sender before and after the pipeline.. but this is way too much hassle for a very very little + // potential gain in the future. + pub fn query_info( + unchecked_extrinsic: Extrinsic, + len: u32, + ) -> RuntimeDispatchInfo> + where T: Send + Sync, + { + let dispatch_info = ::get_dispatch_info(&unchecked_extrinsic); + + let partial_fee = >::compute_fee(len, dispatch_info, 0u32.into()); + let DispatchInfo { weight, class } = dispatch_info; + + RuntimeDispatchInfo { weight, class, partial_fee } + } +} + +/// Require the transactor pay for themselves and maybe include a tip to gain additional priority +/// in the queue. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct ChargeTransactionPayment(#[codec(compact)] BalanceOf); + +impl ChargeTransactionPayment { + /// utility constructor. Used only in client/factory code. + pub fn from(fee: BalanceOf) -> Self { + Self(fee) + } + + /// Compute the final fee value for a particular transaction. + /// + /// The final fee is composed of: + /// - _length-fee_: This is the amount paid merely to pay for size of the transaction. + /// - _weight-fee_: This amount is computed based on the weight of the transaction. Unlike + /// size-fee, this is not input dependent and reflects the _complexity_ of the execution + /// and the time it consumes. + /// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed + /// transactions can have a tip. + fn compute_fee(len: u32, info: DispatchInfo, tip: BalanceOf) -> BalanceOf { + let len_fee = if info.pay_length_fee() { + let len = >::from(len); + let base = T::TransactionBaseFee::get(); + let per_byte = T::TransactionByteFee::get(); + base.saturating_add(per_byte.saturating_mul(len)) + } else { + Zero::zero() + }; + + let weight_fee = { + // cap the weight to the maximum defined in runtime, otherwise it will be the `Bounded` + // maximum of its data type, which is not desired. + let capped_weight = info.weight.min(::MaximumBlockWeight::get()); + T::WeightToFee::convert(capped_weight) + }; + + // everything except for tip + let basic_fee = len_fee.saturating_add(weight_fee); + let fee_update = NextFeeMultiplier::get(); + let adjusted_fee = fee_update.saturated_multiply_accumulate(basic_fee); + + adjusted_fee.saturating_add(tip) + } +} + +impl rstd::fmt::Debug for ChargeTransactionPayment { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + write!(f, "ChargeTransactionPayment<{:?}>", self.0) + } + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for ChargeTransactionPayment + where BalanceOf: Send + Sync +{ + type AccountId = T::AccountId; + type Call = T::Call; + type AdditionalSigned = (); + type Pre = (); + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + who: &Self::AccountId, + _call: &Self::Call, + info: DispatchInfo, + len: usize, + ) -> TransactionValidity { + // pay any fees. + let tip = self.0; + let fee = Self::compute_fee(len as u32, info, tip); + let imbalance = match T::Currency::withdraw( + who, + fee, + if tip.is_zero() { + WithdrawReason::TransactionPayment.into() + } else { + WithdrawReason::TransactionPayment | WithdrawReason::Tip + }, + ExistenceRequirement::KeepAlive, + ) { + Ok(imbalance) => imbalance, + Err(_) => return InvalidTransaction::Payment.into(), + }; + T::OnTransactionPayment::on_unbalanced(imbalance); + + let mut r = ValidTransaction::default(); + // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which + // will be a bit more than setting the priority to tip. For now, this is enough. + r.priority = fee.saturated_into::(); + Ok(r) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + use support::{parameter_types, impl_outer_origin, impl_outer_dispatch}; + use primitives::H256; + use sr_primitives::{ + Perbill, + testing::{Header, TestXt}, + traits::{BlakeTwo256, IdentityLookup, Extrinsic}, + weights::{DispatchClass, DispatchInfo, GetDispatchInfo}, + }; + use balances::Call as BalancesCall; + use rstd::cell::RefCell; + use transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; + + const CALL: &::Call = &Call::Balances(BalancesCall::transfer(2, 69)); + + impl_outer_dispatch! { + pub enum Call for Runtime where origin: Origin { + balances::Balances, + system::System, + } + } + + #[derive(Clone, PartialEq, Eq, Debug)] + pub struct Runtime; + + impl_outer_origin!{ + pub enum Origin for Runtime {} + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl system::Trait for Runtime { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = Call; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + } + + parameter_types! { + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + pub const ExistentialDeposit: u64 = 0; + } + + impl balances::Trait for Runtime { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + + thread_local! { + static TRANSACTION_BASE_FEE: RefCell = RefCell::new(0); + static TRANSACTION_BYTE_FEE: RefCell = RefCell::new(1); + static WEIGHT_TO_FEE: RefCell = RefCell::new(1); + } + + pub struct TransactionBaseFee; + impl Get for TransactionBaseFee { + fn get() -> u64 { TRANSACTION_BASE_FEE.with(|v| *v.borrow()) } + } + + pub struct TransactionByteFee; + impl Get for TransactionByteFee { + fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) } + } + + pub struct WeightToFee(u64); + impl Convert for WeightToFee { + fn convert(t: Weight) -> u64 { + WEIGHT_TO_FEE.with(|v| *v.borrow() * (t as u64)) + } + } + + impl Trait for Runtime { + type Currency = balances::Module; + type OnTransactionPayment = (); + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = WeightToFee; + type FeeMultiplierUpdate = (); + } + + type Balances = balances::Module; + type System = system::Module; + type TransactionPayment = Module; + + pub struct ExtBuilder { + balance_factor: u64, + base_fee: u64, + byte_fee: u64, + weight_to_fee: u64 + } + + impl Default for ExtBuilder { + fn default() -> Self { + Self { + balance_factor: 1, + base_fee: 0, + byte_fee: 1, + weight_to_fee: 1, + } + } + } + + impl ExtBuilder { + pub fn fees(mut self, base: u64, byte: u64, weight: u64) -> Self { + self.base_fee = base; + self.byte_fee = byte; + self.weight_to_fee = weight; + self + } + pub fn balance_factor(mut self, factor: u64) -> Self { + self.balance_factor = factor; + self + } + fn set_constants(&self) { + TRANSACTION_BASE_FEE.with(|v| *v.borrow_mut() = self.base_fee); + TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.byte_fee); + WEIGHT_TO_FEE.with(|v| *v.borrow_mut() = self.weight_to_fee); + } + pub fn build(self) -> runtime_io::TestExternalities { + self.set_constants(); + let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + balances::GenesisConfig:: { + balances: vec![ + (1, 10 * self.balance_factor), + (2, 20 * self.balance_factor), + (3, 30 * self.balance_factor), + (4, 40 * self.balance_factor), + (5, 50 * self.balance_factor), + (6, 60 * self.balance_factor) + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + } + + /// create a transaction info struct from weight. Handy to avoid building the whole struct. + pub fn info_from_weight(w: Weight) -> DispatchInfo { + DispatchInfo { weight: w, ..Default::default() } + } + + #[test] + fn signed_extension_transaction_payment_work() { + ExtBuilder::default() + .balance_factor(10) // 100 + .fees(5, 1, 1) // 5 fixed, 1 per byte, 1 per weight + .build() + .execute_with(|| + { + let len = 10; + assert!( + ChargeTransactionPayment::::from(0) + .pre_dispatch(&1, CALL, info_from_weight(5), len) + .is_ok() + ); + assert_eq!(Balances::free_balance(&1), 100 - 5 - 5 - 10); + + assert!( + ChargeTransactionPayment::::from(5 /* tipped */) + .pre_dispatch(&2, CALL, info_from_weight(3), len) + .is_ok() + ); + assert_eq!(Balances::free_balance(&2), 200 - 5 - 10 - 3 - 5); + }); + } + + #[test] + fn signed_extension_transaction_payment_is_bounded() { + ExtBuilder::default() + .balance_factor(1000) + .fees(0, 0, 1) + .build() + .execute_with(|| + { + use sr_primitives::weights::Weight; + + // maximum weight possible + assert!( + ChargeTransactionPayment::::from(0) + .pre_dispatch(&1, CALL, info_from_weight(Weight::max_value()), 10) + .is_ok() + ); + // fee will be proportional to what is the actual maximum weight in the runtime. + assert_eq!( + Balances::free_balance(&1), + (10000 - ::MaximumBlockWeight::get()) as u64 + ); + }); + } + + #[test] + fn signed_extension_allows_free_transactions() { + ExtBuilder::default() + .fees(100, 1, 1) + .balance_factor(0) + .build() + .execute_with(|| + { + // 1 ain't have a penny. + assert_eq!(Balances::free_balance(&1), 0); + + // like a FreeOperational + let operational_transaction = DispatchInfo { + weight: 0, + class: DispatchClass::Operational + }; + let len = 100; + assert!( + ChargeTransactionPayment::::from(0) + .validate(&1, CALL, operational_transaction , len) + .is_ok() + ); + + // like a FreeNormal + let free_transaction = DispatchInfo { + weight: 0, + class: DispatchClass::Normal + }; + assert!( + ChargeTransactionPayment::::from(0) + .validate(&1, CALL, free_transaction , len) + .is_err() + ); + }); + } + + #[test] + fn signed_ext_length_fee_is_also_updated_per_congestion() { + ExtBuilder::default() + .fees(5, 1, 1) + .balance_factor(10) + .build() + .execute_with(|| + { + // all fees should be x1.5 + NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); + let len = 10; + + assert!( + ChargeTransactionPayment::::from(10) // tipped + .pre_dispatch(&1, CALL, info_from_weight(3), len) + .is_ok() + ); + assert_eq!(Balances::free_balance(&1), 100 - 10 - (5 + 10 + 3) * 3 / 2); + }) + } + + #[test] + fn query_info_works() { + let call = Call::Balances(BalancesCall::transfer(2, 69)); + let origin = 111111; + let extra = (); + let xt = TestXt::new(call, Some((origin, extra))).unwrap(); + let info = xt.get_dispatch_info(); + let ext = xt.encode(); + let len = ext.len() as u32; + ExtBuilder::default() + .fees(5, 1, 2) + .build() + .execute_with(|| + { + // all fees should be x1.5 + NextFeeMultiplier::put(Fixed64::from_rational(1, 2)); + + assert_eq!( + TransactionPayment::query_info(xt, len), + RuntimeDispatchInfo { + weight: info.weight, + class: info.class, + partial_fee: ( + 5 /* base */ + + len as u64 /* len * 1 */ + + info.weight.min(MaximumBlockWeight::get()) as u64 * 2 /* weight * weight_to_fee */ + ) * 3 / 2 + }, + ); + + }); + } +} + + diff --git a/srml/treasury/Cargo.toml b/srml/treasury/Cargo.toml index ae2681e11b48e5e7ac665dd517d06e171d61d4e1..f19fa2c2188eb44a4d1e639c687146a1b60eda73 100644 --- a/srml/treasury/Cargo.toml +++ b/srml/treasury/Cargo.toml @@ -5,16 +5,16 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } balances = { package = "srml-balances", path = "../balances", default-features = false } [dev-dependencies] -runtime_io = { package = "sr-io", path = "../../core/sr-io" } +runtime-io ={ package = "sr-io", path = "../../core/sr-io" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } [features] @@ -24,7 +24,7 @@ std = [ "codec/std", "rstd/std", "sr-primitives/std", - "srml-support/std", + "support/std", "system/std", "balances/std", ] diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index 21c670e152e70ac02a7fe347254cc51e607942d6..504e374430d452a5a1b7f7ac5bbf3bf21ceded33 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -41,16 +41,6 @@ //! respectively. //! - **Pot:** Unspent funds accumulated by the treasury module. //! -//! ### Implementations -//! -//! The treasury module provides an implementation for the following trait: -//! -//! - `OnDilution` - When new funds are minted to reward the deployment of other existing funds, -//! a corresponding amount of tokens are minted into the treasury so that the tokens being rewarded -//! do not represent a higher portion of total supply. For example, in the default substrate node, -//! when validators are rewarded new tokens for staking, they do not hold a higher portion of total -//! tokens. Rather, tokens are added to the treasury to keep the portion of tokens staked constant. -//! //! ## Interface //! //! ### Dispatchable Functions @@ -70,14 +60,14 @@ #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; use rstd::prelude::*; -use srml_support::{StorageValue, StorageMap, decl_module, decl_storage, decl_event, ensure, print}; -use srml_support::traits::{ - Currency, ExistenceRequirement, Get, Imbalance, OnDilution, OnUnbalanced, +use support::{decl_module, decl_storage, decl_event, ensure, print}; +use support::traits::{ + Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, ReservableCurrency, WithdrawReason }; use sr_primitives::{Permill, ModuleId}; use sr_primitives::traits::{ - Zero, EnsureOrigin, StaticLookup, CheckedSub, CheckedMul, AccountIdConversion + Zero, EnsureOrigin, StaticLookup, AccountIdConversion, Saturating }; use sr_primitives::weights::SimpleDispatchInfo; use codec::{Encode, Decode}; @@ -89,11 +79,6 @@ type NegativeImbalanceOf = <::Currency as Currency< + ReservableCurrency; @@ -107,9 +92,6 @@ pub trait Trait: system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; - /// Handler for the unbalanced increase when minting cash from the "Pot". - type MintedForSpending: OnUnbalanced>; - /// Handler for the unbalanced decrease when slashing for a rejected proposal. type ProposalRejection: OnUnbalanced>; @@ -144,7 +126,7 @@ decl_module! { /// Percentage of spare funds (if any) that are burnt per spend period. const Burn: Permill = T::Burn::get(); - fn deposit_event() = default; + fn deposit_event() = default; /// Put forward a suggestion for spending. A deposit proportional to the value /// is reserved and slashed if the proposal is rejected. It is returned once the /// proposal is awarded. @@ -218,8 +200,8 @@ decl_module! { } /// A spending proposal. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[derive(Encode, Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Encode, Decode, Clone, PartialEq, Eq, sr_primitives::RuntimeDebug)] pub struct Proposal { proposer: AccountId, value: Balance, @@ -230,13 +212,22 @@ pub struct Proposal { decl_storage! { trait Store for Module as Treasury { /// Number of proposals that have been made. - ProposalCount get(proposal_count): ProposalIndex; + ProposalCount get(fn proposal_count): ProposalIndex; /// Proposals that have been made. - Proposals get(proposals): map ProposalIndex => Option>>; + Proposals get(fn proposals): map ProposalIndex => Option>>; /// Proposal indices that have been approved but not yet awarded. - Approvals get(approvals): Vec; + Approvals get(fn approvals): Vec; + } + add_extra_genesis { + build(|_config| { + // Create Treasury account + let _ = T::Currency::make_free_balance_be( + &>::account_id(), + T::Currency::minimum_balance(), + ); + }); } } @@ -256,6 +247,8 @@ decl_event!( Burnt(Balance), /// Spending has finished; this is the amount that rolls over until next spend. Rollover(Balance), + /// Some funds have been deposited. + Deposit(Balance), } ); @@ -316,10 +309,14 @@ impl Module { Self::deposit_event(RawEvent::Burnt(burn)) } + // Must never be an error, but better to be safe. + // proof: budget_remaining is account free balance minus ED; + // Thus we can't spend more than account free balance minus ED; + // Thus account is kept alive; qed; if let Err(problem) = T::Currency::settle( &Self::account_id(), imbalance, - WithdrawReason::Transfer, + WithdrawReason::Transfer.into(), ExistenceRequirement::KeepAlive ) { print("Inconsistent state - couldn't settle imbalance for funds spent by treasury"); @@ -330,30 +327,23 @@ impl Module { Self::deposit_event(RawEvent::Rollover(budget_remaining)); } + /// Return the amount of money in the pot. + // The existential deposit is not part of the pot so treasury account never gets deleted. fn pot() -> BalanceOf { T::Currency::free_balance(&Self::account_id()) + // Must never be less than 0 but better be safe. + .saturating_sub(T::Currency::minimum_balance()) } } impl OnUnbalanced> for Module { fn on_unbalanced(amount: NegativeImbalanceOf) { - T::Currency::resolve_creating(&Self::account_id(), amount); - } -} + let numeric_amount = amount.peek(); -impl OnDilution> for Module { - fn on_dilution(minted: BalanceOf, portion: BalanceOf) { - // Mint extra funds for the treasury to keep the ratio of portion to total_issuance equal - // pre dilution and post-dilution. - if !minted.is_zero() && !portion.is_zero() { - let total_issuance = T::Currency::total_issuance(); - if let Some(funding) = total_issuance.checked_sub(&portion) { - let funding = funding / portion; - if let Some(funding) = funding.checked_mul(&minted) { - Self::on_unbalanced(T::Currency::issue(funding)); - } - } - } + // Must resolve into existing but better to be safe. + let _ = T::Currency::resolve_creating(&Self::account_id(), amount); + + Self::deposit_event(RawEvent::Deposit(numeric_amount)); } } @@ -361,10 +351,11 @@ impl OnDilution> for Module { mod tests { use super::*; - use runtime_io::with_externalities; - use srml_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types}; - use primitives::{H256, Blake2Hasher}; - use sr_primitives::{Perbill, traits::{BlakeTwo256, OnFinalize, IdentityLookup}, testing::Header}; + use support::{assert_noop, assert_ok, impl_outer_origin, parameter_types}; + use primitives::H256; + use sr_primitives::{ + traits::{BlakeTwo256, OnFinalize, IdentityLookup}, testing::Header, Perbill + }; impl_outer_origin! { pub enum Origin for Test {} @@ -388,34 +379,28 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } parameter_types! { - pub const ExistentialDeposit: u64 = 0; + pub const ExistentialDeposit: u64 = 1; pub const TransferFee: u64 = 0; pub const CreationFee: u64 = 0; - pub const TransactionBaseFee: u64 = 0; - pub const TransactionByteFee: u64 = 0; } impl balances::Trait for Test { type Balance = u64; type OnNewAccount = (); type OnFreeBalanceZero = (); type Event = (); - type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = (); } parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(5); @@ -428,7 +413,6 @@ mod tests { type ApproveOrigin = system::EnsureRoot; type RejectOrigin = system::EnsureRoot; type Event = (); - type MintedForSpending = (); type ProposalRejection = (); type ProposalBond = ProposalBond; type ProposalBondMinimum = ProposalBondMinimum; @@ -438,18 +422,20 @@ mod tests { type Balances = balances::Module; type Treasury = Module; - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); balances::GenesisConfig::{ - balances: vec![(0, 100), (1, 99), (2, 1)], + // Total issuance will be 200 with treasury account initialized at ED. + balances: vec![(0, 100), (1, 98), (2, 1)], vesting: vec![], }.assimilate_storage(&mut t).unwrap(); + GenesisConfig::default().assimilate_storage::(&mut t).unwrap(); t.into() } #[test] fn genesis_config_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(Treasury::pot(), 0); assert_eq!(Treasury::proposal_count(), 0); }); @@ -457,16 +443,16 @@ mod tests { #[test] fn minting_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { // Check that accumulate works when we have Some value in Dummy already. - Treasury::on_dilution(100, 100); + Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_eq!(Treasury::pot(), 100); }); } #[test] fn spend_proposal_takes_min_deposit() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); assert_eq!(Balances::free_balance(&0), 99); assert_eq!(Balances::reserved_balance(&0), 1); @@ -475,7 +461,7 @@ mod tests { #[test] fn spend_proposal_takes_proportional_deposit() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_eq!(Balances::free_balance(&0), 95); assert_eq!(Balances::reserved_balance(&0), 5); @@ -484,15 +470,15 @@ mod tests { #[test] fn spend_proposal_fails_when_proposer_poor() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_noop!(Treasury::propose_spend(Origin::signed(2), 100, 3), "Proposer's balance too low"); }); } #[test] fn accepted_spend_proposal_ignored_outside_spend_period() { - with_externalities(&mut new_test_ext(), || { - Treasury::on_dilution(100, 100); + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); @@ -505,18 +491,21 @@ mod tests { #[test] fn unused_pot_should_diminish() { - with_externalities(&mut new_test_ext(), || { - Treasury::on_dilution(100, 100); + new_test_ext().execute_with(|| { + let init_total_issuance = Balances::total_issuance(); + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Balances::total_issuance(), init_total_issuance + 100); >::on_finalize(2); assert_eq!(Treasury::pot(), 50); + assert_eq!(Balances::total_issuance(), init_total_issuance + 50); }); } #[test] fn rejected_spend_proposal_ignored_on_spend_period() { - with_externalities(&mut new_test_ext(), || { - Treasury::on_dilution(100, 100); + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); @@ -529,8 +518,8 @@ mod tests { #[test] fn reject_already_rejected_spend_proposal_fails() { - with_externalities(&mut new_test_ext(), || { - Treasury::on_dilution(100, 100); + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); @@ -540,22 +529,22 @@ mod tests { #[test] fn reject_non_existant_spend_proposal_fails() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } #[test] fn accept_non_existant_spend_proposal_fails() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), "No proposal at that index"); }); } #[test] fn accept_already_rejected_spend_proposal_fails() { - with_externalities(&mut new_test_ext(), || { - Treasury::on_dilution(100, 100); + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); @@ -565,8 +554,8 @@ mod tests { #[test] fn accepted_spend_proposal_enacted_on_spend_period() { - with_externalities(&mut new_test_ext(), || { - Treasury::on_dilution(100, 100); + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_eq!(Treasury::pot(), 100); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); @@ -579,51 +568,80 @@ mod tests { } #[test] - // Note: This test demonstrates that `on_dilution` does not increase the pot with good resolution - // with large amounts of the network staked. https://github.com/paritytech/substrate/issues/2579 - // A fix to 2579 should include a change of this test. - fn on_dilution_quantization_effects() { - with_externalities(&mut new_test_ext(), || { - // minted = 1% of total issuance for all cases - assert_eq!(Balances::total_issuance(), 200); - - Treasury::on_dilution(2, 66); // portion = 33% of total issuance - assert_eq!(Treasury::pot(), 4); // should increase by 4 (200 - 66) / 66 * 2 - Balances::make_free_balance_be(&Treasury::account_id(), 0); - - Treasury::on_dilution(2, 67); // portion = 33+eps% of total issuance - assert_eq!(Treasury::pot(), 2); // should increase by 2 (200 - 67) / 67 * 2 - Balances::make_free_balance_be(&Treasury::account_id(), 0); - - Treasury::on_dilution(2, 100); // portion = 50% of total issuance - assert_eq!(Treasury::pot(), 2); // should increase by 2 (200 - 100) / 100 * 2 - Balances::make_free_balance_be(&Treasury::account_id(), 0); - - // If any more than 50% of the network is staked (i.e. (2 * portion) > total_issuance) - // then the pot will not increase. - Treasury::on_dilution(2, 101); // portion = 50+eps% of total issuance - assert_eq!(Treasury::pot(), 0); // should increase by 0 (200 - 101) / 101 * 2 - - Treasury::on_dilution(2, 134); // portion = 67% of total issuance - assert_eq!(Treasury::pot(), 0); // should increase by 0 (200 - 134) / 134 * 2 + fn pot_underflow_should_not_diminish() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + + >::on_finalize(2); + assert_eq!(Treasury::pot(), 100); // Pot hasn't changed + + Balances::deposit_into_existing(&Treasury::account_id(), 100); + >::on_finalize(4); + assert_eq!(Balances::free_balance(&3), 150); // Fund has been spent + assert_eq!(Treasury::pot(), 25); // Pot has finally changed }); } + // Treasury account doesn't get deleted if amount approved to spend is all its free balance. + // i.e. pot should not include existential deposit needed for account survival. #[test] - fn pot_underflow_should_not_diminish() { - with_externalities(&mut new_test_ext(), || { - Treasury::on_dilution(100, 100); + fn treasury_account_doesnt_get_deleted() { + new_test_ext().execute_with(|| { + Balances::make_free_balance_be(&Treasury::account_id(), 101); + assert_eq!(Treasury::pot(), 100); + let treasury_balance = Balances::free_balance(&Treasury::account_id()); - assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), treasury_balance, 3)); assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); >::on_finalize(2); - assert_eq!(Treasury::pot(), 100); + assert_eq!(Treasury::pot(), 100); // Pot hasn't changed + + assert_ok!(Treasury::propose_spend(Origin::signed(0), Treasury::pot(), 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); + + >::on_finalize(4); + assert_eq!(Treasury::pot(), 0); // Pot is emptied + assert_eq!(Balances::free_balance(&Treasury::account_id()), 1); // but the account is still there + }); + } + + // In case treasury account is not existing then it works fine. + // This is usefull for chain that will just update runtime. + #[test] + fn inexisting_account_works() { + let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + balances::GenesisConfig::{ + balances: vec![(0, 100), (1, 99), (2, 1)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + // Treasury genesis config is not build thus treasury account does not exist + let mut t: runtime_io::TestExternalities = t.into(); + + t.execute_with(|| { + assert_eq!(Balances::free_balance(&Treasury::account_id()), 0); // Account does not exist + assert_eq!(Treasury::pot(), 0); // Pot is empty + + assert_ok!(Treasury::propose_spend(Origin::signed(0), 99, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); + assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); + assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); + >::on_finalize(2); + assert_eq!(Treasury::pot(), 0); // Pot hasn't changed + assert_eq!(Balances::free_balance(&3), 0); // Balance of `3` hasn't changed + + Balances::make_free_balance_be(&Treasury::account_id(), 100); + assert_eq!(Treasury::pot(), 99); // Pot now contains funds + assert_eq!(Balances::free_balance(&Treasury::account_id()), 100); // Account does exist - Treasury::on_dilution(100, 100); >::on_finalize(4); - assert_eq!(Balances::free_balance(&3), 150); - assert_eq!(Treasury::pot(), 75); + + assert_eq!(Treasury::pot(), 0); // Pot has changed + assert_eq!(Balances::free_balance(&3), 99); // Balance of `3` has changed }); } } diff --git a/srml/utility/Cargo.toml b/srml/utility/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..5e92bcf88ad4860ce0ddeed6172d05c6aa87f7ac --- /dev/null +++ b/srml/utility/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "srml-utility" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime-io = { package = "sr-io", path = "../../core/sr-io", default-features = false } + +[dev-dependencies] +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +balances = { package = "srml-balances", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sr-primitives/std", + "support/std", + "system/std", + "runtime-io/std", + "rstd/std" +] diff --git a/srml/utility/src/lib.rs b/srml/utility/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d69e260ff9aac4f7b25c8b1923ff238e28456c7a --- /dev/null +++ b/srml/utility/src/lib.rs @@ -0,0 +1,158 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Utility Module +//! A module full of useful helpers for practical chain management. + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::prelude::*; +use support::{decl_module, decl_event, Parameter}; +use system::ensure_root; +use sr_primitives::{traits::Dispatchable, weights::SimpleDispatchInfo, DispatchError}; + +/// Configuration trait. +pub trait Trait: system::Trait { + /// The overarching event type. + type Event: From + Into<::Event>; + + /// The overarching call type. + type Call: Parameter + Dispatchable; +} + +decl_event!( + /// Events type. + pub enum Event { + BatchExecuted(Vec>), + } +); + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Deposit one of this module's events by using the default implementation. + fn deposit_event() = default; + + /// Send a batch of dispatch calls (only root). + #[weight = SimpleDispatchInfo::FreeOperational] + fn batch(origin, calls: Vec<::Call>) { + ensure_root(origin)?; + let results = calls.into_iter() + .map(|call| call.dispatch(system::RawOrigin::Root.into())) + .map(|res| res.map_err(Into::into)) + .collect::>(); + Self::deposit_event(Event::BatchExecuted(results)); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use support::{assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch}; + use primitives::H256; + use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + + impl_outer_origin! { + pub enum Origin for Test {} + } + + impl_outer_dispatch! { + pub enum Call for Test where origin: Origin { + balances::Balances, + utility::Utility, + } + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = Call; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + impl Trait for Test { + type Event = (); + type Call = Call; + } + type Balances = balances::Module; + type Utility = Module; + + fn new_test_ext() -> runtime_io::TestExternalities { + let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + balances::GenesisConfig:: { + balances: vec![(1, 10), (2, 0)], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn batch_works() { + new_test_ext().execute_with(|| { + assert_eq!(Balances::free_balance(1), 10); + assert_eq!(Balances::free_balance(2), 0); + assert_noop!(Utility::batch(Origin::signed(1), vec![ + Call::Balances(balances::Call::force_transfer(1, 2, 5)), + Call::Balances(balances::Call::force_transfer(1, 2, 5)) + ]), "RequireRootOrigin"); + assert_ok!(Utility::batch(Origin::ROOT, vec![ + Call::Balances(balances::Call::force_transfer(1, 2, 5)), + Call::Balances(balances::Call::force_transfer(1, 2, 5)) + ])); + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::free_balance(2), 10); + }); + } +} diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml index 9e7112a029c203d84eeac2ee79fb2d05fe542a5e..e1c3ef64d26d410e12794c03679486735567cb3c 100644 --- a/subkey/Cargo.toml +++ b/subkey/Cargo.toml @@ -9,16 +9,17 @@ primitives = { package = "substrate-primitives", version = "*", path = "../core node-runtime = { version = "*", path = "../node/runtime" } node-primitives = { version = "*", path = "../node/primitives" } sr-primitives = { version = "*", path = "../core/sr-primitives" } -rand = "0.6" -clap = { version = "~2.32", features = ["yaml"] } -tiny-bip39 = "0.6.0" -rustc-hex = "2.0" +rand = "0.7.2" +clap = { version = "2.33.0", features = ["yaml"] } +tiny-bip39 = "0.6.2" +rustc-hex = "2.0.1" substrate-bip39 = "0.3.1" -hex = "0.3" -hex-literal = "0.2" +hex = "0.3.2" +hex-literal = "0.2.1" codec = { package = "parity-scale-codec", version = "1.0.0" } system = { package = "srml-system", path = "../srml/system" } balances = { package = "srml-balances", path = "../srml/balances" } +transaction-payment = { package = "srml-transaction-payment", path = "../srml/transaction-payment" } [features] bench = [] diff --git a/subkey/README.adoc b/subkey/README.adoc index 52770e78ec4432778a5683bd140e25005b877a96..07533a002f80ef1f1912b352829c147be81bad88 100644 --- a/subkey/README.adoc +++ b/subkey/README.adoc @@ -31,7 +31,7 @@ OUTPUT: `subkey` expects a message to come in on STDIN, one way to sign a message would look like this: ```bash -echo | subkey sign +echo -n | subkey sign OUTPUT: a69da4a6ccbf81dbbbfad235fa12cf8528c18012b991ae89214de8d20d29c1280576ced6eb38b7406d1b7e03231df6dd4a5257546ddad13259356e1c3adfb509 @@ -40,7 +40,7 @@ a69da4a6ccbf81dbbbfad235fa12cf8528c18012b991ae89214de8d20d29c1280576ced6eb38b740 === Verifying a signature ```bash -echo | subkey verify

+echo -n | subkey verify
OUTPUT: Signature verifies correctly. diff --git a/subkey/src/cli.yml b/subkey/src/cli.yml index b4f99f8743fa545898a93e06e9693c737b66bc16..5d8cd11b1e6f8def2ff8a4dfb3ae877e6f8d6057 100644 --- a/subkey/src/cli.yml +++ b/subkey/src/cli.yml @@ -12,6 +12,11 @@ args: long: sr25519 help: Use Schnorr/Ristretto x25519/BIP39 cryptography takes_value: false + - secp256k1: + short: k + long: secp256k1 + help: Use SECP256k1/ECDSA/BIP39 cryptography + takes_value: false - password: short: p long: password @@ -23,7 +28,7 @@ args: long: network takes_value: true required: false - help: Specify a network. One of substrate (default), polkadot and kusama. + help: Specify a network. One of substrate (default), polkadot, kusama, or dothereum. subcommands: - generate: about: Generate a random account diff --git a/subkey/src/main.rs b/subkey/src/main.rs index fde301b44f25c7b9954a8517a7c7f56579f46cdc..1b537580f57ff739f41c9a552ebbfd28bac7161c 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -18,54 +18,86 @@ #[cfg(feature = "bench")] extern crate test; -use std::{str::FromStr, io::{stdin, Read}, convert::TryInto}; +use bip39::{Language, Mnemonic, MnemonicType}; +use clap::{load_yaml, App, ArgMatches}; +use codec::{Decode, Encode}; use hex_literal::hex; -use clap::load_yaml; -use bip39::{Mnemonic, Language, MnemonicType}; +use node_primitives::{Balance, Hash, Index, AccountId, Signature}; +use node_runtime::{BalancesCall, Call, Runtime, SignedPayload, UncheckedExtrinsic, VERSION}; use primitives::{ - ed25519, sr25519, hexdisplay::HexDisplay, Pair, Public, blake2_256, - crypto::{Ss58Codec, set_default_ss58_version, Ss58AddressFormat} + crypto::{set_default_ss58_version, Ss58AddressFormat, Ss58Codec}, + ed25519, sr25519, ecdsa, Pair, Public, H256, hexdisplay::HexDisplay, +}; +use sr_primitives::{traits::{IdentifyAccount, Verify}, generic::Era}; +use std::{ + convert::{TryInto, TryFrom}, + io::{stdin, Read}, + str::FromStr, }; -use codec::{Encode, Decode}; -use sr_primitives::generic::Era; -use node_primitives::{Balance, Index, Hash}; -use node_runtime::{Call, UncheckedExtrinsic, BalancesCall, Runtime}; mod vanity; -trait Crypto { - type Pair: Pair; +trait Crypto: Sized { + type Pair: Pair; type Public: Public + Ss58Codec + AsRef<[u8]> + std::hash::Hash; fn pair_from_suri(suri: &str, password: Option<&str>) -> Self::Pair { Self::Pair::from_string(suri, password).expect("Invalid phrase") } - fn ss58_from_pair(pair: &Self::Pair) -> String { pair.public().to_ss58check() } - fn public_from_pair(pair: &Self::Pair) -> Vec { pair.public().as_ref().to_owned() } + fn ss58_from_pair(pair: &Self::Pair) -> String where + ::Public: PublicT, + { + pair.public().into_runtime().into_account().to_ss58check() + } + fn public_from_pair(pair: &Self::Pair) -> Self::Public { + pair.public() + } fn print_from_uri( uri: &str, password: Option<&str>, network_override: Option, - ) where ::Public: Sized + Ss58Codec + AsRef<[u8]> { + ) where + ::Public: PublicT, + { if let Ok((pair, seed)) = Self::Pair::from_phrase(uri, password) { - println!("Secret phrase `{}` is account:\n Secret seed: 0x{}\n Public key (hex): 0x{}\n Address (SS58): {}", + let public_key = Self::public_from_pair(&pair); + println!("Secret phrase `{}` is account:\n \ + Secret seed: {}\n \ + Public key (hex): {}\n \ + Account ID: {}\n \ + SS58 Address: {}", uri, - HexDisplay::from(&seed.as_ref()), - HexDisplay::from(&Self::public_from_pair(&pair)), + format_seed::(seed), + format_public_key::(public_key.clone()), + format_account_id::(public_key), Self::ss58_from_pair(&pair) ); - } else if let Ok(pair) = Self::Pair::from_string(uri, password) { - println!("Secret Key URI `{}` is account:\n Public key (hex): 0x{}\n Address (SS58): {}", + } else if let Ok((pair, seed)) = Self::Pair::from_string_with_seed(uri, password) { + let public_key = Self::public_from_pair(&pair); + println!("Secret Key URI `{}` is account:\n \ + Secret seed: {}\n \ + Public key (hex): {}\n \ + Account ID: {}\n \ + SS58 Address: {}", uri, - HexDisplay::from(&Self::public_from_pair(&pair)), + if let Some(seed) = seed { format_seed::(seed) } else { "n/a".into() }, + format_public_key::(public_key.clone()), + format_account_id::(public_key), Self::ss58_from_pair(&pair) ); - } else if let Ok((public, v)) = ::Public::from_string_with_version(uri) { + } else if let Ok((public_key, v)) = + ::Public::from_string_with_version(uri) + { let v = network_override.unwrap_or(v); - println!("Public Key URI `{}` is account:\n Network ID/version: {}\n Public key (hex): 0x{}\n Address (SS58): {}", + println!("Public Key URI `{}` is account:\n \ + Network ID/version: {}\n \ + Public key (hex): {}\n \ + Account ID: {}\n \ + SS58 Address: {}", uri, String::from(v), - HexDisplay::from(&public.as_ref()), - public.to_ss58check_with_version(v) + format_public_key::(public_key.clone()), + format_account_id::(public_key.clone()), + public_key.to_ss58check_with_version(v) ); } else { println!("Invalid phrase/URI given"); @@ -91,215 +123,405 @@ impl Crypto for Sr25519 { type Public = sr25519::Public; } -fn execute(matches: clap::ArgMatches) where - <::Pair as Pair>::Signature: AsRef<[u8]> + AsMut<[u8]> + Default, - <::Pair as Pair>::Public: Sized + AsRef<[u8]> + Ss58Codec, +struct Ecdsa; + +impl Crypto for Ecdsa { + type Pair = ecdsa::Pair; + type Public = ecdsa::Public; +} + +type SignatureOf = <::Pair as Pair>::Signature; +type PublicOf = <::Pair as Pair>::Public; +type SeedOf = <::Pair as Pair>::Seed; +type AccountPublic = ::Signer; + +trait SignatureT: AsRef<[u8]> + AsMut<[u8]> + Default { + /// Converts the signature into a runtime account signature, if possible. If not possible, bombs out. + fn into_runtime(self) -> Signature { + panic!("This cryptography isn't supported for this runtime.") + } +} +trait PublicT: Sized + AsRef<[u8]> + Ss58Codec { + /// Converts the public key into a runtime account public key, if possible. If not possible, bombs out. + fn into_runtime(self) -> AccountPublic { + panic!("This cryptography isn't supported for this runtime.") + } +} + +impl SignatureT for sr25519::Signature { fn into_runtime(self) -> Signature { self.into() } } +impl SignatureT for ed25519::Signature { fn into_runtime(self) -> Signature { self.into() } } +impl SignatureT for ecdsa::Signature { fn into_runtime(self) -> Signature { self.into() } } +impl PublicT for sr25519::Public { fn into_runtime(self) -> AccountPublic { self.into() } } +impl PublicT for ed25519::Public { fn into_runtime(self) -> AccountPublic { self.into() } } +impl PublicT for ecdsa::Public { fn into_runtime(self) -> AccountPublic { self.into() } } + +fn main() { + let yaml = load_yaml!("cli.yml"); + let matches = App::from_yaml(yaml) + .version(env!("CARGO_PKG_VERSION")) + .get_matches(); + + if matches.is_present("ed25519") { + return execute::(matches) + } + if matches.is_present("secp256k1") { + return execute::(matches) + } + return execute::(matches) +} + +fn execute(matches: ArgMatches) +where + SignatureOf: SignatureT, + PublicOf: PublicT, { - let extra = |i: Index, f: Balance| { - ( - system::CheckGenesis::::new(), - system::CheckEra::::from(Era::Immortal), - system::CheckNonce::::from(i), - system::CheckWeight::::new(), - balances::TakeFees::::from(f), - ) - }; let password = matches.value_of("password"); - let maybe_network: Option = matches.value_of("network") - .map(|network| network.try_into() - .expect("Invalid network name: must be polkadot/substrate/kusama") - ); + let maybe_network: Option = matches.value_of("network").map(|network| { + network + .try_into() + .expect("Invalid network name: must be polkadot/substrate/kusama/dothereum") + }); if let Some(network) = maybe_network { set_default_ss58_version(network); } match matches.subcommand() { ("generate", Some(matches)) => { - // create a new randomly generated mnemonic phrase - let words = matches.value_of("words") - .map(|x| usize::from_str(x).expect("Invalid number given for --words")) - .map(|x| MnemonicType::for_word_count(x) - .expect("Invalid number of words given for phrase: must be 12/15/18/21/24") - ).unwrap_or(MnemonicType::Words12); - let mnemonic = Mnemonic::new(words, Language::English); + let mnemonic = generate_mnemonic(matches); C::print_from_uri(mnemonic.phrase(), password, maybe_network); } ("inspect", Some(matches)) => { - let uri = matches.value_of("uri") + let uri = matches + .value_of("uri") .expect("URI parameter is required; thus it can't be None; qed"); C::print_from_uri(uri, password, maybe_network); } - ("vanity", Some(matches)) => { - let desired: String = matches.value_of("pattern").map(str::to_string).unwrap_or_default(); - let result = vanity::generate_key::(&desired).expect("Key generation failed"); - C::print_from_uri( - &format!("0x{}", HexDisplay::from(&result.seed.as_ref())), - None, - maybe_network - ); - } ("sign", Some(matches)) => { - let suri = matches.value_of("suri") - .expect("secret URI parameter is required; thus it can't be None; qed"); - let pair = C::pair_from_suri(suri, password); - let mut message = vec![]; - stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); - if matches.is_present("hex") { - message = hex::decode(&message).expect("Invalid hex in message"); + let should_decode = matches.is_present("hex"); + let message = read_message_from_stdin(should_decode); + let signature = do_sign::(matches, message, password); + println!("{}", signature); + } + ("verify", Some(matches)) => { + let should_decode = matches.is_present("hex"); + let message = read_message_from_stdin(should_decode); + let is_valid_signature = do_verify::(matches, message); + if is_valid_signature { + println!("Signature verifies correctly."); + } else { + println!("Signature invalid."); } - let sig = pair.sign(&message); - println!("{}", hex::encode(&sig)); + } + ("vanity", Some(matches)) => { + let desired: String = matches + .value_of("pattern") + .map(str::to_string) + .unwrap_or_default(); + let result = vanity::generate_key::(&desired).expect("Key generation failed"); + let formated_seed = format_seed::(result.seed); + C::print_from_uri(&formated_seed, None, maybe_network); } ("transfer", Some(matches)) => { - let signer = matches.value_of("from") - .expect("parameter is required; thus it can't be None; qed"); - let signer = Sr25519::pair_from_suri(signer, password); - - let to = matches.value_of("to") - .expect("parameter is required; thus it can't be None; qed"); - let to = sr25519::Public::from_string(to).ok().or_else(|| - sr25519::Pair::from_string(to, password).ok().map(|p| p.public()) - ).expect("Invalid 'to' URI; expecting either a secret URI or a public URI."); - - let amount = matches.value_of("amount") - .expect("parameter is required; thus it can't be None; qed"); - let amount = str::parse::(amount) - .expect("Invalid 'amount' parameter; expecting an integer."); - - let index = matches.value_of("index") - .expect("parameter is required; thus it can't be None; qed"); - let index = str::parse::(index) - .expect("Invalid 'amount' parameter; expecting an integer."); + let signer = read_pair::(matches.value_of("from"), password); + let index = read_required_parameter::(matches, "index"); + let genesis_hash = read_genesis_hash(matches); + let to: AccountId = read_account_id(matches.value_of("to")); + let amount = read_required_parameter::(matches, "amount"); let function = Call::Balances(BalancesCall::transfer(to.into(), amount)); - let genesis_hash: Hash = match matches.value_of("genesis").unwrap_or("alex") { - "elm" => hex!["10c08714a10c7da78f40a60f6f732cf0dba97acfb5e2035445b032386157d5c3"].into(), - "alex" => hex!["dcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b"].into(), - h => hex::decode(h).ok().and_then(|x| Decode::decode(&mut &x[..]).ok()) - .expect("Invalid genesis hash or unrecognised chain identifier"), - }; + let extrinsic = create_extrinsic::(function, index, signer, genesis_hash); - println!("Using a genesis hash of {}", HexDisplay::from(&genesis_hash.as_ref())); - - let raw_payload = ( - function, - extra(index, 0), - (&genesis_hash, &genesis_hash), - ); - let signature = raw_payload.using_encoded(|payload| if payload.len() > 256 { - signer.sign(&blake2_256(payload)[..]) - } else { - println!("Signing {}", HexDisplay::from(&payload)); - signer.sign(payload) - }); - let extrinsic = UncheckedExtrinsic::new_signed( - raw_payload.0, - signer.public().into(), - signature.into(), - extra(index, 0), - ); - println!("0x{}", hex::encode(&extrinsic.encode())); + print_extrinsic(extrinsic); } ("sign-transaction", Some(matches)) => { - let s = matches.value_of("suri") - .expect("secret URI parameter is required; thus it can't be None; qed"); - let signer = Sr25519::pair_from_suri(s, password); - - let index = matches.value_of("nonce") - .expect("nonce is required; thus it can't be None; qed"); - let index = str::parse::(index) - .expect("Invalid 'index' parameter; expecting an integer."); - - let call = matches.value_of("call") - .expect("call is required; thus it can't be None; qed"); - let function: Call = hex::decode(&call).ok() - .and_then(|x| Decode::decode(&mut &x[..]).ok()).unwrap(); - - let genesis_hash: Hash = match matches.value_of("genesis").unwrap_or("alex") { - "elm" => hex!["10c08714a10c7da78f40a60f6f732cf0dba97acfb5e2035445b032386157d5c3"].into(), - "alex" => hex!["dcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b"].into(), - h => hex::decode(h).ok().and_then(|x| Decode::decode(&mut &x[..]).ok()) - .expect("Invalid genesis hash or unrecognised chain identifier"), - }; - - println!("Using a genesis hash of {}", HexDisplay::from(&genesis_hash.as_ref())); - - let raw_payload = ( - function, - extra(index, 0), - (&genesis_hash, &genesis_hash), - ); - let signature = raw_payload.using_encoded(|payload| - if payload.len() > 256 { - signer.sign(&blake2_256(payload)[..]) - } else { - signer.sign(payload) - } - ); + let signer = read_pair::(matches.value_of("suri"), password); + let index = read_required_parameter::(matches, "nonce"); + let genesis_hash = read_genesis_hash(matches); - let extrinsic = UncheckedExtrinsic::new_signed( - raw_payload.0, - signer.public().into(), - signature.into(), - extra(index, 0), - ); + let call = matches.value_of("call").expect("call is required; qed"); + let function: Call = hex::decode(&call) + .ok() + .and_then(|x| Decode::decode(&mut &x[..]).ok()) + .unwrap(); - println!("0x{}", hex::encode(&extrinsic.encode())); - } - ("verify", Some(matches)) => { - let sig_data = matches.value_of("sig") - .expect("signature parameter is required; thus it can't be None; qed"); - let mut sig = <::Pair as Pair>::Signature::default(); - let sig_data = hex::decode(sig_data).expect("signature is invalid hex"); - if sig_data.len() != sig.as_ref().len() { - panic!("signature is an invalid length. {} bytes is not the expected value of {} bytes", sig_data.len(), sig.as_ref().len()); - } - sig.as_mut().copy_from_slice(&sig_data); - let uri = matches.value_of("uri") - .expect("public uri parameter is required; thus it can't be None; qed"); - let pubkey = <::Pair as Pair>::Public::from_string(uri).ok().or_else(|| - ::Pair::from_string(uri, password).ok().map(|p| p.public()) - ).expect("Invalid URI; expecting either a secret URI or a public URI."); - let mut message = vec![]; - stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); - if matches.is_present("hex") { - message = hex::decode(&message).expect("Invalid hex in message"); - } - if <::Pair as Pair>::verify(&sig, &message, &pubkey) { - println!("Signature verifies correctly.") - } else { - println!("Signature invalid.") - } + let extrinsic = create_extrinsic::(function, index, signer, genesis_hash); + + print_extrinsic(extrinsic); } _ => print_usage(&matches), } } -fn main() { - let yaml = load_yaml!("cli.yml"); - let matches = clap::App::from_yaml(yaml) - .version(env!("CARGO_PKG_VERSION")) - .get_matches(); +/// Creates a new randomly generated mnemonic phrase. +fn generate_mnemonic(matches: &ArgMatches) -> Mnemonic { + let words = matches + .value_of("words") + .map(|x| usize::from_str(x).expect("Invalid number given for --words")) + .map(|x| { + MnemonicType::for_word_count(x) + .expect("Invalid number of words given for phrase: must be 12/15/18/21/24") + }) + .unwrap_or(MnemonicType::Words12); + Mnemonic::new(words, Language::English) +} - if matches.is_present("ed25519") { - execute::(matches) +fn do_sign(matches: &ArgMatches, message: Vec, password: Option<&str>) -> String +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let pair = read_pair::(matches.value_of("suri"), password); + let signature = pair.sign(&message); + format_signature::(&signature) +} + +fn do_verify(matches: &ArgMatches, message: Vec) -> bool +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let signature = read_signature::(matches); + let pubkey = read_public_key::(matches.value_of("uri")); + <::Pair as Pair>::verify(&signature, &message, &pubkey) +} + +fn read_message_from_stdin(should_decode: bool) -> Vec { + let mut message = vec![]; + stdin() + .lock() + .read_to_end(&mut message) + .expect("Error reading from stdin"); + if should_decode { + message = hex::decode(&message).expect("Invalid hex in message"); + } + message +} + +fn read_required_parameter(matches: &ArgMatches, name: &str) -> T +where + ::Err: std::fmt::Debug, +{ + let str_value = matches + .value_of(name) + .expect("parameter is required; thus it can't be None; qed"); + str::parse::(str_value).expect("Invalid 'nonce' parameter; expecting an integer.") +} + +fn read_genesis_hash(matches: &ArgMatches) -> H256 { + let genesis_hash: Hash = match matches.value_of("genesis").unwrap_or("alex") { + "elm" => hex!["10c08714a10c7da78f40a60f6f732cf0dba97acfb5e2035445b032386157d5c3"].into(), + "alex" => hex!["dcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b"].into(), + h => hex::decode(h) + .ok() + .and_then(|x| Decode::decode(&mut &x[..]).ok()) + .expect("Invalid genesis hash or unrecognised chain identifier"), + }; + println!( + "Using a genesis hash of {}", + HexDisplay::from(&genesis_hash.as_ref()) + ); + genesis_hash +} + +fn read_signature(matches: &ArgMatches) -> SignatureOf +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let sig_data = matches + .value_of("sig") + .expect("signature parameter is required; thus it can't be None; qed"); + let mut signature = <::Pair as Pair>::Signature::default(); + let sig_data = hex::decode(sig_data).expect("signature is invalid hex"); + if sig_data.len() != signature.as_ref().len() { + panic!( + "signature has an invalid length. read {} bytes, expected {} bytes", + sig_data.len(), + signature.as_ref().len(), + ); + } + signature.as_mut().copy_from_slice(&sig_data); + signature +} + +fn read_public_key(matched_uri: Option<&str>) -> PublicOf where + PublicOf: PublicT, +{ + let uri = matched_uri.expect("parameter is required; thus it can't be None; qed"); + let uri = if uri.starts_with("0x") { + &uri[2..] } else { - execute::(matches) + uri + }; + if let Ok(pubkey_vec) = hex::decode(uri) { + ::Public::from_slice(pubkey_vec.as_slice()) + } else { + ::Public::from_string(uri) + .ok() + .expect("Invalid URI; expecting either a secret URI or a public URI.") } } -fn print_usage(matches: &clap::ArgMatches) { +fn read_account_id(matched_uri: Option<&str>) -> AccountId { + let uri = matched_uri.expect("parameter is required; thus it can't be None; qed"); + let uri = if uri.starts_with("0x") { + &uri[2..] + } else { + uri + }; + if let Ok(data_vec) = hex::decode(uri) { + AccountId::try_from(data_vec.as_slice()) + .expect("Invalid hex length for account ID; should be 32 bytes") + } else { + AccountId::from_ss58check(uri).ok() + .expect("Invalid SS58-check address given for account ID.") + } +} + +fn read_pair( + matched_suri: Option<&str>, + password: Option<&str>, +) -> ::Pair +where + SignatureOf: SignatureT, + PublicOf: PublicT, +{ + let suri = matched_suri.expect("parameter is required; thus it can't be None; qed"); + C::pair_from_suri(suri, password) +} + +fn format_signature(signature: &SignatureOf) -> String { + format!("{}", hex::encode(signature)) +} + +fn format_seed(seed: SeedOf) -> String { + format!("0x{}", HexDisplay::from(&seed.as_ref())) +} + +fn format_public_key(public_key: PublicOf) -> String { + format!("0x{}", HexDisplay::from(&public_key.as_ref())) +} + +fn format_account_id(public_key: PublicOf) -> String where + PublicOf: PublicT, +{ + format!("0x{}", HexDisplay::from(&public_key.into_runtime().into_account().as_ref())) +} + +fn create_extrinsic( + function: Call, + index: Index, + signer: C::Pair, + genesis_hash: H256, +) -> UncheckedExtrinsic where + PublicOf: PublicT, + SignatureOf: SignatureT, +{ + let extra = |i: Index, f: Balance| { + ( + system::CheckVersion::::new(), + system::CheckGenesis::::new(), + system::CheckEra::::from(Era::Immortal), + system::CheckNonce::::from(i), + system::CheckWeight::::new(), + transaction_payment::ChargeTransactionPayment::::from(f), + Default::default(), + ) + }; + let raw_payload = SignedPayload::from_raw( + function, + extra(index, 0), + ( + VERSION.spec_version as u32, + genesis_hash, + genesis_hash, + (), + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)).into_runtime(); + let signer = signer.public().into_runtime(); + let (function, extra, _) = raw_payload.deconstruct(); + + UncheckedExtrinsic::new_signed( + function, + signer.into_account().into(), + signature, + extra, + ) +} + +fn print_extrinsic(extrinsic: UncheckedExtrinsic) { + println!("0x{}", hex::encode(&extrinsic.encode())); +} + +fn print_usage(matches: &ArgMatches) { println!("{}", matches.usage()); } #[cfg(test)] mod tests { - use super::{Hash, Decode}; + use super::*; + + fn test_generate_sign_verify() + where + SignatureOf: SignatureT, + PublicOf: PublicT, + { + let yaml = load_yaml!("cli.yml"); + let app = App::from_yaml(yaml); + let password = None; + + // Generate public key and seed. + let arg_vec = vec!["subkey", "generate"]; + + let matches = app.clone().get_matches_from(arg_vec); + let matches = matches.subcommand().1.unwrap(); + let mnemonic = generate_mnemonic(matches); + + let (pair, seed) = + <::Pair as Pair>::from_phrase(mnemonic.phrase(), password) + .unwrap(); + let public_key = CryptoType::public_from_pair(&pair); + let public_key = format_public_key::(public_key); + let seed = format_seed::(seed); + + // Sign a message using previous seed. + let arg_vec = vec!["subkey", "sign", &seed[..]]; + + let matches = app.get_matches_from(arg_vec); + let matches = matches.subcommand().1.unwrap(); + let message = "Blah Blah\n".as_bytes().to_vec(); + let signature = do_sign::(matches, message.clone(), password); + + // Verify the previous signature. + let arg_vec = vec!["subkey", "verify", &signature[..], &public_key[..]]; + + let matches = App::from_yaml(yaml).get_matches_from(arg_vec); + let matches = matches.subcommand().1.unwrap(); + assert!(do_verify::(matches, message)); + } + + #[test] + fn generate_sign_verify_should_work_for_ed25519() { + test_generate_sign_verify::(); + } + + #[test] + fn generate_sign_verify_should_work_for_sr25519() { + test_generate_sign_verify::(); + } + #[test] fn should_work() { let s = "0123456789012345678901234567890123456789012345678901234567890123"; - let d1: Hash = hex::decode(s).ok().and_then(|x| Decode::decode(&mut &x[..]).ok()).unwrap(); + let d1: Hash = hex::decode(s) + .ok() + .and_then(|x| Decode::decode(&mut &x[..]).ok()) + .unwrap(); let d2: Hash = { let mut gh: [u8; 32] = Default::default(); diff --git a/subkey/src/vanity.rs b/subkey/src/vanity.rs index 988055c67cac4402c67f8c2da3d2afe469027ec9..835001a0aa9d0d4dd82b7e719a91f907cce4f495 100644 --- a/subkey/src/vanity.rs +++ b/subkey/src/vanity.rs @@ -14,15 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use rand::{rngs::OsRng, RngCore}; -use super::Crypto; +use super::{PublicOf, PublicT, Crypto}; use primitives::Pair; +use rand::{rngs::OsRng, RngCore}; fn good_waypoint(done: u64) -> u64 { match done { - 0 ..= 1_000_000 => 100_000, - 0 ..= 10_000_000 => 1_000_000, - 0 ..= 100_000_000 => 10_000_000, + 0..=1_000_000 => 100_000, + 0..=10_000_000 => 1_000_000, + 0..=100_000_000 => 10_000_000, _ => 100_000_000, } } @@ -30,8 +30,13 @@ fn good_waypoint(done: u64) -> u64 { fn next_seed(seed: &mut [u8]) { for i in 0..seed.len() { match seed[i] { - 255 => { seed[i] = 0; } - _ => { seed[i] += 1; break; } + 255 => { + seed[i] = 0; + } + _ => { + seed[i] += 1; + break; + } } } } @@ -57,7 +62,9 @@ fn calculate_score(_desired: &str, key: &str) -> usize { 0 } -pub(super) fn generate_key(desired: &str) -> Result, &str> { +pub(super) fn generate_key(desired: &str) -> Result, &str> where + PublicOf: PublicT, +{ if desired.is_empty() { return Err("Pattern must not be empty"); } @@ -71,7 +78,7 @@ pub(super) fn generate_key(desired: &str) -> Result, &str> loop { if done % 100000 == 0 { - OsRng::new().unwrap().fill_bytes(seed.as_mut()); + OsRng.fill_bytes(seed.as_mut()); } else { next_seed(seed.as_mut()); } @@ -101,15 +108,20 @@ pub(super) fn generate_key(desired: &str) -> Result, &str> #[cfg(test)] mod tests { - use super::*; use super::super::Ed25519; - use primitives::{Pair, crypto::Ss58Codec}; + use super::*; + use primitives::{crypto::Ss58Codec, Pair}; #[cfg(feature = "bench")] use test::Bencher; #[test] fn test_generation_with_single_char() { - assert!(generate_key::("j").unwrap().pair.public().to_ss58check().contains("j")); + assert!(generate_key::("j") + .unwrap() + .pair + .public() + .to_ss58check() + .contains("j")); } #[test] @@ -120,34 +132,45 @@ mod tests { #[test] fn test_score_100() { - let score = calculate_score("Polkadot", "5PolkadotwHY5k9GpdTgpqs9xjuNvtv8EcwCFpEeyEf3KHim"); + let score = calculate_score( + "Polkadot", + "5PolkadotwHY5k9GpdTgpqs9xjuNvtv8EcwCFpEeyEf3KHim", + ); assert_eq!(score, 430); } #[test] fn test_score_50_2() { // 50% for the position + 50% for the size - assert_eq!(calculate_score("Polkadot", "5PolkXXXXwHY5k9GpdTgpqs9xjuNvtv8EcwCFpEeyEf3KHim"), 238); + assert_eq!( + calculate_score( + "Polkadot", + "5PolkXXXXwHY5k9GpdTgpqs9xjuNvtv8EcwCFpEeyEf3KHim" + ), + 238 + ); } #[test] fn test_score_0() { - assert_eq!(calculate_score("Polkadot", "5GUWv4bLCchGUHJrzULXnh4JgXsMpTKRnjuXTY7Qo1Kh9uYK"), 0); + assert_eq!( + calculate_score( + "Polkadot", + "5GUWv4bLCchGUHJrzULXnh4JgXsMpTKRnjuXTY7Qo1Kh9uYK" + ), + 0 + ); } #[cfg(feature = "bench")] #[bench] fn bench_paranoiac(b: &mut Bencher) { - b.iter(|| { - generate_key("polk") - }); + b.iter(|| generate_key("polk")); } #[cfg(feature = "bench")] #[bench] fn bench_not_paranoiac(b: &mut Bencher) { - b.iter(|| { - generate_key("polk") - }); + b.iter(|| generate_key("polk")); } } diff --git a/test-utils/chain-spec-builder/Cargo.lock b/test-utils/chain-spec-builder/Cargo.lock deleted file mode 100644 index afa92a46f8f4dd70021d0b2e7a53fb81dff6a3fa..0000000000000000000000000000000000000000 --- a/test-utils/chain-spec-builder/Cargo.lock +++ /dev/null @@ -1,5198 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "aes" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aes-ctr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aes-soft" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aesni" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aio-limited" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "app_dirs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "arrayref" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "arrayvec" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "asn1_der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "asn1_der_derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "backtrace" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base-x" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "base58" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bigint" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bindgen" -version = "0.47.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bitflags" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitmask" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "blake2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-buffer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-buffer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-cipher-trait" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-modes" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-padding" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bs58" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bstr" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bumpalo" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byte-tools" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "c_linked_list" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cc" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cexpr" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cfg-if" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "chain-spec-builder" -version = "0.1.0" -dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "node-cli 1.0.0", - "substrate-primitives 1.0.0", - "substrate-service 1.0.0", -] - -[[package]] -name = "chrono" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clang-sys" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clap" -version = "2.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clear_on_drop" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "core-foundation" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crossbeam" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-channel" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crunchy" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crypto-mac" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crypto-mac" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ctr" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cuckoofilter" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "curve25519-dalek" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "data-encoding" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "derive_more" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "digest" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "digest" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "digest" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "dns-parser" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.0-pre.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "elastic-array" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "environmental" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "erased-serde" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "error-chain" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "exit-future" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure_derive" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fdlimit" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "finality-grandpa" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fixed-hash" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fnv" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fork-tree" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fs-swap" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "generic-array" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "generic-array" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "generic-array" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "get_if_addrs" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "get_if_addrs-sys" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "glob" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "globset" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "h2" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hash-db" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hash256-std-hasher" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashbrown" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashmap_core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "heapsize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "heck" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hex" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hex-literal" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hex-literal" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hex-literal-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hex-literal-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hex-literal-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hmac" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hmac" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hmac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hmac-drbg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "http" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "httparse" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "humantime" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper" -version = "0.12.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-codec" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-serde" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "indexmap" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "integer-sqrt" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "interleaved-ordered" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "iovec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "js-sys" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wasm-bindgen 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-core" -version = "10.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-derive" -version = "10.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-http-server" -version = "10.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-pubsub" -version = "10.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-server-utils" -version = "10.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-ws-server" -version = "10.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kvdb" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" -dependencies = [ - "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", -] - -[[package]] -name = "kvdb-rocksdb" -version = "0.1.4" -source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" -dependencies = [ - "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libloading" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core-derive 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-dns 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-floodsub 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-kad 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mdns 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mplex 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-noise 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-plaintext 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ratelimit 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-secio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-tcp 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-uds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-websocket 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-yamux 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-core" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "multistream-select 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-core-derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-dns" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-floodsub" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-identify" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-kad" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-mdns" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-mplex" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-noise" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "curve25519-dalek 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-ping" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-plaintext" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-ratelimit" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-secio" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-tcp" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-uds" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-websocket" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.22.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-yamux" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "yamux 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "librocksdb-sys" -version = "5.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libsecp256k1" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "linked_hash_set" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memory-db" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memory_units" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "merlin" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio" -version = "0.6.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio-extras" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio-uds" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "multistream-select" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "names" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "native-tls" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "net2" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "node-cli" -version = "1.0.0" -dependencies = [ - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "node-executor 1.0.0", - "node-primitives 1.0.0", - "node-runtime 1.0.0", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-basic-authorship 1.0.0", - "substrate-cli 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-aura 1.1.0", - "substrate-finality-grandpa 1.0.0", - "substrate-inherents 1.0.0", - "substrate-keystore 1.0.0", - "substrate-network 0.1.0", - "substrate-primitives 1.0.0", - "substrate-service 1.0.0", - "substrate-telemetry 1.0.0", - "substrate-transaction-pool 1.0.0", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "node-executor" -version = "1.0.0" -dependencies = [ - "node-primitives 1.0.0", - "node-runtime 1.0.0", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "substrate-executor 1.0.0", - "substrate-primitives 1.0.0", - "substrate-state-machine 1.0.0", - "substrate-trie 1.0.0", - "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "node-primitives" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "node-runtime" -version = "1.0.0" -dependencies = [ - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "node-primitives 1.0.0", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "sr-version 1.0.0", - "srml-aura 1.0.0", - "srml-balances 1.0.0", - "srml-consensus 1.0.0", - "srml-contract 1.0.0", - "srml-council 1.0.0", - "srml-democracy 1.0.0", - "srml-executive 1.0.0", - "srml-finality-tracker 1.0.0", - "srml-grandpa 1.0.0", - "srml-indices 1.0.0", - "srml-session 1.0.0", - "srml-staking 1.0.0", - "srml-sudo 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "srml-timestamp 1.0.0", - "srml-treasury 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-aura-primitives 1.0.0", - "substrate-consensus-authorities 1.0.0", - "substrate-keyring 1.0.0", - "substrate-offchain-primitives 0.1.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "nodrop" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nohash-hasher" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nom" -version = "4.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num_cpus" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ole32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "once_cell" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "opaque-debug" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl" -version = "0.10.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl-sys" -version = "0.9.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "owning_ref" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "owning_ref" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-bytes" -version = "0.1.0" -source = "git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d#b0317f649ab2c665b7987b8475878fc4d2e1f81d" - -[[package]] -name = "parity-codec" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-codec-derive" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-crypto" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scrypt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-multiaddr" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-multihash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.31.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-ws" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "paste" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "paste-impl" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pbkdf2" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pbkdf2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pkg-config" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "primitive-types" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-hack" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-hack-impl" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "protobuf" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pwasm-utils" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quick-error" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quick-error" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quote" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "remove_dir_all" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ring" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ripemd160" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rocksdb" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "librocksdb-sys 5.18.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-hex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rw-stream-sink" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ryu" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "safe-mix" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "safemem" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "schannel" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "schnorrkel" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scrypt" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "secp256k1" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "send_wrapper" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha-1" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sha2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha2" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha3" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "shell32-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slog" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-async" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-json" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-scope" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog_derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "smallvec" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "snow" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sourcefile" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "spin" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sr-api-macros" -version = "1.0.0" -dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sr-io" -version = "1.0.0" -dependencies = [ - "environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 1.0.0", - "substrate-primitives 1.0.0", - "substrate-state-machine 1.0.0", - "substrate-trie 1.0.0", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sr-primitives" -version = "1.0.0" -dependencies = [ - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-std 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "sr-sandbox" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 1.0.0", - "substrate-primitives 1.0.0", - "wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sr-std" -version = "1.0.0" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sr-version" -version = "1.0.0" -dependencies = [ - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", -] - -[[package]] -name = "srml-aura" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-session 1.0.0", - "srml-staking 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "srml-timestamp 1.0.0", - "substrate-inherents 1.0.0", -] - -[[package]] -name = "srml-balances" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-keyring 1.0.0", -] - -[[package]] -name = "srml-consensus" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-inherents 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "srml-contract" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-sandbox 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "srml-timestamp 1.0.0", - "substrate-primitives 1.0.0", - "wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "srml-council" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-democracy 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "srml-democracy" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", -] - -[[package]] -name = "srml-executive" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", -] - -[[package]] -name = "srml-finality-tracker" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-inherents 1.0.0", -] - -[[package]] -name = "srml-grandpa" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-consensus 1.0.0", - "srml-finality-tracker 1.0.0", - "srml-session 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-finality-grandpa-primitives 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "srml-indices" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-keyring 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "srml-metadata" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "srml-session" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-consensus 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "srml-timestamp 1.0.0", -] - -[[package]] -name = "srml-staking" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-consensus 1.0.0", - "srml-session 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-keyring 1.0.0", -] - -[[package]] -name = "srml-sudo" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-support-procedural 1.0.0", - "srml-system 1.0.0", -] - -[[package]] -name = "srml-support" -version = "1.0.0" -dependencies = [ - "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-metadata 1.0.0", - "srml-support-procedural 1.0.0", - "substrate-inherents 1.0.0", -] - -[[package]] -name = "srml-support-procedural" -version = "1.0.0" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-api-macros 1.0.0", - "srml-support-procedural-tools 1.0.0", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "srml-support-procedural-tools" -version = "1.0.0" -dependencies = [ - "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "srml-support-procedural-tools-derive 1.0.0", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "srml-support-procedural-tools-derive" -version = "1.0.0" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "srml-system" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "srml-timestamp" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", - "substrate-inherents 1.0.0", -] - -[[package]] -name = "srml-treasury" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "srml-balances 1.0.0", - "srml-support 1.0.0", - "srml-system 1.0.0", -] - -[[package]] -name = "stable_deref_trait" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "static_assertions" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "static_slice" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "stdweb" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-internal-macros 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "stdweb-internal-runtime 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "stream-cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strsim" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "structopt" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "structopt-derive" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "strum" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strum_macros" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-basic-authorship" -version = "1.0.0" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-aura-primitives 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-inherents 1.0.0", - "substrate-primitives 1.0.0", - "substrate-telemetry 1.0.0", - "substrate-transaction-pool 1.0.0", -] - -[[package]] -name = "substrate-bip39" -version = "0.2.1" -source = "git+https://github.com/paritytech/substrate-bip39#44307fda4ea17fe97aeb93af317fbc8f6ed34193" -dependencies = [ - "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-cli" -version = "1.0.0" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-client 1.0.0", - "substrate-keyring 1.0.0", - "substrate-network 0.1.0", - "substrate-panic-handler 1.0.0", - "substrate-primitives 1.0.0", - "substrate-service 1.0.0", - "substrate-state-machine 1.0.0", - "substrate-telemetry 1.0.0", - "sysinfo 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-client" -version = "1.0.0" -dependencies = [ - "derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-api-macros 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "sr-version 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-executor 1.0.0", - "substrate-inherents 1.0.0", - "substrate-keyring 1.0.0", - "substrate-primitives 1.0.0", - "substrate-state-machine 1.0.0", - "substrate-telemetry 1.0.0", - "substrate-trie 1.0.0", -] - -[[package]] -name = "substrate-client-db" -version = "1.0.0" -dependencies = [ - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-executor 1.0.0", - "substrate-primitives 1.0.0", - "substrate-state-db 1.0.0", - "substrate-state-machine 1.0.0", - "substrate-trie 1.0.0", -] - -[[package]] -name = "substrate-consensus-aura" -version = "1.1.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-version 1.0.0", - "srml-aura 1.0.0", - "srml-consensus 1.0.0", - "srml-support 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-aura-primitives 1.0.0", - "substrate-consensus-authorities 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-consensus-slots 1.1.0", - "substrate-inherents 1.0.0", - "substrate-primitives 1.0.0", - "substrate-telemetry 1.0.0", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-consensus-aura-primitives" -version = "1.0.0" -dependencies = [ - "sr-primitives 1.0.0", - "substrate-client 1.0.0", -] - -[[package]] -name = "substrate-consensus-authorities" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "sr-version 1.0.0", - "srml-support 1.0.0", - "substrate-client 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "substrate-consensus-common" -version = "1.0.0" -dependencies = [ - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-version 1.0.0", - "substrate-inherents 1.0.0", - "substrate-primitives 1.0.0", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-consensus-slots" -version = "1.1.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-inherents 1.0.0", - "substrate-primitives 1.0.0", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-executor" -version = "1.0.0" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-version 1.0.0", - "substrate-panic-handler 1.0.0", - "substrate-primitives 1.0.0", - "substrate-serializer 1.0.0", - "substrate-state-machine 1.0.0", - "substrate-trie 1.0.0", - "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-finality-grandpa" -version = "1.0.0" -dependencies = [ - "finality-grandpa 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fork-tree 1.0.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "srml-finality-tracker 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-finality-grandpa-primitives 1.0.0", - "substrate-inherents 1.0.0", - "substrate-network 0.1.0", - "substrate-primitives 1.0.0", - "substrate-service 1.0.0", - "substrate-telemetry 1.0.0", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-finality-grandpa-primitives" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", - "substrate-client 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "substrate-inherents" -version = "1.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-std 1.0.0", -] - -[[package]] -name = "substrate-keyring" -version = "1.0.0" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "substrate-keystore" -version = "1.0.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-primitives 1.0.0", - "subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-network" -version = "0.1.0" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fork-tree 1.0.0", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-network-libp2p 1.0.0", - "substrate-peerset 1.0.0", - "substrate-primitives 1.0.0", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-network-libp2p" -version = "1.0.0" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slog_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-peerset 1.0.0", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-offchain" -version = "0.1.0" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-client 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-inherents 1.0.0", - "substrate-offchain-primitives 0.1.0", - "substrate-primitives 1.0.0", - "substrate-transaction-pool 1.0.0", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-offchain-primitives" -version = "0.1.0" -dependencies = [ - "sr-primitives 1.0.0", - "substrate-client 1.0.0", -] - -[[package]] -name = "substrate-panic-handler" -version = "1.0.0" -dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-peerset" -version = "1.0.0" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-primitives" -version = "1.0.0" -dependencies = [ - "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 1.0.0", - "substrate-bip39 0.2.1 (git+https://github.com/paritytech/substrate-bip39)", - "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "twox-hash 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-rpc" -version = "1.0.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-derive 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "sr-version 1.0.0", - "substrate-client 1.0.0", - "substrate-executor 1.0.0", - "substrate-network 0.1.0", - "substrate-primitives 1.0.0", - "substrate-state-machine 1.0.0", - "substrate-transaction-pool 1.0.0", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-rpc-servers" -version = "1.0.0" -dependencies = [ - "jsonrpc-http-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-pubsub 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-ws-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-rpc 1.0.0", -] - -[[package]] -name = "substrate-serializer" -version = "1.0.0" -dependencies = [ - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-service" -version = "1.0.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 1.0.0", - "sr-primitives 1.0.0", - "substrate-client 1.0.0", - "substrate-client-db 1.0.0", - "substrate-consensus-common 1.0.0", - "substrate-executor 1.0.0", - "substrate-inherents 1.0.0", - "substrate-keystore 1.0.0", - "substrate-network 0.1.0", - "substrate-offchain 0.1.0", - "substrate-primitives 1.0.0", - "substrate-rpc-servers 1.0.0", - "substrate-telemetry 1.0.0", - "substrate-transaction-pool 1.0.0", - "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-state-db" -version = "1.0.0" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "substrate-state-machine" -version = "1.0.0" -dependencies = [ - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-panic-handler 1.0.0", - "substrate-primitives 1.0.0", - "substrate-trie 1.0.0", - "trie-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-telemetry" -version = "1.0.0" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-transaction-graph" -version = "1.0.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-primitives 1.0.0", -] - -[[package]] -name = "substrate-transaction-pool" -version = "1.0.0" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 1.0.0", - "substrate-client 1.0.0", - "substrate-primitives 1.0.0", - "substrate-transaction-graph 1.0.0", -] - -[[package]] -name = "substrate-trie" -version = "1.0.0" -dependencies = [ - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 1.0.0", - "substrate-primitives 1.0.0", - "trie-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "subtle" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "0.15.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synstructure" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sysinfo" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "take_mut" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "target_info" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "tempfile" -version = "3.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termcolor" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "textwrap" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "time" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiny-bip39" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiny-keccak" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tk-listen" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-dns-unofficial" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-fs" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-sync" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-timer" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tls" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-trace-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-udp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-uds" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "trie-db" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "trie-root" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "try-lock" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "twofish" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "twox-hash" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "typenum" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ucd-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "uint" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-segmentation" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unsigned-varint" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "untrusted" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf8-ranges" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vcpkg" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "want" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wasm-bindgen-macro 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bumpalo 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.43" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wasm-bindgen-webidl" -version = "0.2.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasmi" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasmi-validation" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "web-sys" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", - "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-webidl 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "websocket" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "weedle" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "which" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wincolor" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ws" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "x25519-dalek" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "xdg" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "yaml-rust" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "yamux" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "zeroize" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" -"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" -"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" -"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" -"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" -"checksum aio-limited 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f10b352bc3fc08ae24dc5d2d3ddcac153678533986122dc283d747b12071000" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" -"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum asn1_der 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9893d63fc3b1c44231e667da6836a33f27d8b6b3bdc82f83da5dfd579d1b6528" -"checksum asn1_der_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7f92edafad155aff997fa5b727c6429b91e996b5a5d62a2b0adbae1306b5fe" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum base-x 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d55aa264e822dbafa12db4d54767aff17c6ba55ea2d8559b3e17392c7d000e5d" -"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bigint 4.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebecac13b3c745150d7b6c3ea7572d372f09d627c2077e893bf26c5c7f70d282" -"checksum bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df683a55b54b41d5ea8ebfaebb5aa7e6b84e3f3006a78f010dadc9ca88469260" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead" -"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814" -"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" -"checksum block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42" -"checksum bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c8203ca06c502958719dae5f653a79e0cc6ba808ed02beffbf27d09610f2143" -"checksum bumpalo 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4639720be048090544634e0402490838995ccdc9d2fe648f528f30d3c33ae71f" -"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" -"checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" -"checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum clang-sys 0.26.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" -"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" -"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" -"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198" -"checksum crypto-mac 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" -"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" -"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" -"checksum curve25519-dalek 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "750226d75fc2f5a8daec6e7477624e258674023eb73d8d647f63b943ca182a4a" -"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" -"checksum derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fbe9f11be34f800b3ecaaed0ec9ec2e015d1d0ba0c8644c1310f73d6e8994615" -"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a" -"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" -"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" -"checksum ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81956bcf7ef761fb4e1d88de3fa181358a0d26cbcb9755b587a08f9119824b86" -"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" -"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" -"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" -"checksum environmental 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c7464757b80de8930c91c9afe77ddce501826bf9d134a87db2c67d9dc177e2c" -"checksum erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3beee4bc16478a1b26f2e80ad819a52d24745e292f521a63c16eea5f74b7eb60" -"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum exit-future 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d8013f441e38e31c670e7f34ec8f1d5d3a2bd9d303c1ff83976ca886005e8f48" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" -"checksum finality-grandpa 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5cdd9ef7c48777665dacc9657c272778121d4d09848100bcc2bd9c773c6cf837" -"checksum fixed-hash 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a683d1234507e4f3bf2736eeddf0de1dc65996dc0164d57eba0a74bcf29489" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fs-swap 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "921d332c89b3b61a826de38c61ee5b6e02c56806cade1b0e5d81bd71f57a71bb" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "62941eff9507c8177d448bd83a44d9b9760856e184081d8cd79ba9f03dd24981" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" -"checksum generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fceb69994e330afed50c93524be68c42fa898c2d9fd4ee8da03bd7363acd26f2" -"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" -"checksum get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" -"checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" -"checksum hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ba7fb417e5c470acdd61068c79767d0e65962e70836cf6c9dfd2409f06345ce0" -"checksum hash256-std-hasher 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b2027c19ec91eb304999abae7307d225cf93be42af53b0039f76e98ed5af86" -"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" -"checksum hashmap_core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8e04cb7a5051270ef3fa79f8c7604d581ecfa73d520e74f554e45541c4b5881a" -"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc2928beef125e519d69ae1baa8c37ea2e0d3848545217f6db0179c5eb1d639" -"checksum hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3da68162fdd2147e66682e78e729bd77f93b4c99656db058c5782d8c6b6225a" -"checksum hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "520870c3213943eb8d7803e80180d12a6c7ceb4ae74602544529d1643dc4ddda" -"checksum hex-literal-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06095d08c7c05760f11a071b3e1d4c5b723761c01bd8d7201c30a9536668a612" -"checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" -"checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" -"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" -"checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" -"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" -"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -"checksum hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e4606fed1c162e3a63d408c07584429f49a4f34c7176cb6cbee60e78f2372c" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum impl-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2050d823639fbeae26b2b5ba09aca8907793117324858070ade0673c49f793b" -"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" -"checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" -"checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum js-sys 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e9c0d432259f651d765d888e30164c096ddbae13c89e56dd1d02a719e020efa8" -"checksum jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc15eef5f8b6bef5ac5f7440a957ff95d036e2f98706947741bfc93d1976db4c" -"checksum jsonrpc-derive 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dae61ca8a3b047fb11309b00661bc56837085bd07e46f907b9c562c0b03e68" -"checksum jsonrpc-http-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d2a00824306155b8ef57fe957f31b8cd8ad24262f15cf911d84dcf9a3f206d" -"checksum jsonrpc-pubsub 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37fce55133ee264d0ab42bd862efcd45ae1d062cda599f4cc12ccc4be3195f2a" -"checksum jsonrpc-server-utils 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9527f01ef25f251d64082cbefc0c6d6f367349afe6848ef908a674e06b2bdd3" -"checksum jsonrpc-ws-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3889012aa638a2f18eb1a879f46fc8b34e7e1423cbff3247cd1531de0d51084b" -"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum kvdb-rocksdb 0.1.4 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" -"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" -"checksum libp2p 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0231edab431064b30b7749484a39735eb36492cef4658c372c9059e58c3003aa" -"checksum libp2p-core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a3bad2ed26297112847678683dd221473a0d44297250b61f004e1b35e72493" -"checksum libp2p-core-derive 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f765f103b680cbed910b02bfdbdcfce5b1142899c93e51acb960bf59b6f81b1" -"checksum libp2p-dns 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b129d20cc8cbb6ce5da8361045649c024659173e246c5dfbf20ae06071c046a" -"checksum libp2p-floodsub 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70d68816b8435d6788399416eb2f0a6974fb1d15c4be5c30141f87c8e81746df" -"checksum libp2p-identify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "718ca645a065fd70855ca6042a7df686c24cd21add750c37a82c811fbd1e5c43" -"checksum libp2p-kad 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bbe27c623a6a720efd5d704347838972062f89149a9c3cd149748da60bdcd3e0" -"checksum libp2p-mdns 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9bc1a5d85f4812cae6367b49a432763fe28997bac7c530dc55b70ec18a78aa7" -"checksum libp2p-mplex 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe5a858342a1cc89464474f7edc4bae1da649b9c823a3e04d9fb494493601746" -"checksum libp2p-noise 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc6b5185c50a52a12e7bbe2ee7799059e24de4e52ab25edbfd26c8ab8515d317" -"checksum libp2p-ping 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7905c1431ad115bee83405770629a27d6f17153ad02ec9670a7347998ef20e22" -"checksum libp2p-plaintext 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc17626763ded57da8fed73187c2d9f6ebb89d30838673c430315bf560c7e4db" -"checksum libp2p-ratelimit 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2409d08b809ab1a74269597f7da2829d117cc11b9ed3343af33fc20831619726" -"checksum libp2p-secio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258cdc6742945c8f6402997bbbf36733588e2db18e5a0014da6d46e3ccfb92cf" -"checksum libp2p-tcp 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b5691e2ba2720d42bd1e93d6b90239fa9235c1956ef6a5f1dd499a7ae2767be" -"checksum libp2p-uds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ab0b9ca050105fd94229c48911c0c84aef4d6b86a53d1b6df81d938354e47e" -"checksum libp2p-websocket 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81692c3141a9aefd84f4faffdc93985af3858ef82ed7fe8185e6b27437b36183" -"checksum libp2p-yamux 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6ff51a5b2056bacee1c9f2ed8455cdf3c5c619261ddb4efc783119130aaf52" -"checksum librocksdb-sys 5.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19778314deaa7048f2ea7d07b8aa12e1c227acebe975a37eeab6d2f8c74e41b" -"checksum libsecp256k1 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "688e8d65e495567c2c35ea0001b26b9debf0b4ea11f8cccc954233b75fc3428a" -"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum linked_hash_set 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7c91c4c7bbeb4f2f7c4e5be11e6a05bd6830bc37249c47ce1ad86ad453ff9c" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum memory-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7623b01a4f1b7acb7cf8e3f678f05e15e6ae26cb0b738dfeb5cc186fd6b82ef4" -"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum merlin 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c39467de91b004f5b9c06fac5bbc8e7d28309a205ee66905166b70804a71fea" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" -"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multistream-select 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f989d40aab0ed0d83c1cdb4856b5790e980b96548d1a921f280e985eb049f38d" -"checksum names 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef320dab323286b50fb5cdda23f61c796a72a89998ab565ca32525c5c556f2da" -"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum nohash-hasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d138afcce92d219ccb6eb53d9b1e8a96ac0d633cfd3c53cd9856d96d1741bb8" -"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" -"checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" -"checksum openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a51f452b82d622fc8dd973d7266e9055ac64af25b957d9ced3989142dc61cb6b" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" -"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)" = "" -"checksum parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb43c05fb71c03b4ea7327bf15694da1e0f23f19d5b1e95bab6c6d74097e336" -"checksum parity-codec-derive 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00a486fd383382ddcb2de928364b1f82571c1e48274fc43b7667a4738ee4056c" -"checksum parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1b9c063d87e1507cb3807493c8d21859ef23b5414b39f81c53f0ba267d64c1" -"checksum parity-multiaddr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18a130a727008cfcd1068a28439fe939897ccad28664422aeca65b384d6de6d0" -"checksum parity-multihash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05d6a68e07ab34a9e87bd8dd4936f6bb5be21e4f6dbcdbaf04d8e854eba0af01" -"checksum parity-wasm 0.31.3 (registry+https://github.com/rust-lang/crates.io-index)" = "511379a8194230c2395d2f5fa627a5a7e108a9f976656ce723ae68fca4097bfc" -"checksum parity-ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fec5048fba72a2e01baeb0d08089db79aead4b57e2443df172fb1840075a233" -"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" -"checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" -"checksum pbkdf2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0c09cddfbfc98de7f76931acf44460972edb4023eb14d0c6d4018800e552d8e0" -"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" -"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum primitive-types 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99d5a5fe9d93ddb394e2fb3fc49d0e31acb475fd45a30eeb8f3e76b767ecb7e1" -"checksum proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6cf4e5b00300d151dfffae39f529dfa5188f42eeb14201229aa420d6aad10c" -"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" -"checksum proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1dd4172a1e1f96f709341418f49b11ea6c2d95d53dca08c0f74cbd332d9cf3" -"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum protobuf 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc7badf647ae2fa27ba51c218e347386c88cc604fcfe71f2aba0ad017f3f2b75" -"checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" -"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" -"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" -"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473" -"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" -"checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" -"checksum rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1651697fefd273bfb4fd69466cc2a9d20de557a0213b97233b22b5e95924b5e" -"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" -"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rw-stream-sink 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d548a40fe17c3a77d54b82457b79fcc9b8a288d509ca20fbf5aa1dac386d22d6" -"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" -"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" -"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" -"checksum schnorrkel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5eff518f9bed3d803a0d002af0ab96339b0ebbedde3bec98a684986134b7a39" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum scrypt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8570c5e2fa69cb29d492fd4e9974b6b5facb5a888e1c6da630d4a3cd7ebfef4a" -"checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e" -"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" -"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" -"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" -"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" -"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" -"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a" -"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" -"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" -"checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e1a2eec401952cd7b12a84ea120e2d57281329940c3f93c2bf04f462539508e" -"checksum slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e544d16c6b230d84c866662fe55e31aacfca6ae71e6fc49ae9a311cb379bfc2f" -"checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-scope 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "60c04b4726fa04595ccf2c2dad7bcd15474242c4c5e109a8a376e8a2c9b1539a" -"checksum slog_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eff3b513cf2e0d1a60e1aba152dc72bedc5b05585722bb3cebd7bcb1e31b98f" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum snow 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5a64f02fd208ef15bd2d1a65861df4707e416151e1272d02c8faafad1c138100" -"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" -"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362" -"checksum stdweb 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c34362bb10ac1a9439674795cc0e1bdcb0c46444c8fd4874ef39a01d9a8a8f24" -"checksum stdweb-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e21ebd9179de08f2300a65454268a17ea3de204627458588c84319c4def3930" -"checksum stdweb-internal-macros 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e68f7d08b76979a43e93fe043b66d2626e35d41d68b0b85519202c6dd8ac59fa" -"checksum stdweb-internal-runtime 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d52317523542cc0af5b7e31017ad0f7d1e78da50455e38d5657cd17754f617da" -"checksum stream-cipher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8861bc80f649f5b4c9bd38b696ae9af74499d479dbfb327f0607de6b326a36bc" -"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1" -"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6" -"checksum strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1810e25f576e7ffce1ff5243b37066da5ded0310b3274c20baaeccb1145b2806" -"checksum strum_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "572a2f4e53dd4c3483fd79e5cc10ddd773a3acb1169bbfe8762365e107110579" -"checksum substrate-bip39 0.2.1 (git+https://github.com/paritytech/substrate-bip39)" = "" -"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum subtle 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01dca13cf6c3b179864ab3292bd794e757618d35a7766b7c46050c614ba00829" -"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" -"checksum sysinfo 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d88e417391431019773011a31a6c967538da388782b7711f2f6fafd9e601e55" -"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" -"checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" -"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" -"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" -"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" -"checksum tk-listen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5462b0f968c0457efe38fcd2df7e487096b992419e4f5337b06775a614bbda4b" -"checksum tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cec6c34409089be085de9403ba2010b80e36938c9ca992c4f67f407bb13db0b1" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" -"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" -"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" -"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" -"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" -"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" -"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum trie-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba73747fd3a64ab531274c04cb588dfa9d30d972d62990831e63fbce2cfec59" -"checksum trie-root 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfa2e20c4f1418ac2e71ddc418e35e1b56e34022e2146209ffdbf1b2de8b1bd9" -"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" -"checksum twox-hash 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09871da9f15424236082e0b220fd404a4eb6bebc7205c67653701229234ac64c" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum uint 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91bb295c2c53c54742a6b8acb705114f6dfdf3c42becdb146a662cb77fcc0d02" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unsigned-varint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c64cdf40b4a9645534a943668681bcb219faf51874d4b65d2e0abda1b10a2ab" -"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" -"checksum wasm-bindgen 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "546e4ab1bf7f9a3532d21472efd72d01a23f55abd885c60b165f393394dbad95" -"checksum wasm-bindgen-backend 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "7b84bedebfd6ae3522cce59dec6b52ee6c53ceeaae8541668c15b9f42df8ecab" -"checksum wasm-bindgen-futures 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "c6fc76797785881eac82f72e9b676032a737dea717103878100dbf6106d8d2cb" -"checksum wasm-bindgen-macro 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "f2a033fc6bfd5e486a488b0e19d7d1bb29e667ebb91db85f698381a8aa831786" -"checksum wasm-bindgen-macro-support 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "fba68375ef8f095c4a169c093c95ed2e1b5e44f7872f3bcbcafe2c51b4a80480" -"checksum wasm-bindgen-shared 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "321949f4d7f7bf7a49dccd464bdc46581b180f761d9505e4943926d50b2a4a64" -"checksum wasm-bindgen-webidl 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c2c2b45b827f96657beea954a5430d37da4cf477d2874595f5f0a6ad027980" -"checksum wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aebbaef470840d157a5c47c8c49f024da7b1b80e90ff729ca982b2b80447e78b" -"checksum wasmi-validation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab380192444b3e8522ae79c0a1976e42a82920916ccdfbce3def89f456ea33f3" -"checksum web-sys 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "47ad2ecfe3793a87a0aa49562ad6f01cb3af3c870213283bc60032ec8dd7e62a" -"checksum websocket 0.22.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0adcd2a64c5746c9702b354a1b992802b0c363df1dfa324a74cb7aebe10e0cbf" -"checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044" -"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee1585dc1484373cbc1cee7aafda26634665cf449436fd6e24bfd1fad230538" -"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" -"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" -"checksum yamux 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01bd67889938c48f0049fc60a77341039e6c3eaf16cb7693e6ead7c0ba701295" -"checksum zeroize 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddfeb6eee2fb3b262ef6e0898a52b7563bb8e0d5955a313b3cf2f808246ea14" diff --git a/test-utils/chain-spec-builder/Cargo.toml b/test-utils/chain-spec-builder/Cargo.toml index 1e048a91cdb92d51ff78293dcb133f98772dc60e..e8ca8d354025a0890e61121e0c2c89bb54769a5c 100644 --- a/test-utils/chain-spec-builder/Cargo.toml +++ b/test-utils/chain-spec-builder/Cargo.toml @@ -3,9 +3,12 @@ name = "chain-spec-builder" version = "2.0.0" authors = ["Parity Technologies "] edition = "2018" +build = "build.rs" [dependencies] -clap = { version = "~2.32", features = ["yaml"] } +ansi_term = "0.12.1" +keystore = { package = "substrate-keystore", path = "../../core/keystore" } node-cli = { path = "../../node/cli" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } -substrate-service = { path = "../../core/service" } +rand = "0.7.2" +structopt = "0.3.3" diff --git a/test-utils/chain-spec-builder/build.rs b/test-utils/chain-spec-builder/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..36730271c715eaa1daf6e957e4b1e01443a2bc7a --- /dev/null +++ b/test-utils/chain-spec-builder/build.rs @@ -0,0 +1,23 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::env; + +fn main() { + if let Ok(profile) = env::var("PROFILE") { + println!("cargo:rustc-cfg=build_type=\"{}\"", profile); + } +} diff --git a/test-utils/chain-spec-builder/src/cli.yml b/test-utils/chain-spec-builder/src/cli.yml deleted file mode 100644 index f4b1cb7e2eaaab0e5d2df01a6801d36a3de527b8..0000000000000000000000000000000000000000 --- a/test-utils/chain-spec-builder/src/cli.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: chain-spec-builder -author: "azban " -about: Utility for creating chain specs primarily for testing -args: -- initial_authority_seed: - short: a - value_name: INITIAL_AUTHORITY_SEED - help: Initial authority seed - takes_value: true - multiple: true - required: true -- endowed_account_seed: - short: e - value_name: ENDOWED_ACCOUNT_SEED - help: Endowed account seed - takes_value: true - multiple: true - required: true -- sudo_key_seed: - short: u - value_name: SUDO_KEY_SEED - help: Sudo key seed - takes_value: true - required: true diff --git a/test-utils/chain-spec-builder/src/main.rs b/test-utils/chain-spec-builder/src/main.rs index 13b4cc38a16463f3166f18fef09a482e8ffb52db..d46f4b7f0bc98beb0f19c0286dd5a6693ff85c5f 100644 --- a/test-utils/chain-spec-builder/src/main.rs +++ b/test-utils/chain-spec-builder/src/main.rs @@ -1,49 +1,268 @@ -use clap::{App, load_yaml}; +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use std::{fs, path::{Path, PathBuf}}; + +use ansi_term::Style; +use rand::{Rng, distributions::Alphanumeric, rngs::OsRng}; +use structopt::StructOpt; + +use keystore::{Store as Keystore}; use node_cli::chain_spec::{self, AccountId}; -use substrate_service::chain_ops::build_spec; +use primitives::{sr25519, crypto::{Public, Ss58Codec}, traits::BareCryptoStore}; -fn genesis_constructor() -> chain_spec::GenesisConfig { - let yaml = load_yaml!("./cli.yml"); - let matches = App::from_yaml(yaml).get_matches(); - let authorities = matches.values_of("initial_authority_seed") - .unwrap() - .map(chain_spec::get_authority_keys_from_seed) - .collect(); +/// A utility to easily create a testnet chain spec definition with a given set +/// of authorities and endowed accounts and/or generate random accounts. +#[derive(StructOpt)] +#[structopt(rename_all = "kebab-case")] +enum ChainSpecBuilder { + /// Create a new chain spec with the given authorities, endowed and sudo + /// accounts. + New { + /// Authority key seed. + #[structopt(long, short, required = true)] + authority_seeds: Vec, + /// Endowed account address (SS58 format). + #[structopt(long, short)] + endowed_accounts: Vec, + /// Sudo account address (SS58 format). + #[structopt(long, short)] + sudo_account: String, + /// The path where the chain spec should be saved. + #[structopt(long, short, default_value = "./chain_spec.json")] + chain_spec_path: PathBuf, + }, + /// Create a new chain spec with the given number of authorities and endowed + /// accounts. Random keys will be generated as required. + Generate { + /// The number of authorities. + #[structopt(long, short)] + authorities: usize, + /// The number of endowed accounts. + #[structopt(long, short, default_value = "0")] + endowed: usize, + /// The path where the chain spec should be saved. + #[structopt(long, short, default_value = "./chain_spec.json")] + chain_spec_path: PathBuf, + /// Path to use when saving generated keystores for each authority. + /// + /// At this path, a new folder will be created for each authority's + /// keystore named `auth-$i` where `i` is the authority index, i.e. + /// `auth-0`, `auth-1`, etc. + #[structopt(long, short)] + keystore_path: Option, + }, +} - let endowed_accounts = matches.values_of("endowed_account_seed") - .unwrap() - .map(chain_spec::get_from_seed::) - .collect(); +impl ChainSpecBuilder { + /// Returns the path where the chain spec should be saved. + fn chain_spec_path(&self) -> &Path { + match self { + ChainSpecBuilder::New { chain_spec_path, .. } => + chain_spec_path.as_path(), + ChainSpecBuilder::Generate { chain_spec_path, .. } => + chain_spec_path.as_path(), + } + } +} - let sudo_key_seed = matches.value_of("sudo_key_seed").unwrap(); - let sudo_key = chain_spec::get_from_seed::(sudo_key_seed); +fn genesis_constructor( + authority_seeds: &[String], + endowed_accounts: &[AccountId], + sudo_account: &AccountId, +) -> chain_spec::GenesisConfig { + let authorities = authority_seeds + .iter() + .map(AsRef::as_ref) + .map(chain_spec::get_authority_keys_from_seed) + .collect::>(); let enable_println = true; chain_spec::testnet_genesis( authorities, - sudo_key.into(), - Some(endowed_accounts), + sudo_account.clone(), + Some(endowed_accounts.to_vec()), enable_println, ) } -fn generate_chain_spec() -> String { +fn generate_chain_spec( + authority_seeds: Vec, + endowed_accounts: Vec, + sudo_account: String, +) -> Result { + let parse_account = |address: &String| { + AccountId::from_string(address) + .map_err(|err| format!("Failed to parse account address: {:?}", err)) + }; + + let endowed_accounts = endowed_accounts + .iter() + .map(parse_account) + .collect::, String>>()?; + + let sudo_account = parse_account(&sudo_account)?; + let chain_spec = chain_spec::ChainSpec::from_genesis( "Custom", "custom", - genesis_constructor, + move || genesis_constructor(&authority_seeds, &endowed_accounts, &sudo_account), vec![], None, None, None, - None, + Default::default(), ); - build_spec(chain_spec, false).unwrap() + + chain_spec.to_json(false).map_err(|err| err.to_string()) } -fn main() { - let json = generate_chain_spec(); - println!("{}", json); +fn generate_authority_keys_and_store( + seeds: &[String], + keystore_path: &Path, +) -> Result<(), String> { + for (n, seed) in seeds.into_iter().enumerate() { + let keystore = Keystore::open( + keystore_path.join(format!("auth-{}", n)), + None, + ).map_err(|err| err.to_string())?; + + let (_, _, grandpa, babe, im_online) = + chain_spec::get_authority_keys_from_seed(seed); + + let insert_key = |key_type, public| { + keystore.write().insert_unknown( + key_type, + &format!("//{}", seed), + public, + ).map_err(|_| format!("Failed to insert key: {}", grandpa)) + }; + + insert_key( + primitives::crypto::key_types::BABE, + babe.as_slice(), + )?; + + insert_key( + primitives::crypto::key_types::GRANDPA, + grandpa.as_slice(), + )?; + + insert_key( + primitives::crypto::key_types::IM_ONLINE, + im_online.as_slice(), + )?; + } + + Ok(()) +} + +fn print_seeds( + authority_seeds: &[String], + endowed_seeds: &[String], + sudo_seed: &str, +) { + let header = Style::new().bold().underline(); + let entry = Style::new().bold(); + + println!("{}", header.paint("Authority seeds")); + + for (n, seed) in authority_seeds.iter().enumerate() { + println!("{} //{}", + entry.paint(format!("auth-{}:", n)), + seed, + ); + } + + println!(); + + if !endowed_seeds.is_empty() { + println!("{}", header.paint("Endowed seeds")); + for (n, seed) in endowed_seeds.iter().enumerate() { + println!("{} //{}", + entry.paint(format!("endowed-{}:", n)), + seed, + ); + } + + println!(); + } + + println!("{}", header.paint("Sudo seed")); + println!("//{}", sudo_seed); +} + +fn main() -> Result<(), String> { + #[cfg(build_type="debug")] + println!( + "The chain spec builder builds a chain specification that includes a Substrate runtime compiled as WASM. To \ + ensure proper functioning of the included runtime compile (or run) the chain spec builder binary in \ + `--release` mode.\n", + ); + + let builder = ChainSpecBuilder::from_args(); + let chain_spec_path = builder.chain_spec_path().to_path_buf(); + + let (authority_seeds, endowed_accounts, sudo_account) = match builder { + ChainSpecBuilder::Generate { authorities, endowed, keystore_path, .. } => { + let authorities = authorities.max(1); + let rand_str = || -> String { + OsRng.sample_iter(&Alphanumeric) + .take(32) + .collect() + }; + + let authority_seeds = (0..authorities).map(|_| rand_str()).collect::>(); + let endowed_seeds = (0..endowed).map(|_| rand_str()).collect::>(); + let sudo_seed = rand_str(); + + print_seeds( + &authority_seeds, + &endowed_seeds, + &sudo_seed, + ); + + if let Some(keystore_path) = keystore_path { + generate_authority_keys_and_store( + &authority_seeds, + &keystore_path, + )?; + } + + let endowed_accounts = endowed_seeds.iter().map(|seed| { + chain_spec::get_account_id_from_seed::(seed) + .to_ss58check() + }).collect(); + + let sudo_account = chain_spec::get_account_id_from_seed::(&sudo_seed) + .to_ss58check(); + + (authority_seeds, endowed_accounts, sudo_account) + }, + ChainSpecBuilder::New { authority_seeds, endowed_accounts, sudo_account, .. } => { + (authority_seeds, endowed_accounts, sudo_account) + }, + }; + + let json = generate_chain_spec( + authority_seeds, + endowed_accounts, + sudo_account, + )?; + + fs::write(chain_spec_path, json).map_err(|err| err.to_string()) } diff --git a/test-utils/transaction-factory/Cargo.toml b/test-utils/transaction-factory/Cargo.toml index f3c392c3d66ded30d9a3798b3cde37297588a57a..e53972eec65c50c63e1ea317401e42ea8ae1d336 100644 --- a/test-utils/transaction-factory/Cargo.toml +++ b/test-utils/transaction-factory/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" cli = { package = "substrate-cli", path = "../../core/cli" } client = { package = "substrate-client", path = "../../core/client" } consensus_common = { package = "substrate-consensus-common", path = "../../core/consensus/common" } -log = "0.4" +log = "0.4.8" codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } diff --git a/test-utils/transaction-factory/src/complex_mode.rs b/test-utils/transaction-factory/src/complex_mode.rs index 25170f8c1888b8e425ac3781186eb25fdd7574c7..ed76a66b09083e72ad9f8a19bdec4a5610db14aa 100644 --- a/test-utils/transaction-factory/src/complex_mode.rs +++ b/test-utils/transaction-factory/src/complex_mode.rs @@ -41,28 +41,30 @@ use std::sync::Arc; use log::info; +use client::Client; use client::block_builder::api::BlockBuilder; use client::runtime_api::ConstructRuntimeApi; +use primitives::{Blake2Hasher, Hasher}; use sr_primitives::generic::BlockId; use sr_primitives::traits::{Block as BlockT, ProvideRuntimeApi, One, Zero}; -use substrate_service::{ - FactoryBlock, FullClient, ServiceFactory, ComponentClient, FullComponents -}; use crate::{RuntimeAdapter, create_block}; -pub fn next( +pub fn next( factory_state: &mut RA, - client: &Arc>>, + client: &Arc>, + version: u32, genesis_hash: ::Hash, prior_block_hash: ::Hash, - prior_block_id: BlockId, -) -> Option<::Block> + prior_block_id: BlockId, +) -> Option where - F: ServiceFactory, - F::RuntimeApi: ConstructRuntimeApi, FullClient>, - FullClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilder>, + Block: BlockT::Out>, + Exec: client::CallExecutor + Send + Sync + Clone, + Backend: client::backend::Backend + Send, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: BlockBuilder, + RtApi: ConstructRuntimeApi> + Send + Sync, RA: RuntimeAdapter, { let total = factory_state.start_number() + factory_state.num() * factory_state.rounds(); @@ -92,6 +94,7 @@ where &from.1, &to, &amount, + version, &genesis_hash, &prior_block_hash, ); @@ -100,7 +103,7 @@ where let inherents = client.runtime_api().inherent_extrinsics(&prior_block_id, inherents) .expect("Failed to create inherent extrinsics"); - let block = create_block::(&client, transfer, inherents); + let block = create_block::(&client, transfer, inherents); info!( "Created block {} with hash {}. Transferring {} from {} to {}.", factory_state.block_no() + RA::Number::one(), diff --git a/test-utils/transaction-factory/src/lib.rs b/test-utils/transaction-factory/src/lib.rs index ab7dfb8ceab221c7159bf3ea4e7576ccc6e8cf7c..067c75c3fc3443e281a21f6b23a252efa0ed6733 100644 --- a/test-utils/transaction-factory/src/lib.rs +++ b/test-utils/transaction-factory/src/lib.rs @@ -26,22 +26,19 @@ use std::fmt::Display; use log::info; -use client::block_builder::api::BlockBuilder; -use client::runtime_api::ConstructRuntimeApi; +use client::{Client, block_builder::api::BlockBuilder, runtime_api::ConstructRuntimeApi}; use consensus_common::{ BlockOrigin, BlockImportParams, InherentData, ForkChoiceStrategy, SelectChain }; use consensus_common::block_import::BlockImport; use codec::{Decode, Encode}; +use primitives::{Blake2Hasher, Hasher}; use sr_primitives::generic::BlockId; use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, ProvideRuntimeApi, SimpleArithmetic, One, Zero, }; -use substrate_service::{ - FactoryBlock, FactoryFullConfiguration, FullClient, new_client, - ServiceFactory, ComponentClient, FullComponents}; pub use crate::modes::Mode; pub mod modes; @@ -77,6 +74,7 @@ pub trait RuntimeAdapter { key: &Self::Secret, destination: &Self::AccountId, amount: &Self::Balance, + version: u32, genesis_hash: &::Hash, prior_block_hash: &::Hash, ) -> ::Extrinsic; @@ -94,15 +92,19 @@ pub trait RuntimeAdapter { /// Manufactures transactions. The exact amount depends on /// `mode`, `num` and `rounds`. -pub fn factory( +pub fn factory( mut factory_state: RA, - mut config: FactoryFullConfiguration, + client: &Arc>, + select_chain: &Sc, ) -> cli::error::Result<()> where - F: ServiceFactory, - F::RuntimeApi: ConstructRuntimeApi, FullClient>, - FullClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilder>, + Block: BlockT::Out>, + Exec: client::CallExecutor + Send + Sync + Clone, + Backend: client::backend::Backend + Send, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: BlockBuilder, + RtApi: ConstructRuntimeApi> + Send + Sync, + Sc: SelectChain, RA: RuntimeAdapter, <::Block as BlockT>::Hash: From, { @@ -111,35 +113,35 @@ where return Err(cli::error::Error::Input(msg)); } - let client = new_client::(&config)?; - - let select_chain = F::build_select_chain(&mut config, client.clone())?; - - let best_header: Result<::Header, cli::error::Error> = + let best_header: Result<::Header, cli::error::Error> = select_chain.best_chain().map_err(|e| format!("{:?}", e).into()); let mut best_hash = best_header?.hash(); - let best_block_id = BlockId::::hash(best_hash); + let mut best_block_id = BlockId::::hash(best_hash); + let version = client.runtime_version_at(&best_block_id)?.spec_version; let genesis_hash = client.block_hash(Zero::zero())? .expect("Genesis block always exists; qed").into(); while let Some(block) = match factory_state.mode() { - Mode::MasterToNToM => complex_mode::next::( + Mode::MasterToNToM => complex_mode::next::( &mut factory_state, &client, + version, genesis_hash, best_hash.into(), best_block_id, ), - _ => simple_modes::next::( + _ => simple_modes::next::( &mut factory_state, &client, + version, genesis_hash, best_hash.into(), best_block_id, ), } { best_hash = block.header().hash(); - import_block::(&client, block); + best_block_id = BlockId::::hash(best_hash); + import_block(&client, block); info!("Imported block at {}", factory_state.block_no()); } @@ -148,16 +150,18 @@ where } /// Create a baked block from a transfer extrinsic and timestamp inherent. -pub fn create_block( - client: &Arc>>, +pub fn create_block( + client: &Arc>, transfer: ::Extrinsic, - inherent_extrinsics: Vec<::Extrinsic>, -) -> ::Block + inherent_extrinsics: Vec<::Extrinsic>, +) -> Block where - F: ServiceFactory, - FullClient: ProvideRuntimeApi, - F::RuntimeApi: ConstructRuntimeApi, FullClient>, - as ProvideRuntimeApi>::Api: BlockBuilder>, + Block: BlockT::Out>, + Exec: client::CallExecutor + Send + Sync + Clone, + Backend: client::backend::Backend + Send, + Client: ProvideRuntimeApi, + RtApi: ConstructRuntimeApi> + Send + Sync, + as ProvideRuntimeApi>::Api: BlockBuilder, RA: RuntimeAdapter, { let mut block = client.new_block(Default::default()).expect("Failed to create new block"); @@ -173,10 +177,13 @@ where block.bake().expect("Failed to bake block") } -fn import_block( - client: &Arc>>, - block: ::Block -) -> () where F: ServiceFactory +fn import_block( + client: &Arc>, + block: Block +) -> () where + Block: BlockT::Out>, + Exec: client::CallExecutor + Send + Sync + Clone, + Backend: client::backend::Backend + Send, { let import = BlockImportParams { origin: BlockOrigin::File, diff --git a/test-utils/transaction-factory/src/simple_modes.rs b/test-utils/transaction-factory/src/simple_modes.rs index 0554678fbbd0d058e1224c2930c67f41dafde59a..bcbb91200657f2a0bd33031f9df021cd911299e5 100644 --- a/test-utils/transaction-factory/src/simple_modes.rs +++ b/test-utils/transaction-factory/src/simple_modes.rs @@ -36,28 +36,30 @@ use std::sync::Arc; use log::info; +use client::Client; use client::block_builder::api::BlockBuilder; use client::runtime_api::ConstructRuntimeApi; +use primitives::{Blake2Hasher, Hasher}; use sr_primitives::traits::{Block as BlockT, ProvideRuntimeApi, One}; use sr_primitives::generic::BlockId; -use substrate_service::{ - FactoryBlock, FullClient, ServiceFactory, ComponentClient, FullComponents -}; use crate::{Mode, RuntimeAdapter, create_block}; -pub fn next( +pub fn next( factory_state: &mut RA, - client: &Arc>>, + client: &Arc>, + version: u32, genesis_hash: ::Hash, prior_block_hash: ::Hash, - prior_block_id: BlockId, -) -> Option<::Block> + prior_block_id: BlockId, +) -> Option where - F: ServiceFactory, - F::RuntimeApi: ConstructRuntimeApi, FullClient>, - FullClient: ProvideRuntimeApi, - as ProvideRuntimeApi>::Api: BlockBuilder>, + Block: BlockT::Out>, + Exec: client::CallExecutor + Send + Sync + Clone, + Backend: client::backend::Backend + Send, + Client: ProvideRuntimeApi, + as ProvideRuntimeApi>::Api: BlockBuilder, + RtApi: ConstructRuntimeApi> + Send + Sync, RA: RuntimeAdapter, { if factory_state.block_no() >= factory_state.num() { @@ -83,6 +85,7 @@ where &from.1, &to, &amount, + version, &genesis_hash, &prior_block_hash, ); @@ -91,7 +94,7 @@ where let inherents = client.runtime_api().inherent_extrinsics(&prior_block_id, inherents) .expect("Failed to create inherent extrinsics"); - let block = create_block::(&client, transfer, inherents); + let block = create_block::(&client, transfer, inherents); factory_state.set_block_no(factory_state.block_no() + RA::Number::one());

{ } } -pub fn extract_type_option(typ: &syn::Type) -> Option { +pub fn extract_type_option(typ: &syn::Type) -> Option { if let syn::Type::Path(ref path) = typ { let v = path.path.segments.last()?; - if v.value().ident == "Option" { - if let syn::PathArguments::AngleBracketed(ref a) = v.value().arguments { - let args = &a.args; - return Some(quote!{ #args }) + if v.ident == "Option" { + // Option has only one type argument in angle bracket. + if let syn::PathArguments::AngleBracketed(a) = &v.arguments { + if let syn::GenericArgument::Type(typ) = a.args.last()? { + return Some(typ.clone()) + } } } } @@ -228,7 +224,7 @@ impl<'ast> Visit<'ast> for ContainsIdent<'ast> { } fn visit_macro(&mut self, input: &'ast syn::Macro) { - self.visit_tokenstream(input.tts.clone()); + self.visit_tokenstream(input.tokens.clone()); visit::visit_macro(self, input); } } @@ -253,4 +249,4 @@ pub fn expr_contains_ident(expr: &syn::Expr, ident: &Ident) -> bool { visit::visit_expr(&mut visit, expr); visit.result -} \ No newline at end of file +} diff --git a/srml/support/src/debug.rs b/srml/support/src/debug.rs new file mode 100644 index 0000000000000000000000000000000000000000..b8c7457eb237cbc2d6dd9d6340086e597d8a9e22 --- /dev/null +++ b/srml/support/src/debug.rs @@ -0,0 +1,215 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime debugging and logging utilities. +//! +//! This module contains macros and functions that will allow +//! you to print logs out of the runtime code. +//! +//! First and foremost be aware that adding regular logging code to +//! your runtime will have a negative effect on the performance +//! and size of the blob. Luckily there are some ways to mitigate +//! this that are described below. +//! +//! First component to utilize debug-printing and loggin is actually +//! located in `primitives` crate: `primitives::RuntimeDebug`. +//! This custom-derive generates `core::fmt::Debug` implementation, +//! just like regular `derive(Debug)`, however it does not generate +//! any code when the code is compiled to WASM. This means that +//! you can safely sprinkle `RuntimeDebug` in your runtime codebase, +//! without affecting the size. This also allows you to print/log +//! both when the code is running natively or in WASM, but note +//! that WASM debug formatting of structs will be empty. +//! +//! ```rust,no_run +//! use srml_support::debug; +//! +//! #[derive(primitives::RuntimeDebug)] +//! struct MyStruct { +//! a: u64, +//! } +//! +//! // First initialize the logger. +//! // +//! // This is only required when you want the logs to be printed +//! // also during non-native run. +//! // Note that enabling the logger has performance impact on +//! // WASM runtime execution and should be used sparingly. +//! debug::RuntimeLogger::init(); +//! +//! let x = MyStruct { a: 5 }; +//! // will log an info line `"My struct: MyStruct{a:5}"` when running +//! // natively, but will only print `"My struct: "` when running WASM. +//! debug::info!("My struct: {:?}", x); +//! +//! // same output here, although this will print to stdout +//! // (and without log format) +//! debug::print!("My struct: {:?}", x); +//! ``` +//! +//! If you want to avoid extra overhead in WASM, but still be able +//! to print / log when the code is executed natively you can use +//! macros coming from `native` sub-module. This module enables +//! logs conditionally and strips out logs in WASM. +//! +//! ```rust,no_run +//! use srml_support::debug::native; +//! +//! #[derive(primitives::RuntimeDebug)] +//! struct MyStruct { +//! a: u64, +//! } +//! +//! // We don't initialize the logger, since +//! // we are not printing anything out in WASM. +//! // debug::RuntimeLogger::init(); +//! +//! let x = MyStruct { a: 5 }; +//! +//! // Displays an info log when running natively, nothing when WASM. +//! native::info!("My struct: {:?}", x); +//! +//! // same output to stdout, no overhead on WASM. +//! native::print!("My struct: {:?}", x); +//! ``` + +use rstd::vec::Vec; +use rstd::fmt::{self, Debug}; + +pub use log::{info, debug, error, trace, warn}; +pub use crate::runtime_print as print; + +/// Native-only logging. +/// +/// Using any functions from this module will have any effect +/// only if the runtime is running natively (i.e. not via WASM) +#[cfg(feature = "std")] +pub mod native { + pub use super::{info, debug, error, trace, warn, print}; +} + +/// Native-only logging. +/// +/// Using any functions from this module will have any effect +/// only if the runtime is running natively (i.e. not via WASM) +#[cfg(not(feature = "std"))] +pub mod native { + #[macro_export] + macro_rules! noop { + ($($arg:tt)+) => {} + } + pub use noop as info; + pub use noop as debug; + pub use noop as error; + pub use noop as trace; + pub use noop as warn; + pub use noop as print; +} + +/// Print out a formatted message. +/// +/// # Example +/// +/// ``` +/// srml_support::runtime_print!("my value is {}", 3); +/// ``` +#[macro_export] +macro_rules! runtime_print { + ($($arg:tt)+) => { + use core::fmt::Write; + let mut w = $crate::debug::Writer::default(); + let _ = core::write!(&mut w, $($arg)+); + w.print(); + } +} + +/// Print out the debuggable type. +pub fn debug(data: &impl Debug) { + runtime_print!("{:?}", data); +} + +/// A target for `core::write!` macro - constructs a string in memory. +#[derive(Default)] +pub struct Writer(Vec); + +impl fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.0.extend(s.as_bytes()); + Ok(()) + } +} + +impl Writer { + /// Print the content of this `Writer` out. + pub fn print(&self) { + runtime_io::print_utf8(&self.0) + } +} + +/// Runtime logger implementation - `log` crate backend. +/// +/// The logger should be initialized if you want to display +/// logs inside the runtime that is not necessarily running natively. +/// +/// When runtime is executed natively any log statements are displayed +/// even if this logger is NOT initialized. +/// +/// Note that even though the logs are not displayed in WASM, they +/// may still affect the size and performance of the generated runtime. +/// To lower the footprint make sure to only use macros from `native` +/// sub-module. +pub struct RuntimeLogger; + +impl RuntimeLogger { + /// Initialize the logger. + /// + /// This is a no-op when running natively (`std`). + #[cfg(feature = "std")] + pub fn init() {} + + /// Initialize the logger. + /// + /// This is a no-op when running natively (`std`). + #[cfg(not(feature = "std"))] + pub fn init() { + static LOGGER: RuntimeLogger = RuntimeLogger;; + let _ = log::set_logger(&LOGGER); + } +} + +impl log::Log for RuntimeLogger { + fn enabled(&self, _metadata: &log::Metadata) -> bool { + // to avoid calling to host twice, we pass everything + // and let the host decide what to print. + // If someone is initializing the logger they should + // know what they are doing. + true + } + + fn log(&self, record: &log::Record) { + use fmt::Write; + let mut w = Writer::default(); + let _ = core::write!(&mut w, "{}", record.args()); + + runtime_io::log( + record.level().into(), + record.target().as_bytes(), + &w.0, + ); + } + + fn flush(&self) {} +} diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 21a2a817fbb1fb78b24d974c0a8c6e3d39a3869c..df86f436117a1bf7c66508bb26a56251473bacbb 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -17,26 +17,26 @@ //! Dispatch system. Contains a macro for defining runtime modules and //! generating values representing lazy module function calls. -pub use crate::rstd::{result, prelude::{Vec, Clone, Eq, PartialEq}, marker}; -#[cfg(feature = "std")] -pub use std::fmt; -pub use crate::codec::{Codec, Decode, Encode, Input, Output, HasCompact, EncodeAsRef}; +pub use crate::rstd::{result, fmt, prelude::{Vec, Clone, Eq, PartialEq}, marker}; +pub use crate::codec::{Codec, EncodeLike, Decode, Encode, Input, Output, HasCompact, EncodeAsRef}; pub use srml_metadata::{ FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata, - ModuleConstantMetadata, DefaultByte, DefaultByteGetter, + ModuleConstantMetadata, DefaultByte, DefaultByteGetter, ModuleErrorMetadata, ErrorMetadata }; -pub use sr_primitives::weights::{SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, - ClassifyDispatch, - TransactionPriority +pub use sr_primitives::{ + weights::{ + SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, + TransactionPriority + }, + traits::{Dispatchable, DispatchResult, ModuleDispatchError}, + DispatchError, }; -pub use sr_primitives::traits::{Dispatchable, DispatchResult}; /// A type that cannot be instantiated. pub enum Never {} -/// Result of a module function call; either nothing (functions are only called for "side effects") -/// or an error message. -pub type Result = DispatchResult; +/// Result with string error message. This exists for backward compatibility purpose. +pub type Result = DispatchResult<&'static str>; /// Serializable version of Dispatchable. /// This value can be used as a "function" in an extrinsic. @@ -48,17 +48,8 @@ pub trait Callable { // https://github.com/rust-lang/rust/issues/51331 pub type CallableCallFor = >::Call; -#[cfg(feature = "std")] -pub trait Parameter: Codec + Clone + Eq + fmt::Debug {} - -#[cfg(feature = "std")] -impl Parameter for T where T: Codec + Clone + Eq + fmt::Debug {} - -#[cfg(not(feature = "std"))] -pub trait Parameter: Codec + Clone + Eq {} - -#[cfg(not(feature = "std"))] -impl Parameter for T where T: Codec + Clone + Eq {} +pub trait Parameter: Codec + EncodeLike + Clone + Eq + fmt::Debug {} +impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// Declares a `Module` struct and a `Call` enum, which implements the dispatch logic. /// @@ -171,6 +162,9 @@ impl Parameter for T where T: Codec + Clone + Eq {} /// # fn main() {} /// ``` /// +/// Note: `decl_storage` must be called to generate `Instance` trait and optionally +/// `DefaultInstance` type. +/// /// ## Where clause /// /// Besides the default `origin: T::Origin`, you can also pass other bounds to the module declaration. @@ -200,7 +194,7 @@ impl Parameter for T where T: Codec + Clone + Eq {} /// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.dev/docs/event-enum). /// The default behavior is to call `deposit_event` from the [System module](../srml_system/index.html). /// However, you can write your own implementation for events in your runtime. To use the default behavior, -/// add `fn deposit_event() = default;` to your `Module`. +/// add `fn deposit_event() = default;` to your `Module`. /// /// The following reserved functions also take the block number (with type `T::BlockNumber`) as an optional input: /// @@ -236,6 +230,7 @@ macro_rules! decl_module { {} {} {} + {} [] $($t)* ); @@ -267,6 +262,7 @@ macro_rules! decl_module { {} {} {} + {} [] $($t)* ); @@ -283,9 +279,10 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* - $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* () = default; + $vis:vis fn deposit_event() = default; $($rest:tt)* ) => { $crate::decl_module!(@normalize @@ -293,11 +290,12 @@ macro_rules! decl_module { pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> for enum $call_type where origin: $origin_type, system = $system { $( $other_where_bounds )* } - { $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* () = default; } + { $vis fn deposit_event() = default; } { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } + { $( $error_type )* } [ $( $dispatchables )* ] $($rest)* ); @@ -312,25 +310,14 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* - $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* ( - $($param_name:ident : $param:ty),* - ) { $( $impl:tt )* } + $vis:vis fn deposit_event $($rest:tt)* ) => { - $crate::decl_module!(@normalize - $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name$(, I: $instantiable $(= $module_default_instance)?)?> - for enum $call_type where origin: $origin_type, system = $system - { $( $other_where_bounds )* } - { $vis fn deposit_event $(<$dpeg $(, $dpeg_instance)?>)* ($( $param_name: $param ),* ) { $( $impl )* } } - { $( $on_initialize )* } - { $( $on_finalize )* } - { $( $offchain )* } - { $( $constants )* } - [ $( $dispatchables )* ] - $($rest)* + compile_error!( + "`deposit_event` function is reserved and must follow the syntax: `$vis:vis fn deposit_event() = default;`" ); }; (@normalize @@ -343,9 +330,10 @@ macro_rules! decl_module { {} { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* - fn on_finalize($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } $($rest:tt)* ) => { $crate::decl_module!(@normalize @@ -358,29 +346,11 @@ macro_rules! decl_module { { fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } } { $( $offchain )* } { $( $constants )* } + { $( $error_type )* } [ $( $dispatchables )* ] $($rest)* ); }; - (@normalize - $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> - for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident - { $( $other_where_bounds:tt )* } - { $( $deposit_event:tt )* } - { $( $on_initialize:tt )* } - {} - { $( $offchain:tt )* } - { $( $constants:tt )* } - [ $( $dispatchables:tt )* ] - $(#[doc = $doc_attr:tt])* - fn on_finalise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } - $($rest:tt)* - ) => { - compile_error!( - "`on_finalise` was renamed to `on_finalize`. Please rename your function accordingly." - ); - }; (@normalize $(#[$attr:meta])* pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> @@ -391,9 +361,10 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* - fn on_initialize($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } $($rest:tt)* ) => { $crate::decl_module!(@normalize @@ -406,29 +377,11 @@ macro_rules! decl_module { { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } + { $( $error_type )* } [ $( $dispatchables )* ] $($rest)* ); }; - (@normalize - $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(, I: $instantiable:path $(= $module_default_instance:path)?)?> - for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident - { $( $other_where_bounds:tt )* } - { $( $deposit_event:tt )* } - {} - { $( $on_finalize:tt )* } - { $( $offchain:tt )* } - { $( $constants:tt )* } - [ $( $dispatchables:tt )* ] - $(#[doc = $doc_attr:tt])* - fn on_initialise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } - $($rest:tt)* - ) => { - compile_error!( - "`on_initialise` was renamed to `on_initialize`. Please rename your function accordingly." - ); - }; (@normalize $(#[$attr:meta])* pub struct $mod_type:ident< @@ -442,9 +395,10 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* - fn offchain_worker($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } + fn offchain_worker( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* } $($rest:tt)* ) => { $crate::decl_module!(@normalize @@ -459,6 +413,7 @@ macro_rules! decl_module { { $( $on_finalize )* } { fn offchain_worker( $( $param_name : $param ),* ) { $( $impl )* } } { $( $constants )* } + { $( $error_type )* } [ $( $dispatchables )* ] $($rest)* ); @@ -478,6 +433,7 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $( #[doc = $doc_attr:tt] )* const $name:ident: $ty:ty = $value:expr; @@ -500,10 +456,84 @@ macro_rules! decl_module { $( #[doc = $doc_attr ] )* $name: $ty = $value; } + { $( $error_type )* } + [ $( $dispatchables )* ] + $($rest)* + ); + }; + + // Parse error type + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident< + $trait_instance:ident: + $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)? + > + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $other_where_bounds:tt )* } + { $( $deposit_event:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { } + [ $( $dispatchables:tt )* ] + $(#[doc = $doc_attr:tt])* + type Error = $error_type:ty; + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type< + $trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)? + > + for enum $call_type where origin: $origin_type, system = $system + { $( $other_where_bounds )* } + { $( $deposit_event )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } + { $( $constants )* } + { $error_type } [ $( $dispatchables )* ] $($rest)* ); }; + // Add default Error if none supplied + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident< + $trait_instance:ident: + $trait_name:ident$(, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)? + > + for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident + { $( $other_where_bounds:tt )* } + { $( $deposit_event:tt )* } + { $( $on_initialize:tt )* } + { $( $on_finalize:tt )* } + { $( $offchain:tt )* } + { $( $constants:tt )* } + { } + [ $($t:tt)* ] + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type< + $trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)? + > + for enum $call_type where origin: $origin_type, system = $system + { $( $other_where_bounds )* } + { $( $deposit_event )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } + { $( $constants )* } + { &'static str } + [ $($t)* ] + $($rest)* + ); + }; // This puts the function statement into the [], decreasing `$rest` and moving toward finishing the parse. (@normalize @@ -519,11 +549,12 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $error_type:ty } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* #[weight = $weight:expr] $fn_vis:vis fn $fn_name:ident( - $origin:ident $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* + $origin:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty )* $(,)? ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -539,6 +570,7 @@ macro_rules! decl_module { { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } + { $error_type } [ $( $dispatchables )* $(#[doc = $doc_attr])* @@ -565,10 +597,11 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( - $from:ident $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* + $from:ident $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)? ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -584,6 +617,7 @@ macro_rules! decl_module { { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } + { $( $error_type )* } [ $( $dispatchables )* ] $(#[doc = $doc_attr])* #[weight = $crate::dispatch::SimpleDispatchInfo::default()] @@ -604,11 +638,12 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? $fn_vis:vis fn $fn_name:ident( - $origin:ident : T::Origin $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* + $origin:ident : T::Origin $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)? ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -628,11 +663,12 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? $fn_vis:vis fn $fn_name:ident( - origin : $origin:ty $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* + origin : $origin:ty $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)? ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -652,11 +688,12 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? $fn_vis:vis fn $fn_name:ident( - $( $(#[$codec_attr:ident])* $param_name:ident : $param:ty),* + $( $(#[$codec_attr:ident])* $param_name:ident : $param:ty ),* $(,)? ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -677,6 +714,7 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $( $error_type:tt )* } [ $( $dispatchables:tt )* ] ) => { $crate::decl_module!(@imp @@ -691,6 +729,7 @@ macro_rules! decl_module { { $( $on_finalize )* } { $( $offchain )* } { $( $constants )* } + { $( $error_type )* } ); }; @@ -720,25 +759,10 @@ macro_rules! decl_module { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { - $vis fn deposit_event(event: Event$(<$event_trait_instance $(, $event_instance)?>)?) { - <$system::Module<$trait_instance>>::deposit_event( - <$trait_instance as $trait_name$(<$instance>)?>::Event::from(event).into() - ); - } - } - }; - - (@impl_deposit_event - $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; - $system:ident; - { $( $other_where_bounds:tt )* } - $vis:vis fn deposit_event($param:ident : $param_ty:ty) { $( $impl:tt )* } - ) => { - impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> - where $( $other_where_bounds )* - { - $vis fn deposit_event($param: $param_ty) { - $( $impl )* + $vis fn deposit_event( + event: impl Into<< $trait_instance as $trait_name $(<$instance>)? >::Event> + ) { + <$system::Module<$trait_instance>>::deposit_event(event.into()) } } }; @@ -856,6 +880,7 @@ macro_rules! decl_module { (@impl_function $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; + $error_type:ty; $ignore:ident; $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( @@ -866,7 +891,7 @@ macro_rules! decl_module { #[allow(unreachable_code)] $vis fn $name( $origin: $origin_ty $(, $param: $param_ty )* - ) -> $crate::dispatch::Result { + ) -> $crate::dispatch::DispatchResult<$error_type> { { $( $impl )* } // May be unreachable. Ok(()) @@ -877,6 +902,7 @@ macro_rules! decl_module { (@impl_function $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; + $error_type:ty; $ignore:ident; $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( @@ -1031,12 +1057,12 @@ macro_rules! decl_module { { $( $on_finalize:tt )* } { $( $offchain:tt )* } { $( $constants:tt )* } + { $error_type:ty } ) => { $crate::__check_reserved_fn_name! { $( $fn_name )* } // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, Copy, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive(Clone, Copy, PartialEq, Eq, $crate::RuntimeDebug)] pub struct $mod_type< $trait_instance: $trait_name $(, $instance: $instantiable $( = $module_default_instance)?)? @@ -1082,6 +1108,7 @@ macro_rules! decl_module { @impl_function $mod_type<$trait_instance: $trait_name $(, $fn_instance: $fn_instantiable)?>; $origin_type; + $error_type; $from; $(#[doc = $doc_attr])* $fn_vis fn $fn_name ( @@ -1186,7 +1213,6 @@ macro_rules! decl_module { for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* {} - #[cfg(feature = "std")] impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::fmt::Debug for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { @@ -1212,7 +1238,8 @@ macro_rules! decl_module { { type Trait = $trait_instance; type Origin = $origin_type; - fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::Result { + type Error = $error_type; + fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResult { match self { $( $call_type::$fn_name( $( $param_name ),* ) => { @@ -1239,8 +1266,8 @@ macro_rules! decl_module { #[doc(hidden)] pub fn dispatch>( d: D, - origin: D::Origin, - ) -> $crate::dispatch::Result { + origin: D::Origin + ) -> $crate::dispatch::DispatchResult { d.dispatch(origin) } } @@ -1260,6 +1287,14 @@ macro_rules! decl_module { { $( $other_where_bounds )* } $( $constants )* } + + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::ModuleErrorMetadata + for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* + { + fn metadata() -> &'static [$crate::dispatch::ErrorMetadata] { + <$error_type as $crate::dispatch::ModuleErrorMetadata>::metadata() + } + } } } @@ -1279,8 +1314,12 @@ macro_rules! impl_outer_dispatch { } ) => { $(#[$attr])* - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive( + Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] pub enum $call_type { $( $camelcase ( $crate::dispatch::CallableCallFor<$camelcase, $runtime> ) @@ -1296,9 +1335,19 @@ macro_rules! impl_outer_dispatch { impl $crate::dispatch::Dispatchable for $call_type { type Origin = $origin; type Trait = $call_type; - fn dispatch(self, origin: $origin) -> $crate::dispatch::Result { - match self { - $( $call_type::$camelcase(call) => call.dispatch(origin), )* + type Error = $crate::dispatch::DispatchError; + fn dispatch( + self, + origin: $origin, + ) -> $crate::dispatch::DispatchResult<$crate::dispatch::DispatchError> { + $crate::impl_outer_dispatch! { + @DISPATCH_MATCH + self + $call_type + origin + {} + 0; + $( $camelcase ),* } } } @@ -1320,6 +1369,43 @@ macro_rules! impl_outer_dispatch { } } )* + }; + (@DISPATCH_MATCH + $self:ident + $call_type:ident + $origin:ident + { $( $generated:tt )* } + $index:expr; + $name:ident + $( , $rest:ident )* + ) => { + $crate::impl_outer_dispatch! { + @DISPATCH_MATCH + $self + $call_type + $origin + { + $( $generated )* + $call_type::$name(call) => call.dispatch($origin).map_err(|e| { + let mut error: $crate::dispatch::DispatchError = e.into(); + error.module = Some($index); + error + }), + } + $index + 1; + $( $rest ),* + } + }; + (@DISPATCH_MATCH + $self:ident + $call_type:ident + $origin:ident + { $( $generated:tt )* } + $index:expr; + ) => { + match $self { + $( $generated )* + } } } @@ -1576,13 +1662,13 @@ macro_rules! __check_reserved_fn_name { $crate::__check_reserved_fn_name!(@compile_error on_initialize); }; (on_initialise $( $rest:ident )*) => { - $crate::__check_reserved_fn_name!(@compile_error on_initialise); + $crate::__check_reserved_fn_name!(@compile_error_renamed on_initialise on_initialize); }; (on_finalize $( $rest:ident )*) => { $crate::__check_reserved_fn_name!(@compile_error on_finalize); }; (on_finalise $( $rest:ident )*) => { - $crate::__check_reserved_fn_name!(@compile_error on_finalise); + $crate::__check_reserved_fn_name!(@compile_error_renamed on_finalise on_finalize); }; (offchain_worker $( $rest:ident )*) => { $crate::__check_reserved_fn_name!(@compile_error offchain_worker); @@ -1592,9 +1678,26 @@ macro_rules! __check_reserved_fn_name { }; () => {}; (@compile_error $ident:ident) => { - compile_error!(concat!("Invalid call fn name: `", stringify!($ident), - "`, name is reserved and doesn't match expected signature, please refer to `decl_module!`", - " documentation to see the appropriate usage, or rename it to an unreserved keyword.")); + compile_error!( + concat!( + "Invalid call fn name: `", + stringify!($ident), + "`, name is reserved and doesn't match expected signature, please refer to ", + "`decl_module!` documentation to see the appropriate usage, or rename it to an ", + "unreserved keyword." + ), + ); + }; + (@compile_error_renamed $ident:ident $new_ident:ident) => { + compile_error!( + concat!( + "`", + stringify!($ident), + "` was renamed to `", + stringify!($new_ident), + "`. Please rename your function accordingly.", + ), + ); }; } @@ -1628,19 +1731,19 @@ mod tests { pub struct Module for enum Call where origin: T::Origin, T::AccountId: From { /// Hi, this is a comment. fn aux_0(_origin) -> Result { unreachable!() } - fn aux_1(_origin, #[compact] _data: u32) -> Result { unreachable!() } + fn aux_1(_origin, #[compact] _data: u32,) -> Result { unreachable!() } fn aux_2(_origin, _data: i32, _data2: String) -> Result { unreachable!() } #[weight = SimpleDispatchInfo::FixedNormal(3)] fn aux_3(_origin) -> Result { unreachable!() } fn aux_4(_origin, _data: i32) -> Result { unreachable!() } - fn aux_5(_origin, _data: i32, #[compact] _data2: u32) -> Result { unreachable!() } + fn aux_5(_origin, _data: i32, #[compact] _data2: u32,) -> Result { unreachable!() } - fn on_initialize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_initialize") } } + fn on_initialize(n: T::BlockNumber,) { if n.into() == 42 { panic!("on_initialize") } } fn on_finalize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalize") } } fn offchain_worker() {} #[weight = SimpleDispatchInfo::FixedOperational(5)] - fn operational(_origin) { unreachable!() } + fn operational(_origin,) { unreachable!() } } } diff --git a/srml/support/src/double_map.rs b/srml/support/src/double_map.rs deleted file mode 100644 index aec7f497a63913391256237b7a8df1a360ab3ccb..0000000000000000000000000000000000000000 --- a/srml/support/src/double_map.rs +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! An implementation of double map backed by storage. - -use crate::rstd::prelude::*; -use crate::codec::{Codec, Encode}; -use crate::storage::unhashed; -use sr_std::borrow::Borrow; - -/// An implementation of a map with a two keys. -/// -/// It provides an important ability to efficiently remove all entries -/// that have a common first key. -/// -/// # Mapping of keys to a storage path -/// -/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. -/// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part -/// is a hash of a `Key2`. -/// -/// Hasher are implemented in derive_key* methods. -pub trait StorageDoubleMapWithHasher { - type Key1: Encode; - type Key2: Encode; - type Value: Codec + Default; - - const PREFIX: &'static [u8]; - - /// Insert an entry into this map. - fn insert(k1: &Q, k2: &R, val: Self::Value) - where - Self::Key1: Borrow, - Self::Key2: Borrow, - Q: Codec, - R: Codec - { - unhashed::put(&Self::full_key(k1, k2)[..], &val); - } - - /// Remove an entry from this map. - fn remove(k1: &Q, k2: &R) - where - Self::Key1: Borrow, - Self::Key2: Borrow, - Q: Codec, - R: Codec - { - unhashed::kill(&Self::full_key(k1, k2)[..]); - } - - /// Get an entry from this map. - /// - /// If there is no entry stored under the given keys, returns `None`. - fn get(k1: &Q, k2: &R) -> Option - where - Self::Key1: Borrow, - Self::Key2: Borrow, - Q: Codec, - R: Codec - { - unhashed::get(&Self::full_key(k1, k2)[..]) - } - - /// Returns `true` if value under the specified keys exists. - fn exists(k1: &Q, k2: &R) -> bool - where - Self::Key1: Borrow, - Self::Key2: Borrow, - Q: Codec, - R: Codec - { - unhashed::exists(&Self::full_key(k1, k2)[..]) - } - - /// Removes all entries that shares the `k1` as the first key. - fn remove_prefix(k1: &Q) - where - Self::Key1: Borrow, - Q: Codec - { - unhashed::kill_prefix(&Self::derive_key1(Self::encode_key1(k1))) - } - - /// Encode key1 into Vec and prepend a prefix - fn encode_key1(key: &Q) -> Vec - where - Self::Key1: Borrow, - Q: Codec - { - let mut raw_prefix = Vec::new(); - raw_prefix.extend(Self::PREFIX); - key.encode_to(&mut raw_prefix); - raw_prefix - } - - /// Encode key2 into Vec - fn encode_key2(key: &R) -> Vec - where - Self::Key2: Borrow, - R: Codec - { - Encode::encode(&key) - } - - /// Derive the first part of the key - fn derive_key1(key1_data: Vec) -> Vec; - - /// Derive the remaining part of the key - fn derive_key2(key2_data: Vec) -> Vec; - - /// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`. - /// The first part is hashed and then concatenated with a hash of `k2`. - fn full_key(k1: &Q, k2: &R) -> Vec - where - Self::Key1: Borrow, - Self::Key2: Borrow, - Q: Codec, - R: Codec - { - let key1_data = Self::encode_key1(k1); - let key2_data = Self::encode_key2(k2); - let mut key = Self::derive_key1(key1_data); - key.extend(Self::derive_key2(key2_data)); - key - } -} diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..9aa13713daafb7f418cd82efee587613e0841d32 --- /dev/null +++ b/srml/support/src/error.rs @@ -0,0 +1,166 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Macro for declaring a module error. + +#[doc(hidden)] +pub use sr_primitives::traits::LookupError; +pub use srml_metadata::{ModuleErrorMetadata, ErrorMetadata, DecodeDifferent}; + +/// Declare an error type for a runtime module. +/// +/// The generated error type inherently has the variants `Other` and `CannotLookup`. `Other` can +/// hold any `&'static str` error message and is present for convenience/backward compatibility. +/// The `CannotLookup` variant indicates that some lookup could not be done. For both variants the +/// error type implements `From<&'static str>` and `From` to make them usable with the +/// try operator. +/// +/// # Usage +/// +/// ``` +/// # use srml_support::decl_error; +/// decl_error! { +/// /// Errors that can occur in my module. +/// pub enum MyError { +/// /// Hey this is an error message that indicates bla. +/// MyCoolErrorMessage, +/// /// You are just not cool enough for my module! +/// YouAreNotCoolEnough, +/// } +/// } +/// ``` +/// +/// `decl_error!` supports only variants that do not hold any data. +#[macro_export] +macro_rules! decl_error { + ( + $(#[$attr:meta])* + pub enum $error:ident { + $( + $( #[doc = $doc_attr:tt] )* + $name:ident + ),* + $(,)? + } + ) => { + #[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)] + $(#[$attr])* + pub enum $error { + Other(&'static str), + CannotLookup, + $( + $( #[doc = $doc_attr] )* + $name + ),* + } + + impl $crate::dispatch::ModuleDispatchError for $error { + fn as_u8(&self) -> u8 { + $crate::decl_error! { + @GENERATE_AS_U8 + self + $error + {} + 2, + $( $name ),* + } + } + + fn as_str(&self) -> &'static str { + match self { + $error::Other(err) => err, + $error::CannotLookup => "Can not lookup", + $( + $error::$name => stringify!($name), + )* + } + } + } + + impl From<&'static str> for $error { + fn from(val: &'static str) -> $error { + $error::Other(val) + } + } + + impl From<$crate::error::LookupError> for $error { + fn from(_: $crate::error::LookupError) -> $error { + $error::CannotLookup + } + } + + impl From<$error> for &'static str { + fn from(err: $error) -> &'static str { + use $crate::dispatch::ModuleDispatchError; + err.as_str() + } + } + + impl Into<$crate::dispatch::DispatchError> for $error { + fn into(self) -> $crate::dispatch::DispatchError { + use $crate::dispatch::ModuleDispatchError; + $crate::dispatch::DispatchError::new(None, self.as_u8(), Some(self.as_str())) + } + } + + impl $crate::error::ModuleErrorMetadata for $error { + fn metadata() -> &'static [$crate::error::ErrorMetadata] { + &[ + $( + $crate::error::ErrorMetadata { + name: $crate::error::DecodeDifferent::Encode(stringify!($name)), + documentation: $crate::error::DecodeDifferent::Encode(&[ + $( $doc_attr ),* + ]), + } + ),* + ] + } + } + }; + (@GENERATE_AS_U8 + $self:ident + $error:ident + { $( $generated:tt )* } + $index:expr, + $name:ident + $( , $rest:ident )* + ) => { + $crate::decl_error! { + @GENERATE_AS_U8 + $self + $error + { + $( $generated )* + $error::$name => $index, + } + $index + 1, + $( $rest ),* + } + }; + (@GENERATE_AS_U8 + $self:ident + $error:ident + { $( $generated:tt )* } + $index:expr, + ) => { + match $self { + $error::Other(_) => 0, + $error::CannotLookup => 1, + $( $generated )* + } + } +} diff --git a/srml/support/src/event.rs b/srml/support/src/event.rs index 857f42f49e8aaa2b9dfc2a2c49f6a1575a9883b2..3411c93922e2b08c034171d117adaa69cce989a3 100644 --- a/srml/support/src/event.rs +++ b/srml/support/src/event.rs @@ -121,8 +121,12 @@ macro_rules! decl_event { } ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive( + Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] /// Events for this module. /// $(#[$attr])* @@ -260,9 +264,12 @@ macro_rules! __decl_generic_event { /// [`Trait`]: trait.Trait.html pub type Event<$event_generic_param $(, $instance $( = $event_default_instance)? )?> = RawEvent<$( $generic_type ),* $(, $instance)? >; - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive( + Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] /// Events for this module. /// $(#[$attr])* @@ -452,31 +459,48 @@ macro_rules! impl_outer_event { $( $module_name:ident::Event $( <$generic_param:ident> )? $( { $generic_instance:ident } )?, )*; ) => { $crate::paste::item! { - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug))] - $(#[$attr])* - #[allow(non_camel_case_types)] - pub enum $name { - system($system::Event), - $( - [< $module_name $(_ $generic_instance )? >]( - $module_name::Event < $( $generic_param )? $(, $module_name::$generic_instance )? > - ), - )* - } - impl From<$system::Event> for $name { - fn from(x: $system::Event) -> Self { - $name::system(x) + #[derive( + Clone, PartialEq, Eq, + $crate::codec::Encode, + $crate::codec::Decode, + $crate::RuntimeDebug, + )] + $(#[$attr])* + #[allow(non_camel_case_types)] + pub enum $name { + system($system::Event), + $( + [< $module_name $(_ $generic_instance )? >]( + $module_name::Event < $( $generic_param )? $(, $module_name::$generic_instance )? > + ), + )* } - } - $( - impl From<$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >> for $name { - fn from(x: $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >) -> Self { - $name::[< $module_name $(_ $generic_instance )? >](x) + impl From<$system::Event> for $name { + fn from(x: $system::Event) -> Self { + $name::system(x) } } - )* + $( + impl From<$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >> for $name { + fn from(x: $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >) -> Self { + $name::[< $module_name $(_ $generic_instance )? >](x) + } + } + impl $crate::rstd::convert::TryInto< + $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? > + > for $name { + type Error = (); + + fn try_into(self) -> $crate::rstd::result::Result< + $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >, Self::Error + > { + match self { + Self::[< $module_name $(_ $generic_instance )? >](evt) => Ok(evt), + _ => Err(()), + } + } + } + )* } $crate::__impl_outer_event_json_metadata!( $runtime; diff --git a/srml/support/src/hash.rs b/srml/support/src/hash.rs new file mode 100644 index 0000000000000000000000000000000000000000..cbd78f603241eb5746045be59f6c4f462af77b49 --- /dev/null +++ b/srml/support/src/hash.rs @@ -0,0 +1,114 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Hash utilities. + +use codec::Codec; +use rstd::prelude::Vec; +use runtime_io::{blake2_128, blake2_256, twox_64, twox_128, twox_256}; + +// This trait must be kept coherent with srml-support-procedural HasherKind usage +pub trait Hashable: Sized { + fn blake2_128(&self) -> [u8; 16]; + fn blake2_256(&self) -> [u8; 32]; + fn twox_128(&self) -> [u8; 16]; + fn twox_256(&self) -> [u8; 32]; + fn twox_64_concat(&self) -> Vec; +} + +impl Hashable for T { + fn blake2_128(&self) -> [u8; 16] { + self.using_encoded(blake2_128) + } + fn blake2_256(&self) -> [u8; 32] { + self.using_encoded(blake2_256) + } + fn twox_128(&self) -> [u8; 16] { + self.using_encoded(twox_128) + } + fn twox_256(&self) -> [u8; 32] { + self.using_encoded(twox_256) + } + fn twox_64_concat(&self) -> Vec { + self.using_encoded(Twox64Concat::hash) + } +} + +/// Hasher to use to hash keys to insert to storage. +pub trait StorageHasher: 'static { + type Output: AsRef<[u8]>; + fn hash(x: &[u8]) -> Self::Output; +} + +/// Hash storage keys with `concat(twox64(key), key)` +pub struct Twox64Concat; +impl StorageHasher for Twox64Concat { + type Output = Vec; + fn hash(x: &[u8]) -> Vec { + twox_64(x) + .iter() + .chain(x.into_iter()) + .cloned() + .collect::>() + } +} + +/// Hash storage keys with blake2 128 +pub struct Blake2_128; +impl StorageHasher for Blake2_128 { + type Output = [u8; 16]; + fn hash(x: &[u8]) -> [u8; 16] { + blake2_128(x) + } +} + +/// Hash storage keys with blake2 256 +pub struct Blake2_256; +impl StorageHasher for Blake2_256 { + type Output = [u8; 32]; + fn hash(x: &[u8]) -> [u8; 32] { + blake2_256(x) + } +} + +/// Hash storage keys with twox 128 +pub struct Twox128; +impl StorageHasher for Twox128 { + type Output = [u8; 16]; + fn hash(x: &[u8]) -> [u8; 16] { + twox_128(x) + } +} + +/// Hash storage keys with twox 256 +pub struct Twox256; +impl StorageHasher for Twox256 { + type Output = [u8; 32]; + fn hash(x: &[u8]) -> [u8; 32] { + twox_256(x) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_twox_64_concat() { + let r = Twox64Concat::hash(b"foo"); + assert_eq!(r.split_at(8), (&twox_128(b"foo")[..8], &b"foo"[..])) + } +} diff --git a/srml/support/src/hashable.rs b/srml/support/src/hashable.rs deleted file mode 100644 index b3ee2b3612c1efda2615a9f21d4e26b64325e528..0000000000000000000000000000000000000000 --- a/srml/support/src/hashable.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Hashable trait. - -use crate::codec::Codec; -use runtime_io::{blake2_128, blake2_256, twox_128, twox_256}; -use crate::storage::hashed::generator::StorageHasher; -use crate::Twox64Concat; -use crate::rstd::prelude::Vec; - -// This trait must be kept coherent with srml-support-procedural HasherKind usage -pub trait Hashable: Sized { - fn blake2_128(&self) -> [u8; 16]; - fn blake2_256(&self) -> [u8; 32]; - fn twox_128(&self) -> [u8; 16]; - fn twox_256(&self) -> [u8; 32]; - fn twox_64_concat(&self) -> Vec; -} - -impl Hashable for T { - fn blake2_128(&self) -> [u8; 16] { - self.using_encoded(blake2_128) - } - fn blake2_256(&self) -> [u8; 32] { - self.using_encoded(blake2_256) - } - fn twox_128(&self) -> [u8; 16] { - self.using_encoded(twox_128) - } - fn twox_256(&self) -> [u8; 32] { - self.using_encoded(twox_256) - } - fn twox_64_concat(&self) -> Vec { - self.using_encoded(Twox64Concat::hash) - } -} diff --git a/srml/support/src/inherent.rs b/srml/support/src/inherent.rs index 1b6d8fbdd7ed93588da2892c1ccc3357c900fd2f..935d3b4e74e4f47c14a7c6703a579533d0501dab 100644 --- a/srml/support/src/inherent.rs +++ b/srml/support/src/inherent.rs @@ -55,14 +55,16 @@ macro_rules! impl_outer_inherent { fn create_extrinsics(&self) -> $crate::inherent::Vec<<$block as $crate::inherent::BlockT>::Extrinsic> { use $crate::inherent::ProvideInherent; + use $crate::inherent::Extrinsic; let mut inherents = Vec::new(); $( if let Some(inherent) = $module::create_inherent(self) { - inherents.push($uncheckedextrinsic::new_unsigned( - Call::$call(inherent)) - ); + inherents.push($uncheckedextrinsic::new( + Call::$call(inherent), + None, + ).expect("Runtime UncheckedExtrinsic is not Opaque, so it has to return `Some`; qed")); } )* diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 5623cab70f2ab4dc9b1f3451d1e17f7a72e12554..cfe6487203dddfdf4722247d13d01a46d232ed3d 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -27,7 +27,7 @@ extern crate bitmask; #[cfg(feature = "std")] pub use serde; #[doc(hidden)] -pub use sr_std as rstd; +pub use rstd; #[doc(hidden)] pub use codec; #[cfg(feature = "std")] @@ -35,17 +35,20 @@ pub use codec; pub use once_cell; #[doc(hidden)] pub use paste; - -pub use self::storage::hashed::generator::{ - HashedStorage, Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat -}; -pub use self::storage::unhashed::generator::UnhashedStorage; +#[cfg(feature = "std")] +#[doc(hidden)] +pub use runtime_io::with_storage; +#[doc(hidden)] +pub use runtime_io::storage_root; +#[doc(hidden)] +pub use sr_primitives::RuntimeDebug; #[macro_use] -pub mod dispatch; +pub mod debug; #[macro_use] +pub mod dispatch; pub mod storage; -mod hashable; +mod hash; #[macro_use] pub mod event; #[macro_use] @@ -58,17 +61,14 @@ mod runtime; pub mod inherent; #[macro_use] pub mod unsigned; -mod double_map; +#[macro_use] +pub mod error; pub mod traits; -pub use self::storage::{ - StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap, AppendableStorageMap -}; -pub use self::hashable::Hashable; -pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType}; -pub use self::double_map::StorageDoubleMapWithHasher; -pub use runtime_io::{print, storage_root}; -pub use sr_primitives::{self, ConsensusEngineId}; +pub use self::hash::{Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat, Hashable}; +pub use self::storage::{StorageValue, StorageMap, StorageLinkedMap, StorageDoubleMap}; +pub use self::dispatch::{Parameter, Callable, IsSubType}; +pub use sr_primitives::{self, ConsensusEngineId, print, traits::Printable}; /// Macro for easily creating a new implementation of the `Get` trait. Use similarly to /// how you would declare a `const`: @@ -130,7 +130,7 @@ macro_rules! fail { /// Used as `ensure!(expression_to_ensure, expression_to_return_on_false)`. #[macro_export] macro_rules! ensure { - ( $x:expr, $y:expr ) => {{ + ( $x:expr, $y:expr $(,)? ) => {{ if !$x { $crate::fail!($y); } @@ -144,7 +144,10 @@ macro_rules! ensure { #[macro_export] #[cfg(feature = "std")] macro_rules! assert_noop { - ( $x:expr , $y:expr ) => { + ( + $x:expr, + $y:expr $(,)? + ) => { let h = $crate::storage_root(); $crate::assert_err!($x, $y); assert_eq!(h, $crate::storage_root()); @@ -161,7 +164,7 @@ macro_rules! assert_noop { #[macro_export] #[cfg(feature = "std")] macro_rules! assert_err { - ( $x:expr , $y:expr ) => { + ( $x:expr , $y:expr $(,)? ) => { assert_eq!($x, Err($y)); } } @@ -173,10 +176,10 @@ macro_rules! assert_err { #[macro_export] #[cfg(feature = "std")] macro_rules! assert_ok { - ( $x:expr ) => { + ( $x:expr $(,)? ) => { assert_eq!($x, Ok(())); }; - ( $x:expr, $y:expr ) => { + ( $x:expr, $y:expr $(,)? ) => { assert_eq!($x, Ok($y)); } } @@ -222,75 +225,27 @@ macro_rules! __assert_eq_uvec { } } -/// Checks that `$x` is equal to `$y` with an error rate of `$error`. -/// -/// # Example -/// -/// ```rust -/// # fn main() { -/// srml_support::assert_eq_error_rate!(10, 10, 0); -/// srml_support::assert_eq_error_rate!(10, 11, 1); -/// srml_support::assert_eq_error_rate!(12, 10, 2); -/// # } -/// ``` -/// -/// ```rust,should_panic -/// # fn main() { -/// srml_support::assert_eq_error_rate!(12, 10, 1); -/// # } -/// ``` -#[macro_export] -#[cfg(feature = "std")] -macro_rules! assert_eq_error_rate { - ($x:expr, $y:expr, $error:expr) => { - assert!( - ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), - "{:?} != {:?} (with error rate {:?})", - $x, - $y, - $error, - ); - }; -} - /// The void type - it cannot exist. // Oh rust, you crack me up... -#[derive(Clone, Eq, PartialEq)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] pub enum Void {} #[cfg(feature = "std")] #[doc(hidden)] pub use serde::{Serialize, Deserialize}; -/// Programatically create derivations for tuples of up to 19 elements. You provide a second macro -/// which is called once per tuple size, along with a number of identifiers, one for each element -/// of the tuple. -#[macro_export] -macro_rules! for_each_tuple { - ($m:ident) => { - for_each_tuple! { @IMPL $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, } - }; - (@IMPL $m:ident !!) => { $m! { } }; - (@IMPL $m:ident !! $h:ident, $($t:ident,)*) => { - $m! { $h $($t)* } - for_each_tuple! { @IMPL $m !! $($t,)* } - } -} - #[cfg(test)] mod tests { use super::*; - use codec::Codec; - use runtime_io::{with_externalities, Blake2Hasher}; - pub use srml_metadata::{ + use codec::{Codec, EncodeLike}; + use srml_metadata::{ DecodeDifferent, StorageEntryMetadata, StorageMetadata, StorageEntryType, - StorageEntryModifier, DefaultByte, DefaultByteGetter, StorageHasher + StorageEntryModifier, DefaultByteGetter, StorageHasher, }; - pub use rstd::marker::PhantomData; + use rstd::marker::PhantomData; pub trait Trait { - type BlockNumber: Codec + Default; + type BlockNumber: Codec + EncodeLike + Default; type Origin; } @@ -307,10 +262,11 @@ mod tests { decl_storage! { trait Store for Module as Example { - pub Data get(data) build(|_| vec![(15u32, 42u64)]): linked_map hasher(twox_64_concat) u32 => u64; + pub Data get(fn data) build(|_| vec![(15u32, 42u64)]): linked_map hasher(twox_64_concat) u32 => u64; pub OptionLinkedMap: linked_map u32 => Option; - pub GenericData get(generic_data): linked_map hasher(twox_128) T::BlockNumber => T::BlockNumber; - pub GenericData2 get(generic_data2): linked_map T::BlockNumber => Option; + pub GenericData get(fn generic_data): linked_map hasher(twox_128) T::BlockNumber => T::BlockNumber; + pub GenericData2 get(fn generic_data2): linked_map T::BlockNumber => Option; + pub GetterNoFnKeyword get(no_fn): Option; pub DataDM config(test_config) build(|_| vec![(15u32, 16u32, 42u64)]): double_map hasher(twox_64_concat) u32, blake2_256(u32) => u64; @@ -326,7 +282,7 @@ mod tests { type Origin = u32; } - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { GenesisConfig::default().build_storage().unwrap().into() } @@ -334,7 +290,7 @@ mod tests { #[test] fn linked_map_issue_3318() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { OptionLinkedMap::insert(1, 1); assert_eq!(OptionLinkedMap::get(1), Some(1)); OptionLinkedMap::insert(1, 2); @@ -342,9 +298,38 @@ mod tests { }); } + #[test] + fn linked_map_swap_works() { + new_test_ext().execute_with(|| { + OptionLinkedMap::insert(0, 0); + OptionLinkedMap::insert(1, 1); + OptionLinkedMap::insert(2, 2); + OptionLinkedMap::insert(3, 3); + + let collect = || OptionLinkedMap::enumerate().collect::>(); + assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); + + // Two existing + OptionLinkedMap::swap(1, 2); + assert_eq!(collect(), vec![(3, 3), (2, 1), (1, 2), (0, 0)]); + + // Back to normal + OptionLinkedMap::swap(2, 1); + assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); + + // Left existing + OptionLinkedMap::swap(2, 5); + assert_eq!(collect(), vec![(5, 2), (3, 3), (1, 1), (0, 0)]); + + // Right existing + OptionLinkedMap::swap(5, 2); + assert_eq!(collect(), vec![(2, 2), (3, 3), (1, 1), (0, 0)]); + }); + } + #[test] fn linked_map_basic_insert_remove_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { // initialized during genesis assert_eq!(Map::get(&15u32), 42u64); @@ -370,7 +355,7 @@ mod tests { #[test] fn linked_map_enumeration_and_head_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { assert_eq!(Map::head(), Some(15)); assert_eq!(Map::enumerate().collect::>(), vec![(15, 42)]); // insert / remove @@ -422,7 +407,7 @@ mod tests { #[test] fn double_map_basic_insert_remove_remove_prefix_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { type DoubleMap = DataDM; // initialized during genesis assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64); @@ -462,7 +447,7 @@ mod tests { #[test] fn double_map_append_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { type DoubleMap = AppendableDM; let key1 = 17u32; @@ -534,6 +519,15 @@ mod tests { ), documentation: DecodeDifferent::Encode(&[]), }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetterNoFnKeyword"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetterNoFnKeyword(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, StorageEntryMetadata { name: DecodeDifferent::Encode("DataDM"), modifier: StorageEntryModifier::Default, diff --git a/srml/support/src/metadata.rs b/srml/support/src/metadata.rs index 4bc1f906dad55821f6e8326d31177d582849fc33..a223a14f9e4050e64fe559804769b073f211154c 100644 --- a/srml/support/src/metadata.rs +++ b/srml/support/src/metadata.rs @@ -17,7 +17,7 @@ pub use srml_metadata::{ DecodeDifferent, FnEncode, RuntimeMetadata, ModuleMetadata, RuntimeMetadataLastVersion, DefaultByteGetter, RuntimeMetadataPrefixed, StorageEntryMetadata, StorageMetadata, - StorageEntryType, StorageEntryModifier, DefaultByte, StorageHasher + StorageEntryType, StorageEntryModifier, DefaultByte, StorageHasher, ModuleErrorMetadata }; /// Implements the metadata support for the given runtime and all its modules. @@ -96,6 +96,11 @@ macro_rules! __runtime_modules_to_metadata { $crate::metadata::FnEncode( $mod::$module::<$runtime $(, $mod::$instance )?>::module_constants_metadata ) + ), + errors: $crate::metadata::DecodeDifferent::Encode( + $crate::metadata::FnEncode( + <$mod::$module::<$runtime $(, $mod::$instance )?> as $crate::metadata::ModuleErrorMetadata>::metadata + ) ) }; $( $rest )* @@ -227,6 +232,7 @@ mod tests { use srml_metadata::{ EventMetadata, StorageEntryModifier, StorageEntryType, FunctionMetadata, StorageEntryMetadata, ModuleMetadata, RuntimeMetadataPrefixed, DefaultByte, ModuleConstantMetadata, DefaultByteGetter, + ErrorMetadata, }; use codec::{Encode, Decode}; use crate::traits::Get; @@ -278,7 +284,7 @@ mod tests { } mod event_module { - use crate::dispatch::Result; + use crate::dispatch::DispatchResult; pub trait Trait { type Origin; @@ -296,7 +302,19 @@ mod tests { decl_module! { pub struct Module for enum Call where origin: T::Origin { - fn aux_0(_origin) -> Result { unreachable!() } + type Error = Error; + + fn aux_0(_origin) -> DispatchResult { unreachable!() } + } + } + + crate::decl_error! { + pub enum Error { + /// Some user input error + UserInputError, + /// Something bad happened + /// this could be due to many reasons + BadThingHappened, } } } @@ -324,7 +342,7 @@ mod tests { StorageMethod : Option; } add_extra_genesis { - build(|_, _| {}); + build(|_| {}); } } } @@ -447,6 +465,7 @@ mod tests { } ]) ), + errors: DecodeDifferent::Encode(FnEncode(|| &[])), }, ModuleMetadata { name: DecodeDifferent::Encode("Module"), @@ -469,6 +488,19 @@ mod tests { ]) )), constants: DecodeDifferent::Encode(FnEncode(|| &[])), + errors: DecodeDifferent::Encode(FnEncode(|| &[ + ErrorMetadata { + name: DecodeDifferent::Encode("UserInputError"), + documentation: DecodeDifferent::Encode(&[" Some user input error"]), + }, + ErrorMetadata { + name: DecodeDifferent::Encode("BadThingHappened"), + documentation: DecodeDifferent::Encode(&[ + " Something bad happened", + " this could be due to many reasons", + ]), + }, + ])), }, ModuleMetadata { name: DecodeDifferent::Encode("Module2"), @@ -505,6 +537,7 @@ mod tests { ]) )), constants: DecodeDifferent::Encode(FnEncode(|| &[])), + errors: DecodeDifferent::Encode(FnEncode(|| &[])), }, ]) }; diff --git a/srml/support/src/origin.rs b/srml/support/src/origin.rs index f3fec6e3ae6ce16909abd27487262923e8286ee2..6da9bc13858364f42aa9ab58ac750802b8588157 100644 --- a/srml/support/src/origin.rs +++ b/srml/support/src/origin.rs @@ -151,9 +151,7 @@ macro_rules! impl_outer_origin { $( $module:ident $( < $generic:ident > )? $( { $generic_instance:ident } )? ,)* ) => { $crate::paste::item! { - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)] $(#[$attr])* #[allow(non_camel_case_types)] pub enum $name { diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs index 9aae241dba18aac3426a4d22b7be4b224d965e09..52bf48baa574096c81835cf47b57972ddb76f4bb 100644 --- a/srml/support/src/runtime.rs +++ b/srml/support/src/runtime.rs @@ -191,8 +191,7 @@ macro_rules! construct_runtime { )* }; ) => { - #[derive(Clone, Copy, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive(Clone, Copy, PartialEq, Eq, $crate::RuntimeDebug)] pub struct $runtime; impl $crate::sr_primitives::traits::GetNodeBlockType for $runtime { type NodeBlock = $node_block; @@ -220,6 +219,7 @@ macro_rules! construct_runtime { $runtime; ; {}; + {}; $( $name: $module:: $( < $module_instance >:: )? { $( $modules ),* }, )* @@ -299,6 +299,7 @@ macro_rules! __create_decl_macro { )* ); }; + // Parse system module (@inner $runtime:ident; ; // there can not be multiple `System`s @@ -315,6 +316,7 @@ macro_rules! __create_decl_macro { $d( $rest )* ); }; + // Parse instantiable module with generic (@inner $runtime:ident; $d( $system:ident )?; @@ -334,6 +336,23 @@ macro_rules! __create_decl_macro { $d( $rest )* ); }; + // Parse instantiable module with no generic + (@inner + $runtime:ident; + $d( $system:ident )?; + { $d( $parsed:tt )* }; + $name:ident : $module:ident:: < $module_instance:ident >:: { + $macro_enum_name $d(, $ingore:ident $d( <$ignor:ident> )* )* + }, + $d( $rest:tt )* + ) => { + compile_error!(concat!( + "Instantiable module with not generic ", stringify!($macro_enum_name), + " cannot be constructed: module `", stringify!($name), "` must have generic ", + stringify!($macro_enum_name), "." + )); + }; + // Parse instantiable module with no generic (@inner $runtime:ident; $d( $system:ident )?; @@ -353,6 +372,7 @@ macro_rules! __create_decl_macro { $d( $rest )* ); }; + // Ignore keyword (@inner $runtime:ident; $d( $system:ident )?; @@ -370,6 +390,7 @@ macro_rules! __create_decl_macro { $d( $rest )* ); }; + // Ignore module (@inner $runtime:ident; $d( $system:ident )?; @@ -384,6 +405,7 @@ macro_rules! __create_decl_macro { $d( $rest )* ); }; + // Expand (@inner $runtime:ident; $system:ident; @@ -412,6 +434,7 @@ macro_rules! __decl_all_modules { $runtime:ident; ; { $( $parsed:tt )* }; + { $( $parsed_nested:tt )* }; System: $module:ident::{ Module $(, $modules:ident )* }, $( $rest:tt )* ) => { @@ -419,6 +442,26 @@ macro_rules! __decl_all_modules { $runtime; $module; { $( $parsed )* }; + { $( $parsed_nested )* }; + $( $rest )* + ); + }; + ( + $runtime:ident; + $( $system:ident )?; + { $( $parsed:tt )* }; + {}; + $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* }, + $( $rest:tt )* + ) => { + $crate::__decl_all_modules!( + $runtime; + $( $system )?; + { + $( $parsed )* + $module::$name $(<$module_instance>)?, + }; + { $name }; $( $rest )* ); }; @@ -426,6 +469,7 @@ macro_rules! __decl_all_modules { $runtime:ident; $( $system:ident )?; { $( $parsed:tt )* }; + { $( $parsed_nested:tt )* }; $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { Module $(, $modules:ident )* }, $( $rest:tt )* ) => { @@ -436,6 +480,7 @@ macro_rules! __decl_all_modules { $( $parsed )* $module::$name $(<$module_instance>)?, }; + { ( $( $parsed_nested )*, $name, ) }; $( $rest )* ); }; @@ -443,6 +488,7 @@ macro_rules! __decl_all_modules { $runtime:ident; $( $system:ident )?; { $( $parsed:tt )* }; + { $( $parsed_nested:tt )* }; $name:ident: $module:ident:: $( < $module_instance:ident >:: )? { $ignore:ident $(, $modules:ident )* }, $( $rest:tt )* ) => { @@ -450,6 +496,7 @@ macro_rules! __decl_all_modules { $runtime; $( $system )?; { $( $parsed )* }; + { $( $parsed_nested )* }; $name: $module::{ $( $modules ),* }, $( $rest )* ); @@ -465,6 +512,7 @@ macro_rules! __decl_all_modules { $runtime; $( $system )?; { $( $parsed )* }; + { $( $parsed_nested )* }; $( $rest )* ); }; @@ -472,12 +520,13 @@ macro_rules! __decl_all_modules { $runtime:ident; $system:ident; { $( $parsed_module:ident :: $parsed_name:ident $(<$instance:ident>)? ,)*}; + { $( $parsed_nested:tt )* }; ) => { pub type System = system::Module<$runtime>; $( pub type $parsed_name = $parsed_module::Module<$runtime $(, $parsed_module::$instance )?>; )* - type AllModules = ( $( $parsed_name, )* ); + type AllModules = ( $( $parsed_nested )* ); } } diff --git a/srml/support/src/storage/child.rs b/srml/support/src/storage/child.rs index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1d6ee7a6f1a61bf0de30a31a0e758cf82cbd931f 100644 --- a/srml/support/src/storage/child.rs +++ b/srml/support/src/storage/child.rs @@ -0,0 +1,107 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Operation on runtime child storages. +//! +//! This module is a currently only a variant of unhashed with additional `storage_key`. +//! Note that `storage_key` must be unique and strong (strong in the sense of being long enough to +//! avoid collision from a resistant hash function (which unique implies)). +// NOTE: could replace unhashed by having only one kind of storage (root being null storage key (storage_key can become Option<&[u8]>). + +use crate::rstd::prelude::*; +use codec::{Codec, Encode, Decode}; + +/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. +pub fn get(storage_key: &[u8], key: &[u8]) -> Option { + runtime_io::child_storage(storage_key, key).map(|v| { + Decode::decode(&mut &v[..]).expect("storage is not null, therefore must be a valid type") + }) +} + +/// Return the value of the item in storage under `key`, or the type's default if there is no +/// explicit entry. +pub fn get_or_default(storage_key: &[u8], key: &[u8]) -> T { + get(storage_key, key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. +pub fn get_or(storage_key: &[u8], key: &[u8], default_value: T) -> T { + get(storage_key, key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. +pub fn get_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { + get(storage_key, key).unwrap_or_else(default_value) +} + +/// Put `value` in storage under `key`. +pub fn put(storage_key: &[u8], key: &[u8], value: &T) { + value.using_encoded(|slice| runtime_io::set_child_storage(storage_key, key, slice)); +} + +/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. +pub fn take(storage_key: &[u8], key: &[u8]) -> Option { + let r = get(storage_key, key); + if r.is_some() { + kill(storage_key, key); + } + r +} + +/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, +/// the default for its type. +pub fn take_or_default(storage_key: &[u8], key: &[u8]) -> T { + take(storage_key, key).unwrap_or_else(Default::default) +} + +/// Return the value of the item in storage under `key`, or `default_value` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or(storage_key: &[u8],key: &[u8], default_value: T) -> T { + take(storage_key, key).unwrap_or(default_value) +} + +/// Return the value of the item in storage under `key`, or `default_value()` if there is no +/// explicit entry. Ensure there is no explicit entry on return. +pub fn take_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { + take(storage_key, key).unwrap_or_else(default_value) +} + +/// Check to see if `key` has an explicit entry in storage. +pub fn exists(storage_key: &[u8], key: &[u8]) -> bool { + runtime_io::read_child_storage(storage_key, key, &mut [0;0][..], 0).is_some() +} + +/// Remove all `storage_key` key/values +pub fn kill_storage(storage_key: &[u8]) { + runtime_io::kill_child_storage(storage_key) +} + +/// Ensure `key` has no explicit entry in storage. +pub fn kill(storage_key: &[u8], key: &[u8]) { + runtime_io::clear_child_storage(storage_key, key); +} + +/// Get a Vec of bytes from storage. +pub fn get_raw(storage_key: &[u8], key: &[u8]) -> Option> { + runtime_io::child_storage(storage_key, key) +} + +/// Put a raw byte slice into storage. +pub fn put_raw(storage_key: &[u8], key: &[u8], value: &[u8]) { + runtime_io::set_child_storage(storage_key, key, value) +} diff --git a/srml/support/src/storage/generator/double_map.rs b/srml/support/src/storage/generator/double_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..cac8dbd034e85089e0305df3b68b85c15ad619f1 --- /dev/null +++ b/srml/support/src/storage/generator/double_map.rs @@ -0,0 +1,207 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use rstd::prelude::*; +use rstd::borrow::Borrow; +use codec::{Ref, FullCodec, FullEncode, Encode, EncodeLike, EncodeAppend}; +use crate::{storage::{self, unhashed}, hash::StorageHasher}; + +/// Generator for `StorageDoubleMap` used by `decl_storage`. +/// +/// # Mapping of keys to a storage path +/// +/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. +/// The first part is a hash of a concatenation of the `key1_prefix` and `Key1`. And the second part +/// is a hash of a `Key2`. +/// +/// Thus value for (key1, key2) is stored at: +/// ```nocompile +/// Hasher1(key1_prefix ++ key1) ++ Hasher2(key2) +/// ``` +/// +/// # Warning +/// +/// If the key1s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as +/// `blake2_256` must be used for Hasher1. Otherwise, other values in storage can be compromised. +/// If the key2s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as +/// `blake2_256` must be used for Hasher2. Otherwise, other items in storage with the same first +/// key can be compromised. +pub trait StorageDoubleMap { + /// The type that get/take returns. + type Query; + + /// Hasher for the first key. + type Hasher1: StorageHasher; + + /// Hasher for the second key. + type Hasher2: StorageHasher; + + /// Get the prefix for first key. + fn key1_prefix() -> &'static [u8]; + + /// Convert an optional value retrieved from storage to the type queried. + fn from_optional_value_to_query(v: Option) -> Self::Query; + + /// Convert a query to an optional value into storage. + fn from_query_to_optional_value(v: Self::Query) -> Option; + + /// Generate the first part of the key used in top storage. + fn storage_double_map_final_key1(k1: KArg1) -> ::Output + where + KArg1: EncodeLike, + { + let mut final_key1 = Self::key1_prefix().to_vec(); + k1.encode_to(&mut final_key1); + Self::Hasher1::hash(&final_key1) + } + + /// Generate the full key used in top storage. + fn storage_double_map_final_key(k1: KArg1, k2: KArg2) -> Vec + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + let mut final_key = Self::storage_double_map_final_key1(k1).as_ref().to_vec(); + final_key.extend_from_slice(k2.using_encoded(Self::Hasher2::hash).as_ref()); + final_key + } +} + +impl storage::StorageDoubleMap for G +where + K1: FullEncode, + K2: FullEncode, + V: FullCodec, + G: StorageDoubleMap, +{ + type Query = G::Query; + + fn exists(k1: KArg1, k2: KArg2) -> bool + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + unhashed::exists(&Self::storage_double_map_final_key(k1, k2)) + } + + fn get(k1: KArg1, k2: KArg2) -> Self::Query + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + G::from_optional_value_to_query(unhashed::get(&Self::storage_double_map_final_key(k1, k2))) + } + + fn take(k1: KArg1, k2: KArg2) -> Self::Query + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + let final_key = Self::storage_double_map_final_key(k1, k2); + + let value = unhashed::take(&final_key); + G::from_optional_value_to_query(value) + } + + fn insert(k1: KArg1, k2: KArg2, val: VArg) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + VArg: EncodeLike, + { + unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val.borrow()) + } + + fn remove(k1: KArg1, k2: KArg2) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + unhashed::kill(&Self::storage_double_map_final_key(k1, k2)) + } + + fn remove_prefix(k1: KArg1) where KArg1: EncodeLike { + unhashed::kill_prefix(Self::storage_double_map_final_key1(k1).as_ref()) + } + + fn mutate(k1: KArg1, k2: KArg2, f: F) -> R + where + KArg1: EncodeLike, + KArg2: EncodeLike, + F: FnOnce(&mut Self::Query) -> R, + { + let final_key = Self::storage_double_map_final_key(k1, k2); + let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref())); + + let ret = f(&mut val); + match G::from_query_to_optional_value(val) { + Some(ref val) => unhashed::put(final_key.as_ref(), val), + None => unhashed::kill(final_key.as_ref()), + } + ret + } + + fn append( + k1: KArg1, + k2: KArg2, + items: Items, + ) -> Result<(), &'static str> + where + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator + { + let final_key = Self::storage_double_map_final_key(k1, k2); + + let encoded_value = unhashed::get_raw(&final_key) + .unwrap_or_else(|| { + match G::from_query_to_optional_value(G::from_optional_value_to_query(None)) { + Some(value) => value.encode(), + None => vec![], + } + }); + + let new_val = V::append_or_new( + encoded_value, + items, + ).map_err(|_| "Could not append given item")?; + unhashed::put_raw(&final_key, &new_val); + + Ok(()) + } + + fn append_or_insert( + k1: KArg1, + k2: KArg2, + items: Items, + ) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator + { + Self::append(Ref::from(&k1), Ref::from(&k2), items.clone()) + .unwrap_or_else(|_| Self::insert(k1, k2, items)); + } +} diff --git a/srml/support/src/storage/generator/linked_map.rs b/srml/support/src/storage/generator/linked_map.rs new file mode 100644 index 0000000000000000000000000000000000000000..6643a37f4f50cef2af2f7a784582975917fc8b29 --- /dev/null +++ b/srml/support/src/storage/generator/linked_map.rs @@ -0,0 +1,363 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use codec::{FullCodec, Encode, Decode, EncodeLike, Ref}; +use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len}; +use rstd::marker::PhantomData; + +/// Generator for `StorageLinkedMap` used by `decl_storage`. +/// +/// # Mapping of keys to a storage path +/// +/// The key for the head of the map is stored at one fixed path: +/// ```nocompile +/// Hasher(head_key) +/// ``` +/// +/// For each key, the value stored under that key is appended with a +/// [`Linkage`](struct.Linkage.html) (which hold previous and next key) at the path: +/// ```nocompile +/// Hasher(prefix ++ key) +/// ``` +/// +/// Enumeration is done by getting the head of the linked map and then iterating getting the +/// value and linkage stored at the key until the found linkage has no next key. +/// +/// # Warning +/// +/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as +/// `blake2_256` must be used. Otherwise, other values in storage can be compromised. +pub trait StorageLinkedMap { + /// The type that get/take returns. + type Query; + + /// Hasher used to insert into storage. + type Hasher: StorageHasher; + + /// Prefix used to prepend each key. + fn prefix() -> &'static [u8]; + + /// Key used to store linked map head. + fn head_key() -> &'static [u8]; + + /// Convert an optionnal value retrieved from storage to the type queried. + fn from_optional_value_to_query(v: Option) -> Self::Query; + + /// Convert a query to an optionnal value into storage. + fn from_query_to_optional_value(v: Self::Query) -> Option; + + /// Generate the full key used in top storage. + fn storage_linked_map_final_key(key: KeyArg) -> ::Output + where + KeyArg: EncodeLike, + { + let mut final_key = Self::prefix().to_vec(); + key.encode_to(&mut final_key); + Self::Hasher::hash(&final_key) + } + + /// Generate the hashed key for head + fn storage_linked_map_final_head_key() -> ::Output { + Self::Hasher::hash(Self::head_key()) + } +} + +/// Linkage data of an element (it's successor and predecessor) +#[derive(Encode, Decode)] +pub struct Linkage { + /// Previous element key in storage (None for the first element) + pub previous: Option, + /// Next element key in storage (None for the last element) + pub next: Option, +} + +impl Default for Linkage { + fn default() -> Self { + Self { + previous: None, + next: None, + } + } +} + +// Encode like a linkage. +#[derive(Encode)] +struct EncodeLikeLinkage, NKey: EncodeLike, Key: Encode> { + // Previous element key in storage (None for the first element) + previous: Option, + // Next element key in storage (None for the last element) + next: Option, + // The key of the linkage this type encode to + phantom: core::marker::PhantomData, +} + +/// A key-value pair iterator for enumerable map. +pub struct Enumerator> { + next: Option, + _phantom: PhantomData<(G, V)>, +} + +impl Iterator for Enumerator +where + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + type Item = (K, V); + + fn next(&mut self) -> Option { + let next = self.next.take()?; + let (val, linkage): (V, Linkage) = { + let next_full_key = G::storage_linked_map_final_key(&next); + unhashed::get(next_full_key.as_ref()) + .expect("previous/next only contain existing entires; + we enumerate using next; entry exists; qed") + }; + + self.next = linkage.next; + Some((next, val)) + } +} + +/// Update linkage when this element is removed. +/// +/// Takes care of updating previous and next elements points +/// as well as updates head if the element is first or last. +fn remove_linkage(linkage: Linkage) +where + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + let next_key = linkage.next.as_ref() + .map(G::storage_linked_map_final_key) + .map(|x| x.as_ref().to_vec()); + let prev_key = linkage.previous.as_ref() + .map(G::storage_linked_map_final_key) + .map(|x| x.as_ref().to_vec()); + + if let Some(prev_key) = prev_key { + // Retrieve previous element and update `next` + let mut res = read_with_linkage::<_, _, G>(prev_key.as_ref()) + .expect("Linkage is updated in case entry is removed; + it always points to existing keys; qed"); + res.1.next = linkage.next; + unhashed::put(prev_key.as_ref(), &res); + } else { + // we were first so let's update the head + write_head::<_, _, _, G>(linkage.next.as_ref()); + } + if let Some(next_key) = next_key { + // Update previous of next element + let mut res = read_with_linkage::<_, _, G>(next_key.as_ref()) + .expect("Linkage is updated in case entry is removed; + it always points to existing keys; qed"); + res.1.previous = linkage.previous; + unhashed::put(next_key.as_ref(), &res); + } +} + +/// Read the contained data and it's linkage. +fn read_with_linkage(key: &[u8]) -> Option<(V, Linkage)> +where + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + unhashed::get(key) +} + +/// Generate linkage for newly inserted element. +/// +/// Takes care of updating head and previous head's pointer. +fn new_head_linkage(key: KeyArg) -> Linkage +where + KeyArg: EncodeLike, + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + if let Some(head) = read_head::<_, _, G>() { + // update previous head predecessor + { + let head_key = G::storage_linked_map_final_key(&head); + let (data, linkage) = read_with_linkage::<_, _, G>(head_key.as_ref()) + .expect("head is set when first element is inserted + and unset when last element is removed; + if head is Some then it points to existing key; qed"); + let new_linkage = EncodeLikeLinkage::<_, _, K> { + previous: Some(Ref::from(&key)), + next: linkage.next.as_ref(), + phantom: Default::default(), + }; + unhashed::put(head_key.as_ref(), &(data, new_linkage)); + } + // update to current head + write_head::<_, _, _, G>(Some(key)); + // return linkage with pointer to previous head + let mut linkage = Linkage::default(); + linkage.next = Some(head); + linkage + } else { + // we are first - update the head and produce empty linkage + write_head::<_, _, _, G>(Some(key)); + Linkage::default() + } +} + +/// Read current head pointer. +fn read_head() -> Option +where + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + unhashed::get(G::storage_linked_map_final_head_key().as_ref()) +} + +/// Overwrite current head pointer. +/// +/// If `None` is given head is removed from storage. +fn write_head(head: Option) +where + KeyArg: EncodeLike, + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + match head.as_ref() { + Some(head) => unhashed::put(G::storage_linked_map_final_head_key().as_ref(), head), + None => unhashed::kill(G::storage_linked_map_final_head_key().as_ref()), + } +} + +impl storage::StorageLinkedMap for G +where + K: FullCodec, + V: FullCodec, + G: StorageLinkedMap, +{ + type Query = G::Query; + + type Enumerator = Enumerator; + + fn exists>(key: KeyArg) -> bool { + unhashed::exists(Self::storage_linked_map_final_key(key).as_ref()) + } + + fn get>(key: KeyArg) -> Self::Query { + let val = unhashed::get(Self::storage_linked_map_final_key(key).as_ref()); + G::from_optional_value_to_query(val) + } + + fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2) { + let final_key1 = Self::storage_linked_map_final_key(Ref::from(&key1)); + let final_key2 = Self::storage_linked_map_final_key(Ref::from(&key2)); + let full_value_1 = read_with_linkage::<_, _, G>(final_key1.as_ref()); + let full_value_2 = read_with_linkage::<_, _, G>(final_key2.as_ref()); + + match (full_value_1, full_value_2) { + // Just keep linkage in order and only swap values. + (Some((value1, linkage1)), Some((value2, linkage2))) => { + unhashed::put(final_key1.as_ref(), &(value2, linkage1)); + unhashed::put(final_key2.as_ref(), &(value1, linkage2)); + } + // Remove key and insert the new one. + (Some((value, _linkage)), None) => { + Self::remove(key1); + let linkage = new_head_linkage::<_, _, _, G>(key2); + unhashed::put(final_key2.as_ref(), &(value, linkage)); + } + // Remove key and insert the new one. + (None, Some((value, _linkage))) => { + Self::remove(key2); + let linkage = new_head_linkage::<_, _, _, G>(key1); + unhashed::put(final_key1.as_ref(), &(value, linkage)); + } + // No-op. + (None, None) => (), + } + } + + fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg) { + let final_key = Self::storage_linked_map_final_key(Ref::from(&key)); + let linkage = match read_with_linkage::<_, _, G>(final_key.as_ref()) { + // overwrite but reuse existing linkage + Some((_data, linkage)) => linkage, + // create new linkage + None => new_head_linkage::<_, _, _, G>(key), + }; + unhashed::put(final_key.as_ref(), &(val, linkage)) + } + + fn remove>(key: KeyArg) { + G::take(key); + } + + fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R { + let final_key = Self::storage_linked_map_final_key(Ref::from(&key)); + + let (mut val, _linkage) = read_with_linkage::<_, _, G>(final_key.as_ref()) + .map(|(data, linkage)| (G::from_optional_value_to_query(Some(data)), Some(linkage))) + .unwrap_or_else(|| (G::from_optional_value_to_query(None), None)); + + let ret = f(&mut val); + match G::from_query_to_optional_value(val) { + Some(ref val) => G::insert(key, val), + None => G::remove(key), + } + ret + } + + fn take>(key: KeyArg) -> Self::Query { + let final_key = Self::storage_linked_map_final_key(key); + + let full_value: Option<(V, Linkage)> = unhashed::take(final_key.as_ref()); + + let value = full_value.map(|(data, linkage)| { + remove_linkage::<_, _, G>(linkage); + data + }); + + G::from_optional_value_to_query(value) + } + + fn enumerate() -> Self::Enumerator { + Enumerator::<_, _, G> { + next: read_head::<_, _, G>(), + _phantom: Default::default(), + } + } + + fn head() -> Option { + read_head::<_, _, G>() + } + + fn decode_len>(key: KeyArg) -> Result + where V: codec::DecodeLength + Len + { + let key = Self::storage_linked_map_final_key(key); + if let Some(v) = unhashed::get_raw(key.as_ref()) { + ::len(&v).map_err(|e| e.what()) + } else { + let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) + .map(|v| v.len()) + .unwrap_or(0); + + Ok(len) + } + } +} diff --git a/srml/support/src/storage/generator/map.rs b/srml/support/src/storage/generator/map.rs new file mode 100644 index 0000000000000000000000000000000000000000..3c3edac28a42a37f779c93c8eded02dc968672e0 --- /dev/null +++ b/srml/support/src/storage/generator/map.rs @@ -0,0 +1,172 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[cfg(not(feature = "std"))] +use rstd::prelude::*; +use rstd::borrow::Borrow; +use codec::{FullCodec, FullEncode, Encode, EncodeLike, Ref, EncodeAppend}; +use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len}; + +/// Generator for `StorageMap` used by `decl_storage`. +/// +/// For each key value is stored at: +/// ```nocompile +/// Hasher(prefix ++ key) +/// ``` +/// +/// # Warning +/// +/// If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as +/// `blake2_256` must be used. Otherwise, other values in storage can be compromised. +pub trait StorageMap { + /// The type that get/take returns. + type Query; + + /// Hasher used to insert into storage. + type Hasher: StorageHasher; + + /// Prefix used to prepend each key. + fn prefix() -> &'static [u8]; + + /// Convert an optional value retrieved from storage to the type queried. + fn from_optional_value_to_query(v: Option) -> Self::Query; + + /// Convert a query to an optional value into storage. + fn from_query_to_optional_value(v: Self::Query) -> Option; + + /// Generate the full key used in top storage. + fn storage_map_final_key(key: KeyArg) -> ::Output + where + KeyArg: EncodeLike, + { + let mut final_key = Self::prefix().to_vec(); + key.borrow().encode_to(&mut final_key); + Self::Hasher::hash(&final_key) + } +} + +impl> storage::StorageMap for G { + type Query = G::Query; + + fn hashed_key_for>(key: KeyArg) -> Vec { + Self::storage_map_final_key(key).as_ref().to_vec() + } + + fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2) { + let k1 = Self::storage_map_final_key(key1); + let k2 = Self::storage_map_final_key(key2); + + let v1 = unhashed::get_raw(k1.as_ref()); + if let Some(val) = unhashed::get_raw(k2.as_ref()) { + unhashed::put_raw(k1.as_ref(), &val); + } else { + unhashed::kill(k1.as_ref()) + } + if let Some(val) = v1 { + unhashed::put_raw(k2.as_ref(), &val); + } else { + unhashed::kill(k2.as_ref()) + } + } + + fn exists>(key: KeyArg) -> bool { + unhashed::exists(Self::storage_map_final_key(key).as_ref()) + } + + fn get>(key: KeyArg) -> Self::Query { + G::from_optional_value_to_query(unhashed::get(Self::storage_map_final_key(key).as_ref())) + } + + fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg) { + unhashed::put(Self::storage_map_final_key(key).as_ref(), &val.borrow()) + } + + fn remove>(key: KeyArg) { + unhashed::kill(Self::storage_map_final_key(key).as_ref()) + } + + fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R { + let final_key = Self::storage_map_final_key(key); + let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref())); + + let ret = f(&mut val); + match G::from_query_to_optional_value(val) { + Some(ref val) => unhashed::put(final_key.as_ref(), &val.borrow()), + None => unhashed::kill(final_key.as_ref()), + } + ret + } + + fn take>(key: KeyArg) -> Self::Query { + let key = Self::storage_map_final_key(key); + let value = unhashed::take(key.as_ref()); + G::from_optional_value_to_query(value) + } + + fn append(key: KeyArg, items: Items) -> Result<(), &'static str> + where + KeyArg: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator, + { + let key = Self::storage_map_final_key(key); + let encoded_value = unhashed::get_raw(key.as_ref()) + .unwrap_or_else(|| { + match G::from_query_to_optional_value(G::from_optional_value_to_query(None)) { + Some(value) => value.encode(), + None => vec![], + } + }); + + let new_val = V::append_or_new( + encoded_value, + items, + ).map_err(|_| "Could not append given item")?; + unhashed::put_raw(key.as_ref(), &new_val); + Ok(()) + } + + fn append_or_insert(key: KeyArg, items: Items) + where + KeyArg: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator, + { + Self::append(Ref::from(&key), items.clone()) + .unwrap_or_else(|_| Self::insert(key, items)); + } + + fn decode_len>(key: KeyArg) -> Result + where V: codec::DecodeLength + Len + { + let key = Self::storage_map_final_key(key); + if let Some(v) = unhashed::get_raw(key.as_ref()) { + ::len(&v).map_err(|e| e.what()) + } else { + let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) + .map(|v| v.len()) + .unwrap_or(0); + + Ok(len) + } + } +} diff --git a/srml/support/src/storage/generator/mod.rs b/srml/support/src/storage/generator/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..1bda791023792f2e2dc73b4f65a737f3dcd155e9 --- /dev/null +++ b/srml/support/src/storage/generator/mod.rs @@ -0,0 +1,81 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Generators are a set of trait on which storage traits are implemented. +//! +//! (i.e. implementing the generator for StorageValue on a type will automatically derive the +//! implementation of StorageValue for this type). +//! +//! They are used by `decl_storage`. + +mod linked_map; +mod map; +mod double_map; +mod value; + +pub use linked_map::{StorageLinkedMap, Enumerator, Linkage}; +pub use map::StorageMap; +pub use double_map::StorageDoubleMap; +pub use value::StorageValue; + + +#[cfg(test)] +#[allow(dead_code)] +mod tests { + use runtime_io::TestExternalities; + use codec::Encode; + use crate::storage::{unhashed, generator::StorageValue}; + + struct Runtime {} + pub trait Trait { + type Origin; + type BlockNumber; + } + + impl Trait for Runtime { + type Origin = u32; + type BlockNumber = u32; + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + crate::decl_storage! { + trait Store for Module as Runtime { + Value get(fn value) config(): (u64, u64); + } + } + + #[test] + fn value_translate_works() { + let t = GenesisConfig::default().build_storage().unwrap(); + TestExternalities::new(t).execute_with(|| { + // put the old value `1111u32` in the storage. + let key = Value::storage_value_final_key(); + unhashed::put_raw(&key, &1111u32.encode()); + + // translate + let translate_fn = |old: Option| -> Option<(u64, u64)> { + old.map(|o| (o.into(), (o*2).into())) + }; + let _ = Value::translate(translate_fn); + + // new storage should be `(1111, 1111 * 2)` + assert_eq!(Value::get(), (1111, 2222)); + }) + } +} diff --git a/srml/support/src/storage/generator/value.rs b/srml/support/src/storage/generator/value.rs new file mode 100644 index 0000000000000000000000000000000000000000..5ebc25a70af2a6eba052c5870ad61a5443fdb28d --- /dev/null +++ b/srml/support/src/storage/generator/value.rs @@ -0,0 +1,171 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[cfg(not(feature = "std"))] +use rstd::prelude::*; +use codec::{FullCodec, Encode, EncodeAppend, EncodeLike, Decode}; +use crate::{storage::{self, unhashed}, hash::{Twox128, StorageHasher}, traits::Len}; + +/// Generator for `StorageValue` used by `decl_storage`. +/// +/// Value is stored at: +/// ```nocompile +/// Twox128(unhashed_key) +/// ``` +pub trait StorageValue { + /// The type that get/take returns. + type Query; + + /// Unhashed key used in storage + fn unhashed_key() -> &'static [u8]; + + /// Convert an optional value retrieved from storage to the type queried. + fn from_optional_value_to_query(v: Option) -> Self::Query; + + /// Convert a query to an optional value into storage. + fn from_query_to_optional_value(v: Self::Query) -> Option; + + /// Generate the full key used in top storage. + fn storage_value_final_key() -> [u8; 16] { + Twox128::hash(Self::unhashed_key()) + } +} + +impl> storage::StorageValue for G { + type Query = G::Query; + + fn hashed_key() -> [u8; 16] { + Self::storage_value_final_key() + } + + fn exists() -> bool { + unhashed::exists(&Self::storage_value_final_key()) + } + + fn get() -> Self::Query { + let value = unhashed::get(&Self::storage_value_final_key()); + G::from_optional_value_to_query(value) + } + + fn translate) -> Option>(f: F) -> Result, ()> { + let key = Self::storage_value_final_key(); + + // attempt to get the length directly. + let maybe_old = match unhashed::get_raw(&key) { + Some(old_data) => Some(O::decode(&mut &old_data[..]).map_err(|_| ())?), + None => None, + }; + let maybe_new = f(maybe_old); + if let Some(new) = maybe_new.as_ref() { + new.using_encoded(|d| unhashed::put_raw(&key, d)); + } else { + unhashed::kill(&key); + } + Ok(maybe_new) + } + + fn put>(val: Arg) { + unhashed::put(&Self::storage_value_final_key(), &val) + } + + fn kill() { + unhashed::kill(&Self::storage_value_final_key()) + } + + fn mutate R>(f: F) -> R { + let mut val = G::get(); + + let ret = f(&mut val); + match G::from_query_to_optional_value(val) { + Some(ref val) => G::put(val), + None => G::kill(), + } + ret + } + + fn take() -> G::Query { + let key = Self::storage_value_final_key(); + let value = unhashed::get(&key); + if value.is_some() { + unhashed::kill(&key) + } + G::from_optional_value_to_query(value) + } + + /// Append the given items to the value in the storage. + /// + /// `T` is required to implement `codec::EncodeAppend`. + fn append(items: Items) -> Result<(), &'static str> + where + Item: Encode, + EncodeLikeItem: EncodeLike, + T: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator, + { + let key = Self::storage_value_final_key(); + let encoded_value = unhashed::get_raw(&key) + .unwrap_or_else(|| { + match G::from_query_to_optional_value(G::from_optional_value_to_query(None)) { + Some(value) => value.encode(), + None => vec![], + } + }); + + let new_val = T::append_or_new( + encoded_value, + items, + ).map_err(|_| "Could not append given item")?; + unhashed::put_raw(&key, &new_val); + Ok(()) + } + + /// Safely append the given items to the value in the storage. If a codec error occurs, then the + /// old (presumably corrupt) value is replaced with the given `items`. + /// + /// `T` is required to implement `codec::EncodeAppend`. + fn append_or_put(items: Items) where + Item: Encode, + EncodeLikeItem: EncodeLike, + T: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator + { + Self::append(items.clone()).unwrap_or_else(|_| Self::put(items)); + } + + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + /// + /// Note that `0` is returned as the default value if no encoded value exists at the given key. + /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` + /// function for this purpose. + fn decode_len() -> Result where T: codec::DecodeLength, T: Len { + let key = Self::storage_value_final_key(); + + // attempt to get the length directly. + if let Some(k) = unhashed::get_raw(&key) { + ::len(&k).map_err(|e| e.what()) + } else { + let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) + .map(|v| v.len()) + .unwrap_or(0); + + Ok(len) + } + } +} diff --git a/srml/support/src/storage/hashed/mod.rs b/srml/support/src/storage/hashed.rs similarity index 57% rename from srml/support/src/storage/hashed/mod.rs rename to srml/support/src/storage/hashed.rs index 5ca718df8c012e1bc5942b97ee1a6ec988a397d4..2eca8f5bcafbc8390537b4187a3b249f0049c3b1 100644 --- a/srml/support/src/storage/hashed/mod.rs +++ b/srml/support/src/storage/hashed.rs @@ -16,12 +16,9 @@ //! Operation on runtime storage using hashed keys. -pub mod generator; use super::unhashed; -use crate::rstd::prelude::*; -use crate::rstd::borrow::Borrow; -use runtime_io::{self, twox_128}; -use crate::codec::{Codec, Encode, Decode, KeyedVec}; +use rstd::prelude::*; +use codec::{Encode, Decode}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(hash: &HashFn, key: &[u8]) -> Option @@ -156,131 +153,3 @@ where { unhashed::put_raw(&hash(key).as_ref(), value) } - -/// A trait to conveniently store a vector of storable data. -/// -/// It uses twox_128 hasher. Final keys in trie are `twox_128(concatenation(PREFIX,count))` -pub trait StorageVec { - type Item: Default + Sized + Codec; - const PREFIX: &'static [u8]; - - /// Get the current set of items. - fn items() -> Vec { - (0..Self::count()).into_iter().map(Self::item).collect() - } - - /// Set the current set of items. - fn set_items(items: I) - where - I: IntoIterator, - T: Borrow, - { - let mut count: u32 = 0; - - for i in items.into_iter() { - put(&twox_128, &count.to_keyed_vec(Self::PREFIX), i.borrow()); - count = count.checked_add(1).expect("exceeded runtime storage capacity"); - } - - Self::set_count(count); - } - - /// Push an item. - fn push(item: &Self::Item) { - let len = Self::count(); - put(&twox_128, &len.to_keyed_vec(Self::PREFIX), item); - Self::set_count(len + 1); - } - - fn set_item(index: u32, item: &Self::Item) { - if index < Self::count() { - put(&twox_128, &index.to_keyed_vec(Self::PREFIX), item); - } - } - - fn clear_item(index: u32) { - if index < Self::count() { - kill(&twox_128, &index.to_keyed_vec(Self::PREFIX)); - } - } - - fn item(index: u32) -> Self::Item { - get_or_default(&twox_128, &index.to_keyed_vec(Self::PREFIX)) - } - - fn set_count(count: u32) { - (count..Self::count()).for_each(Self::clear_item); - put(&twox_128, &b"len".to_keyed_vec(Self::PREFIX), &count); - } - - fn count() -> u32 { - get_or_default(&twox_128, &b"len".to_keyed_vec(Self::PREFIX)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use runtime_io::{twox_128, TestExternalities, with_externalities}; - - #[test] - fn integers_can_be_stored() { - let mut t = TestExternalities::default(); - with_externalities(&mut t, || { - let x = 69u32; - put(&twox_128, b":test", &x); - let y: u32 = get(&twox_128, b":test").unwrap(); - assert_eq!(x, y); - }); - with_externalities(&mut t, || { - let x = 69426942i64; - put(&twox_128, b":test", &x); - let y: i64 = get(&twox_128, b":test").unwrap(); - assert_eq!(x, y); - }); - } - - #[test] - fn bools_can_be_stored() { - let mut t = TestExternalities::default(); - with_externalities(&mut t, || { - let x = true; - put(&twox_128, b":test", &x); - let y: bool = get(&twox_128, b":test").unwrap(); - assert_eq!(x, y); - }); - - with_externalities(&mut t, || { - let x = false; - put(&twox_128, b":test", &x); - let y: bool = get(&twox_128, b":test").unwrap(); - assert_eq!(x, y); - }); - } - - #[test] - fn vecs_can_be_retrieved() { - let mut t = TestExternalities::default(); - with_externalities(&mut t, || { - runtime_io::set_storage(&twox_128(b":test"), b"\x2cHello world"); - let x = b"Hello world".to_vec(); - let y = get::, _, _>(&twox_128, b":test").unwrap(); - assert_eq!(x, y); - }); - } - - #[test] - fn vecs_can_be_stored() { - let mut t = TestExternalities::default(); - let x = b"Hello world".to_vec(); - - with_externalities(&mut t, || { - put(&twox_128, b":test", &x); - }); - - with_externalities(&mut t, || { - let y: Vec = get(&twox_128, b":test").unwrap(); - assert_eq!(x, y); - }); - } -} diff --git a/srml/support/src/storage/hashed/generator.rs b/srml/support/src/storage/hashed/generator.rs deleted file mode 100644 index f8b8fb5483e1e163744afd51a8172004602b89f9..0000000000000000000000000000000000000000 --- a/srml/support/src/storage/hashed/generator.rs +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Abstract storage to use on HashedStorage trait - -use crate::codec::{self, Encode}; -use crate::rstd::prelude::{Vec, Box}; -#[cfg(feature = "std")] -use crate::storage::unhashed::generator::UnhashedStorage; -use runtime_io::{twox_64, twox_128, blake2_128, twox_256, blake2_256}; - -pub trait StorageHasher: 'static { - type Output: AsRef<[u8]>; - fn hash(x: &[u8]) -> Self::Output; -} - -/// Hash storage keys with `concat(twox64(key), key)` -pub struct Twox64Concat; -impl StorageHasher for Twox64Concat { - type Output = Vec; - fn hash(x: &[u8]) -> Vec { - twox_64(x) - .into_iter() - .chain(x.into_iter()) - .cloned() - .collect::>() - } -} - -#[test] -fn test_twox_64_concat() { - let r = Twox64Concat::hash(b"foo"); - assert_eq!(r.split_at(8), (&twox_128(b"foo")[..8], &b"foo"[..])) -} - -/// Hash storage keys with blake2 128 -pub struct Blake2_128; -impl StorageHasher for Blake2_128 { - type Output = [u8; 16]; - fn hash(x: &[u8]) -> [u8; 16] { - blake2_128(x) - } -} - -/// Hash storage keys with blake2 256 -pub struct Blake2_256; -impl StorageHasher for Blake2_256 { - type Output = [u8; 32]; - fn hash(x: &[u8]) -> [u8; 32] { - blake2_256(x) - } -} - -/// Hash storage keys with twox 128 -pub struct Twox128; -impl StorageHasher for Twox128 { - type Output = [u8; 16]; - fn hash(x: &[u8]) -> [u8; 16] { - twox_128(x) - } -} - -/// Hash storage keys with twox 256 -pub struct Twox256; -impl StorageHasher for Twox256 { - type Output = [u8; 32]; - fn hash(x: &[u8]) -> [u8; 32] { - twox_256(x) - } -} - -/// Abstraction around storage. -pub trait HashedStorage { - /// true if the key exists in storage. - fn exists(&self, key: &[u8]) -> bool; - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option; - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. Will panic if - /// it's not there. - fn require(&self, key: &[u8]) -> T { - self.get(key).expect("Required values must be in storage") - } - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. The type's - /// default is returned if it's not there. - fn get_or_default(&self, key: &[u8]) -> T { - self.get(key).unwrap_or_default() - } - - /// Put a value in under a key. - fn put(&mut self, key: &[u8], val: &T); - - /// Remove the bytes of a key from storage. - fn kill(&mut self, key: &[u8]); - - /// Take a value from storage, deleting it after reading. - fn take(&mut self, key: &[u8]) -> Option { - let value = self.get(key); - self.kill(key); - value - } - - /// Take a value from storage, deleting it after reading. - fn take_or_panic(&mut self, key: &[u8]) -> T { - self.take(key).expect("Required values must be in storage") - } - - /// Take a value from storage, deleting it after reading. - fn take_or_default(&mut self, key: &[u8]) -> T { - self.take(key).unwrap_or_default() - } - - /// Get a Vec of bytes from storage. - fn get_raw(&self, key: &[u8]) -> Option>; - - /// Put a raw byte slice into storage. - fn put_raw(&mut self, key: &[u8], value: &[u8]); -} - -// We use a construct like this during when genesis storage is being built. -#[cfg(feature = "std")] -impl HashedStorage for sr_primitives::StorageOverlay { - fn exists(&self, key: &[u8]) -> bool { - UnhashedStorage::exists(self, &H::hash(key).as_ref()) - } - - fn get(&self, key: &[u8]) -> Option { - UnhashedStorage::get(self, &H::hash(key).as_ref()) - } - - fn put(&mut self, key: &[u8], val: &T) { - UnhashedStorage::put(self, &H::hash(key).as_ref(), val) - } - - fn kill(&mut self, key: &[u8]) { - UnhashedStorage::kill(self, &H::hash(key).as_ref()) - } - - fn get_raw(&self, key: &[u8]) -> Option> { - UnhashedStorage::get_raw(self, &H::hash(key).as_ref()) - } - - fn put_raw(&mut self, key: &[u8], value: &[u8]) { - UnhashedStorage::put_raw(self, &H::hash(key).as_ref(), value) - } -} - -/// A strongly-typed value kept in storage. -pub trait StorageValue { - /// The type that get/take returns. - type Query; - - /// Get the storage key. - fn key() -> &'static [u8]; - - /// true if the value is defined in storage. - fn exists>(storage: &S) -> bool { - storage.exists(Self::key()) - } - - /// Load the value from the provided storage instance. - fn get>(storage: &S) -> Self::Query; - - /// Take a value from storage, removing it afterwards. - fn take>(storage: &mut S) -> Self::Query; - - /// Store a value under this key into the provided storage instance. - fn put>(val: &T, storage: &mut S) { - storage.put(Self::key(), val) - } - - /// Store a value under this key into the provided storage instance; this can take any reference - /// type that derefs to `T` (and has `Encode` implemented). - /// Store a value under this key into the provided storage instance. - fn put_ref>(val: &Arg, storage: &mut S) where T: AsRef { - val.using_encoded(|b| storage.put_raw(Self::key(), b)) - } - - /// Mutate this value - fn mutate R, S: HashedStorage>(f: F, storage: &mut S) -> R; - - /// Clear the storage value. - fn kill>(storage: &mut S) { - storage.kill(Self::key()) - } - - /// Append the given items to the value in the storage. - /// - /// `T` is required to implement `codec::EncodeAppend`. - fn append, I: codec::Encode>( - items: &[I], storage: &mut S - ) -> Result<(), &'static str> where T: codec::EncodeAppend { - let new_val = ::append( - storage.get_raw(Self::key()).unwrap_or_default(), - items, - ).map_err(|_| "Could not append given item")?; - storage.put_raw(Self::key(), &new_val); - Ok(()) - } -} - -/// A strongly-typed map in storage. -pub trait StorageMap { - /// The type that get/take returns. - type Query; - - type Hasher: StorageHasher; - - /// Get the prefix key in storage. - fn prefix() -> &'static [u8]; - - /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for(x: &K) -> Vec; - - /// true if the value is defined in storage. - fn exists>(key: &K, storage: &S) -> bool { - storage.exists(&Self::key_for(key)[..]) - } - - /// Load the value associated with the given key from the map. - fn get>(key: &K, storage: &S) -> Self::Query; - - /// Take the value under a key. - fn take>(key: &K, storage: &mut S) -> Self::Query; - - /// Swap the values of two keys. - fn swap>(key1: &K, key2: &K, storage: &mut S) { - let k1 = Self::key_for(key1); - let k2 = Self::key_for(key2); - let v1 = storage.get_raw(&k1[..]); - if let Some(val) = storage.get_raw(&k2[..]) { - storage.put_raw(&k1[..], &val[..]); - } else { - storage.kill(&k1[..]) - } - if let Some(val) = v1 { - storage.put_raw(&k2[..], &val[..]); - } else { - storage.kill(&k2[..]) - } - } - - /// Store a value to be associated with the given key from the map. - fn insert>(key: &K, val: &V, storage: &mut S) { - storage.put(&Self::key_for(key)[..], val); - } - - /// Store a value under this key into the provided storage instance; this can take any reference - /// type that derefs to `T` (and has `Encode` implemented). - /// Store a value under this key into the provided storage instance. - fn insert_ref>( - key: &K, - val: &Arg, - storage: &mut S - ) where V: AsRef { - val.using_encoded(|b| storage.put_raw(&Self::key_for(key)[..], b)) - } - - /// Remove the value under a key. - fn remove>(key: &K, storage: &mut S) { - storage.kill(&Self::key_for(key)[..]); - } - - /// Mutate the value under a key. - fn mutate R, S: HashedStorage>(key: &K, f: F, storage: &mut S) -> R; -} - -/// A `StorageMap` with enumerable entries. -pub trait EnumerableStorageMap: StorageMap { - /// Return current head element. - fn head>(storage: &S) -> Option; - - /// Enumerate all elements in the map. - fn enumerate<'a, S: HashedStorage>( - storage: &'a S - ) -> Box + 'a> where K: 'a, V: 'a; -} - -/// A `StorageMap` with appendable entries. -pub trait AppendableStorageMap: StorageMap { - /// Append the given items to the value in the storage. - /// - /// `T` is required to implement `codec::EncodeAppend`. - fn append, I: codec::Encode>( - key : &K, items: &[I], storage: &mut S - ) -> Result<(), &'static str> where V: codec::EncodeAppend { - let k = Self::key_for(key); - let new_val = ::append( - storage.get_raw(&k[..]).unwrap_or_default(), - items, - ).map_err(|_| "Could not append given item")?; - storage.put_raw(&k[..], &new_val); - Ok(()) - } -} diff --git a/srml/support/src/storage/mod.rs b/srml/support/src/storage/mod.rs index 385fad42eb260bc8be30de7052b28533e6bf4c6b..f10deb93d241a32ec72431d3e4c334cb8c482f02 100644 --- a/srml/support/src/storage/mod.rs +++ b/srml/support/src/storage/mod.rs @@ -16,100 +16,25 @@ //! Stuff to do with the runtime's storage. -use crate::rstd::prelude::*; -use crate::rstd::borrow::Borrow; -use codec::{Codec, Encode, Decode, KeyedVec, EncodeAppend}; -use hashed::generator::{HashedStorage, StorageHasher}; -use unhashed::generator::UnhashedStorage; - -#[macro_use] -pub mod storage_items; +use rstd::prelude::*; +use codec::{FullCodec, FullEncode, Encode, EncodeAppend, EncodeLike, Decode}; +use crate::traits::Len; + pub mod unhashed; pub mod hashed; - -/// The underlying runtime storage. -pub struct RuntimeStorage; - -impl HashedStorage for RuntimeStorage { - fn exists(&self, key: &[u8]) -> bool { - hashed::exists(&H::hash, key) - } - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option { - hashed::get(&H::hash, key) - } - - /// Put a value in under a key. - fn put(&mut self, key: &[u8], val: &T) { - hashed::put(&H::hash, key, val) - } - - /// Remove the bytes of a key from storage. - fn kill(&mut self, key: &[u8]) { - hashed::kill(&H::hash, key) - } - - /// Take a value from storage, deleting it after reading. - fn take(&mut self, key: &[u8]) -> Option { - hashed::take(&H::hash, key) - } - - fn get_raw(&self, key: &[u8]) -> Option> { - hashed::get_raw(&H::hash, key) - } - - fn put_raw(&mut self, key: &[u8], value: &[u8]) { - hashed::put_raw(&H::hash, key, value) - } -} - -impl UnhashedStorage for RuntimeStorage { - fn exists(&self, key: &[u8]) -> bool { - unhashed::exists(key) - } - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option { - unhashed::get(key) - } - - /// Put a value in under a key. - fn put(&mut self, key: &[u8], val: &T) { - unhashed::put(key, val) - } - - /// Remove the bytes of a key from storage. - fn kill(&mut self, key: &[u8]) { - unhashed::kill(key) - } - - /// Remove the bytes of a key from storage. - fn kill_prefix(&mut self, prefix: &[u8]) { - unhashed::kill_prefix(prefix) - } - - /// Take a value from storage, deleting it after reading. - fn take(&mut self, key: &[u8]) -> Option { - unhashed::take(key) - } - - fn get_raw(&self, key: &[u8]) -> Option> { - unhashed::get_raw(key) - } - - fn put_raw(&mut self, key: &[u8], value: &[u8]) { - unhashed::put_raw(key, value) - } -} +pub mod child; +pub mod generator; /// A trait for working with macro-generated storage values under the substrate storage API. -pub trait StorageValue { +/// +/// Details on implementation can be found at +/// [`generator::StorageValue`] +pub trait StorageValue { /// The type that get/take return. type Query; /// Get the storage key. - fn key() -> &'static [u8]; + fn hashed_key() -> [u8; 16]; /// Does the value (explicitly) exist in storage? fn exists() -> bool; @@ -117,12 +42,30 @@ pub trait StorageValue { /// Load the value from the provided storage instance. fn get() -> Self::Query; - /// Store a value under this key into the provided storage instance. - fn put>(val: Arg); + /// Translate a value from some previous type (`O`) to the current type. + /// + /// `f: F` is the translation function. + /// + /// Returns `Err` if the storage item could not be interpreted as the old type, and Ok, along + /// with the new value if it could. + /// + /// NOTE: This operates from and to `Option<_>` types; no effort is made to respect the default + /// value of the original type. + /// + /// # Warning + /// + /// This function must be used with care, before being updated the storage still contains the + /// old type, thus other calls (such as `get`) will fail at decoding it. + /// + /// # Usage + /// + /// This would typically be called inside the module implementation of on_initialize, while + /// ensuring **no usage of this storage are made before the call to `on_initialize`**. (More + /// precisely prior initialized modules doesn't make use of this storage). + fn translate) -> Option>(f: F) -> Result, ()>; - /// Store a value under this key into the provided storage instance; this can take any reference - /// type that derefs to `T` (and has `Encode` implemented). - fn put_ref(val: &Arg) where T: AsRef; + /// Store a value under this key into the provided storage instance. + fn put>(val: Arg); /// Mutate the value fn mutate R>(f: F) -> R; @@ -136,166 +79,157 @@ pub trait StorageValue { /// Append the given item to the value in the storage. /// /// `T` is required to implement `codec::EncodeAppend`. - fn append(items: &[I]) -> Result<(), &'static str> - where T: EncodeAppend; -} + fn append(items: Items) -> Result<(), &'static str> + where + Item: Encode, + EncodeLikeItem: EncodeLike, + T: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator; + + /// Append the given items to the value in the storage. + /// + /// `T` is required to implement `Codec::EncodeAppend`. + /// + /// Upon any failure, it replaces `items` as the new value (assuming that the previous stored + /// data is simply corrupt and no longer usable). + /// + /// ### WARNING + /// + /// use with care; if your use-case is not _exactly_ as what this function is doing, + /// you should use append and sensibly handle failure within the runtime code if it happens. + fn append_or_put(items: Items) where + Item: Encode, + EncodeLikeItem: EncodeLike, + T: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator; + -impl StorageValue for U where U: hashed::generator::StorageValue { - type Query = U::Query; - - fn key() -> &'static [u8] { - >::key() - } - fn exists() -> bool { - U::exists(&RuntimeStorage) - } - fn get() -> Self::Query { - U::get(&RuntimeStorage) - } - fn put>(val: Arg) { - U::put(val.borrow(), &mut RuntimeStorage) - } - fn put_ref(val: &Arg) where T: AsRef { - U::put_ref(val, &mut RuntimeStorage) - } - fn mutate R>(f: F) -> R { - U::mutate(f, &mut RuntimeStorage) - } - fn kill() { - U::kill(&mut RuntimeStorage) - } - fn take() -> Self::Query { - U::take(&mut RuntimeStorage) - } - fn append(items: &[I]) -> Result<(), &'static str> - where T: EncodeAppend - { - U::append(items, &mut RuntimeStorage) - } + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + fn decode_len() -> Result + where T: codec::DecodeLength + Len; } /// A strongly-typed map in storage. -pub trait StorageMap { +/// +/// Details on implementation can be found at +/// [`generator::StorageMap`] +pub trait StorageMap { /// The type that get/take return. type Query; - /// Get the prefix key in storage. - fn prefix() -> &'static [u8]; - /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for>(key: KeyArg) -> Vec; + fn hashed_key_for>(key: KeyArg) -> Vec; /// Does the value (explicitly) exist in storage? - fn exists>(key: KeyArg) -> bool; + fn exists>(key: KeyArg) -> bool; /// Load the value associated with the given key from the map. - fn get>(key: KeyArg) -> Self::Query; + fn get>(key: KeyArg) -> Self::Query; /// Swap the values of two keys. - fn swap, KeyArg2: Borrow>(key1: KeyArg1, key2: KeyArg2); + fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2); /// Store a value to be associated with the given key from the map. - fn insert, ValArg: Borrow>(key: KeyArg, val: ValArg); - - /// Store a value under this key into the provided storage instance; this can take any reference - /// type that derefs to `T` (and has `Encode` implemented). - fn insert_ref, ValArg: ?Sized + Encode>(key: KeyArg, val: &ValArg) where V: AsRef; + fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg); /// Remove the value under a key. - fn remove>(key: KeyArg); + fn remove>(key: KeyArg); /// Mutate the value under a key. - fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; + fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; /// Take the value under a key. - fn take>(key: KeyArg) -> Self::Query; -} - -impl StorageMap for U where U: hashed::generator::StorageMap { - type Query = U::Query; - - fn prefix() -> &'static [u8] { - >::prefix() - } + fn take>(key: KeyArg) -> Self::Query; - fn key_for>(key: KeyArg) -> Vec { - >::key_for(key.borrow()) - } - - fn exists>(key: KeyArg) -> bool { - U::exists(key.borrow(), &RuntimeStorage) - } + /// Append the given items to the value in the storage. + /// + /// `V` is required to implement `codec::EncodeAppend`. + fn append(key: KeyArg, items: Items) -> Result<(), &'static str> + where + KeyArg: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator; + + /// Safely append the given items to the value in the storage. If a codec error occurs, then the + /// old (presumably corrupt) value is replaced with the given `items`. + /// + /// `V` is required to implement `codec::EncodeAppend`. + fn append_or_insert(key: KeyArg, items: Items) + where + KeyArg: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator; + + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + /// + /// Note that `0` is returned as the default value if no encoded value exists at the given key. + /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` + /// function for this purpose. + fn decode_len>(key: KeyArg) -> Result + where V: codec::DecodeLength + Len; +} - fn get>(key: KeyArg) -> Self::Query { - U::get(key.borrow(), &RuntimeStorage) - } +/// A strongly-typed linked map in storage. +/// +/// Similar to `StorageMap` but allows to enumerate other elements and doesn't implement append. +/// +/// Details on implementation can be found at +/// [`generator::StorageLinkedMap`] +pub trait StorageLinkedMap { + /// The type that get/take return. + type Query; - fn swap, KeyArg2: Borrow>(key1: KeyArg1, key2: KeyArg2) { - U::swap(key1.borrow(), key2.borrow(), &mut RuntimeStorage) - } + /// The type that iterates over all `(key, value)`. + type Enumerator: Iterator; - fn insert, ValArg: Borrow>(key: KeyArg, val: ValArg) { - U::insert(key.borrow(), val.borrow(), &mut RuntimeStorage) - } + /// Does the value (explicitly) exist in storage? + fn exists>(key: KeyArg) -> bool; - fn insert_ref, ValArg: ?Sized + Encode>(key: KeyArg, val: &ValArg) where V: AsRef { - U::insert_ref(key.borrow(), val, &mut RuntimeStorage) - } + /// Load the value associated with the given key from the map. + fn get>(key: KeyArg) -> Self::Query; - fn remove>(key: KeyArg) { - U::remove(key.borrow(), &mut RuntimeStorage) - } + /// Swap the values of two keys. + fn swap, KeyArg2: EncodeLike>(key1: KeyArg1, key2: KeyArg2); - fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R { - U::mutate(key.borrow(), f, &mut RuntimeStorage) - } + /// Store a value to be associated with the given key from the map. + fn insert, ValArg: EncodeLike>(key: KeyArg, val: ValArg); - fn take>(key: KeyArg) -> Self::Query { - U::take(key.borrow(), &mut RuntimeStorage) - } -} + /// Remove the value under a key. + fn remove>(key: KeyArg); -/// A storage map with values that can be appended to. -pub trait AppendableStorageMap: StorageMap { - /// Append the given item to the value in the storage. - /// - /// `T` is required to implement `codec::EncodeAppend`. - fn append, I: Encode>(key: KeyArg, items: &[I]) -> Result<(), &'static str> - where V: EncodeAppend; -} + /// Mutate the value under a key. + fn mutate, R, F: FnOnce(&mut Self::Query) -> R>(key: KeyArg, f: F) -> R; -impl AppendableStorageMap for U - where U: hashed::generator::AppendableStorageMap -{ - fn append, I: Encode>(key: KeyArg, items: &[I]) -> Result<(), &'static str> - where V: EncodeAppend - { - U::append(key.borrow(), items, &mut RuntimeStorage) - } -} + /// Take the value under a key. + fn take>(key: KeyArg) -> Self::Query; -/// A storage map that can be enumerated. -/// -/// Primarily useful for off-chain computations. -/// Runtime implementors should avoid enumerating storage entries on-chain. -pub trait EnumerableStorageMap: StorageMap { /// Return current head element. fn head() -> Option; /// Enumerate all elements in the map. - fn enumerate() -> Box> where K: 'static, V: 'static; -} - -impl EnumerableStorageMap for U - where U: hashed::generator::EnumerableStorageMap -{ - fn head() -> Option { - >::head(&RuntimeStorage) - } + fn enumerate() -> Self::Enumerator; - fn enumerate() -> Box> where K: 'static, V: 'static { - >::enumerate(&RuntimeStorage) - } + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + /// + /// Note that `0` is returned as the default value if no encoded value exists at the given key. + /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` + /// function for this purpose. + fn decode_len>(key: KeyArg) -> Result + where V: codec::DecodeLength + Len; } /// An implementation of a map with a two keys. @@ -303,286 +237,71 @@ impl EnumerableStorageMap for U /// It provides an important ability to efficiently remove all entries /// that have a common first key. /// -/// # Mapping of keys to a storage path -/// -/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. -/// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part -/// is a hash of a `Key2`. -/// -/// /!\ be careful while choosing the Hash, indeed malicious could craft second keys to lower the trie. -pub trait StorageDoubleMap { +/// Details on implementation can be found at +/// [`generator::StorageDoubleMap`] +pub trait StorageDoubleMap { /// The type that get/take returns. type Query; - fn prefix() -> &'static [u8]; - - fn key_for(k1: &KArg1, k2: &KArg2) -> Vec + fn exists(k1: KArg1, k2: KArg2) -> bool where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; + KArg1: EncodeLike, + KArg2: EncodeLike; - fn prefix_for(k1: &KArg1) -> Vec where KArg1: ?Sized + Encode, K1: Borrow; - - fn exists(k1: &KArg1, k2: &KArg2) -> bool + fn get(k1: KArg1, k2: KArg2) -> Self::Query where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; + KArg1: EncodeLike, + KArg2: EncodeLike; - fn get(k1: &KArg1, k2: &KArg2) -> Self::Query + fn take(k1: KArg1, k2: KArg2) -> Self::Query where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; + KArg1: EncodeLike, + KArg2: EncodeLike; - fn take(k1: &KArg1, k2: &KArg2) -> Self::Query + fn insert(k1: KArg1, k2: KArg2, val: VArg) where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; + KArg1: EncodeLike, + KArg2: EncodeLike, + VArg: EncodeLike; - fn insert(k1: &KArg1, k2: &KArg2, val: &VArg) - where - K1: Borrow, - K2: Borrow, - V: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - VArg: ?Sized + Encode; - - fn remove(k1: &KArg1, k2: &KArg2) + fn remove(k1: KArg1, k2: KArg2) where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; + KArg1: EncodeLike, + KArg2: EncodeLike; - fn remove_prefix(k1: &KArg1) where KArg1: ?Sized + Encode, K1: Borrow; + fn remove_prefix(k1: KArg1) where KArg1: ?Sized + EncodeLike; - fn mutate(k1: &KArg1, k2: &KArg2, f: F) -> R + fn mutate(k1: KArg1, k2: KArg2, f: F) -> R where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, + KArg1: EncodeLike, + KArg2: EncodeLike, F: FnOnce(&mut Self::Query) -> R; - fn append( - k1: &KArg1, - k2: &KArg2, - items: &[I], + fn append( + k1: KArg1, + k2: KArg2, + items: Items, ) -> Result<(), &'static str> where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - I: codec::Encode, - V: EncodeAppend; -} - -impl StorageDoubleMap for U -where - U: unhashed::generator::StorageDoubleMap -{ - type Query = U::Query; - - fn prefix() -> &'static [u8] { - >::prefix() - } - - fn key_for(k1: &KArg1, k2: &KArg2) -> Vec - where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - { - >::key_for(k1, k2) - } - - fn prefix_for(k1: &KArg1) -> Vec where KArg1: ?Sized + Encode, K1: Borrow { - >::prefix_for(k1) - } - - fn exists(k1: &KArg1, k2: &KArg2) -> bool + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator, + Items::IntoIter: ExactSizeIterator; + + fn append_or_insert( + k1: KArg1, + k2: KArg2, + items: Items, + ) where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - { - U::exists(k1, k2, &RuntimeStorage) - } - - fn get(k1: &KArg1, k2: &KArg2) -> Self::Query - where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - { - U::get(k1, k2, &RuntimeStorage) - } - - fn take(k1: &KArg1, k2: &KArg2) -> Self::Query - where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - { - U::take(k1.borrow(), k2.borrow(), &mut RuntimeStorage) - } - - fn insert(k1: &KArg1, k2: &KArg2, val: &VArg) - where - K1: Borrow, - K2: Borrow, - V: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - VArg: ?Sized + Encode, - { - U::insert(k1, k2, val, &mut RuntimeStorage) - } - - fn remove(k1: &KArg1, k2: &KArg2) - where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - { - U::remove(k1, k2, &mut RuntimeStorage) - } - - fn remove_prefix(k1: &KArg1) where KArg1: ?Sized + Encode, K1: Borrow { - U::remove_prefix(k1, &mut RuntimeStorage) - } - - fn mutate(k1: &KArg1, k2: &KArg2, f: F) -> R - where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - F: FnOnce(&mut Self::Query) -> R - { - U::mutate(k1, k2, f, &mut RuntimeStorage) - } - - fn append( - k1: &KArg1, - k2: &KArg2, - items: &[I], - ) -> Result<(), &'static str> - where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - I: codec::Encode, - V: EncodeAppend, - { - U::append(k1, k2, items, &mut RuntimeStorage) - } -} - -/// child storage NOTE could replace unhashed by having only one kind of storage (root being null storage -/// key (storage_key can become Option<&[u8]>). -/// This module is a currently only a variant of unhashed with additional `storage_key`. -/// Note that `storage_key` must be unique and strong (strong in the sense of being long enough to -/// avoid collision from a resistant hash function (which unique implies)). -pub mod child { - use super::{Codec, Decode, Vec}; - - /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. - pub fn get(storage_key: &[u8], key: &[u8]) -> Option { - runtime_io::child_storage(storage_key, key).map(|v| { - Decode::decode(&mut &v[..]).expect("storage is not null, therefore must be a valid type") - }) - } - - /// Return the value of the item in storage under `key`, or the type's default if there is no - /// explicit entry. - pub fn get_or_default(storage_key: &[u8], key: &[u8]) -> T { - get(storage_key, key).unwrap_or_else(Default::default) - } - - /// Return the value of the item in storage under `key`, or `default_value` if there is no - /// explicit entry. - pub fn get_or(storage_key: &[u8], key: &[u8], default_value: T) -> T { - get(storage_key, key).unwrap_or(default_value) - } - - /// Return the value of the item in storage under `key`, or `default_value()` if there is no - /// explicit entry. - pub fn get_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { - get(storage_key, key).unwrap_or_else(default_value) - } - - /// Put `value` in storage under `key`. - pub fn put(storage_key: &[u8], key: &[u8], value: &T) { - value.using_encoded(|slice| runtime_io::set_child_storage(storage_key, key, slice)); - } - - /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise. - pub fn take(storage_key: &[u8], key: &[u8]) -> Option { - let r = get(storage_key, key); - if r.is_some() { - kill(storage_key, key); - } - r - } - - /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, - /// the default for its type. - pub fn take_or_default(storage_key: &[u8], key: &[u8]) -> T { - take(storage_key, key).unwrap_or_else(Default::default) - } - - /// Return the value of the item in storage under `key`, or `default_value` if there is no - /// explicit entry. Ensure there is no explicit entry on return. - pub fn take_or(storage_key: &[u8],key: &[u8], default_value: T) -> T { - take(storage_key, key).unwrap_or(default_value) - } - - /// Return the value of the item in storage under `key`, or `default_value()` if there is no - /// explicit entry. Ensure there is no explicit entry on return. - pub fn take_or_else T>(storage_key: &[u8], key: &[u8], default_value: F) -> T { - take(storage_key, key).unwrap_or_else(default_value) - } - - /// Check to see if `key` has an explicit entry in storage. - pub fn exists(storage_key: &[u8], key: &[u8]) -> bool { - runtime_io::read_child_storage(storage_key, key, &mut [0;0][..], 0).is_some() - } - - /// Remove all `storage_key` key/values - pub fn kill_storage(storage_key: &[u8]) { - runtime_io::kill_child_storage(storage_key) - } - - /// Ensure `key` has no explicit entry in storage. - pub fn kill(storage_key: &[u8], key: &[u8]) { - runtime_io::clear_child_storage(storage_key, key); - } - - /// Get a Vec of bytes from storage. - pub fn get_raw(storage_key: &[u8], key: &[u8]) -> Option> { - runtime_io::child_storage(storage_key, key) - } - - /// Put a raw byte slice into storage. - pub fn put_raw(storage_key: &[u8], key: &[u8], value: &[u8]) { - runtime_io::set_child_storage(storage_key, key, value) - } - - pub use super::unhashed::StorageVec; + KArg1: EncodeLike, + KArg2: EncodeLike, + Item: Encode, + EncodeLikeItem: EncodeLike, + V: EncodeAppend, + Items: IntoIterator + Clone + EncodeLike, + Items::IntoIter: ExactSizeIterator; } diff --git a/srml/support/src/storage/unhashed/mod.rs b/srml/support/src/storage/unhashed.rs similarity index 72% rename from srml/support/src/storage/unhashed/mod.rs rename to srml/support/src/storage/unhashed.rs index 5d086c36c4819aa8c97183e393828f9615d4a4c9..6397fd39fcd2d90dd39012e199c329c741c50832 100644 --- a/srml/support/src/storage/unhashed/mod.rs +++ b/srml/support/src/storage/unhashed.rs @@ -14,12 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Operation on unhashed runtime storage +//! Operation on unhashed runtime storage. -use crate::rstd::borrow::Borrow; -use super::{Codec, Encode, Decode, KeyedVec, Vec}; - -pub mod generator; +use rstd::prelude::*; +use codec::{Encode, Decode}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(key: &[u8]) -> Option { @@ -102,55 +100,3 @@ pub fn get_raw(key: &[u8]) -> Option> { pub fn put_raw(key: &[u8], value: &[u8]) { runtime_io::set_storage(key, value) } - -/// A trait to conveniently store a vector of storable data. -pub trait StorageVec { - type Item: Default + Sized + Codec; - const PREFIX: &'static [u8]; - - /// Get the current set of items. - fn items() -> Vec { - (0..Self::count()).into_iter().map(Self::item).collect() - } - - /// Set the current set of items. - fn set_items(items: I) - where - I: IntoIterator, - T: Borrow, - { - let mut count: u32 = 0; - - for i in items.into_iter() { - put(&count.to_keyed_vec(Self::PREFIX), i.borrow()); - count = count.checked_add(1).expect("exceeded runtime storage capacity"); - } - - Self::set_count(count); - } - - fn set_item(index: u32, item: &Self::Item) { - if index < Self::count() { - put(&index.to_keyed_vec(Self::PREFIX), item); - } - } - - fn clear_item(index: u32) { - if index < Self::count() { - kill(&index.to_keyed_vec(Self::PREFIX)); - } - } - - fn item(index: u32) -> Self::Item { - get_or_default(&index.to_keyed_vec(Self::PREFIX)) - } - - fn set_count(count: u32) { - (count..Self::count()).for_each(Self::clear_item); - put(&b"len".to_keyed_vec(Self::PREFIX), &count); - } - - fn count() -> u32 { - get_or_default(&b"len".to_keyed_vec(Self::PREFIX)) - } -} diff --git a/srml/support/src/storage/unhashed/generator.rs b/srml/support/src/storage/unhashed/generator.rs deleted file mode 100644 index a5385af8fb2f97154361dfe8846f6e673c3cb2bd..0000000000000000000000000000000000000000 --- a/srml/support/src/storage/unhashed/generator.rs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -use crate::codec::{self, Encode, EncodeAppend}; -use crate::rstd::{borrow::Borrow, vec::Vec}; - -/// Abstraction around storage with unhashed access. -pub trait UnhashedStorage { - /// true if the key exists in storage. - fn exists(&self, key: &[u8]) -> bool; - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. - fn get(&self, key: &[u8]) -> Option; - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. Will panic if - /// it's not there. - fn require(&self, key: &[u8]) -> T { - self.get(key).expect("Required values must be in storage") - } - - /// Load the bytes of a key from storage. Can panic if the type is incorrect. The type's - /// default is returned if it's not there. - fn get_or_default(&self, key: &[u8]) -> T { - self.get(key).unwrap_or_default() - } - - /// Put a value in under a key. - fn put(&mut self, key: &[u8], val: &T); - - /// Remove the bytes of a key from storage. - fn kill(&mut self, key: &[u8]); - - /// Remove the bytes of a key from storage. - fn kill_prefix(&mut self, prefix: &[u8]); - - /// Take a value from storage, deleting it after reading. - fn take(&mut self, key: &[u8]) -> Option { - let value = self.get(key); - self.kill(key); - value - } - - /// Take a value from storage, deleting it after reading. - fn take_or_panic(&mut self, key: &[u8]) -> T { - self.take(key).expect("Required values must be in storage") - } - - /// Take a value from storage, deleting it after reading. - fn take_or_default(&mut self, key: &[u8]) -> T { - self.take(key).unwrap_or_default() - } - - /// Get a Vec of bytes from storage. - fn get_raw(&self, key: &[u8]) -> Option>; - - /// Put a raw byte slice into storage. - fn put_raw(&mut self, key: &[u8], value: &[u8]); -} - -// We use a construct like this during when genesis storage is being built. -#[cfg(feature = "std")] -impl UnhashedStorage for sr_primitives::StorageOverlay { - fn exists(&self, key: &[u8]) -> bool { - self.contains_key(key) - } - - fn get(&self, key: &[u8]) -> Option { - self.get(key) - .map(|x| codec::Decode::decode(&mut x.as_slice()).expect("Unable to decode expected type.")) - } - - fn put(&mut self, key: &[u8], val: &T) { - self.insert(key.to_vec(), codec::Encode::encode(val)); - } - - fn kill(&mut self, key: &[u8]) { - self.remove(key); - } - - fn kill_prefix(&mut self, prefix: &[u8]) { - self.retain(|key, _| { - !key.starts_with(prefix) - }) - } - - fn get_raw(&self, key: &[u8]) -> Option> { - self.get(key).cloned() - } - - fn put_raw(&mut self, key: &[u8], value: &[u8]) { - self.insert(key.to_vec(), value.to_vec()); - } -} - -/// An implementation of a map with a two keys. -/// -/// It provides an important ability to efficiently remove all entries -/// that have a common first key. -/// -/// # Mapping of keys to a storage path -/// -/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts. -/// The first part is a hash of a concatenation of the `PREFIX` and `Key1`. And the second part -/// is a hash of a `Key2`. -/// -/// /!\ be careful while choosing the Hash, indeed malicious could craft second keys to lower the trie. -pub trait StorageDoubleMap { - /// The type that get/take returns. - type Query; - - /// Get the prefix key in storage. - fn prefix() -> &'static [u8]; - - /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for( - k1: &KArg1, - k2: &KArg2, - ) -> Vec where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; - - /// Get the storage prefix used to fetch keys corresponding to a specific key1. - fn prefix_for(k1: &KArg1) -> Vec where KArg1: ?Sized + Encode, K1: Borrow; - - /// true if the value is defined in storage. - fn exists( - k1: &KArg1, - k2: &KArg2, - storage: &S, - ) -> bool where K1: Borrow, K2: Borrow, KArg1: ?Sized + Encode, KArg2: ?Sized + Encode { - storage.exists(&Self::key_for(k1, k2)) - } - - /// Load the value associated with the given key from the map. - fn get( - k1: &KArg1, - k2: &KArg2, - storage: &S, - ) -> Self::Query where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; - - /// Take the value under a key. - fn take( - k1: &KArg1, - k2: &KArg2, - storage: &mut S, - ) -> Self::Query where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode; - - /// Store a value to be associated with the given key from the map. - fn insert( - k1: &KArg1, - k2: &KArg2, - val: &VArg, - storage: &mut S, - ) where - K1: Borrow, - K2: Borrow, - V: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - VArg: ?Sized + Encode, - { - storage.put(&Self::key_for(k1, k2), val); - } - - /// Remove the value under a key. - fn remove( - k1: &KArg1, - k2: &KArg2, - storage: &mut S, - ) where K1: Borrow, K2: Borrow, KArg1: ?Sized + Encode, KArg2: ?Sized + Encode { - storage.kill(&Self::key_for(k1, k2)); - } - - /// Removes all entries that shares the `k1` as the first key. - fn remove_prefix( - k1: &KArg1, - storage: &mut S, - ) where KArg1: ?Sized + Encode, K1: Borrow { - storage.kill_prefix(&Self::prefix_for(k1)); - } - - /// Mutate the value under a key. - fn mutate( - k1: &KArg1, - k2: &KArg2, - f: F, - storage: &mut S, - ) -> R where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - F: FnOnce(&mut Self::Query) -> R; - - /// Append the given items to the value under the key specified. - fn append( - k1: &KArg1, - k2: &KArg2, - items: &[I], - storage: &mut S, - ) -> Result<(), &'static str> - where - K1: Borrow, - K2: Borrow, - KArg1: ?Sized + Encode, - KArg2: ?Sized + Encode, - I: codec::Encode, - V: EncodeAppend, - { - let key = Self::key_for(k1, k2); - let new_val = ::append( - storage.get_raw(&key).unwrap_or_default(), - items, - ).map_err(|_| "Could not append given item")?; - storage.put_raw(&key, &new_val); - Ok(()) - } -} diff --git a/srml/support/src/traits.rs b/srml/support/src/traits.rs index 2766ba0a98767e7510332336e1da0d0751a240aa..297e128ebc2f05170ffa4ef0b201bc69f6913b1c 100644 --- a/srml/support/src/traits.rs +++ b/srml/support/src/traits.rs @@ -18,13 +18,25 @@ //! //! NOTE: If you're looking for `parameter_types`, it has moved in to the top-level module. -use crate::rstd::{prelude::*, result, marker::PhantomData, ops::Div}; -use crate::codec::{Codec, Encode, Decode}; +use rstd::{prelude::*, result, marker::PhantomData, ops::Div, fmt::Debug}; +use codec::{FullCodec, Codec, Encode, Decode}; use primitives::u32_trait::Value as U32; -use crate::sr_primitives::traits::{MaybeSerializeDebug, SimpleArithmetic, Saturating}; -use crate::sr_primitives::ConsensusEngineId; +use sr_primitives::{ + ConsensusEngineId, + traits::{MaybeSerializeDeserialize, SimpleArithmetic, Saturating}, +}; + +/// Anything that can have a `::len()` method. +pub trait Len { + /// Return the length of data type. + fn len(&self) -> usize; +} -use super::for_each_tuple; +impl Len for T where ::IntoIter: ExactSizeIterator { + fn len(&self) -> usize { + self.clone().into_iter().len() + } +} /// A trait for querying a single fixed value from a type. pub trait Get { @@ -32,6 +44,10 @@ pub trait Get { fn get() -> T; } +impl Get for () { + fn get() -> T { T::default() } +} + /// A trait for querying whether a type can be said to statically "contain" a value. Similar /// in nature to `Get`, except it is designed to be lazy rather than active (you can't ask it to /// enumerate all values that it contains) and work for multiple values rather than just one. @@ -47,40 +63,12 @@ impl> Contains for T { } /// The account with the given id was killed. +#[impl_trait_for_tuples::impl_for_tuples(30)] pub trait OnFreeBalanceZero { /// The account was the given id was killed. fn on_free_balance_zero(who: &AccountId); } -macro_rules! impl_on_free_balance_zero { - () => ( - impl OnFreeBalanceZero for () { - fn on_free_balance_zero(_: &AccountId) {} - } - ); - - ( $($t:ident)* ) => { - impl),*> OnFreeBalanceZero for ($($t,)*) { - fn on_free_balance_zero(who: &AccountId) { - $($t::on_free_balance_zero(who);)* - } - } - } -} - -for_each_tuple!(impl_on_free_balance_zero); - -/// Trait for a hook to get called when some balance has been minted, causing dilution. -pub trait OnDilution { - /// Some `portion` of the total balance just "grew" by `minted`. `portion` is the pre-growth - /// amount (it doesn't take account of the recent growth). - fn on_dilution(minted: Balance, portion: Balance); -} - -impl OnDilution for () { - fn on_dilution(_minted: Balance, _portion: Balance) {} -} - /// Outcome of a balance update. pub enum UpdateBalanceOutcome { /// Account balance was simply updated. @@ -117,8 +105,8 @@ pub trait VerifySeal { pub trait KeyOwnerProofSystem { /// The proof of membership itself. type Proof: Codec; - /// The full identification of a key owner. - type FullIdentification: Codec; + /// The full identification of a key owner and the stash account. + type IdentificationTuple: Codec; /// Prove membership of a key owner in the current block-state. /// @@ -131,7 +119,7 @@ pub trait KeyOwnerProofSystem { /// Check a proof of membership on-chain. Return `Some` iff the proof is /// valid and recent enough to check. - fn check_proof(key: Key, proof: Self::Proof) -> Option; + fn check_proof(key: Key, proof: Self::Proof) -> Option; } /// Handler for when some currency "account" decreased in balance for @@ -149,7 +137,7 @@ pub trait OnUnbalanced { fn on_unbalanced(amount: Imbalance); } -impl OnUnbalanced for () { +impl OnUnbalanced for () { fn on_unbalanced(amount: Imbalance) { drop(amount); } } @@ -157,6 +145,9 @@ impl OnUnbalanced for () { #[derive(Copy, Clone, Eq, PartialEq)] pub enum ExistenceRequirement { /// Operation must not result in the account going out of existence. + /// + /// Note this implies that if the account never existed in the first place, then the operation + /// may legitimately leave the account unchanged and still non-existent. KeepAlive, /// Operation may result in account going out of existence. AllowDeath, @@ -255,7 +246,7 @@ pub enum SignedImbalance>{ impl< P: Imbalance, N: Imbalance, - B: SimpleArithmetic + Codec + Copy + MaybeSerializeDebug + Default, + B: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default, > SignedImbalance { pub fn zero() -> Self { SignedImbalance::Positive(P::zero()) @@ -318,7 +309,7 @@ impl< /// Abstraction over a fungible assets system. pub trait Currency { /// The balance of an account. - type Balance: SimpleArithmetic + Codec + Copy + MaybeSerializeDebug + Default; + type Balance: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default; /// The opaque token type for an imbalance. This is returned by unbalanced operations /// and must be dealt with. It may be dropped but cannot be cloned. @@ -379,7 +370,7 @@ pub trait Currency { fn ensure_can_withdraw( who: &AccountId, _amount: Self::Balance, - reason: WithdrawReason, + reasons: WithdrawReasons, new_balance: Self::Balance, ) -> result::Result<(), &'static str>; @@ -393,6 +384,7 @@ pub trait Currency { source: &AccountId, dest: &AccountId, value: Self::Balance, + existence_requirement: ExistenceRequirement, ) -> result::Result<(), &'static str>; /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the @@ -457,7 +449,7 @@ pub trait Currency { fn withdraw( who: &AccountId, value: Self::Balance, - reason: WithdrawReason, + reasons: WithdrawReasons, liveness: ExistenceRequirement, ) -> result::Result; @@ -465,11 +457,11 @@ pub trait Currency { fn settle( who: &AccountId, value: Self::PositiveImbalance, - reason: WithdrawReason, + reasons: WithdrawReasons, liveness: ExistenceRequirement, ) -> result::Result<(), Self::PositiveImbalance> { let v = value.peek(); - match Self::withdraw(who, v, reason, liveness) { + match Self::withdraw(who, v, reasons, liveness) { Ok(opposite) => Ok(drop(value.offset(opposite))), _ => Err(value), } @@ -612,17 +604,29 @@ bitmask! { Reserve = 0b00000100, /// In order to pay some other (higher-level) fees. Fee = 0b00001000, + /// In order to tip a validator for transaction inclusion. + Tip = 0b00010000, } } pub trait Time { - type Moment: SimpleArithmetic + Codec + Clone + Default; + type Moment: SimpleArithmetic + FullCodec + Clone + Default + Copy; fn now() -> Self::Moment; } impl WithdrawReasons { /// Choose all variants except for `one`. + /// + /// ```rust + /// # use srml_support::traits::{WithdrawReason, WithdrawReasons}; + /// # fn main() { + /// assert_eq!( + /// WithdrawReason::Fee | WithdrawReason::Transfer | WithdrawReason::Reserve | WithdrawReason::Tip, + /// WithdrawReasons::except(WithdrawReason::TransactionPayment), + /// ); + /// # } + /// ``` pub fn except(one: WithdrawReason) -> WithdrawReasons { let mut mask = Self::all(); mask.toggle(one); @@ -652,6 +656,16 @@ pub trait ChangeMembers { /// Set the new members; they **must already be sorted**. This will compute the diff and use it to /// call `change_members_sorted`. fn set_members_sorted(new_members: &[AccountId], old_members: &[AccountId]) { + let (incoming, outgoing) = Self::compute_members_diff(new_members, old_members); + Self::change_members_sorted(&incoming[..], &outgoing[..], &new_members); + } + + /// Set the new members; they **must already be sorted**. This will compute the diff and use it to + /// call `change_members_sorted`. + fn compute_members_diff( + new_members: &[AccountId], + old_members: &[AccountId] + ) -> (Vec, Vec) { let mut old_iter = old_members.iter(); let mut new_iter = new_members.iter(); let mut incoming = Vec::new(); @@ -679,8 +693,7 @@ pub trait ChangeMembers { } } } - - Self::change_members_sorted(&incoming[..], &outgoing[..], &new_members); + (incoming, outgoing) } } @@ -689,3 +702,33 @@ impl ChangeMembers for () { fn change_members_sorted(_: &[T], _: &[T], _: &[T]) {} fn set_members_sorted(_: &[T], _: &[T]) {} } + +/// Trait for type that can handle the initialization of account IDs at genesis. +pub trait InitializeMembers { + /// Initialize the members to the given `members`. + fn initialize_members(members: &[AccountId]); +} + +impl InitializeMembers for () { + fn initialize_members(_: &[T]) {} +} + +// A trait that is able to provide randomness. +pub trait Randomness { + /// Get a "random" value + /// + /// Being a deterministic blockchain, real randomness is difficult to come by. This gives you + /// something that approximates it. `subject` is a context identifier and allows you to get a + /// different result to other callers of this function; use it like + /// `random(&b"my context"[..])`. + fn random(subject: &[u8]) -> Output; + + /// Get the basic random seed. + /// + /// In general you won't want to use this, but rather `Self::random` which allows you to give a + /// subject for the random result and whose value will be independently low-influence random + /// from any other such seeds. + fn random_seed() -> Output { + Self::random(&[][..]) + } +} diff --git a/srml/support/src/unsigned.rs b/srml/support/src/unsigned.rs index 1c62dd0c58435670e1e1ee3a562d2539deb0c2ac..282f3ac8ae9a8a178a06a1d7a7bd7188821af7b5 100644 --- a/srml/support/src/unsigned.rs +++ b/srml/support/src/unsigned.rs @@ -15,9 +15,10 @@ // along with Substrate. If not, see . #[doc(hidden)] +#[allow(deprecated)] pub use crate::sr_primitives::traits::ValidateUnsigned; #[doc(hidden)] -pub use crate::sr_primitives::transaction_validity::TransactionValidity; +pub use crate::sr_primitives::transaction_validity::{TransactionValidity, UnknownTransaction}; #[doc(hidden)] pub use crate::sr_primitives::ApplyError; @@ -65,14 +66,25 @@ macro_rules! impl_outer_validate_unsigned { $( $module:ident )* } ) => { + #[allow(deprecated)] // Allow ValidateUnsigned impl $crate::unsigned::ValidateUnsigned for $runtime { type Call = Call; + fn pre_dispatch(call: &Self::Call) -> Result<(), $crate::unsigned::ApplyError> { + #[allow(unreachable_patterns)] + match call { + $( Call::$module(inner_call) => $module::pre_dispatch(inner_call), )* + // pre-dispatch should not stop inherent extrinsics, validation should prevent + // including arbitrary (non-inherent) extrinsics to blocks. + _ => Ok(()), + } + } + fn validate_unsigned(call: &Self::Call) -> $crate::unsigned::TransactionValidity { #[allow(unreachable_patterns)] match call { $( Call::$module(inner_call) => $module::validate_unsigned(inner_call), )* - _ => $crate::unsigned::TransactionValidity::Invalid($crate::unsigned::ApplyError::BadSignature as i8), + _ => $crate::unsigned::UnknownTransaction::NoUnsignedValidator.into(), } } } @@ -81,8 +93,7 @@ macro_rules! impl_outer_validate_unsigned { #[cfg(test)] mod test_empty_call { - pub enum Call { - } + pub enum Call {} #[allow(unused)] pub struct Runtime; @@ -98,6 +109,7 @@ mod test_partial_and_full_call { pub mod timestamp { pub struct Module; + #[allow(deprecated)] // Allow ValidateUnsigned impl super::super::ValidateUnsigned for Module { type Call = Call; diff --git a/srml/support/test/Cargo.toml b/srml/support/test/Cargo.toml index fa3a04d3bc32a1dfb4ec33b610eadce55081180d..a5e375b5c6b9383f46069df871f2f4e5094cc063 100644 --- a/srml/support/test/Cargo.toml +++ b/srml/support/test/Cargo.toml @@ -5,13 +5,14 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", default-features = false, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -runtime_io = { package = "sr-io", path = "../../../core/sr-io", default-features = false } -srml-support = { version = "2", path = "../", default-features = false } +runtime-io ={ package = "sr-io", path = "../../../core/sr-io", default-features = false } +support = { package = "srml-support", version = "2", path = "../", default-features = false } inherents = { package = "substrate-inherents", path = "../../../core/inherents", default-features = false } +sr-primitives = { package = "sr-primitives", path = "../../../core/sr-primitives", default-features = false } primitives = { package = "substrate-primitives", path = "../../../core/primitives", default-features = false } -trybuild = "1" +trybuild = "1.0.17" pretty_assertions = "0.6.1" [features] @@ -19,8 +20,9 @@ default = ["std"] std = [ "serde/std", "codec/std", - "runtime_io/std", - "srml-support/std", + "runtime-io/std", + "support/std", "inherents/std", "primitives/std", + "sr-primitives/std", ] diff --git a/srml/support/test/src/lib.rs b/srml/support/test/src/lib.rs index a7a869cf8794d7855697b6c7d3066c21b32533bb..b65bc43cbb5a8b2ca728ea7c3d419d34314222f1 100644 --- a/srml/support/test/src/lib.rs +++ b/srml/support/test/src/lib.rs @@ -14,11 +14,5 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Test crate for srml_support. Allow to make use of `srml_support::decl_storage`. +//! Test crate for srml_support. Allow to make use of `support::decl_storage`. //! See tests directory. - -#[test] -fn reserved_keyword() { - let t = trybuild::TestCases::new(); - t.compile_fail("tests/reserved_keyword/*.rs"); -} diff --git a/srml/support/src/storage/storage_items.rs b/srml/support/test/tests/decl_storage.rs similarity index 52% rename from srml/support/src/storage/storage_items.rs rename to srml/support/test/tests/decl_storage.rs index 06cb8fc55b5cd7c3c7bc64aa03b0509799172257..c9dd96791b16443b72fe02f782a3995ec82e0806 100644 --- a/srml/support/src/storage/storage_items.rs +++ b/srml/support/test/tests/decl_storage.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -14,372 +14,71 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Strongly typed wrappers around values in storage. -//! -//! This crate exports a macro `storage_items!` and traits describing behavior of generated -//! structs. -//! -//! Three kinds of data types are currently supported: -//! - values -//! - maps -//! -//! # Examples: -//! -//! ```rust -//! #[macro_use] -//! extern crate srml_support; -//! -//! type AuthorityId = [u8; 32]; -//! type Balance = u64; -//! pub type SessionKey = [u8; 32]; -//! -//! storage_items! { -//! // public value -//! pub Value: b"putd_key" => SessionKey; -//! // private map. -//! Balances: b"private_map:" => map [AuthorityId => Balance]; -//! } -//! -//!# fn main() { } -//! ``` - -#[doc(hidden)] -pub use crate::rstd::borrow::Borrow; -#[doc(hidden)] -pub use crate::rstd::marker::PhantomData; -#[doc(hidden)] -pub use crate::rstd::boxed::Box; - -// FIXME #1466 Remove this in favor of `decl_storage` macro. -/// Declares strongly-typed wrappers around codec-compatible types in storage. -#[macro_export] -macro_rules! storage_items { - // simple values - ($name:ident : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); - storage_items!($($t)*); - }; - - ($name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $key:expr => $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $key:expr => default $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $key => $ty); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $key:expr => required $ty:ty; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $key => $ty); - storage_items!($($t)*); - }; - - // maps - ($name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() () (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) () (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - - ($name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $prefix:expr => map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (OPTION_TYPE Option<$ty>) (get) (take) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $prefix:expr => default map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (get_or_default) (take_or_default) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - ($name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!(() ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - (pub $name:ident get($getfn:ident) : $prefix:expr => required map [$kty:ty => $ty:ty]; $($t:tt)*) => { - $crate::__storage_items_internal!((pub) ($getfn) (RAW_TYPE $ty) (require) (take_or_panic) $name: $prefix => map [$kty => $ty]); - storage_items!($($t)*); - }; - - () => () -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __storage_items_internal { - // generator for values. - (($($vis:tt)*) ($get_fn:ident) ($wraptype:ident $gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => { - $crate::__storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($getter) ($taker) $name : $key => $ty } - pub fn $get_fn() -> $gettype { <$name as $crate::storage::hashed::generator::StorageValue<$ty>> :: get(&$crate::storage::RuntimeStorage) } - }; - (($($vis:tt)*) () ($wraptype:ident $gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $key:expr => $ty:ty) => { - $($vis)* struct $name; - - impl $crate::storage::hashed::generator::StorageValue<$ty> for $name { - type Query = $gettype; - - /// Get the storage key. - fn key() -> &'static [u8] { - $key - } - - /// Load the value from the provided storage instance. - fn get>(storage: &S) -> Self::Query { - storage.$getter($key) - } - - /// Take a value from storage, removing it afterwards. - fn take>(storage: &mut S) -> Self::Query { - storage.$taker($key) - } - - /// Mutate this value. - fn mutate R, S: $crate::HashedStorage<$crate::Twox128>>(f: F, storage: &mut S) -> R { - let mut val = >::get(storage); - - let ret = f(&mut val); - - $crate::__handle_wrap_internal!($wraptype { - // raw type case - >::put(&val, storage) - } { - // Option<> type case - match val { - Some(ref val) => >::put(&val, storage), - None => >::kill(storage), - } - }); - - ret - } - } - }; - // generator for maps. - (($($vis:tt)*) ($get_fn:ident) ($wraptype:ident $gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => { - $crate::__storage_items_internal!{ ($($vis)*) () ($wraptype $gettype) ($getter) ($taker) $name : $prefix => map [$kty => $ty] } - pub fn $get_fn>(key: K) -> $gettype { - <$name as $crate::storage::hashed::generator::StorageMap<$kty, $ty>> :: get(key.borrow(), &$crate::storage::RuntimeStorage) - } - }; - (($($vis:tt)*) () ($wraptype:ident $gettype:ty) ($getter:ident) ($taker:ident) $name:ident : $prefix:expr => map [$kty:ty => $ty:ty]) => { - $($vis)* struct $name; - - impl $crate::storage::hashed::generator::StorageMap<$kty, $ty> for $name { - type Query = $gettype; - - type Hasher = $crate::Blake2_256; - - /// Get the prefix key in storage. - fn prefix() -> &'static [u8] { - $prefix - } - - /// Get the storage key used to fetch a value corresponding to a specific key. - fn key_for(x: &$kty) -> $crate::rstd::vec::Vec { - let mut key = $prefix.to_vec(); - $crate::codec::Encode::encode_to(x, &mut key); - key - } - - /// Load the value associated with the given key from the map. - fn get>(key: &$kty, storage: &S) -> Self::Query { - let key = <$name as $crate::storage::hashed::generator::StorageMap<$kty, $ty>>::key_for(key); - storage.$getter(&key[..]) - } - - /// Take the value, reading and removing it. - fn take>(key: &$kty, storage: &mut S) -> Self::Query { - let key = <$name as $crate::storage::hashed::generator::StorageMap<$kty, $ty>>::key_for(key); - storage.$taker(&key[..]) - } - - /// Mutate the value under a key. - fn mutate R, S: $crate::HashedStorage>(key: &$kty, f: F, storage: &mut S) -> R { - let mut val = >::take(key, storage); - - let ret = f(&mut val); - - $crate::__handle_wrap_internal!($wraptype { - // raw type case - >::insert(key, &val, storage) - } { - // Option<> type case - match val { - Some(ref val) => >::insert(key, &val, storage), - None => >::remove(key, storage), - } - }); - - ret - } - } - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __handle_wrap_internal { - (RAW_TYPE { $($raw:tt)* } { $($option:tt)* }) => { - $($raw)*; - }; - (OPTION_TYPE { $($raw:tt)* } { $($option:tt)* }) => { - $($option)*; - }; -} - -// FIXME: revisit this idiom once we get `type`s in `impl`s. -/*impl Module { - type Now = super::Now; -}*/ - #[cfg(test)] // Do not complain about unused `dispatch` and `dispatch_aux`. #[allow(dead_code)] mod tests { - use std::collections::HashMap; - use super::*; - use crate::metadata::*; - use crate::metadata::StorageHasher; - use crate::rstd::marker::PhantomData; - use crate::storage::hashed::generator::*; - - storage_items! { - Value: b"a" => u32; - Map: b"c:" => map [u32 => [u8; 32]]; - } - - #[test] - fn value() { - let mut storage = HashMap::new(); - assert!(Value::get(&storage).is_none()); - Value::put(&100_000, &mut storage); - assert_eq!(Value::get(&storage), Some(100_000)); - Value::kill(&mut storage); - assert!(Value::get(&storage).is_none()); - } + use support::metadata::*; + use support::metadata::StorageHasher; + use support::rstd::marker::PhantomData; + use support::codec::{Encode, Decode, EncodeLike}; - #[test] - fn map() { - let mut storage = HashMap::new(); - assert!(Map::get(&5, &storage).is_none()); - Map::insert(&5, &[1; 32], &mut storage); - assert_eq!(Map::get(&5, &storage), Some([1; 32])); - assert_eq!(Map::take(&5, &mut storage), Some([1; 32])); - assert!(Map::get(&5, &storage).is_none()); - assert!(Map::get(&999, &storage).is_none()); + support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} } pub trait Trait { - type Origin: crate::codec::Encode + crate::codec::Decode + ::std::default::Default; + type Origin: Encode + Decode + EncodeLike + std::default::Default; type BlockNumber; } - decl_module! { - pub struct Module for enum Call where origin: T::Origin {} - } - - crate::decl_storage! { + support::decl_storage! { trait Store for Module as TestStorage { // non-getters: pub / $default /// Hello, this is doc! - U32 : Option = Some(3); + U32 : Option; pub PUBU32 : Option; - U32MYDEF : Option = None; - pub PUBU32MYDEF : Option = Some(3); + U32MYDEF : Option; + pub PUBU32MYDEF : Option; // getters: pub / $default // we need at least one type which uses T, otherwise GenesisConfig will complain. - GETU32 get(u32_getter): T::Origin; - pub PUBGETU32 get(pub_u32_getter) build(|config: &GenesisConfig| config.u32_getter_with_config): u32; - GETU32WITHCONFIG get(u32_getter_with_config) config(): u32; - pub PUBGETU32WITHCONFIG get(pub_u32_getter_with_config) config(): u32; - GETU32MYDEF get(u32_getter_mydef): Option = Some(4); - pub PUBGETU32MYDEF get(pub_u32_getter_mydef) config(): u32 = 3; - GETU32WITHCONFIGMYDEF get(u32_getter_with_config_mydef) config(): u32 = 2; - pub PUBGETU32WITHCONFIGMYDEF get(pub_u32_getter_with_config_mydef) config(): u32 = 1; - PUBGETU32WITHCONFIGMYDEFOPT get(pub_u32_getter_with_config_mydef_opt) config(): Option = Some(100); + GETU32 get(fn u32_getter): T::Origin; + pub PUBGETU32 get(fn pub_u32_getter) build(|config: &GenesisConfig| config.u32_getter_with_config): u32; + GETU32WITHCONFIG get(fn u32_getter_with_config) config(): u32; + pub PUBGETU32WITHCONFIG get(fn pub_u32_getter_with_config) config(): u32; + GETU32MYDEF get(fn u32_getter_mydef): Option; + pub PUBGETU32MYDEF get(fn pub_u32_getter_mydef) config(): u32 = 3; + GETU32WITHCONFIGMYDEF get(fn u32_getter_with_config_mydef) config(): u32 = 2; + pub PUBGETU32WITHCONFIGMYDEF get(fn pub_u32_getter_with_config_mydef) config(): u32 = 1; + PUBGETU32WITHCONFIGMYDEFOPT get(fn pub_u32_getter_with_config_mydef_opt) config(): Option; // map non-getters: pub / $default MAPU32 : map u32 => Option; pub PUBMAPU32 : map u32 => Option; - MAPU32MYDEF : map u32 => Option = None; - pub PUBMAPU32MYDEF : map u32 => Option = Some("hello".into()); + MAPU32MYDEF : map u32 => Option; + pub PUBMAPU32MYDEF : map u32 => Option; // map getters: pub / $default - GETMAPU32 get(map_u32_getter): map u32 => String; - pub PUBGETMAPU32 get(pub_map_u32_getter): map u32 => String; + GETMAPU32 get(fn map_u32_getter): map u32 => String; + pub PUBGETMAPU32 get(fn pub_map_u32_getter): map u32 => String; - GETMAPU32MYDEF get(map_u32_getter_mydef): map u32 => String = "map".into(); - pub PUBGETMAPU32MYDEF get(pub_map_u32_getter_mydef): map u32 => String = "pubmap".into(); + GETMAPU32MYDEF get(fn map_u32_getter_mydef): map u32 => String = "map".into(); + pub PUBGETMAPU32MYDEF get(fn pub_map_u32_getter_mydef): map u32 => String = "pubmap".into(); // linked map LINKEDMAPU32 : linked_map u32 => Option; - pub PUBLINKEDMAPU32MYDEF : linked_map u32 => Option = Some("hello".into()); - GETLINKEDMAPU32 get(linked_map_u32_getter): linked_map u32 => String; - pub PUBGETLINKEDMAPU32MYDEF get(pub_linked_map_u32_getter_mydef): linked_map u32 => String = "pubmap".into(); + pub PUBLINKEDMAPU32MYDEF : linked_map u32 => Option; + GETLINKEDMAPU32 get(fn linked_map_u32_getter): linked_map u32 => String; + pub PUBGETLINKEDMAPU32MYDEF get(fn pub_linked_map_u32_getter_mydef): linked_map u32 => String = "pubmap".into(); COMPLEXTYPE1: ::std::vec::Vec<::Origin>; COMPLEXTYPE2: (Vec)>>, u32); COMPLEXTYPE3: ([u32;25]); } add_extra_genesis { - build(|_, _| {}); + build(|_| {}); } } @@ -726,7 +425,7 @@ mod tests { assert_eq!(config.pub_u32_getter_mydef, 3u32); assert_eq!(config.u32_getter_with_config_mydef, 2u32); assert_eq!(config.pub_u32_getter_with_config_mydef, 1u32); - assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 100u32); + assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 0u32); } } @@ -739,13 +438,13 @@ mod test2 { type BlockNumber; } - decl_module! { + support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } type PairOf = (T, T); - crate::decl_storage! { + support::decl_storage! { trait Store for Module as TestStorage { SingleDef : u32; PairDef : PairOf; @@ -755,7 +454,7 @@ mod test2 { add_extra_genesis { config(_marker) : ::std::marker::PhantomData; config(extra_field) : u32 = 32; - build(|_, _| {}); + build(|_| {}); } } @@ -774,12 +473,12 @@ mod test3 { type Origin; type BlockNumber; } - decl_module! { + support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } - crate::decl_storage! { + support::decl_storage! { trait Store for Module as Test { - Foo get(foo) config(initial_foo): u32; + Foo get(fn foo) config(initial_foo): u32; } } @@ -795,18 +494,37 @@ mod test3 { #[cfg(test)] #[allow(dead_code)] -mod test_map_vec_append { +mod test_append_and_len { + use runtime_io::TestExternalities; + use codec::{Encode, Decode}; + pub trait Trait { type Origin; type BlockNumber; } - decl_module! { + + support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } - crate::decl_storage! { + + #[derive(PartialEq, Eq, Clone, Encode, Decode)] + struct NoDef(u32); + + support::decl_storage! { trait Store for Module as Test { + NoDefault: Option; + JustVec: Vec; + JustVecWithDefault: Vec = vec![6, 9]; + OptionVec: Option>; + MapVec: map u32 => Vec; + MapVecWithDefault: map u32 => Vec = vec![6, 9]; + OptionMapVec: map u32 => Option>; + + LinkedMapVec: linked_map u32 => Vec; + LinkedMapVecWithDefault: linked_map u32 => Vec = vec![6, 9]; + OptionLinkedMapVec: linked_map u32 => Option>; } } @@ -817,21 +535,108 @@ mod test_map_vec_append { type BlockNumber = u32; } + #[test] + fn default_for_option() { + TestExternalities::default().execute_with(|| { + assert_eq!(OptionVec::get(), None); + assert_eq!(JustVec::get(), vec![]); + }); + } + #[test] fn append_works() { - use crate::storage::{AppendableStorageMap, StorageMap, StorageValue}; - use runtime_io::{with_externalities, TestExternalities}; + TestExternalities::default().execute_with(|| { + let _ = MapVec::append(1, [1, 2, 3].iter()); + let _ = MapVec::append(1, [4, 5].iter()); + assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); + + let _ = JustVec::append([1, 2, 3].iter()); + let _ = JustVec::append([4, 5].iter()); + assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); + }); + } - with_externalities(&mut TestExternalities::default(), || { - let _ = MapVec::append(1, &[1, 2, 3]); - let _ = MapVec::append(1, &[4, 5]); + #[test] + fn append_works_for_default() { + TestExternalities::default().execute_with(|| { + assert_eq!(JustVecWithDefault::get(), vec![6, 9]); + let _ = JustVecWithDefault::append([1].iter()); + assert_eq!(JustVecWithDefault::get(), vec![6, 9, 1]); + + assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); + let _ = MapVecWithDefault::append(0, [1].iter()); + assert_eq!(MapVecWithDefault::get(0), vec![6, 9, 1]); + + assert_eq!(OptionVec::get(), None); + let _ = OptionVec::append([1].iter()); + assert_eq!(OptionVec::get(), Some(vec![1])); + }); + } + + #[test] + fn append_or_put_works() { + TestExternalities::default().execute_with(|| { + let _ = MapVec::append_or_insert(1, &[1, 2, 3][..]); + let _ = MapVec::append_or_insert(1, &[4, 5][..]); assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); - let _ = JustVec::append(&[1, 2, 3]); - let _ = JustVec::append(&[4, 5]); + let _ = JustVec::append_or_put(&[1, 2, 3][..]); + let _ = JustVec::append_or_put(&[4, 5][..]); assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); + + let _ = OptionVec::append_or_put(&[1, 2, 3][..]); + let _ = OptionVec::append_or_put(&[4, 5][..]); + assert_eq!(OptionVec::get(), Some(vec![1, 2, 3, 4, 5])); + }); + } + + #[test] + fn len_works() { + TestExternalities::default().execute_with(|| { + JustVec::put(&vec![1, 2, 3, 4]); + OptionVec::put(&vec![1, 2, 3, 4, 5]); + MapVec::insert(1, &vec![1, 2, 3, 4, 5, 6]); + LinkedMapVec::insert(2, &vec![1, 2, 3]); + + assert_eq!(JustVec::decode_len().unwrap(), 4); + assert_eq!(OptionVec::decode_len().unwrap(), 5); + assert_eq!(MapVec::decode_len(1).unwrap(), 6); + assert_eq!(LinkedMapVec::decode_len(2).unwrap(), 3); }); } -} + #[test] + fn len_works_for_default() { + TestExternalities::default().execute_with(|| { + // vec + assert_eq!(JustVec::get(), vec![]); + assert_eq!(JustVec::decode_len(), Ok(0)); + assert_eq!(JustVecWithDefault::get(), vec![6, 9]); + assert_eq!(JustVecWithDefault::decode_len(), Ok(2)); + + assert_eq!(OptionVec::get(), None); + assert_eq!(OptionVec::decode_len(), Ok(0)); + + // map + assert_eq!(MapVec::get(0), vec![]); + assert_eq!(MapVec::decode_len(0), Ok(0)); + + assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); + assert_eq!(MapVecWithDefault::decode_len(0), Ok(2)); + + assert_eq!(OptionMapVec::get(0), None); + assert_eq!(OptionMapVec::decode_len(0), Ok(0)); + + // linked map + assert_eq!(LinkedMapVec::get(0), vec![]); + assert_eq!(LinkedMapVec::decode_len(0), Ok(0)); + + assert_eq!(LinkedMapVecWithDefault::get(0), vec![6, 9]); + assert_eq!(LinkedMapVecWithDefault::decode_len(0), Ok(2)); + + assert_eq!(OptionLinkedMapVec::get(0), None); + assert_eq!(OptionLinkedMapVec::decode_len(0), Ok(0)); + }); + } +} diff --git a/srml/support/test/tests/decl_storage_ui.rs b/srml/support/test/tests/decl_storage_ui.rs new file mode 100644 index 0000000000000000000000000000000000000000..32c15eb390f8b80f860434cf13b1db744913d095 --- /dev/null +++ b/srml/support/test/tests/decl_storage_ui.rs @@ -0,0 +1,24 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[test] +fn decl_storage_ui() { + // As trybuild is using `cargo check`, we don't need the real WASM binaries. + std::env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/decl_storage_ui/*.rs"); +} diff --git a/core/consensus/common/primitives/src/lib.rs b/srml/support/test/tests/decl_storage_ui/config_duplicate.rs similarity index 66% rename from core/consensus/common/primitives/src/lib.rs rename to srml/support/test/tests/decl_storage_ui/config_duplicate.rs index f6c1800081f90c4f07b51d20e4ffb8f368d2155b..bdd7da7449aa80686313aca3f7b4a25a1d2fad33 100644 --- a/core/consensus/common/primitives/src/lib.rs +++ b/srml/support/test/tests/decl_storage_ui/config_duplicate.rs @@ -14,18 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Common consensus primitives. - -#![cfg_attr(not(feature = "std"), no_std)] +pub trait Trait { + type Origin; + type BlockNumber: codec::Codec + codec::EncodeLike + Default + Clone; +} -use codec::Codec; -use client::decl_runtime_apis; -use rstd::vec::Vec; +support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} +} -decl_runtime_apis! { - /// Common consensus runtime api. - pub trait ConsensusApi { - /// Returns the set of authorities of the currently active consensus mechanism. - fn authorities() -> Vec; +support::decl_storage!{ + trait Store for Module as FinalKeysNone { + pub Value config(value): u32; + pub Value2 config(value): u32; } } + +fn main() {} diff --git a/srml/support/test/tests/decl_storage_ui/config_duplicate.stderr b/srml/support/test/tests/decl_storage_ui/config_duplicate.stderr new file mode 100644 index 0000000000000000000000000000000000000000..761e3f3b7982492444854ec669094eb948f0c409 --- /dev/null +++ b/srml/support/test/tests/decl_storage_ui/config_duplicate.stderr @@ -0,0 +1,5 @@ +error: `config()`/`get()` with the same name already defined. + --> $DIR/config_duplicate.rs:29:21 + | +29 | pub Value2 config(value): u32; + | ^^^^^ diff --git a/srml/support/test/tests/decl_storage_ui/config_get_duplicate.rs b/srml/support/test/tests/decl_storage_ui/config_get_duplicate.rs new file mode 100644 index 0000000000000000000000000000000000000000..2bf8df45322ccd037091d305b522b65ecf9dd391 --- /dev/null +++ b/srml/support/test/tests/decl_storage_ui/config_get_duplicate.rs @@ -0,0 +1,33 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub trait Trait { + type Origin; + type BlockNumber: codec::Codec + codec::EncodeLike + Default + Clone; +} + +support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} +} + +support::decl_storage!{ + trait Store for Module as FinalKeysNone { + pub Value get(fn value) config(): u32; + pub Value2 config(value): u32; + } +} + +fn main() {} diff --git a/srml/support/test/tests/decl_storage_ui/config_get_duplicate.stderr b/srml/support/test/tests/decl_storage_ui/config_get_duplicate.stderr new file mode 100644 index 0000000000000000000000000000000000000000..34d040f4e14f19a8fbfc1e904675ec6dacc5e963 --- /dev/null +++ b/srml/support/test/tests/decl_storage_ui/config_get_duplicate.stderr @@ -0,0 +1,5 @@ +error: `config()`/`get()` with the same name already defined. + --> $DIR/config_get_duplicate.rs:29:21 + | +29 | pub Value2 config(value): u32; + | ^^^^^ diff --git a/srml/support/test/tests/decl_storage_ui/get_duplicate.rs b/srml/support/test/tests/decl_storage_ui/get_duplicate.rs new file mode 100644 index 0000000000000000000000000000000000000000..41ca708352e8b76a8279d2bcc3655a25fcd1ff0f --- /dev/null +++ b/srml/support/test/tests/decl_storage_ui/get_duplicate.rs @@ -0,0 +1,33 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +pub trait Trait { + type Origin; + type BlockNumber: codec::Codec + codec::EncodeLike + Default + Clone; +} + +support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} +} + +support::decl_storage!{ + trait Store for Module as FinalKeysNone { + pub Value get(fn value) config(): u32; + pub Value2 get(fn value) config(): u32; + } +} + +fn main() {} diff --git a/srml/support/test/tests/decl_storage_ui/get_duplicate.stderr b/srml/support/test/tests/decl_storage_ui/get_duplicate.stderr new file mode 100644 index 0000000000000000000000000000000000000000..130244196f67e03bb40de703fbb127d7bdecbfc8 --- /dev/null +++ b/srml/support/test/tests/decl_storage_ui/get_duplicate.stderr @@ -0,0 +1,5 @@ +error: `config()`/`get()` with the same name already defined. + --> $DIR/get_duplicate.rs:29:21 + | +29 | pub Value2 get(fn value) config(): u32; + | ^^^^^ diff --git a/srml/support/test/tests/final_keys.rs b/srml/support/test/tests/final_keys.rs index 9c770075c46493c0a4bde76d74fc520fa13b43f5..44a6b540a7a0e32896dab3aa267c7b2b15b7aeea 100644 --- a/srml/support/test/tests/final_keys.rs +++ b/srml/support/test/tests/final_keys.rs @@ -14,83 +14,211 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use runtime_io::{with_externalities, Blake2Hasher}; -use srml_support::{StorageValue, StorageMap, StorageDoubleMap}; -use srml_support::storage::unhashed; -use codec::{Encode, Decode}; - -pub trait Trait { - type Origin; - type BlockNumber: Encode + Decode + Default + Clone; -} +use runtime_io::with_storage; +use support::storage::unhashed; +use codec::Encode; +use support::{StorageDoubleMap, StorageLinkedMap, StorageMap, StorageValue}; -srml_support::decl_module! { - pub struct Module for enum Call where origin: T::Origin {} -} +mod no_instance { + use codec::{Encode, Decode, EncodeLike}; + + pub trait Trait { + type Origin; + type BlockNumber: Encode + Decode + EncodeLike + Default + Clone; + } -srml_support::decl_storage!{ - trait Store for Module as FinalKeys { - pub Value config(value): u32; + support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + + support::decl_storage!{ + trait Store for Module as FinalKeysNone { + pub Value config(value): u32; - pub Map: map u32 => u32; - pub Map2: map hasher(twox_128) u32 => u32; + pub Map: map u32 => u32; + pub Map2: map hasher(twox_128) u32 => u32; - pub LinkedMap: linked_map u32 => u32; - pub LinkedMap2: linked_map hasher(twox_128) u32 => u32; + pub LinkedMap: linked_map u32 => u32; + pub LinkedMap2: linked_map hasher(twox_128) u32 => u32; - pub DoubleMap: double_map u32, blake2_256(u32) => u32; - pub DoubleMap2: double_map hasher(twox_128) u32, blake2_128(u32) => u32; + pub DoubleMap: double_map u32, blake2_256(u32) => u32; + pub DoubleMap2: double_map hasher(twox_128) u32, blake2_128(u32) => u32; - pub Foo get(foo) config(): Option; - pub Foo2 get(foo2) config(): double_map u32, blake2_256(T::BlockNumber) => Option; + pub TestGenericValue get(fn test_generic_value) config(): Option; + pub TestGenericDoubleMap get(fn foo2) config(test_generic_double_map): + double_map u32, blake2_256(T::BlockNumber) => Option; + } } } -struct Test; -impl Trait for Test { - type BlockNumber = u32; - type Origin = u32; +mod instance { + pub trait Trait: super::no_instance::Trait {} + + support::decl_module! { + pub struct Module, I: Instantiable = DefaultInstance> + for enum Call where origin: T::Origin {} + } + + support::decl_storage!{ + trait Store for Module, I: Instantiable = DefaultInstance> + as FinalKeysSome + { + pub Value config(value): u32; + + pub Map: map u32 => u32; + pub Map2: map hasher(twox_128) u32 => u32; + + pub LinkedMap: linked_map u32 => u32; + pub LinkedMap2: linked_map hasher(twox_128) u32 => u32; + + pub DoubleMap: double_map u32, blake2_256(u32) => u32; + pub DoubleMap2: double_map hasher(twox_128) u32, blake2_128(u32) => u32; + + pub TestGenericValue get(fn test_generic_value) config(): Option; + pub TestGenericDoubleMap get(fn foo2) config(test_generic_double_map): + double_map u32, blake2_256(T::BlockNumber) => Option; + } + add_extra_genesis { + // See `decl_storage` limitation. + config(phantom): core::marker::PhantomData; + } + } } -fn new_test_ext() -> runtime_io::TestExternalities { - GenesisConfig::::default().build_storage().unwrap().into() +#[test] +fn final_keys_no_instance() { + with_storage(&mut Default::default(), || { + no_instance::Value::put(1); + assert_eq!(unhashed::get::(&runtime_io::twox_128(b"FinalKeysNone Value")), Some(1u32)); + + no_instance::Map::insert(1, 2); + let mut k = b"FinalKeysNone Map".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); + + no_instance::Map2::insert(1, 2); + let mut k = b"FinalKeysNone Map2".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); + + let head = b"head of FinalKeysNone LinkedMap".to_vec(); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), None); + + no_instance::LinkedMap::insert(1, 2); + let mut k = b"FinalKeysNone LinkedMap".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), Some(1u32)); + + no_instance::LinkedMap2::insert(1, 2); + let mut k = b"FinalKeysNone LinkedMap2".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); + + no_instance::DoubleMap::insert(&1, &2, &3); + let mut k = b"FinalKeysNone DoubleMap".to_vec(); + k.extend(1u32.encode()); + let mut k = runtime_io::blake2_256(&k).to_vec(); + k.extend(&runtime_io::blake2_256(&2u32.encode())); + assert_eq!(unhashed::get::(&k), Some(3u32)); + + no_instance::DoubleMap2::insert(&1, &2, &3); + let mut k = b"FinalKeysNone DoubleMap2".to_vec(); + k.extend(1u32.encode()); + let mut k = runtime_io::twox_128(&k).to_vec(); + k.extend(&runtime_io::blake2_128(&2u32.encode())); + assert_eq!(unhashed::get::(&k), Some(3u32)); + }); } #[test] -fn final_keys() { - with_externalities(&mut new_test_ext(), || { - Value::put(1); - assert_eq!(unhashed::get::(&runtime_io::twox_128(b"FinalKeys Value")), Some(1u32)); +fn final_keys_default_instance() { + with_storage(&mut Default::default(), || { + >::put(1); + assert_eq!(unhashed::get::(&runtime_io::twox_128(b"FinalKeysSome Value")), Some(1u32)); + + >::insert(1, 2); + let mut k = b"FinalKeysSome Map".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); + + >::insert(1, 2); + let mut k = b"FinalKeysSome Map2".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - Map::insert(1, 2); - let mut k = b"FinalKeys Map".to_vec(); + let head = b"head of FinalKeysSome LinkedMap".to_vec(); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), None); + + >::insert(1, 2); + let mut k = b"FinalKeysSome LinkedMap".to_vec(); k.extend(1u32.encode()); assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), Some(1u32)); - Map2::insert(1, 2); - let mut k = b"FinalKeys Map2".to_vec(); +< instance::LinkedMap2>::insert(1, 2); + let mut k = b"FinalKeysSome LinkedMap2".to_vec(); k.extend(1u32.encode()); assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - LinkedMap::insert(1, 2); - let mut k = b"FinalKeys LinkedMap".to_vec(); + >::insert(&1, &2, &3); + let mut k = b"FinalKeysSome DoubleMap".to_vec(); + k.extend(1u32.encode()); + let mut k = runtime_io::blake2_256(&k).to_vec(); + k.extend(&runtime_io::blake2_256(&2u32.encode())); + assert_eq!(unhashed::get::(&k), Some(3u32)); + + >::insert(&1, &2, &3); + let mut k = b"FinalKeysSome DoubleMap2".to_vec(); + k.extend(1u32.encode()); + let mut k = runtime_io::twox_128(&k).to_vec(); + k.extend(&runtime_io::blake2_128(&2u32.encode())); + assert_eq!(unhashed::get::(&k), Some(3u32)); + }); +} + +#[test] +fn final_keys_instance_2() { + with_storage(&mut Default::default(), || { + >::put(1); + assert_eq!( + unhashed::get::(&runtime_io::twox_128(b"Instance2FinalKeysSome Value")), + Some(1u32) + ); + + >::insert(1, 2); + let mut k = b"Instance2FinalKeysSome Map".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); + + >::insert(1, 2); + let mut k = b"Instance2FinalKeysSome Map2".to_vec(); + k.extend(1u32.encode()); + assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); + + let head = b"head of Instance2FinalKeysSome LinkedMap".to_vec(); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), None); + + >::insert(1, 2); + let mut k = b"Instance2FinalKeysSome LinkedMap".to_vec(); k.extend(1u32.encode()); assert_eq!(unhashed::get::(&runtime_io::blake2_256(&k)), Some(2u32)); + assert_eq!(unhashed::get::(&runtime_io::blake2_256(&head)), Some(1u32)); - LinkedMap2::insert(1, 2); - let mut k = b"FinalKeys LinkedMap2".to_vec(); + >::insert(1, 2); + let mut k = b"Instance2FinalKeysSome LinkedMap2".to_vec(); k.extend(1u32.encode()); assert_eq!(unhashed::get::(&runtime_io::twox_128(&k)), Some(2u32)); - DoubleMap::insert(&1, &2, &3); - let mut k = b"FinalKeys DoubleMap".to_vec(); + >::insert(&1, &2, &3); + let mut k = b"Instance2FinalKeysSome DoubleMap".to_vec(); k.extend(1u32.encode()); let mut k = runtime_io::blake2_256(&k).to_vec(); k.extend(&runtime_io::blake2_256(&2u32.encode())); assert_eq!(unhashed::get::(&k), Some(3u32)); - DoubleMap2::insert(&1, &2, &3); - let mut k = b"FinalKeys DoubleMap2".to_vec(); + >::insert(&1, &2, &3); + let mut k = b"Instance2FinalKeysSome DoubleMap2".to_vec(); k.extend(1u32.encode()); let mut k = runtime_io::twox_128(&k).to_vec(); k.extend(&runtime_io::blake2_128(&2u32.encode())); diff --git a/srml/support/test/tests/genesisconfig.rs b/srml/support/test/tests/genesisconfig.rs index b190fa8b747f3e161ff956930bbcc86689f2fea1..e945c774c0d07e97cc5186316fe77425748d2d23 100644 --- a/srml/support/test/tests/genesisconfig.rs +++ b/srml/support/test/tests/genesisconfig.rs @@ -15,18 +15,18 @@ // along with Substrate. If not, see . pub trait Trait { - type BlockNumber: codec::Codec + Default; - type Origin; + type BlockNumber: codec::Codec + codec::EncodeLike + Default; + type Origin; } -srml_support::decl_module! { - pub struct Module for enum Call where origin: T::Origin {} +support::decl_module! { + pub struct Module for enum Call where origin: T::Origin {} } -srml_support::decl_storage! { - trait Store for Module as Example { - pub AppendableDM config(t): double_map u32, blake2_256(T::BlockNumber) => Vec; - } +support::decl_storage! { + trait Store for Module as Example { + pub AppendableDM config(t): double_map u32, blake2_256(T::BlockNumber) => Vec; + } } struct Test; diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs index 440fb9e779996b5ae5e7ce77bb5cb3787731e2a7..282fb9a6e299f149aedcb61bf2c83c10310020c0 100644 --- a/srml/support/test/tests/instance.rs +++ b/srml/support/test/tests/instance.rs @@ -13,21 +13,21 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . + #![recursion_limit="128"] -use runtime_io::{with_externalities, Blake2Hasher}; -use srml_support::{ +use sr_primitives::{generic, BuildStorage, traits::{BlakeTwo256, Block as _, Verify}}; +use support::{ Parameter, traits::Get, parameter_types, - sr_primitives::{generic, BuildStorage, traits::{BlakeTwo256, Block as _, Verify}}, metadata::{ DecodeDifferent, StorageMetadata, StorageEntryModifier, StorageEntryType, DefaultByteGetter, - StorageEntryMetadata, StorageHasher + StorageEntryMetadata, StorageHasher, }, + StorageValue, StorageMap, StorageLinkedMap, StorageDoubleMap, }; use inherents::{ ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError }; -use srml_support::{StorageValue, StorageMap, StorageDoubleMap, EnumerableStorageMap}; use primitives::{H256, sr25519}; mod system; @@ -45,17 +45,17 @@ mod module1 { type Event: From> + Into<::Event>; type Origin: From>; type SomeParameter: Get; - type GenericType: Default + Clone + codec::Codec; + type GenericType: Default + Clone + codec::Codec + codec::EncodeLike; } - srml_support::decl_module! { + support::decl_module! { pub struct Module, I: InstantiableThing> for enum Call where origin: ::Origin, T::BlockNumber: From { fn offchain_worker() {} - fn deposit_event() = default; + fn deposit_event() = default; fn one(origin) { system::ensure_root(origin)?; @@ -64,7 +64,7 @@ mod module1 { } } - srml_support::decl_storage! { + support::decl_storage! { trait Store for Module, I: InstantiableThing> as Module1 where T::BlockNumber: From + std::fmt::Display { @@ -75,21 +75,20 @@ mod module1 { add_extra_genesis { config(test) : T::BlockNumber; - build(|_, config: &Self| { + build(|config: &Self| { println!("{}", config.test); }); } } - srml_support::decl_event! { + support::decl_event! { pub enum Event where Phantom = std::marker::PhantomData { _Phantom(Phantom), AnotherVariant(u32), } } - #[derive(PartialEq, Eq, Clone)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] pub enum Origin, I> where T::BlockNumber: From { Members(u32), _Phantom(std::marker::PhantomData<(T, I)>), @@ -128,15 +127,15 @@ mod module2 { impl, I: Instance> Currency for Module {} - srml_support::decl_module! { + support::decl_module! { pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { - fn deposit_event() = default; + fn deposit_event() = default; } } - srml_support::decl_storage! { + support::decl_storage! { trait Store for Module, I: Instance=DefaultInstance> as Module2 { pub Value config(value): T::Amount; pub Map config(map): map u64 => u64; @@ -145,14 +144,13 @@ mod module2 { } } - srml_support::decl_event! { + support::decl_event! { pub enum Event where Amount = >::Amount { Variant(Amount), } } - #[derive(PartialEq, Eq, Clone)] - #[cfg_attr(feature = "std", derive(Debug))] + #[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] pub enum Origin, I=DefaultInstance> { Members(u32), _Phantom(std::marker::PhantomData<(T, I)>), @@ -185,7 +183,7 @@ mod module3 { type Currency2: Currency; } - srml_support::decl_module! { + support::decl_module! { pub struct Module for enum Call where origin: ::Origin {} } } @@ -244,7 +242,7 @@ impl system::Trait for Runtime { type Event = Event; } -srml_support::construct_runtime!( +support::construct_runtime!( pub enum Runtime where Block = Block, NodeBlock = Block, @@ -275,7 +273,7 @@ pub type Header = generic::Header; pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; -fn new_test_ext() -> runtime_io::TestExternalities { +fn new_test_ext() -> runtime_io::TestExternalities { GenesisConfig{ module1_Instance1: Some(module1::GenesisConfig { value: 3, @@ -304,58 +302,32 @@ fn new_test_ext() -> runtime_io::TestExternalities { #[test] fn storage_instance_independance() { - with_externalities(&mut new_test_ext(), || { - let mut map = std::collections::btree_map::BTreeMap::new(); - for key in [ - module2::Value::::key().to_vec(), - module2::Value::::key().to_vec(), - module2::Value::::key().to_vec(), - module2::Value::::key().to_vec(), - module2::Map::::prefix().to_vec(), - module2::Map::::prefix().to_vec(), - module2::Map::::prefix().to_vec(), - module2::Map::::prefix().to_vec(), - module2::LinkedMap::::prefix().to_vec(), - module2::LinkedMap::::prefix().to_vec(), - module2::LinkedMap::::prefix().to_vec(), - module2::LinkedMap::::prefix().to_vec(), - module2::DoubleMap::::prefix().to_vec(), - module2::DoubleMap::::prefix().to_vec(), - module2::DoubleMap::::prefix().to_vec(), - module2::DoubleMap::::prefix().to_vec(), - module2::Map::::key_for(0), - module2::Map::::key_for(0).to_vec(), - module2::Map::::key_for(0).to_vec(), - module2::Map::::key_for(0).to_vec(), - module2::LinkedMap::::key_for(0), - module2::LinkedMap::::key_for(0).to_vec(), - module2::LinkedMap::::key_for(0).to_vec(), - module2::LinkedMap::::key_for(0).to_vec(), - module2::Map::::key_for(1), - module2::Map::::key_for(1).to_vec(), - module2::Map::::key_for(1).to_vec(), - module2::Map::::key_for(1).to_vec(), - module2::LinkedMap::::key_for(1), - module2::LinkedMap::::key_for(1).to_vec(), - module2::LinkedMap::::key_for(1).to_vec(), - module2::LinkedMap::::key_for(1).to_vec(), - module2::DoubleMap::::prefix_for(&1), - module2::DoubleMap::::prefix_for(&1).to_vec(), - module2::DoubleMap::::prefix_for(&1).to_vec(), - module2::DoubleMap::::prefix_for(&1).to_vec(), - module2::DoubleMap::::key_for(&1, &1), - module2::DoubleMap::::key_for(&1, &1).to_vec(), - module2::DoubleMap::::key_for(&1, &1).to_vec(), - module2::DoubleMap::::key_for(&1, &1).to_vec(), - ].iter() { - assert!(map.insert(key, ()).is_none()) - } + let mut storage = (std::collections::HashMap::new(), std::collections::HashMap::new()); + runtime_io::with_storage(&mut storage, || { + module2::Value::::put(0); + module2::Value::::put(0); + module2::Value::::put(0); + module2::Value::::put(0); + module2::Map::::insert(0, 0); + module2::Map::::insert(0, 0); + module2::Map::::insert(0, 0); + module2::Map::::insert(0, 0); + module2::LinkedMap::::insert::<_, Vec>(0, vec![]); + module2::LinkedMap::::insert::<_, Vec>(0, vec![]); + module2::LinkedMap::::insert::<_, Vec>(0, vec![]); + module2::LinkedMap::::insert::<_, Vec>(0, vec![]); + module2::DoubleMap::::insert(&0, &0, &0); + module2::DoubleMap::::insert(&0, &0, &0); + module2::DoubleMap::::insert(&0, &0, &0); + module2::DoubleMap::::insert(&0, &0, &0); }); + // 16 storage values + 4 linked_map head. + assert_eq!(storage.0.len(), 16 + 4); } #[test] fn storage_with_instance_basic_operation() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { type Value = module2::Value; type Map = module2::Map; type LinkedMap = module2::LinkedMap; @@ -403,7 +375,7 @@ fn storage_with_instance_basic_operation() { assert_eq!(LinkedMap::get(key), vec![]); assert_eq!(LinkedMap::exists(key), false); assert_eq!(LinkedMap::enumerate().count(), 1); - LinkedMap::insert_ref(key, &vec![1]); + LinkedMap::insert(key, &vec![1]); assert_eq!(LinkedMap::enumerate().count(), 2); let key1 = 1; diff --git a/srml/support/test/tests/issue2219.rs b/srml/support/test/tests/issue2219.rs index cb8b4cef09f0d61ed7b6ea79c6a72a76d385dfad..72e0bc8caf198f5a4519b09dfc9fc02bb4d55ff6 100644 --- a/srml/support/test/tests/issue2219.rs +++ b/srml/support/test/tests/issue2219.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -use srml_support::sr_primitives::generic; -use srml_support::sr_primitives::traits::{BlakeTwo256, Block as _, Verify}; -use srml_support::codec::{Encode, Decode}; +use support::sr_primitives::generic; +use support::sr_primitives::traits::{BlakeTwo256, Block as _, Verify}; +use support::codec::{Encode, Decode}; use primitives::{H256, sr25519}; use serde::{Serialize, Deserialize}; @@ -82,7 +82,7 @@ mod module { pub trait Trait: system::Trait {} - srml_support::decl_module! { + support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } @@ -99,10 +99,10 @@ mod module { } } - srml_support::decl_storage! { + support::decl_storage! { trait Store for Module as Actors { /// requirements to enter and maintain status in roles - pub Parameters get(parameters) build(|config: &GenesisConfig| { + pub Parameters get(fn parameters) build(|config: &GenesisConfig| { if config.enable_storage_role { let storage_params: RoleParameters = Default::default(); vec![(Role::Storage, storage_params)] @@ -112,7 +112,7 @@ mod module { }): map Role => Option>; /// the roles members can enter into - pub AvailableRoles get(available_roles) build(|config: &GenesisConfig| { + pub AvailableRoles get(fn available_roles) build(|config: &GenesisConfig| { if config.enable_storage_role { vec![(Role::Storage)] } else { @@ -121,13 +121,13 @@ mod module { }): Vec; /// Actors list - pub ActorAccountIds get(actor_account_ids) : Vec; + pub ActorAccountIds get(fn actor_account_ids) : Vec; /// actor accounts associated with a role - pub AccountIdsByRole get(account_ids_by_role) : map Role => Vec; + pub AccountIdsByRole get(fn account_ids_by_role) : map Role => Vec; /// tokens locked until given block number - pub Bondage get(bondage) : map T::AccountId => T::BlockNumber; + pub Bondage get(fn bondage) : map T::AccountId => T::BlockNumber; /// First step before enter a role is registering intent with a new account/key. /// This is done by sending a role_entry_request() from the new account. @@ -135,10 +135,10 @@ mod module { /// The account making the request will be bonded and must have /// sufficient balance to cover the minimum stake for the role. /// Bonding only occurs after successful entry into a role. - pub RoleEntryRequests get(role_entry_requests) : Requests; + pub RoleEntryRequests get(fn role_entry_requests) : Requests; /// Entry request expires after this number of blocks - pub RequestLifeTime get(request_life_time) config(request_life_time) : u64 = 0; + pub RequestLifeTime get(fn request_life_time) config(request_life_time) : u64 = 0; } add_extra_genesis { config(enable_storage_role): bool; @@ -164,7 +164,7 @@ impl system::Trait for Runtime { impl module::Trait for Runtime {} -srml_support::construct_runtime!( +support::construct_runtime!( pub enum Runtime where Block = Block, NodeBlock = Block, diff --git a/srml/support/test/tests/reserved_keyword.rs b/srml/support/test/tests/reserved_keyword.rs new file mode 100644 index 0000000000000000000000000000000000000000..898d61b8279e91cc4e569df289de683e51cf111a --- /dev/null +++ b/srml/support/test/tests/reserved_keyword.rs @@ -0,0 +1,24 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[test] +fn reserved_keyword() { + // As trybuild is using `cargo check`, we don't need the real WASM binaries. + std::env::set_var("BUILD_DUMMY_WASM_BINARY", "1"); + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/reserved_keyword/*.rs"); +} diff --git a/srml/support/test/tests/reserved_keyword/on_initialize.rs b/srml/support/test/tests/reserved_keyword/on_initialize.rs index f9c2f5f7f0e5add4bdf3358e3330fec4123321eb..f9604c9487a9eb5098734071dd5740d6ec74f6fe 100644 --- a/srml/support/test/tests/reserved_keyword/on_initialize.rs +++ b/srml/support/test/tests/reserved_keyword/on_initialize.rs @@ -2,7 +2,7 @@ macro_rules! reserved { ($($reserved:ident)*) => { $( mod $reserved { - pub use srml_support::dispatch::Result; + pub use support::dispatch::Result; pub trait Trait { type Origin; @@ -10,14 +10,14 @@ macro_rules! reserved { } pub mod system { - use srml_support::dispatch::Result; + use support::dispatch::Result; pub fn ensure_root(_: R) -> Result { Ok(()) } } - srml_support::decl_module! { + support::decl_module! { pub struct Module for enum Call where origin: T::Origin { fn $reserved(_origin) -> Result { unreachable!() } } @@ -29,5 +29,4 @@ macro_rules! reserved { reserved!(on_finalize on_initialize on_finalise on_initialise offchain_worker deposit_event); -fn main() { -} +fn main() {} diff --git a/srml/support/test/tests/reserved_keyword/on_initialize.stderr b/srml/support/test/tests/reserved_keyword/on_initialize.stderr index 7a37eb66c32acd89f96ef45fa3a88dd9724030c1..13c2ef8d2c8691b7a6a576612683e9c3f963671a 100644 --- a/srml/support/test/tests/reserved_keyword/on_initialize.stderr +++ b/srml/support/test/tests/reserved_keyword/on_initialize.stderr @@ -14,7 +14,7 @@ error: Invalid call fn name: `on_initialize`, name is reserved and doesn't match | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: Invalid call fn name: `on_finalise`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. +error: `on_finalise` was renamed to `on_finalize`. Please rename your function accordingly. --> $DIR/on_initialize.rs:30:1 | 30 | reserved!(on_finalize on_initialize on_finalise on_initialise offchain_worker deposit_event); @@ -22,7 +22,7 @@ error: Invalid call fn name: `on_finalise`, name is reserved and doesn't match e | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: Invalid call fn name: `on_initialise`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. +error: `on_initialise` was renamed to `on_initialize`. Please rename your function accordingly. --> $DIR/on_initialize.rs:30:1 | 30 | reserved!(on_finalize on_initialize on_finalise on_initialise offchain_worker deposit_event); @@ -38,7 +38,7 @@ error: Invalid call fn name: `offchain_worker`, name is reserved and doesn't mat | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: Invalid call fn name: `deposit_event`, name is reserved and doesn't match expected signature, please refer to `decl_module!` documentation to see the appropriate usage, or rename it to an unreserved keyword. +error: `deposit_event` function is reserved and must follow the syntax: `$vis:vis fn deposit_event() = default;` --> $DIR/on_initialize.rs:30:1 | 30 | reserved!(on_finalize on_initialize on_finalise on_initialise offchain_worker deposit_event); diff --git a/srml/support/test/tests/system.rs b/srml/support/test/tests/system.rs index 6483161211afcc3ab232c8d1fcfa2e71dce6e215..2996724f625988feab38795dee5d1c046b98b17a 100644 --- a/srml/support/test/tests/system.rs +++ b/srml/support/test/tests/system.rs @@ -1,32 +1,44 @@ -use srml_support::codec::{Encode, Decode}; +use support::codec::{Encode, Decode, EncodeLike}; pub trait Trait: 'static + Eq + Clone { type Origin: Into, Self::Origin>> + From>; - type BlockNumber: Decode + Encode + Clone + Default; + type BlockNumber: Decode + Encode + EncodeLike + Clone + Default; type Hash; - type AccountId: Encode + Decode; + type AccountId: Encode + EncodeLike + Decode; type Event: From; } -srml_support::decl_module! { +support::decl_module! { pub struct Module for enum Call where origin: T::Origin { - pub fn deposit_event(_event: T::Event) { - } } } -srml_support::decl_event!( +impl Module { + pub fn deposit_event(_event: impl Into) { + } +} + +support::decl_event!( pub enum Event { ExtrinsicSuccess, ExtrinsicFailed, } ); +support::decl_error! { + pub enum Error { + /// Test error documentation + TestError, + /// Error documentation + /// with multiple lines + AnotherError + } +} + /// Origin for the system module. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, sr_primitives::RuntimeDebug)] pub enum RawOrigin { Root, Signed(AccountId), @@ -49,4 +61,4 @@ pub fn ensure_root(o: OuterOrigin) -> Result<(), &'stati where OuterOrigin: Into, OuterOrigin>> { o.into().map(|_| ()).map_err(|_| "bad origin: expected to be a root origin") -} \ No newline at end of file +} diff --git a/srml/system/Cargo.toml b/srml/system/Cargo.toml index 98165556216fc344ae75289fd099d614c486fa06..52570617a1b974a3e3a09bb84c8f05ffdd5776ed 100644 --- a/srml/system/Cargo.toml +++ b/srml/system/Cargo.toml @@ -5,17 +5,19 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } -safe-mix = { version = "1.0", default-features = false} +serde = { version = "1.0.101", optional = true, features = ["derive"] } +safe-mix = { version = "1.0.0", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false } +runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } +sr-version = { path = "../../core/sr-version", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +impl-trait-for-tuples = "0.1.3" [dev-dependencies] -criterion = "0.2" +criterion = "0.2.11" [features] default = ["std"] @@ -25,9 +27,10 @@ std = [ "codec/std", "primitives/std", "rstd/std", - "runtime_io/std", - "srml-support/std", + "runtime-io/std", + "support/std", "sr-primitives/std", + "sr-version/std", ] [[bench]] diff --git a/srml/system/benches/bench.rs b/srml/system/benches/bench.rs index 521123118d274a00f5708a96099d2f0a460f8227..6da02cf9c8cea0edb4d48a9d7534e2e4ed797ada 100644 --- a/srml/system/benches/bench.rs +++ b/srml/system/benches/bench.rs @@ -16,8 +16,7 @@ use criterion::{Criterion, criterion_group, criterion_main, black_box}; use srml_system as system; -use srml_support::{decl_module, decl_event, impl_outer_origin, impl_outer_event}; -use runtime_io::{with_externalities, Blake2Hasher}; +use support::{decl_module, decl_event, impl_outer_origin, impl_outer_event}; use primitives::H256; use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; @@ -51,7 +50,7 @@ impl_outer_event! { } } -srml_support::parameter_types! { +support::parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; @@ -69,25 +68,25 @@ impl system::Trait for Runtime { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); } impl module::Trait for Runtime { type Event = Event; } -fn new_test_ext() -> runtime_io::TestExternalities { +fn new_test_ext() -> runtime_io::TestExternalities { system::GenesisConfig::default().build_storage::().unwrap().into() } fn deposit_events(n: usize) { let mut t = new_test_ext(); - with_externalities(&mut t, || { + t.execute_with(|| { for _ in 0..n { module::Module::::deposit_event( module::Event::Complex(vec![1, 2, 3], 2, 3, 899) diff --git a/srml/system/rpc/Cargo.toml b/srml/system/rpc/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e71e1f588a7ef5ab66e023dfeccfe2f0b57ef2fe --- /dev/null +++ b/srml/system/rpc/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "srml-system-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../../core/client" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +log = "0.4.8" +serde = { version = "1.0.101", features = ["derive"] } +sr-primitives = { path = "../../../core/sr-primitives" } +srml-system-rpc-runtime-api = { path = "./runtime-api" } +substrate-primitives = { path = "../../../core/primitives" } +transaction_pool = { package = "substrate-transaction-pool", path = "../../../core/transaction-pool" } + +[dev-dependencies] +test-client = { package = "substrate-test-runtime-client", path = "../../../core/test-runtime/client" } +env_logger = "0.7.0" +futures03 = { package = "futures-preview", version = "=0.3.0-alpha.19" } diff --git a/srml/system/rpc/runtime-api/Cargo.toml b/srml/system/rpc/runtime-api/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..fc525d8fce2adb9fd1d8cd4adc582461613e322a --- /dev/null +++ b/srml/system/rpc/runtime-api/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "srml-system-rpc-runtime-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../../../core/client", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } + +[features] +default = ["std"] +std = [ + "client/std", + "codec/std", +] diff --git a/srml/system/rpc/runtime-api/src/lib.rs b/srml/system/rpc/runtime-api/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..45af0241e08365f44bfa77e1893d9a3a477e077d --- /dev/null +++ b/srml/system/rpc/runtime-api/src/lib.rs @@ -0,0 +1,34 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime API definition required by System RPC extensions. +//! +//! This API should be imported and implemented by the runtime, +//! of a node that wants to use the custom RPC extension +//! adding System access methods. + +#![cfg_attr(not(feature = "std"), no_std)] + +client::decl_runtime_apis! { + /// The API to query account nonce (aka transaction index). + pub trait AccountNonceApi where + AccountId: codec::Codec, + Index: codec::Codec, + { + /// Get current account nonce of given `AccountId`. + fn account_nonce(account: AccountId) -> Index; + } +} diff --git a/srml/system/rpc/src/lib.rs b/srml/system/rpc/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..c6c0a658fba535bb59bc3aa20de3d382c3d6f3fb --- /dev/null +++ b/srml/system/rpc/src/lib.rs @@ -0,0 +1,158 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! System SRML specific RPC methods. + +use std::sync::Arc; + +use codec::{self, Codec, Encode}; +use client::blockchain::HeaderBackend; +use jsonrpc_core::{Result, Error, ErrorCode}; +use jsonrpc_derive::rpc; +use sr_primitives::{ + generic::BlockId, + traits, +}; +use substrate_primitives::hexdisplay::HexDisplay; +use transaction_pool::txpool::{self, Pool}; + +pub use srml_system_rpc_runtime_api::AccountNonceApi; +pub use self::gen_client::Client as SystemClient; + +/// System RPC methods. +#[rpc] +pub trait SystemApi { + /// Returns the next valid index (aka nonce) for given account. + /// + /// This method takes into consideration all pending transactions + /// currently in the pool and if no transactions are found in the pool + /// it fallbacks to query the index from the runtime (aka. state nonce). + #[rpc(name = "system_accountNextIndex", alias("account_nextIndex"))] + fn nonce(&self, account: AccountId) -> Result; +} + +const RUNTIME_ERROR: i64 = 1; + +/// An implementation of System-specific RPC methods. +pub struct System { + client: Arc, + pool: Arc>, + _marker: std::marker::PhantomData, +} + +impl System { + /// Create new `System` given client and transaction pool. + pub fn new(client: Arc, pool: Arc>) -> Self { + System { + client, + pool, + _marker: Default::default(), + } + } +} + +impl SystemApi for System +where + C: traits::ProvideRuntimeApi, + C: HeaderBackend, + C: Send + Sync + 'static, + C::Api: AccountNonceApi, + P: txpool::ChainApi + Sync + Send + 'static, + Block: traits::Block, + AccountId: Clone + std::fmt::Display + Codec, + Index: Clone + std::fmt::Display + Codec + traits::SimpleArithmetic, +{ + fn nonce(&self, account: AccountId) -> Result { + let api = self.client.runtime_api(); + let best = self.client.info().best_hash; + let at = BlockId::hash(best); + + let nonce = api.account_nonce(&at, account.clone()).map_err(|e| Error { + code: ErrorCode::ServerError(RUNTIME_ERROR), + message: "Unable to query nonce.".into(), + data: Some(format!("{:?}", e).into()), + })?; + + log::debug!(target: "rpc", "State nonce for {}: {}", account, nonce); + // Now we need to query the transaction pool + // and find transactions originating from the same sender. + // + // Since extrinsics are opaque to us, we look for them using + // `provides` tag. And increment the nonce if we find a transaction + // that matches the current one. + let mut current_nonce = nonce.clone(); + let mut current_tag = (account.clone(), nonce.clone()).encode(); + for tx in self.pool.ready() { + log::debug!( + target: "rpc", + "Current nonce to {}, checking {} vs {:?}", + current_nonce, + HexDisplay::from(¤t_tag), + tx.provides.iter().map(|x| format!("{}", HexDisplay::from(x))).collect::>(), + ); + // since transactions in `ready()` need to be ordered by nonce + // it's fine to continue with current iterator. + if tx.provides.get(0) == Some(¤t_tag) { + current_nonce += traits::One::one(); + current_tag = (account.clone(), current_nonce.clone()).encode(); + } + } + + Ok(current_nonce) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use futures03::executor::block_on; + use test_client::{ + runtime::Transfer, + AccountKeyring, + }; + + #[test] + fn should_return_next_nonce_for_some_account() { + // given + let _ = env_logger::try_init(); + let client = Arc::new(test_client::new()); + let pool = Arc::new(Pool::new(Default::default(), transaction_pool::FullChainApi::new(client.clone()))); + + let new_transaction = |nonce: u64| { + let t = Transfer { + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), + amount: 5, + nonce, + }; + t.into_signed_tx() + }; + // Populate the pool + let ext0 = new_transaction(0); + block_on(pool.submit_one(&BlockId::number(0), ext0)).unwrap(); + let ext1 = new_transaction(1); + block_on(pool.submit_one(&BlockId::number(0), ext1)).unwrap(); + + let accounts = System::new(client, pool); + + // when + let nonce = accounts.nonce(AccountKeyring::Alice.into()); + + // then + assert_eq!(nonce.unwrap(), 2); + } +} diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 7127c912a929bbf8464cb2469f9de3a6cfa6c1d4..963909172f96342fe9527ef42d07cbef7fe2898a 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -42,16 +42,33 @@ //! //! See the [`Module`](./struct.Module.html) struct for details of publicly available functions. //! +//! ### Signed Extensions +//! +//! The system module defines the following extensions: +//! +//! - [`CheckWeight`]: Checks the weight and length of the block and ensure that it does not +//! exceed the limits. +//! - [`CheckNonce`]: Checks the nonce of the transaction. Contains a single payload of type +//! `T::Index`. +//! - [`CheckEra`]: Checks the era of the transaction. Contains a single payload of type `Era`. +//! - [`CheckGenesis`]: Checks the provided genesis hash of the transaction. Must be a part of the +//! signed payload of the transaction. +//! - [`CheckVersion`]: Checks that the runtime version is the same as the one encoded in the +//! transaction. +//! +//! Lookup the runtime aggregator file (e.g. `node/runtime`) to see the full list of signed +//! extensions included in a chain. +//! //! ## Usage //! //! ### Prerequisites //! //! Import the System module and derive your module's configuration trait from the system trait. //! -//! ### Example - Get random seed and extrinsic count for the current block +//! ### Example - Get extrinsic count and parent hash for the current block //! //! ``` -//! use srml_support::{decl_module, dispatch::Result}; +//! use support::{decl_module, dispatch::Result}; //! use srml_system::{self as system, ensure_signed}; //! //! pub trait Trait: system::Trait {} @@ -60,8 +77,8 @@ //! pub struct Module for enum Call where origin: T::Origin { //! pub fn system_module_example(origin) -> Result { //! let _sender = ensure_signed(origin)?; -//! let _random_seed = >::random_seed(); //! let _extrinsic_count = >::extrinsic_count(); +//! let _parent_hash = >::parent_hash(); //! Ok(()) //! } //! } @@ -77,53 +94,42 @@ use rstd::prelude::*; #[cfg(any(feature = "std", test))] use rstd::map; use rstd::marker::PhantomData; -use sr_primitives::generic::{self, Era}; -use sr_primitives::Perbill; -use sr_primitives::weights::{ - Weight, DispatchInfo, DispatchClass, WeightMultiplier, SimpleDispatchInfo -}; -use sr_primitives::transaction_validity::{ - ValidTransaction, TransactionPriority, TransactionLongevity +use rstd::fmt::Debug; +use sr_version::RuntimeVersion; +use sr_primitives::{ + RuntimeDebug, + generic::{self, Era}, Perbill, ApplyError, ApplyOutcome, DispatchError, + weights::{Weight, DispatchInfo, DispatchClass, SimpleDispatchInfo}, + transaction_validity::{ + ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, + InvalidTransaction, TransactionValidity, + }, + traits::{ + self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Lookup, LookupError, + SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, SaturatedConversion, + MaybeSerialize, MaybeSerializeDeserialize, StaticLookup, One, Bounded, + }, }; -use sr_primitives::traits::{self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Convert, - SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, DispatchError, SaturatedConversion, - MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup, One, Bounded, Lookup, -}; -use primitives::{storage::well_known_keys, ChangesTrieConfiguration}; -use srml_support::{ - storage, decl_module, decl_event, decl_storage, StorageDoubleMap, StorageValue, StorageMap, - Parameter, for_each_tuple, traits::{Contains, Get} + +use primitives::{ChangesTrieConfiguration, storage::well_known_keys}; +use support::{ + decl_module, decl_event, decl_storage, decl_error, storage, Parameter, + traits::{Contains, Get}, }; -use safe_mix::TripletMix; use codec::{Encode, Decode}; #[cfg(any(feature = "std", test))] -use runtime_io::{twox_128, TestExternalities, Blake2Hasher}; +use runtime_io::TestExternalities; + +pub mod offchain; /// Handler for when a new account has been created. +#[impl_trait_for_tuples::impl_for_tuples(30)] pub trait OnNewAccount { /// A new account `who` has been registered. fn on_new_account(who: &AccountId); } -macro_rules! impl_on_new_account { - () => ( - impl OnNewAccount for () { - fn on_new_account(_: &AccountId) {} - } - ); - - ( $($t:ident)* ) => { - impl),*> OnNewAccount for ($($t,)*) { - fn on_new_account(who: &AccountId) { - $($t::on_new_account(who);)* - } - } - } -} - -for_each_tuple!(impl_on_new_account); - /// Determiner to say whether a given account is unused. pub trait IsDeadAccount { /// Is the given account dead? @@ -143,53 +149,48 @@ pub fn extrinsics_root(extrinsics: &[E]) -> H::Output /// Compute the trie root of a list of extrinsics. pub fn extrinsics_data_root(xts: Vec>) -> H::Output { - let xts = xts.iter().map(Vec::as_slice).collect::>(); - H::ordered_trie_root(&xts) + H::ordered_trie_root(xts) } pub trait Trait: 'static + Eq + Clone { /// The aggregated `Origin` type used by dispatchable calls. - type Origin: Into, Self::Origin>> + From>; + type Origin: + Into, Self::Origin>> + From>; /// The aggregated `Call` type. - type Call; + type Call: Debug; - /// Account index (aka nonce) type. This stores the number of previous transactions associated with a sender - /// account. + /// Account index (aka nonce) type. This stores the number of previous transactions associated + /// with a sender account. type Index: - Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + MaybeDisplay + SimpleArithmetic + Copy; + Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + SimpleArithmetic + + Copy; /// The block number type used by the runtime. type BlockNumber: - Parameter + Member + MaybeSerializeDebug + MaybeDisplay + SimpleArithmetic + Default + Bounded + Copy - + rstd::hash::Hash; + Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleArithmetic + + Default + Bounded + Copy + rstd::hash::Hash; /// The output of the `Hashing` function. type Hash: - Parameter + Member + MaybeSerializeDebug + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual - + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]>; + Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + SimpleBitOps + + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]>; /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). type Hashing: Hash; /// The user account identifier type for the runtime. - type AccountId: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + Ord + Default; + type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + + Default; /// Converting trait to take a source type and convert to `AccountId`. /// - /// Used to define the type and conversion mechanism for referencing accounts in transactions. It's perfectly - /// reasonable for this to be an identity conversion (with the source type being `AccountId`), but other modules - /// (e.g. Indices module) may provide more functional/efficient alternatives. + /// Used to define the type and conversion mechanism for referencing accounts in transactions. + /// It's perfectly reasonable for this to be an identity conversion (with the source type being + /// `AccountId`), but other modules (e.g. Indices module) may provide more functional/efficient + /// alternatives. type Lookup: StaticLookup; - /// Handler for updating the weight multiplier at the end of each block. - /// - /// It receives the current block's weight as input and returns the next weight multiplier for next - /// block. - /// - /// Note that passing `()` will keep the value constant. - type WeightMultiplierUpdate: Convert<(Weight, WeightMultiplier), WeightMultiplier>; - /// The block header. type Header: Parameter + traits::Header< Number = Self::BlockNumber, @@ -197,7 +198,7 @@ pub trait Trait: 'static + Eq + Clone { >; /// The aggregated event type of the runtime. - type Event: Parameter + Member + From; + type Event: Parameter + Member + From + Debug; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount: Get; @@ -213,6 +214,8 @@ pub trait Trait: 'static + Eq + Clone { /// module, including weight and length. type AvailableBlockRatio: Get; + /// Get the chain's current version. + type Version: Get; } pub type DigestOf = generic::Digest<::Hash>; @@ -223,10 +226,7 @@ pub type KeyValue = (Vec, Vec); decl_module! { pub struct Module for enum Call where origin: T::Origin { - /// Deposits an event into this block's event record. - pub fn deposit_event(event: T::Event) { - Self::deposit_event_indexed(&[], event); - } + type Error = Error; /// A big dispatch that will disallow any other transaction to be included. // TODO: this must be preferable available for testing really (not possible at the moment). @@ -289,12 +289,19 @@ decl_module! { storage::unhashed::kill(&key); } } + + /// Kill all storage items with a key that starts with the given prefix. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + fn kill_prefix(origin, prefix: Key) { + ensure_root(origin)?; + storage::unhashed::kill_prefix(&prefix); + } } } /// A phase of a block's execution. -#[derive(Encode, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone, Debug))] +#[derive(Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))] pub enum Phase { /// Applying an extrinsic. ApplyExtrinsic(u32), @@ -303,8 +310,8 @@ pub enum Phase { } /// Record of an event happening. -#[derive(Encode, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone, Debug))] +#[derive(Encode, Decode, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone))] pub struct EventRecord { /// The phase of the block it happened in. pub phase: Phase, @@ -320,13 +327,23 @@ decl_event!( /// An extrinsic completed successfully. ExtrinsicSuccess, /// An extrinsic failed. - ExtrinsicFailed, + ExtrinsicFailed(DispatchError), } ); +decl_error! { + /// Error for the System module + pub enum Error { + BadSignature, + BlockFull, + RequireSignedOrigin, + RequireRootOrigin, + RequireNoOrigin, + } +} + /// Origin for the System module. -#[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] pub enum RawOrigin { /// The system itself ordained this dispatch to happen: this is the highest privilege level. Root, @@ -368,35 +385,29 @@ type EventIndex = u32; decl_storage! { trait Store for Module as System { /// Extrinsics nonce for accounts. - pub AccountNonce get(account_nonce): map T::AccountId => T::Index; + pub AccountNonce get(fn account_nonce): map T::AccountId => T::Index; /// Total extrinsics count for the current block. ExtrinsicCount: Option; /// Total weight for all extrinsics put together, for the current block. AllExtrinsicsWeight: Option; /// Total length (in bytes) for all extrinsics put together, for the current block. AllExtrinsicsLen: Option; - /// The next weight multiplier. This should be updated at the end of each block based on the - /// saturation level (weight). - pub NextWeightMultiplier get(next_weight_multiplier): WeightMultiplier = Default::default(); /// Map of block numbers to block hashes. - pub BlockHash get(block_hash) build(|_| vec![(T::BlockNumber::zero(), hash69())]): map T::BlockNumber => T::Hash; + pub BlockHash get(fn block_hash) build(|_| vec![(T::BlockNumber::zero(), hash69())]): map T::BlockNumber => T::Hash; /// Extrinsics data for the current block (maps an extrinsic's index to its data). - ExtrinsicData get(extrinsic_data): map u32 => Vec; - /// Series of block headers from the last 81 blocks that acts as random seed material. This is arranged as a - /// ring buffer with the `i8` prefix being the index into the `Vec` of the oldest hash. - RandomMaterial get(random_material): (i8, Vec); + ExtrinsicData get(fn extrinsic_data): map u32 => Vec; /// The current block number being processed. Set by `execute_block`. - Number get(block_number) build(|_| 1.into()): T::BlockNumber; + Number get(fn block_number) build(|_| 1.into()): T::BlockNumber; /// Hash of the previous block. - ParentHash get(parent_hash) build(|_| hash69()): T::Hash; + ParentHash get(fn parent_hash) build(|_| hash69()): T::Hash; /// Extrinsics root of the current block, also part of the block header. - ExtrinsicsRoot get(extrinsics_root): T::Hash; + ExtrinsicsRoot get(fn extrinsics_root): T::Hash; /// Digest of the current block, also part of the block header. - Digest get(digest): DigestOf; + Digest get(fn digest): DigestOf; /// Events deposited for the current block. - Events get(events): Vec>; + Events get(fn events): Vec>; /// The number of events in the `Events` list. - EventCount get(event_count): EventIndex; + EventCount get(fn event_count): EventIndex; // TODO: https://github.com/paritytech/substrate/issues/2553 // Possibly, we can improve it by using something like: @@ -416,7 +427,7 @@ decl_storage! { /// The value has the type `(T::BlockNumber, EventIndex)` because if we used only just /// the `EventIndex` then in case if the topic has the same contents on the next block /// no notification will be triggered thus the event might be lost. - EventTopics get(event_topics): double_map hasher(blake2_256) (), blake2_256(T::Hash) + EventTopics get(fn event_topics): double_map hasher(blake2_256) (), blake2_256(T::Hash) => Vec<(T::BlockNumber, EventIndex)>; } add_extra_genesis { @@ -424,25 +435,23 @@ decl_storage! { #[serde(with = "primitives::bytes")] config(code): Vec; - build( - |storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), - config: &GenesisConfig| - { + build(|config: &GenesisConfig| { use codec::Encode; - storage.0.insert(well_known_keys::CODE.to_vec(), config.code.clone()); - storage.0.insert(well_known_keys::EXTRINSIC_INDEX.to_vec(), 0u32.encode()); + runtime_io::set_storage(well_known_keys::CODE, &config.code); + runtime_io::set_storage(well_known_keys::EXTRINSIC_INDEX, &0u32.encode()); if let Some(ref changes_trie_config) = config.changes_trie_config { - storage.0.insert( - well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), - changes_trie_config.encode()); + runtime_io::set_storage( + well_known_keys::CHANGES_TRIE_CONFIG, + &changes_trie_config.encode(), + ); } }); } } -pub struct EnsureRoot(::rstd::marker::PhantomData); +pub struct EnsureRoot(rstd::marker::PhantomData); impl< O: Into, O>> + From>, AccountId, @@ -456,7 +465,7 @@ impl< } } -pub struct EnsureSigned(::rstd::marker::PhantomData); +pub struct EnsureSigned(rstd::marker::PhantomData); impl< O: Into, O>> + From>, AccountId, @@ -470,7 +479,7 @@ impl< } } -pub struct EnsureSignedBy(::rstd::marker::PhantomData<(Who, AccountId)>); +pub struct EnsureSignedBy(rstd::marker::PhantomData<(Who, AccountId)>); impl< O: Into, O>> + From>, Who: Contains, @@ -485,7 +494,7 @@ impl< } } -pub struct EnsureNone(::rstd::marker::PhantomData); +pub struct EnsureNone(rstd::marker::PhantomData); impl< O: Into, O>> + From>, AccountId, @@ -499,7 +508,7 @@ impl< } } -pub struct EnsureNever(::rstd::marker::PhantomData); +pub struct EnsureNever(rstd::marker::PhantomData); impl EnsureOrigin for EnsureNever { type Success = T; fn try_origin(o: O) -> Result { @@ -509,36 +518,41 @@ impl EnsureOrigin for EnsureNever { /// Ensure that the origin `o` represents a signed extrinsic (i.e. transaction). /// Returns `Ok` with the account that signed the extrinsic or an `Err` otherwise. -pub fn ensure_signed(o: OuterOrigin) -> Result +pub fn ensure_signed(o: OuterOrigin) -> Result where OuterOrigin: Into, OuterOrigin>> { match o.into() { Ok(RawOrigin::Signed(t)) => Ok(t), - _ => Err("bad origin: expected to be a signed origin"), + _ => Err(Error::RequireSignedOrigin), } } /// Ensure that the origin `o` represents the root. Returns `Ok` or an `Err` otherwise. -pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str> +pub fn ensure_root(o: OuterOrigin) -> Result<(), Error> where OuterOrigin: Into, OuterOrigin>> { match o.into() { Ok(RawOrigin::Root) => Ok(()), - _ => Err("bad origin: expected to be a root origin"), + _ => Err(Error::RequireRootOrigin), } } /// Ensure that the origin `o` represents an unsigned extrinsic. Returns `Ok` or an `Err` otherwise. -pub fn ensure_none(o: OuterOrigin) -> Result<(), &'static str> +pub fn ensure_none(o: OuterOrigin) -> Result<(), Error> where OuterOrigin: Into, OuterOrigin>> { match o.into() { Ok(RawOrigin::None) => Ok(()), - _ => Err("bad origin: expected to be no origin"), + _ => Err(Error::RequireNoOrigin), } } impl Module { + /// Deposits an event into this block's event record. + pub fn deposit_event(event: impl Into) { + Self::deposit_event_indexed(&[], event.into()); + } + /// Deposits an event into this block's event record adding this event /// to the corresponding topic indexes. /// @@ -572,7 +586,7 @@ impl Module { // We perform early return if we've reached the maximum capacity of the event list, // so `Events` seems to be corrupted. Also, this has happened after the start of execution // (since the event list is cleared at the block initialization). - if >::append(&[event]).is_err() { + if >::append([event].iter()).is_err() { // The most sensible thing to do here is to just ignore this event and wait until the // new block. return; @@ -606,17 +620,6 @@ impl Module { AllExtrinsicsLen::get().unwrap_or_default() } - /// Update the next weight multiplier. - /// - /// This should be called at then end of each block, before `all_extrinsics_weight` is cleared. - pub fn update_weight_multiplier() { - // update the multiplier based on block weight. - let current_weight = Self::all_extrinsics_weight(); - NextWeightMultiplier::mutate(|fm| { - *fm = T::WeightMultiplierUpdate::convert((current_weight, *fm)) - }); - } - /// Start the execution of a particular block. pub fn initialize( number: &T::BlockNumber, @@ -631,12 +634,6 @@ impl Module { >::put(parent_hash); >::insert(*number - One::one(), parent_hash); >::put(txs_root); - >::mutate(|&mut(ref mut index, ref mut values)| if values.len() < 81 { - values.push(parent_hash.clone()) - } else { - values[*index as usize] = parent_hash.clone(); - *index = (*index + 1) % 81; - }); >::kill(); EventCount::kill(); >::remove_prefix(&()); @@ -645,7 +642,6 @@ impl Module { /// Remove temporary "environment" entries in storage. pub fn finalize() -> T::Header { ExtrinsicCount::kill(); - Self::update_weight_multiplier(); AllExtrinsicsWeight::kill(); AllExtrinsicsLen::kill(); @@ -695,11 +691,11 @@ impl Module { /// Get the basic externalities for this module, useful for tests. #[cfg(any(feature = "std", test))] - pub fn externalities() -> TestExternalities { + pub fn externalities() -> TestExternalities { TestExternalities::new((map![ - twox_128(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), - twox_128(>::key()).to_vec() => T::BlockNumber::one().encode(), - twox_128(>::key()).to_vec() => [69u8; 32].encode() + >::hashed_key_for(T::BlockNumber::zero()) => [69u8; 32].encode(), + >::hashed_key().to_vec() => T::BlockNumber::one().encode(), + >::hashed_key().to_vec() => [69u8; 32].encode() ], map![])) } @@ -723,68 +719,15 @@ impl Module { >::put(n); } - /// Get the basic random seed. - /// - /// In general you won't want to use this, but rather `Self::random` which - /// allows you to give a subject for the random result and whose value will - /// be independently low-influence random from any other such seeds. - pub fn random_seed() -> T::Hash { - Self::random(&[][..]) + /// Set the current block weight. This should only be used in some integration tests. + #[cfg(any(feature = "std", test))] + pub fn set_block_limits(weight: Weight, len: usize) { + AllExtrinsicsWeight::put(weight); + AllExtrinsicsLen::put(len as u32); } - /// Get a low-influence "random" value. - /// - /// Being a deterministic block chain, real randomness is difficult to come - /// by. This gives you something that approximates it. `subject` is a - /// context identifier and allows you to get a different result to other - /// callers of this function; use it like `random(&b"my context"[..])`. - /// - /// This is initially implemented through a low-influence "triplet mix" - /// convolution of previous block hash values. In the future it will be - /// generated from a secure verifiable random function (VRF). - /// - /// ### Security Notes - /// - /// This randomness uses a low-influence function, drawing upon the block - /// hashes from the previous 81 blocks. Its result for any given subject - /// will be known in advance by the block producer of this block (and, - /// indeed, anyone who knows the block's `parent_hash`). However, it is - /// mostly impossible for the producer of this block *alone* to influence - /// the value of this hash. A sizable minority of dishonest and coordinating - /// block producers would be required in order to affect this value. If that - /// is an insufficient security guarantee then two things can be used to - /// improve this randomness: - /// - /// - Name, in advance, the block number whose random value will be used; - /// ensure your module retains a buffer of previous random values for its - /// subject and then index into these in order to obviate the ability of - /// your user to look up the parent hash and choose when to transact based - /// upon it. - /// - Require your user to first commit to an additional value by first - /// posting its hash. Require them to reveal the value to determine the - /// final result, hashing it with the output of this random function. This - /// reduces the ability of a cabal of block producers from conspiring - /// against individuals. - /// - /// WARNING: Hashing the result of this function will remove any - /// low-influnce properties it has and mean that all bits of the resulting - /// value are entirely manipulatable by the author of the parent block, who - /// can determine the value of `parent_hash`. - pub fn random(subject: &[u8]) -> T::Hash { - let (index, hash_series) = >::get(); - if hash_series.len() > 0 { - // Always the case after block 1 is initialised. - hash_series.iter() - .cycle() - .skip(index as usize) - .take(81) - .enumerate() - .map(|(i, h)| (i as i8, subject, h).using_encoded(T::Hashing::hash)) - .triplet_mix() - } else { - T::Hash::default() - } - } + /// Return the chain's current runtime version. + pub fn runtime_version() -> RuntimeVersion { T::Version::get() } /// Increment a particular account's nonce by 1. pub fn inc_account_nonce(who: &T::AccountId) { @@ -802,11 +745,13 @@ impl Module { } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(r: &Result<(), &'static str>, _encoded_len: u32) { - Self::deposit_event(match r { - Ok(_) => Event::ExtrinsicSuccess, - Err(_) => Event::ExtrinsicFailed, - }.into()); + pub fn note_applied_extrinsic(r: &ApplyOutcome, _encoded_len: u32) { + Self::deposit_event( + match r { + Ok(()) => Event::ExtrinsicSuccess, + Err(err) => Event::ExtrinsicFailed(err.clone()), + } + ); let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; @@ -835,14 +780,12 @@ impl Module { pub struct CheckWeight(PhantomData); impl CheckWeight { - /// Get the quota ratio of each dispatch class type. This indicates that all operational /// dispatches can use the full capacity of any resource, while user-triggered ones can consume /// a portion. fn get_dispatch_limit_ratio(class: DispatchClass) -> Perbill { match class { DispatchClass::Operational => Perbill::one(), - // TODO: this must be some sort of a constant. DispatchClass::Normal => T::AvailableBlockRatio::get(), } } @@ -850,31 +793,33 @@ impl CheckWeight { /// Checks if the current extrinsic can fit into the block with respect to block weight limits. /// /// Upon successes, it returns the new block weight as a `Result`. - fn check_weight(info: DispatchInfo) -> Result { + fn check_weight(info: DispatchInfo) -> Result { let current_weight = Module::::all_extrinsics_weight(); let maximum_weight = T::MaximumBlockWeight::get(); let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_weight; let added_weight = info.weight.min(limit); let next_weight = current_weight.saturating_add(added_weight); if next_weight > limit { - return Err(DispatchError::Exhausted) + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(next_weight) } - Ok(next_weight) } /// Checks if the current extrinsic can fit into the block with respect to block length limits. /// /// Upon successes, it returns the new block length as a `Result`. - fn check_block_length(info: DispatchInfo, len: usize) -> Result { + fn check_block_length(info: DispatchInfo, len: usize) -> Result { let current_len = Module::::all_extrinsics_len(); let maximum_len = T::MaximumBlockLength::get(); let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_len; let added_len = len as u32; let next_len = current_len.saturating_add(added_len); if next_len > limit { - return Err(DispatchError::Exhausted) + Err(InvalidTransaction::ExhaustsResources.into()) + } else { + Ok(next_len) } - Ok(next_len) } /// get the priority of an extrinsic denoted by `info`. @@ -885,8 +830,7 @@ impl CheckWeight { } } - /// Utility constructor for tests and client code. - #[cfg(feature = "std")] + /// Creates new `SignedExtension` to check weight of the extrinsic. pub fn new() -> Self { Self(PhantomData) } @@ -898,7 +842,7 @@ impl SignedExtension for CheckWeight { type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } fn pre_dispatch( self, @@ -906,7 +850,7 @@ impl SignedExtension for CheckWeight { _call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result<(), DispatchError> { + ) -> Result<(), ApplyError> { let next_len = Self::check_block_length(info, len)?; AllExtrinsicsLen::put(next_len); let next_weight = Self::check_weight(info)?; @@ -920,20 +864,31 @@ impl SignedExtension for CheckWeight { _call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { + ) -> TransactionValidity { // There is no point in writing to storage here since changes are discarded. This basically - // discards any transaction which is bigger than the length or weight limit **alone**,which + // discards any transaction which is bigger than the length or weight limit **alone**, which // is a guarantee that it will fail in the pre-dispatch phase. - let _ = Self::check_block_length(info, len)?; - let _ = Self::check_weight(info)?; + if let Err(e) = Self::check_block_length(info, len) { + return Err(e); + } + + if let Err(e) = Self::check_weight(info) { + return Err(e); + } + Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) } } -#[cfg(feature = "std")] -impl rstd::fmt::Debug for CheckWeight { +impl Debug for CheckWeight { + #[cfg(feature = "std")] fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { - write!(f, "CheckWeight") + write!(f, "CheckWeight") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) } } @@ -941,7 +896,6 @@ impl rstd::fmt::Debug for CheckWeight { #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct CheckNonce(#[codec(compact)] T::Index); -#[cfg(feature = "std")] impl CheckNonce { /// utility constructor. Used only in client/factory code. pub fn from(nonce: T::Index) -> Self { @@ -949,11 +903,16 @@ impl CheckNonce { } } -#[cfg(feature = "std")] -impl rstd::fmt::Debug for CheckNonce { +impl Debug for CheckNonce { + #[cfg(feature = "std")] fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { self.0.fmt(f) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } } impl SignedExtension for CheckNonce { @@ -962,7 +921,7 @@ impl SignedExtension for CheckNonce { type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } fn pre_dispatch( self, @@ -970,13 +929,18 @@ impl SignedExtension for CheckNonce { _call: &Self::Call, _info: DispatchInfo, _len: usize, - ) -> Result<(), DispatchError> { + ) -> Result<(), ApplyError> { let expected = >::get(who); if self.0 != expected { return Err( - if self.0 < expected { DispatchError::Stale } else { DispatchError::Future } + if self.0 < expected { + InvalidTransaction::Stale + } else { + InvalidTransaction::Future + }.into() ) } + >::insert(who, expected + T::Index::one()); Ok(()) } @@ -987,11 +951,11 @@ impl SignedExtension for CheckNonce { _call: &Self::Call, info: DispatchInfo, _len: usize, - ) -> Result { + ) -> TransactionValidity { // check index let expected = >::get(who); if self.0 < expected { - return Err(DispatchError::Stale) + return InvalidTransaction::Stale.into() } let provides = vec![Encode::encode(&(who, self.0))]; @@ -1011,11 +975,10 @@ impl SignedExtension for CheckNonce { } } -/// Nonce check and increment to give replay protection for transactions. +/// Check for transaction mortality. #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct CheckEra((Era, rstd::marker::PhantomData)); -#[cfg(feature = "std")] impl CheckEra { /// utility constructor. Used only in client/factory code. pub fn from(era: Era) -> Self { @@ -1023,11 +986,16 @@ impl CheckEra { } } -#[cfg(feature = "std")] -impl rstd::fmt::Debug for CheckEra { +impl Debug for CheckEra { + #[cfg(feature = "std")] fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { self.0.fmt(f) } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } } impl SignedExtension for CheckEra { @@ -1036,11 +1004,29 @@ impl SignedExtension for CheckEra { type AdditionalSigned = T::Hash; type Pre = (); - fn additional_signed(&self) -> Result { + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: DispatchInfo, + _len: usize, + ) -> TransactionValidity { + let current_u64 = >::block_number().saturated_into::(); + let valid_till = (self.0).0.death(current_u64); + Ok(ValidTransaction { + longevity: valid_till.saturating_sub(current_u64), + ..Default::default() + }) + } + + fn additional_signed(&self) -> Result { let current_u64 = >::block_number().saturated_into::(); let n = (self.0).0.birth(current_u64).saturated_into::(); - if !>::exists(n) { Err("transaction birth block ancient")? } - Ok(>::block_hash(n)) + if !>::exists(n) { + Err(InvalidTransaction::AncientBirthBlock.into()) + } else { + Ok(>::block_hash(n)) + } } } @@ -1048,17 +1034,22 @@ impl SignedExtension for CheckEra { #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct CheckGenesis(rstd::marker::PhantomData); -#[cfg(feature = "std")] -impl rstd::fmt::Debug for CheckGenesis { - fn fmt(&self, _f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { +impl Debug for CheckGenesis { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + write!(f, "CheckGenesis") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { Ok(()) } } -#[cfg(feature = "std")] impl CheckGenesis { + /// Creates new `SignedExtension` to check genesis hash. pub fn new() -> Self { - Self(std::marker::PhantomData) + Self(rstd::marker::PhantomData) } } @@ -1068,22 +1059,57 @@ impl SignedExtension for CheckGenesis { type AdditionalSigned = T::Hash; type Pre = (); - fn additional_signed(&self) -> Result { + fn additional_signed(&self) -> Result { Ok(>::block_hash(T::BlockNumber::zero())) } } -pub struct ChainContext(::rstd::marker::PhantomData); +/// Ensure the runtime version registered in the transaction is the same as at present. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckVersion(rstd::marker::PhantomData); + +impl Debug for CheckVersion { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + write!(f, "CheckVersion") + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, _: &mut rstd::fmt::Formatter) -> rstd::fmt::Result { + Ok(()) + } +} + +impl CheckVersion { + /// Create new `SignedExtension` to check runtime version. + pub fn new() -> Self { + Self(rstd::marker::PhantomData) + } +} + +impl SignedExtension for CheckVersion { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = u32; + type Pre = (); + + fn additional_signed(&self) -> Result { + Ok(>::runtime_version().spec_version) + } +} + +pub struct ChainContext(rstd::marker::PhantomData); impl Default for ChainContext { fn default() -> Self { - ChainContext(::rstd::marker::PhantomData) + ChainContext(rstd::marker::PhantomData) } } impl Lookup for ChainContext { type Source = ::Source; type Target = ::Target; - fn lookup(&self, s: Self::Source) -> rstd::result::Result { + + fn lookup(&self, s: Self::Source) -> Result { ::lookup(s) } } @@ -1091,12 +1117,11 @@ impl Lookup for ChainContext { #[cfg(test)] mod tests { use super::*; - use runtime_io::with_externalities; use primitives::H256; - use sr_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - use srml_support::{impl_outer_origin, parameter_types}; + use sr_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header, DispatchError}; + use support::{impl_outer_origin, parameter_types}; - impl_outer_origin!{ + impl_outer_origin! { pub enum Origin for Test where system = super {} } @@ -1120,19 +1145,19 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = u16; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } impl From for u16 { fn from(e: Event) -> u16 { match e { Event::ExtrinsicSuccess => 100, - Event::ExtrinsicFailed => 101, + Event::ExtrinsicFailed(_) => 101, } } } @@ -1141,7 +1166,7 @@ mod tests { const CALL: &::Call = &(); - fn new_test_ext() -> runtime_io::TestExternalities { + fn new_test_ext() -> runtime_io::TestExternalities { GenesisConfig::default().build_storage::().unwrap().into() } @@ -1162,7 +1187,7 @@ mod tests { #[test] fn deposit_event_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { System::initialize(&1, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::note_finished_extrinsics(); System::deposit_event(1u16); @@ -1181,25 +1206,33 @@ mod tests { System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::deposit_event(42u16); System::note_applied_extrinsic(&Ok(()), 0); - System::note_applied_extrinsic(&Err(""), 0); + System::note_applied_extrinsic(&Err(DispatchError::new(Some(1), 2, None)), 0); System::note_finished_extrinsics(); System::deposit_event(3u16); System::finalize(); - assert_eq!(System::events(), vec![ - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(1), event: 101u16, topics: vec![] }, - EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } - ]); + assert_eq!( + System::events(), + vec![ + EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(1), event: 101u16, topics: vec![] }, + EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } + ] + ); }); } #[test] fn deposit_event_topics() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { const BLOCK_NUMBER: u64 = 1; - System::initialize(&BLOCK_NUMBER, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); + System::initialize( + &BLOCK_NUMBER, + &[0u8; 32].into(), + &[0u8; 32].into(), + &Default::default(), + ); System::note_finished_extrinsics(); let topics = vec![ @@ -1256,7 +1289,7 @@ mod tests { #[test] fn prunes_block_hash_mappings() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { // simulate import of 15 blocks for n in 1..=15 { System::initialize( @@ -1289,7 +1322,7 @@ mod tests { #[test] fn signed_ext_check_nonce_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { >::insert(1, 1); let info = DispatchInfo::default(); let len = 0_usize; @@ -1307,7 +1340,7 @@ mod tests { #[test] fn signed_ext_check_weight_works_normal_tx() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let normal_limit = normal_weight_limit(); let small = DispatchInfo { weight: 100, ..Default::default() }; let medium = DispatchInfo { @@ -1334,7 +1367,7 @@ mod tests { #[test] fn signed_ext_check_weight_fee_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let free = DispatchInfo { weight: 0, ..Default::default() }; let len = 0_usize; @@ -1347,7 +1380,7 @@ mod tests { #[test] fn signed_ext_check_weight_max_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let max = DispatchInfo { weight: Weight::max_value(), ..Default::default() }; let len = 0_usize; let normal_limit = normal_weight_limit(); @@ -1361,7 +1394,7 @@ mod tests { #[test] fn signed_ext_check_weight_works_operational_tx() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let normal = DispatchInfo { weight: 100, ..Default::default() }; let op = DispatchInfo { weight: 100, class: DispatchClass::Operational }; let len = 0_usize; @@ -1384,25 +1417,28 @@ mod tests { #[test] fn signed_ext_check_weight_priority_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal }; let op = DispatchInfo { weight: 100, class: DispatchClass::Operational }; let len = 0_usize; - assert_eq!( - CheckWeight::(PhantomData).validate(&1, CALL, normal, len).unwrap().priority, - 100, - ); - assert_eq!( - CheckWeight::(PhantomData).validate(&1, CALL, op, len).unwrap().priority, - Bounded::max_value(), - ); + let priority = CheckWeight::(PhantomData) + .validate(&1, CALL, normal, len) + .unwrap() + .priority; + assert_eq!(priority, 100); + + let priority = CheckWeight::(PhantomData) + .validate(&1, CALL, op, len) + .unwrap() + .priority; + assert_eq!(priority, Bounded::max_value()); }) } #[test] fn signed_ext_check_weight_block_size_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { let normal = DispatchInfo::default(); let normal_limit = normal_weight_limit() as usize; let reset_check_weight = |tx, s, f| { @@ -1426,11 +1462,11 @@ mod tests { #[test] fn signed_ext_check_era_should_work() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { // future assert_eq!( CheckEra::::from(Era::mortal(4, 2)).additional_signed().err().unwrap(), - "transaction birth block ancient" + InvalidTransaction::AncientBirthBlock.into(), ); // correct @@ -1439,4 +1475,20 @@ mod tests { assert!(CheckEra::::from(Era::mortal(4, 12)).additional_signed().is_ok()); }) } + + #[test] + fn signed_ext_check_era_should_change_longevity() { + new_test_ext().execute_with(|| { + let normal = DispatchInfo { weight: 100, class: DispatchClass::Normal }; + let len = 0_usize; + let ext = ( + CheckWeight::(PhantomData), + CheckEra::::from(Era::mortal(16, 256)), + ); + System::set_block_number(17); + >::insert(16, H256::repeat_byte(1)); + + assert_eq!(ext.validate(&1, CALL, normal, len).unwrap().longevity, 15); + }) + } } diff --git a/srml/system/src/offchain.rs b/srml/system/src/offchain.rs new file mode 100644 index 0000000000000000000000000000000000000000..11f7e234f71977707913b7930a95913aeb6a7522 --- /dev/null +++ b/srml/system/src/offchain.rs @@ -0,0 +1,168 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Module helpers for offchain calls. + +use codec::Encode; +use sr_primitives::app_crypto::{self, RuntimeAppPublic}; +use sr_primitives::traits::{Extrinsic as ExtrinsicT, IdentifyAccount}; + +/// A trait responsible for signing a payload using given account. +pub trait Signer { + /// Sign any encodable payload with given account and produce a signature. + /// + /// Returns `Some` if signing succeeded and `None` in case the `account` couldn't be used. + fn sign(public: Public, payload: &Payload) -> Option; +} + +/// A `Signer` implementation for any `AppPublic` type. +/// +/// This implementation additionaly supports conversion to/from multi-signature/multi-signer +/// wrappers. +/// If the wrapped crypto doesn't match `AppPublic`s crypto `None` is returned. +impl Signer for AppPublic where + AppPublic: RuntimeAppPublic + + app_crypto::AppPublic + + From<::Generic>, + ::Signature: app_crypto::AppSignature, + Signature: From< + <::Signature as app_crypto::AppSignature>::Generic + >, + Public: rstd::convert::TryInto<::Generic> +{ + fn sign(public: Public, raw_payload: &Payload) -> Option { + raw_payload.using_encoded(|payload| { + let public = public.try_into().ok()?; + AppPublic::from(public).sign(&payload) + .map( + <::Signature as app_crypto::AppSignature> + ::Generic::from + ) + .map(Signature::from) + }) + } +} + +/// Creates runtime-specific signed transaction. +pub trait CreateTransaction { + /// A `Public` key representing a particular `AccountId`. + type Public; + /// A `Signature` generated by the `Signer`. + type Signature; + + /// Attempt to create signed extrinsic data that encodes call from given account. + /// + /// Runtime implementation is free to construct the payload to sign and the signature + /// in any way it wants. + /// Returns `None` if signed extrinsic could not be created (either because signing failed + /// or because of any other runtime-specific reason). + fn create_transaction>( + call: Extrinsic::Call, + public: Self::Public, + account: T::AccountId, + nonce: T::Index, + ) -> Option<(Extrinsic::Call, Extrinsic::SignaturePayload)>; +} + +type PublicOf = < + >::CreateTransaction as CreateTransaction< + T, + >::Extrinsic, + > +>::Public; + +/// A trait to sign and submit transactions in offchain calls. +pub trait SubmitSignedTransaction +where + PublicOf: IdentifyAccount + Clone, +{ + /// Unchecked extrinsic type. + type Extrinsic: ExtrinsicT + codec::Encode; + + /// A runtime-specific type to produce signed data for the extrinsic. + type CreateTransaction: CreateTransaction; + + /// A type used to sign transactions created using `CreateTransaction`. + type Signer: Signer< + PublicOf, + >::Signature, + >; + + /// Sign given call and submit it to the transaction pool. + /// + /// Returns `Ok` if the transaction was submitted correctly + /// and `Err` if the key for given `id` was not found or the + /// transaction was rejected from the pool. + fn sign_and_submit(call: impl Into, public: PublicOf) -> Result<(), ()> { + let call = call.into(); + let id = public.clone().into_account(); + let expected = >::account_nonce(&id); + let (call, signature_data) = Self::CreateTransaction + ::create_transaction::(call, public, id, expected) + .ok_or(())?; + let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?; + runtime_io::submit_transaction(xt.encode()) + } +} + +/// A trait to submit unsigned transactions in offchain calls. +pub trait SubmitUnsignedTransaction { + /// Unchecked extrinsic type. + type Extrinsic: ExtrinsicT + codec::Encode; + + /// Submit given call to the transaction pool as unsigned transaction. + /// + /// Returns `Ok` if the transaction was submitted correctly + /// and `Err` if transaction was rejected from the pool. + fn submit_unsigned(call: impl Into) -> Result<(), ()> { + let xt = Self::Extrinsic::new(call.into(), None).ok_or(())?; + runtime_io::submit_transaction(xt.encode()) + } +} + +/// A default type used to submit transactions to the pool. +pub struct TransactionSubmitter { + _signer: rstd::marker::PhantomData<(S, C, E)>, +} + +impl Default for TransactionSubmitter { + fn default() -> Self { + Self { + _signer: Default::default(), + } + } +} + +/// A blanket implementation to simplify creation of transaction signer & submitter in the runtime. +impl SubmitSignedTransaction for TransactionSubmitter where + T: crate::Trait, + C: CreateTransaction, + S: Signer<>::Public, >::Signature>, + E: ExtrinsicT + codec::Encode, + >::Public: IdentifyAccount + Clone, +{ + type Extrinsic = E; + type CreateTransaction = C; + type Signer = S; +} + +/// A blanket impl to use the same submitter for usigned transactions as well. +impl SubmitUnsignedTransaction for TransactionSubmitter where + T: crate::Trait, + E: ExtrinsicT + codec::Encode, +{ + type Extrinsic = E; +} diff --git a/srml/timestamp/Cargo.toml b/srml/timestamp/Cargo.toml index 9b066a15058d72192460553c663e8689f0f544cd..d8eab64f9f3d983d5b8d3d67f68e91fef18c48b9 100644 --- a/srml/timestamp/Cargo.toml +++ b/srml/timestamp/Cargo.toml @@ -5,16 +5,17 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -serde = { version = "1.0", optional = true } +serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } sr-primitives = { path = "../../core/sr-primitives", default-features = false } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -srml-support = { path = "../support", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } +impl-trait-for-tuples = "0.1.3" [dev-dependencies] -runtime_io = { package = "sr-io", path = "../../core/sr-io" } +runtime-io ={ package = "sr-io", path = "../../core/sr-io" } primitives = { package = "substrate-primitives", path = "../../core/primitives" } [features] @@ -24,7 +25,7 @@ std = [ "codec/std", "rstd/std", "sr-primitives/std", - "srml-support/std", + "support/std", "serde", "system/std", ] diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index 502acadf61e330bc2fda515caa11ba7025d89852..2ab751088e8c7ad2a12b82e944cbaa2ba93bb47a 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -61,7 +61,7 @@ //! ### Get current timestamp //! //! ``` -//! use srml_support::{decl_module, dispatch::Result}; +//! use support::{decl_module, dispatch::Result}; //! # use srml_timestamp as timestamp; //! use system::ensure_signed; //! @@ -96,8 +96,8 @@ use codec::Encode; use codec::Decode; #[cfg(feature = "std")] use inherents::ProvideInherentData; -use srml_support::{StorageValue, Parameter, decl_storage, decl_module, for_each_tuple}; -use srml_support::traits::{Time, Get}; +use support::{Parameter, decl_storage, decl_module}; +use support::traits::{Time, Get}; use sr_primitives::traits::{ SimpleArithmetic, Zero, SaturatedConversion, Scale }; @@ -111,8 +111,8 @@ pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0"; pub type InherentType = u64; /// Errors that can occur while checking the timestamp inherent. -#[derive(Encode)] -#[cfg_attr(feature = "std", derive(Debug, Decode))] +#[derive(Encode, sr_primitives::RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Decode))] pub enum InherentError { /// The timestamp is valid in the future. /// This is a non-fatal-error and will not stop checking the inherents. @@ -183,33 +183,16 @@ impl ProvideInherentData for InherentDataProvider { } /// A trait which is called when the timestamp is set. +#[impl_trait_for_tuples::impl_for_tuples(30)] pub trait OnTimestampSet { fn on_timestamp_set(moment: Moment); } -macro_rules! impl_timestamp_set { - () => ( - impl OnTimestampSet for () { - fn on_timestamp_set(_: Moment) {} - } - ); - - ( $($t:ident)* ) => { - impl),*> OnTimestampSet for ($($t,)*) { - fn on_timestamp_set(moment: Moment) { - $($t::on_timestamp_set(moment.clone());)* - } - } - } -} - -for_each_tuple!(impl_timestamp_set); - /// The module configuration trait pub trait Trait: system::Trait { /// Type used for expressing timestamp. type Moment: Parameter + Default + SimpleArithmetic - + Scale; + + Scale + Copy; /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. type OnTimestampSet: OnTimestampSet; @@ -246,7 +229,7 @@ decl_module! { Self::now().is_zero() || now >= Self::now() + T::MinimumPeriod::get(), "Timestamp must increment by at least between sequential blocks" ); - ::Now::put(now.clone()); + ::Now::put(now); ::DidUpdate::put(true); >::on_timestamp_set(now); @@ -261,7 +244,7 @@ decl_module! { decl_storage! { trait Store for Module as Timestamp { /// Current time for the current block. - pub Now get(now) build(|_| 0.into()): T::Moment; + pub Now get(fn now) build(|_| 0.into()): T::Moment; /// Did the timestamp get updated in this block? DidUpdate: bool; @@ -338,8 +321,8 @@ impl Time for Module { mod tests { use super::*; - use srml_support::{impl_outer_origin, assert_ok, parameter_types}; - use runtime_io::{with_externalities, TestExternalities}; + use support::{impl_outer_origin, assert_ok, parameter_types}; + use runtime_io::TestExternalities; use primitives::H256; use sr_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; @@ -365,12 +348,12 @@ mod tests { type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; - type WeightMultiplierUpdate = (); type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; + type Version = (); } parameter_types! { pub const MinimumPeriod: u64 = 5; @@ -385,7 +368,7 @@ mod tests { #[test] fn timestamp_works() { let t = system::GenesisConfig::default().build_storage::().unwrap(); - with_externalities(&mut TestExternalities::new(t), || { + TestExternalities::new(t).execute_with(|| { Timestamp::set_timestamp(42); assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); assert_eq!(Timestamp::now(), 69); @@ -396,7 +379,7 @@ mod tests { #[should_panic(expected = "Timestamp must be updated only once in the block")] fn double_timestamp_should_fail() { let t = system::GenesisConfig::default().build_storage::().unwrap(); - with_externalities(&mut TestExternalities::new(t), || { + TestExternalities::new(t).execute_with(|| { Timestamp::set_timestamp(42); assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); let _ = Timestamp::dispatch(Call::set(70), Origin::NONE); @@ -407,7 +390,7 @@ mod tests { #[should_panic(expected = "Timestamp must increment by at least between sequential blocks")] fn block_period_minimum_enforced() { let t = system::GenesisConfig::default().build_storage::().unwrap(); - with_externalities(&mut TestExternalities::new(t), || { + TestExternalities::new(t).execute_with(|| { Timestamp::set_timestamp(42); let _ = Timestamp::dispatch(Call::set(46), Origin::NONE); }); diff --git a/srml/transaction-payment/Cargo.toml b/srml/transaction-payment/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..cbce1e945e69b8e17d78295fb66e3d3d9a9e8919 --- /dev/null +++ b/srml/transaction-payment/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "srml-transaction-payment" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +sr-primitives = { path = "../../core/sr-primitives", default-features = false } +support = { package = "srml-support", path = "../support", default-features = false } +system = { package = "srml-system", path = "../system", default-features = false } +transaction-payment-rpc-runtime-api = { package = "srml-transaction-payment-rpc-runtime-api", path = "./rpc/runtime-api", default-features = false } + +[dev-dependencies] +runtime-io = { package = "sr-io", path = "../../core/sr-io" } +primitives = { package = "substrate-primitives", path = "../../core/primitives" } +balances = { package = "srml-balances", path = "../balances" } + +[features] +default = ["std"] +std = [ + "codec/std", + "rstd/std", + "sr-primitives/std", + "support/std", + "system/std", + "transaction-payment-rpc-runtime-api/std" +] diff --git a/srml/transaction-payment/rpc/Cargo.toml b/srml/transaction-payment/rpc/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..1fcfc21f805c30531781e1cdd2e7e13122240f16 --- /dev/null +++ b/srml/transaction-payment/rpc/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "srml-transaction-payment-rpc" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +client = { package = "substrate-client", path = "../../../core/client" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +jsonrpc-core = "14.0.3" +jsonrpc-core-client = "14.0.3" +jsonrpc-derive = "14.0.3" +primitives = { package = "substrate-primitives", path = "../../../core/primitives" } +rpc-primitives = { package = "substrate-rpc-primitives", path = "../../../core/rpc/primitives" } +serde = { version = "1.0.101", features = ["derive"] } +sr-primitives = { path = "../../../core/sr-primitives" } +srml-transaction-payment-rpc-runtime-api = { path = "./runtime-api" } diff --git a/srml/transaction-payment/rpc/runtime-api/Cargo.toml b/srml/transaction-payment/rpc/runtime-api/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..c26f295f4bec313a3f52e45f50455e9e052839f3 --- /dev/null +++ b/srml/transaction-payment/rpc/runtime-api/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "srml-transaction-payment-rpc-runtime-api" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true, features = ["derive"] } +client = { package = "substrate-client", path = "../../../../core/client", default-features = false } +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../../../../core/sr-std", default-features = false } +sr-primitives = { path = "../../../../core/sr-primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "serde", + "client/std", + "codec/std", + "rstd/std", + "sr-primitives/std", +] diff --git a/srml/transaction-payment/rpc/runtime-api/src/lib.rs b/srml/transaction-payment/rpc/runtime-api/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..dc6360ca88d76abe159baac8bd1d9d2172084277 --- /dev/null +++ b/srml/transaction-payment/rpc/runtime-api/src/lib.rs @@ -0,0 +1,47 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Runtime API definition for transaction payment module. + +#![cfg_attr(not(feature = "std"), no_std)] + +use rstd::prelude::*; +use sr_primitives::weights::{Weight, DispatchClass}; +use codec::{Encode, Codec, Decode}; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; + +/// Some information related to a dispatchable that can be queried from the runtime. +#[derive(Eq, PartialEq, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub struct RuntimeDispatchInfo { + /// Weight of this dispatch. + pub weight: Weight, + /// Class of this dispatch. + pub class: DispatchClass, + /// The partial inclusion fee of this dispatch. This does not include tip or anything else which + /// is dependent on the signature (aka. depends on a `SignedExtension`). + pub partial_fee: Balance, +} + +client::decl_runtime_apis! { + pub trait TransactionPaymentApi where + Balance: Codec, + Extrinsic: Codec, + { + fn query_info(uxt: Extrinsic, len: u32) -> RuntimeDispatchInfo; + } +} diff --git a/srml/transaction-payment/rpc/src/lib.rs b/srml/transaction-payment/rpc/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..6ee3c7eddbc55cce2d76c2e83fa0e192fd0038c6 --- /dev/null +++ b/srml/transaction-payment/rpc/src/lib.rs @@ -0,0 +1,108 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! RPC interface for the transaction payment module. + +use std::sync::Arc; +use codec::{Codec, Decode}; +use client::blockchain::HeaderBackend; +use jsonrpc_core::{Error as RpcError, ErrorCode, Result}; +use jsonrpc_derive::rpc; +use sr_primitives::{ + generic::BlockId, + traits::{Block as BlockT, ProvideRuntimeApi}, +}; +use primitives::Bytes; +use srml_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; +pub use srml_transaction_payment_rpc_runtime_api::TransactionPaymentApi as TransactionPaymentRuntimeApi; +pub use self::gen_client::Client as TransactionPaymentClient; + +#[rpc] +pub trait TransactionPaymentApi { + #[rpc(name = "payment_queryInfo")] + fn query_info( + &self, + encoded_xt: Bytes, + at: Option + ) -> Result>; +} + +/// A struct that implements the [`TransactionPaymentApi`]. +pub struct TransactionPayment { + client: Arc, + _marker: std::marker::PhantomData